diff --git a/ora2mqtt/BaseCommand.cs b/ora2mqtt/BaseCommand.cs index 3ecf60c..e6899e1 100644 --- a/ora2mqtt/BaseCommand.cs +++ b/ora2mqtt/BaseCommand.cs @@ -2,15 +2,27 @@ using libgwmapi; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; +using Microsoft.Extensions.Http.Logging; +using Microsoft.Extensions.Logging; using YamlDotNet.Serialization; namespace ora2mqtt; public abstract class BaseCommand { + [Option('d', "debug", Default = false, HelpText = "enable debug logging")] + public bool Debug { get; set; } + [Option('c', "config", Default = "ora2mqtt.yml", HelpText = "path to yaml config file")] public string ConfigFile { get; set; } + protected ILoggerFactory LoggerFactory { get; private set; } + + protected void Setup() + { + LoggerFactory = Microsoft.Extensions.Logging.LoggerFactory.Create(x => x.SetMinimumLevel(Debug ? LogLevel.Trace : LogLevel.Error).AddConsole()); + } + protected GwmApiClient ConfigureApiClient(Ora2MqttOptions options) { var certHandler = new CertificateHandler(); @@ -39,7 +51,16 @@ protected GwmApiClient ConfigureApiClient(Ora2MqttOptions options) } } - return new GwmApiClient(new HttpClient(), new HttpClient(httpHandler)) + var httpLogger = LoggerFactory.CreateLogger(); + var h5Client = new HttpClient(new LoggingHttpMessageHandler(httpLogger) + { + InnerHandler = new HttpClientHandler() + }); + var appClient = new HttpClient(new LoggingHttpMessageHandler(httpLogger) + { + InnerHandler = httpHandler + }); + return new GwmApiClient(h5Client, appClient) { Country = options.Country }; diff --git a/ora2mqtt/ConfigureCommand.cs b/ora2mqtt/ConfigureCommand.cs index 7918c42..2959c79 100644 --- a/ora2mqtt/ConfigureCommand.cs +++ b/ora2mqtt/ConfigureCommand.cs @@ -7,16 +7,20 @@ using Sharprompt; using Sharprompt.Fluent; using YamlDotNet.Serialization; -using System.Runtime.InteropServices; -using System.Security.Cryptography.X509Certificates; +using ora2mqtt.Logging; +using Microsoft.Extensions.Logging; namespace ora2mqtt { [Verb("configure", HelpText = "run config file wizard")] public class ConfigureCommand:BaseCommand { + private ILogger _logger; + public async Task Run(CancellationToken cancellationToken) { + Setup(); + _logger = LoggerFactory.CreateLogger(); Ora2MqttOptions config; if (!File.Exists(ConfigFile)) { @@ -76,7 +80,7 @@ private async Task LoginAsync(GwmApiClient client, Ora2MqttOptions options, Canc } catch (GwmApiException e) { - await Console.Error.WriteLineAsync($"Access token expired ({e.Message}). Trying to refresh token..."); + _logger.LogError($"Access token expired ({e.Message}). Trying to refresh token..."); } var refresh = new RefreshTokenRequest { @@ -94,7 +98,7 @@ private async Task LoginAsync(GwmApiClient client, Ora2MqttOptions options, Canc } catch (GwmApiException e) { - await Console.Error.WriteLineAsync($"Token refresh failed: {e.Message}"); + _logger.LogError($"Token refresh failed: {e.Message}"); } } var request = new LoginAccountRequest @@ -160,7 +164,7 @@ private async Task TestMqttAsync(Ora2MqttOptions oraOptions, CancellationT try { - var factory = new MqttFactory(); + var factory = new MqttFactory(new MqttLogger(LoggerFactory)); using var client = factory.CreateMqttClient(); var builder = new MqttClientOptionsBuilder() .WithTcpServer(options.Host); @@ -174,7 +178,7 @@ private async Task TestMqttAsync(Ora2MqttOptions oraOptions, CancellationT } catch (MqttCommunicationException ex) { - await Console.Error.WriteLineAsync($"Mqtt connection failed: {ex.Message}"); + _logger.LogError($"Mqtt connection failed: {ex.Message}"); return false; } return true; diff --git a/ora2mqtt/Logging/MqttLogger.cs b/ora2mqtt/Logging/MqttLogger.cs new file mode 100644 index 0000000..13a9f2b --- /dev/null +++ b/ora2mqtt/Logging/MqttLogger.cs @@ -0,0 +1,30 @@ +using Microsoft.Extensions.Logging; +using MQTTnet.Diagnostics; + +namespace ora2mqtt.Logging +{ + internal class MqttLogger: IMqttNetLogger + { + private readonly ILogger _logger; + + public MqttLogger(ILoggerFactory factory) + { + _logger = factory.CreateLogger(); + } + + public void Publish(MqttNetLogLevel logLevel, string source, string message, object[] parameters, Exception exception) + { + var level = logLevel switch + { + MqttNetLogLevel.Verbose => LogLevel.Debug, + MqttNetLogLevel.Info => LogLevel.Information, + MqttNetLogLevel.Warning => LogLevel.Warning, + MqttNetLogLevel.Error => LogLevel.Error, + _ => throw new ArgumentOutOfRangeException(nameof(logLevel)) + }; + _logger.Log(level, exception, message, parameters); + } + + public bool IsEnabled => true; + } +} diff --git a/ora2mqtt/Program.cs b/ora2mqtt/Program.cs index 69319ee..635535e 100644 --- a/ora2mqtt/Program.cs +++ b/ora2mqtt/Program.cs @@ -1,18 +1,8 @@ -using System.Runtime.InteropServices; -using System.Security.Cryptography.X509Certificates; -using CommandLine; -using libgwmapi; -using libgwmapi.DTO.UserAuth; -using MQTTnet; -using MQTTnet.Client; -using MQTTnet.Exceptions; +using CommandLine; using ora2mqtt; -using Sharprompt; -using Sharprompt.Fluent; -using YamlDotNet.Serialization; using var cts = new CancellationTokenSource(); -Console.CancelKeyPress += (s, e) => +Console.CancelKeyPress += (_, e) => { cts.Cancel(); e.Cancel = true; diff --git a/ora2mqtt/RunCommand.cs b/ora2mqtt/RunCommand.cs index 1c9671e..dda6889 100644 --- a/ora2mqtt/RunCommand.cs +++ b/ora2mqtt/RunCommand.cs @@ -4,22 +4,27 @@ using MQTTnet.Client; using MQTTnet; using YamlDotNet.Serialization; -using MQTTnet.Server; using libgwmapi.DTO.UserAuth; +using Microsoft.Extensions.Logging; +using ora2mqtt.Logging; namespace ora2mqtt; [Verb("run", true, HelpText = "default")] public class RunCommand:BaseCommand { + private ILogger _logger; + [Option('i', "interval", Default = 10, HelpText = "GWM API polling interval")] public int Intervall { get; set; } public async Task Run(CancellationToken cancellationToken) { + Setup(); + _logger = LoggerFactory.CreateLogger(); if (!File.Exists(ConfigFile)) { - await Console.Error.WriteLineAsync($"config file ({ConfigFile}) missing"); + _logger.LogError($"config file ({ConfigFile}) missing"); return 1; } Ora2MqttOptions config; @@ -52,7 +57,7 @@ public async Task Run(CancellationToken cancellationToken) private async Task ConnectMqttAsync(Ora2MqttMqttOptions options,CancellationToken cancellationToken) { - var factory = new MqttFactory(); + var factory = new MqttFactory(new MqttLogger(LoggerFactory)); var client = factory.CreateMqttClient(); var builder = new MqttClientOptionsBuilder() .WithTcpServer(options.Host); @@ -90,7 +95,7 @@ private async Task RefreshTokenAsync(GwmApiClient client, Ora2MqttOptions option } catch (GwmApiException e) { - await Console.Error.WriteLineAsync($"Access token expired ({e.Message}). Trying to refresh token..."); + _logger.LogError($"Access token expired ({e.Message}). Trying to refresh token..."); } var refresh = new RefreshTokenRequest diff --git a/ora2mqtt/ora2mqtt.csproj b/ora2mqtt/ora2mqtt.csproj index 903baf9..f31d271 100644 --- a/ora2mqtt/ora2mqtt.csproj +++ b/ora2mqtt/ora2mqtt.csproj @@ -9,6 +9,7 @@ +