101 lines
2.6 KiB
C#
101 lines
2.6 KiB
C#
using System.Globalization;
|
|
using System.Text;
|
|
|
|
namespace YMhut.Box.Core.Tools;
|
|
|
|
public enum SerialParityMode
|
|
{
|
|
None,
|
|
Odd,
|
|
Even,
|
|
Mark,
|
|
Space
|
|
}
|
|
|
|
public enum SerialStopBitsMode
|
|
{
|
|
One,
|
|
OnePointFive,
|
|
Two
|
|
}
|
|
|
|
public sealed record SerialConnectionOptions(
|
|
string PortName,
|
|
int BaudRate,
|
|
int DataBits = 8,
|
|
SerialParityMode Parity = SerialParityMode.None,
|
|
SerialStopBitsMode StopBits = SerialStopBitsMode.One);
|
|
|
|
public sealed class SerialDataReceivedEventArgs(ReadOnlyMemory<byte> data) : EventArgs
|
|
{
|
|
public ReadOnlyMemory<byte> Data { get; } = data;
|
|
}
|
|
|
|
public interface ISerialPortTransport : IDisposable
|
|
{
|
|
bool IsOpen { get; }
|
|
|
|
event EventHandler<SerialDataReceivedEventArgs>? DataReceived;
|
|
|
|
IReadOnlyList<string> GetPortNames();
|
|
|
|
Task OpenAsync(SerialConnectionOptions options, CancellationToken cancellationToken = default);
|
|
|
|
Task WriteAsync(ReadOnlyMemory<byte> data, CancellationToken cancellationToken = default);
|
|
|
|
Task CloseAsync(CancellationToken cancellationToken = default);
|
|
}
|
|
|
|
public static class SerialPayloadCodec
|
|
{
|
|
public static byte[] Parse(string value, bool hexadecimal)
|
|
{
|
|
if (!hexadecimal)
|
|
{
|
|
return Encoding.UTF8.GetBytes(value ?? string.Empty);
|
|
}
|
|
|
|
var input = value ?? string.Empty;
|
|
foreach (var character in input)
|
|
{
|
|
if (!char.IsAsciiHexDigit(character) &&
|
|
!char.IsWhiteSpace(character) &&
|
|
character is not (',' or ';' or ':' or '-'))
|
|
{
|
|
throw new FormatException("Hexadecimal input contains an invalid character.");
|
|
}
|
|
}
|
|
|
|
var compact = new string(input.Where(char.IsAsciiHexDigit).ToArray());
|
|
if (compact.Length == 0)
|
|
{
|
|
return [];
|
|
}
|
|
if (compact.Length % 2 != 0)
|
|
{
|
|
throw new FormatException("Hexadecimal input must contain complete byte pairs.");
|
|
}
|
|
|
|
var bytes = new byte[compact.Length / 2];
|
|
for (var index = 0; index < bytes.Length; index++)
|
|
{
|
|
if (!byte.TryParse(compact.AsSpan(index * 2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out bytes[index]))
|
|
{
|
|
throw new FormatException("Hexadecimal input contains an invalid byte.");
|
|
}
|
|
}
|
|
return bytes;
|
|
}
|
|
|
|
public static string Format(ReadOnlySpan<byte> data, bool hexadecimal)
|
|
{
|
|
if (!hexadecimal)
|
|
{
|
|
return Encoding.UTF8.GetString(data);
|
|
}
|
|
|
|
var encoded = Convert.ToHexString(data);
|
|
return string.Join(' ', encoded.Chunk(2).Select(chars => new string(chars)));
|
|
}
|
|
}
|