Multiprocotol Terminalprogram (BAT)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
MultiTerm/MultiTerm.Protocols/Serial/SerialProtocol.cs

133 lines
4.4 KiB

using Common.Logging;
using CommunityToolkit.Mvvm.Messaging;
using MultiTerm.Protocols.Model;
using MultiTerm.Protocols.Types;
using RJCP.IO.Ports;
using System.Text;
namespace MultiTerm.Protocols.Serial;
public class SerialProtocol : CommunicationProtocol
{
public override ProtocolType ProtocolType => ProtocolType.Serial;
public override string InstanceIdentifier { get; protected set; } = string.Empty;
public override string LongInstanceIdentifier { get; protected set; } = string.Empty;
private ISerialProtocolSettings? serialSettings;
private SerialPortStream serialPort = new();
public SerialProtocol(ILogger logger, IMessenger messenger) : base(logger, messenger) { }
protected override bool InternalConnect(IProtocolSettings settings)
{
// check if settings are of correct type
if (settings is not ISerialProtocolSettings serialProtocolSettings)
{
this.serialSettings = null;
throw new ArgumentException($"Cannot connect due to wrong type of Protocol Settings. " +
$"Check parameter {nameof(settings)}' of '{nameof(InternalConnect)}()' in {nameof(SerialProtocol)}.");
}
// store locally
this.serialSettings = serialProtocolSettings;
// update identifier
this.InstanceIdentifier = this.serialSettings.PortName;
this.LongInstanceIdentifier = this.serialSettings.PortName;
// create new serial port
this.serialPort = new()
{
// apply user settings, where needed converters are used
PortName = this.serialSettings.PortName,
BaudRate = this.serialSettings.BaudRate,
DataBits = this.serialSettings.DataBits,
Parity = new ParityLibraryEquivalentConverter().ConvertToLibraryType(this.serialSettings.Parity),
StopBits = new StopBitsLibraryEquivalentConverter().ConvertToLibraryType(this.serialSettings.StopBits),
Handshake = new HandshakeLibraryEquivalentConverter().ConvertToLibraryType(this.serialSettings.Handshake),
// define static settings
Encoding = Encoding.ASCII,
ReadTimeout = 500,
WriteTimeout = 500
};
// try opening serial port
try
{
this.serialPort.Open();
}
catch (Exception ex)
{
this.logger.LogException(ex, $"'{nameof(InternalConnect)}()'Opening serial port failed:", nameof(SerialProtocol));
return false;
}
return true;
}
protected override void InternalDisconnect()
{
this.serialPort.Close();
this.serialSettings = null;
}
protected override void InternalRead(CancellationToken ct)
{
while(ct.IsCancellationRequested == false)
{
int readByte = -1;
// try reading
try
{
// reads character based on configured encoding (here ASCII)
readByte = this.serialPort.ReadByte();
}
catch (IOException ex) // thrown when a device disconnected
{
this.logger.LogException(ex, $"Exception while reading data in {nameof(InternalRead)}", nameof(SerialProtocol));
this.OnUnintentionallyDisconnected(); // report disconnect
break; // break loop
}
if (readByte != -1) // -1 = end of stream
{
// report new data with event
this.OnReceivedData(new ExtendedByte((byte)readByte));
}
}
}
protected override bool InternalSendBytes(byte[] bytes)
{
foreach (byte b in bytes)
{
try
{
this.serialPort.WriteByte(b);
}
// When the Serial Port is closed and InvalidOperationException is thrown => report error
catch(InvalidOperationException)
{
this.OnUnintentionallyDisconnected();
return false;
}
// any other exception => report error
catch
{
return false;
}
// report that data was be sent
this.OnSentData(new ExtendedByte(b));
}
return true; // success
}
public static IEnumerable<string> GetPortNames()
{
return SerialPortStream.GetPortNames();
}
}