Skip to content

Commit

Permalink
Modbus: add coils (#8385)
Browse files Browse the repository at this point in the history
  • Loading branch information
kscholty committed Jun 11, 2023
1 parent cc22337 commit 228a01a
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 4 deletions.
16 changes: 13 additions & 3 deletions provider/modbus.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"github.com/evcc-io/evcc/util/modbus"
gridx "github.com/grid-x/modbus"
"github.com/volkszaehler/mbmd/meters"
"github.com/volkszaehler/mbmd/meters/rs485"
"github.com/volkszaehler/mbmd/meters/sunspec"
)

Expand Down Expand Up @@ -140,10 +139,12 @@ func NewModbusFromConfig(other map[string]interface{}) (Provider, error) {
func (m *Modbus) bytesGetter() ([]byte, error) {
if op := m.op.MBMD; op.FuncCode != 0 {
switch op.FuncCode {
case rs485.ReadHoldingReg:
case gridx.FuncCodeReadHoldingRegisters:
return m.conn.ReadHoldingRegisters(op.OpCode, op.ReadLen)
case rs485.ReadInputReg:
case gridx.FuncCodeReadInputRegisters:
return m.conn.ReadInputRegisters(op.OpCode, op.ReadLen)
case gridx.FuncCodeReadCoils:
return m.conn.ReadCoils(op.OpCode, op.ReadLen)
default:
return nil, fmt.Errorf("unknown function code %d", op.FuncCode)
}
Expand Down Expand Up @@ -234,6 +235,8 @@ func (m *Modbus) StringGetter() func() (string, error) {
// UintFromBytes converts byte slice to bigendian uint value
func UintFromBytes(bytes []byte) (u uint64, err error) {
switch l := len(bytes); l {
case 1:
u = uint64(bytes[0])
case 2:
u = uint64(binary.BigEndian.Uint16(bytes))
case 4:
Expand Down Expand Up @@ -272,6 +275,13 @@ func (m *Modbus) IntSetter(param string) func(int64) error {
switch op.FuncCode {
case gridx.FuncCodeWriteSingleRegister:
_, err = m.conn.WriteSingleRegister(op.OpCode, uval)
case gridx.FuncCodeWriteSingleCoil:
if uval != 0 {
// Modbus protocol requires 0xFF00 for ON
// and 0x0000 for OFF
uval = 0xFF00
}
_, err = m.conn.WriteSingleCoil(op.OpCode, uval)
default:
err = fmt.Errorf("unknown function code %d", op.FuncCode)
}
Expand Down
9 changes: 9 additions & 0 deletions util/modbus/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ func decodeMask(mask string) (uint64, error) {
return strconv.ParseUint(mask, 10, 64)
}

// decodeBool8 converts a masked uint1 to a bool
func decodeBool8(b []byte) float64 {
u := b[0]
if u > 0 {
return 1
}
return 0
}

// decodeBool16 converts a masked uint16 to a bool
func decodeBool16(mask uint64) func(b []byte) float64 {
return func(b []byte) float64 {
Expand Down
13 changes: 12 additions & 1 deletion util/modbus/modbus.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,14 +375,25 @@ func RegisterOperation(r Register) (rs485.Operation, error) {
op.FuncCode = modbus.FuncCodeReadHoldingRegisters
case "input":
op.FuncCode = modbus.FuncCodeReadInputRegisters
case "writesingle":
case "coil":
op.FuncCode = modbus.FuncCodeReadCoils
r.Decode = "bool8"
case "writesingle", "writeholding":
op.FuncCode = modbus.FuncCodeWriteSingleRegister
case "writecoil":
op.FuncCode = modbus.FuncCodeWriteSingleCoil
r.Decode = "bool8"
default:
return rs485.Operation{}, fmt.Errorf("invalid register type: %s", r.Type)
}

switch strings.ToLower(r.Decode) {

// 8 bit (coil)
case "bool8":
op.Transform = decodeBool8
op.ReadLen = 1

// 16 bit
case "int16":
op.Transform = asFloat64(encoding.Int16)
Expand Down

0 comments on commit 228a01a

Please sign in to comment.