Use register 1000 for enable/disable and add delay to support older evse's (#380)

This commit is contained in:
andig 2020-10-13 07:59:21 +02:00 • committed by GitHub
parent 41e29f2560
commit 8e61200216
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 51 additions and 37 deletions

View file

@ -2,6 +2,7 @@ package charger
import (
"errors"
"time"
"github.com/andig/evcc/api"
"github.com/andig/evcc/util"
@ -10,14 +11,14 @@ import (
// SimpleEVSE charger implementation
type SimpleEVSE struct {
log *util.Logger
conn *modbus.Connection
log *util.Logger
conn *modbus.Connection
current int64
}
const (
evseRegAmpsConfig = 1000
evseRegVehicleStatus = 1002
evseRegTurnOff = 1004
)
func init() {
@ -49,9 +50,13 @@ func NewSimpleEVSE(uri, device, comset string, baudrate int, rtu bool, slaveID u
return nil, err
}
conn.Logger(log.TRACE)
conn.Delay(200 * time.Millisecond)
evse := &SimpleEVSE{
log: log,
conn: conn,
log: log,
conn: conn,
current: 6, // assume min current
}
return evse, nil
@ -60,7 +65,6 @@ func NewSimpleEVSE(uri, device, comset string, baudrate int, rtu bool, slaveID u
// Status implements the Charger.Status interface
func (evse *SimpleEVSE) Status() (api.ChargeStatus, error) {
b, err := evse.conn.ReadHoldingRegisters(evseRegVehicleStatus, 1)
evse.log.TRACE.Printf("read status (%d): %0 X", evseRegVehicleStatus, b)
if err != nil {
return api.StatusNone, err
}
@ -83,31 +87,28 @@ func (evse *SimpleEVSE) Status() (api.ChargeStatus, error) {
// Enabled implements the Charger.Enabled interface
func (evse *SimpleEVSE) Enabled() (bool, error) {
b, err := evse.conn.ReadHoldingRegisters(evseRegTurnOff, 1)
evse.log.TRACE.Printf("read charge enable (%d): %0 X", evseRegTurnOff, b)
b, err := evse.conn.ReadHoldingRegisters(evseRegAmpsConfig, 1)
if err != nil {
return false, err
}
return b[1] == 1, nil
enabled := b[1] != 0
if enabled {
evse.current = int64(b[1])
}
return enabled, nil
}
// Enable implements the Charger.Enable interface
func (evse *SimpleEVSE) Enable(enable bool) error {
b, err := evse.conn.ReadHoldingRegisters(evseRegTurnOff, 1)
evse.log.TRACE.Printf("read charge enable (%d): %0 X", evseRegTurnOff, b)
if err != nil {
return err
}
b := []byte{0, 0}
if enable {
b[1] |= 1
} else {
b[1] &= ^byte(1)
b[1] = byte(evse.current)
}
bb, err := evse.conn.WriteMultipleRegisters(evseRegTurnOff, 1, b)
evse.log.TRACE.Printf("write charge enable (%d) %0X: %0 X", evseRegTurnOff, b, bb)
_, err := evse.conn.WriteMultipleRegisters(evseRegAmpsConfig, 1, b)
return err
}
@ -116,8 +117,10 @@ func (evse *SimpleEVSE) Enable(enable bool) error {
func (evse *SimpleEVSE) MaxCurrent(current int64) error {
b := []byte{0, byte(current)}
b, err := evse.conn.WriteMultipleRegisters(evseRegAmpsConfig, 1, b)
evse.log.TRACE.Printf("write max current (%d) %0X: %0 X", evseRegAmpsConfig, current, b)
_, err := evse.conn.WriteMultipleRegisters(evseRegAmpsConfig, 1, b)
if err == nil {
evse.current = current
}
return err
}

View file

@ -5,6 +5,7 @@ import (
"fmt"
"strconv"
"strings"
"time"
"github.com/volkszaehler/mbmd/meters"
"github.com/volkszaehler/mbmd/meters/rs485"
@ -24,6 +25,14 @@ type Settings struct {
type Connection struct {
slaveID uint8
conn meters.Connection
delay time.Duration
}
func (mb *Connection) prepare() {
mb.conn.Slave(mb.slaveID)
if mb.delay > 0 {
time.Sleep(mb.delay)
}
}
func (mb *Connection) handle(res []byte, err error) ([]byte, error) {
@ -33,6 +42,11 @@ func (mb *Connection) handle(res []byte, err error) ([]byte, error) {
return res, err
}
// Delay sets delay so use between subsequent modbus operations
func (mb *Connection) Delay(delay time.Duration) {
mb.delay = delay
}
// Logger sets logger implementation
func (mb *Connection) Logger(logger meters.Logger) {
mb.conn.Logger(logger)
@ -40,82 +54,79 @@ func (mb *Connection) Logger(logger meters.Logger) {
// ReadCoils wraps the underlying implementation
func (mb *Connection) ReadCoils(address, quantity uint16) ([]byte, error) {
mb.conn.Slave(mb.slaveID)
mb.prepare()
return mb.handle(mb.conn.ModbusClient().ReadCoils(address, quantity))
}
// WriteSingleCoil wraps the underlying implementation
func (mb *Connection) WriteSingleCoil(address, quantity uint16) ([]byte, error) {
mb.conn.Slave(mb.slaveID)
mb.prepare()
return mb.handle(mb.conn.ModbusClient().WriteSingleCoil(address, quantity))
}
// ReadInputRegisters wraps the underlying implementation
func (mb *Connection) ReadInputRegisters(address, quantity uint16) ([]byte, error) {
mb.conn.Slave(mb.slaveID)
mb.prepare()
return mb.handle(mb.conn.ModbusClient().ReadInputRegisters(address, quantity))
}
// ReadHoldingRegisters wraps the underlying implementation
func (mb *Connection) ReadHoldingRegisters(address, quantity uint16) ([]byte, error) {
mb.conn.Slave(mb.slaveID)
mb.prepare()
return mb.handle(mb.conn.ModbusClient().ReadHoldingRegisters(address, quantity))
}
// WriteSingleRegister wraps the underlying implementation
func (mb *Connection) WriteSingleRegister(address, value uint16) ([]byte, error) {
mb.conn.Slave(mb.slaveID)
mb.prepare()
return mb.handle(mb.conn.ModbusClient().WriteSingleRegister(address, value))
}
// WriteMultipleRegisters wraps the underlying implementation
func (mb *Connection) WriteMultipleRegisters(address, quantity uint16, value []byte) ([]byte, error) {
mb.conn.Slave(mb.slaveID)
mb.prepare()
return mb.handle(mb.conn.ModbusClient().WriteMultipleRegisters(address, quantity, value))
}
// ReadDiscreteInputs wraps the underlying implementation
func (mb *Connection) ReadDiscreteInputs(address, quantity uint16) (results []byte, err error) {
mb.conn.Slave(mb.slaveID)
mb.prepare()
return mb.handle(mb.conn.ModbusClient().ReadDiscreteInputs(address, quantity))
}
// WriteMultipleCoils wraps the underlying implementation
func (mb *Connection) WriteMultipleCoils(address, quantity uint16, value []byte) (results []byte, err error) {
mb.conn.Slave(mb.slaveID)
mb.prepare()
return mb.handle(mb.conn.ModbusClient().WriteMultipleCoils(address, quantity, value))
}
// ReadWriteMultipleRegisters wraps the underlying implementation
func (mb *Connection) ReadWriteMultipleRegisters(readAddress, readQuantity, writeAddress, writeQuantity uint16, value []byte) (results []byte, err error) {
mb.conn.Slave(mb.slaveID)
mb.prepare()
return mb.handle(mb.conn.ModbusClient().ReadWriteMultipleRegisters(readAddress, readQuantity, writeAddress, writeQuantity, value))
}
// MaskWriteRegister wraps the underlying implementation
func (mb *Connection) MaskWriteRegister(address, andMask, orMask uint16) (results []byte, err error) {
mb.conn.Slave(mb.slaveID)
mb.prepare()
return mb.handle(mb.conn.ModbusClient().MaskWriteRegister(address, andMask, orMask))
}
// ReadFIFOQueue wraps the underlying implementation
func (mb *Connection) ReadFIFOQueue(address uint16) (results []byte, err error) {
mb.conn.Slave(mb.slaveID)
mb.prepare()
return mb.handle(mb.conn.ModbusClient().ReadFIFOQueue(address))
}
var connections map[string]meters.Connection
var connections = make(map[string]meters.Connection)
func registeredConnection(key string, newConn meters.Connection) meters.Connection {
if connections == nil {
connections = make(map[string]meters.Connection)
}
if conn, ok := connections[key]; ok {
return conn
}
connections[key] = newConn
return newConn
}