Use register 1000 for enable/disable and add delay to support older evse's (#380)
This commit is contained in:
parent
41e29f2560
commit
8e61200216
2 changed files with 51 additions and 37 deletions
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue