You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ntool-biz/nmodbus/handler/functions.go

146 lines
4.5 KiB
Go

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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)
for i, value := range s.Coils[register:endRegister] {
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)
for i, value := range s.DiscreteInputs[register:endRegister] {
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
}
return append([]byte{byte(numRegs * 2)}, util.Uint16ToBytes(s.byteOrder, s.HoldingRegisters[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
}
return append([]byte{byte(numRegs * 2)}, util.Uint16ToBytes(s.byteOrder, s.InputRegisters[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
}
s.Coils[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)
s.HoldingRegisters[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
//}
bitCount := 0
for i, value := range valueBytes {
for bitPos := uint(0); bitPos < 8; bitPos++ {
s.Coils[register+(i*8)+int(bitPos)] = util.BitAtPosition(value, bitPos)
bitCount++
if bitCount >= numRegs {
break
}
}
if bitCount >= numRegs {
break
}
}
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)
valuesUpdated := copy(s.HoldingRegisters[register:], values)
if valuesUpdated == numRegs {
err = &protocol.Success
data = pkgData[0:4]
} else {
err = &protocol.IllegalDataAddress
}
return data, err
}