Files
DevToolsAvalonia/常用工具集/Utility/Network/Modbus/SharpSerial/SerialProcess.cs
2025-08-26 08:37:44 +08:00

127 lines
3.9 KiB
C#

using System;
using System.IO;
using System.Text;
using System.Diagnostics;
using System.Threading.Tasks;
namespace SharpSerial
{
//this class should not swallow exceptions outside dispose
public class SerialProcess : ISerialStream, IDisposable
{
private readonly Process process;
private readonly int pid;
public int Pid { get { return pid; } }
public SerialProcess(object settings)
{
var ss = new SerialSettings(settings);
var args = new StringBuilder();
foreach (var p in ss.GetType().GetProperties())
{
if (args.Length > 0) args.Append(" ");
args.AppendFormat("{0}={1}", p.Name, p.GetValue(ss, null).ToString());
}
process = new Process();
process.StartInfo = new ProcessStartInfo()
{
FileName = typeof(SerialProcess).Assembly.Location,
Arguments = args.ToString(),
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = false,
};
EnableStandardError(process.StartInfo);
process.Start();
pid = process.Id;
ForwardStandardError(process.StandardError);
}
public void Dispose()
{
Tools.Try(() =>
{
process.StandardInput.Close();
process.WaitForExit(200);
});
Tools.Try(process.Kill);
Tools.Try(process.Dispose);
}
public void Write(byte[] data)
{
WriteHex(data);
var line = ReadLine();
Tools.Assert(line == "<ok", "Unexpected write response {0}", line);
}
public byte[] Read(int size, int eop, int toms)
{
WriteLine("$r,{0},{1},{2}", size, eop, toms);
return ParseHex(ReadLine());
}
private string ReadLine()
{
var line = process.StandardOutput.ReadLine();
if (line == null) throw new EndOfStreamException("Serial process EOF");
if (line.StartsWith("!"))
{
var trace = process.StandardOutput.ReadToEnd();
throw new SerialException(line.Substring(1), trace);
}
return line;
}
private void WriteLine(string format, params object[] args)
{
process.StandardInput.WriteLine(format, args);
process.StandardInput.Flush();
}
private void WriteHex(byte[] data)
{
var sb = new StringBuilder();
sb.Append(">");
foreach (var b in data) sb.Append(b.ToString("X2"));
WriteLine(sb.ToString());
}
private byte[] ParseHex(string text)
{
Tools.Assert(text.StartsWith("<"), "First char < expected for {0}:{1}", text.Length, text);
Tools.Assert(text.Length % 2 == 1, "Odd length expected for {0}:{1}", text.Length, text);
var bytes = new byte[text.Length / 2];
for (var i = 0; i < bytes.Length; i++)
{
var b2 = text.Substring(1 + i * 2, 2);
bytes[i] = Convert.ToByte(b2, 16);
}
return bytes;
}
[Conditional("DEBUG")]
private void EnableStandardError(ProcessStartInfo psi)
{
psi.RedirectStandardError = true;
}
[Conditional("DEBUG")]
private void ForwardStandardError(StreamReader reader)
{
Task.Factory.StartNew(() =>
{
var line = reader.ReadLine();
while (line != null)
{
Stdio.Trace(line);
line = reader.ReadLine();
}
});
}
}
}