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.

100 lines
2.7 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 (
"encoding/binary"
"fmt"
"github.com/towgo/towgo/errors/terror"
"tgk-touch/internal/global"
)
type DeviceConfig struct {
Latitude float64 // 纬度(实际值)
Longitude float64 // 经度(实际值)
TimezoneOffset float64 // 时区偏移(实际值,单位小时,如 UTC+8 为 8.0)
SunriseAdjust int // 日出偏差调整(分钟)
SunsetAdjust int // 日落偏差调整(分钟)
ProgrammingMode uint8 // 编程模式 0-2
RS485Address uint8 // 485地址 (默认0x01)
}
// todo 和实际有出入
func DeviceConfigRead(deviceId string) (*DeviceConfig, error) {
cmd, err := ReadCmd(deviceId, deviceConfig, "设备配置读取")
if err != nil {
return nil, err
}
data := cmd.Data
// 数据长度校验(至少18字节)
if len(data) < 18 {
return nil, fmt.Errorf("invalid config data length: %d", len(data))
}
dc := &DeviceConfig{}
// 1. 解析纬度(Byte0-3,小端序int32)
latInt := float64(binary.LittleEndian.Uint32(data[0:4]))
dc.Latitude = float64(latInt) / 1_000_000
// 2. 解析经度(Byte4-7,小端序int32)
lngInt := float64(binary.LittleEndian.Uint32(data[4:8]))
dc.Longitude = float64(lngInt) / 1_000_000
// 3. 解析时区偏移(Byte8-11,小端序int32)
tzInt := float64(binary.LittleEndian.Uint32(data[8:12]))
dc.TimezoneOffset = float64(tzInt) / 1_000_000
// 4. 日出/日落调整(Byte12-13)
g.Log().Infof("日出日落偏差2% X", data[12:14])
dc.SunriseAdjust = int(data[12])
dc.SunsetAdjust = int(data[13])
// 5. 编程模式(Byte16)
dc.ProgrammingMode = data[16]
// 6. 485地址(Byte17)
dc.RS485Address = data[17]
return dc, nil
}
func DeviceConfigWrite(deviceId string, dc *DeviceConfig) error {
// 构造18字节数据缓冲区
buf := make([]byte, 18)
// 1. 编码纬度(扩大1,000,000倍)
latInt := int32(dc.Latitude * 1_000_000)
binary.LittleEndian.PutUint32(buf[0:4], uint32(latInt))
// 2. 编码经度
lngInt := int32(dc.Longitude * 1_000_000)
binary.LittleEndian.PutUint32(buf[4:8], uint32(lngInt))
// 3. 编码时区偏移
tzInt := int32(dc.TimezoneOffset * 1_000_000)
binary.LittleEndian.PutUint32(buf[8:12], uint32(tzInt))
// 4. 日出/日落调整
buf[12] = byte(dc.SunriseAdjust)
buf[13] = byte(dc.SunsetAdjust)
// 5. 备用字段(Byte14-15)填充0
binary.LittleEndian.PutUint16(buf[14:16], 0)
// 6. 编程模式
buf[16] = dc.ProgrammingMode
// 7. 485地址
buf[17] = dc.RS485Address
// 发送写入命令
writeResp, err := WriteCmd(deviceId, deviceConfig, buf, "设备配置写入")
if err != nil {
return err
}
if !writeResp.Success {
return terror.New("写入失败")
}
return nil
}