Files
homeAutomation/smappee-api/services/SmappeeTokenService.cs
2026-08-21 08:02:09 +02:00

69 lines
2.1 KiB
C#

using interfaces;
using Microsoft.Extensions.Options;
using options;
namespace services;
internal class SmappeeTokenService : IBearerTokenService
{
private readonly ChargerOptions options;
private readonly IHttpClientFactory httpClientFactory;
private TokenData? tokenData = null;
public SmappeeTokenService(
IOptions<ChargerOptions> options,
IHttpClientFactory httpClientFactory
)
{
this.options = options?.Value ?? throw new ArgumentNullException(nameof(options));
this.httpClientFactory =
httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
}
public async ValueTask<string> GetToken(bool forceNewToken)
{
if (
tokenData == null
|| tokenData.Expiration < DateTime.UtcNow.AddSeconds(-10)
|| forceNewToken
)
{
tokenData = await RequestNewToken();
}
return tokenData.Token;
}
private async Task<TokenData> RequestNewToken()
{
var httpClient = httpClientFactory.CreateClient("smappeeTokenService");
httpClient.BaseAddress = options.Url;
var result = await httpClient.PostAsync(
"/dev/v3/oauth2/token",
new FormUrlEncodedContent(
new Dictionary<string, string>
{
["grant_type"] = "password",
["client_id"] = options.ClientId,
["client_secret"] = options.ClientSecret,
["username"] = options.UserName,
["password"] = options.Password,
}
)
);
result.EnsureSuccessStatusCode();
var tokenResponse =
await result.Content.ReadFromJsonAsync<TokenResponse>()
?? throw new InvalidOperationException("Token could not be fetched");
return new TokenData(
tokenResponse.access_token,
DateTime.UtcNow.AddSeconds(tokenResponse.expires_in)
);
}
record TokenResponse(string access_token, int expires_in);
record TokenData(string Token, DateTime Expiration);
}