Add project files.

This commit is contained in:
Daniel Clark
2022-11-01 15:26:08 +00:00
parent daa7b59f22
commit 7e4f880821
408 changed files with 16863 additions and 0 deletions
@@ -0,0 +1,22 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
namespace TheXamlGuy.Framework.Serial;
public static class IHostBuilderExtensions
{
public static IHostBuilder ConfigureSerial<TConfiguration, TSerialReader, TContent>(this IHostBuilder hostBuilder, Action<HostBuilderContext> configureDelegate) where TSerialReader : SerialReader<TContent> where TConfiguration : ISerialConfiguration, new()
{
hostBuilder.ConfigureServices((hostBuilderContext, serviceCollection) =>
{
configureDelegate.Invoke(hostBuilderContext);
serviceCollection.TryAddSingleton<ISerialFactory, SerialFactory>();
serviceCollection.AddSingleton(provider => provider.GetService<ISerialFactory>()!.Create<TSerialReader, TContent>(provider.GetService<IOptionsMonitor<TConfiguration>>()!.CurrentValue));
});
return hostBuilder;
}
}
+8
View File
@@ -0,0 +1,8 @@
namespace TheXamlGuy.Framework.Serial;
public interface ISerialConfiguration
{
public string PortName { get; set; }
public int BaudRate { get; set; }
}
+10
View File
@@ -0,0 +1,10 @@
namespace TheXamlGuy.Framework.Serial;
public interface ISerialConnection
{
bool IsOpen { get; }
void Close();
bool Open();
}
@@ -0,0 +1,6 @@
namespace TheXamlGuy.Framework.Serial;
public interface ISerialConnectionStreamer
{
Stream Stream { get; }
}
+11
View File
@@ -0,0 +1,11 @@
namespace TheXamlGuy.Framework.Serial;
public interface ISerialContext
{
void Open();
}
public interface ISerialContext<TSerialReader, TContent> : ISerialContext where TSerialReader : SerialReader<TContent>
{
}
+6
View File
@@ -0,0 +1,6 @@
namespace TheXamlGuy.Framework.Serial;
public interface ISerialFactory
{
ISerialContext<TSerialReader, TContent> Create<TSerialReader, TContent>(ISerialConfiguration configuration) where TSerialReader : SerialReader<TContent>;
}
+6
View File
@@ -0,0 +1,6 @@
namespace TheXamlGuy.Framework.Serial;
public interface ISerialResponse
{
ISerialContext Context { get; }
}
+6
View File
@@ -0,0 +1,6 @@
namespace TheXamlGuy.Framework.Serial;
public interface ISerialStreamer
{
Stream Create();
}
+6
View File
@@ -0,0 +1,6 @@
namespace TheXamlGuy.Framework.Serial;
public interface ISerialWriter
{
void Write(byte[] buffer, int offset, int count);
}
+16
View File
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="7.0.0-rc.2.22472.3" />
<PackageReference Include="Microsoft.Extensions.Options" Version="7.0.0-rc.2.22472.3" />
<PackageReference Include="System.IO.Pipelines" Version="7.0.0-rc.2.22472.3" />
<PackageReference Include="System.IO.Ports" Version="7.0.0-rc.2.22472.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Core\Core.csproj" />
</ItemGroup>
</Project>
+11
View File
@@ -0,0 +1,11 @@
using System.Diagnostics.CodeAnalysis;
namespace TheXamlGuy.Framework.Serial;
public class SerialConfiguration : ISerialConfiguration
{
[NotNull]
public string? PortName { get; set; }
public int BaudRate { get; set; }
}
+55
View File
@@ -0,0 +1,55 @@
using System.IO.Ports;
namespace TheXamlGuy.Framework.Serial;
public class SerialConnection : ISerialConnection
{
private readonly SerialPort serialPort;
public SerialConnection(SerialPort serialPort)
{
this.serialPort = serialPort;
}
public bool IsOpen { get; private set; }
public void Close()
{
if (IsOpen)
{
try
{
serialPort.Close();
}
catch
{
}
IsOpen = serialPort.IsOpen;
}
}
public bool Open()
{
if (!IsOpen)
{
try
{
serialPort.Open();
serialPort.DiscardInBuffer();
serialPort.DiscardOutBuffer();
}
catch
{
}
IsOpen = serialPort.IsOpen;
}
return IsOpen;
}
}
@@ -0,0 +1,13 @@
using System.IO.Ports;
namespace TheXamlGuy.Framework.Serial;
public class SerialConnectionStreamer : ISerialConnectionStreamer
{
public SerialConnectionStreamer(SerialPort serial)
{
Stream = serial.BaseStream;
}
public Stream Stream { get; }
}
+35
View File
@@ -0,0 +1,35 @@
using TheXamlGuy.Framework.Core;
namespace TheXamlGuy.Framework.Serial;
public class SerialContext<TSerialReader, TContent> : ISerialContext<TSerialReader, TContent> where TSerialReader : SerialReader<TContent>
{
private readonly ISerialConnection connection;
private readonly IEventAggregator eventAggregator;
private readonly ISerialStreamer serialStreamer;
public SerialContext(IEventAggregator eventAggregator,
ISerialConnection connection,
ISerialStreamer serialStreamer)
{
this.eventAggregator = eventAggregator;
this.connection = connection;
this.serialStreamer = serialStreamer;
}
public async void Open()
{
if (connection.Open())
{
Stream stream = serialStreamer.Create();
if ((TSerialReader?)Activator.CreateInstance(typeof(TSerialReader), new object[] { stream }) is TSerialReader reader)
{
await foreach (TContent content in reader.ReadAsync())
{
eventAggregator.Publish(SerialResponse.Create(this, content));
}
}
}
}
}
+36
View File
@@ -0,0 +1,36 @@
using System.IO.Ports;
using TheXamlGuy.Framework.Core;
namespace TheXamlGuy.Framework.Serial;
public class SerialFactory : ISerialFactory
{
private readonly IServiceFactory factory;
private readonly Dictionary<ISerialConfiguration, ISerialContext> cache = new();
public SerialFactory(IServiceFactory factory)
{
this.factory = factory;
}
public ISerialContext<TSerialReader, TContent> Create<TSerialReader, TContent>(ISerialConfiguration configuration) where TSerialReader : SerialReader<TContent>
{
if (cache.TryGetValue(configuration, out ISerialContext? context))
{
return (ISerialContext<TSerialReader, TContent>)context;
}
SerialPort serialPort = new(configuration.PortName, configuration.BaudRate)
{
DtrEnable = true
};
SerialConnection connection = new(serialPort);
SerialStreamer streamer = new(serialPort);
context = factory.Create<SerialContext<TSerialReader, TContent>>(connection, streamer);
cache.Add(configuration, context);
return (ISerialContext<TSerialReader, TContent>)context;
}
}
+50
View File
@@ -0,0 +1,50 @@
using System.Buffers;
using System.IO.Pipelines;
using System.Text;
namespace TheXamlGuy.Framework.Serial;
public class SerialLineReader : SerialReader<string>
{
private readonly PipeReader reader;
public SerialLineReader(Stream stream) : base(stream)
{
reader = PipeReader.Create(stream);
}
public override async IAsyncEnumerable<string> ReadAsync()
{
while (true)
{
ReadResult result = await reader.ReadAsync();
ReadOnlySequence<byte> buffer = result.Buffer;
while (TryReadLine(ref buffer, out ReadOnlySequence<byte> line))
{
yield return EncodingExtensions.GetString(Encoding.UTF8, line);
}
reader.AdvanceTo(buffer.Start, buffer.End);
if (result.IsCompleted)
{
break;
}
}
}
private bool TryReadLine(ref ReadOnlySequence<byte> buffer, out ReadOnlySequence<byte> line)
{
SequencePosition? position = buffer.PositionOf((byte)'\n');
if (position == null)
{
line = default;
return false;
}
line = buffer.Slice(0, position.Value);
buffer = buffer.Slice(buffer.GetPosition(1, position.Value));
return true;
}
}
+13
View File
@@ -0,0 +1,13 @@
namespace TheXamlGuy.Framework.Serial;
public abstract class SerialReader<TContent>
{
public SerialReader(Stream stream)
{
Stream = stream;
}
public Stream Stream { get; }
public abstract IAsyncEnumerable<TContent> ReadAsync();
}
+9
View File
@@ -0,0 +1,9 @@
using System.Buffers;
using TheXamlGuy.Framework.Core;
namespace TheXamlGuy.Framework.Serial;
public abstract class SerialReaderHandler<TRead> : IMediatorAsyncHandler<TRead, ReadOnlySequence<byte>> where TRead : class
{
public abstract Task<TRead> Handle(ReadOnlySequence<byte> request, CancellationToken cancellationToken = default);
}
+22
View File
@@ -0,0 +1,22 @@
namespace TheXamlGuy.Framework.Serial;
public record SerialResponse
{
public static SerialResponse<TContent> Create<TContent>(ISerialContext context, TContent content)
{
return new SerialResponse<TContent>(context, content);
}
}
public record SerialResponse<TContent> : ISerialResponse
{
public SerialResponse(ISerialContext context, TContent content)
{
Context = context;
Content = content;
}
public ISerialContext Context { get; }
public TContent Content { get; }
}
+18
View File
@@ -0,0 +1,18 @@
using System.IO.Ports;
namespace TheXamlGuy.Framework.Serial;
public class SerialStreamer : ISerialStreamer
{
private readonly SerialPort serialPort;
public SerialStreamer(SerialPort serialPort)
{
this.serialPort = serialPort;
}
public Stream Create()
{
return serialPort.BaseStream;
}
}