Fix: authorize by RFID or WebUI
This commit is contained in:
@@ -46,12 +46,29 @@ type ChargerController struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewChargerController(host string, pool *pgxpool.Pool) *ChargerController {
|
func NewChargerController(host string, pool *pgxpool.Pool) *ChargerController {
|
||||||
return &ChargerController{
|
c := &ChargerController{
|
||||||
host: host,
|
host: host,
|
||||||
pool: pool,
|
pool: pool,
|
||||||
params: ChargingParams{Mode: ModeOff},
|
params: ChargingParams{Mode: ModeOff},
|
||||||
status: "idle",
|
status: "initializing",
|
||||||
}
|
}
|
||||||
|
// Always restore RFID-gated idle state on startup. nmo/acs settings persist
|
||||||
|
// on the charger hardware across app restarts, so we must reset them explicitly.
|
||||||
|
go c.initSafeState()
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ChargerController) initSafeState() {
|
||||||
|
if err := setChargerFrc(c.host, 1); err != nil {
|
||||||
|
log.Printf("charger ctrl: init: %v", err)
|
||||||
|
c.setStatus("charger unreachable")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setChargerNmo(c.host, false)
|
||||||
|
setChargerAcs(c.host, 1)
|
||||||
|
setChargerFrc(c.host, 0)
|
||||||
|
c.setStatus("idle")
|
||||||
|
log.Printf("charger ctrl: initialized — RFID-gated (nmo=false, acs=1)")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ChargerController) State() ControllerState {
|
func (c *ChargerController) State() ControllerState {
|
||||||
@@ -131,12 +148,15 @@ func (c *ChargerController) enableCharging(amps int) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("charger unreachable: %w", err)
|
return fmt.Errorf("charger unreachable: %w", err)
|
||||||
}
|
}
|
||||||
if st.Car == 4 {
|
// car=4: previous session must be cleared before a new one can start.
|
||||||
c.setStatus("resetting — previous session complete")
|
// car=3: car entered IEC state B while acs=1 was active; the CP-line
|
||||||
|
// "wait for auth" signal means the car won't accept frc=2 alone —
|
||||||
|
// a full reset forces a fresh IEC 61851 handshake.
|
||||||
|
if st.Car == 4 || st.Car == 3 {
|
||||||
|
c.setStatus("resetting — fresh IEC negotiation needed")
|
||||||
if err := resetCharger(c.host); err != nil {
|
if err := resetCharger(c.host); err != nil {
|
||||||
return fmt.Errorf("reset: %w", err)
|
return fmt.Errorf("reset: %w", err)
|
||||||
}
|
}
|
||||||
// Reset clears currentPhases so phase-switch logic starts fresh
|
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
c.currentPhases = 0
|
c.currentPhases = 0
|
||||||
c.mu.Unlock()
|
c.mu.Unlock()
|
||||||
@@ -276,6 +296,24 @@ func (c *ChargerController) adjust(ctx context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// frc=2 alone does not override acs=1 on this firmware: if access control
|
||||||
|
// is still blocking (alw=false) and we haven't intentionally force-paused
|
||||||
|
// (frc=1), the session hasn't been authorised yet — call enableCharging to
|
||||||
|
// set acs=0 and start the session properly.
|
||||||
|
// Guard on battPaused: if the battery SOC is already below the cutoff
|
||||||
|
// (set at the top of this function), do not enable charging even if the
|
||||||
|
// charger looks idle — the pause takes priority.
|
||||||
|
c.mu.RLock()
|
||||||
|
paused := c.battPaused
|
||||||
|
c.mu.RUnlock()
|
||||||
|
if !st.Alw && st.Frc != 1 && !paused {
|
||||||
|
if err := c.enableCharging(params.MaxAmp); err != nil {
|
||||||
|
log.Printf("charger ctrl: session start: %v", err)
|
||||||
|
c.setStatus("session start failed: " + err.Error())
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grid mode: current is fixed and already applied by enableCharging(); the
|
// Grid mode: current is fixed and already applied by enableCharging(); the
|
||||||
@@ -412,7 +450,16 @@ func (c *ChargerController) stopOnDisconnect() {
|
|||||||
|
|
||||||
func (c *ChargerController) stopForTarget(reason string) {
|
func (c *ChargerController) stopForTarget(reason string) {
|
||||||
if err := setChargerFrc(c.host, 1); err != nil {
|
if err := setChargerFrc(c.host, 1); err != nil {
|
||||||
log.Printf("charger ctrl: stop: %v", err)
|
log.Printf("charger ctrl: stop frc1: %v", err)
|
||||||
|
}
|
||||||
|
if err := setChargerNmo(c.host, false); err != nil {
|
||||||
|
log.Printf("charger ctrl: stop nmo: %v", err)
|
||||||
|
}
|
||||||
|
if err := setChargerAcs(c.host, 1); err != nil {
|
||||||
|
log.Printf("charger ctrl: stop acs: %v", err)
|
||||||
|
}
|
||||||
|
if err := setChargerFrc(c.host, 0); err != nil {
|
||||||
|
log.Printf("charger ctrl: stop frc0: %v", err)
|
||||||
}
|
}
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
c.params.Mode = ModeOff
|
c.params.Mode = ModeOff
|
||||||
|
|||||||
Reference in New Issue
Block a user