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.
124 lines
4.9 KiB
124 lines
4.9 KiB
package m9z
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
"github.com/gogf/gf/v2/util/gconv"
|
|
)
|
|
|
|
// LoopCommonParameters 回路分控器公共参数结构体 (15个寄存器 = 30字节)
|
|
type LoopCommonParameters struct {
|
|
DCVoltage float32 // 直流电压 (0.1V单位)
|
|
DCCurrent float32 // 直流电流 (0.1A单位)
|
|
DimmingValue float32 // 调光幅度值 (0-100%)
|
|
AlarmStatus uint16 // 告警状态 (位图形式) 告警状态寄存器 0x01欠压 0x02过压 0x08电源故障 其中:欠压=短路故障,过压=开路故障,电源故障。
|
|
AlarmCode string // 告警代码
|
|
RelayStatus uint16 // 继电器状态 (位图形式)
|
|
LoopAddress string // 回路地址
|
|
SubModuleCount uint16 // 子模块数量
|
|
Reserved [14]byte // 备用字段 (7个寄存器=14字节)
|
|
}
|
|
|
|
// LoopModuleParameters 回路子模块参数结构体 (13个寄存器 = 26字节)
|
|
type LoopModuleParameters struct {
|
|
OutputVoltage float32 // 模块输出电压值 (0.1V)
|
|
OutputCurrent float32 // 模块输出电流值 (0.01A)
|
|
CurrentPWMDuty float32 // 模块电流PWM占空比 (0-10000对应0-100%)
|
|
VoltagePWMDuty float32 // 模块电压PWM占空比 (0-10000对应0-100%)
|
|
DeviceAddress string // 模块的设备地址
|
|
ModuleLoopAddress string // 模块的回路地址
|
|
CurrentLimitPct float32 // 模块的限流百分数 (0-100对应0-100%)
|
|
OperatingMode uint16 // 模块手动/自动模式 (0=自动,1=手动)
|
|
ModuleVersion float32 // 模块的版本号
|
|
RatedVoltageDuty uint16 // 额定配置电压PWM占空比 (0-10000对应0-100%)
|
|
RatedCurrentDuty uint16 // 额定配置电流PWM占空比 (0-10000对应0-100%)
|
|
RatedOutputVoltage uint16 // 额定配置输出电压值 (0.1V)
|
|
RatedOutputCurrent uint16 // 额定配置输出电流值 (0.01A)
|
|
}
|
|
|
|
// LoopFullParameters 完整回路参数数据结构
|
|
type LoopFullParameters struct {
|
|
LoopCommonParameters // 公共参数 (30字节)
|
|
Modules []LoopModuleParameters // 8个模块的参数 (208字节)
|
|
}
|
|
|
|
// ParseLoopFullParameters 解析完整的238字节分控器数据
|
|
func ParseLoopFullParameters(data []byte) (*LoopFullParameters, error) {
|
|
if len(data) < 238 {
|
|
return nil, fmt.Errorf("invalid data length %d, expected 238 bytes", len(data))
|
|
}
|
|
|
|
params := &LoopFullParameters{}
|
|
offset := 0
|
|
|
|
// 解析公共参数区 (30字节)
|
|
common := ¶ms.LoopCommonParameters
|
|
|
|
common.DCVoltage = float32(binary.LittleEndian.Uint16(data[offset:])) * 0.1
|
|
offset += 2
|
|
common.DCCurrent = float32(binary.LittleEndian.Uint16(data[offset:])) * 0.1
|
|
offset += 2
|
|
common.DimmingValue = float32(binary.LittleEndian.Uint16(data[offset:])) * 10 * 0.01
|
|
offset += 2
|
|
//log.Debugf("AlarmStatus [% X]", data)
|
|
common.AlarmStatus = uint16(data[offset:][0])
|
|
common.AlarmCode = fmt.Sprintf("% X", data[offset:offset+2])
|
|
offset += 2
|
|
common.RelayStatus = binary.LittleEndian.Uint16(data[offset:])
|
|
offset += 2
|
|
if binary.LittleEndian.Uint16(data[offset:]) == 0 {
|
|
return nil, nil
|
|
}
|
|
common.LoopAddress = fmt.Sprintf("0x%x", binary.LittleEndian.Uint16(data[offset:]))
|
|
|
|
offset += 2
|
|
common.SubModuleCount = binary.LittleEndian.Uint16(data[offset:])
|
|
offset += 2
|
|
copy(common.Reserved[:], data[offset:offset+16])
|
|
offset += 16
|
|
params.Modules = make([]LoopModuleParameters, common.SubModuleCount)
|
|
// 解析8个模块 (每个26字节)
|
|
for i := 0; i < int(common.SubModuleCount); i++ {
|
|
module := ¶ms.Modules[i]
|
|
module.OutputVoltage = float32(binary.LittleEndian.Uint16(data[offset:])) * 0.1
|
|
offset += 2
|
|
module.OutputCurrent = float32(binary.LittleEndian.Uint16(data[offset:])) * 0.1
|
|
offset += 2
|
|
module.CurrentPWMDuty = float32(binary.LittleEndian.Uint16(data[offset:])) * 10 * 0.01
|
|
offset += 2
|
|
module.VoltagePWMDuty = float32(binary.LittleEndian.Uint16(data[offset:])) * 10 * 0.01
|
|
offset += 2
|
|
module.DeviceAddress = fmt.Sprintf("0x%x", binary.LittleEndian.Uint16(data[offset:]))
|
|
offset += 2
|
|
module.ModuleLoopAddress = fmt.Sprintf("0x%x", binary.LittleEndian.Uint16(data[offset:]))
|
|
offset += 2
|
|
module.CurrentLimitPct = float32(binary.LittleEndian.Uint16(data[offset:])) * 0.1
|
|
offset += 2
|
|
module.OperatingMode = binary.LittleEndian.Uint16(data[offset:])
|
|
offset += 2
|
|
version := fmt.Sprintf("%x", binary.LittleEndian.Uint16(data[offset:]))
|
|
floatVersion := gconv.Float32(version)
|
|
module.ModuleVersion = floatVersion * 0.1
|
|
offset += 2
|
|
module.RatedVoltageDuty = binary.LittleEndian.Uint16(data[offset:])
|
|
offset += 2
|
|
module.RatedCurrentDuty = binary.LittleEndian.Uint16(data[offset:])
|
|
offset += 2
|
|
module.RatedOutputVoltage = binary.LittleEndian.Uint16(data[offset:])
|
|
offset += 2
|
|
module.RatedOutputCurrent = binary.LittleEndian.Uint16(data[offset:])
|
|
offset += 2
|
|
}
|
|
|
|
return params, nil
|
|
}
|
|
|
|
func SubLoopParametersRead(device string, idx uint) (*LoopFullParameters, error) {
|
|
readRep, err := ReadCmd(device, subLoopParameters, "读取回路分控器的参数", idx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return ParseLoopFullParameters(readRep.Data)
|
|
}
|