OneNET物联网TCP透传接入及自定义Lua解析脚本
Posted 玖零大壮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OneNET物联网TCP透传接入及自定义Lua解析脚本相关的知识,希望对你有一定的参考价值。
本篇文章内容讲解如何使用TCP透传的协议接入OneNET平台,我已经将接入步骤完整的录制了一个视频,所以接入步骤不再赘述,我在这篇文章中重点讲述一下Lua解析脚本以及如何自定义。
建议先看下面的视频(和我在B站和YouTube发的一样,看过的就不用看了),然后再接着看文章的内容。
如果对Lua脚本一无所知,我专门写了一篇Lua扫盲的入门文章,。
1
OneNET平台的TCP透传使用框架如下:
终端设备通过TCP连接接入OneNET服务器;
发送认证字符串,OneNET认证成功后创建设备实例;
服务器回调Lua脚本中的定时器初始化函数device_timer_init(dev)
终端设备上传数据至OneNET服务器;
服务器回调Lua脚本中数据处理函数device_data_analyze(dev)
我画了个大概的流程图,如下:
也就是说,我们在提供lua解析脚本时,只需要重写两个回调函数:
//定时器初始化函数(可选),在这里设置定时下发设备的数据
device_timer_init(dev)
//解析终端设备上传的数据(必选)
device_data_analyze(dev)
从上面描述还可以看到,device_timer_init(dev)函数在解析脚本中也不是必须的。比如,我下面写的最小的脚本测试程序mini.lua:
function device_data_analyze(dev)
local s = dev:size() --获取上行数据长度
local data = dev:bytes(1,s) --获取上行数据
local json_str = string.format('[{"v":"%s","i":"test_ds","a":0}]', data)
dev:response() -- 设备响应
return s,json_str --保存该数据
end
把它上传至OneNET,同样可以完成数据点解析且以原始数据形式存储至数据流test_ds:
2
我们可以发现,两个函数中的参数都携带dev,我们再来聊聊它。
dev其实是一个user_data类型的值,但是呢,我们可能没有学过lua(至少我当时没接触OneNET时是不懂lua的),我们可以这样“错误通俗”的理解它:
dev就是面向对象中,一个类的实例化对象,比如下面这样:
Device dev_instance = new Device()
void receive_data()
{
device_data_analyze(&dev_instance)
}
device_data_analyze(Device *dev)
{
dev->response()
dev->size()
}
然后上面的response()、size()等就是这个类中定义的方法。
咱们就先这样理解吧,我编不下去了,因为我不知道如果lua专业人士看到会不会大嘴巴子抡我
其实我们只要知道dev自己提供的函数用法就行,如下:
1)dev:add(interval,name,data)
添加定时下发数据。
@param interval number 数据下发的时间间隔(秒)
name string 名称(须保证唯一性)
data string 数据(二进制数据),使用lua转义字符串
@return 成功返回true,否则返回false
@notice 定时数据下发的平均频率不超过1,及1/interval_1+...+1/interval_n<=1
@example local ok = dev:add(10,”test”,”11 150 3725329”)
2)dev:timeout(sec)
设置下发数据的设备响应超时时间(秒)。
@param sec number 响应超时时间(秒)
如果值为0,表示不检测设备响应超时
@return 无
@example dev:timeout(3)
3)dev:response()
设备响应成功。
@param 无
@return 无
@example dev:response()
4)dev:send(data)
下发数据到设备。
@param data string 数据(二进制数据),使用lua转义字符串
@return 无
@example dev:send("22 150 3720689")
5)dev:size()
获取设备数据大小(字节数)。
@param 无
@return 返回设备数据大小(字节数)
@example local sz = dev:size()
6)dev:byte(pos)
获取pos对应位置的设备数据(字节)。
@param pos number 指定的获取位置,取值范围[1,dev:size()+1)
@return 成功返回设备数据(int),否则返回nil
@example local data = dev:byte(1)
7)dev:bytes(pos,count)
获取从pos开始,count个设备数据。
@param pos number 指定的获取起始位置,取值范围[1,dev:size()+1)
count number 指定的获取数据总数,取值范围[0,dev:size()+1-pos]
@return 成功返回设备数据(string),否则返回nil
@example local datas = dev:bytes(1,dev:size())
3
我们再来看看我实验经常用到的一句话,如下箭头所指:
其实就是格式化一个json字符串,为什么要格式化json字符串呢?
这个是device_data_analyze回调函数要求的,它要求返回两个值:
上行数据长度,解析后的json格式数据点集合
其中数据点的格式要求如下:
[
{
“i” : ”dsname1”, // 数据流或数据流模板名称1
“a” : 1234567890, // 毫秒级时间戳,距离(00:00:00 UTC, January 1, 1970)的毫秒
// 如果值为0,表示使用当前时间
“v” : 123 | ”123” | {…} // 布尔值、数值、字符串、json
“b” : “0A0B0C0D…” // 二进制数据(16进制字符串),与v互斥,不同时存在
“d” : xxx | “xxx” | {…} // 用于描述b(可选);布尔值、数值、字符串、json
“c” : “authcode1” // 用于标识数据点归属(设备AuthCode)
// 如果值为“”或不存在,表示数据点归属建立TCP连接的设备
}
…
{
“i” : ”dsnamen”, // 数据流或数据流模板名称n
“a” : 1234567890, // 毫秒级时间戳,距离(00:00:00 UTC, January 1, 1970)的毫秒
// 如果值为0,表示使用当前时间
“v” : 123 | ”123” | {…} // 布尔值、数值、字符串、json
“b” : “0A0B0C0D…” // 二进制数据(16进制字符串),与v互斥,不同时存在
“d” : xxx | “xxx” | {…} // 用于描述b(可选);布尔值、数值、字符串、json
“c” : “authcode1” // 用于标识数据点归属(设备AuthCode,可选)
// 如果值为“”或不存在,表示数据点归属建立TCP连接的设备
}
]
仔细看看上面的格式说明,就能理解我写的自定义测试代码的意思了。
可能你会问,明明一个string.format字符串能搞定的事情,为啥还OneNET官方提供的lua测试脚本有那么多函数,比如add_val()、to_json()等?其实就是安全、通用。
如果你后期开发调试好,约定好上传的数据格式,你也可以自己简化。
然后,这里再说一下,device_data_analyze回调函数是支持返回一个不同数据点的集合的。
比如终端设备里上传了一个温度数据和一个湿度数据组成的字符串,你需要保存在两个数据流,你也可以约定好字符串的格式,比如123#456这样的字符串格式,然后在lua脚本里把字符串分割,再如下赋值:
local json_str = string.format('[{"v":%f,"i":"wendu","a":0},{"v":%f,"i":"shidu","a":0}]', wendu_value, shidu_value)
4
上面分析之后,你可以自己试着按照自己的想法去多做做实验,我就不继续赘述了。
我们再来说一下有些注意的地方:
表 lua脚本使用限制
对一些时延要求高的场景,建议慎用。
如果你想对连接的设备下发指令,比如你想在自己的应用中关掉某个设备的LED灯,你可以在应用中调用OneNET的API接口。关于这个,我也会在后面的基于NB和WIFI的物联网开发板的实用教程中展示。
以上是关于OneNET物联网TCP透传接入及自定义Lua解析脚本的主要内容,如果未能解决你的问题,请参考以下文章
安信可EC系列模组接入OneNET物联网开放平台的多协议接入产品
安信可EC系列模组接入OneNET物联网开放平台的多协议接入产品
安信可EC系列模组接入OneNET物联网开放平台的多协议接入产品