|
|
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
|
|
|
}
|