Check-in Source

Signed-off-by: mharb <mharb@noreply.localhost>
This commit is contained in:
2025-08-02 19:40:09 -04:00
parent b9cf975de8
commit 80d6e912ab
5 changed files with 177 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<None Remove="ProtosXdigitalDemo.zip" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="NModbus4" Version="2.1.0" />
<PackageReference Include="System.IO.Ports" Version="9.0.7" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.14.36121.58
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProtosXdigitalDemo", "ProtosXdigitalDemo.csproj", "{A013091C-203C-48BA-8CD2-317296C4FB44}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A013091C-203C-48BA-8CD2-317296C4FB44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A013091C-203C-48BA-8CD2-317296C4FB44}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A013091C-203C-48BA-8CD2-317296C4FB44}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A013091C-203C-48BA-8CD2-317296C4FB44}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {86B02D30-0D88-436B-BEAE-84202E5FBFF8}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,31 @@
using System;
using System.Net.Sockets;
using static System.Console;
namespace ProtosXdigitalDemo
{
internal class TcpClientConnector
{
private readonly string _ip;
private readonly int _port;
public TcpClientConnector(string ip, int port)
{
_ip = ip;
_port = port;
}
public TcpClient Connect()
{
try
{
return new TcpClient(_ip, _port);
}
catch (Exception ex)
{
WriteLine($"[Error] Unable to connect to {_ip}:{_port} → {ex.Message}");
throw;
}
}
}
}

View File

@@ -0,0 +1,77 @@
using System.Runtime.InteropServices;
using static System.Console;
namespace ProtosXdigitalDemo
{
static class WindowUtility
{
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
const uint SWP_NOSIZE = 0x0001;
const uint SWP_NOZORDER = 0x0004;
private static Size GetScreenSize() => new Size(GetSystemMetrics(0), GetSystemMetrics(1));
private struct Size
{
public int Width { get; set; }
public int Height { get; set; }
public Size(int width, int height)
{
Width = width;
Height = height;
}
}
[DllImport("kernel32.dll", ExactSpelling = true)]
private static extern IntPtr GetConsoleWindow();
[DllImport("User32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
private static extern int GetSystemMetrics(int nIndex);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowRect(HandleRef hWnd, out Rect lpRect);
[StructLayout(LayoutKind.Sequential)]
private struct Rect
{
public int Left; // x position of upper-left corner
public int Top; // y position of upper-left corner
public int Right; // x position of lower-right corner
public int Bottom; // y position of lower-right corner
}
private static Size GetWindowSize(IntPtr window)
{
if (!GetWindowRect(new HandleRef(null, window), out Rect rect))
throw new Exception("Unable to get window rect!");
int width = rect.Right - rect.Left;
int height = rect.Bottom - rect.Top;
return new Size(width, height);
}
public static void MoveWindowToCenter()
{
IntPtr window = GetConsoleWindow();
if (window == IntPtr.Zero)
throw new Exception("Couldn't find a window to center!");
Size screenSize = GetScreenSize();
Size windowSize = GetWindowSize(window);
int x = (screenSize.Width - windowSize.Width) / 2;
int y = (screenSize.Height - windowSize.Height) / 2;
SetWindowPos(window, IntPtr.Zero, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}
public static void SetAppearanceOptions()
{
if (!IsOutputRedirected) // set console window size
{
BufferWidth = 150;
SetWindowSize(BufferWidth, 50);
}
}
}
}

View File

@@ -0,0 +1,25 @@
using System;
using static System.Console;
using Modbus.Device; // Hard dependency on Nmodbus4
using System.Net.Sockets;
namespace ProtosXdigitalDemo
{
internal class WriteMachineDigitalStateToIO
{
public static byte WriteMachineStateToIO(ModbusIpMaster master, ushort coilOutputStartAddress)
{
try
{
master.WriteMultipleCoils(coilOutputStartAddress, Data.MachineState.digitalOutputChannels);
}
catch (Exception ex)
{
WriteLine($"Error writing discrete outputs: {ex.Message}");
_ = ReadKey(true);
return Data.MachineState.failureCode[1];
}
return Data.MachineState.failureCode[0];
}
}
}