简介

我们的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”

保存并应用更改。

验证

最终结果应该是这样的:

现在两个表都显示小数的温度

  • 没有标签