MikroTik Tag advertisement formats
TG-BT5-XX 标签可以在 4 种不同的模式下运行:
简介
TG-BT5-XX 标签可以在 4 种不同的模式下运行:
- 工厂休眠模式
- 配置模式
- 广播模式
- 升级模式
在广播模式下,标签将通过 Bluetooth 广告数据包广播关于自身的信息。信息取决于广告数据包类型。
目前,以下是所有可以使用 MikroTik Beacon Manager 应用配置的受支持类型:
DeviceName、MikroTik、Eddystone-TLM、Eddystone-UID 和 iBeacon。
Bluetooth 技术数据交换期间使用 2 种类型的信道(各自使用不同的频率):
- 专用于数据传输的数据信道;
- 专用于广播的广播信道。
共有 40 个唯一的频段(信道),每个频段间隔 2 MHz。信道 37、38 和 39 用于广播,信道 0-36 用于数据传输。
在广播过程中,会广播 BLE 广播数据包。该数据包包含 Preamble、Access Address、PDU 和 CRS 字段。
Preamble 和 Access Address 字段帮助接收方检测帧。CRS 字段用于检查错误。PDU 定义了数据包本身。
MikroTik 标签支持 legacy 不可连接、不可扫描的非定向广播(ADV_NOCONN_IND)。在这种情况下,Payload 由 "AdvA"(包含广播者地址信息的字段)和 "AdvData"(包含数据信息的字段)字段组成。
1 octet = 1 byte = 8 bits
| 属性 | 描述 |
|---|---|
| Preamble | 1 octet |
| Access-Address | 4 octets |
| PDU | PDU Header = 2 octets PDU Payload = AdvA (6 octets)+AdvData (0...31 octets) |
| CRS | 3 octets |
MikroTik 数据包结构
"AdvData" 字段结构(最多 31 octets/bytes):
| 属性 | 描述 | |
|---|---|---|
| Flags | Flags 字段的长度、类型和数据。用于 "告知" 周围的扫描器设备处于何种状态。 | 3 octets (020106): 1st octet - length 2nd octet - type 3d octet - data |
| Length | 负载的长度。 | 1 octet (15) |
| Type | 制造商特定数据。 | 1 octet (ff) |
| ManufacturerData | 公司标识符。 | 2 octets (4F09) |
| Version | 此广告结构的版本。 | 1 octet (uint) |
| UserData | 用户配置的负载部分。 | 1 octet (uint) |
| Secret | 可选的已加密(AES-ECB)负载部分。 | secret: salt(用于加密)= 2 octets (uint) secret: acceleration(加速度,采用带符号 8.8 定点格式,所有 3 个轴的加速度(0=x, 1=y, 2=z))= 6 octets (uint) secret: temperature(环境温度,摄氏度,采用带符号 8.8 定点格式)= 2 octet (int) secret: uptime(运行时间,以秒为单位)= 4 octets (uint) secret: flags(标志位掩码)= 1 octet (uint) secret: batteryPercentage(电池电量百分比)= 1 octet (uint) |
信息
请注意,所有多字节值均采用 little-endian。也就是说,例如,如果你想获取温度值,且第 14 和第 15 个 octet 将温度表示为 "a1 19"("正" 温度)→ 实际温度值为 (0x19a1)/256 = 25.6 C。 稍后将在 PDU payload structure 部分展示如何将 hexadecimal 负载值转换为 decimal 值的详细示例。
UserData 和 Secret 字段通过 flags 进行配置。在 "UserData" 部分中,控制 "Secret" 是否加密的参数称为 FLAG_ENCRYPTED。当 FLAG_ENCRYPTED=0 时,表示 secret 未加密(第 6 个 octet 中的第 1 位将设置为 0);当 FLAG_ENCRYPTED=1 时,表示 secret 已加密(第 6 个 octet 中的第 1 位将设置为 1)。
在 "Secret" 部分中,有 7 个 flags(第 24 个 octet):
FLAG_REED_SWITCH(第 1 位 - 如果设置为 1,表示广播时刻簧片开关处于闭合状态)FLAG_ACCEL_TILT(第 2 位 - 如果设置为 1,表示广告是通过倾斜设备发送的)FLAG_ACCEL_FREE_FALL(第 3 位 - 如果设置为 1,表示广告是通过跌落设备发送的)FLAG_IMPACT_X(第 4 位 - 如果设置为 1,表示广告时刻 x 轴发生了撞击)FLAG_IMPACT_Y(第 5 位 - 如果设置为 1,表示广告时刻 y 轴发生了撞击)FLAG_IMPACT_Z(第 6 位 - 如果设置为 1,表示广告时刻 z 轴发生了撞击)FLAG_ACCEL_DISABLED(第 7 位 - 如果设置为 1,表示加速度计已被禁用) 例如,如果你看到十六进制消息的第 24 个 octet 是 "02"(将 hexadecimal 值 "02" 转换为 binary 得到 "0010" → 第 2 位设置为 1)→ 这意味着设备发生了倾斜。如果你看到 "04"(hex "04" 转 bin 为 "0100" → 第 3 位设置为 1)→ 这意味着设备被跌落(触发了自由落体)。如果你看到 "38"(hex 转 bin 为 "00111000" → 第 4、5 和 6 位设置为 1)→ 这意味着在发送广告时,加速度计在所有 3 个 x/y/z 轴上检测到了撞击/唤醒。
更多示例(针对第 24 octet 的值):
- "08" 表示仅在 x 轴发生撞击;
- "18" 表示在 x 和 y 轴发生撞击;
- "28" 表示在 x 和 z 轴发生撞击;
- "10" 表示仅在 y 轴发生撞击;
- "30" 表示在 y 和 z 轴发生撞击;
- "20" 表示仅在 z 轴发生撞击。
- "40" 表示加速度计已禁用。
MikroTik PDU Payload 结构
| Octet | Value | ||
|---|---|---|---|
| 0 | 02 | Flags | flags 字段的长度 |
| 1 | 01 | Flags | flags 字段的类型 |
| 2 | 06 | Flags | flags 字段的数据 |
| 3 | 15 | Length | 负载的长度 |
| 4 | FF | Type | 制造商特定数据 |
| 5 | 4F | Company identifier | MikroTik |
| 6 | 09 | Company identifier | MikroTik |
| 7 | 01 | Version | 此广告结构的版本 |
| 8 | 00 | UserData | 用户配置的负载部分 |
| 9 | xx* | Secret | secret: salt |
| 10 | xx* | Secret | secret: salt |
| 11 | xx* | Secret | secret: acceleration on the X-axis |
| 12 | xx* | Secret | secret: acceleration on the X-axis |
| 13 | xx* | Secret | secret: acceleration on the Y-axis |
| 14 | xx* | Secret | secret: acceleration on the Y-axis |
| 15 | xx* | Secret | secret: acceleration on the Z-axis |
| 16 | xx* | Secret | secret: acceleration on the Z-axis |
| 17 | xx* | Secret | secret: temperature |
| 18 | xx* | Secret | secret: temperature |
| 19 | xx* | Secret | secret: uptime |
| 20 | xx* | Secret | secret: uptime |
| 21 | xx* | Secret | secret: uptime |
| 22 | xx* | Secret | secret: uptime |
| 23 | 00 | Secret | secret: flags |
| 24 | xx* | Secret | secret: batteryPercentage |
* - 可能发生变化
示例
MikroTik 格式(非加密)配置的负载示例如下:
| 02010615ff4f090100cea6000000000200a01c91085700005f |
|---|
020106(前 3 个 octets)→ flags 字段的长度、类型和数据。
15ff4f09(第 4、5、6 和第 7 个 octets)→ Length(0x15 hex-to-dec 为 21)。Type(0xff)。公司标识符(0x4f09)。
01(第 8 个 octet)→ 负载结构的当前版本。对于每个负载都应相同(常量数据)。
00(第 9 个 octet)→ 表示负载未加密。"01" 则表示已加密。
cea6(第 10 和第 11 个 octets)→ Salt。每个新负载都应生成不同的 salt 值。你可以使用此值来检查相同的负载是否以不同的方式加密。该值本身不包含任何有用信息。如果你看到在不同时间间隔内接收到的两个负载的 salt 值相同,则意味着收到的这两个负载完全相同。你可以使用与 uptime 计算相同的原理来计算 salt 值 - 见下文。
0000(第 12 和第 13 个 octets)→ 广播时刻 X 轴上的加速度 = 0 m/s<sup>2</sup>。请查看下方 Z 轴的加速度计算。
0000(第 14 和第 15 个 octets)→ 广播时刻 Y 轴上的加速度 = 0 m/s<sup>2</sup>。请查看下方 Z 轴的加速度计算。
0200(第 16 和第 17 个 octets)→ 广播时刻 Z 轴上的加速度 = 0.0078 m/s<sup>2</sup>。要从十六进制格式得出十进制值,你需要按照以下步骤操作:
- 如前所述,多字节值采用 little-endian,这意味着要计算实际值,你需要切换 octets 的位置(交换 octets 顺序)。因此第一步是将值从 0x0200 交换为 0x0002。0x0002 从 hexadecimal 转换为 decimal 为 02。
- 请记住,加速度采用带符号的 8.8 定点格式(二进制补码),这意味着你基本上需要将结果除以 "256"。第二步是将该值除以 256 → (0x0002 hex 或 02 dec)/256 = 0.0078 m/s<sup>2</sup>。
- 相同的计算原理适用于 X 和 Y 轴的加速度。在我们的示例中,它们恰好为 0 → 0x0000/256=0。
a01c(第 18 和第 19 个 octets)→ 标签检测到的摄氏温度 = 28.625 C。温度采用 little-endian(因为它是多字节值),并且采用 signed 16-bit integer [twos complement] 8.8 fixed point format,因此同样的 "公式" 在这里也适用: 0x1ca0/256=28.625 C。
91085700(第 20、21、22、23 个 octets)→ 标签的 uptime(以秒为单位)= 5703825 s。0x91085700 采用 little-endian,所以只需将 octets 交换为 0x00570891,结果就是十进制的 5703825。即 1584.395833 小时或 66 天的运行时间。
00(第 24 个 octet)→ 发送该负载的触发器(flag)。如果为 "00",表示未检测到触发器,只是基于为标签配置的广告间隔周期性广播的负载。如果该值为 "04",则表示设备被跌落(触发了自由落体)。你可以在上文的 packet structure 部分中的 "flags" 和 "Secret" 部分找到更多信息。
5f(第 25 个 octet)→ 标签的电池百分比 = 95 %。0x5f 从 hex 到 dec 为 95。
信息
从 v7.11 开始,你可以使用 Peripheral Device 部分和/或 Decode-ad 功能查看解码后的值!
#### Script for decoding
Add a new script under the "**System>Scripts**" tab and import the script there (for non-encrypted payloads).
# POSIX regex for filtering advertisement Bluetooth addresses. E.g. "^BC:33:AC"
# would only include addresses which start with those 3 octets.
# To disable this filter, set it to ""
:local addressRegex "2C:C8:1B:4B:BB:0A"
# POSIX regex for filtering Bluetooth advertisements based on their data. Same
# usage as with 'addressRegex'.
:local advertisingDataRegex ""
# Signal strength filter. E.g. -40 would only include Bluetooth advertisements
# whose signal strength is stronger than -40dBm.
# To disable this filter, set it to ""
:local rssiThreshold ""
################################## Bluetooth ##################################
:global invertU16 do={
:local inverted 0
:for idx from=0 to=15 step=1 do={
:local mask (1 << $idx)
:if ($1 & $mask = 0) do={
:set $inverted ($inverted | $mask)
}
}
return $inverted
}
:global le16ToHost do={
:local lsb [:pick $1 0 2]
:local msb [:pick $1 2 4]
:return [:tonum "0x$msb$lsb"]
}
:local le32ToHost do={
:local lsb [:pick $1 0 2]
:local midL [:pick $1 2 4]
:local midH [:pick $1 4 6]
:local msb [:pick $1 6 8]
:return [:tonum "0x$msb$midH$midL$lsb"]
}
:local from88 do={
:global invertU16
:global le16ToHost
:local num [$le16ToHost $1]
# Handle negative numbers
:if ($num & 0x8000) do={
:set num (-1 * ([$invertU16 $num] + 1))
}
# Convert from 8.8. Scale by 1000 since floating point is not supported
:return (($num * 125) / 32)
}
:local flagStr do={
:local str ""
:if ($1 & 0x01) do={ :set $str " switch" }
:if ($1 & 0x02) do={ :set $str "$str tilt" }
:if ($1 & 0x04) do={ :set $str "$str free_fall" }
:if ($1 & 0x08) do={ :set $str "$str impact_x" }
:if ($1 & 0x10) do={ :set $str "$str impact_y" }
:if ($1 & 0x20) do={ :set $str "$str impact_z" }
:if ([:len $str] = 0) do={ :return "" }
:return [:pick $str 1 [:len $str]]
}
# Find fresh Bluetooth advertisements
:global btOldestAdvertisementTimestamp
:if ([:typeof $btOldestAdvertisementTimestamp] = "nothing") do={
# First time this script has been run since booting, need to initialize
# persistent variables
:set $btOldestAdvertisementTimestamp 0
}
:local advertisements [/iot bluetooth scanners advertisements print detail \
as-value where \
epoch > $btOldestAdvertisementTimestamp and \
address ~ $addressRegex and \
data ~ $advertisingDataRegex and \
rssi > $rssiThreshold
]
:local advCount 0
:local lastAdvTimestamp 0
:local advJson ""
:local advSeparator ""
# Remove semicolons from MAC/Bluetooth addresses
:local minimizeMac do={
:local minimized
:local lastIdx ([:len $address] - 1)
:for idx from=0 to=$lastIdx step=1 do={
:local char [:pick $address $idx]
:if ($char != ":") do={
:set $minimized "$minimized$char"
}
}
:return $minimized
}
:foreach adv in=$advertisements do={
:local address ($adv->"address")
:local rssi ($adv->"rssi")
:local epoch ($adv->"epoch")
:local ad ($adv->"data")
:local version [:tonum "0x$[:pick $ad 14 16]"]
:local encrypted [:tonum "0x$[:pick $ad 16 18]"]
:local salt [$le16ToHost [:pick $ad 18 22]]
:local accelX [$from88 [:pick $ad 22 26]]
:local accelY [$from88 [:pick $ad 26 30]]
:local accelZ [$from88 [:pick $ad 30 34]]
:local temp [$from88 [:pick $ad 34 38]]
:local uptime [$le32ToHost [:pick $ad 38 46]]
:local flags [:tonum "0x$[:pick $ad 46 48]"]
:local bat [:tonum "0x$[:pick $ad 48 50]"]
:put ("$advCount: \
address=$address \
ts=$epoch \
rssi=$rssi \
version=$version \
encrypted=$encrypted \
salt=$salt \
accelX=$accelX \
accelY=$accelY \
accelZ=$accelZ \
temp=$temp \
uptime=$uptime \
flags=\"$[$flagStr $flags]\" \
bat=$bat" \
)
:set $advCount ($advCount + 1)
:set $lastAdvTimestamp $epoch
}
:if ($advCount > 0) do={
:set $btOldestAdvertisementTimestamp $lastAdvTimestamp
}
你唯一需要修改的行是:
:local addressRegex "2C:C8:1B:4B:BB:0A"
该行中你需要输入标签的 MAC 地址。
用你喜欢的任意名称保存脚本,例如 decode。
通过命令行界面运行脚本(Winbox/Webfig 中的 "New Terminal" 按钮):
[admin@MikroTik] > system script run decode
0: address=2C:C8:1B:4B:BB:0A ts=1662553431348 rssi=-45 version=1 encrypted=0 salt=57919 accelX=3 accelY=-35 accelZ=-70 temp=25535 uptime=1046174 flags="" bat=99
1: address=2C:C8:1B:4B:BB:0A ts=1662553436349 rssi=-40 version=1 encrypted=0 salt=24154 accelX=-19 accelY=-23 accelZ=0 temp=25546 uptime=1046179 flags="" bat=99
2: address=2C:C8:1B:4B:BB:0A ts=1662553446351 rssi=-37 version=1 encrypted=0 salt=37822 accelX=-15 accelY=35 accelZ=15 temp=25550 uptime=1046189 flags="" bat=99
从上方的示例可以看出,脚本会将所有负载从 hexadecimal 格式 "转换" 为 decimal 格式,并将它们打印到终端。
你还可以进一步修改脚本,将 "已解码" 的值组织成消息,并发布到你选择的 EMAIL、MQTT 或 HTTP 服务器 但是! 请记住,这可能会增加设备负载。因此,你需要测试运行脚本时的性能。在服务器端进行解码对 RouterOS 资源更友好。
信息
由于不支持浮点运算 → 小数点后的每次计算都将 "向上取整" 为整数。这就是脚本会将温度和加速度值 放大 1000 倍(乘以 1000)来计算的原因。 因此,如果你看到温度显示为 temp=25546,实际温度是 25.546 C(25546/1000);如果你看到 accelZ=15,z 轴上的实际加速度是 0.015 m/s<sup>2</sup>(15/1000)。
iBeacon 数据包结构
iBeacon 是受支持的广告数据包类型之一。你可以通过链接找到有关该协议的更多信息。
在这种情况下,PDU Payload 由 "AdvA"(6 个 octets 长)和 "AdvData"(包含数据信息的字段)字段组成。Legacy Bluetooth 设备只能支持 31 字节长的 beacon 消息。UUID 为 16 字节长(MikroTik 默认 UID=b2b98de4-c81c-47c2-b14e-791b3e5587ec)。
"AdvData" 字段结构:
| 属性 | 描述 | |
|---|---|---|
| Flags | Flags 字段的长度、类型和数据。用于 "告知" 周围的扫描器设备处于何种状态。 | 3 octets (020106): 1st octet - length 2nd octet - type 3d octet - data |
| ManufacturerData | 公司标识符 | 4 octets (1aff4c00) |
| BeaconType | 次要标识符 | 1 octet (const) |
| RemainingDataLength | 定义负载的剩余长度(以字节为单位) | 1 octet (const) |
| UserData | 用户配置的负载部分 | Proximity UUID(通用唯一标识符)= 16 octets (uint) Major Number(特定组标识符)= 2 octets (uint) Minor Number(特定 beacon 标识符)= 2 octets (uint) |
| TxPower | 表示距设备一米处的信号强度 | 1 octet (int) |
iBeacon PDU Payload 结构
| Octet | Value | ||
|---|---|---|---|
| 0 | 02 | Flags | flags 字段的长度 |
| 1 | 01 | Flags | flags 字段的类型 |
| 2 | 06 | Flags | flags 字段的数据 |
| 3 | 1a | ManufacturerData | 公司标识符 |
| 4 | ff | ManufacturerData | 公司标识符 |
| 5 | 4c | ManufacturerData | 公司标识符 |
| 6 | 00 | ManufacturerData | 公司标识符 |
| 7 | 02 | BeaconType | 次要标识符 |
| 8 | 15 | RemainingDataLength | 定义负载的剩余长度(以字节为单位) |
| 9 | xx* | UserData | Proximity UUID |
| 10 | xx* | UserData | Proximity UUID |
| 11 | xx* | UserData | Proximity UUID |
| 12 | xx* | UserData | Proximity UUID |
| 13 | xx* | UserData | Proximity UUID |
| 14 | xx* | UserData | Proximity UUID |
| 15 | xx* | UserData | Proximity UUID |
| 16 | xx* | UserData | Proximity UUID |
| 17 | xx* | UserData | Proximity UUID |
| 18 | xx* | UserData | Proximity UUID |
| 19 | xx* | UserData | Proximity UUID |
| 20 | xx* | UserData | Proximity UUID |
| 21 | xx* | UserData | Proximity UUID |
| 22 | xx* | UserData | Proximity UUID |
| 23 | xx* | UserData | Proximity UUID |
| 24 | xx* | UserData | Proximity UUID |
| 25 | xx* | UserData | Major Number |
| 26 | xx* | UserData | Major Number |
| 27 | xx* | UserData | Minor Number |
| 28 | xx* | UserData | Minor Number |
| 29 | xx* | TxPower | 表示距设备一米处的信号强度 |
* - 可能发生变化
Eddystone-TLM 数据包结构
Eddystone-TLM 是受支持的广告数据包类型之一。你可以通过链接找到有关该协议的更多信息。
在这种情况下,PDU Payload 由 "AdvA"(6 个 octets 长)和 "AdvData"(包含数据信息的字段)字段组成。MikroTik 默认 CompleteUUID=03 03 aa fe;ServiceData=11 16 aa fe。
"AdvData" 字段结构:
| 属性 | 描述 | |
|---|---|---|
| Flags | Flags 字段的长度、类型和数据。用于 "告知" 周围的扫描器设备处于何种状态。 | 3 octets (020106): 1st octet - length 2nd octet - type 3d octet - data |
| CommonPayload | 对所有 Eddystone 帧类型通用的广告负载部分 | CompleteUUID(通用唯一标识符)= 4 octets (const) ServiceData(16 bit UUID 数据类型)= 4 octets (const) FrameType(值 = 0x20)= 1 octet (const) |
| TlmPayload | Eddystone-TLM 帧负载 | Version(TLM 版本)= 1 octet (const) BatteryVoltageMv(电池电压,1 mV/bit)= 2 octets (uint) TemperatureC(Beacon 温度,摄氏度)= 2 octets (int) AdvertisementCount(广告 PDU 计数)= 4 octets (uint) UptimeCounter(自开机或重启以来的时间)= 4 octets (uint) |
Eddystone-TLM PDU Payload 结构
| Octet | Value | ||
|---|---|---|---|
| 0 | 02 | Flags | flags 字段的长度 |
| 1 | 01 | Flags | flags 字段的类型 |
| 2 | 06 | Flags | flags 字段的数据 |
| 3 | 03 | CommonPayload | CompleteUUID |
| 4 | 03 | CommonPayload | CompleteUUID |
| 5 | aa | CommonPayload | CompleteUUID |
| 6 | fe | CommonPayload | CompleteUUID |
| 7 | 11 | CommonPayload | ServiceData |
| 8 | 16 | CommonPayload | ServiceData |
| 9 | aa | CommonPayload | ServiceData |
| 10 | fe | CommonPayload | ServiceData |
| 11 | 20 | CommonPayload | FrameType |
| 12 | 00 | TlmPayload | Version |
| 13 | xx* | TlmPayload | BatteryVoltageMv |
| 14 | xx* | TlmPayload | BatteryVoltageMv |
| 15 | xx* | TlmPayload | TemperatureC |
| 16 | xx* | TlmPayload | TemperatureC |
| 17 | xx* | TlmPayload | AdvertisementCount |
| 18 | xx* | TlmPayload | AdvertisementCount |
| 19 | xx* | TlmPayload | AdvertisementCount |
| 20 | xx* | TlmPayload | AdvertisementCount |
| 21 | xx* | TlmPayload | UptimeCounter |
| 22 | xx* | TlmPayload | UptimeCounter |
| 23 | xx* | TlmPayload | UptimeCounter |
| 24 | xx* | TlmPayload | UptimeCounter |
* - 可能发生变化
Eddystone-UID 数据包结构
Eddystone-UID 是受支持的广告数据包类型之一。你可以通过链接找到有关该协议的更多信息。
在这种情况下,PDU Payload 由 "AdvA"(6 个 octets 长)和 "AdvData"(包含数据信息的字段)字段组成。MikroTik 默认 CompleteUUID=03 03 aa fe;ServiceData=17 16 aa fe。
"AdvData" 字段结构:
| 属性 | 描述 | |
|---|---|---|
| Flags | Flags 字段的长度、类型和数据。用于 "告知" 周围的扫描器设备处于何种状态。 | 3 octets (020106): 1st octet - length 2nd octet - type 3d octet - data |
| CommonPayload | 对所有 Eddystone 帧类型通用的广告负载部分 | CompleteUUID(通用唯一标识符)= 4 octets (const) ServiceData(16 bit UUID 数据类型)= 4 octets (const) FrameType(值 = 0x00)= 1 octet (const) |
| UidPayload | Eddystone-UID 帧负载 | Ranging Data(0 m 处校准的 Tx 功率)= 1 octet (int) Nspace(唯一的自定义 beacon ID 命名空间)= 10 octets (uint) Instance(命名空间内的唯一 ID)= 6 octets (uint) RFU1(保留供将来使用,值=0x00)= 1 octet (const) RFU2(保留供将来使用,值=0x00)= 1 octet (const) |
Eddystone-UID PDU Payload 结构
| Octet | Value | ||
|---|---|---|---|
| 0 | 02 | Flags | flags 字段的长度 |
| 1 | 01 | Flags | flags 字段的类型 |
| 2 | 06 | Flags | flags 字段的数据 |
| 3 | 03 | CommonPayload | CompleteUUID |
| 4 | 03 | CommonPayload | CompleteUUID |
| 5 | aa | CommonPayload | CompleteUUID |
| 6 | fe | CommonPayload | CompleteUUID |
| 7 | 17 | CommonPayload | ServiceData |
| 8 | 16 | CommonPayload | ServiceData |
| 9 | aa | CommonPayload | ServiceData |
| 10 | fe | CommonPayload | ServiceData |
| 11 | 00 | CommonPayload | FrameType |
| 12 | xx* | UidPayload | Ranging Data |
| 13 | xx* | UidPayload | Nspace |
| 14 | xx* | UidPayload | Nspace |
| 15 | xx* | UidPayload | Nspace |
| 16 | xx* | UidPayload | Nspace |
| 17 | xx* | UidPayload | Nspace |
| 18 | xx* | UidPayload | Nspace |
| 19 | xx* | UidPayload | Nspace |
| 20 | xx* | UidPayload | Nspace |
| 21 | xx* | UidPayload | Nspace |
| 22 | xx* | UidPayload | Nspace |
| 23 | xx* | UidPayload | Instance |
| 24 | xx* | UidPayload | Instance |
| 25 | xx* | UidPayload | Instance |
| 26 | xx* | UidPayload | Instance |
| 27 | xx* | UidPayload | Instance |
| 28 | xx* | UidPayload | Instance |
| 29 | 00 | UidPayload | RFU1 |
| 30 | 00 | UidPayload | RFU2 |
* - 可能发生变化
Device Name
启用后,标签将广播一个包含所配置 "Device Name" 的短负载。
| 属性 | 描述 | |
|---|---|---|
| Flags | Flags 字段的长度、类型和数据。用于 "告知" 周围的扫描器设备处于何种状态。 | 3 octets (020106): 1st octet - length 2nd octet - type 3d octet - data |
| Complette Local Name | 广告负载的一部分,包含 Local Name 信息。 | Length = 1 octet AD type = 1 octet Name bytes = x octets. |
Device Name PDU Payload 结构
如果我们将 "Device Name" 配置为 "TG-BT5-OUT":
| Octet | Value | ||
|---|---|---|---|
| 0 | 02 | Flags | flags 字段的长度 |
| 1 | 01 | Flags | flags 字段的类型 |
| 2 | 06 | Flags | flags 字段的数据 |
| 3 | 0b | Length | 长度字节 |
| 4 | 09 | AD Type | Complete Local Name 类型字节 |
| 5 | 54 | Name byte #1 | ASCII "T" |
| 6 | 47 | Name byte #2 | ASCII "G" |
| 7 | 2d | Name byte #3 | ASCII "-" |
| 8 | 42 | Name byte #4 | ASCII "B" |
| 9 | 54 | Name byte #5 | ASCII "T" |
| 10 | 35 | Name byte #6 | ASCII "5" |
| 11 | 2d | Name byte #7 | ASCII "-" |
| 12 | 4f | Name byte #8 | ASCII "O" |
| 13 | 55 | Name byte #9 | ASCII "U" |
| 14 | 54 | Name byte #10 | ASCII "T" |