Innovenergy_trunk/csharp/Lib/Protocols/Modbus/Connections/RemoteSerialConnection.cs

113 lines
3.0 KiB
C#

using System.Diagnostics.CodeAnalysis;
using System.IO.Ports;
using System.Reactive.Linq;
using CliWrap;
using InnovEnergy.Lib.Utils;
namespace InnovEnergy.Lib.Protocols.Modbus.Connections;
public class RemoteSerialConnection : ModbusConnection
{
private readonly Command _Command;
private ObservableProcess? _ObservableProcess;
private Func<Int32, Task<IReadOnlyList<Byte>>>? _Read;
public RemoteSerialConnection(SshHost host,
String tty,
Int32 baudRate,
Parity parity,
Int32 stopBits,
Int32 dataBits)
{
tty = tty.EnsureStartsWith("/dev/");
var configure = ConfigureTty(tty, baudRate, parity, stopBits, dataBits);
// https://unix.stackexchange.com/questions/19604/all-about-ssh-proxycommand
var call = $"{configure}; " +
$"exec 3<>{tty}; " +
$"cat <&3 & cat >&3; " +
$"kill $!";
_Command = host
.Command
.AppendArgument(call);
_Command.WriteLine();
}
[SuppressMessage("ReSharper", "StringLiteralTypo")]
private static String ConfigureTty(String tty, Int32 baudRate, Parity parity, Int32 stopBits, Int32 dataBits)
{
var oParity = parity switch
{
Parity.Even => "parenb -parodd",
Parity.Odd => "parenb parodd",
Parity.None => "-parenb",
_ => throw new NotImplementedException()
};
var oStopBits = stopBits switch
{
1 => "-cstopb",
2 => "cstopb",
_ => throw new NotImplementedException()
};
var oDataBits = "cs" + dataBits;
return $"stty -F {tty} {baudRate} {oDataBits} {oStopBits} {oParity}";
}
public override IReadOnlyList<Byte> Receive(UInt16 bytesToRead)
{
Open();
return _Read!(bytesToRead).Result;
}
public override void Transmit(IEnumerable<Byte> bytes)
{
Open();
try
{
_ObservableProcess!.StdIn.OnNext(bytes.ToArray());
}
catch
{
Close();
throw;
}
}
public override void Open()
{
if (_ObservableProcess is not null)
return;
_ObservableProcess = new ObservableProcess(_Command);
_ObservableProcess.Start();
_Read = _ObservableProcess
.StdOut
.Select(b => b.ToArray())
.SelectMany(t => t)
.PushToPull();
}
public override void Close()
{
throw new NotImplementedException();
// if (_ObservableProcess is null)
// return;
// https://stackoverflow.com/questions/6960520/when-to-dispose-cancellationtokensource
}
}