MQTT_OneJson方式接入Onenet云平台(基于SDK)
注册OneNet云平台账号
根据引导注册账号即可
创建产品
官网主页进入开发者中心
点击产品开发,创建产品
产品品类选择其他,智能化方式选择设备接入
接入协议选择MQTT,数据协议选择OneJson
添加物模型(属性点)
物模型简单理解为要上传的数据
- 创建好产品后,点击产品开发
-
点击设置物模型
-
点击添加自定义功能点
- 根据需求填写参数(以下以湿度为例)
- 添加完后记得保存
获取SDK
点击设备开发,基于SDK开发获取自动生成SDK
点击功能接口SDK获取,即可下载到SDK
点击设备端开发指南,有官方的文档对SDK作简单说明
SDK中使用4G模块连接Onenet
硬件准备
4G免驱网卡(ML307R)
带Linux系统设备(香橙派)
简要说明
在SDK ./examples/things_model/main.c文件中, 使用tm_login()
接口登录到Onenet服务器
/** Device Initialization*/
ret = tm_init(&dl_tbl); // 初始化物模型参数 顺带初始化mqtt的一些参数 成功返回0
CHECK_EXPR_GOTO(ERR_OK != ret, _END, "ThingModel init failed!\n");
logi("ThingModel init ok");
/** Device Login*/
ret = tm_login(product_id, device_sn, auth_code, TM_EXPIRE_TIME, timeout_ms); // 连接到服务器
CHECK_EXPR_GOTO(ERR_OK != ret, _END, "ThingModel login failed!");
logi("ThingModel login ok");
在tm_login()
中调用tm_mqtt_login()
使用mqtt协议进行登录
ret = tm_mqtt_login(product_id, dev_name, dev_token, timeout_ms); // 使用mqtt进行登录
在tm_mqtt_login()
则调用mqtt_connect()
接口
g_mqtt_obj->client = mqtt_connect((const uint8_t *)g_server_ip, port, g_tm_cert, osl_strlen(g_tm_cert),&(g_mqtt_obj->mqtt_param), countdown_left(cd_hdl));
在mqtt_connect()
中调用plat_tcp_connect()
接口
net_cb->handle = plat_tcp_connect(remote_addr, remote_port, countdown_left(cd_hdl));
在plat_tcp_connect()
接口中则创建TCP套接字,并与Onenet服务器进行连接
handle_t plat_tcp_connect(const uint8_t *host, uint16_t port, uint32_t timeout_ms)
{
handle_t fd = -1;
struct sockaddr_in addr_in;
struct sockaddr_in my_addr; // 绑定的地址
struct hostent *ip_addr;
int32_t flags = -1;
int ret = -1;
if(0 == (ip_addr = gethostbyname(host))) // 域名解析
{
goto exit;
}
addr_in.sin_family = AF_INET;
addr_in.sin_addr = *((struct in_addr *)ip_addr->h_addr_list[0]);
addr_in.sin_port = htons(port);
if(0 > (fd = socket(AF_INET, SOCK_STREAM, 0))) // 创建TCP套接字
{
goto exit;
}
if((0 > (flags = fcntl(fd, F_GETFL, 0))) || (0 > fcntl(fd, F_SETFL, flags | O_NONBLOCK)))
{
goto close_socket;
}
if(0 > (ret = connect(fd, (struct sockaddr *)&addr_in, sizeof(addr_in))))
{
if(EINPROGRESS != errno)
{
goto close_socket;
}
}
if(check_connect(fd, timeout_ms))
return fd;
close_socket:
close(fd);
exit:
return -1;
}
可以看到,创建完TCP套接字后,并没有指定使用的网卡设备,要想指定4G模块,则需将其IP等信息与TCP套接字进行绑定
获取4G模块IP
输入ifconfig 获取4G模块信息
ifconfig
4G模块对应的设备名为eth2(通过拔插设备判断设备名),IPv4地址为: 192.168.0.100
可以简单测试下4G模块是否联网
ping baidu.com -I eth2
修改SDK对应源码
找到plat_tcp_connect
函数
在创建好TCP套接字后加入以下内容,将其绑定到4G模块对应的IP地址
struct sockaddr_in my_addr; // 绑定的地址
// 绑定自己的地址和端口, 通过固定地址端口访问服务器 to be continue
my_addr.sin_family = AF_INET;
my_addr.sin_addr.s_addr = inet_addr("192.168.0.100");
my_addr.sin_port = htons(8080);
ret = bind(fd, (struct sockaddr*)&my_addr, sizeof(my_addr));
完整代码修改如下:
handle_t plat_tcp_connect(const uint8_t *host, uint16_t port, uint32_t timeout_ms)
{
handle_t fd = -1;
struct sockaddr_in addr_in;
struct sockaddr_in my_addr; // 绑定的地址
struct hostent *ip_addr;
int32_t flags = -1;
int ret = -1;
if(0 == (ip_addr = gethostbyname(host))) // 域名解析
{
goto exit;
}
addr_in.sin_family = AF_INET;
addr_in.sin_addr = *((struct in_addr *)ip_addr->h_addr_list[0]);
addr_in.sin_port = htons(port);
if(0 > (fd = socket(AF_INET, SOCK_STREAM, 0))) // 创建TCP套接字
{
goto exit;
}
// 绑定自己的地址和端口, 通过固定地址端口访问服务器 to be continue
my_addr.sin_family = AF_INET;
my_addr.sin_addr.s_addr = inet_addr("192.168.0.100");
my_addr.sin_port = htons(8080);
ret = bind(fd, (struct sockaddr*)&my_addr, sizeof(my_addr));
if (ret < 0)
{
perror("bind");
return -1;
}
// end
if((0 > (flags = fcntl(fd, F_GETFL, 0))) || (0 > fcntl(fd, F_SETFL, flags | O_NONBLOCK)))
{
goto close_socket;
}
if(0 > (ret = connect(fd, (struct sockaddr *)&addr_in, sizeof(addr_in))))
{
if(EINPROGRESS != errno)
{
goto close_socket;
}
}
if(check_connect(fd, timeout_ms))
return fd;
close_socket:
close(fd);
exit:
return -1;
}
生成可执行文件(远程开发可参考)
参考VS远程Linux_CMake项目搭建,连上远程主机并配置好相关配置后,点击生成–>全部生成
可以看到相关源代码和生成的可执行文件被复制到远程主机的指定目录中
进入目录,查看可执行文件(绿色的)
输入./mqtts_onejson_soc.app执行文件
可以看到设备接入成功
进入onenet设备管理,刷新页面,看到设备在线
- Note: 此时还未有数据上报等功能实现,需要在main函数中,根据自己的业务逻辑调用相关接口。