From 6f65584e8748950525801841ae25fd9c7c0bedae Mon Sep 17 00:00:00 2001 From: andig Date: Sun, 3 Aug 2025 14:24:33 +0200 Subject: [PATCH] Ocpp: fix connector not de-registered (#22113) --- assets/js/components/Config/ChargerModal.vue | 4 ++-- assets/js/components/Config/DeviceTags.vue | 2 +- assets/js/components/Config/utils/test.ts | 1 + charger/ocpp.go | 2 +- charger/ocpp/connector.go | 8 +++++++- charger/ocpp/connector_test.go | 3 ++- charger/ocpp/cp.go | 7 +++++++ server/http_config_device_handler.go | 3 ++- 8 files changed, 23 insertions(+), 7 deletions(-) diff --git a/assets/js/components/Config/ChargerModal.vue b/assets/js/components/Config/ChargerModal.vue index 8367c9717..b73058783 100644 --- a/assets/js/components/Config/ChargerModal.vue +++ b/assets/js/components/Config/ChargerModal.vue @@ -252,10 +252,10 @@ export default defineComponent({ ); }, normalParams() { - return this.templateParams.filter((p) => !p.Advanced); + return this.templateParams.filter((p) => !p.Advanced && !p.Deprecated); }, advancedParams() { - return this.templateParams.filter((p) => p.Advanced); + return this.templateParams.filter((p) => p.Advanced || p.Deprecated); }, modbus() { const params = this.template?.Params || []; diff --git a/assets/js/components/Config/DeviceTags.vue b/assets/js/components/Config/DeviceTags.vue index f55c3a0f2..82e25c83c 100644 --- a/assets/js/components/Config/DeviceTags.vue +++ b/assets/js/components/Config/DeviceTags.vue @@ -76,7 +76,7 @@ export default { case "phasePowers": return value.map((v) => this.fmtW(v, POWER_UNIT.KW, false)).join(" ยท ") + " kW"; case "chargeStatus": - return this.$t(`config.deviceValue.chargeStatus${value}`); + return value ? this.$t(`config.deviceValue.chargeStatus${value}`) : "-"; case "gridPrice": case "feedinPrice": return this.fmtPricePerKWh(value, options.currency, true); diff --git a/assets/js/components/Config/utils/test.ts b/assets/js/components/Config/utils/test.ts index 888f4f7f3..045297f26 100644 --- a/assets/js/components/Config/utils/test.ts +++ b/assets/js/components/Config/utils/test.ts @@ -30,6 +30,7 @@ export const performTest = async ( state.isSuccess = false; state.isError = false; state.isRunning = true; + state.error = null; state.errorLine = null; try { const res = await api(); diff --git a/charger/ocpp.go b/charger/ocpp.go index dd12922d3..7cab56522 100644 --- a/charger/ocpp.go +++ b/charger/ocpp.go @@ -178,7 +178,7 @@ func NewOCPP(ctx context.Context, idTag = lo.CoalesceOrEmpty(idTag, cp.IdTag, defaultIdTag) } - conn, err := ocpp.NewConnector(log, connector, cp, idTag, meterInterval) + conn, err := ocpp.NewConnector(ctx, log, connector, cp, idTag, meterInterval) if err != nil { return nil, err } diff --git a/charger/ocpp/connector.go b/charger/ocpp/connector.go index a13c1f4d5..bcd312fb3 100644 --- a/charger/ocpp/connector.go +++ b/charger/ocpp/connector.go @@ -36,7 +36,7 @@ type Connector struct { meterInterval time.Duration } -func NewConnector(log *util.Logger, id int, cp *CP, idTag string, meterInterval time.Duration) (*Connector, error) { +func NewConnector(ctx context.Context, log *util.Logger, id int, cp *CP, idTag string, meterInterval time.Duration) (*Connector, error) { conn := &Connector{ log: log, cp: cp, @@ -53,6 +53,12 @@ func NewConnector(log *util.Logger, id int, cp *CP, idTag string, meterInterval return nil, err } + go func() { + // deregister connector when the context is cancelled + <-ctx.Done() + cp.deregisterConnector(conn.id) + }() + // trigger status for all connectors var ok bool diff --git a/charger/ocpp/connector_test.go b/charger/ocpp/connector_test.go index 8250a3e7a..fb80a46bd 100644 --- a/charger/ocpp/connector_test.go +++ b/charger/ocpp/connector_test.go @@ -1,6 +1,7 @@ package ocpp import ( + "context" "testing" "time" @@ -26,7 +27,7 @@ func (suite *connTestSuite) SetupTest() { // setup instance Instance() suite.cp = NewChargePoint(util.NewLogger("foo"), "abc") - suite.conn, _ = NewConnector(util.NewLogger("foo"), 1, suite.cp, "", Timeout) + suite.conn, _ = NewConnector(context.TODO(), util.NewLogger("foo"), 1, suite.cp, "", Timeout) suite.clock = clock.NewMock() suite.conn.clock = suite.clock diff --git a/charger/ocpp/cp.go b/charger/ocpp/cp.go index 69efe3c49..08f878eef 100644 --- a/charger/ocpp/cp.go +++ b/charger/ocpp/cp.go @@ -67,6 +67,13 @@ func (cp *CP) registerConnector(id int, conn *Connector) error { return nil } +func (cp *CP) deregisterConnector(id int) { + cp.mu.Lock() + defer cp.mu.Unlock() + + delete(cp.connectors, id) +} + func (cp *CP) connectorByID(id int) *Connector { cp.mu.RLock() defer cp.mu.RUnlock() diff --git a/server/http_config_device_handler.go b/server/http_config_device_handler.go index 95528c9cf..ea08bb163 100644 --- a/server/http_config_device_handler.go +++ b/server/http_config_device_handler.go @@ -601,8 +601,9 @@ func testConfigHandler(w http.ResponseWriter, r *http.Request) { return } - // prevent context from being cancelled + // prevent context from being cancelled during test close(done) + defer cancel() jsonWrite(w, testInstance(instance)) }