gh-24 0.0.14 ReadCoil, WriteCoil, WriteCoils, andheckMutexCoils, now use common modbus.Client with proper locking
This commit is contained in:
parent
afcbe06581
commit
415bf638be
|
@ -22,7 +22,7 @@ import (
|
||||||
var static embed.FS
|
var static embed.FS
|
||||||
|
|
||||||
var (
|
var (
|
||||||
version = "0.0.13"
|
version = "0.0.14"
|
||||||
pingvin pingvinKL.PingvinKL
|
pingvin pingvinKL.PingvinKL
|
||||||
DEBUG *bool
|
DEBUG *bool
|
||||||
INTERVAL *int
|
INTERVAL *int
|
||||||
|
@ -166,4 +166,5 @@ func main() {
|
||||||
pingvin.Update()
|
pingvin.Update()
|
||||||
go pingvin.Monitor(*INTERVAL)
|
go pingvin.Monitor(*INTERVAL)
|
||||||
listen()
|
listen()
|
||||||
|
pingvin.Quit()
|
||||||
}
|
}
|
||||||
|
|
|
@ -240,6 +240,7 @@ func (p *PingvinKL) WriteRegister(addr uint16, value uint16) (uint16, error) {
|
||||||
return 0, fmt.Errorf("Failed to write register")
|
return 0, fmt.Errorf("Failed to write register")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update all holding register values
|
||||||
func (p *PingvinKL) updateRegisters() {
|
func (p *PingvinKL) updateRegisters() {
|
||||||
var err error
|
var err error
|
||||||
regs := len(p.Registers)
|
regs := len(p.Registers)
|
||||||
|
@ -305,47 +306,37 @@ func (p *PingvinKL) updateRegisters() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wrapper function for updating coils, registers and populating
|
||||||
|
// p.Status for Home Assistant
|
||||||
func (p *PingvinKL) Update() {
|
func (p *PingvinKL) Update() {
|
||||||
p.updateCoils()
|
p.updateCoils()
|
||||||
p.updateRegisters()
|
p.updateRegisters()
|
||||||
p.populateStatus()
|
p.populateStatus()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p PingvinKL) ReadCoil(n uint16) []byte {
|
// Read single coil
|
||||||
// handler := p.getHandler()
|
func (p PingvinKL) ReadCoil(n uint16) ([]byte, error) {
|
||||||
p.buslock.Lock()
|
p.buslock.Lock()
|
||||||
err := p.handler.Connect()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("ReadCoil: handler.Connect: ", err)
|
|
||||||
}
|
|
||||||
defer p.handler.Close()
|
|
||||||
// client := modbus.NewClient(handler)
|
|
||||||
results, err := p.modbusclient.ReadCoils(n, 1)
|
results, err := p.modbusclient.ReadCoils(n, 1)
|
||||||
p.buslock.Unlock()
|
p.buslock.Unlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("ReadCoil: client.ReadCoils: ", err)
|
log.Fatal("ReadCoil: client.ReadCoils: ", err)
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
p.Coils[n].Value = results[0] == 1
|
p.Coils[n].Value = results[0] == 1
|
||||||
return results
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Force a single coil
|
||||||
func (p *PingvinKL) WriteCoil(n uint16, val bool) bool {
|
func (p *PingvinKL) WriteCoil(n uint16, val bool) bool {
|
||||||
// handler := p.getHandler()
|
|
||||||
p.buslock.Lock()
|
|
||||||
err := p.handler.Connect()
|
|
||||||
if val {
|
if val {
|
||||||
p.checkMutexCoils(n, p.handler)
|
p.checkMutexCoils(n, p.handler)
|
||||||
}
|
}
|
||||||
if err != nil {
|
|
||||||
log.Println("WARNING: WriteCoil: failed to connect handler")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
defer p.handler.Close()
|
|
||||||
var value uint16 = 0
|
var value uint16 = 0
|
||||||
if val {
|
if val {
|
||||||
value = 0xff00
|
value = 0xff00
|
||||||
}
|
}
|
||||||
// client := modbus.NewClient(handler)
|
p.buslock.Lock()
|
||||||
results, err := p.modbusclient.WriteSingleCoil(n, value)
|
results, err := p.modbusclient.WriteSingleCoil(n, value)
|
||||||
p.buslock.Unlock()
|
p.buslock.Unlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -362,15 +353,8 @@ func (p *PingvinKL) WriteCoil(n uint16, val bool) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Force multiple coils
|
||||||
func (p *PingvinKL) WriteCoils(startaddr uint16, quantity uint16, vals []bool) error {
|
func (p *PingvinKL) WriteCoils(startaddr uint16, quantity uint16, vals []bool) error {
|
||||||
// handler := p.getHandler()
|
|
||||||
p.buslock.Lock()
|
|
||||||
err := p.handler.Connect()
|
|
||||||
if err != nil {
|
|
||||||
log.Println("WARNING: WriteCoils: failed to connect handler:", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer p.handler.Close()
|
|
||||||
p.updateCoils()
|
p.updateCoils()
|
||||||
coilslice := p.Coils[startaddr:(startaddr + quantity)]
|
coilslice := p.Coils[startaddr:(startaddr + quantity)]
|
||||||
if len(coilslice) != len(vals) {
|
if len(coilslice) != len(vals) {
|
||||||
|
@ -407,8 +391,8 @@ func (p *PingvinKL) WriteCoils(startaddr uint16, quantity uint16, vals []bool) e
|
||||||
}
|
}
|
||||||
p.Debug.Println("index:", i/8, "value:", bits[i/8], "shift:", i%8)
|
p.Debug.Println("index:", i/8, "value:", bits[i/8], "shift:", i%8)
|
||||||
}
|
}
|
||||||
log.Println(bits)
|
p.Debug.Println(bits)
|
||||||
// client := modbus.NewClient(handler)
|
p.buslock.Lock()
|
||||||
results, err := p.modbusclient.WriteMultipleCoils(startaddr, quantity, bits)
|
results, err := p.modbusclient.WriteMultipleCoils(startaddr, quantity, bits)
|
||||||
p.buslock.Unlock()
|
p.buslock.Unlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -419,12 +403,16 @@ func (p *PingvinKL) WriteCoils(startaddr uint16, quantity uint16, vals []bool) e
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Some of the coils are mutually exclusive, and can only be 1 one at a time.
|
||||||
|
// Check if coil is one of them and force all of them to 0 if so
|
||||||
func (p *PingvinKL) checkMutexCoils(addr uint16, handler *modbus.RTUClientHandler) error {
|
func (p *PingvinKL) checkMutexCoils(addr uint16, handler *modbus.RTUClientHandler) error {
|
||||||
for _, mutexcoil := range mutexcoils {
|
for _, mutexcoil := range mutexcoils {
|
||||||
if mutexcoil == addr {
|
if mutexcoil == addr {
|
||||||
for _, n := range mutexcoils {
|
for _, n := range mutexcoils {
|
||||||
if p.Coils[n].Value {
|
if p.Coils[n].Value {
|
||||||
|
p.buslock.Lock()
|
||||||
_, err := p.modbusclient.WriteSingleCoil(n, 0)
|
_, err := p.modbusclient.WriteSingleCoil(n, 0)
|
||||||
|
p.buslock.Unlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("ERROR: checkMutexCoils:", err)
|
log.Println("ERROR: checkMutexCoils:", err)
|
||||||
return err
|
return err
|
||||||
|
@ -437,6 +425,7 @@ func (p *PingvinKL) checkMutexCoils(addr uint16, handler *modbus.RTUClientHandle
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// populate p.Status struct for Home Assistant
|
||||||
func (p *PingvinKL) populateStatus() {
|
func (p *PingvinKL) populateStatus() {
|
||||||
hpct := p.Registers[49].Value / p.Registers[49].Multiplier
|
hpct := p.Registers[49].Value / p.Registers[49].Multiplier
|
||||||
if hpct > 100 {
|
if hpct > 100 {
|
||||||
|
@ -468,6 +457,7 @@ func (p *PingvinKL) populateStatus() {
|
||||||
p.Status.Coils = p.Coils
|
p.Status.Coils = p.Coils
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse readable status from integer (bitfield) value
|
||||||
func parseStatus(value int) string {
|
func parseStatus(value int) string {
|
||||||
val := int16(value)
|
val := int16(value)
|
||||||
pingvinStatuses := []string{
|
pingvinStatuses := []string{
|
||||||
|
|
Loading…
Reference in New Issue