package m9z import ( "encoding/binary" "fmt" "strconv" "strings" "github.com/gogf/gf/v2/util/gconv" ) // LoopCommonParameters 回路分控器公共参数结构体 (15个寄存器 = 30字节) type LoopCommonParameters struct { DCVoltage float32 // 直流电压 (0.1V单位) DCCurrent float32 // 直流电流 (0.001A单位) 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字节) } type LoopFault struct { LoopIdx uint `json:"loop_idx"` DeviceIdx uint `json:"device_idx,omitempty"` Type string `json:"type"` Message string `json:"message"` Code string `json:"code"` } func BuildLoopFaults(loopIdx uint, alarmStatus uint16, alarmCode string) []LoopFault { status := byte(alarmStatus) if status == 0 { return nil } faults := make([]LoopFault, 0, 3) if status&0x01 != 0 { faults = append(faults, LoopFault{ LoopIdx: loopIdx, Type: "short_circuit", Message: fmt.Sprintf("回路%d短路故障", loopIdx), Code: "01", }) } if status&0x02 != 0 { faults = append(faults, LoopFault{ LoopIdx: loopIdx, Type: "open_circuit", Message: fmt.Sprintf("回路%d开路故障", loopIdx), Code: "02", }) } if status&0x04 != 0 { deviceMask := alarmDeviceMask(alarmCode) faults = append(faults, LoopFault{ LoopIdx: loopIdx, Type: "power", Message: buildPowerFaultMessage(loopIdx, deviceMask), Code: fmt.Sprintf("04 %02X", deviceMask), }) } if unknownStatus := status &^ 0x07; unknownStatus != 0 { faults = append(faults, LoopFault{ LoopIdx: loopIdx, Type: "unknown", Message: fmt.Sprintf("回路%d未知异常", loopIdx), Code: strings.TrimSpace(alarmCode), }) } return faults } func alarmDeviceMask(alarmCode string) byte { fields := strings.Fields(alarmCode) if len(fields) < 2 { return 0 } value, err := strconv.ParseUint(fields[1], 16, 8) if err != nil { return 0 } return byte(value) } func buildPowerFaultMessage(loopIdx uint, deviceMask byte) string { deviceNames := make([]string, 0, 8) for i := 0; i < 8; i++ { if deviceMask&(1<