From aed25811faec96b607c49ede8952fe0c62b37a35 Mon Sep 17 00:00:00 2001 From: "K. Shankari" Date: Sun, 26 Jan 2025 17:48:21 -0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=AA=A0=20Plumb=20through=20notify=5Fcharg?= =?UTF-8?q?ing=5Flimit=20as=20a=20NOP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So that we can finish testing the EVerest changes in https://github.com/EVerest/everest-demo/issues/101 end-to-end I have not yet plumbed through the changes to `clear_charging_limit` but they should be fairly simple, and I can leave them as an exercise for @Abby-Wheelis Outline of changes: - add `notify_charging_limit` to the `CallMap`, and have it redirect to the `notify_charging_limit_handler` - add a handler for the `notify_charging_limit` - add classes for the request and response that we can use in the handler Testing done: Without this change: https://github.com/EVerest/everest-demo/issues/101#issuecomment-2614205778 With this change: ``` 2025-01-27 02:36:16.234166 [INFO] ocpp:OCPP201 :: Received internal set_charging_limit: for 1 with purpose 15 2025-01-27 02:36:16.234471 [INFO] ocpp:OCPP201 :: SHANKARI: Invoking validate_and_add_profile with 1 and source EMS 2025-01-27 02:36:16.234598 [INFO] evse_manager_1: :: set_max_current (14, 2025-01-27 02:36:26.094000000) called 2025-01-27 02:36:16.234517 [INFO] ocpp:OCPP201 :: SHANKARI: invoked validate_profile for evse_id: 1 and profile { "chargingProfileKind": "Absolute", "chargingProfilePurpose": "ChargingStationExternalConstraints", "chargingSchedule": [ { "chargingRateUnit": "A", "chargingSchedulePeriod": [ { "limit": 15.0, "startPeriod": 0 } ], "duration": 86400, "id": 0, "startSchedule": "2025-01-27T02:36:16.234Z" } ], "id": 398, "stackLevel": 10 } 2025-01-27 02:36:16.234902 [INFO] ocpp:OCPP201 :: SHANKARI: after validating file request source 2025-01-27 02:36:16.234926 [INFO] ocpp:OCPP201 :: SHANKARI: after validating conflicting external constraints 2025-01-27 02:36:16.235939 [INFO] ocpp:OCPP201 :: SHANKARI: before validating by purpose 2025-01-27 02:36:16.235974 [INFO] ocpp:OCPP201 :: SHANKARI: should return valid here! 2025-01-27 02:36:16.235986 [INFO] ocpp:OCPP201 :: SHANKARI: result for 1 is Valid 2025-01-27 02:36:16.236010 [INFO] ocpp:OCPP201 :: SHANKARI: Modifying database 2025-01-27 02:36:16.243501 [INFO] ocpp:OCPP201 :: Returning from on_charging_limit_set with 1 and status Accepted ``` ``` {"type":2,"action":"NotifyChargingLimit","id":"feda7835-c7d5-4717-8df6-79cdc5b17e9c","request":{"chargingLimit":{"chargingLimitSource":"EMS"},"chargingSchedule":[{"chargingRateUnit":"A","chargingSchedulePeriod":[{"limit":15.0,"startPeriod":0}],"duration":86400,"id":0,"startSchedule":"2025-01-27T02:36:16.234Z"}],"evseId":1}} {"type":3,"action":"NotifyChargingLimit","id":"feda7835-c7d5-4717-8df6-79cdc5b17e9c","response":{}} ``` --- .../handlers/ocpp201/notify_charging_limit.go | 25 ++++++++++++++ manager/handlers/ocpp201/routing.go | 6 ++++ .../ocpp201/notify_charging_limit_request.go | 34 +++++++++++++++++++ .../ocpp201/notify_charging_limit_response.go | 11 ++++++ 4 files changed, 76 insertions(+) create mode 100644 manager/handlers/ocpp201/notify_charging_limit.go create mode 100644 manager/ocpp/ocpp201/notify_charging_limit_request.go create mode 100644 manager/ocpp/ocpp201/notify_charging_limit_response.go diff --git a/manager/handlers/ocpp201/notify_charging_limit.go b/manager/handlers/ocpp201/notify_charging_limit.go new file mode 100644 index 0000000..faf5f59 --- /dev/null +++ b/manager/handlers/ocpp201/notify_charging_limit.go @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: Apache-2.0 + +package ocpp201 + +import ( + "context" + "github.com/thoughtworks/maeve-csms/manager/ocpp" + "github.com/thoughtworks/maeve-csms/manager/ocpp/ocpp201" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" +) + +type NotifyChargingLimitHandler struct{} + +func (h NotifyChargingLimitHandler) HandleCall(ctx context.Context, chargeStationId string, request ocpp.Request) (response ocpp.Response, err error) { + req := request.(*ocpp201.NotifyChargingLimitRequestJson) + + span := trace.SpanFromContext(ctx) + + span.SetAttributes( + attribute.String("notify_charging_limit.charging_limit_source", string(req.ChargingLimit.ChargingLimitSource)), + attribute.Int("notify_charging_limit.evse_id", req.EvseId)) + + return &ocpp201.NotifyChargingLimitResponseJson{}, nil +} diff --git a/manager/handlers/ocpp201/routing.go b/manager/handlers/ocpp201/routing.go index 6bf4bb8..820a159 100644 --- a/manager/handlers/ocpp201/routing.go +++ b/manager/handlers/ocpp201/routing.go @@ -101,6 +101,12 @@ func NewRouter(emitter transport.Emitter, ResponseSchema: "ocpp201/NotifyReportResponse.json", Handler: NotifyReportHandler{}, }, + "NotifyChargingLimit": { + NewRequest: func() ocpp.Request { return new(ocpp201.NotifyChargingLimitRequestJson) }, + RequestSchema: "ocpp201/NotifyChargingLimitRequest.json", + ResponseSchema: "ocpp201/NotifyChargingLimitResponse.json", + Handler: NotifyChargingLimitHandler{}, + }, "StatusNotification": { NewRequest: func() ocpp.Request { return new(ocpp201.StatusNotificationRequestJson) }, RequestSchema: "ocpp201/StatusNotificationRequest.json", diff --git a/manager/ocpp/ocpp201/notify_charging_limit_request.go b/manager/ocpp/ocpp201/notify_charging_limit_request.go new file mode 100644 index 0000000..a0ee493 --- /dev/null +++ b/manager/ocpp/ocpp201/notify_charging_limit_request.go @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: Apache-2.0 + +package ocpp201 + +type NotifyChargingLimitRequestJson struct { + // CustomData corresponds to the JSON schema field "customData". + CustomData *CustomDataType `json:"customData,omitempty" yaml:"customData,omitempty" mapstructure:"customData,omitempty"` + + // Number of the EVSE on which the limit has been applied. + EvseId int `json:"evseId,omitempty" yaml:"evseId,omitempty" mapstructure:"evseId,omitempty"` + // Number of the EVSE on which the limit has been applied. + ChargingLimit ChargingLimitType `json:"chargingLimit,omitempty" yaml:"chargingLimit,omitempty" mapstructure:"chargingLimit,omitempty"` + + // ChargingSchedule corresponds to the JSON schema field "chargingSchedule". + ChargingSchedule []ChargingScheduleType `json:"chargingSchedule" yaml:"chargingSchedule" mapstructure:"chargingSchedule"` +} + +func (*NotifyChargingLimitRequestJson) IsRequest() {} + +type ChargingLimitSourceEnumType string + +const ChargingLimitSourceEnumEMS ChargingLimitSourceEnumType = "EMS" +const ChargingLimitSourceEnumOther ChargingLimitSourceEnumType = "Other" +const ChargingLimitSourceEnumSO ChargingLimitSourceEnumType = "SO" +const ChargingLimitSourceEnumCSO ChargingLimitSourceEnumType = "CSO" + +type ChargingLimitType struct { + // CustomData corresponds to the JSON schema field "customData". + CustomData *CustomDataType `json:"customData,omitempty" yaml:"customData,omitempty" mapstructure:"customData,omitempty"` + + ChargingLimitSource BootReasonEnumType `json:"chargingLimitSource" yaml:"chargingLimitSource" mapstructure:"chargingLimitSource"` + + IsGridCritical bool `json:"isGridCritical,omitempty" yaml:"isGridCritical,omitempty" mapstructure:"isGridCritical,omitempty"` +} diff --git a/manager/ocpp/ocpp201/notify_charging_limit_response.go b/manager/ocpp/ocpp201/notify_charging_limit_response.go new file mode 100644 index 0000000..2af1730 --- /dev/null +++ b/manager/ocpp/ocpp201/notify_charging_limit_response.go @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: Apache-2.0 + +package ocpp201 + +type NotifyChargingLimitResponseJson struct { + // CustomData corresponds to the JSON schema field "customData". + CustomData *CustomDataType `json:"customData,omitempty" yaml:"customData,omitempty" mapstructure:"customData,omitempty"` +} + +func (*NotifyChargingLimitResponseJson) IsResponse() {} +