package handler import ( "git.noahlan.cn/noahlan/ntool-biz/nmodbus/protocol" "git.noahlan.cn/noahlan/ntool-biz/nmodbus/serialize" "git.noahlan.cn/noahlan/ntool-biz/nmodbus/util" ) // ReadCoils 读线圈寄存器(DO) 功能码0x01 func ReadCoils(s *Handler, packet protocol.Packet) ([]byte, *protocol.MError) { register, numRegs, endRegister := serialize.RegisterAddressAndNumber(packet.GetBody()) if endRegister > 65535 { return []byte{}, &protocol.IllegalDataAddress } // 一个寄存器2字节 dataSize := numRegs / 8 if (numRegs % 8) != 0 { dataSize++ } data := make([]byte, 1+dataSize) data[0] = byte(dataSize) dataMgr := s.DataManager(packet.GetAddress()) coils := dataMgr.ReadCoils(register, endRegister) for i, value := range coils { if value != 0 { shift := uint(i) % 8 data[1+i/8] |= byte(1 << shift) } } return data, &protocol.Success } // ReadDiscreteInputs 读离散输入寄存器(DI) 功能码0x02 func ReadDiscreteInputs(s *Handler, packet protocol.Packet) ([]byte, *protocol.MError) { register, numRegs, endRegister := serialize.RegisterAddressAndNumber(packet.GetBody()) if endRegister > 65535 { return []byte{}, &protocol.IllegalDataAddress } dataSize := numRegs / 8 if (numRegs % 8) != 0 { dataSize++ } data := make([]byte, 1+dataSize) data[0] = byte(dataSize) dataMgr := s.DataManager(packet.GetAddress()) discreteInputs := dataMgr.ReadDiscreteInputs(register, endRegister) for i, value := range discreteInputs { if value != 0 { shift := uint(i) % 8 data[1+i/8] |= byte(1 << shift) } } return data, &protocol.Success } // ReadHoldingRegisters 读保持寄存器(AI) 功能码0x03 func ReadHoldingRegisters(s *Handler, packet protocol.Packet) ([]byte, *protocol.MError) { register, numRegs, endRegister := serialize.RegisterAddressAndNumber(packet.GetBody()) if endRegister > 65536 { return []byte{}, &protocol.IllegalDataAddress } dataMgr := s.DataManager(packet.GetAddress()) return append([]byte{byte(numRegs * 2)}, util.Uint16ToBytes(s.byteOrder, dataMgr.ReadHoldingRegisters(register, endRegister))...), &protocol.Success } // ReadInputRegisters 读输入寄存器(AO) 功能码0x04 func ReadInputRegisters(s *Handler, packet protocol.Packet) ([]byte, *protocol.MError) { register, numRegs, endRegister := serialize.RegisterAddressAndNumber(packet.GetBody()) if endRegister > 65536 { return []byte{}, &protocol.IllegalDataAddress } dataMgr := s.DataManager(packet.GetAddress()) return append([]byte{byte(numRegs * 2)}, util.Uint16ToBytes(s.byteOrder, dataMgr.ReadInputRegisters(register, endRegister))...), &protocol.Success } // WriteSingleCoil 写单个线圈寄存器 功能码0x05 func WriteSingleCoil(s *Handler, packet protocol.Packet) ([]byte, *protocol.MError) { data := packet.GetBody() register, value := serialize.RegisterAddressAndValue(data) // TODO Should we use 0 for off and 65,280 (0xFF00) for on? if value != 0 { value = 1 } dataMgr := s.DataManager(packet.GetAddress()) dataMgr.WriteSingleCoil(register, byte(value)) return data[0:4], &protocol.Success } // WriteHoldingRegister 写单个保持寄存器 功能码0x06 func WriteHoldingRegister(s *Handler, packet protocol.Packet) ([]byte, *protocol.MError) { data := packet.GetBody() register, value := serialize.RegisterAddressAndValue(data) dataMgr := s.DataManager(packet.GetAddress()) dataMgr.WriteSingleHoldingRegister(register, value) return data[0:4], &protocol.Success } // WriteMultipleCoils 写多个线圈寄存器 功能码 0x0F=15 func WriteMultipleCoils(s *Handler, packet protocol.Packet) ([]byte, *protocol.MError) { data := packet.GetBody() register, numRegs, endRegister := serialize.RegisterAddressAndNumber(data) valueBytes := data[5:] if endRegister > 65536 { return []byte{}, &protocol.IllegalDataAddress } // TODO This is not correct, bits and bytes do not always align //if len(valueBytes)/2 != numRegs { // return []byte{}, &IllegalDataAddress //} idxList := make([]int, 0) values := make([]byte, 0) bitCount := 0 for i, value := range valueBytes { for bitPos := uint(0); bitPos < 8; bitPos++ { idxList = append(idxList, register+(i*8)+int(bitPos)) values = append(values, util.BitAtPosition(value, bitPos)) bitCount++ if bitCount >= numRegs { break } } if bitCount >= numRegs { break } } dataMgr := s.DataManager(packet.GetAddress()) dataMgr.WriteCoils(idxList, values) return data[0:4], &protocol.Success } // WriteHoldingRegisters 写入 多个保持寄存器 功能码 0x10=16 func WriteHoldingRegisters(s *Handler, packet protocol.Packet) ([]byte, *protocol.MError) { pkgData := packet.GetBody() register, numRegs, _ := serialize.RegisterAddressAndNumber(packet.GetBody()) valueBytes := pkgData[5:] var err *protocol.MError var data []byte if len(valueBytes)/2 != numRegs { err = &protocol.IllegalDataAddress } // Copy data to memory values := util.BytesToUint16(s.byteOrder, valueBytes) dataMgr := s.DataManager(packet.GetAddress()) valuesUpdated := dataMgr.WriteHoldingRegisters(values, register) if valuesUpdated == numRegs { err = &protocol.Success data = pkgData[0:4] } else { err = &protocol.IllegalDataAddress } return data, err }