Ready to test in Fab
This commit is contained in:
20
Server/ApiControllers/LastScanController.cs
Normal file
20
Server/ApiControllers/LastScanController.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using Barcode.Host.Shared.Models.Stateless;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Barcode.Host.Server.ApiControllers;
|
||||
|
||||
[Route("api/[controller]")]
|
||||
public class LastScanController : Controller, ILastScanController<IActionResult>
|
||||
{
|
||||
|
||||
private readonly ILastScanService _LastScanService;
|
||||
|
||||
public LastScanController(ILastScanService lastScanService) =>
|
||||
_LastScanService = lastScanService;
|
||||
|
||||
[HttpGet()]
|
||||
public IActionResult GetScan() =>
|
||||
Json(_LastScanService.GetScan(), new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true });
|
||||
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64</RuntimeIdentifiers>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<UserSecretsId>02dce973-df1d-4325-962a-ed549af8d4c5</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
@ -22,6 +22,7 @@
|
||||
<DefineConstants>Linux</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CliWrap" Version="3.6.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="7.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
|
||||
@ -31,9 +32,18 @@
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
<PackageReference Include="ShellProgressBar" Version="5.2.0" />
|
||||
<PackageReference Include="System.IO.Ports" Version="7.0.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="7.0.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Shared\Barcode.Host.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="appsettings.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="appsettings.Development.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
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)}"); }
|
||||
}
|
||||
|
||||
}
|
@ -2,26 +2,23 @@ using System.Text.Json;
|
||||
|
||||
namespace Barcode.Host.Server.Models;
|
||||
|
||||
public record AppSettings(string ApiExportPath,
|
||||
string ApiLoggingContentTypes,
|
||||
string ApiLoggingPathPrefixes,
|
||||
string ApiLogPath,
|
||||
string ApiUrl,
|
||||
string AttachmentPath,
|
||||
string BuildNumber,
|
||||
public record AppSettings(string BuildNumber,
|
||||
string Company,
|
||||
string ConnectionString,
|
||||
int ClearLastScanServiceAfter,
|
||||
string DeviceNameEndsWith,
|
||||
int ExpectedScanLengthA,
|
||||
int ExpectedScanLengthB,
|
||||
string GitCommitSeven,
|
||||
string InboundApiAllowedIPList,
|
||||
string LinuxDevicePath,
|
||||
bool IsDevelopment,
|
||||
bool IsStaging,
|
||||
string MockRoot,
|
||||
string MonAResource,
|
||||
string MonASite,
|
||||
string OI2SqlConnectionString,
|
||||
string OIExportPath,
|
||||
string RootPassword,
|
||||
string URLs,
|
||||
string WorkingDirectoryName)
|
||||
string WorkingDirectoryName,
|
||||
int WriteToSerialEvery)
|
||||
{
|
||||
|
||||
public override string ToString()
|
||||
|
@ -9,26 +9,23 @@ public class AppSettings
|
||||
|
||||
#nullable disable
|
||||
|
||||
[Display(Name = "Api Export Path"), Required] public string ApiExportPath { get; set; }
|
||||
[Display(Name = "Api Logging Content Types"), Required] public string ApiLoggingContentTypes { get; set; }
|
||||
[Display(Name = "Api Logging Path Prefixes"), Required] public string ApiLoggingPathPrefixes { get; set; }
|
||||
[Display(Name = "Api Log Path"), Required] public string ApiLogPath { get; set; }
|
||||
[Display(Name = "Api URL"), Required] public string ApiUrl { get; set; }
|
||||
[Display(Name = "Attachment Path"), Required] public string AttachmentPath { get; set; }
|
||||
[Display(Name = "Build Number"), Required] public string BuildNumber { get; set; }
|
||||
[Display(Name = "Company"), Required] public string Company { get; set; }
|
||||
[Display(Name = "Connection String"), Required] public string ConnectionString { get; set; }
|
||||
[Display(Name = "Last Scan Service Clear After"), Required] public int? ClearLastScanServiceAfter { get; set; }
|
||||
[Display(Name = "Device Name Ends With"), Required] public string DeviceNameEndsWith { get; set; }
|
||||
[Display(Name = "ExpectedScanLengthA"), Required] public int? ExpectedScanLengthA { get; set; }
|
||||
[Display(Name = "ExpectedScanLengthB"), Required] public int? ExpectedScanLengthB { get; set; }
|
||||
[Display(Name = "Git Commit Seven"), Required] public string GitCommitSeven { get; set; }
|
||||
[Display(Name = "Inbound Api Allowed IP List"), Required] public string InboundApiAllowedIPList { get; set; }
|
||||
[Display(Name = "Linux Device Path"), Required] public string LinuxDevicePath { get; set; }
|
||||
[Display(Name = "Is Development"), Required] public bool? IsDevelopment { get; set; }
|
||||
[Display(Name = "Is Staging"), Required] public bool? IsStaging { get; set; }
|
||||
[Display(Name = "Mock Root"), Required] public string MockRoot { get; set; }
|
||||
[Display(Name = "MonA Resource"), Required] public string MonAResource { get; set; }
|
||||
[Display(Name = "MonA Site"), Required] public string MonASite { get; set; }
|
||||
[Display(Name = "Oi 2 Sql Connection String"), Required] public string Oi2SqlConnectionString { get; set; }
|
||||
[Display(Name = "OI Export Path"), Required] public string OIExportPath { get; set; }
|
||||
[Display(Name = "RootPassword"), Required] public string RootPassword { get; set; }
|
||||
[Display(Name = "URLs"), Required] public string URLs { get; set; }
|
||||
[Display(Name = "Working Directory Name"), Required] public string WorkingDirectoryName { get; set; }
|
||||
[Display(Name = "WriteToSerialEvery"), Required] public int? WriteToSerialEvery { get; set; }
|
||||
|
||||
#nullable restore
|
||||
|
||||
@ -43,28 +40,22 @@ public class AppSettings
|
||||
Models.AppSettings result;
|
||||
if (appSettings is null)
|
||||
throw new NullReferenceException(nameof(appSettings));
|
||||
if (appSettings.ApiExportPath is null)
|
||||
throw new NullReferenceException(nameof(ApiExportPath));
|
||||
if (appSettings.ApiLoggingContentTypes is null)
|
||||
throw new NullReferenceException(nameof(ApiLoggingContentTypes));
|
||||
if (appSettings.ApiLoggingPathPrefixes is null)
|
||||
throw new NullReferenceException(nameof(ApiLoggingPathPrefixes));
|
||||
if (appSettings.ApiLogPath is null)
|
||||
throw new NullReferenceException(nameof(ApiLogPath));
|
||||
if (appSettings.ApiUrl is null)
|
||||
throw new NullReferenceException(nameof(ApiUrl));
|
||||
if (appSettings.AttachmentPath is null)
|
||||
throw new NullReferenceException(nameof(AttachmentPath));
|
||||
if (appSettings.BuildNumber is null)
|
||||
throw new NullReferenceException(nameof(BuildNumber));
|
||||
if (appSettings.Company is null)
|
||||
throw new NullReferenceException(nameof(Company));
|
||||
if (appSettings.ConnectionString is null)
|
||||
throw new NullReferenceException(nameof(ConnectionString));
|
||||
if (appSettings.ClearLastScanServiceAfter is null)
|
||||
throw new NullReferenceException(nameof(ClearLastScanServiceAfter));
|
||||
if (appSettings.DeviceNameEndsWith is null)
|
||||
throw new NullReferenceException(nameof(DeviceNameEndsWith));
|
||||
if (appSettings.ExpectedScanLengthA is null)
|
||||
throw new NullReferenceException(nameof(ExpectedScanLengthA));
|
||||
if (appSettings.ExpectedScanLengthB is null)
|
||||
throw new NullReferenceException(nameof(ExpectedScanLengthB));
|
||||
if (appSettings.GitCommitSeven is null)
|
||||
throw new NullReferenceException(nameof(GitCommitSeven));
|
||||
if (appSettings.InboundApiAllowedIPList is null)
|
||||
throw new NullReferenceException(nameof(InboundApiAllowedIPList));
|
||||
if (appSettings.LinuxDevicePath is null)
|
||||
throw new NullReferenceException(nameof(LinuxDevicePath));
|
||||
if (appSettings.IsDevelopment is null)
|
||||
throw new NullReferenceException(nameof(IsDevelopment));
|
||||
if (appSettings.IsStaging is null)
|
||||
@ -75,35 +66,32 @@ public class AppSettings
|
||||
throw new NullReferenceException(nameof(MonAResource));
|
||||
if (appSettings.MonASite is null)
|
||||
throw new NullReferenceException(nameof(MonASite));
|
||||
if (appSettings.Oi2SqlConnectionString is null)
|
||||
throw new NullReferenceException(nameof(Oi2SqlConnectionString));
|
||||
if (appSettings.OIExportPath is null)
|
||||
throw new NullReferenceException(nameof(OIExportPath));
|
||||
if (appSettings.RootPassword is null)
|
||||
throw new NullReferenceException(nameof(RootPassword));
|
||||
if (appSettings.URLs is null)
|
||||
throw new NullReferenceException(nameof(URLs));
|
||||
if (appSettings.WorkingDirectoryName is null)
|
||||
throw new NullReferenceException(nameof(WorkingDirectoryName));
|
||||
if (appSettings.WriteToSerialEvery is null)
|
||||
throw new NullReferenceException(nameof(WriteToSerialEvery));
|
||||
result = new(
|
||||
appSettings.ApiExportPath,
|
||||
appSettings.ApiLoggingContentTypes,
|
||||
appSettings.ApiLoggingPathPrefixes,
|
||||
appSettings.ApiLogPath,
|
||||
appSettings.ApiUrl,
|
||||
appSettings.AttachmentPath,
|
||||
appSettings.BuildNumber,
|
||||
appSettings.Company,
|
||||
appSettings.ConnectionString,
|
||||
appSettings.ClearLastScanServiceAfter.Value,
|
||||
appSettings.DeviceNameEndsWith,
|
||||
appSettings.ExpectedScanLengthA.Value,
|
||||
appSettings.ExpectedScanLengthB.Value,
|
||||
appSettings.GitCommitSeven,
|
||||
appSettings.InboundApiAllowedIPList,
|
||||
appSettings.LinuxDevicePath,
|
||||
appSettings.IsDevelopment.Value,
|
||||
appSettings.IsStaging.Value,
|
||||
appSettings.MockRoot,
|
||||
appSettings.MonAResource,
|
||||
appSettings.MonASite,
|
||||
appSettings.Oi2SqlConnectionString,
|
||||
appSettings.OIExportPath,
|
||||
appSettings.RootPassword,
|
||||
appSettings.URLs,
|
||||
appSettings.WorkingDirectoryName);
|
||||
appSettings.WorkingDirectoryName,
|
||||
appSettings.WriteToSerialEvery.Value);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
using Barcode.Host.Server.Models;
|
||||
using Barcode.Host.Server.HostedService;
|
||||
using Barcode.Host.Server.Models;
|
||||
using Barcode.Host.Server.Services;
|
||||
using Barcode.Host.Shared.Models;
|
||||
using Barcode.Host.Shared.Models.Stateless;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
@ -35,7 +37,7 @@ public class Program
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
LoggerConfiguration loggerConfiguration = new();
|
||||
(string assemblyName, WebApplicationOptions _) = Get(args);
|
||||
(string assemblyName, _) = Get(args);
|
||||
WebApplicationBuilder webApplicationBuilder = WebApplication.CreateBuilder(args);
|
||||
_ = webApplicationBuilder.Configuration.AddUserSecrets<Program>();
|
||||
AppSettings appSettings = Models.Binder.AppSettings.Get(webApplicationBuilder.Configuration);
|
||||
@ -49,44 +51,35 @@ public class Program
|
||||
ILogger log = Log.ForContext<Program>();
|
||||
try
|
||||
{
|
||||
_ = webApplicationBuilder.Services.AddMemoryCache();
|
||||
_ = webApplicationBuilder.Services.Configure<ApiBehaviorOptions>(options => options.SuppressModelStateInvalidFilter = true);
|
||||
if (appSettings.IsStaging && appSettings.IsDevelopment)
|
||||
throw new NotSupportedException("Please check appsettings file(s)!");
|
||||
if (appSettings.IsStaging != webApplicationBuilder.Environment.IsStaging())
|
||||
throw new NotSupportedException("Please check appsettings file(s)!");
|
||||
if (appSettings.IsDevelopment != webApplicationBuilder.Environment.IsDevelopment())
|
||||
throw new NotSupportedException("Please check appsettings file(s)!");
|
||||
_ = webApplicationBuilder.Services.AddControllersWithViews();
|
||||
_ = webApplicationBuilder.Services.AddDistributedMemoryCache();
|
||||
|
||||
_ = webApplicationBuilder.Services.AddSingleton(_ => appSettings);
|
||||
|
||||
_ = webApplicationBuilder.Services.AddSingleton<ISerialService, SerialService>();
|
||||
_ = webApplicationBuilder.Services.AddSingleton<ILastScanService, LastScanService>();
|
||||
_ = webApplicationBuilder.Services.AddSingleton<ILinuxGroupManager, LinuxGroupManager>();
|
||||
_ = webApplicationBuilder.Services.AddHostedService<TimedHostedService>();
|
||||
_ = webApplicationBuilder.Services.AddSwaggerGen();
|
||||
_ = webApplicationBuilder.Services.AddSession(sessionOptions =>
|
||||
{
|
||||
sessionOptions.IdleTimeout = TimeSpan.FromSeconds(2000);
|
||||
sessionOptions.Cookie.HttpOnly = true;
|
||||
sessionOptions.Cookie.IsEssential = true;
|
||||
}
|
||||
);
|
||||
WebApplication webApplication = webApplicationBuilder.Build();
|
||||
_ = webApplication.UseCors(corsPolicyBuilder => corsPolicyBuilder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
|
||||
if (!webApplicationBuilder.Environment.IsDevelopment())
|
||||
if (appSettings.IsDevelopment)
|
||||
{
|
||||
_ = webApplication.UseExceptionHandler("/Error");
|
||||
_ = webApplication.UseHttpsRedirection();
|
||||
_ = webApplication.UseHsts();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string.IsNullOrEmpty(appSettings.URLs))
|
||||
{
|
||||
Environment.ExitCode = -1;
|
||||
webApplication.Lifetime.StopApplication();
|
||||
}
|
||||
_ = webApplication.UseSwagger();
|
||||
_ = webApplication.UseDeveloperExceptionPage();
|
||||
_ = webApplication.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Server V1"));
|
||||
}
|
||||
if (!appSettings.IsDevelopment)
|
||||
{
|
||||
_ = webApplication.UseExceptionHandler("/Error");
|
||||
_ = webApplication.UseHsts();
|
||||
}
|
||||
_ = webApplication.UseCors(corsPolicyBuilder => corsPolicyBuilder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
|
||||
_ = webApplication.Lifetime.ApplicationStopped.Register(Log.CloseAndFlush);
|
||||
_ = SerilogApplicationBuilderExtensions.UseSerilogRequestLogging(webApplication);
|
||||
_ = webApplication.UseFileServer(enableDirectoryBrowsing: true);
|
||||
_ = webApplication.UseStaticFiles();
|
||||
_ = webApplication.UseSession();
|
||||
_ = webApplication.MapControllers();
|
||||
log.Information("Starting Web Application");
|
||||
webApplication.Run();
|
||||
|
93
Server/Services/LastScanService.cs
Normal file
93
Server/Services/LastScanService.cs
Normal file
@ -0,0 +1,93 @@
|
||||
using Barcode.Host.Shared.DataModels;
|
||||
using Barcode.Host.Shared.KeyboardMouse;
|
||||
using Barcode.Host.Shared.Models.Stateless;
|
||||
|
||||
namespace Barcode.Host.Server.Services;
|
||||
|
||||
public class LastScanService : ILastScanService
|
||||
{
|
||||
|
||||
private readonly List<(EventCode EventCode, char Char)> _EventCodes;
|
||||
|
||||
public LastScanService() =>
|
||||
_EventCodes = new();
|
||||
|
||||
void ILastScanService.Clear()
|
||||
{
|
||||
lock (_EventCodes)
|
||||
_EventCodes.Clear();
|
||||
}
|
||||
|
||||
void ILastScanService.Add(EventCode eventCode, char @char)
|
||||
{
|
||||
lock (_EventCodes)
|
||||
_EventCodes.Add((eventCode, @char));
|
||||
}
|
||||
|
||||
Result<string> ILastScanService.GetScan()
|
||||
{
|
||||
Result<string> result;
|
||||
char[] chars;
|
||||
lock (_EventCodes)
|
||||
chars = _EventCodes.Select(l => l.Char).ToArray();
|
||||
result = new() { Results = new string(chars), TotalRows = chars.Length };
|
||||
return result;
|
||||
}
|
||||
|
||||
int ILastScanService.GetCount()
|
||||
{
|
||||
int result;
|
||||
lock (_EventCodes)
|
||||
result = _EventCodes.Count;
|
||||
return result;
|
||||
}
|
||||
|
||||
List<(EventCode, char)> ILastScanService.IncludeEventCodes()
|
||||
{
|
||||
List<(EventCode, char)> results = new()
|
||||
{
|
||||
(EventCode.A, 'A'),
|
||||
(EventCode.B, 'B'),
|
||||
(EventCode.C, 'C'),
|
||||
(EventCode.D, 'D'),
|
||||
(EventCode.E, 'E'),
|
||||
(EventCode.F, 'F'),
|
||||
(EventCode.G, 'G'),
|
||||
(EventCode.H, 'H'),
|
||||
(EventCode.I, 'I'),
|
||||
(EventCode.J, 'J'),
|
||||
(EventCode.K, 'K'),
|
||||
(EventCode.L, 'L'),
|
||||
(EventCode.M, 'M'),
|
||||
(EventCode.N, 'N'),
|
||||
(EventCode.O, 'O'),
|
||||
(EventCode.P, 'P'),
|
||||
(EventCode.Q, 'Q'),
|
||||
(EventCode.R, 'R'),
|
||||
(EventCode.S, 'S'),
|
||||
(EventCode.T, 'T'),
|
||||
(EventCode.U, 'U'),
|
||||
(EventCode.V, 'V'),
|
||||
(EventCode.W, 'W'),
|
||||
(EventCode.X, 'X'),
|
||||
(EventCode.Y, 'Y'),
|
||||
(EventCode.Z, 'Z'),
|
||||
(EventCode.Num0, '0'),
|
||||
(EventCode.Num1, '1'),
|
||||
(EventCode.Num2, '2'),
|
||||
(EventCode.Num3, '3'),
|
||||
(EventCode.Num4, '4'),
|
||||
(EventCode.Num5, '5'),
|
||||
(EventCode.Num6, '6'),
|
||||
(EventCode.Num7, '7'),
|
||||
(EventCode.Num8, '8'),
|
||||
(EventCode.Num9, '9'),
|
||||
(EventCode.Minus, '-'),
|
||||
(EventCode.Dot, '.'),
|
||||
(EventCode.Slash, '/'),
|
||||
(EventCode.Space, ' '),
|
||||
};
|
||||
return results;
|
||||
}
|
||||
|
||||
}
|
42
Server/Services/LinuxGroupManager.cs
Normal file
42
Server/Services/LinuxGroupManager.cs
Normal file
@ -0,0 +1,42 @@
|
||||
using Barcode.Host.Shared.Models.Stateless;
|
||||
using CliWrap;
|
||||
using CliWrap.Buffered;
|
||||
|
||||
namespace Barcode.Host.Server.Services;
|
||||
|
||||
public class LinuxGroupManager : ILinuxGroupManager
|
||||
{
|
||||
|
||||
public async Task<bool> IsInInputGroup()
|
||||
{
|
||||
BufferedCommandResult result = await Cli.Wrap("id")
|
||||
.ExecuteBufferedAsync();
|
||||
string output = result.StandardOutput;
|
||||
const StringSplitOptions options = StringSplitOptions.RemoveEmptyEntries;
|
||||
bool inInputGroup = output.Split(new[] { ' ' }, options)
|
||||
.First(p => p.StartsWith("groups"))
|
||||
.Remove(0, "groups".Length)
|
||||
.Split(',', options)
|
||||
.Any(p => p.Contains("input"));
|
||||
return inInputGroup;
|
||||
}
|
||||
|
||||
public async Task AddUserToInputGroup(string password)
|
||||
{
|
||||
using CancellationTokenSource cts = new();
|
||||
cts.CancelAfter(TimeSpan.FromSeconds(10));
|
||||
_ = await Cli.Wrap("bash")
|
||||
.WithArguments($"-c \"echo '{password}' | sudo -S gpasswd -a $USER input")
|
||||
.ExecuteBufferedAsync(cts.Token);
|
||||
}
|
||||
|
||||
public async Task RebootSystem(string password)
|
||||
{
|
||||
using CancellationTokenSource cts = new();
|
||||
cts.CancelAfter(TimeSpan.FromSeconds(10));
|
||||
_ = await Cli.Wrap("bash")
|
||||
.WithArguments($"-c \"echo '{password}' | sudo -S reboot\"")
|
||||
.ExecuteBufferedAsync(cts.Token);
|
||||
}
|
||||
|
||||
}
|
44
Server/Services/SerialService.cs
Normal file
44
Server/Services/SerialService.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using Barcode.Host.Server.Models;
|
||||
using Barcode.Host.Shared.Models.Stateless;
|
||||
using System.Text;
|
||||
|
||||
namespace Barcode.Host.Server.Services;
|
||||
|
||||
public class SerialService : ISerialService
|
||||
{
|
||||
|
||||
private string _LastRaw;
|
||||
private readonly AppSettings _AppSettings;
|
||||
private readonly System.IO.Ports.SerialPort _SerialPort;
|
||||
|
||||
public SerialService(AppSettings appSettings)
|
||||
{
|
||||
_LastRaw = string.Empty;
|
||||
_AppSettings = appSettings;
|
||||
_SerialPort = new("/dev/ttyUSB0", 9600) { ReadTimeout = 2 };
|
||||
}
|
||||
|
||||
void ISerialService.Open() =>
|
||||
_SerialPort.Open();
|
||||
|
||||
void ISerialService.Close() =>
|
||||
_SerialPort.Close();
|
||||
|
||||
void ISerialService.SerialPortWrite(int count, string raw)
|
||||
{
|
||||
if (raw != _LastRaw)
|
||||
{
|
||||
string message;
|
||||
if (count == _AppSettings.ExpectedScanLengthA)
|
||||
message = $" {raw[2..]} {DateTime.Now:h:m tt}";
|
||||
else if (count == _AppSettings.ExpectedScanLengthB)
|
||||
message = $" {raw[2..]}";
|
||||
else
|
||||
message = $" {raw}";
|
||||
byte[] bytes = Encoding.ASCII.GetBytes(message);
|
||||
_SerialPort.Write(bytes, 0, bytes.Length);
|
||||
_LastRaw = raw;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,47 +1,13 @@
|
||||
{
|
||||
"ApiExportPath": "\\\\messdv002.na.infineon.com\\Candela",
|
||||
"ApiUrl": "~/api",
|
||||
"ConnectionString": "Data Source=MESSAD1001\\TEST1,59583;Integrated Security=True;Initial Catalog=Metrology;",
|
||||
"IsDevelopment": true,
|
||||
"MockRoot": "",
|
||||
"MonAResource": "OI_Metrology_Viewer_IFX",
|
||||
"Oi2SqlConnectionString": "Data Source=MESSAD1001\\TEST1,59583;Initial Catalog=LSL2SQL;Persist Security Info=True;User ID=srpadmin;Password=0okm9ijn;",
|
||||
"Serilog": {
|
||||
"Using": [
|
||||
"Serilog.Sinks.Console",
|
||||
"Serilog.Sinks.File"
|
||||
],
|
||||
"MinimumLevel": "Debug",
|
||||
"WriteTo": [
|
||||
{
|
||||
"Name": "Debug",
|
||||
"Args": {
|
||||
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Console",
|
||||
"Args": {
|
||||
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "File",
|
||||
"Args": {
|
||||
"path": "%workingDirectory% - Log/log-.txt",
|
||||
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}",
|
||||
"rollingInterval": "Hour"
|
||||
}
|
||||
}
|
||||
],
|
||||
"Enrich": [
|
||||
"FromLogContext",
|
||||
"WithMachineName",
|
||||
"WithThreadId"
|
||||
],
|
||||
"Properties": {
|
||||
"Application": "Sample"
|
||||
"ExpectedScanLengthA": 6,
|
||||
"ExpectedScanLengthB": 9,
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Log4netProvider": "Debug"
|
||||
}
|
||||
},
|
||||
"URLs": "https://localhost:7130;http://localhost:5126"
|
||||
"IsDevelopment": true,
|
||||
"Serilog": {
|
||||
"MinimumLevel": "Debug"
|
||||
}
|
||||
}
|
@ -1,31 +1,26 @@
|
||||
{
|
||||
"AllowedHosts": "*",
|
||||
"ApiExportPath": "\\\\messv02ecc1.ec.local\\EC_Metrology_Si",
|
||||
"ApiLoggingContentTypes": "application/json",
|
||||
"ApiLoggingPathPrefixes": "/api/inbound",
|
||||
"ApiUrl": "~/api",
|
||||
"ApiLogPath": "D:\\Metrology\\MetrologyAPILogs",
|
||||
"AttachmentPath": "\\\\messv02ecc1.ec.local\\EC_Metrology_Si\\MetrologyAttachments",
|
||||
"BuildNumber": "1",
|
||||
"Company": "Infineon Technologies Americas Corp.",
|
||||
"ConnectionString": "Data Source=messv01ec.ec.local\\PROD1,53959;Integrated Security=True;Initial Catalog=Metrology;",
|
||||
"DeviceNameEndsWith": "Symbol Bar Code Scanner",
|
||||
"ExpectedScanLengthA": 8,
|
||||
"ExpectedScanLengthB": 14,
|
||||
"ExpectedScanLengthBExample": "1TO172125.1.11",
|
||||
"ClearLastScanServiceAfter": 250,
|
||||
"GitCommitSeven": "1234567",
|
||||
"LinuxDevicePath": "/proc/bus/input/devices",
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Log4netProvider": "Debug",
|
||||
"Log4netProvider": "Information",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"InboundApiAllowedIPList": "",
|
||||
"IsDevelopment": false,
|
||||
"IsStaging": false,
|
||||
"MockRoot": "",
|
||||
"MonAResource": "OI_Metrology_Viewer_EC",
|
||||
"MonASite": "auc",
|
||||
"Oi2SqlConnectionString": "Data Source=messv01ec.ec.local\\PROD1,53959;Initial Catalog=LSL2SQL;Persist Security Info=True;User ID=srpadmin;Password=0okm9ijn;",
|
||||
"OIExportPath": "\\\\openinsight-db-srv.na.infineon.com\\apps\\Metrology\\Data",
|
||||
"Serilog": {
|
||||
"Using": [
|
||||
"Serilog.Sinks.Console",
|
||||
@ -63,6 +58,8 @@
|
||||
"Application": "Sample"
|
||||
}
|
||||
},
|
||||
"URLs": "http://localhost:5002;",
|
||||
"WorkingDirectoryName": "IFXApps"
|
||||
"RootPassword": "",
|
||||
"URLs": "http://localhost:5003;",
|
||||
"WorkingDirectoryName": "IFXApps",
|
||||
"WriteToSerialEvery": 750
|
||||
}
|
Reference in New Issue
Block a user