Skip to content

Commit

Permalink
Added ILogger support, example program with DI and configuration/logg…
Browse files Browse the repository at this point in the history
…ing (#3)

Updated to .NET 8 and file scoped namespaces
  • Loading branch information
hagronnestad authored Aug 15, 2024
1 parent 06c08a1 commit 7af64f0
Show file tree
Hide file tree
Showing 26 changed files with 525 additions and 451 deletions.
9 changes: 9 additions & 0 deletions NissanConnect/NissanConnectLib.Example/Configuration.cs
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 NissanConnect/NissanConnectLib.Example/CustomConsoleFormatter.cs
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 NissanConnect/NissanConnectLib.Example/NissanConnectHostedService.cs
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");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UserSecretsId>d454171b-3384-4901-807c-335902959850</UserSecretsId>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\NissanConnectLib\NissanConnectLib.csproj" />
</ItemGroup>
Expand Down
Loading

0 comments on commit 7af64f0

Please sign in to comment.