gh-5 Fetch register data from bus

- goburrow/modbus' ReadHoldingRegisters can only fetch 125 registers at a
time, so updateRegisters does several readings
- modbus.ReadHoldingRegisters returns a []byte, where each even byte represents
  the MSB of a int16/uint16 and every odd byte is the LSB
- updateRegisters loops through each response slice forming the 16-bit
  integers

Still need to figure out a way to properly handle the signed/unsigned
values, and also the enumerations and bitfields. Perhaps changing the
'signed' boolean to a byte and making that a bitfield representing the
value type would be a good way to go. The value can then be properly
formed when fetching it from the in-memory pingvinKL struct, while being
stored as an int(64) internally.
This commit is contained in:
Jarno Rankinen 2023-01-31 23:49:09 +02:00
parent 9f2d4b0c29
commit f4eb787a10
1 changed files with 46 additions and 10 deletions

View File

@ -30,13 +30,12 @@ type PingvinKL struct {
// single register data
type pingvinRegister struct {
Address int `json:"address"`
Symbol string `json:"symbol"`
Value_signed int16 `json:"value_signed"`
Value_unsigned uint16 `json:"value_unsigned"`
Signed bool `json:"signed"`
Description string `json:"description"`
Reserved bool `json:"reserved"`
Address int `json:"address"`
Symbol string `json:"symbol"`
Value int `json:"value"`
Signed bool `json:"signed"`
Description string `json:"description"`
Reserved bool `json:"reserved"`
}
func newCoil(address string, symbol string, description string) pingvinCoil {
@ -55,7 +54,7 @@ func newRegister(address string, symbol string, signed bool, description string)
log.Fatal("newRegister: Atio: ")
}
reserved := symbol == "Reserved" && description == "Reserved"
register := pingvinRegister{addr, symbol, 0, 0, signed, description, reserved}
register := pingvinRegister{addr, symbol, 0, signed, description, reserved}
return register
}
@ -97,13 +96,13 @@ func (p PingvinKL) updateCoils() {
p.buslock.Lock()
err := handler.Connect()
if err != nil {
log.Fatal("Update: handler.Connect: ", err)
log.Fatal("updateCoils: handler.Connect: ", err)
}
defer handler.Close()
client := modbus.NewClient(handler)
results, err := client.ReadCoils(0, uint16(len(p.Coils)))
if err != nil {
log.Fatal("Update: client.ReadCoils: ", err)
log.Fatal("updateCoils: client.ReadCoils: ", err)
}
p.buslock.Unlock()
// modbus.ReadCoils returns a byte array, with the first byte's bits representing coil values 0-7,
@ -125,8 +124,45 @@ func (p PingvinKL) updateCoils() {
}
}
func (p PingvinKL) updateRegisters() {
handler := p.getHandler()
p.buslock.Lock()
err := handler.Connect()
if err != nil {
log.Fatal("updateRegisters: handler.Connect: ", err)
}
defer handler.Close()
client := modbus.NewClient(handler)
regs := len(p.Registers)
k := 0
for k < regs {
r := 125
if regs-k < 125 {
r = regs - k
}
results, err := client.ReadHoldingRegisters(uint16(k), uint16(r))
if err != nil {
log.Fatal("updateRegisters: client.ReadCoils: ", err)
}
msb := true
value := 0
for i := 0; i < len(results); i++ {
if msb {
value = int(results[i]) << 8
} else {
value += int(results[i])
p.Registers[k].Value = value
k++
}
msb = !msb
}
}
p.buslock.Unlock()
}
func (p PingvinKL) Update() {
p.updateCoils()
p.updateRegisters()
}
func (p PingvinKL) ReadCoil(n uint16) []byte {