Decent蓝牙秤在出厂时已使用1000g和2000g砝码进行过校准。
- 但是,校准可能会受到运输的影响。
- 请参阅用户手册或此校准视频 a> 了解更多信息。
- 重量数值以10hz的频率发送。
- 电池状态在重量数据传输中返回,以响应LED开启或关闭蓝牙命令。
- 请参阅“发送命令以打开或关闭 LED”视频。
- 电池电量不足3%或更低时,秤会在开机时显示LO信息。
- 我们不建议在秤上长时间放置重物,否则会慢慢使称重传感器变形,使其无法校准。
- 秤可以无限次重新校准。
- 没有用于设置秤显示克与盎司的蓝牙命令。
- 必须手动操作,打开秤后立即同时按下○和□按钮。更多信息,请参阅用户手册。
- 通过读取LED开启或关闭的蓝牙命令的响应,您可以发现电子秤显示的是克还是盎司。请参阅“发送打开或关闭LED的命令”
- 如果在执行完第一条命令之前向秤发送了第二条蓝牙命令,则秤将忽略第二条命令。
- 例如:一个去皮命令紧跟一个计时启动命令。
- 建议发送到秤的命令之间有200毫秒的间隔。
- 或者,您可以延迟发送第二个命令,直到您确认第一个命令已执行。
- 例如:在去皮(或LED开/关命令)之后,设置一个6字节的FE响应被发送回您的应用程序,以执行成功。
蓝牙介绍
“0000FFF4-0000-1000-8000-00805F9B34FB”体现了decent蓝牙秤的数据包
所有Decent秤的蓝牙数据包都具有以下7字节结构:
第一个字节 | 第二个字节 | 第三个字节 | 第四个字节 | 第五个字节 | 第六个字节 | 第七个字节 |
型号 03 = Decent | 类型 0A=LED开启/关闭 0B=计时开始/关闭 0F=去皮 | 命令/数据 (1) | 命令/数据 (2) | 命令/数据 (3) | 命令/数据 (4) | 异或验证 用于验证的6字节异或条件
|
下面给出了有关每个命令和信息类型的更多详细信息。
这是一个Tcl过程,它构建了7个字节的二进制数据包以发送到 Decent秤。它首先构建为文本字符串,然后在过程结束时转换为7字节的二进制文件:
proc decent_scale_make_command {cmdtype cmdddata {cmddata2 {}} } {
if {$cmddata2 == ""} {
msg "1 part decent scale command"
set hex [subst {03${cmdtype}${cmdddata}000000[decent_scale_calc_xor "0x$cmdtype" "0x$cmdddata"]}]
} else {
msg "2 part decent scale command"
set hex [subst {03${cmdtype}${cmdddata}${cmddata2}0000[decent_scale_calc_xor4 "0x$cmdtype" "0x$cmdddata" "0x$cmddata2"]}]
}
msg "hex is '$hex' for '$cmdtype' '$cmdddata' '$cmddata2'"
return [binary decode hex $hex]
}
异或计算
要进行异或计算,应该对前6个字节进行数学异或计算。
下面的Tcl编程代码,为一个只接受一个参数的简单命令(例如:去皮)异或计算:
proc decent_scale_calc_xor {cmdtype cmdddata} {
set xor [format %02X [expr {0x03 ^ $cmdtype ^ $cmdddata ^ 0x00 ^ 0x00 ^ 0x00}]]
msg "decent_scale_calc_xor for '$cmdtype' '$cmdddata' is '$xor'"
return $xor
}
这个Tcl编程代码,是用于计算两个参数命令的异或计算,例如启用LED显示:
proc decent_scale_calc_xor4 {cmdtype cmdddata1 cmdddata2} {
set xor [format %02X [expr {0x03 ^ $cmdtype ^ $cmdddata1 ^ $cmdddata2 ^ 0x00 ^ 0x00}]]
msg "decent_scale_calc_xor4 for '$cmdtype' '$cmdddata1' '$cmdddata2' is '$xor'"
return $xor
}
接收重量
接收重量数据是一种稍微特殊的情况,因为重量是作为克重量*10的两字节有符号短整数发送的:
固件v1.0和v1.1以7个字节格式发送重量数据。
第一个字节 | 第二个字节 | 第三个字节 | 第四个字节 | 第五个字节 | 第六个字节 | 第七个字节 |
型号 03 = Decent | 类型 CE=重量稳定 CA=重量变化 | Data (1) 克重*10
有符号短整数的高位字节 |
Data (2) 克重*10
有符号短整数的低位字节 | Data (3) 变化*10
有符号短整数的高位字节 |
Data (4) 变化*10
有符号短整数的低位字节 |
异或验证 用于验证的6字节异或条件
|
固件v1.2版本以10个字节格式发送带有时间信息的重量数据。
第一个字节 | 第二个字节 | 第三个字节 | 第四个字节 | 第五个字节 | 第六个字节 | 第七个字节 | 字节 8 | 字节 9 | 字节 10 |
型号 03 = Decent | 类型 CE=重量稳定 CA=重量变化 | Data (1) 克重*10
有符号短整数的高位字节 |
Data (2) 克重*10
有符号短整数的低位字节 |
Data (3) 分钟 |
Data (4) 秒(0-59 十六进制) |
数据(5) 分秒数(0-9) |
数据(6) 供将来使用 |
数据(7) 供将来使用 |
异或验证 用于验证的6字节异或条件
|
注意:
- 您的应用程序应该查看接收到的消息的长度,并支持两者的解析。 大多数应用程序只需要知道当前的重量:只需查看字节3和4即可,与所有Decent蓝牙秤固件兼容。 或者,您可以检查固件版本是否等于或大于03。
- 当前重量在数据字节1和2上以两字节短的大端有符号整数的形式传达。
- 每秒重量变化以两字节无符号大端字节的形式出现。但是,此功能目前存在问题,不建议使用。如果你需要重量变化数据,您可以自己计算。
自固件v1.2起,重量变化率功能已停用。
- 重量数据以每秒10次的频率发送。
- 秤尝试确定重量何时稳定(不再变化)并将第二个字节设置为CE。当重量发生变化时,第二个字节是CA。但是,您可以选择忽略这一点并实施您自己的逻辑来决定重量何时稳定,因为我们没有对重量数据做数据平滑或稳定处理。
- 查看本页顶部的7字节和10字节消息示例。
接收按钮点击信号
第一个字节 | 第二个字节 | 第三个字节 | 第四个字节 | 第五个字节 | 第六个字节 | 第七个字节 |
型号 03 = Decent | 类型 AA | Data (1) 01=圆形按键 02=方形按键 | Data (2) 01=短按
02=长按 | Data (3) | Data (4) | 异或验证 00 |
注意:
- 当有蓝牙连接时,按钮轻敲无功能相应,并且您可以编程您喜欢的任何功能。
- 在de秤v1.1固件上,按下圆形按钮不会通过蓝牙发送信号。如果您的应用需要去皮,您的应用应向秤发送去皮命令。
以下是Light Blue应用程序日志中的触控按钮示例:
16:59:51.479 - 特征 (FFF4) 通知: 03aa0101 0000a9 (短按圆形按钮)
17:35:49.591 - 特征 (FFF4) 通知: 03aa0102 0000aa (长按圆形按钮)
17:38:16.702 - 特征 (FFF4) 通知: 03aa0201 0000aa (短按方形按钮)
17:39:08.003 - 特征 (FFF4) 通知: 03aa0202 0000a9 (长按方形按钮)
发送去皮命令(将重量重置为零)
第一个字节 | 第二个字节 | 第三个字节 | 第四个字节 | 第五个字节 | 第六个字节 | 第七个字节 |
型号 03 = Decent | 类型 0F | Data (1) 递增整数 (可以一直为零) |
Data (2) 00 | Data (3) 00 | Data (4) 00=disable heartbeat requirement 01=maintain heartbeat | 异或验证 计算 |
注意:
- “递增整数”是可选的,并且可以始终为零。
- 030F000000000C字符串将始终为去皮。
- 确保您正确计算了7字节的异或运算,否则去皮命令将被忽略。
- 如果至少每5秒没有接收到“03 0a 03 ff 00 0a”的信号,则薄款Decent蓝牙秤将断开连接。
如果你想禁用这个要求,字节6应该是00。
如果你想保持这个要求,字节6应该是01。
将字节6设置为01对不支持心跳功能的模型没有负面影响。
下面是一段代码,展示了如何构建一个7字节的去皮命令:
proc tare_counter_incr {} {
if {[info exists ::decent_scale_tare_counter] != 1} {
set ::decent_scale_tare_counter 0
} elseif {$::decent_scale_tare_counter >= 255} {
set ::decent_scale_tare_counter 0
} else {
incr ::decent_scale_tare_counter
}
# alternatively: the tare counter can in fact be any not-recently-used integer, such as this random digit-picker
# set ::decent_scale_tare_counter [expr {int(rand() * 255)}]
}
proc decent_scale_tare_cmd {} {
tare_counter_incr
set cmd [decent_scale_make_command "0F" [format %02X $::decent_scale_tare_counter]]
return $cmd
}
Decent秤将在发出去皮命令后发回应答。
该应答具有以下结构:
第一个字节 | 第二个字节 | 第三个字节 | 第四个字节 | 第五个字节 | 第六个字节 | 第七个字节 |
型号 03 = Decent | 类型 0F | Data (1) 去皮计数器 | Data (2) 00 | Data (3) 00 | Data (4) FE | 异或验证 |
发送命令以打开或关闭LED显示
第一个字节 | 第二个字节 | 第三个字节 | 第四个字节 | 第五个字节 | 第六个字节 | 第七个字节 |
型号 03 = Decent | 类型 0A | Data (1) 重量LED显示开/关 00=关 01=开 02=关机 | Data (2) 计时器LED显示开/关 00=关 01=开 | Data (3) 00=克 01=盎司 | Data (4) 00 | 异或验证 计算 |
注意:
- 保持LED显示关闭可延长电池寿命。
- 即使两个LED显示都关闭,秤仍将继续工作。
- 固件v1.2中增加了关机命令。
- 显示“重量变化”的单个LED 将亮起,即使两个LED都已关闭。
- 从v1.1固件开始,方形按钮上方的LED在重量变化时不再亮起。
- 而当按下任一按钮时,该LED会亮起。
- 这是为了向用户提供视觉反馈,即秤已感应到按钮按下。
示例:使用克单位时,所有LED亮起命令:
03 0A 01 01 00 00 09
示例:使用盎司单位时,所有LED亮起命令:[需要 v1.1 固件]
03 0A 01 01 01 00 08
示例:所有LED关闭命令:
03 0A 00 00 00 00 09
示例:关机命令:
03 0A 02 00 00 00 0B
在LED开/关命令(固件 v1.1)后,Decent秤将在重量数据反馈中发回应答,包括克与盎司信息、电池电量和固件版本。
数据结构如下:
第一个字节 | 第二个字节 | 第三个字节 | 第四个字节 | 第五个字节 | 第六个字节 | 第七个字节 |
型号 03 = Decent | 类型 0A | Data (1) 00 | Data (2) 显示的重量单位 00=克
01=盎司 | Data (3) 电池电量 在3%(低电量)和100%(满电)之间。 FF (255) = USB供电 | Data (4) 固件版本
FE=V1.0 02=V1.1 03=v1.2固件版本 | 异或验证 |
由于电子秤PCB的限制,电池电量始终会显示100%。 |
以下是从Light Blue app应用日志中读取电池电量的示例:
16:02:36.005 - 特征(36F5)写入新值: <030a0101 000009> (我们使用应用程序发送此值,打开LED)
16:02:36.061 - 特征(36F5)读取:(空)
16:02:36.135 - 特征 (FFF4) 通知: 030a0000 64026f (64 hex = 100%, 使用电池运行
15:59:50.421 - 特征(36F5)写入新值: <030a0101 000009> (我们使用应用程序发送此值,打开LED)
15:59:50.485 - 特征(36F5)读取:(空)
15:59:50.522 - 特征 (FFF4) 通知: 030a0000ff0ac7 (FF 十六进制 = 255%,使用USB电源供电)
发送命令来控制计时器
第一个字节 | 第二个字节 | 第三个字节 | 第四个字节 | 第五个字节 | 第六个字节 | 第七个字节 |
型号 03 = Decent | 类型 0B | Data (1) 计时开始/停止/重置
00=停止 02=重置归零 03=开始 | Data (2) 00 | Data (3) 00 | Data (4) 00 | 异或验证 计算 |
例如:计时开始命令
03 0B 03 00 00 00 0B
例如:计时停止命令
03 0B 00 00 00 00 08
例如:计时重置命令
03 0B 02 00 00 00 0A
用于从Decent秤接收各种数据的大型示例代码
Github上更大的bluetooth.tcl示例
以下代码(使用 Tcl 语言,但希望您能理解)可以实现:
- 接收重量信息
- 接收按键操作信息
- 接收当前时间值
set ::de1(cuuid_decentscale_read) "0000FFF4-0000-1000-8000-00805F9B34FB"
set ::de1(cuuid_decentscale_write) "000036F5-0000-1000-8000-00805F9B34FB"
set ::de1(cuuid_decentscale_writeback) "83CDC3D4-3BA2-13FC-CC5E-106C351A9352"
if {$cuuid eq $::de1(cuuid_decentscale_read)} {
# decent scale
parse_decent_scale_recv $value weightarray
if {[ifexists weightarray(command)] == [expr 0x0F] && [ifexists weightarray(data6)] == [expr 0xFE]} {
# tare cmd success is a msg back to us with the tare in 'command', and a byte6 of 0xFE
msg "- decent scale: tare confirmed"
return
} elseif {[ifexists weightarray(command)] == 0xAA} {
msg "Decentscale BUTTON $weightarray(data3) pressed"
if {[ifexists $weightarray(data3)] == 1} {
# button 1 "O" pressed
decentscale_tare
} elseif {[ifexists $weightarray(data3)] == 2} {
# button 2 "[]" pressed
}
} elseif {[ifexists weightarray(command)] != ""} {
msg "scale command received: [array get weightarray]"
}
if {[info exists weightarray(weight)] == 1} {
set sensorweight [expr {$weightarray(weight) / 10.0}]
#msg "decent scale: ${sensorweight}g [array get weightarray] '[convert_string_to_hex $value]'"
#msg "decentscale recv read: '[convert_string_to_hex $value]'"
::device::scale::process_weight_update $sensorweight $event_time
} else {
msg "decent scale recv: [array get weightarray]"
}
}
proc parse_decent_scale_recv {packed destarrname} {
upvar $destarrname recv
unset -nocomplain recv
::fields::unpack $packed [decent_scale_generic_read_spec] recv bigeendian
if {$recv(command) == 0xCE || $recv(command) == 0xCA} {
unset -nocomplain recv
::fields::unpack $packed [decent_scale_weight_read_spec2] recv bigeendian
} elseif {$recv(command) == 0xAA} {
msg "Decentscale BUTTON pressed: [array get recv]"
} elseif {$recv(command) == 0x0C} {
unset -nocomplain recv
::fields::unpack $packed [decent_scale_timing_read_spec] recv bigeendian
msg "Decentscale time received: [array get recv]"
}
}
proc decent_scale_generic_read_spec {} {
set spec {
model {char {} {} {unsigned} {}}
command {char {} {} {unsigned} {}}
data3 {char {} {} {unsigned} {}}
data4 {char {} {} {unsigned} {}}
data5 {char {} {} {unsigned} {}}
data6 {char {} {} {unsigned} {}}
xor {char {} {} {unsigned} {}}
}
return $spec
}
proc decent_scale_weight_read_spec2 {} {
set spec {
model {char {} {} {unsigned} {}}
wtype {char {} {} {unsigned} {}}
weight {Short {} {} {signed} {}}
rate {Short {} {} {unsigned} {}}
xor {char {} {} {unsigned} {}}
}
return $spec
}