Skip to content

Instantly share code, notes, and snippets.

@chrisgate
Created December 18, 2019 15:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrisgate/451b597e8d7f6dc5dff51b0c6d641c62 to your computer and use it in GitHub Desktop.
Save chrisgate/451b597e8d7f6dc5dff51b0c6d641c62 to your computer and use it in GitHub Desktop.
public class TslReaderManager
: ReactiveObject, IReaderManager
{
private readonly IAsciiTransportsManager transportsManager;
private readonly List<AsciiReader> readers;
public TslReaderManager(IAsciiTransportsManager transportsManager)
{
this.Readers = this.readers = new List<AsciiReader>();
this.transportsManager = transportsManager;
//this.transportsManager.TransportChanged += TransportsManager_TransportChanged;
Observable.FromEventPattern<TransportStateChangedEventArgs>
(h => this.transportsManager.TransportChanged += h,
h => this.transportsManager.TransportChanged -= h)
.DistinctUntilChanged()
.Select(val => val.EventArgs)
.Subscribe(TransportsManager_TransportChanged);
this.WhenAnyValue(x => x.ActiveReader)
.DistinctUntilChanged()
.Subscribe((value) =>
{
if (this.ActiveReader != value)
{
if (this.ActiveReader != null)
{
this.ActiveReaderState = ReaderStates.Disconnecting;
this.ActiveReaderState = ReaderStates.Disconnected;
}
this.ActiveReaderState = ReaderStates.Connecting;
this.ActiveReaderState = ReaderStates.Connected;
}
//if (x != null)
//{
// this.ActiveReaderState = ReaderStates.Disconnecting;
// this.ActiveReaderState = ReaderStates.Disconnected;
//}
//this.ActiveReader = x;
//this.RaisePropertyChanged("ActiveReader");
//this.ActiveReaderState = ReaderStates.Connecting;
//this.ActiveReaderState = ReaderStates.Connected;
});
this.WhenAnyValue(x => x.ActiveReaderState)
// .Where(x => Enum.IsDefined(typeof(ReaderStates), x))
.DistinctUntilChanged()
.Subscribe((value) =>
{
if (this.ActiveReaderState != value)
{
if (this.ActiveReader != null)
{
this.ActiveReaderChanged?.Invoke(this, new ReaderEventArgs(this.ActiveReader, value));
}
}
});
}
/// <summary>
/// Raised when an <see cref="IReader"/> state changes;
/// </summary>
public event EventHandler<ReaderEventArgs> ReaderChanged;
/// <summary>
/// Raised when the <see cref="ActiveReader"/> changes
/// </summary>
public event EventHandler<ReaderEventArgs> ActiveReaderChanged;
/// <summary>
/// Gets the available <see cref="IReader"/>s
/// </summary>
public IEnumerable<IReader> Readers { get; private set; }
#region ActiveReader
/// <summary>
/// Gets the state of the <see cref="ActiveReader"/>
/// </summary>
public ReaderStates ActiveReaderState
{
get => this.activeReaderState;
private set => this.RaiseAndSetIfChanged(ref this.activeReaderState, value);
//private set
//{
// if (this.activeReaderState !=value)
// {
// this.activeReaderState = value;
// if (this.activeReader != null)
// {
// this.ActiveReaderChanged?.Invoke(this, new ReaderEventArgs(this.activeReader, this.activeReaderState));
// }
// }
//}
}
/// <summary>
/// Backing field for <see cref="ActiveReaderState"/>
/// </summary>
private ReaderStates activeReaderState = ReaderStates.Disconnected;
/// <summary>
/// Gets or sets the ActiveReader
/// </summary>
public IReader ActiveReader
{
get => this.activeReader;
set => this.RaiseAndSetIfChanged(ref this.activeReader, value);
//set
//{
// if (this.activeReader != value)
// {
// if (this.activeReader != null)
// {
// this.ActiveReaderState = ReaderStates.Disconnecting;
// this.ActiveReaderState = ReaderStates.Disconnected;
// }
// this.activeReader = value;
// this.ActiveReaderState = ReaderStates.Connecting;
// this.ActiveReaderState = ReaderStates.Connected;
// }
//}
}
/// <summary>
/// Backing field for <see cref="ActiveReader"/>
/// </summary>
private IReader activeReader;
#endregion
public async Task DisconnectReaderAsync(IReader reader)
{
if (reader != null)
{
var asciiReader = (reader as AsciiReader);
if (asciiReader != null)
{
await asciiReader.DisconnectAsync();
}
}
}
public void AnnounceReaderChange(IReader reader, ReaderStates state)
{
this.ReaderChanged.Invoke(this, new ReaderEventArgs(reader, state));
}
//private async void TransportsManager_TransportChanged(object sender, TransportStateChangedEventArgs e)
private async void TransportsManager_TransportChanged(TransportStateChangedEventArgs e)
{
// does a reader have this transport?
var readerWithTransport = this.readers.Where(r => r.Transports.Any(t => t.Id == e.Transport.Id)).FirstOrDefault();
if (readerWithTransport == null)
{
if (e.Transport.State == ConnectionState.Connected)
{
await this.IdentifyReaderAsync(e.Transport);
}
}
else
{
ReaderStates state = ReaderStates.Connecting;
switch (e.Transport.State)
{
//case ConnectionState.Connecting:
case ConnectionState.Connected:
await readerWithTransport.RefreshAsync();
state = ReaderStates.Connected;
// if we don't yet have an active reader we do now
if (this.ActiveReader == null)
{
this.ActiveReader = readerWithTransport;
}
break;
case ConnectionState.Lost:
state = ReaderStates.Lost;
if (readerWithTransport == this.ActiveReader)
{
this.ActiveReader = null;
}
break;
case ConnectionState.Disconnecting:
state = ReaderStates.Disconnecting;
if (readerWithTransport == this.ActiveReader)
{
this.ActiveReader = null;
}
break;
case ConnectionState.Disconnected:
state = ReaderStates.Disconnected;
if (readerWithTransport == this.ActiveReader)
{
this.ActiveReader = null;
}
break;
//case ConnectionState.Interrupted:
}
if (state != ReaderStates.Connecting)
{
// TODO: change transport if we can
this.AnnounceReaderChange(readerWithTransport, state);
}
}
}
private async Task IdentifyReaderAsync(IAsciiTransport transport)
{
// We have a connected transport not associated with a reader.
// Lets create a new reader and identify it
var reader = new AsciiReader();
reader.AddTransport(transport);
await reader.RefreshAsync();
// This, now identified, new transport may belong to an existing reader if so merge it
var mergeReader = this.readers.Where(r => r.SerialNumber == reader.SerialNumber).FirstOrDefault();
if (mergeReader == null)
{
if (String.IsNullOrEmpty(reader.SerialNumber))
{
// Unable to identify the Reader via its transport
// This could be because the transport is Bluetooth and Reader is already connected via USB
// To avoid confusing, unnamed Readers in the list disconnect the unknown transport
// Note: A future release may implement a different policy
transport.Disconnect();
return;
}
else
{
// New reader has been identified
this.readers.Add(reader);
}
}
else
{
// merge the transport to the existing reader
reader.RemoveTransport(transport);
mergeReader.AddTransport(transport);
reader.Dispose();
reader = mergeReader;
// Transports have changed on the Reader so ensure the appropriate transport is in use
await reader.RefreshAsync();
}
this.AnnounceReaderChange(reader, ReaderStates.Connected);
// if we don't yet have an active reader we do now
if (this.ActiveReader == null)
{
this.ActiveReader = reader;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment