1.4.2.2.4 嵌入式设备C SDK

优质
小牛编辑
133浏览
2023-12-01

嵌入式设备C SDK

更新时间:2018-03-23 15:11:43

C SDK 快速开始

本节描述如何申请自己的设备, 并结合本SDK快速体验该设备通过MQTT+TLS/SSL协议连接到Link Develop, 上报和接收业务报文。

实现原理:

MQTT协议(Message Queuing Telemetry Transport, 消息队列遥测传输)是IBM开发的一个即时通讯协议, 是为大量计算能力有限, 且工作在低带宽, 不可靠的网络的远程传感器和控制设备通讯而设计的协议

利用MQTT协议是一种基于二进制消息的发布/订阅编程模式的消息协议, 下面的应用程序先在Link Develop订阅(Subscribe)一个Topic成功, 然后自己向该Topic做发布(Publish)动作

Link Develop收到之后, 就会原样推送回这个应用程序, 因为该程序之前已经通过订阅(Subscribe)动作成为该Topic的一个接收者, 发布到这个Topic上的任何消息, 都会被推送到已订阅该Topic的所有终端上

开发环境准备

安装Ubuntu16.04

本SDK的编译环境是64位Ubuntu16.04, 在其它Linux上尚未测试过, 所以推荐安装与Link Develop开发者一致的发行版

如果您使用Windows操作系统, 建议安装虚拟机软件Virtualbox, 下载地址: https://www.virtualbox.org/wiki/Downloads

然后安装64位的desktop版本Ubuntu 16.04.x LTS, 下载地址: https://www.ubuntu.com/download/desktop

安装必备软件

本SDK的开发编译环境使用如下软件: make-4.1, git-2.7.4, gcc-5.4.0, gcov-5.4.0, lcov-1.12, bash-4.3.48, tar-1.28, mingw-5.3.1

可使用如下命令行安装必要的软件:

apt-get install -y build-essential make git gcc

获取设备激活凭证

创建产品

点击页面左侧导航栏点击的设备按钮, 下拉菜单产品开发按钮, 再到页面右侧点新增产品。

image.png | center | 830x431

添加测试设备

产品创建完成,点击进入产品详情页面的“设备开发”标签页,下载IoT SDK。

在下方的测试设备列表,点击“新增测试设备”,输入DeviceName添加一个测试设备,如果为空将由系统为您自动颁发一个DeviceName。

创建成功后将显示系统颁发的设备激活凭证:

  • productKey: 标识设备所属的产品

  • deviceName: 标识产品下的具体设备

  • deviceSecret: 该设备的密钥, 需填写到SDK中, 用于连接阿里云服务器时完成认证

image.png | center | 613x414

编译样例程序

解压缩 SDK

登录云平台,将下载到的压缩包在Linux上解压缩:

image.png | center | 600x252

填入设备信息

编辑文件sample/mqtt/mqtt-example.c, 编辑如下代码段, 填入之前创建产品和设备步骤中得到的设备标识三元组:

编译SDK产生样例程序

运行如下命令:

$ make distclean
$ make

编译成功完成后, 生成的样例程序在当前目录的output/release/bin目录下:

$ tree output/release
output/release
├── bin
│   ├── coap-example
│   ├── http-example
│   ├── mqtt-example
│   ├── mqtt_rrpc-example
│   ├── ota_mqtt-example
│   ├── sdk-testsuites
│   └── shadow-example
...
...

服务同步调用能力开发

能力概述

MQTT协议是基于PUB/SUB的异步通信模式,对于有些场景,服务端发请求给设备端需要同时获得设备端返回结果的不太适用,IoT SDK基于MQTT协议做了一套请求和响应的同步机制,无需改动MQTT协议即可实现同步通信。对于服务端我们提供了API,设备端只需要按照固定的格式回复PUB消息,即可将响应同步返回给服务端。

设备端实现

#define PRODUCT_KEY          "..."
#define DEVICE_NAME          "..."
#define TOPIC_RRPC_REQ       "/sys/"PRODUCT_KEY"/"DEVICE_NAME"/rrpc/request/"
#define TOPIC_RRPC_RSP       "/sys/"PRODUCT_KEY"/"DEVICE_NAME"/rrpc/response/"
// 订阅RRPC的Topic
rc = IOT_MQTT_Subscribe(pclient, TOPIC_RRPC_REQ "+", IOTX_MQTT_QOS0, mqtt_rrpc_msg_arrive, NULL);
    if (rc < 0) {
        IOT_MQTT_Destroy(pclient);
        printf("IOT_MQTT_Subscribe() failed, rc = %d\n", rc);
        rc = -1;
        goto do_exit;
    }
// 回复RRPC响应
void mqtt_rrpc_msg_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
{
   iotx_mqtt_topic_info_pt     ptopic_info = (iotx_mqtt_topic_info_pt) msg->msg;
    iotx_mqtt_topic_info_t      topic_msg;
    char                        msg_pub[MSG_LEN_MAX] = {0};
    char                        topic[TOPIC_LEN_MAX] = {0};
    char                        msg_id[MSG_ID_LEN_MAX] = {0};
    // print topic name and topic message
    printf("----\n");
    printf("Topic: '%.*s' (Length: %d)\n",
           ptopic_info->topic_len,
           ptopic_info->ptopic,
           ptopic_info->topic_len);
    printf("Payload: '%.*s' (Length: %d)\n",
           ptopic_info->payload_len,
           ptopic_info->payload,
           ptopic_info->payload_len);
    printf("----\n");
    if (snprintf(msg_id,
                 ptopic_info->topic_len - strlen(TOPIC_RRPC_REQ) + 1,
                 "%s",
                 ptopic_info->ptopic + strlen(TOPIC_RRPC_REQ))
            > sizeof(msg_id)) {
        printf("snprintf error!\n");
        return;
    }
    printf("response msg_id = %s\n", msg_id);
    if (snprintf(topic, sizeof(topic), "%s%s", TOPIC_RRPC_RSP, msg_id) > sizeof(topic)) {
        printf("snprintf error!\n");
        return;
    }
    printf("response topic = %s\n", topic);
    sprintf(msg_pub, "rrpc client has received message!\n");
    topic_msg.qos = IOTX_MQTT_QOS0;
    topic_msg.retain = 0;
    topic_msg.dup = 0;
    topic_msg.payload = (void *)msg_pub;
    topic_msg.payload_len = strlen(msg_pub);
    if (IOT_MQTT_Publish(pclient, topic, &topic_msg) < 0) {
        printf("error occur when publish!\n");
    }
}

运行样例程序

执行样例程序

$ ./output/release/bin/mqtt-example
[inf] iotx_device_info_init(40): device_info created successfully!
[dbg] iotx_device_info_set(50): start to set device info!
[dbg] iotx_device_info_set(64): device_info set successfully!
[dbg] _calc_hmac_signature(57): | source: clientId2UCRZpAbCGC.ExampleDevdeviceNameExampleDevproductKey2UCRZpAbCGCtimestamp2524608000000 (93)
[dbg] _calc_hmac_signature(58): | secret: fbh47lGBSayncmTHEjF1E5x4CZdeJTO9 (32)
[dbg] _calc_hmac_signature(61): | method: hmacsha1
[dbg] _calc_hmac_signature(74): | signature: 326a4a6ed38b1bd5ddb6a5d11d27928bfb5a62d0 (40)
[dbg] guider_print_dev_guider_info(236): ....................................................
[dbg] guider_print_dev_guider_info(237):           ProductKey : 2UCRZpAbCGC
[dbg] guider_print_dev_guider_info(238):           DeviceName : ExampleDev
[dbg] guider_print_dev_guider_info(239):             DeviceID : 2UCRZpAbCGC.ExampleDev
[dbg] guider_print_dev_guider_info(240):         DeviceSecret : fbh47lGBSayncmTHEjF1E5x4CZdeJTO9
[dbg] guider_print_dev_guider_info(241): ....................................................
...
...
_demo_message_arrive|136 :: ----
_demo_message_arrive|140 :: Topic: '/2UCRZpAbCGC/ExampleDev/data' (Length: 28)
_demo_message_arrive|144 :: Payload: '{"attr_name":"temperature", "attr_value":"1"}' (Length: 45)
_demo_message_arrive|145 :: ----
[inf] iotx_mc_unsubscribe(1416): mqtt unsubscribe success,topic = /2UCRZpAbCGC/ExampleDev/data!
[dbg] iotx_mc_disconnect(2106): rc = MQTTDisconnect() = 0
[inf] _network_ssl_disconnect(413): ssl_disconnect
[inf] iotx_mc_disconnect(2114): mqtt disconnect!
[inf] iotx_mc_release(2160): mqtt release!

---------------------------------------------------
. bytes_total_allocated:    1292
. bytes_total_freed:        1292
. bytes_total_in_use:       0
. bytes_max_allocated:      560
. bytes_max_in_use:         1066
. iterations_allocated:     20
. iterations_freed:         20
. iterations_in_use:        0
. iterations_max_in_use:    11

---------------------------------------------------
main|441 :: out of sample!

观察消息上报

如下日志信息显示样例程序正在通过MQTTPublish类型消息, 上报业务数据到/${prodcutKey}/${deviceName}/data

mqtt_client|256 :: packet-id=3, publish topic msg={"attr_name":"temperature", "attr_value":"1"}

观察消息下推

如下日志信息显示该消息因为是到达已被订阅的Topic, 所以又被服务器原样推送到样例程序, 并进入相应的回调函数

_demo_message_arrive|136 :: ----
_demo_message_arrive|140 :: Topic: '/2UCRZpAbCGC/ExampleDev/data' (Length: 28)
_demo_message_arrive|144 :: Payload: '{"attr_name":"temperature", "attr_value":"1"}' (Length: 45)
_demo_message_arrive|145 :: ----

观察设备状态和设备日志

登录平台后,可以看到该设备的运行状态和设备日志。

image.png | center | 600x296

设备量产

测试设备完成功能调试,产品发布后,您可以批量添加设备,下载Excel格式的设备激活凭证,批量烧录到产线中,完成设备的量产和管理。

image.png | center | 600x294