You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

121 lines
4.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package m9z
import (
"bytes"
"fmt"
"github.com/towgo/towgo/errors/terror"
)
// 对应C的db_ble_extern_t结构体(简化版,使用bool型Enable)
type BluetoothConfig struct {
Enable bool // 离线监控使能(false=禁止,true=允许/0xAA)
OfflineMin uint8 // 离线时间(分钟数)
BleName string // 蓝牙名称(最大20字节) 不支持中文
}
func BluetoothRead(deviceId string) (*BluetoothConfig, error) {
// 1. 读取指令
cmd, err := ReadCmd(deviceId, bluetooth, "设备蓝牙配置读取")
if err != nil {
errMsg := fmt.Sprintf("读取设备%s蓝牙配置失败: %v", deviceId, err)
return nil, terror.New(errMsg)
}
data := cmd.Data
// 2. 校验基础长度(至少2字节:离线监控+离线时间)
const minDataLen = 2
if len(data) < minDataLen {
errMsg := fmt.Sprintf("蓝牙配置数据长度不足,至少需要%d字节,实际收到%d字节", minDataLen, len(data))
return nil, terror.New(errMsg)
}
// 3. 解析基础字段(固定2字节)
var bleConfig BluetoothConfig
bleConfig.Enable = data[0] == 0xAA // 0xAA对应true(允许),其他为false(禁止)
bleConfig.OfflineMin = data[1] // 离线时间
// 4. 解析蓝牙名称(动态长度,最多20字节)
nameBytes := data[2:] // 取基础字段后的所有字节
if len(nameBytes) > 20 {
nameBytes = nameBytes[:20] // 超过20字节则截断
}
// 去掉名称末尾的空字符(设备返回的结束符)
bleConfig.BleName = string(bytes.TrimRight(nameBytes, "\x00"))
return &bleConfig, nil
}
// BluetoothWrite 写入蓝牙配置到设备(修复所有核心问题)
func BluetoothWrite(deviceId string, bleConfig *BluetoothConfig) error {
// 1. 精准参数校验(拆分判断,提示语匹配)
if bleConfig == nil {
errMsg := "蓝牙配置结构体为nil,无法写入"
return terror.New(errMsg)
}
nameBytes := []byte(bleConfig.BleName)
if len(nameBytes) > 20 {
errMsg := fmt.Sprintf("蓝牙名称超长,最大支持20字节,实际传入%d字节", len(nameBytes))
return terror.New(errMsg)
}
// 校验1:是否包含中文/非ASCII字符
if hasChinese(bleConfig.BleName) {
errMsg := fmt.Sprintf("设备[%s]蓝牙名称包含中文/非ASCII字符,仅支持英文/数字/符号等ASCII字符", deviceId)
return terror.New(errMsg)
}
// 2. 构造缓冲区:2字节基础字段 + 动态长度蓝牙名称
buf := make([]byte, 2) // 先初始化基础字段缓冲区
// 编码离线监控使能(Byte0:0=禁止,0xAA=允许)
if bleConfig.Enable {
buf[0] = 0xAA
} else {
buf[0] = 0x00
}
// 编码离线时间(Byte1)
buf[1] = bleConfig.OfflineMin
// 追加蓝牙名称(仅追加一次,修复重复追加问题)
buf = append(buf, nameBytes...)
// 调试日志:打印最终缓冲区(长度+十六进制)
//g.Log().Debugf("Bluetooth Write raw data: len=%d , hex=% X", len(buf), buf)
// 3. 发送写入命令
writeResp, err := WriteCmd(deviceId, bluetooth, buf, "设备蓝牙配置写入")
if err != nil {
errMsg := fmt.Sprintf("设备[%s]蓝牙配置写入命令调用失败", deviceId)
return terror.Wrapf(err, errMsg)
}
// 4. 检查写入响应状态(修复err为nil的问题)
if !writeResp.Success {
errMsg := fmt.Sprintf("设备[%s]蓝牙配置写入失败,响应状态为失败", deviceId)
// 手动构造错误,避免Wrapf传入nil
return terror.New(errMsg)
}
// 5. 写入成功日志(修复切片越界问题:用buf[2:]而非固定22)
//bleNameStr := string(bytes.TrimRight(buf[2:], "\x00"))
//g.Log().Infof("设备%s蓝牙配置写入成功,离线监控使能:%v,离线时间:%d分钟,蓝牙名称:%s",
// deviceId, bleConfig.Enable, bleConfig.OfflineMin, bleNameStr)
return nil
}
// hasChinese 辅助函数:判断字符串是否包含中文(或非ASCII字符)
func hasChinese(s string) bool {
for _, r := range s {
// 中文Unicode范围:0x4E00-0x9FFF,同时拦截所有>127的非ASCII字符
if r > 127 || (r >= 0x4E00 && r <= 0x9FFF) {
return true
}
}
return false
}