Skip to content

Commit

Permalink
updates
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisPulman committed May 1, 2021
1 parent 343fb91 commit 6acfd0d
Show file tree
Hide file tree
Showing 9 changed files with 235 additions and 122 deletions.
2 changes: 1 addition & 1 deletion CodeMaid.config
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<value>2</value>
</setting>
<setting name="Cleaning_AutoCleanupOnFileSave" serializeAs="String">
<value>True</value>
<value>False</value>
</setting>
<setting name="Reorganizing_MemberTypeStructs" serializeAs="String">
<value>Structs||9||Structs</value>
Expand Down
17 changes: 9 additions & 8 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>

<ItemGroup>
<!--<Compile Update="**\*.cs" DependentUpon="I%(Filename).cs" />-->
<PackageReference Include="Nerdbank.GitVersioning" Version="3.*" PrivateAssets="all" />
<!--<PackageReference Include="stylecop.analyzers" Version="1.*" PrivateAssets="all" />-->
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="5.*" PrivateAssets="all" />
<PackageReference Include="Roslynator.Analyzers" Version="3.*" PrivateAssets="All" />
<AdditionalFiles Include="$(MSBuildThisFileDirectory)stylecop.json" Link="stylecop.json" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)'=='Debug'">
<!--<Compile Update="**\*.cs" DependentUpon="I%(Filename).cs" />-->
<PackageReference Include="Nerdbank.GitVersioning" Version="3.*" PrivateAssets="all" />
<PackageReference Include="stylecop.analyzers" Version="1.*" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="5.*" PrivateAssets="all" />
<PackageReference Include="Roslynator.Analyzers" Version="3.*" PrivateAssets="All" />
<AdditionalFiles Include="$(MSBuildThisFileDirectory)stylecop.json" Link="stylecop.json" />
</ItemGroup>

</Project>
2 changes: 2 additions & 0 deletions SerialPortRx.sln
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SerialPortRx", "SerialPortR
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ConfigFiles", "ConfigFiles", "{D4EE9FBC-EA31-4BF1-8F9D-A8D1E0B9500C}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
appveyor.yml = appveyor.yml
Directory.Build.props = Directory.Build.props
README.md = README.md
stylecop.json = stylecop.json
Version.json = Version.json
EndProjectSection
EndProject
Expand Down
19 changes: 13 additions & 6 deletions SerialPortRx/IDisposableExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
using System.Collections.Generic;
// <copyright file="IDisposableExtensions.cs" company="Chris Pulman">
// Copyright (c) Chris Pulman. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>

using System;
using System.Collections.Generic;

namespace CP.IO.Ports
{
using System;

/// <summary>
/// IDisposable Extensions
/// IDisposable Extensions.
/// </summary>
public static class IDisposableExtensions

{
/// <summary>
/// Add disposable(self) to CompositeDisposable(or other ICollection)
/// Add disposable(self) to CompositeDisposable(or other ICollection).
/// </summary>
/// <typeparam name="T">The type.</typeparam>
/// <param name="disposable">The disposable.</param>
/// <param name="container">The container.</param>
/// <returns>Type of T.</returns>
public static T AddTo<T>(this T disposable, ICollection<IDisposable> container)
where T : IDisposable
{
Expand Down
24 changes: 16 additions & 8 deletions SerialPortRx/ISerialPortRx.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
namespace CP.IO.Ports
{
using System;
using System.IO.Ports;
using System.Threading.Tasks;
// <copyright file="ISerialPortRx.cs" company="Chris Pulman">
// Copyright (c) Chris Pulman. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>

using System;
using System.IO.Ports;
using System.Threading.Tasks;

namespace CP.IO.Ports
{
/// <summary>
/// Serial Port Rx interface
/// Serial Port Rx interface.
/// </summary>
public interface ISerialPortRx : IDisposable
{
Expand Down Expand Up @@ -46,9 +51,11 @@ public interface ISerialPortRx : IDisposable
bool IsDisposed { get; }

/// <summary>
/// Gets the is open.
/// Gets a value indicating whether gets the is open.
/// </summary>
/// <value>The is open.</value>
/// <value>
/// The is open.
/// </value>
bool IsOpen { get; }

/// <summary>
Expand Down Expand Up @@ -95,6 +102,7 @@ public interface ISerialPortRx : IDisposable
/// <summary>
/// Opens this instance.
/// </summary>
/// <returns>A Task.</returns>
Task Open();

/// <summary>
Expand Down
7 changes: 6 additions & 1 deletion SerialPortRx/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
using System.Reflection;
// <copyright file="AssemblyInfo.cs" company="Chris Pulman">
// Copyright (c) Chris Pulman. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>

using System.Reflection;
using System.Runtime.InteropServices;

[assembly: ComVisible(false)]
Expand Down
150 changes: 107 additions & 43 deletions SerialPortRx/SerialPortRx.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
namespace CP.IO.Ports
// <copyright file="SerialPortRx.cs" company="Chris Pulman">
// Copyright (c) Chris Pulman. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO.Ports;
using System.Linq;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace CP.IO.Ports
{
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO.Ports;
using System.Linq;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

/// <summary>
/// Serial Port Rx
/// Serial Port Rx.
/// </summary>
/// <seealso cref="CP.IO.Ports.ISerialPortRx"/>
public class SerialPortRx : ISerialPortRx
Expand Down Expand Up @@ -104,10 +109,13 @@ public SerialPortRx(string port, int baudRate)
}

/// <summary>
/// Initializes a new instance of the <see cref="SerialPortRx"/> class.
/// Initializes a new instance of the <see cref="SerialPortRx" /> class.
/// </summary>
/// <param name="port">The port.</param>
public SerialPortRx(string port) { PortName = port; }
public SerialPortRx(string port)
{
PortName = port;
}

/// <summary>
/// Initializes a new instance of the <see cref="SerialPortRx"/> class.
Expand Down Expand Up @@ -173,7 +181,7 @@ public SerialPortRx()
public bool IsDisposed { get; private set; } = false;

/// <summary>
/// Gets the is open.
/// Gets a value indicating whether gets the is open.
/// </summary>
/// <value>The is open.</value>
[Browsable(true)]
Expand Down Expand Up @@ -231,13 +239,17 @@ public SerialPortRx()
[MonitoringDescription("WriteTimeout")]
public int WriteTimeout { get; set; } = -1;

private IObservable<Unit> Connect => Observable.Create<Unit>(obs => {
private IObservable<Unit> Connect => Observable.Create<Unit>(obs =>
{
var dis = new CompositeDisposable();

// Check that the port exists
if (!SerialPort.GetPortNames().Any(name => name.Equals(PortName))) {
if (!SerialPort.GetPortNames().Any(name => name.Equals(PortName)))
{
obs.OnError(new Exception($"Serial Port {PortName} does not exist"));
} else {
}
else
{
// Setup Com Port
var port = new SerialPort(PortName, BaudRate, Parity, DataBits, StopBits);
dis.Add(port);
Expand All @@ -246,20 +258,26 @@ public SerialPortRx()
port.ReadTimeout = ReadTimeout;
port.WriteTimeout = WriteTimeout;
port.Encoding = Encoding;
try {
try
{
port.Open();
} catch (Exception ex) {
}
catch (Exception ex)
{
errors.OnNext(ex);
obs.OnCompleted();
}

isOpen.OnNext(port.IsOpen);
IsOpen = port.IsOpen;

// Clear any existing buffers
if (IsOpen) {
if (IsOpen)
{
port.DiscardInBuffer();
port.DiscardOutBuffer();
}

Thread.Sleep(100);

// Subscribe to port errors
Expand All @@ -273,28 +291,58 @@ from data in port.ReadExisting()
dis.Add(dataStream.Subscribe(dataReceived.OnNext, obs.OnError));

// setup Write streams
dis.Add(writeString.Subscribe(x => {
try { port?.Write(x); } catch (Exception ex) {
dis.Add(writeString.Subscribe(
x =>
{
try
{
port?.Write(x);
}
catch (Exception ex)
{
obs.OnError(ex);
}
}, obs.OnError));
dis.Add(writeStringLine.Subscribe(x => {
try { port?.WriteLine(x); } catch (Exception ex) {
dis.Add(writeStringLine.Subscribe(
x =>
{
try
{
port?.WriteLine(x);
}
catch (Exception ex)
{
obs.OnError(ex);
}
}, obs.OnError));
dis.Add(writeByte.Subscribe(x => {
try { port?.Write(x.Item1, x.Item2, x.Item3); } catch (Exception ex) {
dis.Add(writeByte.Subscribe(
x =>
{
try
{
port?.Write(x.Item1, x.Item2, x.Item3);
}
catch (Exception ex)
{
obs.OnError(ex);
}
}, obs.OnError));
dis.Add(writeChar.Subscribe(x => {
try { port?.Write(x.Item1, x.Item2, x.Item3); } catch (Exception ex) {
dis.Add(writeChar.Subscribe(
x =>
{
try
{
port?.Write(x.Item1, x.Item2, x.Item3);
}
catch (Exception ex)
{
obs.OnError(ex);
}
}, obs.OnError));
}
return Disposable.Create(() => {

return Disposable.Create(() =>
{
IsOpen = false;
isOpen.OnNext(false);
dis.Dispose();
Expand All @@ -306,29 +354,39 @@ from data in port.ReadExisting()
/// </summary>
/// <param name="pollInterval">The poll interval.</param>
/// <param name="pollLimit">The poll limit, once number is reached observable will complete.</param>
/// <returns></returns>
/// <returns>Observable string.</returns>
/// <value>The port names.</value>
public static IObservable<string[]> PortNames(int pollInterval = 500, int pollLimit = 0) => Observable.Create<string[]>(obs => {
public static IObservable<string[]> PortNames(int pollInterval = 500, int pollLimit = 0) => Observable.Create<string[]>(obs =>
{
string[] compare = null;
var numberOfPolls = 0;
return Observable.Interval(TimeSpan.FromMilliseconds(pollInterval)).Subscribe(_ => {
return Observable.Interval(TimeSpan.FromMilliseconds(pollInterval)).Subscribe(_ =>
{
var compareNew = SerialPort.GetPortNames();
if (compareNew.Length == 0) {
if (compareNew.Length == 0)
{
compareNew = new string[] { "NoPorts" };
}

if (compare == null) {
if (compare == null)
{
compare = compareNew;
obs.OnNext(compareNew);
}
if (string.Concat(compare) != string.Concat(compareNew)) {

if (string.Concat(compare) != string.Concat(compareNew))
{
obs.OnNext(compareNew);
compare = compareNew;
}
if (numberOfPolls > pollLimit) {

if (numberOfPolls > pollLimit)
{
obs.OnCompleted();
}
if (pollLimit > 0 && numberOfPolls < pollLimit) {

if (pollLimit > 0 && numberOfPolls < pollLimit)
{
numberOfPolls++;
}
});
Expand All @@ -349,11 +407,15 @@ public void Close()
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

/// <summary>
/// Opens this instance.
/// </summary>
/// <returns>
/// A Task.
/// </returns>
public Task Open()
{
return disposablePort?.Count == 0 ? Task.Run(() => Connect.Subscribe().AddTo(disposablePort)) : Task.CompletedTask;
Expand Down Expand Up @@ -426,8 +488,10 @@ public void WriteLine(string text)
/// </param>
protected virtual void Dispose(bool disposing)
{
if (!IsDisposed) {
if (disposing) {
if (!IsDisposed)
{
if (disposing)
{
disposablePort?.Dispose();
}

Expand Down
Loading

0 comments on commit 6acfd0d

Please sign in to comment.