initial version with serial link
This commit is contained in:
158
analog_system_monitor_dotnet/SerialManager.cs
Normal file
158
analog_system_monitor_dotnet/SerialManager.cs
Normal file
@@ -0,0 +1,158 @@
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.IO.Ports;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
public class SerialManager : IDisposable
|
||||
{
|
||||
private SerialPort? port;
|
||||
private DateTime lastResponse = DateTime.UtcNow;
|
||||
|
||||
private const int BaudRate = 115200;
|
||||
private const int PingTimeoutMs = 300;
|
||||
private const int WatchdogTimeoutMs = 3000;
|
||||
|
||||
public bool IsConnected => port != null && port.IsOpen;
|
||||
|
||||
// ---------------- DEVICE DISCOVERY ----------------
|
||||
|
||||
public void DiscoverDevice()
|
||||
{
|
||||
DisposePort();
|
||||
|
||||
foreach (string com in SerialPort.GetPortNames().OrderBy(s => s))
|
||||
{
|
||||
string? response = null;
|
||||
|
||||
try
|
||||
{
|
||||
using (var testPort = CreatePort(com, PingTimeoutMs))
|
||||
{
|
||||
testPort.Open();
|
||||
Thread.Sleep(350); // RP2040 resets on open
|
||||
|
||||
testPort.DiscardInBuffer();
|
||||
testPort.DiscardOutBuffer();
|
||||
|
||||
testPort.Write("PING\n");
|
||||
|
||||
try
|
||||
{
|
||||
if (testPort.BytesToRead > 0)
|
||||
response = testPort.ReadLine();
|
||||
}
|
||||
catch (TimeoutException)
|
||||
{
|
||||
// No response — move to next port
|
||||
}
|
||||
}
|
||||
|
||||
if (response != null &&
|
||||
response.StartsWith("Analog_System_Monitor_"))
|
||||
{
|
||||
port = CreatePort(com, 500);
|
||||
port.Open();
|
||||
Thread.Sleep(350); // allow RP2040 reboot again
|
||||
|
||||
lastResponse = DateTime.UtcNow;
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Silent fail — move to next COM port
|
||||
}
|
||||
}
|
||||
|
||||
port = null;
|
||||
}
|
||||
|
||||
// ---------------- PORT FACTORY ----------------
|
||||
|
||||
private SerialPort CreatePort(string com, int timeout)
|
||||
{
|
||||
return new SerialPort(com, BaudRate)
|
||||
{
|
||||
Parity = Parity.None,
|
||||
DataBits = 8,
|
||||
StopBits = StopBits.One,
|
||||
Handshake = Handshake.None,
|
||||
|
||||
NewLine = "\n",
|
||||
Encoding = System.Text.Encoding.ASCII,
|
||||
|
||||
ReadTimeout = timeout,
|
||||
WriteTimeout = timeout,
|
||||
|
||||
DtrEnable = true, // REQUIRED for RP2040 USB CDC
|
||||
RtsEnable = true
|
||||
};
|
||||
}
|
||||
|
||||
// ---------------- WATCHDOG ----------------
|
||||
|
||||
public bool WatchdogExpired =>
|
||||
(DateTime.UtcNow - lastResponse).TotalMilliseconds > WatchdogTimeoutMs;
|
||||
|
||||
// ---------------- SEND COMMAND ----------------
|
||||
|
||||
public void SendSetAll(string cmd)
|
||||
{
|
||||
if (!IsConnected)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
port!.Write(cmd + "\n");
|
||||
|
||||
string? response = null;
|
||||
|
||||
try
|
||||
{
|
||||
if (port.BytesToRead > 0)
|
||||
response = port.ReadLine();
|
||||
}
|
||||
catch (TimeoutException)
|
||||
{
|
||||
// No response this tick — totally fine
|
||||
}
|
||||
|
||||
if (response != null &&
|
||||
(response.StartsWith("OK") || response.StartsWith("ERROR")))
|
||||
{
|
||||
lastResponse = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Silent fail — watchdog will trigger reconnect
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------- CLEANUP ----------------
|
||||
|
||||
private void DisposePort()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (port != null)
|
||||
{
|
||||
port.Close();
|
||||
port.Dispose();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
port = null;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DisposePort();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user