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 data) : EventArgs { public ReadOnlyMemory Data { get; } = data; } public interface ISerialPortTransport : IDisposable { bool IsOpen { get; } event EventHandler? DataReceived; IReadOnlyList GetPortNames(); Task OpenAsync(SerialConnectionOptions options, CancellationToken cancellationToken = default); Task WriteAsync(ReadOnlyMemory 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 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))); } }