Initial commit
This commit is contained in:
221
SerialCom/BatteryController.cs
Normal file
221
SerialCom/BatteryController.cs
Normal file
@@ -0,0 +1,221 @@
|
||||
using System.IO.Ports;
|
||||
using MoniteurBaie.DataModels;
|
||||
using MoniteurBaie.Utils;
|
||||
|
||||
namespace MoniteurBaie.SerialCom;
|
||||
|
||||
public sealed class BatteryController : IBatteryController
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly SerialPort _serialPort;
|
||||
private readonly bool _closePort;
|
||||
|
||||
private readonly List<IObserver<BatteryControllerPacket>> _packetObservers = new();
|
||||
private readonly BlockingListener<string> _commandListener = new();
|
||||
|
||||
public BatteryController(ILogger logger, Action<SerialPort> configure)
|
||||
{
|
||||
_logger = logger;
|
||||
_serialPort = new SerialPort();
|
||||
configure(_serialPort);
|
||||
_closePort = true;
|
||||
}
|
||||
|
||||
public BatteryController(ILogger logger, SerialPort serialPort, bool closePort = false)
|
||||
{
|
||||
_logger = logger;
|
||||
_serialPort = serialPort;
|
||||
_closePort = closePort;
|
||||
}
|
||||
|
||||
public Task Open(CancellationToken cancellationToken)
|
||||
{
|
||||
_serialPort.Open();
|
||||
|
||||
var readThread = new Thread(Test)
|
||||
{
|
||||
IsBackground = true
|
||||
};
|
||||
readThread.Start();
|
||||
|
||||
// var writeThread = new Thread(DoWrite)
|
||||
// {
|
||||
// IsBackground = true
|
||||
// };
|
||||
// writeThread.Start();
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public IDisposable AddSerialObserver(IObserver<BatteryControllerPacket> observer)
|
||||
{
|
||||
_packetObservers.Add(observer);
|
||||
return new Disposer(() => _packetObservers.Remove(observer));
|
||||
}
|
||||
|
||||
public Task SendCommand(string command, CancellationToken cancellationToken)
|
||||
{
|
||||
_commandListener.Push(command);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void Test()
|
||||
{
|
||||
try
|
||||
{
|
||||
while (_serialPort.IsOpen)
|
||||
{
|
||||
var b = _serialPort.ReadByte();
|
||||
Console.WriteLine(b);
|
||||
}
|
||||
}
|
||||
catch (ObjectDisposedException ex)
|
||||
{
|
||||
_logger.LogError(ex, "The serial connection has been disposed.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "An exception occurred in the serial read loop.");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void DoRead()
|
||||
{
|
||||
try
|
||||
{
|
||||
while (_serialPort.IsOpen)
|
||||
{
|
||||
string line;
|
||||
try
|
||||
{
|
||||
line = _serialPort.ReadLine();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to read line from serial connection.");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(line))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var packet = new BatteryControllerPacket(line);
|
||||
|
||||
foreach (var observer in _packetObservers)
|
||||
{
|
||||
try
|
||||
{
|
||||
observer.OnNext(packet);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "An exception occurred in a packet handler.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ObjectDisposedException ex)
|
||||
{
|
||||
_logger.LogError(ex, "The serial connection has been disposed.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "An exception occurred in the serial read loop.");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void DoWrite()
|
||||
{
|
||||
try
|
||||
{
|
||||
while (_serialPort.IsOpen)
|
||||
{
|
||||
var line = _commandListener.Next();
|
||||
|
||||
if (string.IsNullOrEmpty(line))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_serialPort.Write(line + "\n");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to send command.");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ObjectDisposedException ex)
|
||||
{
|
||||
_logger.LogError(ex, "The serial connection has been disposed.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "An exception occurred in the serial write loop.");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
#region IObservable
|
||||
|
||||
IDisposable IObservable<BatteryControllerPacket>.Subscribe(IObserver<BatteryControllerPacket> observer)
|
||||
{
|
||||
return AddSerialObserver(observer);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IObserver
|
||||
|
||||
void IObserver<string>.OnCompleted()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void IObserver<string>.OnError(Exception error)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void IObserver<string>.OnNext(string value)
|
||||
{
|
||||
SendCommand(value, default);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable
|
||||
|
||||
private bool disposedValue;
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (_closePort)
|
||||
{
|
||||
_serialPort.Close();
|
||||
}
|
||||
}
|
||||
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user