diff --git a/charger/delta.go b/charger/delta.go index cb9715101..fbdd96f82 100644 --- a/charger/delta.go +++ b/charger/delta.go @@ -28,34 +28,32 @@ type Delta struct { const ( // EV Charger // Read Input Registers (0x04) - deltaRegState = 100 // Charger State - UINT16 0: not ready, 1: operational, 10: faulted, 255: not responding - deltaRegVersion = 101 // Charger Version - UINT16 - deltaRegCount = 102 // Charger EVSE Count - UINT16 - deltaRegError = 103 // Charger Error - UINT16 - deltaRegSerial = 110 // Charger Serial - STRING20 - deltaRegModel = 130 // Charger Model - STRING20 + deltaRegState = 100 // Charger State - UINT16 0: not ready, 1: operational, 10: faulted, 255: not responding + deltaRegCount = 102 // Charger EVSE Count - UINT16 + deltaRegSerial = 110 // Charger Serial - STRING20 + deltaRegModel = 130 // Charger Model - STRING20 // Write Multiple Registers (0x10) - deltaRegCommunicationTimeoutEnabled = 201 // Communication Timeout Enabled 0/1 - deltaRegCommunicationTimeout = 202 // Communication Timeout [s] - deltaRegFallbackPower = 203 // Fallback Power [W] + deltaRegCommunicationTimeoutEnabled = 201 // Communication Timeout Enabled - UINT16 0: false, 1: true + deltaRegCommunicationTimeout = 202 // Communication Timeout - UINT16 [s] + deltaRegFallbackPower = 203 // Fallback Power - UINT32 [W] // EVSE - The following Register tables are defined as repeating blocks for each single EVSE // Read Input Registers (0x04) deltaRegEvseState = 0 // EVSE State - UINT16 0: Unavailable, 1: Available, 2: Occupied, 3: Preparing, 4: Charging, 5: Finishing, 6: Suspended EV, 7: Suspended EVSE, 8: Not ready, 9: Faulted - deltaRegEvseChargerState = 1 // EVSE Charger State - UINT16 0: Charging process not started (no vehicle connected), 1: Connected, waiting for release (by RFID or local), 2: Charging process starts, 3: Charging, 4: Suspended (paused), 5: Charging process successfully completed (vehicle still plugged in), 6: Charging process completed by user (vehicle still plugged in), 7: Charging ended with error (vehicle still connected) - deltaRegEvseActualOutputVoltage = 3 // EVSE Actual Output Voltage - FLOAT32 [V] + deltaRegEvseChargerState = 1 // EVSE Charger State* - UINT16 0: Charging process not started (no vehicle connected), 1: Connected, waiting for release (by RFID or local), 2: Charging process starts, 3: Charging, 4: Suspended (paused), 5: Charging process successfully completed (vehicle still plugged in), 6: Charging process completed by user (vehicle still plugged in), 7: Charging ended with error (vehicle still connected) + deltaRegEvseActualOutputVoltage = 3 // EVSE Actual Output Voltage* - FLOAT32 [V] deltaRegEvseActualChargingPower = 5 // EVSE Actual Charging Power - UINT32 [W] - deltaRegEvseActualChargingCurrent = 7 // EVSE Actual Charging Current - FLOAT32 [A] - deltaRegEvseActualOutputPower = 9 // EVSE Actual Output Power - FLOAT32 [W] - deltaRegEvseSoc = 11 // EVSE SOC [%/10] - deltaRegEvseChargingTime = 17 // EVSE Charging Time [s] - deltaRegEvseChargedEnergy = 19 // EVSE Charged Energy [Wh] + deltaRegEvseActualChargingCurrent = 7 // EVSE Actual Charging Current* - FLOAT32 [A] + deltaRegEvseActualOutputPower = 9 // EVSE Actual Output Power* - FLOAT32 [W] + deltaRegEvseSoc = 11 // EVSE SOC* [%/10] + deltaRegEvseChargingTime = 17 // EVSE Charging Time* [s] + deltaRegEvseChargedEnergy = 19 // EVSE Charged Energy* [Wh] deltaRegEvseRfidUID = 100 // EVSE Used Authentication ID - STRING // Write Multiple Registers (0x10) deltaRegEvseChargingPowerLimit = 600 // EVSE Charging Power Limit - UINT32 [W] - deltaRegEvseSuspendCharging = 602 // EVSE Suspend Charging - UINT16 - 0: no pause, 1 charging pause (lock on) + deltaRegEvseSuspendCharging = 602 // EVSE Suspend Charging - UINT16 0: no pause, 1 charging pause (lock on) ) func init() { @@ -103,16 +101,22 @@ func NewDelta(uri, device, comset string, baudrate int, proto modbus.Protocol, s wb.base = connector * 1000 - // get failsafe timeout from charger - b, err := wb.conn.ReadHoldingRegisters(deltaRegCommunicationTimeout, 1) + b, err := wb.conn.ReadHoldingRegisters(deltaRegCommunicationTimeoutEnabled, 1) if err != nil { - return nil, fmt.Errorf("failsafe timeout: %w", err) - } - if u := encoding.Uint16(b); u > 0 { - go wb.heartbeat(time.Duration(u) * time.Second / 2) + return nil, fmt.Errorf("failsafe timeout enabled: %w", err) } - return wb, err + if encoding.Uint16(b) != 0 { + b, err := wb.conn.ReadHoldingRegisters(deltaRegCommunicationTimeout, 1) + if err != nil { + return nil, fmt.Errorf("failsafe timeout: %w", err) + } + if u := encoding.Uint16(b); u > 0 { + go wb.heartbeat(time.Duration(u) * time.Second / 2) + } + } + + return wb, nil } func (wb *Delta) heartbeat(timeout time.Duration) { @@ -131,25 +135,27 @@ func (wb *Delta) heartbeat(timeout time.Duration) { // Status implements the api.Charger interface func (wb *Delta) Status() (api.ChargeStatus, error) { - b, err := wb.conn.ReadInputRegisters(wb.base+deltaRegEvseChargerState, 1) + b, err := wb.conn.ReadInputRegisters(wb.base+deltaRegEvseState, 1) if err != nil { return api.StatusNone, err } - // 0: Charging process not started (no vehicle connected) - // 1: Connected, waiting for release (by RFID or local) - // 2: Charging process starts - // 3: Charging - // 4: Suspended (loading paused) - // 5: Charging process successfully completed (vehicle still plugged in) - // 6: Charging process completed by user (vehicle still plugged in) - // 7: Charging ended with error (vehicle still connected) + // 0: Unavailable + // 1: Available + // 2: Occupied + // 3: Preparing + // 4: Charging + // 5: Finishing + // 6: Suspended EV + // 7: Suspended EVSE + // 8: Not ready + // 9: Faulted switch s := encoding.Uint16(b); s { - case 0: + case 0, 1: return api.StatusA, nil - case 1, 2, 4, 5, 6, 7: + case 2, 3, 5, 6, 7: return api.StatusB, nil - case 3: + case 4: return api.StatusC, nil default: return api.StatusNone, fmt.Errorf("invalid status: %0x", s) @@ -235,23 +241,11 @@ func (wb *Delta) CurrentPower() (float64, error) { return float64(encoding.Uint32(b)), err } -var _ api.ChargeRater = (*Delta)(nil) - -// ChargedEnergy implements the api.ChargeRater interface -func (wb *Delta) ChargedEnergy() (float64, error) { - b, err := wb.conn.ReadInputRegisters(wb.base+deltaRegEvseChargedEnergy, 2) - if err != nil { - return 0, err - } - - return float64(encoding.Uint32(b)) / 1e3, err -} - var _ api.Identifier = (*Delta)(nil) // Identify implements the api.Identifier interface func (wb *Delta) Identify() (string, error) { - b, err := wb.conn.ReadInputRegisters(wb.base+deltaRegEvseRfidUID, 6) + b, err := wb.conn.ReadInputRegisters(wb.base+deltaRegEvseRfidUID, 20) if err != nil { return "", err } @@ -266,21 +260,24 @@ func (wb *Delta) Diagnose() { if b, err := wb.conn.ReadInputRegisters(deltaRegState, 1); err == nil { fmt.Printf("\tState:\t%d\n", encoding.Uint16(b)) } - if b, err := wb.conn.ReadInputRegisters(deltaRegVersion, 1); err == nil { - fmt.Printf("\tVersion:\t%d\n", encoding.Uint16(b)) - } if b, err := wb.conn.ReadInputRegisters(deltaRegCount, 1); err == nil { fmt.Printf("\tEVSE Count:\t%d\n", encoding.Uint16(b)) } - if b, err := wb.conn.ReadInputRegisters(deltaRegError, 1); err == nil { - fmt.Printf("\tError:\t%d\n", encoding.Uint16(b)) - } if b, err := wb.conn.ReadInputRegisters(deltaRegSerial, 20); err == nil { fmt.Printf("\tSerial:\t%s\n", bytesAsString(b)) } if b, err := wb.conn.ReadInputRegisters(deltaRegModel, 20); err == nil { fmt.Printf("\tModel:\t%s\n", bytesAsString(b)) } + if b, err := wb.conn.ReadHoldingRegisters(deltaRegCommunicationTimeoutEnabled, 1); err == nil { + fmt.Printf("\tCommunication Timeout Enabled:\t%d\n", encoding.Uint16(b)) + } + if b, err := wb.conn.ReadHoldingRegisters(deltaRegCommunicationTimeout, 1); err == nil { + fmt.Printf("\tCommunication Timeout:\t%d\n", encoding.Uint16(b)) + } + if b, err := wb.conn.ReadHoldingRegisters(deltaRegFallbackPower, 2); err == nil { + fmt.Printf("\tFallback Power:\t%d\n", encoding.Uint32(b)) + } } var _ loadpoint.Controller = (*Delta)(nil)