すべてのプロダクト
Search
ドキュメントセンター

Marketplace:デバイスの目的のプロパティの適用

最終更新日:Mar 26, 2025

重要

免責事項

このページに掲載されているすべてのコンテンツは、Tuya (HK) Limited によって提供されていることにご注意ください。Alibaba Cloud は、そのようなコンテンツの真正性または正確性について、明示的または黙示的に表明または保証するものではなく、Tuya (HK) Limited によって提供される製品および/またはサービスの状態、品質、耐久性、性能、信頼性、商品性、特定の目的への適合性、または非侵害性についても一切保証するものではありません。

モノのインターネット ソリューションでは、属性を配信する際にデバイスがオンラインでない場合、配信は失敗します。属性の配信をよりスマートかつ効率的に完了したい場合はどうすればよいでしょうか? IoT プラットフォームは、期待される属性値を設定する機能を提供します。デバイス属性の期待値をキャッシュすることにより、IoT プラットフォームはクラウドからデバイス属性値を制御できます。 この記事では、目的の属性値を設定して IoT プラットフォームから電球の状態を制御する操作について説明します。

シーン情報

スイッチデバイスが IoT プラットフォームに接続された後、IoT プラットフォームから電球の動作状態を制御する必要がある場合 (1: オン、0: オフ)、電球は常にオンライン状態を維持する必要があります。実際には、電球は常にオンラインであるとは限りません。 IoT Platform で期待されるデバイス属性値を設定して、IoT Platform に保存することができます。デバイスがオンラインになると、IoT プラットフォームによって保存された期待される属性値を読み取って、自身の属性値を更新できます。その後、デバイスは更新された属性値を IoT Platform に報告します。

image.png

全体的なプロセス

1. 製品と機器を作成する 2. Postman を使用してデバイスをシミュレートする 3. 目的のプロパティを設定および取得する。 4. 機器の開発

製品とデバイスの作成

1 入力Tuya IoT プラットフォーム Alibaba Cloud Computing ネスト 。 2 [In] サービス インスタンスタブ フルマネージド サービス対応するインスタンスを見つけて、インスタンスカードを クリック します。

image.png

3 左側のナビゲーションバーで、プロダクト開発> プロダクト、[クリック] 製品を作成、プロダクト bulb test を作成します。

image.png

4 プロダクトが正常に作成された後、[クリック] 開発を継続する見出し 関数定義、プロダクトにカスタム機能を追加して公開します。図に示すように、この例では属性 動作ステータス (LightStatus)

image.png

5 左側のナビゲーション バーで、デバイス管理> デバイスリスト、[クリック] [デバイスの追加]、BULB プロダクトの LampTest に機器を追加します。デバイスが追加された後、デバイス証明書情報 (ProductKey、DeviceName、および DeviceSecret) を取得します。

image.png

デバイス リストで、[クリック] 表示入力機器の詳細ページ、表示実行状態および 接続パラメーター

image.png

Postman を使用したデバイスのシミュレート

1. MQTT 接続パラメーターを Postman 対応する MQTT 接続を作成します。詳細については、「Postman を使用してデバイスをシミュレートする

image.png

2. ペア /sys/${productKey}/${deviceName}/thing/service/property/set のサブスクライブを Topic に完了します。

image.png

期待されるプロパティ値の設定と取得

プラットフォームを介して提供できます。Java 署名サンプルコード生成後、URL 構文に従って IoT プラットフォーム クラウド API を呼び出し、目的のデバイス属性値を設定します。 1. サンプルコードの OpenAPISignatureDemo クラスにある該当のコードブロックを見つけ、SetDeviceDesiredProperty メソッドパラメーターの置き換えを完了します。

//メソッド 2: パラメータマップが既に存在する場合、パラメータを使用して署名します
Map<String, String> map = new HashMap<String, String>();
//公開パラメータ
map.put("AccessKeyId", accessKey);
map.put("SignatureMethod", "HMAC-SHA1");
map.put("Timestamp", formattedDateTime);
map.put("SignatureNonce", signatureOnce);
//インターフェースリクエストパラメータ
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 ("[メソッド 2: 生成開始]=====パラメータに基づいて署名を生成し、curl コマンドを生成します");
System.out.println("curl " + "'" + host+"/?"+buildQueryParam(map) + "&Signature=" + signature + "'");
} catch (Exception e) {
System. out. println ("署名生成に失敗しました"+e.g. etMessage ());
e.printStackTrace();
}

実行後、次の 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'

デバイスがオンラインの場合、デバイス監視/sys/ ${productKey}/${deviceName} /thing/service/property/set は設定されたプロパティを直接受信できます

image.png

デバイスがオフラインの場合、 デバイスはメッセージを受信できません。デバイスがオンラインになった後、/sys/${productKey}/${deviceName}/thing/property/desired/get を介して対応するアップリンクメッセージをプッシュし、/sys/${productKey}/${deviceName}/thing/property/desired/get_reply をサブスクライブして最新の目的のプロパティを取得します。具体的なメッセージ形式については、「デバイスがメッセージを受信できない、デバイスがオンラインになった後、対応するアップリンク メッセージを /sys/${productKey}/${deviceName}/thing/property/desired/get 経由でプッシュし、/sys/${productKey}/${deviceName}/thing/property/desired/get_reply にサブスクライブして最新の desired プロパティを取得します。具体的なメッセージ フォーマットは、デバイスの期待される属性値」をご参照ください。

image.png

デバイス開発

デバイスは期待される属性値を取得します。2 つのシナリオがあります。 ●電球が再びオンラインになると、IoT プラットフォームのクラウドキャッシュの期待される属性値をアクティブに取得します。 ●電球はオンライン状態で、IoT プラットフォームによってプッシュされた期待される属性値をリアルタイムで受信します。 デバイス側の開発の詳細については、「デバイス SDK を使用したアクセス」をご参照ください。 この記事では、Java コードを例として使用して、デバイス Demo の例を提供します。詳細については、以下の付録「デバイス Demo コード」をご参照ください。 1 デバイス証明書、リージョン、MQTT アクセスアドレスの情報を入力します。

/**
* デバイス証明書の 情報
*/
private static String productKey = "******";
private static String deviceName = "********";
private static String deviceSecret = "***************";
/**
* MQTT 接続情報
*/
private static String regionId = "******";
private static String iotInstanceId = "si-*************";

...

/**
* Mqtt の初期化パラメータを設定する
*/
config.channelHost = iotInstanceId + ".aliyun.tuyacloud.com:1883";

2. 実際の電球の属性を変更し、属性が変更された後に最新の属性値に情報を報告する以下のメソッドを追加します。

/**
* 実際のデバイスが属性の変更を処理する場合、次の 2 つのフィールドで呼び出されます。
* シナリオ 1 デバイスのネットワーク接続後に最新の期待される属性値を積極的に取得する (デバイスによって開始、プルモード)
* シナリオ 2 デバイスがオンラインの場合、クラウドの property.set によってプッシュされた属性の期待値を受信する (クラウドによって開始、プッシュモード)
*@ param identifier 属性識別子
*@ param value 期待される属性値
* @paramNeedReport property.post を介してステータスレポートを送信するかどうか。
* シナリオ 2 の処理関数には属性レポート機能が統合されており、demandReport を false に設定します
* @return
*/
private boolean handlePropertySet(String identifier, ValueWrapper value, boolean needReport) {
    ALog.d(TAG, "実際のデバイスが属性の変更を処理しています = [" + identifier + "], value = [" + value + "]");
    // ユーザーは実際の状況に基づいて設定が成功したかどうかを判断し、テストではここで直接成功を返します
    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. 電球がオンラインの場合、IoT プラットフォームが電球の目的の属性値を設定すると、その値はデバイスにプッシュされます。電球はメッセージを処理し、プロパティの状態を変更します。 次のコードでは、connectNotifyListener がメッセージを処理します。Alink プロトコルの詳細については、「」をご参照ください。 非同期ダウンリンクデータを受信した後、mCommonHandler が呼び出され、次に handlePropertySet を呼び出してデバイスの物理プロパティを更新します。デバイスのプロパティ、イベント、およびサービス. 非同期ダウンリンクデータを受信した後、mCommonHandler が呼び出され、それが handlePropertySet を呼び出してデバイスの物理プロパティを更新します。

/**
 * サービスコール (およびプロパティ設定) の登録応答関数。
 * クラウド内のデバイスからサービスを呼び出す場合、デバイスはサービスに応答して返信する必要があります。
 */
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, "クラウドからの非同期サービスコールを受信しました " + serviceIdentifier);
        try {
            if (SERVICE_SET.equals(serviceIdentifier)) {
                Map<String, ValueWrapper> data = (Map<String, ValueWrapper>)((InputParams)result).getData();
                ALog.d(TAG, "非同期ダウンリンクデータを受信しました " + data);
                // 実際のデバイスのプロパティを設定し、完了したプロパティ値を報告します
                boolean isSetPropertySuccess =
                        handlePropertySet("LightStatus", data.get("LightStatus"), false);
                if (isSetPropertySuccess) {
                    if (result instanceof InputParams) {
                        // クラウドへの応答、データの受信に成功しました
                        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 {
                // 異なるサービスを異なる方法で処理することは、特定のサービスに関連しています
                ALog.d(TAG, "実際のサービスに基づいてサービスの値を返します。設定例を参照してください");
                OutputParams outputParams = new OutputParams();
                // outputParams.put("op", new ValueWrapper.IntValueWrapper(20));
                itResResponseCallback.onComplete(serviceIdentifier, null, outputParams);
            }
        } catch (Exception e) {
            e.printStackTrace();
            ALog.d(TAG, "クラウドから返された異常なデータ形式");
        }
    }

    public void onSuccess(Object o, OutputParams outputParams) {
        ALog.d(TAG, "onSuccess() called with: o = [" + o + "], outputParams = [" + outputParams + "]");
        ALog.d(TAG, "登録サービスに成功しました");
    }

    public void onFail(Object o, ErrorInfo errorInfo) {
        ALog.d(TAG, "onFail() called with: o = [" + o + "], errorInfo = [" + errorInfo + "]");
        ALog.d(TAG, "登録サービスに失敗しました");
    }
};

4. 電球がオフラインの後、IoT プラットフォームのクラウドでライトの目的の属性値が設定されている場合、その値はクラウドに保存されます。 電球がオンラインになると、目的の属性値をアクティブに取得し、次に handlePropertySet を呼び出して実際のデバイスのプロパティを更新します。

LinkKit.getInstance().init(params, new ILinkKitConnectListener() {
    public void onError(AError aError) {
        ALog.e(TAG, "初期化エラー 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) {
                            // 期待値が設定されていません
                        } 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);
        }
    }
}

付録: デバイス Demo コード