Add project files.

This commit is contained in:
EugeneTes
2026-01-13 09:06:47 +01:00
parent dd935fe1fa
commit 7390693f50
187 changed files with 83457 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
using System.Text.Json;
using Inspectron.Epson.PrintServer.ConfigurationSources;
using Inspectron.Epson.PrintServer.PrintServices;
namespace ConfigurationPannel.Services;
public class ConfigurationManager
{
private readonly string _configPath;
private readonly SemaphoreSlim _configLock = new SemaphoreSlim(1, 1);
private EpsonPrintServiceConfiguration? _currentConfig;
public ConfigurationManager(IWebHostEnvironment env)
{
_configPath = Path.Combine(env.ContentRootPath, "config.json");
}
public async Task<EpsonPrintServiceConfiguration> LoadConfigurationAsync()
{
await _configLock.WaitAsync();
try
{
if (File.Exists(_configPath))
{
var json = await File.ReadAllTextAsync(_configPath);
_currentConfig = JsonSerializer.Deserialize<EpsonPrintServiceConfiguration>(json);
}
else
{
_currentConfig = new EpsonPrintServiceConfiguration
{
GroupId = "default-group",
RestaurantId = "default-restaurant",
PrinterConfigurations = new Dictionary<string, PrinterConfiguration>()
};
}
return _currentConfig!;
}
finally
{
_configLock.Release();
}
}
public async Task SaveConfigurationAsync(EpsonPrintServiceConfiguration config)
{
await _configLock.WaitAsync();
try
{
var json = JsonSerializer.Serialize(config, new JsonSerializerOptions { WriteIndented = true });
await File.WriteAllTextAsync(_configPath, json);
_currentConfig = config;
}
finally
{
_configLock.Release();
}
}
public EpsonPrintServiceConfiguration? GetCurrentConfiguration() => _currentConfig;
}

View File

@@ -0,0 +1,119 @@
namespace ConfigurationPannel.Services;
public class LogoService
{
private readonly IWebHostEnvironment _env;
private readonly string _logosPath;
private readonly ILogger<LogoService> _logger;
public LogoService(IWebHostEnvironment env, ILogger<LogoService> logger)
{
_env = env;
_logger = logger;
_logosPath = Path.Combine(_env.WebRootPath, "logos");
// Ensure logos directory exists
if (!Directory.Exists(_logosPath))
{
Directory.CreateDirectory(_logosPath);
}
}
public async Task<string> SaveLogoAsync(IFormFile file)
{
if (file == null || file.Length == 0)
throw new ArgumentException("No file provided");
// Validate file type
var allowedExtensions = new[] { ".png", ".jpg", ".jpeg", ".gif", ".bmp" };
var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
if (!allowedExtensions.Contains(extension))
throw new ArgumentException($"Invalid file type. Allowed: {string.Join(", ", allowedExtensions)}");
// Generate unique filename to avoid collisions
var fileName = $"{Path.GetFileNameWithoutExtension(file.FileName)}_{Guid.NewGuid().ToString("N").Substring(0, 8)}{extension}";
var filePath = Path.Combine(_logosPath, fileName);
using (var stream = new FileStream(filePath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
_logger.LogInformation("Logo uploaded: {FileName}", fileName);
return fileName;
}
public List<string> GetAllLogos()
{
if (!Directory.Exists(_logosPath))
return new List<string>();
return Directory.GetFiles(_logosPath)
.Select(Path.GetFileName)
.Where(f => f != null)
.Select(f => f!)
.OrderBy(f => f)
.ToList();
}
public string GetLogoUrl(string? filename)
{
if (string.IsNullOrEmpty(filename))
return string.Empty;
return $"/logos/{filename}";
}
public bool LogoExists(string filename)
{
return File.Exists(Path.Combine(_logosPath, filename));
}
public void DeleteLogo(string filename)
{
var filePath = Path.Combine(_logosPath, filename);
if (File.Exists(filePath))
{
File.Delete(filePath);
_logger.LogInformation("Logo deleted: {FileName}", filename);
}
}
public List<string> CleanUnusedLogos(IEnumerable<string> usedLogoFilenames)
{
var allLogos = GetAllLogos();
var usedSet = new HashSet<string>(usedLogoFilenames.Where(f => !string.IsNullOrEmpty(f))!);
var unusedLogos = allLogos.Where(logo => !usedSet.Contains(logo)).ToList();
foreach (var logo in unusedLogos)
{
DeleteLogo(logo);
}
_logger.LogInformation("Cleaned {Count} unused logos", unusedLogos.Count);
return unusedLogos;
}
public void CopyLogoToDirectory(string filename, string targetDirectory)
{
if (string.IsNullOrEmpty(filename))
return;
var sourcePath = Path.Combine(_logosPath, filename);
if (!File.Exists(sourcePath))
{
_logger.LogWarning("Logo file not found for copy: {FileName}", filename);
return;
}
if (!Directory.Exists(targetDirectory))
{
Directory.CreateDirectory(targetDirectory);
}
var targetPath = Path.Combine(targetDirectory, filename);
File.Copy(sourcePath, targetPath, overwrite: true);
_logger.LogInformation("Logo copied to: {TargetPath}", targetPath);
}
}

View File

@@ -0,0 +1,16 @@
using System.Threading.Channels;
using Inspectron.Epson.PrintServer;
namespace ConfigurationPannel.Services;
public class NoOpPrintJobSource : IPrintJobSource
{
private readonly Channel<PrintJob> _channel = Channel.CreateUnbounded<PrintJob>();
public Task<PrintJob> GetNextJobAsync(CancellationToken cancellationToken)
{
// Blocks indefinitely, keeping PrintLoop alive without processing jobs
// This stub implementation keeps the loop running but never provides actual jobs
return _channel.Reader.ReadAsync(cancellationToken).AsTask();
}
}

View File

@@ -0,0 +1,130 @@
using Ninject;
using Inspectron.Epson.PrintServer;
using Inspectron.Epson.PrintServer.ConfigurationSources;
using Inspectron.Epson.PrintServer.JobSources;
using Inspectron.Epson.PrintServer.Printers;
using Inspectron.Epson.PrintServer.PrintServices;
using Microsoft.Extensions.Logging;
namespace ConfigurationPannel.Services;
public class PrintServerHostedService : IHostedService
{
private readonly ILogger<PrintServerHostedService> _logger;
private readonly ConfigurationManager _configManager;
private PrintServer? _printServer;
private PrintLoop? _printLoop;
private StandardKernel? _kernel;
public PrintServerHostedService(
ILogger<PrintServerHostedService> logger,
ConfigurationManager configManager)
{
_logger = logger;
_configManager = configManager;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Starting PrintServer background service");
await InitializePrintServerAsync();
}
private async Task InitializePrintServerAsync()
{
// Load configuration
var config = await _configManager.LoadConfigurationAsync();
// Setup Ninject kernel (matching EpsonPrintService pattern)
_kernel = new StandardKernel();
_kernel.Bind<EpsonPrintServiceConfiguration>().ToConstant(config);
_kernel.Bind<IPrintJobSource>().To<SignalRPrintJobSource>().InSingletonScope();
_kernel.Bind<IPrintService>().To<Inspectron.Epson.PrintServer.PrintServices.EpsonPrintService>();
_kernel.Bind<Microsoft.Extensions.Logging.ILogger>().ToConstant(_logger);
_kernel.Bind<IAssignedPrinterRepository>().ToConstant(config);
_kernel.Bind<IPrinterFactory>().To<PrinterFactory>().InSingletonScope();
_kernel.Bind<IPrinterConfigurationSource>().ToConstant(config);
_kernel.Bind<PrintServer>().ToSelf().InSingletonScope();
// Get instances
_printServer = _kernel.Get<PrintServer>();
_printLoop = _kernel.Get<PrintLoop>();
// Register printers from configuration
foreach (var printerConfig in config.PrinterConfigurations.Values)
{
_printServer.RegisterPrinter(printerConfig.Address);
}
// Start print loop
await _printLoop.StartAsync();
_logger.LogInformation("PrintServer background service started successfully");
}
public async Task RestartAsync()
{
_logger.LogInformation("Restarting PrintServer with new configuration");
// Stop current print loop
if (_printLoop != null)
{
await _printLoop.StopAsync();
}
// Shutdown print server
if (_printServer != null)
{
await _printServer.ShutdownAsync();
}
// Dispose kernel
_kernel?.Dispose();
// Reinitialize with new config
await InitializePrintServerAsync();
_logger.LogInformation("PrintServer background service restarted successfully");
}
public async Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Stopping PrintServer background service");
if (_printLoop != null)
{
await _printLoop.StopAsync();
}
if (_printServer != null)
{
await _printServer.ShutdownAsync();
}
_kernel?.Dispose();
_logger.LogInformation("PrintServer background service stopped");
}
public async Task<(bool Success, string Message)> SubmitPrintJobAsync(string workAreaId, string content)
{
if (_printServer == null)
return (false, "Print server not initialized");
var config = await _configManager.LoadConfigurationAsync();
var printerIp = config.GetAssignedPrinter(workAreaId);
if (string.IsNullOrEmpty(printerIp))
return (false, "No printer assigned to this work area");
var job = new PrintJob
{
AreaId = workAreaId,
Document = content
};
_printServer.SubmitJob(printerIp, job);
_logger.LogInformation($"Test print job submitted to {printerIp} for work area {workAreaId}");
return (true, $"Print job submitted successfully to {printerIp}");
}
}

View File

@@ -0,0 +1,39 @@
using System.Text.Json;
namespace ConfigurationPannel.Services;
public class UserService
{
private readonly string _usersFilePath;
public UserService(IWebHostEnvironment env)
{
_usersFilePath = Path.Combine(env.ContentRootPath, "users.json");
}
public async Task<bool> ValidateCredentialsAsync(string username, string password)
{
if (!File.Exists(_usersFilePath))
return false;
var json = await File.ReadAllTextAsync(_usersFilePath);
var userStore = JsonSerializer.Deserialize<UserStore>(json, new JsonSerializerOptions(){PropertyNameCaseInsensitive = true});
var user = userStore?.Users.FirstOrDefault(u => u.Username == username);
if (user == null)
return false;
return user.Password==password;
}
}
public class UserStore
{
public List<User> Users { get; set; } = new();
}
public class User
{
public string Username { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
}