From c87c09dde3a2d7fdba41e076d997b6861f966e74 Mon Sep 17 00:00:00 2001 From: Willem Serruys Date: Fri, 21 Aug 2026 08:02:09 +0200 Subject: [PATCH] chore: added smappee api --- docker-compose.yml | 19 ++++++++++++++ smappee-api/Dockerfile | 17 +++++++++++++ smappee-api/Program.cs | 11 ++++---- smappee-api/appsettings.Development.json | 9 +++++-- smappee-api/docker-compose.yml | 7 ++++++ smappee-api/services/SmappeeChargerService.cs | 4 +-- smappee-api/services/SmappeeTokenService.cs | 25 ++++++++----------- 7 files changed, 67 insertions(+), 25 deletions(-) create mode 100644 smappee-api/Dockerfile create mode 100644 smappee-api/docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml index 1d1c97f..2dc038f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -131,6 +131,25 @@ services: # Only enable if external services present # ports: # - 4317:4317 # OTLP gRPC receiver + smappee-api: + build: + context: ./smappee-api + labels: + - traefik.http.routers.smappeeapi.rule=Host(`smappee.pladijs`) + - traefik.http.services.smappeeapi.loadbalancer.server.port=8080 + environment: + ASPNETCORE_ENVIRONMENT: Production + env_file: + - environment-variables/local.env + - environment-variables/production.env + restart: unless-stopped + smappee-api: + build: ./smappee-api + env_file: + - .env.smappee + labels: + - traefik.http.routers.smappee.rule=Host(`smappee.pladijs`) + - traefik.http.services.smappee.loadbalancer.server.port=8080 energy-management: build: context: ./energy-management diff --git a/smappee-api/Dockerfile b/smappee-api/Dockerfile new file mode 100644 index 0000000..10a602a --- /dev/null +++ b/smappee-api/Dockerfile @@ -0,0 +1,17 @@ +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build +WORKDIR /src + +COPY smappee-api.csproj ./ +RUN dotnet restore + +COPY . . +RUN dotnet publish -c Release -o /app + +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime +WORKDIR /app +COPY --from=build /app . + +ENV ASPNETCORE_URLS=http://+:8080 +EXPOSE 8080 + +ENTRYPOINT ["dotnet", "smappee-api.dll"] diff --git a/smappee-api/Program.cs b/smappee-api/Program.cs index abce3ca..d262ba2 100644 --- a/smappee-api/Program.cs +++ b/smappee-api/Program.cs @@ -31,12 +31,11 @@ app.MapPost( app.MapPost( "/disable", - () => - async (IChargerService chargerService) => - { - await chargerService.ExecuteRequest(ChargerRequests.Disable); - return; - } + async (IChargerService chargerService) => + { + await chargerService.ExecuteRequest(ChargerRequests.Disable); + return; + } ) .WithName("Disable"); diff --git a/smappee-api/appsettings.Development.json b/smappee-api/appsettings.Development.json index b16b55c..f27f46a 100644 --- a/smappee-api/appsettings.Development.json +++ b/smappee-api/appsettings.Development.json @@ -3,6 +3,9 @@ "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Information" + }, + "Console": { + "FormatterName": "json" } }, "CHARGER": { @@ -17,8 +20,11 @@ "HttpClientLogging": { "LogRequestStart": false, "LogBody": true, + "LogContentHeaders": true, "BodySizeLimit": 32768, "BodyReadTimeout": "00:00:01", + "RequestBodyContentTypes": [ "application/json", "application/x-www-form-urlencoded" ], + "ResponseBodyContentTypes": [ "application/json" ], "RequestHeadersDataClasses": { "User-Agent": "None", "Content-Type": "None" @@ -26,7 +32,6 @@ "ResponseHeadersDataClasses": { "Content-Type": "None" }, - "RequestPathLoggingMode": "Formatted", - "RequestPathParameterRedactionMode": "Strict" + "RequestPathParameterRedactionMode": "None" } } diff --git a/smappee-api/docker-compose.yml b/smappee-api/docker-compose.yml new file mode 100644 index 0000000..6be53ba --- /dev/null +++ b/smappee-api/docker-compose.yml @@ -0,0 +1,7 @@ +services: + smappee-api: + build: . + ports: + - "5057:8080" + env_file: + - .env diff --git a/smappee-api/services/SmappeeChargerService.cs b/smappee-api/services/SmappeeChargerService.cs index 78ab00a..d43ab5c 100644 --- a/smappee-api/services/SmappeeChargerService.cs +++ b/smappee-api/services/SmappeeChargerService.cs @@ -33,11 +33,11 @@ internal class SmappeeChargerService : IChargerService var response = request switch { ChargerRequests.Enable => await httpClient.PutAsJsonAsync( - $"/dev/v3/chargingstations/${options.ChargingStation}/connectors/{options.Connector}/mode", + $"/dev/v3/chargingstations/{options.ChargingStation}/connectors/{options.Connector}/mode", new SmappeeRequestBody("NORMAL", new Limit("AMPERE", 6)) ), ChargerRequests.Disable => await httpClient.PutAsJsonAsync( - "/dev/v3/chargingstations", + $"/dev/v3/chargingstations/{options.ChargingStation}/connectors/{options.Connector}/mode", new SmappeeRequestBody("PAUSED", null) ), _ => throw new NotImplementedException(), diff --git a/smappee-api/services/SmappeeTokenService.cs b/smappee-api/services/SmappeeTokenService.cs index be272f6..2272299 100644 --- a/smappee-api/services/SmappeeTokenService.cs +++ b/smappee-api/services/SmappeeTokenService.cs @@ -39,14 +39,17 @@ internal class SmappeeTokenService : IBearerTokenService var httpClient = httpClientFactory.CreateClient("smappeeTokenService"); httpClient.BaseAddress = options.Url; - var result = await httpClient.PostAsJsonAsync( + var result = await httpClient.PostAsync( "/dev/v3/oauth2/token", - new TokenRequestBody( - "password", - options.ClientId, - options.ClientSecret, - options.UserName, - options.Password + new FormUrlEncodedContent( + new Dictionary + { + ["grant_type"] = "password", + ["client_id"] = options.ClientId, + ["client_secret"] = options.ClientSecret, + ["username"] = options.UserName, + ["password"] = options.Password, + } ) ); result.EnsureSuccessStatusCode(); @@ -59,14 +62,6 @@ internal class SmappeeTokenService : IBearerTokenService ); } - record TokenRequestBody( - string grant_type, - string client_id, - string client_secret, - string username, - string password - ); - record TokenResponse(string access_token, int expires_in); record TokenData(string Token, DateTime Expiration);