All Products
Search
Document Center

IoT Platform:Device shadows

Last Updated:May 16, 2023

If a product does not support Thing Specification Language (TSL), you can use a device shadow to store the latest status of the device to IoT Platform. The data stored in IoT Platform is in the JSON format. You can parse the data based on your business requirements. TSL offers an advanced device shadow capability. TSL allows you to view the information of each property, event, and service, including the records of all operations.

Upstream data

Note

For more information about device shadow-related API operations, see IDeviceShadow.

  • Obtain a device shadow from IoT Platform

  • Update a device shadow in IoT Platform

  • Delete a device shadow in IoT Platform

// Update a device shadow. You must first read the ver parameter from the obtained shadow data. Then, replace the value of the ver parameter with a new version number when you update the device shadow. The new version number is obtained by adding the value 1 to the last version number.
String shadowUpdate = "{" + "\"method\": \"update\"," + "\"state\": {" + "\"reported\": {" +
  "\"color\": \"red\"" + ",\"mode\": \"1\"" + "}" + "}," + "\"version\": {ver}" + "}";

// Obtain a device shadow
String shadowGet = "{" + "\"method\": \"get\"" + "}";

// Delete the color attribute of a device shadow. Specify the ver parameter as required.
String shadowDelete = "{" + "\"method\": \"delete\"," + "\"state\": {" + "\"reported\": {" +
  "\"color\": \"null\"" + "}" + "}," + "\"version\": {ver}" + "}";

// Delete all attributes of a device shadow. Specify the ver parameter as required.
String shadowDeleteAll = "{" + "\"method\": \"delete\"," + "\"state\": {" +
  "\"reported\":\"null\"" + "}," + "\"version\": {ver}" + "}";

String requestData = shadowUpdate.replace("{ver}";// shadowGet;shadowDelete.replace("{ver}"
LinkKit.getInstance().getDeviceShadow().shadowUpload(requestData, new IConnectSendListener() {
            @Override
            public void onResponse(ARequest aRequest, AResponse aResponse) {
                try {
                    if (aRequest instanceof MqttPublishRequest && aResponse ! = null) {
                        String dataStr = null;
                        if (aResponse.data instanceof byte[]) {
                            dataStr = new String((byte[]) aResponse.data, "UTF-8");
                        } else if (aResponse.data instanceof String) {
                            dataStr = (String) aResponse.data;
                        } else {
                            dataStr = String.valueOf(aResponse.data);
                        }
                        // Sample response
                        // {"method":"reply","payload":{"status":"success","state":{"reported":{}},"metadata":{"reported":{}}},"timestamp":1547641855,"version":7,"clientToken":"null"}
                                
                        ShadowResponse<String> response = JSONObject.parseObject(dataStr, new TypeReference<ShadowResponse<String>>() {
                        }.getType());
                        if (response ! = null && response.version ! = null) {
                            version = Integer.valueOf(response.version);
                        }
                    }
                } catch (NumberFormatException e) {
                    e.printStackTrace();
                    //ALog.e(TAG, "update version failed.");
                } catch (Exception e) {
                    //ALog.e(TAG, "update response parse exception.") ;
                }
            }

            @Override
            public void onFailure(ARequest aRequest, AError aError) {
                //ALog.d(TAG, "onFailure() called with: aRequest = [" + aRequest + "], aError = [" + aError + "]");
            }
        });
        

Downstream data

// Listen to device shadow updates in IoT Platform.
LinkKit.getInstance().getDeviceShadow().setShadowChangeListener(new IShadowRRPC() {
    @Override
    public void onSubscribeSuccess(ARequest aRequest) {
      // ALog.d(TAG, "The subscription to downstream shadow data is successful");
      // ALog.d(TAG, "onSubscribeSuccess() called with: aRequest = [" + aRequest + "]");
    }

    @Override
    public void onSubscribeFailed(ARequest aRequest, AError aError) {
      // ALog.d(TAG, "The subscription to downstream shadow data fails");
      // ALog.d(TAG, "onSubscribeFailed() called with: aRequest = [" + aRequest + "], aError = [" + aError + "]");
    }

    @Override
    public void onReceived(ARequest aRequest, AResponse aResponse, IConnectRrpcHandle iConnectRrpcHandle) {
      // ALog.d(TAG, "onReceived() called with: aRequest = [" + aRequest + "], iConnectRrpcHandle = [" + iConnectRrpcHandle + "]");
      // TODO user logic
      // ALog.d(TAG, "Obtain downstream shadow data");
      try {
        if (aRequest ! = null) {
          String dataStr = null;
          if (aResponse.data instanceof byte[]) {
            dataStr = new String((byte[]) aResponse.data, "UTF-8");
          } else if (aResponse.data instanceof String) {
            dataStr = (String) aResponse.data;
          } else {
            dataStr = String.valueOf(aResponse.data);
          }
          ALog.d(TAG, "dataStr = " + dataStr);
          // Sample response
          // {"method":"reply","payload":{"status":"success","state":{"reported":{}},"metadata":{"reported":{}}},"timestamp":1547641855,"version":7,"clientToken":"null"}
          ShadowResponse<String> shadowResponse = JSONObject.parseObject(dataStr, new TypeReference<ShadowResponse<String>>() {
          }.getType());
          if (shadowResponse ! = null && shadowResponse.version ! = null) {
            version = Integer.valueOf(shadowResponse.version);
          }

          AResponse response = new AResponse();
          // Achieve device control.
          // After you controls the device, submit the shadow data to IoT Platform.
          // Submit the updated shadow data to IoT Platform.
          // You must submit actual values.
          response.data = shadowUpdate.replace("{ver}", String.valueOf(++version));
          // The replyTopic parameter uses the default value. You do not need to set this parameter.
          iConnectRrpcHandle.onRrpcResponse(null, response);
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
    }

    @Override
    public void onResponseSuccess(ARequest aRequest) {
      ALog.d(TAG, "onResponseSuccess() called with: aRequest = [" + aRequest + "]");
    }

    @Override
    public void onResponseFailed(ARequest aRequest, AError aError) {
      ALog.w(TAG, "onResponseFailed() called with: aRequest = [" + aRequest + "], aError = [" + aError + "]");
    }
});