-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added ILogger support, example program with DI and configuration/logg…
…ing (#3) Updated to .NET 8 and file scoped namespaces
- Loading branch information
1 parent
06c08a1
commit 7af64f0
Showing
26 changed files
with
525 additions
and
451 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
namespace NissanConnectLib.Example; | ||
|
||
internal class Configuration | ||
{ | ||
public string TokenCacheFile { get; set; } = "token.cache"; | ||
public string? Username { get; set; } | ||
public string? Password { get; set; } | ||
public bool ForceBatteryStatusRefresh { get; set; } = false; | ||
} |
27 changes: 27 additions & 0 deletions
27
NissanConnect/NissanConnectLib.Example/CustomConsoleFormatter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
using Microsoft.Extensions.Logging; | ||
using Microsoft.Extensions.Logging.Abstractions; | ||
using Microsoft.Extensions.Logging.Console; | ||
|
||
namespace NissanConnectLib.Example; | ||
|
||
internal class CustomConsoleFormatter : ConsoleFormatter | ||
{ | ||
public CustomConsoleFormatter() : base(nameof(CustomConsoleFormatter)) { } | ||
|
||
public override void Write<TState>(in LogEntry<TState> logEntry, IExternalScopeProvider? scopeProvider, TextWriter textWriter) | ||
{ | ||
var message = logEntry.Formatter(logEntry.State, logEntry.Exception); | ||
|
||
if (string.IsNullOrEmpty(message)) | ||
{ | ||
return; | ||
} | ||
|
||
textWriter.WriteLine($"[{DateTime.Now}] [{logEntry.LogLevel,11}] {message}"); | ||
|
||
if (logEntry.Exception is not null) | ||
{ | ||
textWriter.WriteLine($"[{DateTime.Now}] [{logEntry.LogLevel,11}] {logEntry.Exception.Message}"); | ||
} | ||
} | ||
} |
169 changes: 169 additions & 0 deletions
169
NissanConnect/NissanConnectLib.Example/NissanConnectHostedService.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
using Microsoft.Extensions.Logging; | ||
using Microsoft.Extensions.Hosting; | ||
using NissanConnectLib.Api; | ||
using NissanConnectLib.Models; | ||
using System.Text.Json; | ||
|
||
namespace NissanConnectLib.Example; | ||
|
||
internal class NissanConnectHostedService : IHostedService | ||
{ | ||
private readonly NissanConnectClient _ncc; | ||
private readonly Configuration _config; | ||
private readonly ILogger<NissanConnectHostedService> _logger; | ||
|
||
public NissanConnectHostedService( | ||
NissanConnectClient ncc, | ||
Configuration config, | ||
ILogger<NissanConnectHostedService> logger) | ||
{ | ||
_ncc = ncc; | ||
_config = config; | ||
_logger = logger; | ||
} | ||
|
||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2254:Template should be a static expression", Justification = "<Pending>")] | ||
public async Task StartAsync(CancellationToken cancellationToken) | ||
{ | ||
try | ||
{ | ||
await RunExample(); | ||
} | ||
catch (Exception e) | ||
{ | ||
_logger.LogError(e, "Error running example"); | ||
} | ||
} | ||
|
||
public Task StopAsync(CancellationToken cancellationToken) | ||
{ | ||
_logger.LogInformation("Stopping Nissan Connect Hosted Service"); | ||
return Task.CompletedTask; | ||
} | ||
|
||
private async Task RunExample() | ||
{ | ||
var loggedIn = false; | ||
|
||
// Save token to cache file when refreshed | ||
_ncc.AccessTokenRefreshed += (sender, token) => | ||
{ | ||
_logger.LogInformation("Access token refreshed!"); | ||
File.WriteAllText(_config.TokenCacheFile, JsonSerializer.Serialize(token)); | ||
}; | ||
|
||
// Try to use token cache file | ||
if (File.Exists(_config.TokenCacheFile)) | ||
{ | ||
var cachedToken = JsonSerializer.Deserialize<OAuthAccessTokenResult>(File.ReadAllText(_config.TokenCacheFile)); | ||
_ncc.AccessToken = cachedToken; | ||
|
||
if (await _ncc.GetUserId() is null) | ||
{ | ||
_logger.LogWarning("Could not get user ID using cached token, deleting cache file..."); | ||
File.Delete(_config.TokenCacheFile); | ||
} | ||
else | ||
{ | ||
_logger.LogInformation("Cached token is valid!"); | ||
loggedIn = true; | ||
} | ||
} | ||
|
||
// Log in using username and password | ||
if (!loggedIn) | ||
{ | ||
// Are we missing arguments? | ||
if (string.IsNullOrEmpty(_config.Username) || string.IsNullOrEmpty(_config.Password)) | ||
{ | ||
_logger.LogError("Configuration is missing. Specify username and password"); | ||
return; | ||
} | ||
|
||
// Log in using a username and password | ||
loggedIn = await _ncc.LogIn(_config.Username, _config.Password); | ||
if (loggedIn) | ||
{ | ||
_logger.LogInformation("Logged in using username and password. Writing token to cache file..."); | ||
File.WriteAllText(_config.TokenCacheFile, JsonSerializer.Serialize(_ncc.AccessToken)); | ||
} | ||
else | ||
{ | ||
_logger.LogError("Login failed!"); | ||
return; | ||
} | ||
} | ||
|
||
// Get the user id | ||
var userId = await _ncc.GetUserId(); | ||
if (userId == null) | ||
{ | ||
_logger.LogError("Couldn't get user!"); | ||
return; | ||
} | ||
_logger.LogInformation($"Logged in as: {userId[..5]}**********"); | ||
_logger.LogInformation($"Access Token: {_ncc.AccessToken?.AccessToken?[..5] ?? "null"}**********"); | ||
|
||
// Get all cars | ||
var cars = await _ncc.GetCars(userId); | ||
if (cars == null) | ||
{ | ||
_logger.LogError("Couldn't get cars!"); | ||
return; | ||
} | ||
_logger.LogInformation($"Found {cars.Count} car(s)!"); | ||
|
||
// List all cars and their battery status | ||
foreach (var car in cars) | ||
{ | ||
if (car.Vin is null) continue; | ||
|
||
_logger.LogInformation("Cars:"); | ||
_logger.LogInformation($" Nickname: {car.NickName}"); | ||
_logger.LogInformation($" ModelName: {car.ModelName}"); | ||
_logger.LogInformation($" ModelCode: {car.ModelCode}"); | ||
_logger.LogInformation($" ModelYear: {car.ModelYear}"); | ||
_logger.LogInformation($" VIN: {car.Vin[..3]}**********"); | ||
|
||
// Get battery status for car | ||
var bs = await _ncc.GetBatteryStatus(car.Vin, _config.ForceBatteryStatusRefresh); | ||
if (bs == null) | ||
{ | ||
_logger.LogWarning(" Couldn't get battery status!"); | ||
continue; | ||
} | ||
_logger.LogInformation($" BatteryStatus"); | ||
_logger.LogInformation($" BatteryLevel: {bs.BatteryLevel}%"); | ||
_logger.LogInformation($" RangeHvacOff: {bs.RangeHvacOff} km"); | ||
_logger.LogInformation($" RangeHvacOn: {bs.RangeHvacOn} km"); | ||
_logger.LogInformation($" LastUpdateTime: {bs.LastUpdateTime}"); | ||
_logger.LogInformation($" BatteryStatusAge: {bs.BatteryStatusAge}"); | ||
_logger.LogInformation($" PlugStatus: {bs.PlugStatus}"); | ||
_logger.LogInformation($" PlugStatusDetail: {bs.PlugStatusDetail}"); | ||
_logger.LogInformation($" ChargeStatus: {bs.ChargeStatus}"); | ||
_logger.LogInformation($" ChargePower: {bs.ChargePower}"); | ||
|
||
// Get HVAC status for car | ||
var hvacs = await _ncc.GetHvacStatus(car.Vin); | ||
if (hvacs == null) | ||
{ | ||
_logger.LogWarning(" Couldn't get HVAC status!"); | ||
continue; | ||
} | ||
_logger.LogInformation($" HvacStatus"); | ||
_logger.LogInformation($" SocThreshold: {hvacs.SocThreshold}%"); | ||
_logger.LogInformation($" LastUpdateTime: {hvacs.LastUpdateTime}"); | ||
_logger.LogInformation($" HvacStatus: {hvacs.HvacStatus}"); | ||
|
||
// Get cockpit status for car | ||
var cs = await _ncc.GetCockpitStatus(car.Vin); | ||
if (cs == null) | ||
{ | ||
_logger.LogWarning(" Couldn't get cockpit status!"); | ||
continue; | ||
} | ||
_logger.LogInformation($" Cockpit"); | ||
_logger.LogInformation($" TotalMileage: {cs.TotalMileage} km"); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.