fixed value notifications

added observable extensions
This commit is contained in:
Federico Barresi
2018-11-22 14:03:28 +01:00
parent a3fd30a457
commit dcac7002f9
6 changed files with 131 additions and 28 deletions

View File

@@ -1,7 +1,16 @@
using System; using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reactive; using System.Reactive;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
using System.Reactive.Linq; using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Sharp7.Rx.Resources;
namespace Sharp7.Rx.Extensions namespace Sharp7.Rx.Extensions
{ {
@@ -20,5 +29,86 @@ namespace Sharp7.Rx.Extensions
.Select(x => Observable.FromAsync(async () => await selector(x))) .Select(x => Observable.FromAsync(async () => await selector(x)))
.Concat(); .Concat();
} }
public static IObservable<T> LogAndRetry<T>(this IObservable<T> source, ILogger logger, string message)
{
return source
.Do(
_ => { },
ex => logger?.LogError(ex, message))
.Retry();
}
public static IObservable<T> RetryAfterDelay<T>(
this IObservable<T> source,
TimeSpan retryDelay,
int retryCount = -1,
IScheduler scheduler = null)
{
return RedoAfterDelay(source, retryDelay, retryCount, scheduler, Observable.Retry, Observable.Retry);
}
public static IObservable<T> RepeatAfterDelay<T>(
this IObservable<T> source,
TimeSpan retryDelay,
int repeatCount = -1,
IScheduler scheduler = null)
{
return RedoAfterDelay(source, retryDelay, repeatCount, scheduler, Observable.Repeat, Observable.Repeat);
}
public static IObservable<T> LogAndRetryAfterDelay<T>(
this IObservable<T> source,
ILogger logger,
TimeSpan retryDelay,
string message,
int retryCount = -1,
IScheduler scheduler = null)
{
var sourceLogged =
source
.Do(
_ => { },
ex => logger?.LogError(ex, message));
return RetryAfterDelay(sourceLogged, retryDelay, retryCount, scheduler);
}
private static IObservable<T> RedoAfterDelay<T>(IObservable<T> source, TimeSpan retryDelay, int retryCount, IScheduler scheduler, Func<IObservable<T>, IObservable<T>> reDo,
Func<IObservable<T>, int, IObservable<T>> reDoCount)
{
scheduler = scheduler ?? TaskPoolScheduler.Default;
var attempt = 0;
var deferedObs = Observable.Defer(() => ((++attempt == 1) ? source : source.DelaySubscription(retryDelay, scheduler)));
return retryCount > 0 ? reDoCount(deferedObs, retryCount) : reDo(deferedObs);
}
public static IObservable<T> DisposeMany<T>(this IObservable<T> source)
{
return Observable.Create<T>(obs =>
{
var serialDisposable = new SerialDisposable();
var subscription =
source.Subscribe(
item =>
{
serialDisposable.Disposable = item as IDisposable;
obs.OnNext(item);
},
obs.OnError,
obs.OnCompleted);
return new CompositeDisposable(serialDisposable, subscription);
});
}
public static IObservable<Unit> SelectMany<T>(this IObservable<T> source, Func<T, Task> selector)
{
return source.SelectMany(async item =>
{
await selector(item);
return Unit.Default;
});
}
} }
} }

View File

@@ -9,5 +9,6 @@ namespace Sharp7.Rx.Interfaces
IObservable<TValue> CreateNotification<TValue>(string variableName, TransmissionMode transmissionMode, TimeSpan cycleSpan); IObservable<TValue> CreateNotification<TValue>(string variableName, TransmissionMode transmissionMode, TimeSpan cycleSpan);
Task SetValue<TValue>(string variableName, TValue value); Task SetValue<TValue>(string variableName, TValue value);
Task<TValue> GetValue<TValue>(string variableName); Task<TValue> GetValue<TValue>(string variableName);
IObservable<ConnectionState> ConnectionState { get; }
} }
} }

View File

@@ -1,6 +1,7 @@
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Sharp7.Rx.Enums; using Sharp7.Rx.Enums;
namespace Sharp7.Rx.Interfaces namespace Sharp7.Rx.Interfaces
@@ -18,5 +19,6 @@ namespace Sharp7.Rx.Interfaces
Task<bool> WriteBit(Operand operand, ushort startByteAddress, byte bitAdress, bool value, ushort dbNr, CancellationToken token); Task<bool> WriteBit(Operand operand, ushort startByteAddress, byte bitAdress, bool value, ushort dbNr, CancellationToken token);
Task<ushort> WriteBytes(Operand operand, ushort startByteAdress, byte[] data, ushort dBNr, CancellationToken token); Task<ushort> WriteBytes(Operand operand, ushort startByteAdress, byte[] data, ushort dBNr, CancellationToken token);
ILogger Logger { get; }
} }
} }

View File

@@ -13,6 +13,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.1" />
<PackageReference Include="Sharp7" Version="1.0.18" /> <PackageReference Include="Sharp7" Version="1.0.18" />
<PackageReference Include="System.Reactive" Version="4.1.0" /> <PackageReference Include="System.Reactive" Version="4.1.0" />
</ItemGroup> </ItemGroup>

View File

@@ -4,7 +4,9 @@ using System.Reactive.Linq;
using System.Reactive.Subjects; using System.Reactive.Subjects;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Sharp7.Rx.Enums; using Sharp7.Rx.Enums;
using Sharp7.Rx.Extensions;
using Sharp7.Rx.Interfaces; using Sharp7.Rx.Interfaces;
using Sharp7.Rx.Resources; using Sharp7.Rx.Resources;
@@ -18,14 +20,18 @@ namespace Sharp7.Rx
private readonly string ipAddress; private readonly string ipAddress;
private readonly int rackNr; private readonly int rackNr;
private readonly int cpuSlotNr; private readonly int cpuSlotNr;
private readonly int port;
private S7Client sharp7; private S7Client sharp7;
private bool disposed; private bool disposed;
public Sharp7Connector(string ipAddress, int rackNr = 0, int cpuSlotNr = 2) public ILogger Logger { get; set; }
public Sharp7Connector(string ipAddress, int rackNr = 0, int cpuSlotNr = 2, int port = 102)
{ {
this.ipAddress = ipAddress; this.ipAddress = ipAddress;
this.cpuSlotNr = cpuSlotNr; this.cpuSlotNr = cpuSlotNr;
this.port = port;
this.rackNr = rackNr; this.rackNr = rackNr;
ReconnectDelay = TimeSpan.FromSeconds(5); ReconnectDelay = TimeSpan.FromSeconds(5);
@@ -76,21 +82,22 @@ namespace Sharp7.Rx
try try
{ {
sharp7 = new S7Client(); sharp7 = new S7Client();
sharp7.PLCPort = this.port;
var subscription = var subscription =
ConnectionState ConnectionState
.Where(state => state == Enums.ConnectionState.ConnectionLost) .Where(state => state == Enums.ConnectionState.ConnectionLost)
.Take(1) .Take(1)
.SelectMany(_ => Reconnect()) .SelectMany(_ => Reconnect())
// TODO: .RepeatAfterDelay(ReconnectDelay) .RepeatAfterDelay(ReconnectDelay)
// TODO: .LogAndRetry(logger, "Error while reconnecting to S7.") .LogAndRetry(Logger, "Error while reconnecting to S7.")
.Subscribe(); .Subscribe();
disposables.Add(subscription); disposables.Add(subscription);
} }
catch (Exception ex) catch (Exception ex)
{ {
// TODO: Logger?.LogError(ex, StringResources.StrErrorS7DriverCouldNotBeInitialized);
} }
return Task.FromResult(true); return Task.FromResult(true);

View File

@@ -5,7 +5,9 @@ using System.Reactive.Subjects;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Sharp7.Rx.Enums; using Sharp7.Rx.Enums;
using Sharp7.Rx.Extensions;
using Sharp7.Rx.Interfaces; using Sharp7.Rx.Interfaces;
using Sharp7.Rx.Resources; using Sharp7.Rx.Resources;
@@ -247,8 +249,8 @@ namespace Sharp7.Rx
Value = value Value = value
}; };
}) })
// TODO: .RepeatAfterDelay(cycle) .RepeatAfterDelay(cycle)
// TODO: .LogAndRetryAfterDelay(Logger, cycle, StringResources.StrLogErrorReadingDataFromPlc) .LogAndRetryAfterDelay(s7Connector.Logger, cycle, StringResources.StrLogErrorReadingDataFromPlc)
.TakeUntil(disposingSubject) .TakeUntil(disposingSubject)
.Where(union => union.HasValue) .Where(union => union.HasValue)
.Select(union => union.Value); .Select(union => union.Value);