package mitsubishi import ( "fmt" "strconv" "unicode" ) // ProtocolMitsubishi 实现了 SerialProtocol 接口,用于三菱设备的串口通信 type ProtocolMitsubishi struct{} // ConvertLabelToAddress 将设备特定的标签转换为寄存器地址 func (p *ProtocolMitsubishi) ConvertLabelToAddress(label string) string { if label[0] != 'D' { return "" } num := label[1:] for _, c := range num { if !unicode.IsDigit(c) { return "" } } var val int fmt.Sscanf(num, "%d", &val) vaddr := 0x1000 + val*2 return fmt.Sprintf("%X", vaddr) } // MakeReadProtocol 创建读取数据的协议 func (p *ProtocolMitsubishi) MakeReadProtocol(addr string) []byte { // 02 表示开始 + 30 表示读数据 + 4位地址位 + 02 数据长度 + 03 停止 + 偶校验 pro := []byte{0x30} pro = append(pro, []byte(addr)...) pro = append(pro, []byte("02")...) pro = append(pro, []byte{0x03}...) crc := crc(pro) proto := []byte{0x02} proto = append(proto, pro...) proto = append(proto, []byte(crc)...) return proto } // MakeWriteProtocol 创建写入数据的协议 func (p *ProtocolMitsubishi) MakeWriteProtocol(addr string, value int) []byte { valueStr := fmt.Sprintf("000%X", value) val := valueStr[len(valueStr)-2:] val += valueStr[len(valueStr)-4 : len(valueStr)-2] // 02 表示开始 + 31 表示写数据 + 4位地址位 + 02 数据长度 + 03 停止 + 偶校验 pro := []byte{0x31} pro = append(pro, []byte(addr)...) pro = append(pro, []byte("02")...) pro = append(pro, val...) pro = append(pro, []byte{0x03}...) crc := crc(pro) proto := []byte{0x02} proto = append(proto, pro...) proto = append(proto, []byte(crc)...) return proto } // ParseReadValue 解析从设备读取的值 func (p *ProtocolMitsubishi) ParseReadValue(data []byte) int { if len(data) < 6 { return -1 } vhex := data[1:5] v := vhex[2:] v = append(v, vhex[0:2]...) vstr := string(v) var bint int64 bint, _ = strconv.ParseInt(vstr, 16, 32) return int(bint) } // ParseWriteValue 解析写入设备的结果 func (p *ProtocolMitsubishi) ParseWriteValue(data []byte) (v int, ok bool) { if len(data) == 0 { return -1, false } v = int(data[0]) if v == 0x15 { // 失败 return v, false } if v == 0x06 { // 成功 return v, ok } return v, false } // crc 取后两位0x值 func crc(data []byte) string { // 计算校验码, 30 + 地址编码 + 数据长度 + 03 , 十六进制结果取后两位. var sum uint8 for _, d := range data { sum += d } sumStr := fmt.Sprintf("0%X", sum) return sumStr[len(sumStr)-2:] }