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>>? _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 Receive(UInt16 bytesToRead) { Open(); return _Read!(bytesToRead).Result; } public override void Transmit(IEnumerable 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 } }