RRPC是阿里云物联网平台提供给云端应用控制设备的一种机制,本文将介绍如何实现云端应用调用RRPC接口将控制消息通过MQTT发送到设备,以及设备对控制消息进行处理并应答。

例程讲解

说明
  • RRPC存在系统TOPIC RRPC和自定义TOPIC RRPC两种不同的Topic格式,详情请参见什么是RRPC
  • 本文只对自定义topic rrpc进行了讲解。
  1. 运行mqtt-rrpc-demo

    为了进行RRPC功能的演示,修改demos/mqtt_rrpc_demo.c,在demo的demo_mqtt_default_recv_handler函数中将如下注释去掉:

    ...
            case AIOT_MQTTRECV_PUB: {
                printf("pub, qos: %d, topic: %.*s\n", packet->data.pub.qos, packet->data.pub.topic_len, packet->data.pub.topic);
                printf("pub, payload: %.*s\n", packet->data.pub.payload_len, packet->data.pub.payload);
                /* TODO: 处理服务器下发的业务报文, 此处如果收到rrpc的报文, 那么应答时使用相同的topic即可 */
                /* 更多信息请参考 https://help.aliyun.com/document_detail/90570.html */
    
                /* 下面是一个rrpc的应答示例 */
                {
                    char *payload = "pong";
                    char resp_topic[256];
    
                    memset(resp_topic, 0, sizeof(resp_topic));
                    strncpy(resp_topic, packet->data.pub.topic, sizeof(resp_topic));
    
                    aiot_mqtt_pub(handle, resp_topic, (uint8_t *)payload, (uint32_t)strlen(payload));
                } */
            }
            break;
    ...

    编译SDK,运行./output/mqtt-rrpc-demo

    [1578054042.600][LK-0313] MQTT user calls aiot_mqtt_connect api, connect
    [1578054042.600][LK-0317] mqtt_rrpc_demo&a13FNXXXXXX
    [1578054042.600][LK-0318] 24FEB95E42CADB18D0E093F412E6AC27705AA8DF6DB3B649566728E685A78079
    [1578054042.600][LK-0319] a13FNXXXXXX.mqtt_rrpc_demo|timestamp=2524608000000,_ss=1,_v=sdk-c-4.0.0,securemode=2,signmethod=hmacsha256,ext=1,|
    establish mbedtls connection with server(host='a13FNXXXXXX.iot-as-mqtt.cn-shanghai.aliyuncs.com', port=[1883])
    success to establish mbedtls connection, fd = 3
    [1578054042.711][LK-0313] MQTT connect success
    AIOT_MQTTEVT_CONNECT
    heartbeat response
    ...
  2. 调用云端SDK向设备发送RRPC请求

    云端SDK参考

    使用云端SDK调用RRPC

    这里为了配合设备端进行演示,云端SDK调用代码如下:

    RRpcRequest request = new RRpcRequest();
    request.setProductKey("a13FNXXXXXX");
    request.setDeviceName("mqtt_rrpc_demo");
    request.setRequestBase64Byte(Base64.getEncoder().encodeToString("ping".getBytes()));
    if (topic != null) {
        request.setTopic(topic);
    }
    request.setTimeout(2000);
    
    RRpcResponse response = client.getAcsResponse(request);
    System.out.println("RRpcResponse\n" + new Gson().toJson(response) + "\n");
    System.out.println(new String(Base64.getDecoder().decode(response.getPayloadBase64Byte())));

    调用完成后, 云端SDK日志如下:

    {"requestId":"EFB3FD06-9DA4-4425-9DA9-EF92D34CDA22","success":true,"rrpcCode":"SUCCESS","payloadBase64Byte":"cG9uZw\u003d\u003d","messageId":1213068527779593216}
    
    pong

    调用完成后, 设备端日志如下:

    [1578054379.700][LK-0309] pub: /ext/rrpc/1213074107617310208/a13FNXXXXXX/mqtt_rrpc_demo/user/get
    
    [LK-030A] < 70 69 6E 67                                      | ping
    
    pub, qos: 0, topic: /ext/rrpc/1213074107617310208/a13FNXXXXXX/mqtt_rrpc_demo/user/get
    pub, payload: ping
    [1578054379.700][LK-0309] pub: /ext/rrpc/1213074107617310208/a13FNXXXXXX/mqtt_rrpc_demo/user/get
    
    [LK-030A] > 70 6F 6E 67                                      | pong

    从上面云端和设备端的日志可以看出, 云端向设备端发送一个字符串ping, 设备端响应了一个字符串pong。至此,RRPC功能调用完成。