diff --git a/EpsonPrintService/HeartbeatBackgroundTask.cs b/EpsonPrintService/HeartbeatBackgroundTask.cs new file mode 100644 index 0000000..8c5629a --- /dev/null +++ b/EpsonPrintService/HeartbeatBackgroundTask.cs @@ -0,0 +1,105 @@ +using Inspectron.Epson.PrintServer.ConfigurationSources; +using Microsoft.Extensions.Logging; +using System.Net.Http.Json; +using System.Text.Json.Serialization; + +namespace EpsonPrintService; + +/// +/// Background task that periodically sends heartbeat signals to the API +/// +public class HeartbeatBackgroundTask +{ + private readonly EpsonPrintServiceConfiguration _configuration; + private readonly ILogger _logger; + private readonly HttpClient _httpClient; + private readonly TimeSpan _interval; + + public HeartbeatBackgroundTask( + EpsonPrintServiceConfiguration configuration, + ILogger logger) + { + _configuration = configuration; + _logger = logger; + _httpClient = new HttpClient(); + _interval = TimeSpan.FromSeconds(30); + } + + /// + /// Starts the heartbeat background task + /// + /// Token to cancel the background task + public async Task StartAsync(CancellationToken cancellationToken) + { + _logger.LogInformation("Starting heartbeat background task (interval: {Interval}s)", _interval.TotalSeconds); + + // Run immediately on start + await SendHeartbeatAsync(); + + // Then run periodically + while (!cancellationToken.IsCancellationRequested) + { + try + { + await Task.Delay(_interval, cancellationToken); + await SendHeartbeatAsync(); + } + catch (TaskCanceledException) + { + break; + } + catch (Exception ex) + { + _logger.LogError(ex, "Error during heartbeat"); + } + } + + _logger.LogInformation("Heartbeat background task stopped"); + } + + private async Task SendHeartbeatAsync() + { + try + { + var url = _configuration.HeartbeatApiUrl; + var apiKey = _configuration.PrinterServerKey; + + if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(apiKey)) + { + _logger.LogWarning("Heartbeat not configured (missing HeartbeatApiUrl or PrinterServerKey)"); + return; + } + + using var request = new HttpRequestMessage(HttpMethod.Post, url); + request.Headers.Add("X-Printer-Server-Key", apiKey); + + var payload = new HeartbeatPayload + { + OsVersion = Environment.OSVersion.ToString() + }; + + request.Content = JsonContent.Create(payload); + + var response = await _httpClient.SendAsync(request); + + if (response.IsSuccessStatusCode) + { + _logger.LogDebug("Heartbeat sent successfully"); + } + else + { + _logger.LogWarning("Heartbeat failed with status code: {StatusCode}", response.StatusCode); + } + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Failed to send heartbeat"); + } + } + + private class HeartbeatPayload + { + [JsonPropertyName("osVersion")] + public string OsVersion { get; set; } = string.Empty; + } +} diff --git a/EpsonPrintService/Program.cs b/EpsonPrintService/Program.cs index c83fa85..098654a 100644 --- a/EpsonPrintService/Program.cs +++ b/EpsonPrintService/Program.cs @@ -45,12 +45,12 @@ kernel.Bind().To().InSingleto kernel.Bind().ToSelf().InSingletonScope(); kernel.Bind().To().InSingletonScope(); kernel.Bind().ToSelf().InSingletonScope(); +kernel.Bind().ToSelf().InSingletonScope(); var printLoop = kernel.Get(); -var printServer = kernel.Get(); -var discoveryTask = kernel.Get(); -printServer.RegisterPrinter("127.0.0.1"); +var discoveryTask = kernel.Get(); +var heartbeatTask = kernel.Get(); await printLoop.StartAsync(); @@ -64,8 +64,9 @@ Console.CancelKeyPress += (sender, e) => cts.Cancel(); }; -// Start the printer discovery background task +// Start background tasks _ = discoveryTask.StartAsync(cts.Token); +_ = heartbeatTask.StartAsync(cts.Token); try { diff --git a/Inspectron.Epson/PrintServer/ConfigurationSources/EpsonPrintServiceConfiguration.cs b/Inspectron.Epson/PrintServer/ConfigurationSources/EpsonPrintServiceConfiguration.cs index 0935696..f5b8026 100644 --- a/Inspectron.Epson/PrintServer/ConfigurationSources/EpsonPrintServiceConfiguration.cs +++ b/Inspectron.Epson/PrintServer/ConfigurationSources/EpsonPrintServiceConfiguration.cs @@ -7,6 +7,8 @@ public class EpsonPrintServiceConfiguration: IPrinterConfigurationSource, IAssig public string GroupId { get; set; } public string RestaurantId { get; set; } public string ApiKey { get; set; } + public string? HeartbeatApiUrl { get; set; } + public string? PrinterServerKey { get; set; } public Dictionary PrinterConfigurations { get; set; } public PrinterConfiguration GetConfiguration(string printerAddress)