中国电信天翼物联网平台CTWing学习笔记(1)——设备接入(TCP协议)
一、平台简介
天翼物联网平台(AIoT) 是中国电信倾力打造的智能终端汇聚、应用开发运行服务和轻量级应用提供的物联网平台,旨在降低物联网应用开发的准入门槛,降低智能硬件的接入门槛,提供端到端的解决方案,服务于终端开发商、个人极客开发者、能力提供商、应用开发商以及集团内部各生态圈。
官网主页:https://www.ctwing.cn/
帮助中心:https://www.ctwing.cn/czlks/11#see
平台架构:
二、Demo体验与SDK下载
2.1 创建产品及设备
产品信息如下:
安全类型:
- 一机一密:每个设备都有一个不同的特征串
- 一型一密:同款产品下每个设备都使用同一个特征串
添加设备如下:
2.2 SDK下载及修改
SDK下载:
https://www.ctwing.cn/sbjr/72#/callback
从平台获取接入 IP 和端口,设备 ID,认证信息:
然后根据实际获取到的设备 ID,特征串修改 ctiot_tcp_sdk\sample\demo\demo.c
中 ctiot_test_init()
的设备 ID和特征串。
ctiot_status ctiot_test_init()
{char* ip = "180.106.148.146";int port = 8996;char* deviceId = "1517035889860492192091928466";char* passWord = "AqUFr6ntTFDFZUvAO1jELbIz8h3v6yHzH7hEBsKNxrY";char* verSion = "1.0";int certmode = 0;printf("server IP: %s\nserver Port: %d\ndeviceid: %s\npassword: %s\nversion:%s\ncertMode: %d\n",ip, port, deviceId, passWord, verSion, certmode);ctiot_init(&c, ip, port, deviceId, passWord, verSion, certmode);
}
2.3 SDK编译及运行程序对接平台测试
将修改完的 SDK 工程文件夹 ctiot_tcp_sdk 放入 Linux
运行环境中 ,进入 ctiot_tcp_sdk/sample/demo
目录,执行 make
命令,系统自动编译生成可执行文件,运行程序 tcp_client
2.3.1 设备登录
输入'l'
或 'L'
登录:
平台查看终端已在线:
注:若60秒内同一ip建链、断链次数超过30次,将停止该ip连接2小时。
2.3.2 数据上报
输入's'
或 'S'
进行数据上报:
在平台进行数据查看,可看到数据已上报:
可看到上报的两条数据:
对于透传产品,平台对上报的业务数据进行 Base64编码
处理,进行解码后:
2.3.3 指令下发
平台执行指令下发(对于透传产品,平台对下行指令做透传处理,支持字符串和十六进制两种数据类型):
平台可查看指令下发日志,可看到下发已成功:
终端查看指令下发成功:
三、TCP协议接口介绍
帮助文档:https://www.ctwing.cn/sbjr/67#see
3.1 接口地址
通信协议 | 地址 | 端口 | 说明 |
---|---|---|---|
TCP | tcp.ctwing.cn | 8996 |
TCP非加密接口 支持ipv4和ipv6接入 |
3.2 消息格式
应用层数据报文以1个字节的类型字段作为分割,平台支持登录、心跳、上下行业务数据等消息类型。消息携带的参数必须包含两个字节的参数长度。
根据数据报文内容分为:
- 透传设备(对于透传产品,平台对上报的业务数据进行
Base64编码
处理,可以在产品的数据查看页面查看上报的数据内容,也可以通过订阅推送的方式,北向应用订阅设备数据变化通知,平台将上报的数据推送给北向应用。)
消息类型 | 类型描述 | 消息格式 | 备注 |
---|---|---|---|
0x01 | 登录请求 | 0x01 +deviceId_length(2字节) +deviceId +password_length(2字节) +password +version_length(2字节) +version | deviceId是由产品ID和设备编号拼接而成的字符串; password由平台生成,在设备管理业务可以查看; version固定1.0 |
0x02 | 上行数据报文 | 0x02 +数据长度(2字节) +业务数据 | |
0x03 | 下行数据报文 | 0x03 +数据长度(2字节) +业务数据 | |
0x04 | 心跳 | 0x04 | 平台心跳周期为5分钟,设备需在5分钟内发送心跳报文 |
0x05 | 登录响应 | 0x05+结果码(2字节) | 登录结果: 0 成功 1 未知错误 2 设备未注册 3 设备认证失败 4 设备已登录 |
0x06 | 心跳响应 | 0x06 | 平台回复终端心跳的响应 |
- 非透传设备(对于非透传产品,平台
根据物模型对上报的业务数据进行解析
,可以在产品的数据查看页面查看上报的数据内容,也可以通过订阅推送的方式,北向应用订阅设备数据变化通知,平台将上报的数据推送给北向应用。)
消息类型 | 类型描述 | 消息格式 | 备注 |
---|---|---|---|
0x01 | 登录请求 | 0x01 +deviceId_length(2字节) +deviceId +password_length(2字节) +password +version_length(2字节) +version | deviceId是由产品ID和设备编号拼接而成的字符串; password由平台生成,在设备管理业务可以查看; version固定1.1 业务数据非透传格式遵循物模型,上下行业务数据需要响应。 |
0x02 | 上行数据报文 | 0x02+数据长度(2字节)+msgid(2字节)+serviceid(2字节)+param1+params2+param3+…… | 数据长度:从msgid开始,到报文结尾的长度;msgid:报文标识,由终端分配;serviceId:平台分配的服务ID;param:平台服务包含的属性 |
0x82 | 上行数据报文 | 0x82+数据长度(2字节)+msgid(2字节)+结果码(2字节) | 数据长度:从msgid开始,到报文结尾的长度;msgid:报文标识,跟上行报文中msgid对应;结果码:0-成功、1-报文解析失败 |
0x03 | 下行数据报文 | 0x03+数据长度(2字节)+msgid(2字节)+serviceId(2字节)+param1+param2+param3+…… | 数据长度:从msgid开始,到报文结尾的长度;msgid:报文标识,由平台分配;serviceId:平台分配的服务ID;param:平台服务包含的属性(参数)注:msgid字段即为指令的taskId |
0x83 | 下行数据响应 | 0x83+数据长度(2字节)+msgid(2字节)+结果码(2字节)+serviceId(2字节)+param1+param2+param3+…… | 数据长度:从msgid开始,到报文结尾的长度;msgid:报文标识,对应下行指令中的msgid;结果码:0-成功,不带serviceId和参数;1-成功,带serviceId和参数;2-下行数据处理失败,不带serviceId和参数 |
0x04 | 心跳 | 0x04 | 平台心跳周期为5分钟,设备需在5分钟内发送心跳报文 |
0x05 | 登录响应 | 0x05+结果码(2字节) | 登录结果: 0 成功 1 未知错误 2 设备未注册 3 设备认证失败 4 设备已登录 |
0x06 | 心跳响应 | 0x06 | 平台回复终端心跳的响应 |
3.3 业务数据交互流程
3.3.1 设备登录
设备登录需要携带 deviceId
、password
、version
字段,AEP对设备进行认证,认证通过 0x05
消息类型返回成功的响应(响应码为:0),认证失败将失败原因通过响应码带给设备。
- 透传设备
deviceId:10013378001
password:7Sfv-b_HDbLDyJ_K-0SkWqRGd-GE-b3rZp-upOr1kSU
version:1.0
登录请求编码为(16进制):
• 登录报文标识符:0x01
• deviceId_length:0x000b
• deviceId:0x3130303133333738303031
• password_length:0x002b
• password:0x375366762d625f4844624c44794a5f4b2d30536b57715247642d47452d6233725a702d75704f72316b5355
• version_length:0x0003
• version:0x312e30
登录请求的完整报文为:01000b 3130303133333738303031 002b 375366762d625f4844624c44794a5f4b2d30536b57715247642d47452d6233725a702d75704f72316b5355 0003 312e30
- 非透传设备
deviceId:10013378001
password:7Sfv-b_HDbLDyJ_K-0SkWqRGd-GE-b3rZp-upOr1kSU
version:1.1
登录请求编码为(16进制):
• 登录报文标识符:0x01
• deviceId_length:0x000b
• deviceId:0x 3130303133333738303031
• password_length:0x002b
• password:0x375366762d625f4844624c44794a5f4b2d30536b57715247642d47452d6233725a702d75704f72316b5355
• version_length:0x0003
• version:0x312e31
登录请求的完整报文为:01 000b 3130303133333738303031 002b 375366762d625f4844624c44794a5f4b2d30536b57715247642d47452d6233725a702d75704f72316b5355 0003 312e31
3.3.2 上行数据
设备以 0x02
消息类型上报数据,非透传设备平台解析后会以 0x82
回复响应结果。
- 透传设备
业务数据:“hello”
上行数据编码为(16进制):
• 上行报文标识符:0x02
• payload_length:0x0005
• payload:0x68656c6c6f
上行数据报文完整报文为:02 0005 68656c6c6f
- 非透传设备
物模型如下:
服务类型 | 服务标识 | 服务ID | 属性顺序 | 属性标识符 | 属性类型 | 属性长度 |
---|---|---|---|---|---|---|
数据上报 | up | 1 | 1 | data0 | 无符号整型 | 2 |
2 | data1 | 定长字符串 | 5 | |||
3 | data2 | 变长字符串 | / |
服务类型、服务标识、服务ID所在位置:
属性顺序、属性标识符、属性类型所在位置:
上行数据编码为(16进制):
• 上行报文标识符:0x02
• payload_length:0x0012
• msgId: 0x0001
• serviced: 0x0001
• payload:– data0:0x0064(100)– data1:0x68656C6C6F(hello)– data2:0x0005 776F726C64(world)[包含两个字节的长度0005]
上行数据完整报文为:02 0012 0001 0001 0064 68656C6C6F 0005776F726C64
上行数据响应报文编码为:
• 上行响应标识符:0x82
• payload_length:0x0004
• msgId: 0x0001
• 结果码: 0x0000
上行数据响应报文为:82 0004 0001 0000
3.3.3 下行数据
平台以 0x03
消息类型下发指令,非透传设备需以 0x83
回复指令执行结果。
注意:tcp透传没有指令缓存机制,若设备离线指令直接丢弃,不会下发,非透传有缓存机制,收到指令后若不进行回复,在指令ttl有效期内如果设备重新上线,指令会重新下发。
- 透传设备
业务数据:“turn off”
下行数据编码为(16进制):
• 下行报文标识符:0x03
• payload_length:0x0008
• payload:0x7475726e206f6666
下行数据完整报文为:03 0008 7475726e206f6666
- 非透传设备
物模型如下:
服务类型 | 服务标识 | 服务ID | 参数顺序 | 参数标识符 | 参数类型 | 参数长度 |
---|---|---|---|---|---|---|
指令下发 | dn | 8001 | 1 | cmd | 定长字符串 | 5 |
指令下发响应 | rsp | 9001 | 1 | time | 定长字符串 | 5 |
下行指令编码为(16进制):
• 下行报文标识符:0x03
• payload_length:0x0009
• msgId: 0x0001
• serviced: 0x1f41
• payload:– cmd:0x68656C6C6F(hello)
下行指令完整报文为:03 0009 0001 1f41 68656c6c6f
msgid为1,需要在响应中带回
指令响应编码为:
• 下行响应标识符:0x83
• payload_length:0x000b
• msgId: 0x0001
• 结果码: 0x0001
• serviced: 0x2329
• payload:– cmd:0x776F726C64 (world)
下行指令响应的完整包文为:83 000b 0001 0001 2329 776F726C64
3.3.4 心跳
设备需要周期性(5分钟以内
)发送心跳报文来保持业务层会话。
心跳编码为(16进制):
• 心跳标识符:0x04
心跳的完整包文为:04
四、自定义接口函数
由于原来SDK是Linux平台的程序,为了更适用于嵌入式终端程序,这里我修改成几个接口函数。
4.1 ctiot_tcp.c
/********************************************************************** INCLUDES*/
#include <stdio.h>
#include <string.h>#include "ctiot_tcp.h"static ctiot_status ctiot_varify_parameters(uint8_t *deviceId, uint8_t *password, uint8_t *version);/********************************************************************** PUBLIC FUNCTIONS*/
/**@brief 初始化终端信息@param clientInfo -[out] 终端信息@param deviceId -[in] 设备ID@param password -[in] 特征串@param version -[in] 版本@return 无
*/
ctiot_status CTIOT_Init(clientinfo_t *clientInfo, uint8_t *deviceId, uint8_t *password, uint8_t *version)
{if(CTIOT_ERROR == ctiot_varify_parameters(deviceId, password, version)){return CTIOT_ERROR;}clientInfo->deviceIdLen = strlen(deviceId);clientInfo->deviceId = strdup(deviceId);clientInfo->passwordLen = strlen(password);clientInfo->password = strdup(password);clientInfo->versionLen = strlen(version);clientInfo->version = strdup(version);return CTIOT_SUCCESS;
}/**@brief 登录CTWing平台@param pMsg -[out] 消息@param pMsgLen -[out] 消息长度@param pDeviceId -[in] 设备ID@return 无
*/
void CTIOT_Login(clientinfo_t *context)
{uint8_t *pMsg = NULL;uint16_t msgLen = 0;if(CTIOT_SUCCESS != CTIOT_Encode_Login_Para(&pMsg, &msgLen, context)){iopen_debug_print("Login encode failed!\n");}Socket_SendBytes(pMsg, msgLen);free(pMsg);pMsg = NULL;
}/**@brief 下行数据报文处理@param pMsg -[in&out] 消息@param pMsgLen -[in&out] 消息长度@return 无
*/
void CTIOT_Command_MsgHandler(char *pMsg, uint32_t *pMsgLen)
{uint8_t msgType = 0;uint8_t payloadLength[2] = {0};uint8_t msgId[2] = {0};uint8_t serviced[2] = {0};msgType = pMsg[0];memcpy(payloadLength, pMsg + 1, 2);memcpy(msgId, pMsg + 1+2, 2);memcpy(serviced, pMsg + 1+2+2, 2);switch(msgType){case DOWNSTREAM_MESSAGE: // 下行数据报文标识符for(int i = 0; i < *pMsgLen; i++){print("socket msg:%02x\n", pMsg[i]);}CTIOT_Command_Response(msgId);break;case LOGIN_ACK: // 注册ACK报文标识符if(pMsg[2] != CTIOT_LOGIN_FAILED || pMsg[2] != CTIOT_DEVICE_AUTH_FAILED){// 登录成功}break;case HEARTBEAT_ACK: // 心跳ACK报文标识符// 心跳成功break;default:break;}
}/**@brief 封装登录请求@param ptrStream -[out] 请求消息@param ptrLen -[out] 请求消息长度@param data -[in] 需要上传的数据@param dataLen -[in] 需要上传的数据长度@return 状态码
*/
ctiot_status CTIOT_Encode_Login_Para(uint8_t **ptrStream, uint16_t *ptrLen, clientinfo_t *context)
{ctiot_status ret = CTIOT_SUCCESS;*ptrLen = 0;*ptrLen = 7 + context->deviceIdLen + context->passwordLen + context->versionLen;uint32_t i = 0,j = 0;*ptrStream = (uint8_t *)malloc(*ptrLen);if(ptrStream == NULL){ret = CTIOT_ERROR;goto exit;}//message type(*ptrStream)[0] = LOGIN_MESSAGE;i++;//deviceId(*ptrStream)[i++] = (context->deviceIdLen)>>8;(*ptrStream)[i++] = (context->deviceIdLen)>>0;for(j = 0; j < context->deviceIdLen; j++){(*ptrStream)[i++] = (context->deviceId[j]);}//password(*ptrStream)[i++] = (context->passwordLen)>>8;(*ptrStream)[i++] = (context->passwordLen)>>0;for(j = 0; j < context->passwordLen; j++){(*ptrStream)[i++] = (context->password[j]);}//version(*ptrStream)[i++] = (context->versionLen)>>8;(*ptrStream)[i++] = (context->versionLen)>>0;for(j = 0; j < context->versionLen; j++){(*ptrStream)[i++] = (context->version[j]);}if(*ptrLen != i){ret = CTIOT_ERROR;iopen_debug_print("*ptrLen error\n");goto exit;}exit:return ret;
}/**@brief 封装上行数据报文@param ptrStream -[out] 上报消息@param ptrLen -[out] 上报消息长度@param data -[in] 需要上传的数据@param dataLen -[in] 需要上传的数据长度@return 状态码
*/
ctiot_status CTIOT_Encode_Updata_Para(uint8_t **ptrStream, uint16_t *ptrLen, uint8_t *data, uint16_t dataLen)
{ctiot_status ret = CTIOT_SUCCESS;*ptrLen = 0;*ptrLen = 3 + dataLen;uint32_t i = 0,j = 0;*ptrStream = (uint8_t *)malloc(*ptrLen);if(ptrStream == NULL){ret = CTIOT_ERROR;goto exit;}//message type(*ptrStream)[0] = UPSTREAM_MESSAGE;i++;//upstream data(*ptrStream)[i++] = dataLen>>8;(*ptrStream)[i++] = dataLen>>0;for(j = 0; j < dataLen; j++){(*ptrStream)[i++] = (data[j]);}if(*ptrLen != i){ret = CTIOT_ERROR;iopen_debug_print("*ptrLen error\n");goto exit;}exit:return ret;
}/**@brief 封装下行数据响应@param ptrStream -[out] 指令响应消息@param ptrLen -[out] 指令响应消息长度@param data -[in] 需要上传的数据@param dataLen -[in] 需要上传的数据长度@return 状态码
*/
ctiot_status CTIOT_Encode_Command_Response_Para(uint8_t **ptrStream, uint16_t *ptrLen, uint8_t *data, uint16_t dataLen)
{ctiot_status ret = CTIOT_SUCCESS;*ptrLen = 0;*ptrLen = 3 + dataLen;uint32_t i = 0,j = 0;*ptrStream = (uint8_t *)malloc(*ptrLen);if(ptrStream == NULL){ret = CTIOT_ERROR;goto exit;}//message type(*ptrStream)[0] = DOWNSTREAM_MESSAGE_ACK;i++;//upstream data(*ptrStream)[i++] = dataLen>>8;(*ptrStream)[i++] = dataLen>>0;for(j = 0; j < dataLen; j++){(*ptrStream)[i++] = (data[j]);}if(*ptrLen != i){ret = CTIOT_ERROR;iopen_debug_print("*ptrLen error\n");goto exit;}exit:return ret;
}/**@brief 保持心跳@param 无@return 无
*/
void CTIOT_Keep_Alive(void)
{uint8_t ping[1] = {PING_MESSAGE};Socket_SendBytes(ping, sizeof(ping)); // 改成自己的socket发送函数
}/**@brief 指令响应@param pMsgId -[in] 消息ID@return 无
*/
void CTIOT_Command_Response(uint8_t *pMsgId)
{uint8_t *pMsg = NULL;uint16_t msgLen = 0;// msgid resultuint8_t data[4] = {0x00, 0x01, 0x00, 0x00};memcpy(data, pMsgId, 2);CTIOT_Encode_Command_Response_Para(&pMsg, &msgLen, data, sizeof(data));Socket_SendBytes(pMsg, msgLen);free(pMsg);pMsg = NULL;
}/********************************************************************** LOCAL FUNCTIONS*/
/**@brief 校验参数@param deviceId -[in] 设备ID@param password -[in] 特征串@param version -[in] 版本@return 状态码
*/
static ctiot_status ctiot_varify_parameters(uint8_t *deviceId, uint8_t *password, uint8_t *version)
{ctiot_status ret = CTIOT_SUCCESS;if(deviceId == NULL || password == NULL || version == NULL){ret = CTIOT_ERROR;iopen_debug_print("Init paramter error!\n");}return ret;
}/****************************************************END OF FILE****************************************************/
4.2 ctiot_tcp.h
注意:请修改以下地方
PRODUCT_ID
、PASSWORD
、VERSION
,CTIOT_Keep_Alive()
中的socket发送函数,CTIOT_Command_Msghandler()
中进行数据接收处理。
#ifndef _CTIOT_TCP_H_
#define _CTIOT_TCP_H_/********************************************************************** INCLUDES*//********************************************************************** DEFINITIONS*/
#define PRODUCT_ID "10005081" // 产品ID,根据实际修改
#define PASSWORD "WbYvOBP6Zx73gy1o7pqviKkK8EDYFNjsDNJA1I34_oo" // 特征串,根据实际修改
#define VERSION "1.1" // 协议版本,透传设备改成1.0,非透传设备为1.1#define PRODUCT_ID_LEN 8 // 产品ID长度
#define ICCID_LEN 20 // 设备编号长度/********************************************************************** TYPEDEFS*/
typedef enum
{LOGIN_MESSAGE = 0x01, //!<注册报文标识符UPSTREAM_MESSAGE = 0x02, //!<上行数据报文标识符DOWNSTREAM_MESSAGE = 0x03, //!<下行数据报文标识符PING_MESSAGE = 0x04, //!<心跳报文标识符LOGIN_ACK = 0x05, //!<注册ACK报文标识符HEARTBEAT_ACK = 0x06, //!<心跳ACK报文标识符UPSTREAM_MESSAGE_ACK = 0x82, //!<上行数据ACK报文标识符DOWNSTREAM_MESSAGE_ACK = 0x83, //!<下行数据ACK报文标识符
} message_type_e;typedef struct client
{uint16_t deviceIdLen; //!<deviceid长度uint8_t *deviceId; //!<deviceiduint16_t passwordLen; //!<password长度uint8_t *password; //!<passworduint16_t versionLen; //!<version长度uint8_t *version; //!<version
} clientinfo_t;typedef enum
{CTIOT_ERROR = -1, //!<错误CTIOT_SUCCESS = 0, //!<成功CTIOT_LOGIN_FAILED = 1, //!<登录未知错误CTIOT_DEVICE_UNREGISTERED = 2, //!<设备未注册CTIOT_DEVICE_AUTH_FAILED = 3, //!<设备认证失败CTIOT_DEVICE_HAVE_LOGINED = 4, //!<设备已登录CTIOT_READ_PACKET_NONE = 999, //!<未读取到数据
} ctiot_status;/********************************************************************** API FUNCTIONS*/
void CTIOT_Command_Msghandler(char *pMsg, uint32_t *pMsgLen);
ctiot_status CTIOT_Init(clientinfo_t *clientInfo, uint8_t *deviceId, uint8_t *password, uint8_t *version);
ctiot_status CTIOT_Encode_Login_Para(uint8_t **ptrStream, uint16_t *ptrLen, clientinfo_t *context);
ctiot_status CTIOT_Encode_Updata_Para(uint8_t **ptrStream, uint16_t *ptrLen, uint8_t *data, uint16_t dataLen);
ctiot_status CTIOT_Encode_Command_Response_Para(uint8_t **ptrStream, uint16_t *ptrLen, uint8_t *data, uint16_t dataLen);
void CTIOT_Login(clientinfo_t *context);
void CTIOT_Keep_Alive(void);
void CTIOT_Command_Response(uint8_t *pMsgId);#endif /* _CTIOT_TCP_H_ */
4.3 使用方法
- 初始化终端信息
在这里设备ID我采取的是产品ID+iccid的形式,实际应用中把你的设备编号替换iccid的内容。
#include "ctiot_tcp.h"static clientinfo_t s_clientInfo = {0};char iccidString[21] = {0};
GetIccid(iccidString);
char deviceId[PRODUCT_ID_LEN + ICCID_LEN + 1] = {0};
sprintf(deviceId, "%s%s", PRODUCT_ID, iccidString);
char *pPassword = PASSWORD;
char *pVersion = VERSION;CTIOT_Init(&s_clientInfo, deviceId, pPassword, pVersion);
- 登录
CTIOT_Login(&s_clientInfo);
- 数据上报
- msgid:0x00 0x01 可变可不变,按实际需求
- serviced:0x00 0x03 即服务ID为3,按实际情况修改
- data:0x01 这里为无符号整型1字节的属性,按实际情况修改
- Socket_SendBytes():修改成你字节的socket发送函数
uint8_t *pMsg = NULL;
uint16_t msgLen = 0;
// msgid serviced data
uint8_t data[5] = {0x00, 0x01, 0x00, 0x03, 0x01};
CTIOT_Encode_Updata_Para(&pMsg, &msgLen, data, sizeof(data));
Socket_SendBytes(pMsg, msgLen);
free(pMsg);
pMsg = NULL;
- 心跳
设备需要周期性(5分钟以内)发送心跳报文来保持业务层会话。
CTIOT_Keep_Alive();
- 指令下发、登录响应、心跳响应
注意:tcp透传没有指令缓存机制,若设备离线指令直接丢弃,不会下发,非透传有缓存机制,收到指令后若不进行回复,在指令ttl有效期内如果设备重新上线,指令会重新下发。
int recvDataLen = Socket_Receive(recvDataBuf); // 接收服务器数据
if(recvDataLen > 0)
{CTIOT_Command_MsgHandler(recvDataBuf, &recvDataLen);
}
- 指令响应
void CTIOT_Command_MsgHandler(char *pMsg, uint32_t *pMsgLen)
{uint8_t msgType = 0;uint8_t payloadLength[2] = {0};uint8_t msgId[2] = {0};uint8_t serviced[2] = {0};msgType = pMsg[0];memcpy(payloadLength, pMsg + 1, 2);memcpy(msgId, pMsg + 1+2, 2);memcpy(serviced, pMsg + 1+2+2, 2);switch(msgType){case DOWNSTREAM_MESSAGE: // 下行数据报文标识符CTIOT_Command_Response(msgId); // 指令响应break;······default:break;
}
• 由 Leung 写于 2022 年 3 月 30 日
• 参考:电信平台对接CTWing具体实现流程
中国电信天翼物联网平台CTWing学习笔记(1)——设备接入(TCP协议)相关推荐
- Springboot+Netty实现基于天翼物联网平台CTWing(AIOT)终端TCP协议(透传模式)-设备终端(南向设备)
电信的天翼物联网平台CTWing(AIOT)原先是我们俗称的aep,主要用于接入nb-iot设备,当然也可以接入其他的设备,在熟悉AIOT平台后,做后端的我有时候急需终端样品(智能门禁,支付识别终端, ...
- Springboot+Netty实现基于天翼物联网平台CTWing(AIOT)终端TCP协议(透传模式)-应用订阅端(北向应用)
之前实现了使用Springboot+Netty基于天翼物联网平台CTWing(AIOT)终端TCP协议(透传模式)-设备终端(南向设备),模拟设备发送的数据给到了AIOT平台,那么在第三方应用也需要去 ...
- 关于NB-IOT模块链接阿里物联网平台的学习笔记-记录
关于NB-IOT模块链接阿里物联网平台思路的学习笔记-记录 叙述 调试思路总结 调试过程 AT命令-方式一 AT命令-方式二 AT命令-方式三 软件 关于遇到问题 总结 叙述 前一段是写了一篇&quo ...
- 中国移动物联网开放平台OneNET学习笔记(1)——设备接入(MQTT协议)OneNET Studio篇
一.平台简介 中国移动物联网开放平台(OneNET) 是中移物联网有限公司基于物联网技术和产业特点打造的开放平台和生态环境,适配各种网络环境和协议类型,支持各类传感器和智能硬件的快速接入和大数据服务, ...
- 阿里云HaaS100物联网开发板学习笔记(四)轻应用初步--用javascript连接阿里云物联网平台
摘要:本篇文章讲解如何使用JavaScript"轻应用"连接阿里云物联网平台并上报一个数据.仍然延续前几篇文章的结构,从安装软件环境开始讲,以使零基础的同学看了本篇文章之后,也能够 ...
- NB-IOT电信云北向开发,电信天翼物联网平台对接应用服务
创建账号 中国电信天翼物联网CTWing门户网站 注册好之后在个人中心进行认证,否则无法进行设备相关的操作 进入控制台 认证通过后的账号,左侧菜单比较丰富,因此可以对产品设备操作了 输入验证码 点击开 ...
- 一文读懂天翼物联网平台(AIoT)
中国电信天翼智能物联网开放平台(简称"天翼物联网平台AIoT"),是中国电信融合5G.物.云.网.AI等数字要素,打造的泛在智联.全域感知.万物赋智.安全可信.互联互通.虚实共生的 ...
- 阿里云HaaS100物联网开发板学习笔记(六)做个智能灯---一个完整的开发例子
摘要:本篇文章将前期几个专题综合起来,基于阿里云HaaS100的新固件设计制作一个智能灯.这个智能灯由云平台.手机APP端和设备端组成,基本上涵盖了一个物联网小项目所需的主要步骤. 目录 1.在阿里云 ...
- “物联网开发实战”学习笔记-(四)智能音箱制作和语音控制
"物联网开发实战"学习笔记-(四)智能音箱制作和语音控制 这次来造一个属于自己的智能音箱,这里详细介绍了智能音箱的语音控制的实现. 智能音箱的技术架构 智能音箱主要涉及拾音.前端信 ...
- “物联网开发实战”学习笔记-(二)手机控制智能电灯
"物联网开发实战"学习笔记-(二)手机控制智能电灯 如果搭建好硬件平台后,这一次我们的任务主要是调试好智能电灯,并且连接到腾讯云的物联网平台. 腾讯云物联网平台 腾讯物联网平台的优 ...
最新文章
- CSP认证201712-1	最小差值[C++题解]:遍历
- HBase基本操作命令整理
- c语言中的jsonpath的处理
- php中$stu_by,PHP基础案例二:计算学生年龄
- (Deep learning)深度卷积网络实战——第三部分
- 同行压力(兼谈敏捷团队,绩效管理,自组织团队)
- 健康生活--16个健康习惯
- 全国计算机b类一级考试试题题库,全国计算机等级考试模拟题:一级B试题(一)...
- varchar和varchar2之间的区别
- 2021年电工(初级)考试及电工(初级)考试题
- 软件测试VS软件开发 IT行业两大高薪岗位全方位对比 看完就知道选谁了
- 深圳计算机职称叫什么,深圳职称是什么
- 计算机科学导论实验报告,上海电力学院计算机导论实验报告.docx
- 微信网页授权及使用微信jssdk
- 文件存储php源码,FFS5-Mini v120731 最终版 php网络文件存储分享系统
- 行人检测/人体检测综述
- 全网最新-扶风视频解析计费系统,2022优化免授权版(赠接口轮询插件)
- 2018CVPR_Future Frame Prediction for Anomaly Detection – A New Baseline
- TIA博途中如何使用符号方式按位,字节,字访问非结构数据类型
- FILE NAME(filename)文件名的理解
热门文章
- Unity - 撸一个简单版本的 四叉树 + 视锥cascaded,用于场景剔除
- 空间索引之网格与四叉树
- 硬件算法与软件算法实现区别通俗易懂
- 头脑王者答题神器,开发思路
- java 打印 日历 详细 注解_Java实现按年月打印日历功能【基于Calendar】
- 通俗易懂的UART协议帧格式
- 《个人信息安全规范 (2019-6-21) 》征求意见稿的最新变化
- 微信小程序tabBar不显示问题
- vue数据双向绑定,Android-MVP模式详解,附超全教程文档
- 怎么看xp计算机是32位还是64位,教你查看XP系统的不同32位还是64位详细的步骤