Ready to test in Fab
This commit is contained in:
186
Server/HostedService/TimedHostedService.cs
Normal file
186
Server/HostedService/TimedHostedService.cs
Normal file
@ -0,0 +1,186 @@
|
||||
using Barcode.Host.Server.Models;
|
||||
using Barcode.Host.Shared.DataModels;
|
||||
using Barcode.Host.Shared.KeyboardMouse;
|
||||
using Barcode.Host.Shared.Models.Stateless;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Serilog.Context;
|
||||
|
||||
namespace Barcode.Host.Server.HostedService;
|
||||
|
||||
public class TimedHostedService : IHostedService, IAggregateInputReader, IDisposable
|
||||
{
|
||||
|
||||
public event InputReader.RaiseKeyPress? OnKeyPress;
|
||||
|
||||
private readonly int _ExecutionCount;
|
||||
private readonly AppSettings _AppSettings;
|
||||
private readonly ISerialService _SerialService;
|
||||
private readonly ILastScanService _LastScanService;
|
||||
private readonly ILogger<TimedHostedService> _Logger;
|
||||
private readonly ILinuxGroupManager _LinuxGroupManager;
|
||||
private readonly Dictionary<string, InputReader> _Readers;
|
||||
private readonly Dictionary<EventCode, char> _CharToEventCodes;
|
||||
private readonly List<(string MethodName, Timer Timer)> _Timers;
|
||||
|
||||
public TimedHostedService(ILogger<TimedHostedService> logger, AppSettings appSettings, ILinuxGroupManager linuxGroupManager, ILastScanService lastScanService, ISerialService serialService)
|
||||
{
|
||||
_Readers = new();
|
||||
_Logger = logger;
|
||||
_ExecutionCount = 0;
|
||||
_CharToEventCodes = new();
|
||||
_AppSettings = appSettings;
|
||||
_SerialService = serialService;
|
||||
_LastScanService = lastScanService;
|
||||
_LinuxGroupManager = linuxGroupManager;
|
||||
Timer writeTimer = new(Write, null, Timeout.Infinite, Timeout.Infinite);
|
||||
Timer scanForNewInputsTimer = new(ScanForNewInputs, null, Timeout.Infinite, Timeout.Infinite);
|
||||
_Timers = new List<(string, Timer)>() { (nameof(Write), writeTimer), (nameof(ScanForNewInputs), scanForNewInputsTimer) };
|
||||
}
|
||||
|
||||
public Task StartAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
string? methodName = IMethodName.GetActualAsyncMethodName();
|
||||
using (LogContext.PushProperty("MethodName", methodName))
|
||||
{
|
||||
_Logger.LogInformation($"Timed Hosted Service: {_AppSettings.GitCommitSeven}:{Environment.ProcessId} running.");
|
||||
_SerialService.Open();
|
||||
if (!_LinuxGroupManager.IsInInputGroup().WaitAsync(stoppingToken).Result)
|
||||
{
|
||||
if (string.IsNullOrEmpty(_AppSettings.RootPassword))
|
||||
throw new Exception($"Please check appsettings file(s) for <{nameof(_AppSettings.RootPassword)}>!");
|
||||
_ = _LinuxGroupManager.AddUserToInputGroup(_AppSettings.RootPassword);
|
||||
_ = _LinuxGroupManager.RebootSystem(_AppSettings.RootPassword);
|
||||
}
|
||||
List<(EventCode, char)> collection = _LastScanService.IncludeEventCodes();
|
||||
foreach ((EventCode eventCode, char @char) in collection)
|
||||
_CharToEventCodes.Add(eventCode, @char);
|
||||
int dueTime = 0;
|
||||
foreach ((string _, Timer timer) in _Timers)
|
||||
{
|
||||
dueTime += 300;
|
||||
_ = timer.Change(dueTime, Timeout.Infinite);
|
||||
}
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
string? methodName = IMethodName.GetActualAsyncMethodName();
|
||||
using (LogContext.PushProperty("MethodName", methodName))
|
||||
{
|
||||
_Logger.LogInformation($"Timed Hosted Service: {_AppSettings.GitCommitSeven}:{Environment.ProcessId} is stopping.");
|
||||
for (short i = 0; i < short.MaxValue; i++)
|
||||
{
|
||||
Thread.Sleep(500);
|
||||
if (_ExecutionCount == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach ((string _, Timer timer) in _Timers)
|
||||
timer.Dispose();
|
||||
foreach (InputReader inputReader in _Readers.Values)
|
||||
{
|
||||
inputReader.OnKeyPress -= ReaderOnOnKeyPress;
|
||||
inputReader.Dispose();
|
||||
}
|
||||
_Readers.Clear();
|
||||
_SerialService.Close();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void ReaderOnOnKeyPress(KeyPressEvent e)
|
||||
{
|
||||
OnKeyPress?.Invoke(e);
|
||||
if (e.TimeSpan.TotalMilliseconds > _AppSettings.ClearLastScanServiceAfter)
|
||||
_LastScanService.Clear();
|
||||
if (e.KeyState == KeyState.KeyUp && _CharToEventCodes.TryGetValue(e.EventCode, out char @char))
|
||||
_LastScanService.Add(e.EventCode, @char);
|
||||
}
|
||||
|
||||
private Timer? GetTimer(string methodName)
|
||||
{
|
||||
(string MethodName, Timer Timer)[] results = _Timers.Where(l => l.MethodName == methodName).ToArray();
|
||||
return !results.Any() ? null : results.First().Timer;
|
||||
}
|
||||
|
||||
private void ScanForNewInputs()
|
||||
{
|
||||
string fileName;
|
||||
IEnumerable<LinuxDevice>? devices = null;
|
||||
string[] files = Directory.GetFiles("/dev/input/", "event*");
|
||||
foreach (string file in files)
|
||||
{
|
||||
if (_Readers is null || _Readers.ContainsKey(file))
|
||||
continue;
|
||||
devices ??= DeviceReader.Get(_AppSettings.LinuxDevicePath);
|
||||
fileName = Path.GetFileName(file);
|
||||
InputReader reader = new(file, _Logger);
|
||||
if (devices.Any(l => !string.IsNullOrEmpty(l.Name) && l.Name.EndsWith(_AppSettings.DeviceNameEndsWith) && l.Handlers.Any(m => m == fileName)))
|
||||
reader.OnKeyPress += ReaderOnOnKeyPress;
|
||||
_Readers?.Add(file, reader);
|
||||
}
|
||||
IEnumerable<InputReader>? deadReaders = _Readers?.Values.Where(r => r.Faulted);
|
||||
if (deadReaders is not null)
|
||||
{
|
||||
foreach (InputReader? inputReader in deadReaders)
|
||||
{
|
||||
_ = _Readers?.Remove(inputReader.Path);
|
||||
inputReader.OnKeyPress -= ReaderOnOnKeyPress;
|
||||
inputReader.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ScanForNewInputs(object? sender)
|
||||
{
|
||||
try
|
||||
{ ScanForNewInputs(); }
|
||||
catch (Exception ex) { _Logger.LogError(ex, nameof(ScanForNewInputs)); }
|
||||
try
|
||||
{
|
||||
Timer? timer = GetTimer(nameof(ScanForNewInputs));
|
||||
if (timer is not null)
|
||||
{
|
||||
TimeSpan timeSpan = new(DateTime.Now.AddSeconds(30).Ticks - DateTime.Now.Ticks);
|
||||
_ = timer.Change((int)timeSpan.TotalMilliseconds, Timeout.Infinite);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { _Logger.LogError(ex, $"{nameof(ScanForNewInputs)}-{nameof(Timer)}.{nameof(Timer.Change)}"); }
|
||||
}
|
||||
|
||||
private void Write()
|
||||
{
|
||||
int count = _LastScanService.GetCount();
|
||||
if (count > 0)
|
||||
{
|
||||
Result<string> result = _LastScanService.GetScan();
|
||||
if (!string.IsNullOrEmpty(result.Results))
|
||||
_SerialService.SerialPortWrite(count, result.Results);
|
||||
}
|
||||
}
|
||||
|
||||
private void Write(object? sender)
|
||||
{
|
||||
try
|
||||
{ Write(); }
|
||||
catch (Exception ex) { _Logger.LogError(ex, nameof(Write)); }
|
||||
try
|
||||
{
|
||||
Timer? timer = GetTimer(nameof(Write));
|
||||
if (timer is not null)
|
||||
{
|
||||
TimeSpan timeSpan = new(DateTime.Now.AddMilliseconds(_AppSettings.WriteToSerialEvery).Ticks - DateTime.Now.Ticks);
|
||||
_ = timer.Change((int)timeSpan.TotalMilliseconds, Timeout.Infinite);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { _Logger.LogError(ex, $"{nameof(Write)}-{nameof(Timer)}.{nameof(Timer.Change)}"); }
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user