IoT SDK
更新时间:2018-02-07 09:51:35
IoT SDK 快速开始
本节描述如何申请自己的设备, 并结合本SDK快速体验该设备通过MQTT
+TLS/SSL
协议连接到飞凤平台, 上报和接收业务报文。
实现原理:
MQTT协议
(Message Queuing Telemetry Transport
, 消息队列遥测传输)是IBM开发的一个即时通讯协议, 是为大量计算能力有限, 且工作在低带宽, 不可靠的网络的远程传感器和控制设备通讯而设计的协议
利用MQTT协议是一种基于二进制消息的发布/订阅编程模式的消息协议, 下面的应用程序先在飞凤平台订阅(Subscribe
)一个Topic
成功, 然后自己向该Topic
做发布(Publish
)动作
飞凤平台收到之后, 就会原样推送回这个应用程序, 因为该程序之前已经通过订阅(Subscribe
)动作成为该Topic
的一个接收者, 发布到这个Topic
上的任何消息, 都会被推送到已订阅该Topic
的所有终端上
开发环境准备
安装Ubuntu16.04
本SDK的编译环境是64位
的Ubuntu16.04
, 在其它Linux上尚未测试过, 所以推荐安装与飞凤平台开发者一致的发行版
如果您使用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
获取设备激活凭证
创建产品
点击页面左侧导航栏点击的设备按钮, 下拉菜单产品开发按钮, 再到页面右侧点新增产品。
添加测试设备
产品创建完成,点击进入产品详情页面的“设备开发”标签页,下载IoT SDK。
在下方的测试设备列表,点击“新增测试设备”,输入DeviceName添加一个测试设备,如果为空将由系统为您自动颁发一个DeviceName。
创建成功后将显示系统颁发的设备激活凭证:
productKey
: 标识设备所属的产品deviceName
: 标识产品下的具体设备deviceSecret
: 该设备的密钥, 需填写到SDK中, 用于连接飞凤服务器时完成认证
编译样例程序
解压缩 SDK
登录云平台,将下载到的压缩包在Linux上解压缩:
填入设备信息
编辑文件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!
观察消息上报
如下日志信息显示样例程序正在通过MQTT
的Publish
类型消息, 上报业务数据到/${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 :: ----
观察设备状态和设备日志
登录平台后,可以看到该设备的运行状态和设备日志。
设备量产
测试设备完成功能调试,产品发布后,您可以批量添加设备,下载Excel格式的设备激活凭证,批量烧录到产线中,完成设备的量产和管理。