天天看點

阿裡雲物聯網平台物模型功能測試示例Demo

功能類型 說明
屬性(Property) 一般用于描述裝置運作時的狀态,如環境監測裝置所讀取的目前環境溫度等。屬性支援GET和SET請求方式。應用系統可發起對屬性的讀取和設定請求。
服務(Service) 裝置可被外部調用的能力或方法,可設定輸入參數和輸出參數。相比于屬性,服務可通過一條指令實作更複雜的業務邏輯,如執行某項特定的任務。
事件(Event) 裝置運作時的事件。事件一般包含需要被外部感覺和處理的通知資訊,可包含多個輸出參數。如,某項任務完成的資訊,或者裝置發生故障或告警時的溫度等,事件可以被訂閱和推送。

使用: 裝置端可以上報屬性和事件;雲端可以向裝置端發送設定屬性和調用服務的指令。

Step By Step

1、産品物模型model.json(替換産品productKey導入即可)

{
    "schema":"https://iotx-tsl.oss-ap-southeast-1.aliyuncs.com/schema.json",
    "profile":{
        "productKey":"a1qLU******"
    },
    "properties":[
        {
            "identifier":"Temperature",
            "name":"溫度",
            "accessMode":"rw",
            "desc":"電機工作溫度",
            "required":false,
            "dataType":{
                "type":"float",
                "specs":{
                    "min":"-55",
                    "max":"200",
                    "unit":"℃",
                    "step":"0.1"
                }
            }
        }
    ],
    "events":[
        {
            "identifier":"post",
            "name":"post",
            "type":"info",
            "required":true,
            "desc":"屬性上報",
            "method":"thing.event.property.post",
            "outputData":[
                {
                    "identifier":"Temperature",
                    "name":"溫度",
                    "dataType":{
                        "type":"float",
                        "specs":{
                            "min":"-55",
                            "max":"200",
                            "unit":"℃",
                            "step":"0.1"
                        }
                    }
                }
            ]
        },
        {
            "identifier":"event1",
            "name":"異常事件",
            "type":"info",
            "required":false,
            "method":"thing.event.event1.post",
            "outputData":[
                {
                    "identifier":"event1",
                    "name":"事件參數1",
                    "dataType":{
                        "type":"int",
                        "specs":{
                            "min":"1",
                            "max":"100",
                            "step":"1"
                        }
                    }
                }
            ]
        }
    ],
    "services":[
        {
            "identifier":"set",
            "name":"set",
            "required":true,
            "callType":"async",
            "desc":"屬性設定",
            "method":"thing.service.property.set",
            "inputData":[
                {
                    "identifier":"Temperature",
                    "name":"溫度",
                    "dataType":{
                        "type":"float",
                        "specs":{
                            "min":"-55",
                            "max":"200",
                            "unit":"℃",
                            "step":"0.1"
                        }
                    }
                }
            ],
            "outputData":[
                
            ]
        },
        {
            "identifier":"get",
            "name":"get",
            "required":true,
            "callType":"async",
            "desc":"屬性擷取",
            "method":"thing.service.property.get",
            "inputData":[
                "Temperature"
            ],
            "outputData":[
                {
                    "identifier":"Temperature",
                    "name":"溫度",
                    "dataType":{
                        "type":"float",
                        "specs":{
                            "min":"-55",
                            "max":"200",
                            "unit":"℃",
                            "step":"0.1"
                        }
                    }
                }
            ]
        },
        {
            "identifier":"addFuctionServiceAsync",
            "name":"異步加法服務",
            "required":false,
            "callType":"async",
            "method":"thing.service.addFuctionServiceAsync",
            "inputData":[
                {
                    "identifier":"add1",
                    "name":"加數1",
                    "dataType":{
                        "type":"int",
                        "specs":{
                            "min":"1",
                            "max":"100",
                            "step":"1"
                        }
                    }
                },
                {
                    "identifier":"add2",
                    "name":"加數2",
                    "dataType":{
                        "type":"int",
                        "specs":{
                            "min":"1",
                            "max":"100",
                            "step":"1"
                        }
                    }
                }
            ],
            "outputData":[
                {
                    "identifier":"result",
                    "name":"結果",
                    "dataType":{
                        "type":"int",
                        "specs":{
                            "min":"1",
                            "max":"200",
                            "step":"1"
                        }
                    }
                }
            ]
        },
        {
            "identifier":"addFuctionServiceSync",
            "name":"加法服務",
            "required":false,
            "callType":"sync",
            "desc":"同步功能",
            "method":"thing.service.addFuctionServiceSync",
            "inputData":[
                {
                    "identifier":"add2",
                    "name":"加數2",
                    "dataType":{
                        "type":"int",
                        "specs":{
                            "min":"1",
                            "max":"100",
                            "step":"1"
                        }
                    }
                },
                {
                    "identifier":"add1",
                    "name":"加數1",
                    "dataType":{
                        "type":"int",
                        "specs":{
                            "min":"1",
                            "max":"100",
                            "step":"1"
                        }
                    }
                }
            ],
            "outputData":[
                {
                    "identifier":"result",
                    "name":"計算結果",
                    "dataType":{
                        "type":"int",
                        "specs":{
                            "min":"1",
                            "max":"200",
                            "step":"1"
                        }
                    }
                }
            ]
        }
    ]
}           

2、裝置端Code Sample(基于開源Java MQTT Client)

import com.alibaba.fastjson.JSONObject;
import com.alibaba.taro.AliyunIoTSignUtil;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;

import java.util.HashMap;
import java.util.Map;

public class IoTThingTest {

    public static String productKey = "a1qLU******";
    public static String deviceName = "device1";
    public static String deviceSecret = "cA9wzIM6bL2QI6DgAaSO0FPg********";
    public static String regionId = "cn-shanghai";

    // 物模型-屬性上報topic
    private static String pubTopic = "/sys/" + productKey + "/" + deviceName + "/thing/event/property/post";
    // 物模型-屬性響應topic
    private static String subTopic = "/sys/" + productKey + "/" + deviceName + "/thing/event/property/post_reply";
    // 物模型-事件上報topic
    private static String eventPubTopic = "/sys/" + productKey + "/" + deviceName + "/thing/event/event1/post";

    // 物模型-事件上報響應topic
    private static String eventSubTopic = "/sys/" + productKey + "/" + deviceName + "/thing/event/event1/post_reply";


    private static MqttClient mqttClient;

    public static void main(String [] args){

        // 初始化Client
        initAliyunIoTClient();
        try {
            mqttClient.subscribe(subTopic); // 訂閱Topic
            mqttClient.subscribe(eventSubTopic);
        } catch (MqttException e) {
            System.out.println("error:" + e.getMessage());
            e.printStackTrace();
        }

        // 設定訂閱監聽
        mqttClient.setCallback(new MqttCallback() {
            @Override
            public void connectionLost(Throwable throwable) {
                System.out.println("connection Lost");

            }
            @Override
            public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
                System.out.println("Sub message");
                System.out.println("Topic : " + s);
                System.out.println(new String(mqttMessage.getPayload())); //列印輸出消息payLoad

                // 服務調用處理
                if (s.contains("Async") || s.contains("rrpc")) {
                    String content = new String((byte[]) mqttMessage.getPayload());
                    System.out.println("服務請求Topic:" + s);
                    System.out.println("服務指令:" + content);

                    JSONObject request = JSONObject.parseObject(content);
                    JSONObject params = request.getJSONObject("params");
                    if (!params.containsKey("add1")) { // 檢查入參
                        System.out.println("不包含參數add1");
                        return;
                    }
                    Integer input1 = params.getInteger("add1"); // 擷取入參
                    Integer input2 = params.getInteger("add2"); // 擷取入參
                    JSONObject response = new JSONObject();
                    JSONObject data = new JSONObject();
                    data.put("result", input1 + input2);
                    response.put("id", request.get("id"));
                    response.put("code", 200);
                    response.put("data", data);

                    String responseTopic = s;
                    // 服務響應
                    if (s.contains("rrpc")) {
                        // 同步服務調用響應Topic
                        responseTopic = s.replace("request", "response");
                    } else {
                        // 異步服務調用響應Topic
                        responseTopic = responseTopic + "_reply";
                    }
                    MqttMessage message1 = new MqttMessage(response.toString().getBytes("utf-8"));
                    System.out.println("responseTopic: " + responseTopic);
                    mqttClient.publish(responseTopic, message1);
                }
            }

            @Override
            public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {

            }
        });

        // 屬性上報
        postDeviceProperties();
        // 事件上報
        postDeviceEvent();
    }

    /**
     * 初始化 Client 對象
     */
    private static void initAliyunIoTClient() {

        try {
            // 構造連接配接需要的參數
            String clientId = "java" + System.currentTimeMillis();
            Map<String, String> params = new HashMap<>(16);
            params.put("productKey", productKey);
            params.put("deviceName", deviceName);
            params.put("clientId", clientId);
            String timestamp = String.valueOf(System.currentTimeMillis());
            params.put("timestamp", timestamp);
            // cn-shanghai
            String targetServer = "tcp://" + productKey + ".iot-as-mqtt."+regionId+".aliyuncs.com:1883";

            String mqttclientId = clientId + "|securemode=3,signmethod=hmacsha1,timestamp=" + timestamp + "|";
            String mqttUsername = deviceName + "&" + productKey;
            String mqttPassword = AliyunIoTSignUtil.sign(params, deviceSecret, "hmacsha1");

            connectMqtt(targetServer, mqttclientId, mqttUsername, mqttPassword);

        } catch (Exception e) {
            System.out.println("initAliyunIoTClient error " + e.getMessage());
        }
    }

    public static void connectMqtt(String url, String clientId, String mqttUsername, String mqttPassword) throws Exception {

        MemoryPersistence persistence = new MemoryPersistence();
        mqttClient = new MqttClient(url, clientId, persistence);
        MqttConnectOptions connOpts = new MqttConnectOptions();
        // MQTT 3.1.1
        connOpts.setMqttVersion(4);
        connOpts.setAutomaticReconnect(false);
        connOpts.setConnectionTimeout(10);
//        connOpts.setCleanSession(true);
        connOpts.setCleanSession(false);

        connOpts.setUserName(mqttUsername);
        connOpts.setPassword(mqttPassword.toCharArray());
        connOpts.setKeepAliveInterval(60);

        mqttClient.connect(connOpts);
    }

    /**
     * 事件上報
     */
    private static void postDeviceEvent() {

        try {
            //上報資料
            //進階版 物模型-屬性上報payload
            System.out.println("事件上報");
            String payloadJson = "{\"params\":{\"event1\":23}}";
            MqttMessage message = new MqttMessage(payloadJson.getBytes("utf-8"));
            message.setQos(1);
            mqttClient.publish(eventPubTopic, message);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    /**
     * 彙報屬性
     */
    private static void postDeviceProperties() {

        try {
            //上報資料
            //進階版 物模型-屬性上報payload
            System.out.println("上報屬性值");
            String payloadJson = "{\"params\":{\"Temperature\":13}}";
            MqttMessage message = new MqttMessage(payloadJson.getBytes("utf-8"));
            message.setQos(1);
            mqttClient.publish(pubTopic, message);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}           
參考連結: 基于開源JAVA MQTT Client連接配接阿裡雲IoT

3、啟動裝置檢視屬性及事件上報情況

  • 3.1 服務端情況
阿裡雲物聯網平台物模型功能測試示例Demo
阿裡雲物聯網平台物模型功能測試示例Demo
  • 3.2 裝置端reply情況
上報屬性值
事件上報
Sub message
Topic : /sys/a1qLU******/device1/thing/event/property/post_reply
{"code":200,"data":{},"id":"null","message":"success","method":"thing.event.property.post","version":"1.0"}
Sub message
Topic : /sys/a1qLU******/device1/thing/event/event1/post_reply
{"code":200,"data":{},"id":"null","message":"success","method":"thing.event.event1.post","version":"1.0"}           

4、異步服務調用

  • 4.1 說明
通過 InvokeThingService InvokeThingsService 接口調用服務,物聯網平台采用異步方式下行推送請求,裝置也采用異步方式傳回結果。 此時,服務選擇為異步調用方式,物聯網平台訂閱此處的異步響應Topic。異步調用的結果,可以使用 規則引擎資料流轉功能 擷取,也可以使用服務端訂閱擷取。
  • 4.2 Open API
阿裡雲物聯網平台物模型功能測試示例Demo
  • 4.3 裝置端日志
Sub message
Topic : /sys/a1qLU******/device1/thing/service/addFuctionServiceAsync
{"method":"thing.service.addFuctionServiceAsync","id":"2015524670","params":{"add2":2,"add1":2},"version":"1.0.0"}
服務請求Topic:/sys/a1qLU******/device1/thing/service/addFuctionServiceAsync
服務指令:{"method":"thing.service.addFuctionServiceAsync","id":"2015524670","params":{"add2":2,"add1":2},"version":"1.0.0"}
responseTopic: /sys/a1qLU******/device1/thing/service/addFuctionServiceAsync_reply           
  • 4.4 控制台日志
阿裡雲物聯網平台物模型功能測試示例Demo
  • 4.5 AMQP 服務端訂閱擷取的服務響應
Content:{"iotId":"*******","code":200,"data":{"result":4},"requestId":"2009566194","topic":"/sys/*******/device1/thing/service/addFuctionServiceAsync_reply","source":"DEVICE","gmtCreate":1583658474852,"productKey":"a1qLU******","deviceName":"device1"}           

5、同步服務調用

  • 5.1 說明
接口調用服務,物聯網平台直接使用 RRPC同步 方式下行推送請求。此時,服務選擇為同步調用方式,物聯網平台訂閱RRPC對應Topic。
  • 5.2 Open API
阿裡雲物聯網平台物模型功能測試示例Demo
  • 5.3 裝置端日志
Sub message
Topic : /sys/a1qLU******/device1/rrpc/request/1236608506958775809
{"method":"thing.service.addFuctionServiceSync","id":"2015301903","params":{"add2":2,"add1":2},"version":"1.0.0"}
服務請求Topic:/sys/a1qLU******/device1/rrpc/request/1236608506958775809
服務指令:{"method":"thing.service.addFuctionServiceSync","id":"2015301903","params":{"add2":2,"add1":2},"version":"1.0.0"}
responseTopic: /sys/a1qLU******/device1/rrpc/response/1236608506958775809           
  • 5.4 控制台日志
阿裡雲物聯網平台物模型功能測試示例Demo

更多參考

裝置屬性、事件、服務 同步服務調用 基于開源Java MQTT Client的阿裡雲物聯網平台RRPC功能測試 阿裡雲物聯網平台規則引擎綜述