日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

設(shè)備期望屬性的應(yīng)用

更新時間:

設(shè)備期望屬性的應(yīng)用

在物聯(lián)網(wǎng)解決方案中,下發(fā)屬性時如果設(shè)備不在線會導(dǎo)致下發(fā)失敗。如果想要更優(yōu)雅和高效的完成屬性的下發(fā)呢?平臺提供設(shè)置期望屬性值功能,通過緩存設(shè)備屬性的期望值,實現(xiàn)從物聯(lián)網(wǎng)平臺云端控制設(shè)備屬性值。

本文介紹設(shè)置期望屬性值,實現(xiàn)從物聯(lián)網(wǎng)平臺控制燈泡狀態(tài)的相關(guān)操作。

場景信息

開關(guān)設(shè)備接入物聯(lián)網(wǎng)平臺后,若需從物聯(lián)網(wǎng)平臺控制燈泡工作狀態(tài)(1:打開;0:關(guān)閉),需要燈泡一直保持連網(wǎng)在線。實際情況下,燈泡可能無法一直在線。

您可在物聯(lián)網(wǎng)平臺設(shè)置設(shè)備期望屬性值,使其存儲在物聯(lián)網(wǎng)平臺云端。設(shè)備在線后,可讀取物聯(lián)網(wǎng)平臺存儲的期望屬性值,來更新自身屬性值。然后,設(shè)備會將更新后的屬性值上報至物聯(lián)網(wǎng)平臺。

image13.png

整體流程

1.創(chuàng)建產(chǎn)品和設(shè)備

2.使用Postman模擬設(shè)備

3.設(shè)置和獲取期望屬性

4.設(shè)備端開發(fā)

創(chuàng)建產(chǎn)品和設(shè)備

  1. 進(jìn)入Tuya物聯(lián)網(wǎng)平臺阿里云計算巢

  2. 服務(wù)實例頁簽的全托管服務(wù)下,找到對應(yīng)的實例,單擊實例卡片。

image14.png

  1. 在左側(cè)導(dǎo)航欄,選擇產(chǎn)品開發(fā) > 產(chǎn)品,單擊創(chuàng)建產(chǎn)品,創(chuàng)建一個產(chǎn)品:燈泡測試。

image15.png

  1. 產(chǎn)品創(chuàng)建成功后,單擊繼續(xù)開發(fā)前往功能定義,為產(chǎn)品添加自定義功能并發(fā)布。如圖所示,本示例添加屬性工作狀態(tài)(LightStatus)

image16.png

  1. 在左側(cè)導(dǎo)航欄,選擇設(shè)備管理 > 設(shè)備列表,單擊添加設(shè)備,在燈泡產(chǎn)品下添加設(shè)備:LampTest。設(shè)備添加成功后,獲取設(shè)備證書信息(ProductKey、DeviceName和DeviceSecret)。

image17.png

您可在設(shè)備列表,單擊設(shè)備LampTest對應(yīng)的查看進(jìn)入設(shè)備詳情頁面,查看運行狀態(tài)連接參數(shù)

image18.png

使用Postman模擬設(shè)備

1.您可攜帶MQTT連接參數(shù)在Postman創(chuàng)建對應(yīng)的MQTT連接,具體步驟可以參考使用Postman模擬設(shè)備

image19.png

2.完成對/sys/${productKey}/${deviceName}/thing/service/property/set下發(fā)屬性topic的訂閱

image20.png

設(shè)置和獲取期望屬性值

您可通過平臺提供的Java簽名示例代碼生成URL語法后調(diào)用物聯(lián)網(wǎng)平臺云端API,設(shè)置設(shè)備期望屬性值。

1.在示例代碼OpenAPISignatureDemo類中找到對應(yīng)的代碼塊,完成對SetDeviceDesiredProperty方法參數(shù)的替換。

        //方法二:已經(jīng)有參數(shù)Map,使用參數(shù)進(jìn)行簽名
        Map<String, String> map = new HashMap<String, String>();
        // 公共參數(shù)
        map.put("AccessKeyId", accessKey);
        map.put("SignatureMethod", "HMAC-SHA1");
        map.put("Timestamp", formattedDateTime);
        map.put("SignatureNonce", signatureOnce);
        // 接口請求參數(shù)
        map.put("Action", "SetDeviceDesiredProperty");
        map.put("Versions", "{}");
        map.put("Items", "{\"LightStatus\":13}");
        map.put("ProductKey", "xZluAsUunlbuhDdG");
        map.put("DeviceName", "LampTest");
        try {
            String signature = SignatureUtils.generate(httpMethod, map, secretKey);
            System.out.println("[方法二:開始生成]======根據(jù)參數(shù)生成簽名,并且生成curl命令");
            System.out.println("curl " + "'" + host+"/?"+buildQueryParam(map) + "&Signature=" + signature + "'");
        } catch (Exception e) {
            System.out.println("生成簽名失敗"+e.getMessage());
            e.printStackTrace();
        }

執(zhí)行后會得到如下URL語法請求

curl 'https://si-d6e8d812acb848958054.tuyacloud.com:8686/?Action=SetDeviceDesiredProperty&Versions=%7B%7D&SignatureNonce=c653621a65e444b18786e0f096e92b72&AccessKeyId=xMr9wgwXQLhv5AUa65o03mcD&SignatureMethod=HMAC-SHA1&Items=%7B%22LightStatus%22%3A1%7D&Timestamp=2024-11-19T10%3A24%3A29Z&ProductKey=xZluAsUunlbuhDdG&DeviceName=LampTest&Signature=d3RCeZ%2FSk2orvOn8XHzVn3jh8NM%3D'

設(shè)備在線時,設(shè)備監(jiān)聽/sys/${productKey}/${deviceName}/thing/service/property/set可以直接收到設(shè)置的屬性

image21.png

設(shè)備離線時,設(shè)備無法收到消息,在設(shè)備上線后通過對/sys/${productKey}/${deviceName}/thing/property/desired/get推送對應(yīng)的上行消息,

對/sys/${productKey}/${deviceName}/thing/property/desired/get_reply完成訂閱,可以獲取最新的期望屬性。具體消息格式可參考設(shè)備期望屬性值

image22.png

設(shè)備端開發(fā)

設(shè)備獲取期望屬性值,有兩種場景:

  • 燈泡重新上線時,主動獲取物聯(lián)網(wǎng)平臺云端緩存的期望屬性值。

  • 燈泡正處于上線狀態(tài),實時接收物聯(lián)網(wǎng)平臺云端推送的期望屬性值。

設(shè)備端開發(fā)更多信息,請參見使用設(shè)備端SDK接入。

本文以Java 代碼為例,提供了設(shè)備端Demo示例,請參見下文附錄:設(shè)備端Demo代碼。

  1. 填入設(shè)備證書、地域和MQTT接入地址的信息。

/**
* 設(shè)備證書信息
*/
private static String productKey = "******";
private static String deviceName = "********";
private static String deviceSecret = "**************";
/**
* MQTT連接信息
*/
private static String regionId = "******";
private static String iotInstanceId = "si-*************";

......

/**
* 設(shè)置 Mqtt 初始化參數(shù)
*/ 
config.channelHost = iotInstanceId + ".aliyun.tuyacloud.com:1883";

2.添加以下方法,用于變更實際燈泡的屬性,并在屬性變更后,主動將信息上報到最新屬性值中。

/**
 * 真實設(shè)備處理屬性變更時,在以下兩個場下會被調(diào)用:
 * 場景1. 設(shè)備聯(lián)網(wǎng)后主動獲取最新的屬性期望值(由設(shè)備發(fā)起,拉模式)
 * 場景2. 設(shè)備在線時接收到云端property.set推送的屬性期望值(由云端發(fā)起,推模式)
 * @param identifier  屬性標(biāo)識符
 * @param value       期望屬性值
 * @param needReport  是否通過property.post發(fā)送狀態(tài)上報。
 *                    上面場景2的處理函數(shù)中已集成屬性上報能力,會將needReport設(shè)置為false
 * @return
 */
private boolean handlePropertySet(String identifier, ValueWrapper value, boolean needReport) {
    ALog.d(TAG, "真實設(shè)備處理屬性變更 = [" + identifier + "], value = [" + value + "]");
    // 用戶根據(jù)實際情況判性是否設(shè)置成功,這里測試直接返回成功
    boolean success = true;
    if (needReport) {
        reportProperty(identifier, value);
    }
    return success;
}

private void reportProperty(String identifier, ValueWrapper value){
    if (StringUtils.isEmptyString(identifier) || value == null) {
        return;
    }

    ALog.d(TAG, "上報屬性identity=" + identifier);

    Map<String, ValueWrapper> reportData = new HashMap<>();
    reportData.put(identifier, value);
    LinkKit.getInstance().getDeviceThing().thingPropertyPost(reportData, new IPublishResourceListener() {

        public void onSuccess(String s, Object o) {
            // 屬性上報成功
            ALog.d(TAG, "上報成功 onSuccess() called with: s = [" + s + "], o = [" + o + "]");
        }

        public void onError(String s, AError aError) {
            // 屬性上報失敗
            ALog.d(TAG, "上報失敗onError() called with: s = [" + s + "], aError = [" + JSON.toJSONString(aError) + "]");
        }
    });
}

3.燈泡在線時,如果物聯(lián)網(wǎng)平臺設(shè)置了燈泡的期望屬性值,該值將被推送到設(shè)備端。燈泡處理消息,改變屬性狀態(tài)。

如下代碼中,將調(diào)用connectNotifyListener處理消息,相關(guān)Alink協(xié)議說明,請參見設(shè)備上報屬性

收到異步下行的數(shù)據(jù)后,mCommonHandler被調(diào)用,進(jìn)而調(diào)用handlePropertySet更新設(shè)備的物理屬性。

/**
 * 注冊服務(wù)調(diào)用(以及屬性設(shè)置)的響應(yīng)函數(shù)。
 * 云端調(diào)用設(shè)備的某項服務(wù)的時候,設(shè)備端需要響應(yīng)該服務(wù)并回復(fù)。
 */
public void connectNotifyListener() {
    List<Service> serviceList = LinkKit.getInstance().getDeviceThing().getServices();
    for (int i = 0; serviceList != null && i < serviceList.size(); i++) {
        Service service = serviceList.get(i);
        LinkKit.getInstance().getDeviceThing().setServiceHandler(service.getIdentifier(), mCommonHandler);
    }
}

private ITResRequestHandler mCommonHandler = new ITResRequestHandler() {
    public void onProcess(String serviceIdentifier, Object result, ITResResponseCallback itResResponseCallback) {
        ALog.d(TAG, "onProcess() called with: s = [" + serviceIdentifier + "]," +
                " o = [" + result + "], itResResponseCallback = [" + itResResponseCallback + "]");
        ALog.d(TAG, "收到云端異步服務(wù)調(diào)用 " + serviceIdentifier);
        try {
            if (SERVICE_SET.equals(serviceIdentifier)) {
                Map<String, ValueWrapper> data = (Map<String, ValueWrapper>)((InputParams)result).getData();
                ALog.d(TAG, "收到異步下行數(shù)據(jù) " + data);
                // 設(shè)置真實設(shè)備的屬性,然后上報設(shè)置完成的屬性值
                boolean isSetPropertySuccess =
                        handlePropertySet("LightStatus", data.get("LightStatus"), false);
                if (isSetPropertySuccess) {
                    if (result instanceof InputParams) {
                        // 響應(yīng)云端,接收數(shù)據(jù)成功
                        itResResponseCallback.onComplete(serviceIdentifier, null, null);
                    } else {
                        itResResponseCallback.onComplete(serviceIdentifier, null, null);
                    }
                } else {
                    AError error = new AError();
                    error.setCode(100);
                    error.setMsg("setPropertyFailed.");
                    itResResponseCallback.onComplete(serviceIdentifier, new ErrorInfo(error), null);
                }
            } else if (SERVICE_GET.equals(serviceIdentifier)) {
            } else {
                // 根據(jù)不同的服務(wù)做不同的處理,跟具體的服務(wù)有關(guān)系
                ALog.d(TAG, "根據(jù)真實的服務(wù)返回服務(wù)的值,請參照set示例");
                OutputParams outputParams = new OutputParams();
                // outputParams.put("op", new ValueWrapper.IntValueWrapper(20));
                itResResponseCallback.onComplete(serviceIdentifier, null, outputParams);
            }
        } catch (Exception e) {
            e.printStackTrace();
            ALog.d(TAG, "云端返回數(shù)據(jù)格式異常");
        }
    }

    public void onSuccess(Object o, OutputParams outputParams) {
        ALog.d(TAG, "onSuccess() called with: o = [" + o + "], outputParams = [" + outputParams + "]");
        ALog.d(TAG, "注冊服務(wù)成功");
    }

    public void onFail(Object o, ErrorInfo errorInfo) {
        ALog.d(TAG, "onFail() called with: o = [" + o + "], errorInfo = [" + errorInfo + "]");
        ALog.d(TAG, "注冊服務(wù)失敗");
    }
};

4.燈泡離線后,如果物聯(lián)網(wǎng)平臺云端設(shè)置了燈的期望屬性值,該值將被存儲在云端。

燈泡上線后,會主動獲取期望屬性值,然后調(diào)用handlePropertySet更新實際設(shè)備的屬性。

LinkKit.getInstance().init(params, new ILinkKitConnectListener() {
    public void onError(AError aError) {
        ALog.e(TAG, "Init Error error=" + aError);
    }
    public void onInitDone(InitResult initResult) {
        ALog.i(TAG, "onInitDone result=" + initResult);

        connectNotifyListener();

        // 獲取云端最新期望屬性值
        getDesiredProperty(deviceInfo, Arrays.asList("LightStatus"), new IConnectSendListener() {
            public void onResponse(ARequest aRequest, AResponse aResponse) {
                if(aRequest instanceof MqttPublishRequest && aResponse.data != null) {
                    JSONObject jsonObject = JSONObject.parseObject(aResponse.data.toString());
                    ALog.i(TAG, "onResponse result=" + jsonObject);
                    JSONObject dataObj = jsonObject.getJSONObject("data");
                    if (dataObj != null) {
                        if (dataObj.getJSONObject("LightStatus") == null) {
                            // 未設(shè)置期望值
                        } else {
                            Integer value = dataObj.getJSONObject("LightStatus").getInteger("value");
                            handlePropertySet("LightStatus", new ValueWrapper.IntValueWrapper(value), true);
                        }
                    }
                }
            }
            public void onFailure(ARequest aRequest, AError aError) {
                ALog.d(TAG, "onFailure() called with: aRequest = [" + aRequest + "], aError = [" + aError + "]");
            }
        });
    }
});

private void getDesiredProperty(BaseInfo info, List<String> properties, IConnectSendListener listener) {
    ALog.d(TAG, "getDesiredProperty() called with: info = [" + info + "], listener = [" + listener + "]");
    if(info != null && !StringUtils.isEmptyString(info.productKey) && !StringUtils.isEmptyString(info.deviceName)) {
        MqttPublishRequest request = new MqttPublishRequest();
        request.topic = DESIRED_PROPERTY_GET.replace("{productKey}", info.productKey).replace("{deviceName}", info.deviceName);
        request.replyTopic = DESIRED_PROPERTY_GET_REPLY.replace("{productKey}", info.productKey).replace("{deviceName}", info.deviceName);
        request.isRPC = true;
        RequestModel<List<String>> model = new RequestModel<>();
        model.id = String.valueOf(IDGeneraterUtils.getId());
        model.method = METHOD_GET_DESIRED_PROPERTY;
        model.params = properties;
        model.version = "1.0";
        request.payloadObj = model.toString();
        ALog.d(TAG, "getDesiredProperty: payloadObj=" + request.payloadObj);
        ConnectSDK.getInstance().send(request, listener);
    } else {
        ALog.w(TAG, "getDesiredProperty failed, baseInfo Empty.");
        if(listener != null) {
            AError error = new AError();
            error.setMsg("BaseInfoEmpty.");
            listener.onFailure(null, error);
        }
    }
}

附錄:設(shè)備端Demo代碼