Skip to content

Commit 7af64f0

Browse files
authored
Added ILogger support, example program with DI and configuration/logging (#3)
Updated to .NET 8 and file scoped namespaces
1 parent 06c08a1 commit 7af64f0

26 files changed

+525
-451
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace NissanConnectLib.Example;
2+
3+
internal class Configuration
4+
{
5+
public string TokenCacheFile { get; set; } = "token.cache";
6+
public string? Username { get; set; }
7+
public string? Password { get; set; }
8+
public bool ForceBatteryStatusRefresh { get; set; } = false;
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using Microsoft.Extensions.Logging;
2+
using Microsoft.Extensions.Logging.Abstractions;
3+
using Microsoft.Extensions.Logging.Console;
4+
5+
namespace NissanConnectLib.Example;
6+
7+
internal class CustomConsoleFormatter : ConsoleFormatter
8+
{
9+
public CustomConsoleFormatter() : base(nameof(CustomConsoleFormatter)) { }
10+
11+
public override void Write<TState>(in LogEntry<TState> logEntry, IExternalScopeProvider? scopeProvider, TextWriter textWriter)
12+
{
13+
var message = logEntry.Formatter(logEntry.State, logEntry.Exception);
14+
15+
if (string.IsNullOrEmpty(message))
16+
{
17+
return;
18+
}
19+
20+
textWriter.WriteLine($"[{DateTime.Now}] [{logEntry.LogLevel,11}] {message}");
21+
22+
if (logEntry.Exception is not null)
23+
{
24+
textWriter.WriteLine($"[{DateTime.Now}] [{logEntry.LogLevel,11}] {logEntry.Exception.Message}");
25+
}
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
using Microsoft.Extensions.Logging;
2+
using Microsoft.Extensions.Hosting;
3+
using NissanConnectLib.Api;
4+
using NissanConnectLib.Models;
5+
using System.Text.Json;
6+
7+
namespace NissanConnectLib.Example;
8+
9+
internal class NissanConnectHostedService : IHostedService
10+
{
11+
private readonly NissanConnectClient _ncc;
12+
private readonly Configuration _config;
13+
private readonly ILogger<NissanConnectHostedService> _logger;
14+
15+
public NissanConnectHostedService(
16+
NissanConnectClient ncc,
17+
Configuration config,
18+
ILogger<NissanConnectHostedService> logger)
19+
{
20+
_ncc = ncc;
21+
_config = config;
22+
_logger = logger;
23+
}
24+
25+
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2254:Template should be a static expression", Justification = "<Pending>")]
26+
public async Task StartAsync(CancellationToken cancellationToken)
27+
{
28+
try
29+
{
30+
await RunExample();
31+
}
32+
catch (Exception e)
33+
{
34+
_logger.LogError(e, "Error running example");
35+
}
36+
}
37+
38+
public Task StopAsync(CancellationToken cancellationToken)
39+
{
40+
_logger.LogInformation("Stopping Nissan Connect Hosted Service");
41+
return Task.CompletedTask;
42+
}
43+
44+
private async Task RunExample()
45+
{
46+
var loggedIn = false;
47+
48+
// Save token to cache file when refreshed
49+
_ncc.AccessTokenRefreshed += (sender, token) =>
50+
{
51+
_logger.LogInformation("Access token refreshed!");
52+
File.WriteAllText(_config.TokenCacheFile, JsonSerializer.Serialize(token));
53+
};
54+
55+
// Try to use token cache file
56+
if (File.Exists(_config.TokenCacheFile))
57+
{
58+
var cachedToken = JsonSerializer.Deserialize<OAuthAccessTokenResult>(File.ReadAllText(_config.TokenCacheFile));
59+
_ncc.AccessToken = cachedToken;
60+
61+
if (await _ncc.GetUserId() is null)
62+
{
63+
_logger.LogWarning("Could not get user ID using cached token, deleting cache file...");
64+
File.Delete(_config.TokenCacheFile);
65+
}
66+
else
67+
{
68+
_logger.LogInformation("Cached token is valid!");
69+
loggedIn = true;
70+
}
71+
}
72+
73+
// Log in using username and password
74+
if (!loggedIn)
75+
{
76+
// Are we missing arguments?
77+
if (string.IsNullOrEmpty(_config.Username) || string.IsNullOrEmpty(_config.Password))
78+
{
79+
_logger.LogError("Configuration is missing. Specify username and password");
80+
return;
81+
}
82+
83+
// Log in using a username and password
84+
loggedIn = await _ncc.LogIn(_config.Username, _config.Password);
85+
if (loggedIn)
86+
{
87+
_logger.LogInformation("Logged in using username and password. Writing token to cache file...");
88+
File.WriteAllText(_config.TokenCacheFile, JsonSerializer.Serialize(_ncc.AccessToken));
89+
}
90+
else
91+
{
92+
_logger.LogError("Login failed!");
93+
return;
94+
}
95+
}
96+
97+
// Get the user id
98+
var userId = await _ncc.GetUserId();
99+
if (userId == null)
100+
{
101+
_logger.LogError("Couldn't get user!");
102+
return;
103+
}
104+
_logger.LogInformation($"Logged in as: {userId[..5]}**********");
105+
_logger.LogInformation($"Access Token: {_ncc.AccessToken?.AccessToken?[..5] ?? "null"}**********");
106+
107+
// Get all cars
108+
var cars = await _ncc.GetCars(userId);
109+
if (cars == null)
110+
{
111+
_logger.LogError("Couldn't get cars!");
112+
return;
113+
}
114+
_logger.LogInformation($"Found {cars.Count} car(s)!");
115+
116+
// List all cars and their battery status
117+
foreach (var car in cars)
118+
{
119+
if (car.Vin is null) continue;
120+
121+
_logger.LogInformation("Cars:");
122+
_logger.LogInformation($" Nickname: {car.NickName}");
123+
_logger.LogInformation($" ModelName: {car.ModelName}");
124+
_logger.LogInformation($" ModelCode: {car.ModelCode}");
125+
_logger.LogInformation($" ModelYear: {car.ModelYear}");
126+
_logger.LogInformation($" VIN: {car.Vin[..3]}**********");
127+
128+
// Get battery status for car
129+
var bs = await _ncc.GetBatteryStatus(car.Vin, _config.ForceBatteryStatusRefresh);
130+
if (bs == null)
131+
{
132+
_logger.LogWarning(" Couldn't get battery status!");
133+
continue;
134+
}
135+
_logger.LogInformation($" BatteryStatus");
136+
_logger.LogInformation($" BatteryLevel: {bs.BatteryLevel}%");
137+
_logger.LogInformation($" RangeHvacOff: {bs.RangeHvacOff} km");
138+
_logger.LogInformation($" RangeHvacOn: {bs.RangeHvacOn} km");
139+
_logger.LogInformation($" LastUpdateTime: {bs.LastUpdateTime}");
140+
_logger.LogInformation($" BatteryStatusAge: {bs.BatteryStatusAge}");
141+
_logger.LogInformation($" PlugStatus: {bs.PlugStatus}");
142+
_logger.LogInformation($" PlugStatusDetail: {bs.PlugStatusDetail}");
143+
_logger.LogInformation($" ChargeStatus: {bs.ChargeStatus}");
144+
_logger.LogInformation($" ChargePower: {bs.ChargePower}");
145+
146+
// Get HVAC status for car
147+
var hvacs = await _ncc.GetHvacStatus(car.Vin);
148+
if (hvacs == null)
149+
{
150+
_logger.LogWarning(" Couldn't get HVAC status!");
151+
continue;
152+
}
153+
_logger.LogInformation($" HvacStatus");
154+
_logger.LogInformation($" SocThreshold: {hvacs.SocThreshold}%");
155+
_logger.LogInformation($" LastUpdateTime: {hvacs.LastUpdateTime}");
156+
_logger.LogInformation($" HvacStatus: {hvacs.HvacStatus}");
157+
158+
// Get cockpit status for car
159+
var cs = await _ncc.GetCockpitStatus(car.Vin);
160+
if (cs == null)
161+
{
162+
_logger.LogWarning(" Couldn't get cockpit status!");
163+
continue;
164+
}
165+
_logger.LogInformation($" Cockpit");
166+
_logger.LogInformation($" TotalMileage: {cs.TotalMileage} km");
167+
}
168+
}
169+
}

NissanConnect/NissanConnectLib.Example/NissanConnectLib.Example.csproj

+6-1
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,16 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFramework>net6.0</TargetFramework>
5+
<TargetFramework>net8.0</TargetFramework>
66
<ImplicitUsings>enable</ImplicitUsings>
77
<Nullable>enable</Nullable>
8+
<UserSecretsId>d454171b-3384-4901-807c-335902959850</UserSecretsId>
89
</PropertyGroup>
910

11+
<ItemGroup>
12+
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
13+
</ItemGroup>
14+
1015
<ItemGroup>
1116
<ProjectReference Include="..\NissanConnectLib\NissanConnectLib.csproj" />
1217
</ItemGroup>

0 commit comments

Comments
 (0)