updates for starting service and publish package

This commit is contained in:
NinjaPug
2025-03-29 12:41:39 -04:00
parent 22b068773d
commit 7622c3972a
8 changed files with 119 additions and 102 deletions

View File

@@ -1,21 +1,21 @@
# Define the service name and path to the published service # Define the service name and path to the published service
$ServiceName = "ESP32BackgroundService" $ServiceName = "PCPalService"
$ServiceExePath = "$PSScriptRoot\ESP32BackgroundService.exe" $ServiceExePath = "$PSScriptRoot\PCPalService\bin\Release\net8.0\publish\win-x64\PCPalService.exe"
# Function to check if the service exists # Function to check if the service exists
function ServiceExists { function ServiceExists {
return Get-Service -Name $ServiceName -ErrorAction SilentlyContinue return Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
} }
# Install the service
function Install-Service { function Install-Service {
if (ServiceExists) { if (ServiceExists) {
Write-Host "Service '$ServiceName' already exists." Write-Host "Service '$ServiceName' already exists."
return return
} }
Write-Host "Installing service '$ServiceName'..." Write-Host "Installing service '$ServiceName'..."
sc.exe create $ServiceName binPath= "`"$ServiceExePath`"" start= auto sc.exe create $ServiceName binPath= "`"$ServiceExePath`"" start= auto obj= "LocalSystem"
sc.exe failure $ServiceName reset= 0 actions= restart/5000 sc.exe failure $ServiceName reset= 0 actions= restart/5000
sc.exe description $ServiceName "PCPal Background Monitoring Service"
Start-Service -Name $ServiceName Start-Service -Name $ServiceName
Write-Host "Service installed and started successfully with auto-restart enabled." Write-Host "Service installed and started successfully with auto-restart enabled."
} }

View File

@@ -37,7 +37,7 @@ namespace PCPalConfigurator
private static string GetConfigPath() private static string GetConfigPath()
{ {
string folder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "PCPal"); string folder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "PCPal");
Directory.CreateDirectory(folder); Directory.CreateDirectory(folder);
return Path.Combine(folder, "config.json"); return Path.Combine(folder, "config.json");
} }

View File

@@ -10,6 +10,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="LibreHardwareMonitorLib" Version="0.9.4" /> <PackageReference Include="LibreHardwareMonitorLib" Version="0.9.4" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="System.IO.Ports" Version="9.0.3" /> <PackageReference Include="System.IO.Ports" Version="9.0.3" />
</ItemGroup> </ItemGroup>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_LastSelectedProfileId>C:\Users\ckoch\OneDrive\Documents\GitHub\PCPal\PCPalService\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
</PropertyGroup>
</Project>

View File

@@ -1,7 +1,10 @@
using PCPalService; using PCPalService;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System; using System;
using Microsoft.Extensions.Hosting.WindowsServices;
namespace PCPalService namespace PCPalService
{ {
@@ -13,10 +16,11 @@ namespace PCPalService
} }
public static IHostBuilder CreateHostBuilder(string[] args) => public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args) Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) => .UseWindowsService()
{ .ConfigureServices((hostContext, services) =>
services.AddHostedService<Worker>(); {
}); services.AddHostedService<Worker>();
});
} }
} }

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
<Project>
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>bin\Release\net8.0\publish\win-x64\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<_TargetId>Folder</_TargetId>
<TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<SelfContained>true</SelfContained>
<PublishSingleFile>false</PublishSingleFile>
<PublishReadyToRun>false</PublishReadyToRun>
<PublishTrimmed>false</PublishTrimmed>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
<Project>
<PropertyGroup>
<History>True|2025-03-29T16:38:44.4981820Z||;False|2025-03-29T12:38:09.2222007-04:00||;True|2025-03-29T12:24:00.0314544-04:00||;True|2025-03-29T12:02:53.1292190-04:00||;False|2025-03-29T11:58:39.8048030-04:00||;False|2025-03-29T11:58:17.4946697-04:00||;False|2025-03-29T11:57:29.9733195-04:00||;False|2025-03-29T11:56:43.0182350-04:00||;False|2025-03-29T11:56:07.6627870-04:00||;True|2025-03-28T17:00:47.0111533-04:00||;True|2025-03-28T16:59:59.8928039-04:00||;True|2025-03-28T16:58:17.3481844-04:00||;True|2025-03-28T16:57:41.5786839-04:00||;True|2025-03-28T16:55:58.0823642-04:00||;</History>
<LastFailureDetails />
</PropertyGroup>
</Project>

View File

@@ -1,14 +1,13 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System; using System;
using System.IO; using System.IO;
using System.IO.Ports; using System.IO.Ports;
using System.ServiceProcess;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using LibreHardwareMonitor.Hardware;
using Newtonsoft.Json; using Newtonsoft.Json;
using Microsoft.Extensions.Hosting; using LibreHardwareMonitor.Hardware;
using Microsoft.Extensions.Logging;
namespace PCPalService namespace PCPalService
{ {
@@ -17,124 +16,129 @@ namespace PCPalService
private readonly ILogger<Worker> _logger; private readonly ILogger<Worker> _logger;
private SerialPort serialPort; private SerialPort serialPort;
private Computer computer; private Computer computer;
private readonly string ConfigFile = GetConfigPath();
private const string LogFile = "service_log.txt"; private const string AppDataFolder = "PCPal";
private const string ConfigFileName = "config.json";
public Worker(ILogger<Worker> logger) public Worker(ILogger<Worker> logger)
{ {
_logger = logger; _logger = logger;
computer = new Computer { IsCpuEnabled = true, IsMemoryEnabled = true };
computer.Open();
}
private static string GetConfigPath()
{
string folder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "PCPal");
Directory.CreateDirectory(folder); // Ensure folder exists
return Path.Combine(folder, "config.json");
} }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{ {
Log("ESP32 Background Service Starting..."); _logger.LogInformation("Service starting...");
computer = new Computer
{
IsCpuEnabled = true,
IsMemoryEnabled = true,
IsGpuEnabled = true,
IsMotherboardEnabled = true
};
computer.Open();
while (!stoppingToken.IsCancellationRequested) while (!stoppingToken.IsCancellationRequested)
{ {
try try
{ {
if (!File.Exists(ConfigFile)) string configPath = GetConfigPath();
if (!File.Exists(configPath))
{ {
Log("Config file not found. Retrying in 5 seconds..."); _logger.LogWarning("Config file not found. Retrying in 5 seconds...");
await Task.Delay(5000, stoppingToken); await Task.Delay(5000, stoppingToken);
continue; continue;
} }
var config = LoadConfig(); var config = LoadConfig(configPath);
if (serialPort == null || !serialPort.IsOpen) if (serialPort == null || !serialPort.IsOpen)
{ {
string portName = AutoDetectESP32(); string port = AutoDetectESP32();
if (portName != null) if (port != null)
{ {
serialPort = new SerialPort(portName, 115200); serialPort = new SerialPort(port, 115200);
serialPort.Open(); serialPort.Open();
Log($"Connected to ESP32-C3 on {portName}"); _logger.LogInformation($"Connected to ESP32 on {port}");
} }
else else
{ {
Log("ESP32-C3 not found. Retrying in 5 seconds..."); _logger.LogWarning("ESP32 not found. Retrying in 5 seconds...");
await Task.Delay(5000, stoppingToken); await Task.Delay(5000, stoppingToken);
continue; continue;
} }
} }
string line1 = GetLCDContent(config.Line1Selection, config.Line1CustomText, config.Line1PostText); string line1 = GetSensorLine(config.Line1Selection, config.Line1CustomText, config.Line1PostText);
string line2 = GetLCDContent(config.Line2Selection, config.Line2CustomText, config.Line2PostText); string line2 = GetSensorLine(config.Line2Selection, config.Line2CustomText, config.Line2PostText);
SendCommand($"CMD:LCD,0,{line1}"); serialPort.WriteLine($"CMD:LCD,0,{line1}");
SendCommand($"CMD:LCD,1,{line2}"); serialPort.WriteLine($"CMD:LCD,1,{line2}");
_logger.LogInformation("Data sent to LCD.");
await Task.Delay(5000, stoppingToken);
} }
catch (Exception ex) catch (Exception ex)
{ {
Log($"Error in service loop: {ex.Message}"); _logger.LogError(ex, "Error in main loop");
await Task.Delay(5000, stoppingToken);
} }
await Task.Delay(5000, stoppingToken);
} }
serialPort?.Close(); serialPort?.Close();
} }
private string GetConfigPath()
{
string folder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), AppDataFolder);
Directory.CreateDirectory(folder);
return Path.Combine(folder, ConfigFileName);
}
private ConfigData LoadConfig(string path)
{
string json = File.ReadAllText(path);
return JsonConvert.DeserializeObject<ConfigData>(json) ?? new ConfigData();
}
private string AutoDetectESP32() private string AutoDetectESP32()
{ {
foreach (string port in SerialPort.GetPortNames()) foreach (string port in SerialPort.GetPortNames())
{ {
if (IsESP32Device(port)) return port; try
{
using (SerialPort test = new SerialPort(port, 115200))
{
test.Open();
test.WriteLine("CMD:GET_LCD_TYPE");
Thread.Sleep(500);
string response = test.ReadExisting();
if (response.Contains("LCD_TYPE:1602A"))
return port;
}
}
catch { }
} }
return null; return null;
} }
private bool IsESP32Device(string portName) private string GetSensorLine(string selection, string prefix, string suffix)
{ {
try if (selection == "Custom Text")
{ return prefix;
using (SerialPort testPort = new SerialPort(portName, 115200))
{
testPort.Open();
testPort.WriteLine("CMD:GET_LCD_TYPE");
Thread.Sleep(500);
string response = testPort.ReadExisting();
testPort.Close();
return response.Contains("LCD_TYPE:1602A");
}
}
catch { return false; }
}
private void UpdateLCD()
{
ConfigData config = LoadConfig();
string line1 = GetLCDContent(config.Line1Selection, config.Line1CustomText, config.Line1PostText);
string line2 = GetLCDContent(config.Line2Selection, config.Line2CustomText, config.Line2PostText);
SendCommand($"CMD:LCD,0,{line1}");
SendCommand($"CMD:LCD,1,{line2}");
}
private string GetLCDContent(string selection, string prefix, string postfix)
{
var parsed = ParseSensorSelection(selection); var parsed = ParseSensorSelection(selection);
if (parsed == null) if (parsed == null)
return "N/A"; return "N/A";
string value = GetSensorValue(parsed.Value.hardwareType, parsed.Value.sensorName, parsed.Value.sensorType); string value = GetSensorValue(parsed.Value.hardwareType, parsed.Value.sensorName, parsed.Value.sensorType);
return $"{prefix}{value}{postfix}"; return $"{prefix}{value}{suffix}";
} }
private (HardwareType hardwareType, string sensorName, SensorType sensorType)? ParseSensorSelection(string input) private (HardwareType hardwareType, string sensorName, SensorType sensorType)? ParseSensorSelection(string input)
{ {
if (string.IsNullOrWhiteSpace(input))
return null;
try try
{ {
var parts = input.Split(':', 2); var parts = input.Split(':', 2);
@@ -142,7 +146,6 @@ namespace PCPalService
var hardwareType = Enum.Parse<HardwareType>(parts[0].Trim()); var hardwareType = Enum.Parse<HardwareType>(parts[0].Trim());
var sensorInfo = parts[1].Trim(); var sensorInfo = parts[1].Trim();
int idx = sensorInfo.LastIndexOf('('); int idx = sensorInfo.LastIndexOf('(');
if (idx == -1) return null; if (idx == -1) return null;
@@ -157,14 +160,15 @@ namespace PCPalService
return null; return null;
} }
} }
private string GetSensorValue(HardwareType type, string name, SensorType sensorType) private string GetSensorValue(HardwareType type, string name, SensorType sensorType)
{ {
foreach (IHardware hardware in computer.Hardware) foreach (var hardware in computer.Hardware)
{ {
if (hardware.HardwareType == type) if (hardware.HardwareType == type)
{ {
hardware.Update(); hardware.Update();
foreach (ISensor sensor in hardware.Sensors) foreach (var sensor in hardware.Sensors)
{ {
if (sensor.SensorType == sensorType && sensor.Name == name) if (sensor.SensorType == sensorType && sensor.Name == name)
{ {
@@ -175,39 +179,16 @@ namespace PCPalService
} }
return "N/A"; return "N/A";
} }
private ConfigData LoadConfig()
{
if (File.Exists(ConfigFile))
{
string json = File.ReadAllText(ConfigFile);
return JsonConvert.DeserializeObject<ConfigData>(json) ?? new ConfigData();
}
return new ConfigData();
}
private void SendCommand(string command)
{
serialPort.WriteLine(command);
Log($"Sent: {command}");
}
private void Log(string message)
{
string logEntry = $"{DateTime.Now}: {message}";
File.AppendAllText(LogFile, logEntry + Environment.NewLine);
_logger.LogInformation(message);
}
} }
class ConfigData public class ConfigData
{ {
public string Line1Selection { get; set; } public string Line1Selection { get; set; }
public string Line1CustomText { get; set; } public string Line1CustomText { get; set; }
public string Line1PostText { get; set; }
public string Line2Selection { get; set; } public string Line2Selection { get; set; }
public string Line2CustomText { get; set; } public string Line2CustomText { get; set; }
public string Line1PostText { get; set; }
public string Line2PostText { get; set; } public string Line2PostText { get; set; }
public string ScreenType { get; set; }
} }
} }