Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented Set Charging Profile API #44

Open
wants to merge 26 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
2215fa6
Added logs to trace logs
louisg1337 Jun 5, 2024
ced0553
Added in slog import
louisg1337 Jun 5, 2024
42c5313
Added more logs
louisg1337 Jun 5, 2024
ba0f2f0
Added in charging profile types, and tried to add the route to our ro…
louisg1337 Jun 7, 2024
1bb5e81
Changed position of import to hopefully prevent error
louisg1337 Jun 7, 2024
227840a
got rid of slog, trying fmt
louisg1337 Jun 7, 2024
eea2298
got rid of more slogs, changed to fmt
louisg1337 Jun 7, 2024
8bad7f6
added in logs from add_logs
louisg1337 Jun 7, 2024
40bb05d
Trying new import for slog
louisg1337 Jun 7, 2024
46182ff
changed logs to see http body
louisg1337 Jun 7, 2024
6af2e28
changed the logs
louisg1337 Jun 7, 2024
81c8d8c
Attempting to make a call to Send
louisg1337 Jun 7, 2024
a9c3fd8
Got rid of error handling temporarily to see if my call will go through
louisg1337 Jun 7, 2024
27bed61
Fixed the typing so that we now use their types they defined, and got…
louisg1337 Jun 7, 2024
6df4a80
Added our request into the callmaker actions so it won't error. Also …
louisg1337 Jun 7, 2024
fd4dad5
added in todo so I don't forget
louisg1337 Jun 7, 2024
ff3999a
Added more context to how we can deal with the EVerest response to se…
louisg1337 Jun 8, 2024
1b3f432
Fixed typo in charging profile struct and added new comments
louisg1337 Jun 12, 2024
e55f24e
Added in work around for setChargingProfile so that we give EVerest d…
louisg1337 Jun 17, 2024
e665a0e
added in new log
louisg1337 Jun 17, 2024
8c22c88
commented out old changes, added in json mapping in struct
louisg1337 Jun 17, 2024
0269ebd
Got rid of temporary fix, added in more json fields
louisg1337 Jun 17, 2024
385a173
Cleaned up extraneous comments and log statements
louisg1337 Jun 18, 2024
c053e51
Updated API.md with setChargingProfile documentation
louisg1337 Jun 18, 2024
9d9a3fc
Changes logs from info to debug, added API TRACE as the tag
louisg1337 Jun 20, 2024
8b42be9
Reverted changes linter made to packages
louisg1337 Jun 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions manager/api/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,49 @@ This operation does not require authentication
This operation does not require authentication
</aside>

## setChargingProfile

<a id="opIdsetChargingProfile"></a>

`POST /cs/{csId}/setchargingprofile`

> Body parameter

```json
{
"<ChargingProfileType>"
}
```

<h3 id="setChargingProfile-parameters">Parameters</h3>

|Name|In|Type|Required|Description|
|---|---|---|---|---|
|csId|path|string|true|The charge station identifier|
|body|body|[ChargineProfileType](#schemaChargingProfileType)|true|none|

> Example responses

> default Response

```json
{
"status": "string",
"error": "string"
}
```

<h3 id="setChargingProfile-responses">Responses</h3>

|Status|Meaning|Description|Schema|
|---|---|---|---|
|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|OK|None|
|default|Default|Unexpected error|[Status](#schemastatus)|

<aside class="success">
This operation does not require authentication
</aside>

## setToken

<a id="opIdsetToken"></a>
Expand Down Expand Up @@ -838,6 +881,46 @@ Trigger a charge station action
|trigger|SignChargingStationCertificate|
|trigger|SignCombinedCertificate|

<h2 id="ChargingProfileType">ChargingProfileType</h2>
<!-- backwards compatibility -->
<a id="schemaChargingProfileType"></a>
<a id="schema_ChargingProfileType"></a>
<a id="tocSChargingProfileType"></a>
<a id="tocsChargingProfileType"></a>

```json

{
"id": int,
"stackLevel": int,
"chargingProfilePurpose": "ChargingProfilePurposeEnumType",
"chargingProfileKind": "ChargingProfileKindEnumType",
"recurrencyKind": "RecurrencyKindEnumType",
"validFrom": "dateTime",
"validTo": "dateTime",
"transactionId": "identifierString[0..36]",
"chargingSchedule": "ChargingScheduleType"
}

```

Send charging profile to charging station

### Properties ###
<small><em>See OCPP 2.0.1 Specification for ChargingProfileType</em></small>

|Name|Type|Required|Restrictions|Description|
|---|---|---|---|---|
|id|int|true|none|none|
|stackLevel|int|true|none|none|
|chargingProfilePurpose|ChargingProfilePurposeEnumType|true|none|none|
|chargingProfileKind|ChargingProfileKindEnumType|true|none|none|
|recurrencyKind|RecurrencyKindEnumType|false|none|none|
|validFrom|dateTime|false|none|none|
|validTo|dateTime|false|none|none|
|transactionId|identifierString[0..36]|false|none|none|
|chargingSchedule|ChargingScheduleType|true|none|none|

<h2 id="tocS_Token">Token</h2>
<!-- backwards compatibility -->
<a id="schematoken"></a>
Expand Down
38 changes: 38 additions & 0 deletions manager/api/api.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions manager/api/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ func (c ChargeStationTrigger) Bind(r *http.Request) error {
return nil
}

func (c ChargingProfileType) Bind(r *http.Request) error {
return nil
}

func (t Token) Bind(r *http.Request) error {
return nil
}
Expand Down
32 changes: 31 additions & 1 deletion manager/api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ import (
"github.com/thoughtworks/maeve-csms/manager/ocpi"
"net/http"
"time"

"context"
"github.com/getkin/kin-openapi/openapi3"
"github.com/go-chi/render"
"github.com/thoughtworks/maeve-csms/manager/ocpp"
"github.com/thoughtworks/maeve-csms/manager/ocpp/ocpp201"
"github.com/thoughtworks/maeve-csms/manager/store"
"github.com/thoughtworks/maeve-csms/manager/config"
"golang.org/x/exp/slog"
"k8s.io/utils/clock"
)

Expand Down Expand Up @@ -149,6 +152,7 @@ func (s *Server) LookupChargeStationAuth(w http.ResponseWriter, r *http.Request,
}

func (s *Server) TriggerChargeStation(w http.ResponseWriter, r *http.Request, csId string) {
slog.Debug("[API TRACE] in TriggerChargeStation!")
req := new(ChargeStationTrigger)
if err := render.Bind(r, req); err != nil {
_ = render.Render(w, r, ErrInvalidRequest(err))
Expand All @@ -167,6 +171,32 @@ func (s *Server) TriggerChargeStation(w http.ResponseWriter, r *http.Request, cs
w.WriteHeader(http.StatusCreated)
}

func (s *Server) SetChargingProfile(w http.ResponseWriter, r *http.Request, csId string) {
slog.Debug("[API TRACE] In server.go, SetChargingProfile()")
req := new(ChargingProfileType)

if err := render.Bind(r, req); err != nil {
_ = render.Render(w, r, ErrInvalidRequest(err))
return
}

slog.Debug("[API TRACE] req:", req)

// Get the transport.Emitter so that we can send messages
cfg := config.DefaultConfig
settings, _ := config.Configure(context.Background(), &cfg)

// Define the call maker
v201CallMaker := handlers.NewCallMaker(settings.MsgEmitter)

request := ocpp201.SetChargingProfileRequestJson{EvseId: 0, ChargingProfile: ocpp201.ChargingProfileType(*req)}

// Send the call
v201CallMaker.Send(context.Background(), csId, &request)

w.WriteHeader(http.StatusCreated)
}

func (s *Server) SetToken(w http.ResponseWriter, r *http.Request) {
req := new(Token)
if err := render.Bind(r, req); err != nil {
Expand Down
5 changes: 3 additions & 2 deletions manager/handlers/call_maker.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package handlers
import (
"context"
"encoding/json"
"fmt"
"github.com/google/uuid"
"github.com/thoughtworks/maeve-csms/manager/ocpp"
"github.com/thoughtworks/maeve-csms/manager/transport"
Expand All @@ -22,8 +21,10 @@ type OcppCallMaker struct {

func (b OcppCallMaker) Send(ctx context.Context, chargeStationId string, request ocpp.Request) error {
action, ok := b.Actions[reflect.TypeOf(request)]
slog.Debug("[API TRACE] we are in Send() in call_maker.go", "action", action)
if !ok {
return fmt.Errorf("unknown request type: %T", request)
slog.Error("unknown request type", request)
return nil
}

requestBytes, err := json.Marshal(request)
Expand Down
1 change: 1 addition & 0 deletions manager/handlers/ocpp201/routing.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ func NewCallMaker(e transport.Emitter) *handlers.OcppCallMaker {
reflect.TypeOf(&ocpp201.SetVariablesRequestJson{}): "SetVariables",
reflect.TypeOf(&ocpp201.TriggerMessageRequestJson{}): "TriggerMessage",
reflect.TypeOf(&ocpp201.UnlockConnectorRequestJson{}): "UnlockConnector",
reflect.TypeOf(&ocpp201.SetChargingProfileRequestJson{}): "SetChargingProfile",
},
}
}
21 changes: 21 additions & 0 deletions manager/handlers/ocpp201/set_charging_profile_result.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: Apache-2.0

package ocpp201

import (
"context"
"github.com/thoughtworks/maeve-csms/manager/ocpp"
types "github.com/thoughtworks/maeve-csms/manager/ocpp/ocpp201"
"golang.org/x/exp/slog"
)

type SetChargingProfileResultHandler struct{}

func (h SetChargingProfileResultHandler) HandleCallResult(ctx context.Context, chargeStationId string, request ocpp.Request, response ocpp.Response, state any) error {
req := request.(*types.SetChargingProfileRequestJson)
resp := response.(*types.SetChargingProfileResponseJson)

slog.Debug("[API TRACE] in scp_result.go, got response:", resp, "[API TRACE] From request:", req)

return nil
}
6 changes: 6 additions & 0 deletions manager/handlers/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ func (r Router) Handle(ctx context.Context, chargeStationId string, msg *transpo
span := trace.SpanFromContext(ctx)

err := r.route(ctx, chargeStationId, msg)

// TODO: Handle setChargingProfile response here if we want to do more on CSMS side!

if err != nil {
slog.Error("unable to route message", slog.String("chargeStationId", chargeStationId), slog.String("action", msg.Action), "err", err)
span.SetStatus(codes.Error, "routing request failed")
Expand All @@ -54,9 +57,11 @@ func (r Router) Handle(ctx context.Context, chargeStationId string, msg *transpo
}

func (r Router) route(ctx context.Context, chargeStationId string, message *transport.Message) error {
slog.Debug("[API TRACE] we are in route() in router.go", "action", message.Action)
switch message.MessageType {
case transport.MessageTypeCall:
route, ok := r.CallRoutes[message.Action]
slog.Debug("[API TRACE] we are in route() in router.go, in MessageTypeCall", "route", route)
if !ok {
return fmt.Errorf("routing request: %w", transport.NewError(transport.ErrorNotImplemented, fmt.Errorf("%s not implemented", message.Action)))
}
Expand Down Expand Up @@ -101,6 +106,7 @@ func (r Router) route(ctx context.Context, chargeStationId string, message *tran
}
case transport.MessageTypeCallResult:
route, ok := r.CallResultRoutes[message.Action]
slog.Debug("[API TRACE] we are in route() in router.go, in MessageTypeCallResult", "route", route)
if !ok {
return fmt.Errorf("routing request: %w", transport.NewError(transport.ErrorNotImplemented, fmt.Errorf("%s result not implemented", message.Action)))
}
Expand Down
8 changes: 8 additions & 0 deletions manager/ocpp/ocpp201/set_charging_profile_request.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ocpp201

type SetChargingProfileRequestJson struct {
EvseId int `json:"evseId"`
ChargingProfile ChargingProfileType `json:"chargingProfile"`
}

func (*SetChargingProfileRequestJson) IsRequest() {}
17 changes: 17 additions & 0 deletions manager/ocpp/ocpp201/set_charging_profile_response.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: Apache-2.0

package ocpp201

type ChargingProfileStatusEnumType string

const (
Accepted ChargingProfileStatusEnumType = "Accepted"
Rejected ChargingProfileStatusEnumType = "Rejected"
)

type SetChargingProfileResponseJson struct {
Status ChargingProfileStatusEnumType `json:"status"`
StatusInfo StatusInfoType `json:"statusInfo"`
}

func (*SetChargingProfileResponseJson) IsResponse() {}
1 change: 1 addition & 0 deletions manager/sync/triggers.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func SyncTriggers(ctx context.Context,
trace.WithAttributes(attribute.String("sync.trigger.previous", previousChargeStationId)))
defer span.End()
triggerMessages, err := engine.ListChargeStationTriggerMessages(ctx, 50, previousChargeStationId)
slog.Debug("[API TRACE] we are in SyncTriggers() in triggers.go", "triggerMessages", triggerMessages)
if err != nil {
span.RecordError(err)
return
Expand Down