Added SinaglR

This commit is contained in:
Mike Phares 2023-06-08 13:36:25 -07:00
parent 2c38ecb399
commit 9452454b8a
33 changed files with 3540 additions and 33 deletions

8
.gitignore vendored
View File

@ -340,4 +340,10 @@ ASALocalRun/
!.vscode/thunder-tests/ !.vscode/thunder-tests/
# Libman.json # Libman.json
/wwwroot/lib/* /wwwroot/lib/*
SignalRChat/*
Server/wwwroot/js/chat.js
Server/Hubs/ChatHub.cs
Server/Pages/Chat.cshtml
Server/Pages/Chat.cshtml.cs

View File

@ -19,9 +19,12 @@ completedColumns:
- [run-secrets-task](tasks/run-secrets-task.md) - [run-secrets-task](tasks/run-secrets-task.md)
- [install-vscode-extensions](tasks/install-vscode-extensions.md) - [install-vscode-extensions](tasks/install-vscode-extensions.md)
- [run-test-ports](tasks/run-test-ports.md) - [run-test-ports](tasks/run-test-ports.md)
- [signalr](tasks/signalr.md)
- [publish](tasks/publish.md) - [publish](tasks/publish.md)
- [create-as-service](tasks/create-as-service.md) - [create-as-service](tasks/create-as-service.md)
- [setup-nginx](tasks/setup-nginx.md) - [setup-nginx](tasks/setup-nginx.md)
- [self-signed-certificate](tasks/self-signed-certificate.md)
- [roll-out](tasks/roll-out.md)
## Todo ## Todo

16
.kanbn/tasks/roll-out.md Normal file
View File

@ -0,0 +1,16 @@
---
---
# roll-out
- New page in the OI Viewer
- Set ubuntu frame to new OI Viewer page
- Does it refesh by it self?
- EAF needs what for the batch field
- SP1 needs to get the barcode from one of the two servers dependent on tool queued by EDA
## Sub-tasks
- [ ] phares3757
- [ ] unity4
- [ ] unity5

View File

@ -0,0 +1,20 @@
---
---
# self-signed-certificate
```bash
sudo -i
nano /etc/hosts/
apt-get install -y ca-certificates
openssl s_client -showcerts -connect DESKTOP-H6JG91B:443 </dev/null 2>/dev/null|openssl x509 -outform PEM >DESKTOP-H6JG91B.crt
cp /home/unity5/Barcode-Host/DESKTOP-H6JG91B.crt /usr/local/share/ca-certificates/DESKTOP-H6JG91B.crt
update-ca-certificates
exit
```
## Sub-tasks
- [ ] phares3757
- [ ] unity4
- [x] unity5

View File

@ -91,6 +91,11 @@ server {
listen [::]:443 default_server ssl http2; listen [::]:443 default_server ssl http2;
location / { location / {
proxy_pass http://localhost:5003; proxy_pass http://localhost:5003;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
} }
} }
``` ```

21
.kanbn/tasks/signalr.md Normal file
View File

@ -0,0 +1,21 @@
---
---
# signalr
- [Framework-4.5.1](https://learn.microsoft.com/en-us/aspnet/signalr/overview/getting-started/tutorial-getting-started-with-signalr?source=recommendations)
- [OnNotificationReceivedAsync](https://learn.microsoft.com/en-us/training/modules/aspnet-core-signalr/3-how-signalr-works)
```bash
# https://learn.microsoft.com/en-us/aspnet/core/tutorials/signalr?view=aspnetcore-7.0&tabs=visual-studio-code
dotnet tool uninstall -g Microsoft.Web.LibraryManager.Cli
dotnet tool install -g Microsoft.Web.LibraryManager.Cli
libman install @microsoft/signalr@latest -p unpkg -d wwwroot/js/signalr --files dist/browser/signalr.js --files dist/browser/signalr.js
# http://localhost:5003/notification
```
## Sub-tasks
- [ ] phares3757
- [ ] unity4
- [ ] unity5

2
.vscode/launch.json vendored
View File

@ -17,7 +17,7 @@
// Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser // Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
"serverReadyAction": { "serverReadyAction": {
"action": "openExternally", "action": "openExternally",
"pattern": "\\bNow listening on:\\s+(https?://\\S+)", "pattern": "\\bNow listening on:\\s+(http?://\\S+)",
"uriFormat": "%s/swagger/index.html" "uriFormat": "%s/swagger/index.html"
}, },
"env": { "env": {

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
@ -31,7 +31,6 @@
<PackageReference Include="Serilog.AspNetCore" Version="7.0.0" /> <PackageReference Include="Serilog.AspNetCore" Version="7.0.0" />
<PackageReference Include="Serilog" Version="2.12.0" /> <PackageReference Include="Serilog" Version="2.12.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.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.IO.Ports" Version="7.0.0" />
<PackageReference Include="System.Text.Json" Version="7.0.2" /> <PackageReference Include="System.Text.Json" Version="7.0.2" />
</ItemGroup> </ItemGroup>

View File

@ -1,9 +1,10 @@
using Barcode.Host.Server.Hubs;
using Barcode.Host.Server.Models; using Barcode.Host.Server.Models;
using Barcode.Host.Shared.DataModels; using Barcode.Host.Shared.DataModels;
using Barcode.Host.Shared.KeyboardMouse; using Barcode.Host.Shared.KeyboardMouse;
using Barcode.Host.Shared.Models;
using Barcode.Host.Shared.Models.Stateless; using Barcode.Host.Shared.Models.Stateless;
using Microsoft.Extensions.Hosting; using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using Serilog.Context; using Serilog.Context;
namespace Barcode.Host.Server.HostedService; namespace Barcode.Host.Server.HostedService;
@ -19,15 +20,18 @@ public class TimedHostedService : IHostedService, IAggregateInputReader, IDispos
private readonly ILastScanService _LastScanService; private readonly ILastScanService _LastScanService;
private readonly ILogger<TimedHostedService> _Logger; private readonly ILogger<TimedHostedService> _Logger;
private readonly ILinuxGroupManager _LinuxGroupManager; private readonly ILinuxGroupManager _LinuxGroupManager;
private readonly IHubContext<NotificationHub> _HubContext;
private readonly Dictionary<string, InputReader> _Readers; private readonly Dictionary<string, InputReader> _Readers;
private readonly Dictionary<EventCode, char> _CharToEventCodes; private readonly Dictionary<EventCode, char> _CharToEventCodes;
private readonly List<(string MethodName, Timer Timer)> _Timers; private readonly List<(string MethodName, Timer Timer)> _Timers;
public TimedHostedService(ILogger<TimedHostedService> logger, AppSettings appSettings, ILinuxGroupManager linuxGroupManager, ILastScanService lastScanService, ISerialService serialService) public TimedHostedService(ILogger<TimedHostedService> logger, AppSettings appSettings, ILinuxGroupManager linuxGroupManager, ILastScanService lastScanService, ISerialService serialService, IHubContext<NotificationHub> hubContext)
{ {
_Timers = new();
_Readers = new(); _Readers = new();
_Logger = logger; _Logger = logger;
_ExecutionCount = 0; _ExecutionCount = 0;
_HubContext = hubContext;
_CharToEventCodes = new(); _CharToEventCodes = new();
_AppSettings = appSettings; _AppSettings = appSettings;
_SerialService = serialService; _SerialService = serialService;
@ -35,7 +39,11 @@ public class TimedHostedService : IHostedService, IAggregateInputReader, IDispos
_LinuxGroupManager = linuxGroupManager; _LinuxGroupManager = linuxGroupManager;
Timer writeTimer = new(Write, null, Timeout.Infinite, Timeout.Infinite); Timer writeTimer = new(Write, null, Timeout.Infinite, Timeout.Infinite);
Timer scanForNewInputsTimer = new(ScanForNewInputs, 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) }; if (!string.IsNullOrEmpty(_AppSettings.SerialPortName))
_Timers.Add((nameof(Write), writeTimer));
#if Linux
_Timers.Add((nameof(ScanForNewInputs), scanForNewInputsTimer));
#endif
} }
public Task StartAsync(CancellationToken stoppingToken) public Task StartAsync(CancellationToken stoppingToken)
@ -44,7 +52,9 @@ public class TimedHostedService : IHostedService, IAggregateInputReader, IDispos
using (LogContext.PushProperty("MethodName", methodName)) using (LogContext.PushProperty("MethodName", methodName))
{ {
_Logger.LogInformation($"Timed Hosted Service: {_AppSettings.GitCommitSeven}:{Environment.ProcessId} running."); _Logger.LogInformation($"Timed Hosted Service: {_AppSettings.GitCommitSeven}:{Environment.ProcessId} running.");
_SerialService.Open(); if (!string.IsNullOrEmpty(_AppSettings.SerialPortName))
_SerialService.Open();
#if Linux
if (!_LinuxGroupManager.IsInInputGroup().WaitAsync(stoppingToken).Result) if (!_LinuxGroupManager.IsInInputGroup().WaitAsync(stoppingToken).Result)
{ {
if (string.IsNullOrEmpty(_AppSettings.RootPassword)) if (string.IsNullOrEmpty(_AppSettings.RootPassword))
@ -52,6 +62,7 @@ public class TimedHostedService : IHostedService, IAggregateInputReader, IDispos
_ = _LinuxGroupManager.AddUserToInputGroup(_AppSettings.RootPassword); _ = _LinuxGroupManager.AddUserToInputGroup(_AppSettings.RootPassword);
_ = _LinuxGroupManager.RebootSystem(_AppSettings.RootPassword); _ = _LinuxGroupManager.RebootSystem(_AppSettings.RootPassword);
} }
#endif
List<(EventCode, char)> collection = _LastScanService.IncludeEventCodes(); List<(EventCode, char)> collection = _LastScanService.IncludeEventCodes();
foreach ((EventCode eventCode, char @char) in collection) foreach ((EventCode eventCode, char @char) in collection)
_CharToEventCodes.Add(eventCode, @char); _CharToEventCodes.Add(eventCode, @char);
@ -101,7 +112,19 @@ public class TimedHostedService : IHostedService, IAggregateInputReader, IDispos
if (e.TimeSpan.TotalMilliseconds > _AppSettings.ClearLastScanServiceAfter) if (e.TimeSpan.TotalMilliseconds > _AppSettings.ClearLastScanServiceAfter)
_LastScanService.Clear(); _LastScanService.Clear();
if (e.KeyState == KeyState.KeyUp && _CharToEventCodes.TryGetValue(e.EventCode, out char @char)) if (e.KeyState == KeyState.KeyUp && _CharToEventCodes.TryGetValue(e.EventCode, out char @char))
{
_LastScanService.Add(e.EventCode, @char); _LastScanService.Add(e.EventCode, @char);
int count = _LastScanService.GetCount();
if (count > _AppSettings.NotifyMinimum)
{
Result<string> result = _LastScanService.GetScan();
if (!string.IsNullOrEmpty(result.Results))
{
Notification notification = new(e, result.Results);
_ = _HubContext.Clients.All.SendAsync(nameof(NotificationHub.NotifyAll), notification);
}
}
}
} }
private Timer? GetTimer(string methodName) private Timer? GetTimer(string methodName)
@ -157,12 +180,15 @@ public class TimedHostedService : IHostedService, IAggregateInputReader, IDispos
private void Write() private void Write()
{ {
int count = _LastScanService.GetCount(); if (!string.IsNullOrEmpty(_AppSettings.SerialPortName))
if (count > 0)
{ {
Result<string> result = _LastScanService.GetScan(); int count = _LastScanService.GetCount();
if (!string.IsNullOrEmpty(result.Results)) if (count > 0)
_SerialService.SerialPortWrite(count, result.Results); {
Result<string> result = _LastScanService.GetScan();
if (!string.IsNullOrEmpty(result.Results))
_SerialService.SerialPortWrite(count, result.Results);
}
} }
} }

View File

@ -0,0 +1,12 @@
using Barcode.Host.Shared.Models;
using Microsoft.AspNetCore.SignalR;
namespace Barcode.Host.Server.Hubs;
public class NotificationHub : Hub
{
public async Task NotifyAll(Notification notification) =>
await Clients.All.SendAsync(nameof(NotifyAll), notification);
}

View File

@ -12,10 +12,12 @@ public record AppSettings(string BuildNumber,
string LinuxDevicePath, string LinuxDevicePath,
bool IsDevelopment, bool IsDevelopment,
bool IsStaging, bool IsStaging,
int NotifyMinimum,
string MockRoot, string MockRoot,
string MonAResource, string MonAResource,
string MonASite, string MonASite,
string RootPassword, string RootPassword,
string SerialPortName,
string URLs, string URLs,
string WorkingDirectoryName, string WorkingDirectoryName,
int WriteToSerialEvery) int WriteToSerialEvery)

View File

@ -1,4 +1,3 @@
using Microsoft.Extensions.Configuration;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Text.Json; using System.Text.Json;
@ -19,10 +18,12 @@ public class AppSettings
[Display(Name = "Linux Device Path"), Required] public string LinuxDevicePath { 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 Development"), Required] public bool? IsDevelopment { get; set; }
[Display(Name = "Is Staging"), Required] public bool? IsStaging { get; set; } [Display(Name = "Is Staging"), Required] public bool? IsStaging { get; set; }
[Display(Name = "Notify Minimum"), Required] public int? NotifyMinimum { get; set; }
[Display(Name = "Mock Root"), Required] public string MockRoot { 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 Resource"), Required] public string MonAResource { get; set; }
[Display(Name = "MonA Site"), Required] public string MonASite { get; set; } [Display(Name = "MonA Site"), Required] public string MonASite { get; set; }
[Display(Name = "RootPassword"), Required] public string RootPassword { get; set; } [Display(Name = "RootPassword"), Required] public string RootPassword { get; set; }
[Display(Name = "Serial Port Name"), Required] public string SerialPortName { get; set; }
[Display(Name = "URLs"), Required] public string URLs { get; set; } [Display(Name = "URLs"), Required] public string URLs { get; set; }
[Display(Name = "Working Directory Name"), Required] public string WorkingDirectoryName { get; set; } [Display(Name = "Working Directory Name"), Required] public string WorkingDirectoryName { get; set; }
[Display(Name = "WriteToSerialEvery"), Required] public int? WriteToSerialEvery { get; set; } [Display(Name = "WriteToSerialEvery"), Required] public int? WriteToSerialEvery { get; set; }
@ -60,6 +61,8 @@ public class AppSettings
throw new NullReferenceException(nameof(IsDevelopment)); throw new NullReferenceException(nameof(IsDevelopment));
if (appSettings.IsStaging is null) if (appSettings.IsStaging is null)
throw new NullReferenceException(nameof(IsStaging)); throw new NullReferenceException(nameof(IsStaging));
if (appSettings.NotifyMinimum is null)
throw new NullReferenceException(nameof(NotifyMinimum));
if (appSettings.MockRoot is null) if (appSettings.MockRoot is null)
throw new NullReferenceException(nameof(MockRoot)); throw new NullReferenceException(nameof(MockRoot));
if (appSettings.MonAResource is null) if (appSettings.MonAResource is null)
@ -68,6 +71,8 @@ public class AppSettings
throw new NullReferenceException(nameof(MonASite)); throw new NullReferenceException(nameof(MonASite));
if (appSettings.RootPassword is null) if (appSettings.RootPassword is null)
throw new NullReferenceException(nameof(RootPassword)); throw new NullReferenceException(nameof(RootPassword));
if (appSettings.SerialPortName is null)
throw new NullReferenceException(nameof(SerialPortName));
if (appSettings.URLs is null) if (appSettings.URLs is null)
throw new NullReferenceException(nameof(URLs)); throw new NullReferenceException(nameof(URLs));
if (appSettings.WorkingDirectoryName is null) if (appSettings.WorkingDirectoryName is null)
@ -85,10 +90,12 @@ public class AppSettings
appSettings.LinuxDevicePath, appSettings.LinuxDevicePath,
appSettings.IsDevelopment.Value, appSettings.IsDevelopment.Value,
appSettings.IsStaging.Value, appSettings.IsStaging.Value,
appSettings.NotifyMinimum.Value,
appSettings.MockRoot, appSettings.MockRoot,
appSettings.MonAResource, appSettings.MonAResource,
appSettings.MonASite, appSettings.MonASite,
appSettings.RootPassword, appSettings.RootPassword,
appSettings.SerialPortName,
appSettings.URLs, appSettings.URLs,
appSettings.WorkingDirectoryName, appSettings.WorkingDirectoryName,
appSettings.WriteToSerialEvery.Value); appSettings.WriteToSerialEvery.Value);

26
Server/Pages/Error.cshtml Normal file
View File

@ -0,0 +1,26 @@
@page
@model ErrorModel
@{
ViewData["Title"] = "Error";
}
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
@if (Model.ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
}
<h3>Development Mode</h3>
<p>
Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>

View File

@ -0,0 +1,23 @@
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace Barcode.Host.Server.Pages;
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
[IgnoreAntiforgeryToken]
public class ErrorModel : PageModel
{
public string? RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
private readonly ILogger<ErrorModel> _Logger;
public ErrorModel(ILogger<ErrorModel> logger) =>
_Logger = logger;
public void OnGet() =>
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
}

View File

@ -0,0 +1,10 @@
@page
<div class="container">
<div class="row p-1">
<div class="col-6">
<h1 id="data" style="text-align:center"></h1>
</div>
</div>
</div>
<script src="~/js/signalr/dist/browser/signalr.js"></script>
<script src="~/js/notification.js"></script>

View File

@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace Barcode.Host.Server.Pages;
public class NotificationModel : PageModel
{
private readonly ILogger<NotificationModel> _Logger;
public NotificationModel(ILogger<NotificationModel> logger) =>
_Logger = logger;
public void OnGet()
{
}
}

View File

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Barcode Host</title>
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
</head>
<body>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<script src="~/js/site.js" asp-append-version="true"></script>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>

View File

@ -0,0 +1,48 @@
/* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
for details on configuring this project to bundle and minify static web assets. */
a.navbar-brand {
white-space: normal;
text-align: center;
word-break: break-all;
}
a {
color: #0077cc;
}
.btn-primary {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}
.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}
.border-top {
border-top: 1px solid #e5e5e5;
}
.border-bottom {
border-bottom: 1px solid #e5e5e5;
}
.box-shadow {
box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
}
button.accept-policy {
font-size: 1rem;
line-height: inherit;
}
.footer {
position: absolute;
bottom: 0;
width: 100%;
white-space: nowrap;
line-height: 60px;
}

View File

@ -0,0 +1,2 @@
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>

View File

@ -0,0 +1,3 @@
@using Barcode.Host.Server
@namespace Barcode.Host.Server.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

View File

@ -0,0 +1,3 @@
@{
Layout = "_Layout";
}

View File

@ -1,12 +1,9 @@
using Barcode.Host.Server.HostedService; using Barcode.Host.Server.HostedService;
using Barcode.Host.Server.Hubs;
using Barcode.Host.Server.Models; using Barcode.Host.Server.Models;
using Barcode.Host.Server.Services; using Barcode.Host.Server.Services;
using Barcode.Host.Shared.Models; using Barcode.Host.Shared.Models;
using Barcode.Host.Shared.Models.Stateless; using Barcode.Host.Shared.Models.Stateless;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog; using Serilog;
using System.Reflection; using System.Reflection;
@ -48,7 +45,7 @@ public class Program
_ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, webApplicationBuilder.Configuration); _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, webApplicationBuilder.Configuration);
_ = SerilogHostBuilderExtensions.UseSerilog(webApplicationBuilder.Host); _ = SerilogHostBuilderExtensions.UseSerilog(webApplicationBuilder.Host);
Log.Logger = loggerConfiguration.CreateLogger(); Log.Logger = loggerConfiguration.CreateLogger();
ILogger log = Log.ForContext<Program>(); Serilog.ILogger log = Log.ForContext<Program>();
try try
{ {
if (appSettings.IsStaging && appSettings.IsDevelopment) if (appSettings.IsStaging && appSettings.IsDevelopment)
@ -57,6 +54,8 @@ public class Program
throw new NotSupportedException("Please check appsettings file(s)!"); throw new NotSupportedException("Please check appsettings file(s)!");
if (appSettings.IsDevelopment != webApplicationBuilder.Environment.IsDevelopment()) if (appSettings.IsDevelopment != webApplicationBuilder.Environment.IsDevelopment())
throw new NotSupportedException("Please check appsettings file(s)!"); throw new NotSupportedException("Please check appsettings file(s)!");
_ = webApplicationBuilder.Services.AddRazorPages();
_ = webApplicationBuilder.Services.AddSignalR();
_ = webApplicationBuilder.Services.AddControllersWithViews(); _ = webApplicationBuilder.Services.AddControllersWithViews();
_ = webApplicationBuilder.Services.AddSingleton(_ => appSettings); _ = webApplicationBuilder.Services.AddSingleton(_ => appSettings);
_ = webApplicationBuilder.Services.AddSingleton<ISerialService, SerialService>(); _ = webApplicationBuilder.Services.AddSingleton<ISerialService, SerialService>();
@ -76,11 +75,13 @@ public class Program
_ = webApplication.UseExceptionHandler("/Error"); _ = webApplication.UseExceptionHandler("/Error");
_ = webApplication.UseHsts(); _ = webApplication.UseHsts();
} }
_ = webApplication.UseCors(corsPolicyBuilder => corsPolicyBuilder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
_ = webApplication.Lifetime.ApplicationStopped.Register(Log.CloseAndFlush); _ = webApplication.Lifetime.ApplicationStopped.Register(Log.CloseAndFlush);
_ = webApplication.UseFileServer(enableDirectoryBrowsing: true);
_ = webApplication.UseStaticFiles(); _ = webApplication.UseStaticFiles();
_ = webApplication.UseRouting();
_ = webApplication.UseAuthorization();
_ = webApplication.MapControllers(); _ = webApplication.MapControllers();
_ = webApplication.MapRazorPages();
_ = webApplication.MapHub<NotificationHub>($"/{nameof(NotificationHub)}");
log.Information("Starting Web Application"); log.Information("Starting Web Application");
webApplication.Run(); webApplication.Run();
return 0; return 0;

View File

@ -4,7 +4,7 @@
"commandName": "Project", "commandName": "Project",
"dotnetRunMessages": true, "dotnetRunMessages": true,
"launchBrowser": false, "launchBrowser": false,
"applicationUrl": "http://localhost:5126", "applicationUrl": "http://localhost:5003",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }
@ -13,7 +13,7 @@
"commandName": "Project", "commandName": "Project",
"dotnetRunMessages": true, "dotnetRunMessages": true,
"launchBrowser": false, "launchBrowser": false,
"applicationUrl": "https://localhost:7130;http://localhost:5126", "applicationUrl": "https://localhost:5004;http://localhost:5003",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }
@ -22,7 +22,7 @@
"commandName": "Project", "commandName": "Project",
"dotnetRunMessages": true, "dotnetRunMessages": true,
"launchBrowser": false, "launchBrowser": false,
"applicationUrl": "https://localhost:7130;http://localhost:5126", "applicationUrl": "https://localhost:5004;http://localhost:5003",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Production" "ASPNETCORE_ENVIRONMENT": "Production"
} }

View File

@ -9,20 +9,23 @@ public class SerialService : ISerialService
private string _LastRaw; private string _LastRaw;
private readonly AppSettings _AppSettings; private readonly AppSettings _AppSettings;
private readonly System.IO.Ports.SerialPort _SerialPort; private readonly System.IO.Ports.SerialPort? _SerialPort;
public SerialService(AppSettings appSettings) public SerialService(AppSettings appSettings)
{ {
_LastRaw = string.Empty; _LastRaw = string.Empty;
_AppSettings = appSettings; _AppSettings = appSettings;
_SerialPort = new("/dev/ttyUSB0", 9600) { ReadTimeout = 2 }; if (string.IsNullOrEmpty(appSettings.SerialPortName))
_SerialPort = null;
else
_SerialPort = new(appSettings.SerialPortName, 9600) { ReadTimeout = 2 };
} }
void ISerialService.Open() => void ISerialService.Open() =>
_SerialPort.Open(); _SerialPort?.Open();
void ISerialService.Close() => void ISerialService.Close() =>
_SerialPort.Close(); _SerialPort?.Close();
void ISerialService.SerialPortWrite(int count, string raw) void ISerialService.SerialPortWrite(int count, string raw)
{ {
@ -36,7 +39,7 @@ public class SerialService : ISerialService
else else
message = $" {raw}"; message = $" {raw}";
byte[] bytes = Encoding.ASCII.GetBytes(message); byte[] bytes = Encoding.ASCII.GetBytes(message);
_SerialPort.Write(bytes, 0, bytes.Length); _SerialPort?.Write(bytes, 0, bytes.Length);
_LastRaw = raw; _LastRaw = raw;
} }
} }

View File

@ -18,9 +18,11 @@
}, },
"IsDevelopment": false, "IsDevelopment": false,
"IsStaging": false, "IsStaging": false,
"NotifyMinimum": 3,
"MockRoot": "", "MockRoot": "",
"MonAResource": "OI_Metrology_Viewer_EC", "MonAResource": "OI_Metrology_Viewer_EC",
"MonASite": "auc", "MonASite": "auc",
"SerialPortName": "/dev/ttyUSB0",
"Serilog": { "Serilog": {
"Using": [ "Using": [
"Serilog.Sinks.Console", "Serilog.Sinks.Console",

View File

@ -0,0 +1,22 @@
html {
font-size: 14px;
}
@media (min-width: 768px) {
html {
font-size: 16px;
}
}
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}
html {
position: relative;
min-height: 100%;
}
body {
margin-bottom: 60px;
}

BIN
Server/wwwroot/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -0,0 +1,13 @@
"use strict";
var connection = new signalR.HubConnectionBuilder().withUrl("/NotificationHub").build();
connection.on("NotifyAll", function (data) {
var message = `${data.keyPressEvent.dateTime} - [${data.lastScanServiceResultValue}]`;
document.getElementById("data").innerText = message;
});
connection.start().then(function () {
}).catch(function (err) {
return console.error(err.toString());
});

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@


View File

@ -115,9 +115,10 @@ public class InputReader : IDisposable
{ {
short code = GetCode(); short code = GetCode();
int value = GetValue(); int value = GetValue();
DateTime dateTime = DateTime.Now;
KeyState keyState = (KeyState)value; KeyState keyState = (KeyState)value;
EventCode eventCode = (EventCode)code; EventCode eventCode = (EventCode)code;
KeyPressEvent keyPressEvent = new(eventCode, keyState, new TimeSpan(DateTime.Now.Ticks - _Ticks)); KeyPressEvent keyPressEvent = new(dateTime, eventCode, keyState, new TimeSpan(dateTime.Ticks - _Ticks));
OnKeyPress?.Invoke(keyPressEvent); OnKeyPress?.Invoke(keyPressEvent);
} }

View File

@ -2,13 +2,14 @@ namespace Barcode.Host.Shared.KeyboardMouse;
public readonly struct KeyPressEvent public readonly struct KeyPressEvent
{ {
public DateTime DateTime { get; init; }
public EventCode EventCode { get; init; } public EventCode EventCode { get; init; }
public KeyState KeyState { get; init; } public KeyState KeyState { get; init; }
public TimeSpan TimeSpan { get; init; } public TimeSpan TimeSpan { get; init; }
public KeyPressEvent(EventCode eventCode, KeyState keyState, TimeSpan timeSpan) public KeyPressEvent(DateTime dateTime, EventCode eventCode, KeyState keyState, TimeSpan timeSpan)
{ {
DateTime = dateTime;
EventCode = eventCode; EventCode = eventCode;
KeyState = keyState; KeyState = keyState;
TimeSpan = timeSpan; TimeSpan = timeSpan;

View File

@ -0,0 +1,5 @@
using Barcode.Host.Shared.KeyboardMouse;
namespace Barcode.Host.Shared.Models;
public record Notification(KeyPressEvent KeyPressEvent, string LastScanServiceResultValue);