从新大陆云平台下载C语言版本的SDK,目前提供Linux系统运行示例,
将代码放置Ubuntu中的/home目录下(或者其它),如下:
在main.c中修改云服务器IP和端口,如下:
#define SERVER_IP "121.37.241.174"
#define SERVER_PORT 8600
注意 : 请确保你的Ubuntu可以正常上公网
使用记录好的“设备标识”和“传输密钥”做为参数,
在main.c的post_process函数中,修改设备标识和传输密钥,组织TCP握手连接报文,发送到平台与之建立握手连接.
/* 根据协议定义连接请求的结构体 */
con_req.msg_type = PACKET_TYPE_CONN_REQ;
con_req.device_id = "qiuzhb";
con_req.key= "677abb3a5ff3456fb831c96482f11536";
con_req.ver = "V1.0";
/* 利用SDK 中cloud.h 中 packet_msg 方法封包连接协议 */
packet = packet_msg(&con_req);
/*发送连接协议包数据*/
ret = send_packet(sock, packet, strlen(packet), 0);
若握手连接成功,云端会发送响应成功信息,在设备管理中会看到一个在线标记:
若握手连接失败,云端也会发送响应失败信息,告诉失败原因。
利用SDK中提供的接口函数,编写代码将数据上报到平台。
以C语言SDK为例,上传一组温度为30℃,湿度为80%RH的数据。
//数据类型为1(JSON格式1字符串)
post_req.msg_type = PACKET_TYPE_POST_DATA;
post_req.msg_id++;
post_req.data_type = 1;
post_req.data = "{\
\"nl_temperature\": \"23\",\
\"nl_light\": 2000\
}";
post_req.data_len = strlen(post_req.data);
packet = packet_msg(&post_req);
if(packet == NULL){
MAIN_ERR("packet_msg JSON 1 error\n");
}else{
MAIN_DBG("POST JSON 1 \n");
send_flag = 1;
}
/*发送包数据,上报传感数据*/
if(send_flag){
ret = send_packet(sock, packet, strlen(packet), 0);
if(ret < 0){
MAIN_ERR("PACKET_TYPE_POST_DATA error\n");
}
free_packet_msg(packet);
send_flag = 0;
}
输入“make clean”清除旧的可执行文件 ,再输入“make”重新生成新的可执行文件如下:
输入“./main”,运行程序,可以看到程序会自动连接云平台,在线的图标点亮; 并向云平台上传了温度和光照传感器数据,如下:
点击风扇的开关按钮,进行下行控制,如下:
同时在Ubuntu中会终端上能看到如下输出,即成功收到的下行命令:
{
"t": 6,
"cmdid": 24061,
"apitag": "nl_fan",
"data": 1
}
JSON是轻量级的数据交换格式,二进制也是网络通信中广泛采用的一种数制,平台支持这两种格式的数据上报及命令下发,需要做下转换,基本原理是
在TCP协议或MQTT协议中,针对数据的上报或下发都是基于JSON格式的,想在JSON格式协议中再包含JSON对象或二进制数据,分别将他们转化为字符串来传输,大致如下:
以Ubuntu环境、C语言开发的网关做为设备接入端,C#开发的上位机应用为例,介绍JSON的传输。
1)、在云平台添加相应的项目、设备、传感器、执行器,传感器与执行器如下图所示:
2)、C语言上传JSON与二进制的关键代码
//////////////////////////////////////////////数据上报格式//////////////////////////////////////////////
{
"t": 3,
"datatype": 1,
"datas":
{
"jsonsensor": "{\"UserName\":\"李四\",\"Age\":23,\"Sex\":1,\"IsMarry\":false}", //JSON序列化为字符串
"binarysensor": "AQIDBAU=" //{ 0x01, 0x02, 0x03, 0x04, 0x05 }经过Base64编码的字符串
},
"msgid": 123
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
//发送数据到平台函数
int send_data_to_cloud(void)
{
char jsonData[] = "{\"UserName\":\"李四\",\"Age\":23,\"Sex\":1,\"IsMarry\":false}";
char binaryData[] = {0x02,0x04,0x06,0x08};
int binlength = 4;
int send_sock = tcpSend_fd_read();
send_json_data(send_sock, 1, jsonData);
sleep(5);
send_binary_data(send_sock, 2, binaryData, binlength);
sleep(5);
return 0;
}
//发送JSON数据函数
int send_json_data(int sock,int msgid,char *jsonData)
{
int ret;
char data[512] = {0};
sprintf(data, "{\"t\":3,\"datatype\":1,\"msgid\":%d,\"datas\":{\"jsonsensor\":%s}}", msgid, jsonData);
printf("/********************************** SEND JSON DATA **********************************/\r\n");
printf("%s\r\n",data);
printf("/********************************** ************** **********************************/\r\n\r\n");
ret = send_packet(sock, data, strlen(data), 0);
if(ret < 0){
CLIENT_SEND_ERR("send packet to cloud fail\r\n");
return -1;
}
return 0;
}
//发送二进制数据函数
int send_binary_data(int sock,int msgid,char *binaryData, int binlength)
{
int ret;
char data[512] = {0};
char base64[256] = {0};
ret = base64_encode(binaryData, base64, binlength);
if(ret == BASE64FAIL)
{
printf("binary to base64 faill\r\n");
return -1;
}
sprintf(data, "{\"t\":3,\"datatype\":1,\"msgid\":%d,\"datas\":{\"binarysensor\":\"%s\"}}", msgid, base64);
printf("/********************************* SEND Binary DATA *********************************/\r\n");
printf("%s\r\n",data);
printf("/********************************** ************** **********************************/\r\n\r\n");
ret = send_packet(sock, data, strlen(data), 0);
if(ret < 0){
CLIENT_SEND_ERR("send packet to cloud fail\r\n");
return -1;
}
return 0;
}
3)、云平台查询上传的数据记录
进入项目-》设备管理-》历史传感数据
4)、上位机应用获取数据关键代码
//调用批量查询设备最新数据
ResultMsg<IEnumerable<DeviceSensorDataDTO>> qry = SDK.GetDevicesDatas(Cfg.deviceId.ToString(), Token);
Console.WriteLine(lineNum + "、批量查询设备最新数据返回JSON:" + Environment.NewLine);
Console.WriteLine(SerializeToJson(qry) + Environment.NewLine);
lineNum++;
if (qry.IsSuccess())
{
var dev = qry.ResultObj.FirstOrDefault();
try
{
SensorDataDTO jsonSensor = dev.Datas.FirstOrDefault(item => { return item.ApiTag == Cfg.jsonApiTag; });
if (jsonSensor != null && jsonSensor.Value != null && jsonSensor.Value.ToString() != "")
{
//将设备传输的JSON字符串,使用JsonConvert转为对象
Member user = new Member();
user = JsonConvert.DeserializeObject<Member>(jsonSensor.Value.ToString());
Console.WriteLine(lineNum + "、JSON传感器值:" + Environment.NewLine);
Console.WriteLine(String.Format("{0}/{1}/{2}/{3}"
, user.UserName
, user.Age
, user.Sex
, user.IsMarry) + Environment.NewLine);
lineNum++;
}
SensorDataDTO binarySensor = dev.Datas.FirstOrDefault(item => { return item.ApiTag == Cfg.binaryApiTag; });
if (binarySensor != null && binarySensor.Value != null && binarySensor.Value.ToString() != "")
{
//将设备传输的Base64字符串,使用Base64解码为byte[]
Byte[] ary = Convert.FromBase64String(binarySensor.Value.ToString());
Console.WriteLine(lineNum + "、二进制传感器值:" + Environment.NewLine);
Console.WriteLine(String.Format("{0}/{1}/{2}/{3}"
, ary[0]
, ary[1]
, ary[2]
, ary[3]) + Environment.NewLine);
lineNum++;
}
}
catch { }
}
5)、上位机应用下发JSON与二进制关键代码
//发送“JSON格式”的命令
Member user = new Member() { UserName = "张三", Sex = 1, Age = Int32.Parse(CreateRandomNum(2)), IsMarry = false };
String json = JsonConvert.SerializeObject(user);
var qry = SDK.Cmds(Cfg.deviceId, Cfg.jsonActuator, json, Token);
Console.WriteLine(lineNum + "、发送JSON格式命令返回JSON:" + Environment.NewLine);
Console.WriteLine(SerializeToJson(qry) + Environment.NewLine);
lineNum++;
//发送“二进制格式”的命令
byte[] ary = new Byte[] { 0x10, 0x09, 0x08, 0x07, 0x06 };
String binary = Convert.ToBase64String(ary);
qry = SDK.Cmds(Cfg.deviceId, Cfg.binaryActuator, binary, Token);
Console.WriteLine(lineNum + "、发送二进制格式命令返回JSON:" + Environment.NewLine);
Console.WriteLine(SerializeToJson(qry) + Environment.NewLine);
lineNum++;
6)、设备端解析JSON与二进制命令关键代码
static void control_command_deal(void* msg_unpacket)
{
CMD_REQ* cmd_rcv = (CMD_REQ*)msg_unpacket;
int is_cmd_need_rsp = 0;
CMD_REQ_RSP* cmd_rsp = (CMD_REQ_RSP*)cmd_rcv; //CMD_REQ struct is same with CMD_REQ_RSP struct
CLIENT_RCV_DBG("recv CMD, data type:%d\n", cmd_rcv->data_type);
switch(cmd_rcv->data_type){
case CMD_DATA_TYPE_NUM:
is_cmd_need_rsp = 1;
CLIENT_RCV_DBG("1.unpacket, msg_type:%d, msg_id:%d apitag:%s, data:%d\n",
cmd_rcv->msg_type, cmd_rcv->cmd_id, cmd_rcv->api_tag, *((int*)cmd_rcv->data));
break;
case CMD_DATA_TYPE_DOUBLE:
is_cmd_need_rsp = 1;
CLIENT_RCV_DBG("2.unpacket, msg_type:%d, msg_id:%d apitag:%s, data:%f\n",
cmd_rcv->msg_type, cmd_rcv->cmd_id, cmd_rcv->api_tag, *((double*)cmd_rcv->data));
break;
case CMD_DATA_TYPE_STRING:
is_cmd_need_rsp = 1;
CLIENT_RCV_DBG("3.unpacket, msg_type:%d, msg_id:%d apitag:%s, data:%s\n",
cmd_rcv->msg_type, cmd_rcv->cmd_id, cmd_rcv->api_tag, (char*)cmd_rcv->data);
cJSON *msg_json = NULL;
msg_json = cJSON_Parse((char*)cmd_rcv->data);
if(msg_json != NULL)
{
if(msg_json->type == cJSON_Object){
cJSON *name_json = NULL;
cJSON *age_json = NULL;
name_json = cJSON_GetObjectItem(msg_json, "UserName");
if(name_json && name_json->type != cJSON_String){
CLIENT_RCV_ERR("name_json ->type(%d) error\n", name_json ->type);
return NULL;
}
age_json = cJSON_GetObjectItem(msg_json, "Age");
if(age_json && age_json->type != cJSON_Number){
CLIENT_RCV_ERR("age_json ->type(%d) error\n", age_json ->type);
return NULL;
}
printf("/================ RCV Str DATA ================/\r\n");
printf("msg_type:%d\r\n",cmd_rcv->msg_type);
printf("msg_id :%d\r\n",cmd_rcv->cmd_id);
printf("apitag :%s\r\n",cmd_rcv->api_tag);
printf("UserName:%s\r\n",name_json->valuestring);
printf("Age :%d\r\n",age_json->valueint);
printf("/================ ======== ================/\r\n\r\n");
}
}
else
{
printf("/================ RCV Bin DATA ================/\r\n");
uint8_t bindata[256] = {0};
int len = base64_decode((char*)cmd_rcv->data, bindata);
printf("msg_type:%d\r\n",cmd_rcv->msg_type);
printf("msg_id :%d\r\n",cmd_rcv->cmd_id);
printf("apitag :%s\r\n",cmd_rcv->api_tag);
printf("apitag :%s\r\n",cmd_rcv->data);
printf("changhex:");
print_hex(bindata,len);
printf("/================ ======== ================/\r\n\r\n");
}
CLIENT_RCV_DBG("3.unpacket, msg_type:%d, msg_id:%d apitag:%s, data:%s\n",
cmd_rcv->msg_type, cmd_rcv->cmd_id, cmd_rcv->api_tag, (char*)cmd_rcv->data);
break;
case CMD_DATA_TYPE_JSON:
is_cmd_need_rsp = 1;
CLIENT_RCV_DBG("4.unpacket, msg_type:%d, msg_id:%d apitag:%s, data:%s\n",
cmd_rcv->msg_type, cmd_rcv->cmd_id, cmd_rcv->api_tag, (char*)cmd_rcv->data);
break;
default:
CLIENT_RCV_ERR("data_type(%d) error\n", cmd_rcv->data_type);
}
if(is_cmd_need_rsp){
if(gataways_send_answer_to_cloud(cmd_rsp) == -1){
CLIENT_RCV_ERR("gataways_send_answer_to_cloud fail");
}
}
}
7)、案例源代码下载
点击下载