简介
我们的TG-BT5-OUT蓝牙标签模型有一个内置温度传感器。这意味着它可以用来测量周围的温度。
温度的值被“写入”到标签将通过蓝牙广告频道广播的广告有效负载中。根据您如何配置标记,标记可以定期或/和在检测到触发器时广播有效负载。您可以在。中找到有关标记配置选项的更多信息iOS而且Android Beacon管理器导游。
您可以使用我们的工具查看/显示有效载荷结模型下物联网>蓝牙广告报告>标签:
有效载荷将显示在“广告(十六进制)”字段中,它们将在十六进制格式。
当标签以MikroTik格式配置时,有效负载的第14和第15字节表示雷竞技网站温度(环境温度,以摄氏度为单位)有符号16位整数[双补]8.8定点格式)在广播的那一刻被“感知”到。
下面是MikroTik格式的有效载荷示例:雷竞技网站
15 ff4f09010032a500000000ffff5019bd5954000061 |
---|
请注意,负载中的所有多字节值都是小端格式的。因此,如果#14和#15字节表示温度为“50个19→你将需要转换八位位,到0x1950.
温度:
我们得到的温度是0x1950(十六进制)→6480(12月)。要得到实际的温度值,将结果除以256→6480/256=25.31摄氏度.
温度:
我们得到的温度是0xFE80(十六进制)。记住使用双补格式→-384年(带符号的2的补数的小数).要得到实际的温度值,将结果除以256→-384/256=-1.5摄氏度.
有了这些知识,我们就可以利用RouterOS脚本来构造接收到的有效负载的消息,并将l雷竞技其发送到MQTT/HTTP服务器。建议由服务器负责数据转换十六进制格式小数格式。但是!如果您愿意加载RouterOS设备,则可以执行l雷竞技十六进制值转换为小数(它会加载设备并影响Roul雷竞技terOS的性能→我们建议在服务器上转换值,而不是在RouterOS上)。在本指南中,我们将使用MQTT post to实现结果ThingsBoard.
ThingsBoard服务器和MQTT配置
你需要有一个ThingsBoard服务器启动并运行。可以找到有关如何设置服务器的有用信息,请参见链接.您可以将服务器本地安装到一台机器上,或者使用他们的云解决方案。
准备好服务器后,需要对其进行配置,使其能够接收MQTT消息。请按照“ThingsBoard配置链接来设置你的“设备”。
l雷竞技RouterOS配置
请查看链接在这里如何根据ThingsBoard服务器使用的设备凭据设置MQTT代理。
设置代理后,确认蓝牙标记正在广播信息,如上图所示物联网>蓝牙广告报告>选项卡。
系统>脚本
粘贴下面的脚本(在系统> >添加脚本):
#所需软件包:物联网
################################ 配置 ################################
应该用于发布的现有MQTT代理的名称
:本地代理"tb"# MQTT主题,消息应该在其中发布
:local topic "v1/devices/me/telemetry"# MAC应用作“定位器ID”的接口
: locallocatoriface "ether1"# POSIX正则表达式过滤广告蓝牙地址。如。“公元前^:33:交流”
#只包含以这3个字节开头的地址。
#禁用此过滤器,设置为""
:local addressRegex "2C:C8:1B:4B:BB:0A"# POSIX正则表达式用于根据蓝牙广告的数据过滤。相同
#使用'addressRegex'。
:local advertisingDataRegex ""#信号强度滤波器。例如-40只包含蓝牙广告
#信号强度大于-40dBm。
#禁用此过滤器,设置为""
:local rssiThreshold ""####下面的行用于从十六进制到dec###的数据转换
:global invertU16 do={
:局部倒0
step=1 do={
:本地掩码(1 << $idx)
if ($1 & $mask = 0) do={
:设置$倒置($倒置| $mask)
}
}
返回$倒
}:global le16ToHost do={
:local LSB [:pick $ 10 0 2]
:本地MSB [:pick $1 2 4]:return [:tonum "0x$msb$lsb"]
}
:local from88 do={
:全球invertU16
:全球le16ToHost
:local num [$le16ToHost $1]#处理负数
if ($num & 0x8000) do={
-1 * ([$invertU16 $num] + 1))
}#从8.8转换。由于不支持浮点数,因此缩放为1000
return (($num * 125) / 32)
}
################################## 蓝牙 ##################################
:put("[*]正在收集蓝牙信息…")
:全球btOldestAdvertisementTimestamp
:if ([:typeof $btOldestAdvertisementTimestamp] = "nothing") do={
#启动后第一次运行此脚本,需要初始化
#持久变量
:设置$btOldestAdvertisementTimestamp 0
}
:local btProcessingStart [/system clock get time]
:本地广告[/物联网蓝牙扫描仪广告打印细节\
As-value where \
纪元> $btOldestAdvertisementTimestamp和\
地址~ $addressRegex和\
数据~ $advertisingDataRegex和\
rssi > $rssiThreshold
]
:local advJson ""
:local advCount 0
:local advSeparator ""
:local lastAdvTimestamp 0
MAC/蓝牙地址中删除分号
:local minimizeMac do={
:本地最小化
:local lastIdx ([:len $address] - 1)
$lastIdx from=0 to=$lastIdx step=1 do={
:local char [:pick $address $idx]
:if ($char != ":") do={
:设置$最小化"$最小化$char"
}
}
:返回$最小化
}:foreach adv in=$ ads do={
:本地地址($adv->"address")
:local ts ($adv->"epoch")
:local rssi ($adv->"rssi")
:本地AD ($adv->"data")
:local tempf [:pick ($adv->"data") 28 32]#下面的行将以十六进制格式设置温度,如"0x1950"
:local temp ([:pick $tempf 2 4].使用实例[:pick $tempf 0 2])#下面的行将以十进制格式设置温度,如“25313”。它是用“#”注释的,所以如果你想用它来代替十六进制格式的值,注释上面的行,取消注释下面的行>,从下面的行中删除“#”,并在上面的行中添加“#”。
#:local temp [$from88 [:pick $ad 28 32]]
:local obj "{\
\
ts \“\”:ts美元,\
\ \“值”:{\
\ \“id”:\ " $ [$ minimizeMac地址= $地址]\”、\
\“rssi \”,\“rssi美元\”、\
\“temp \”,\“美元temp \”,\
\ \“广告”:\ \“美元广告\”
} \
}”
设置$advCount ($advCount + 1)
:设置$lastAdvTimestamp $ts
#确保最后一个对象没有以逗号结束
:set $advJson "$advJson$advSeparator$obj"
if ($advSeparator = "") do={
:set $advSeparator ","}
}:if ($advCount > 0) do={
:set $btOldestAdvertisementTimestamp $lastAdvTimestamp
}
:put("[*]发现$advCount新广告\
(处理时间:$[([/系统时钟获取时间]- $btProcessingStart)]))")#################################### MQTT #####################################
:本地消息\
“[$ advJson]”
:日志信息"$message";
:put("[*]总消息大小:$[:len $message] bytes")
:put("[*]发送消息到MQTT代理…")
/iot MQTT发布broker=$broker topic=$topic message=$message
:put ("[*] Done")
更改经纪人的名称(在我们的示例中,我们称之为MQTT代理)结核病):
:本地代理"tb"
ThingsBoard使用的默认主题是(你不需要改变它):
:local topic "v1/devices/me/telemetry"
修改MAC地址在我们的例子中,我们有MAC地址2 c: C8:1B: 4 b: BB: 0):
:local addressRegex "2C:C8:1B:4B:BB:0A"
下面的行将采用有效负载的第14和第15字节,并“重新构造”从“ABCD“到”CDAB(根据我们的例子简介Section,来自"5019“到”1950)→基本上构造带有温度的信息十六进制格式:
:local tempf [:pick ($adv->"data") 28 32]
:local temp ([:pick $tempf 2 4].使用实例[:pick $tempf 0 2])
第二个选择是将温度从十六进制来小数(如果你想保持十六进制格式l雷竞技,忽略这一步)。这可以通过在前一行中“注释”(添加“#”)(或完全删除它)和在下一行中“uncomments”(删除“#”)来实现,如下所示:
#:local temp ([:pick $tempf 2 4]。[:pick $tempf 0 2])
:local temp [$from88 [:pick $ad 28 32]]
由于不支持浮点数→小数点后面的每个计算都将被“舍入”为整数。这就是脚本计算温度的原因按1000比例(乘以1000),结果,温度看起来就像“25546(这意味着25.您可以添加额外的脚本来设置小数点(但请记住,额外的操作将加载设备),您也可以在服务器本身上执行此操作。
我们发布的MQTT消息结构如下所示(您不必更改它):
:local obj "{\
\
ts \“\”:ts美元,\
\ \“值”:{\
\ \“id”:\ " $ [$ minimizeMac地址= $地址]\”、\
\“rssi \”,\“rssi美元\”、\
\“temp \”,\“美元temp \”,\
\ \“广告”:\ \“美元广告\”
} \
}”
根据上面的例子构造的消息将以JSON格式显示(我们将关注的唯一真实值是“timestamp”→“ts”和“temperature”→“temp”,因此可以随意删除其他参数)。如果温度计算为十六进制格式,消息看起来像这样:
[ { “t”:1661333913375, "值":{ “id”:“2 cc81b4bbb0a”, “rssi”:“-43”, “临时”:“1939”, “广告”:“15 ff4f0901002de0ffff010000003919877c54000061” } } ] |
---|
如果温度计算为小数格式,它看起来是这样的:
[ { “t”:1661333913375, "值":{ “id”:“2 cc81b4bbb0a”, “rssi”:“-43”, “临时”:“25222", “广告”:“15 ff4f0901002de0ffff010000003919877c54000061” } } ] |
---|
保存脚本并运行:
[admin@雷竞技网站MikroTik] >系统脚本run name_of_the_script[*]收集系统信息…[*]收集蓝牙信息…[*]发现1条新广告(处理时间:00:00:00)[*]消息总大小:134字节[*]正在向MQTT代理发送消息…[*]已完成[admin@Mik雷竞技网站roTik] >
系统>调度器
应用一个调度器以所需的间隔运行脚本。请注意!如果您设置了一个调度器来运行脚本,例如,每2分钟运行一次,这将意味着在2分钟间隔内接收到的每个有效负载(由标记广播)将被“结构化”到MQTT消息中。您很可能不需要每隔2-5秒就知道标签的温度,因此您可以更改MQTT消息的结构,使其只发布最新的温度读数,或者只更改物联网>蓝牙>扫描仪设置过滤重复的“keep-newest(这样,蓝牙扫描仪将覆盖来自每个单独标记的MAC地址的每个新报告),并且脚本在运行脚本时只会发布一个“扫描”的有效负载。
结果
下的结果将能够验证最新遥测部分,在你为ThingsBoard创建的设备下(在我们的例子中,我们称之为“设备”结):
结果是一篇成功的MQTT文章!从上面的截图中,我们可以看到临时参数在十六进制格式。
但是!我们想要显示温度(临时参数)小数格式,我们也希望显示数据更容易感知。
以防万一,我们把温度写在小数格式,我们要设置一个小数点。
这就是"小部件“上场吧。
ThingsBoard小部件
收到后的值下最新遥测部分,您可以在“小部件".
小部件中使用的javascript应该能够将数据从十六进制格式转换为十进制格式。
选择希望在小部件中显示的值(在我们的示例中,临时),并按“在小部件上显示”按钮:
你可以在弹出的窗口中浏览小部件:
点击“添加到仪表板”按钮:
选择要创建的新仪表板或选择已经预安装/预先制作的现有仪表板。点击“添加”.
通过应用复选框"打开仪表板你将被重定向到仪表板菜单,或者你可以手动进入那里。
我们还添加了第二个表,结果,我们的测试仪表板看起来像这样:
以防我们把日期贴上去十六进制格式
属性中的值都将显示十六进制格式作为“17f9”(原始值,因为我们已经发送它从KNOT→javascript表没有转换为十进制值)。
因为标记的有效负载中的值是带符号的8.8定点格式(请记住二补格式),我们需要添加额外的javascript代码来将数据“转换”为十进制值。
进入“编辑模式,然后点击编辑小部件”按钮:
点击“编辑按钮,编辑参数临时:
在弹出窗口中数据密钥配置“启用复选框”使用数据后处理功能然后输入如下代码:
代码:
函数f (p) {
这一点。P = P;
}
f.prototype. compute =函数(mes){
let intValue = parseInt(mes, 16);
令符号= 1;
if(intValue & 0x8000) {
intValue = (~intValue + 1) & 0xFFFF;
符号= -1;
}
intValue =符号* intValue / Math。战俘(2,this.p);
返回intValue;
}
令res = new f(8);
返回(res.calculate(值));
保存并应用更改。
对第二个/第一个表执行相同的步骤。
以防我们把日期贴上去小数格式
结果如下:
执行与上面示例完全相同的步骤,但是对于这个场景,结果除以“1000”:
保存并应用更改。
验证
最终结果应该是这样的:
现在两个表都显示小数的温度.