// Get the whole REST API string for a device, from cache if possible
 public String requestAPI() throws YAPI_Exception {
   if (_cache_expiration > YAPI.GetTickCount()) {
     return _cache_json;
   }
   String yreq = requestHTTPSyncAsString("GET /api.json", null);
   this._cache_expiration = YAPI.GetTickCount() + YAPI.DefaultCacheValidity;
   this._cache_json = yreq;
   return yreq;
 }
 /**
  * Returns the Z component of the magnetic field, as a floating point number.
  *
  * @return a floating point number corresponding to the Z component of the magnetic field, as a
  *     floating point number
  * @throws YAPI_Exception on error
  */
 public double get_zValue() throws YAPI_Exception {
   if (_cacheExpiration <= YAPI.GetTickCount()) {
     if (load(YAPI.DefaultCacheValidity) != YAPI.SUCCESS) {
       return ZVALUE_INVALID;
     }
   }
   return _zValue;
 }
  // Reload a device API (store in cache), and update YAPI function lists accordingly
  // Intended to be called within UpdateDeviceList only
  public int refresh() throws YAPI_Exception {
    String result = this.requestAPI();
    JSONObject loadval;
    Boolean reindex = false;
    try {
      loadval = new JSONObject(result);

      _cache_expiration = YAPI.GetTickCount() + YAPI.DefaultCacheValidity;
      _cache_json = result;

      // parse module and refresh names if needed
      Iterator<?> keys = loadval.keys();
      while (keys.hasNext()) {
        String key = (String) keys.next();
        if (key.equals("module")) {
          JSONObject module = loadval.getJSONObject("module");
          if (!_wpRec.getLogicalName().equals(module.getString("logicalName"))) {
            _wpRec.setLogicalName(module.getString("logicalName"));
            _moduleYPEntry.setLogicalName(_wpRec.getLogicalName());
            reindex = true;
          }
          _wpRec.setBeacon(module.getInt("beacon"));
        } else if (!key.equals("services")) {
          JSONObject func = loadval.getJSONObject(key);
          String name;
          if (func.has("logicalName")) {
            name = func.getString("logicalName");
          } else {
            name = _wpRec.getLogicalName();
          }
          if (func.has("advertisedValue")) {
            String pubval = func.getString("advertisedValue");
            SafeYAPI()._yHash.setFunctionValue(_wpRec.getSerialNumber(), pubval);
          }
          for (int f = 0; f < _ypRecs.size(); f++) {
            if (_ypRecs.get(f).getFuncId().equals(key)) {
              if (!_ypRecs.get(f).getLogicalName().equals(name)) {
                _ypRecs.get(f).setLogicalName(name);
                reindex = true;
              }
              break;
            }
          }
        }
      }
    } catch (JSONException e) {
      throw new YAPI_Exception(YAPI.IO_ERROR, "Request failed, could not parse API result");
    }

    if (reindex) {
      SafeYAPI()._yHash.reindexDevice(this);
    }
    return YAPI.SUCCESS;
  }
  static byte[] formatHTTPUpload(String path, byte[] content) throws YAPI_Exception {
    Random randomGenerator = new Random();
    String boundary;
    String mp_header =
        "Content-Disposition: form-data; name=\""
            + path
            + "\"; filename=\"api\"\r\n"
            + "Content-Type: application/octet-stream\r\n"
            + "Content-Transfer-Encoding: binary\r\n\r\n";
    // find a valid boundary
    do {
      boundary = String.format("Zz%06xzZ", randomGenerator.nextInt(0x1000000));
    } while (mp_header.contains(boundary)
        && YAPI._find_in_bytes(content, boundary.getBytes()) >= 0);
    // construct header parts
    String header_start =
        "Content-Type: multipart/form-data; boundary="
            + boundary
            + "\r\n\r\n--"
            + boundary
            + "\r\n"
            + mp_header;
    String header_stop = "\r\n--" + boundary + "--\r\n";
    byte[] head_body = new byte[header_start.length() + content.length + header_stop.length()];
    int pos = 0;
    int len = header_start.length();
    System.arraycopy(header_start.getBytes(), 0, head_body, pos, len);

    pos += len;
    len = content.length;
    System.arraycopy(content, 0, head_body, pos, len);

    pos += len;
    len = header_stop.length();
    System.arraycopy(header_stop.getBytes(), 0, head_body, pos, len);
    System.arraycopy(header_stop.getBytes(), 0, head_body, pos, len);
    return head_body;
  }