19 Commits

Author SHA1 Message Date
Felix Weiß
43c7f72ac4 Added auto register reset to default typed value on disconnect 2022-10-21 11:56:58 +02:00
Felix Weiß
2e35ed87af Updated hyperlinks in readme 2022-10-20 10:16:11 +02:00
Felix Weiß
a7f97a72ea Package id change in readme 2022-10-20 10:11:13 +02:00
Felix Weiß
51870166e4 Update publish.yml 2022-10-20 10:04:49 +02:00
Felix Weiß
b43e9bd201 Package id 2022-10-20 10:02:59 +02:00
Felix Weiß
e313dbc3ec Changed package ID 2022-10-20 10:01:53 +02:00
Felix Weiß
bdf9f93f97 Update MewtocolNet.csproj 2022-10-20 09:50:58 +02:00
Felix Weiß
fe816ab78e Update publish.yml 2022-10-20 09:46:08 +02:00
Felix Weiß
48a5977185 Create publish.yml 2022-10-20 09:36:35 +02:00
Felix Weiß
c69f63c191 Update README.md 2022-09-27 10:21:37 +02:00
Felix Weiß
6a2f278dd1 Fixed negative queued msges
- version count up
2022-09-27 10:18:01 +02:00
Felix Weiß
19159ed183 Upcount version 2022-09-27 09:53:02 +02:00
Felix Weiß
635823a66f Made poller delay thread safe
- added property for currentlly queued messages
- added (optional) progress to ReadByteRange
2022-09-27 09:52:35 +02:00
Felix Weiß
c7a6559f97 Added methods to pause/resume the auto polling 2022-09-23 16:38:14 +02:00
Felix Weiß
88a453355c Merge branch 'master' of https://github.com/WOmed/MewtocolNet 2022-09-21 16:24:08 +02:00
Felix Weiß
6f8f891760 Added poller delay
- added downstream and upstream speeds
- refactored SerialQueue
- counted version up to 0.5.5
2022-09-21 16:24:00 +02:00
Felix Weiß
8fb8d4989d Update version in package ref 2022-08-04 11:53:20 +02:00
Felix Weiß
45a9fa0520 Version upcount 2022-08-04 11:48:04 +02:00
Felix Weiß
772f8b89a4 Fixed auto value string enum conversion 2022-08-04 11:47:37 +02:00
10 changed files with 485 additions and 167 deletions

57
.github/workflows/publish.yml vendored Normal file
View File

@@ -0,0 +1,57 @@
name: publish to nuget
on:
push:
branches:
- master # Default release branch, may also be named 'master' or 'develop'
jobs:
publish:
name: build, pack & publish
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
# - name: Setup dotnet
# uses: actions/setup-dotnet@v1
# with:
# dotnet-version: 3.1.200
# Publish
- name: publish on version change
id: publish_nuget
uses: brandedoutcast/publish-nuget@v2
with:
# Filepath of the project to be packaged, relative to root of repository
PROJECT_FILE_PATH: MewtocolNet/MewtocolNet.csproj
# Configuration to build and package
# BUILD_CONFIGURATION: Release
# Platform target to compile (default is empty/AnyCPU)
# BUILD_PLATFORM: x64
# NuGet package id, used for version detection & defaults to project name
PACKAGE_NAME: Mewtocol.NET
# Filepath with version info, relative to root of repository & defaults to PROJECT_FILE_PATH
# VERSION_FILE_PATH: Directory.Build.props
# Regex pattern to extract version info in a capturing group
# VERSION_REGEX: ^\s*<Version>(.*)<\/Version>\s*$
# Useful with external providers like Nerdbank.GitVersioning, ignores VERSION_FILE_PATH & VERSION_REGEX
# VERSION_STATIC: 1.0.0
# Flag to toggle git tagging, enabled by default
# TAG_COMMIT: true
# Format of the git tag, [*] gets replaced with actual version
# TAG_FORMAT: v*
# API key to authenticate with NuGet server
NUGET_KEY: ${{secrets.NUGET_KEY}}
# NuGet server uri hosting the packages, defaults to https://api.nuget.org
# NUGET_SOURCE: https://api.nuget.org
# Flag to toggle pushing symbols along with nuget package to the server, disabled by default
# INCLUDE_SYMBOLS: false

View File

@@ -27,12 +27,14 @@ class Program {
Console.ReadLine(); Console.ReadLine();
} }
private static bool isProgressReadout = false;
static void Scenario1 () { static void Scenario1 () {
Task.Factory.StartNew(async () => { Task.Factory.StartNew(async () => {
//attaching the logger //attaching the logger
Logger.LogLevel = LogLevel.Critical; Logger.LogLevel = LogLevel.Verbose;
Logger.OnNewLogMessage((date, msg) => { Logger.OnNewLogMessage((date, msg) => {
Console.WriteLine($"{date.ToString("HH:mm:ss")} {msg}"); Console.WriteLine($"{date.ToString("HH:mm:ss")} {msg}");
}); });
@@ -44,45 +46,128 @@ class Program {
//attaching the register collection and an automatic poller //attaching the register collection and an automatic poller
interf.WithRegisterCollection(registers).WithPoller(); interf.WithRegisterCollection(registers).WithPoller();
await interf.ConnectAsync( _ = Task.Factory.StartNew(async () => {
(plcinf) => { while (true) {
if (isProgressReadout) continue;
//reading a value from the register collection Console.Title = $"Polling Paused: {interf.PollingPaused}, " +
Console.WriteLine($"BitValue is: {registers.BitValue}"); $"Poller active: {interf.PollerActive}, " +
Console.WriteLine($"TestEnum is: {registers.TestEnum}"); $"Speed UP: {interf.BytesPerSecondUpstream} B/s, " +
$"Speed DOWN: {interf.BytesPerSecondDownstream} B/s, " +
//writing a value to the registers $"Poll delay: {interf.PollerDelayMs} ms, " +
Task.Factory.StartNew(async () => { $"Queued MSGs: {interf.QueuedMessages}";
await Task.Delay(1000);
//set plc to run mode if not already
await interf.SetOperationMode(OPMode.Run);
int startAdress = 10000;
int entryByteSize = 20 * 20;
var bytes = await interf.ReadByteRange(startAdress, entryByteSize);
Console.WriteLine($"Bytes: {string.Join('-', bytes)}");
await Task.Delay(2000);
await interf.SetRegisterAsync(nameof(registers.TestInt32), 100);
//adds 10 each time the plc connects to the PLCs INT regíster
interf.SetRegister(nameof(registers.TestInt16), (short)(registers.TestInt16 + 10));
//adds 1 each time the plc connects to the PLCs DINT regíster
interf.SetRegister(nameof(registers.TestInt32), (registers.TestInt32 + 1));
//adds 11.11 each time the plc connects to the PLCs REAL regíster
interf.SetRegister(nameof(registers.TestFloat32), (float)(registers.TestFloat32 + 11.11));
//writes 'Hello' to the PLCs string register
interf.SetRegister(nameof(registers.TestString2), "Hello");
//set the current second to the PLCs TIME register
interf.SetRegister(nameof(registers.TestTime), TimeSpan.FromSeconds(DateTime.Now.Second));
});
} }
); });
//await interf.ConnectAsync((plcinf) => AfterConnect(interf, registers));
bool flip = false;
while(true) {
if(!flip) {
await interf.ConnectAsync();
} else {
interf.Disconnect();
}
flip = !flip;
await Task.Delay(5000);
}
});
}
static void AfterConnect (MewtocolInterface interf, TestRegisters registers) {
//reading a value from the register collection
Console.WriteLine($"BitValue is: {registers.BitValue}");
Console.WriteLine($"TestEnum is: {registers.TestEnum}");
_ = Task.Factory.StartNew(async () => {
while(true) {
isProgressReadout = true;
await interf.ReadByteRange(1000, 2000, (p) => {
var totSteps = 10;
var cSteps = totSteps * p;
string progBar = "";
for (int i = 0; i < totSteps; i++) {
if(i < (int)cSteps) {
progBar += "⬛";
} else {
progBar += "⬜";
}
}
Console.Title = $"Prog read range: {(p * 100).ToString("N1")}% {progBar} Queued MSGs: {interf.QueuedMessages}";
});
isProgressReadout = false;
await Task.Delay(3000);
}
});
//writing a value to the registers
_ = Task.Factory.StartNew(async () => {
//set plc to run mode if not already
await interf.SetOperationMode(OPMode.Run);
int startAdress = 10000;
int entryByteSize = 20 * 20;
var bytes = await interf.ReadByteRange(startAdress, entryByteSize);
Console.WriteLine($"Bytes: {string.Join('-', bytes)}");
await Task.Delay(2000);
await interf.SetRegisterAsync(nameof(registers.TestInt32), 100);
//adds 10 each time the plc connects to the PLCs INT regíster
interf.SetRegister(nameof(registers.TestInt16), (short)(registers.TestInt16 + 10));
//adds 1 each time the plc connects to the PLCs DINT regíster
interf.SetRegister(nameof(registers.TestInt32), (registers.TestInt32 + 1));
//adds 11.11 each time the plc connects to the PLCs REAL regíster
interf.SetRegister(nameof(registers.TestFloat32), (float)(registers.TestFloat32 + 11.11));
//writes 'Hello' to the PLCs string register
interf.SetRegister(nameof(registers.TestString2), "Hello");
//set the current second to the PLCs TIME register
interf.SetRegister(nameof(registers.TestTime), TimeSpan.FromSeconds(DateTime.Now.Second));
//test pausing poller
bool pollerPaused = false;
while (true) {
await Task.Delay(5000);
pollerPaused = !pollerPaused;
if (pollerPaused) {
Console.WriteLine("Pausing poller");
await interf.PausePollingAsync();
//interf.PollerDelayMs += 10;
Console.WriteLine("Paused poller");
} else {
interf.ResumePolling();
Console.WriteLine("Resumed poller");
}
}
}); });

View File

@@ -68,6 +68,8 @@ namespace Examples {
[Register(50)] [Register(50)]
public CurrentState TestEnum { get; private set; } public CurrentState TestEnum { get; private set; }
[Register(100)]
public TimeSpan TsTest2 { get; private set; }
} }
} }

View File

@@ -14,15 +14,69 @@ namespace MewtocolNet {
/// </summary> /// </summary>
public partial class MewtocolInterface { public partial class MewtocolInterface {
/// <summary>
/// True if the auto poller is currently paused
/// </summary>
public bool PollingPaused => pollerIsPaused;
/// <summary>
/// True if the poller is actvice (can be paused)
/// </summary>
public bool PollerActive => !pollerTaskStopped;
internal event Action PolledCycle; internal event Action PolledCycle;
internal bool ContinousReaderRunning;
internal volatile bool pollerTaskRunning;
internal volatile bool pollerTaskStopped;
internal volatile bool pollerIsPaused;
internal volatile bool pollerFirstCycle = false;
internal bool usePoller = false; internal bool usePoller = false;
#region Register Polling #region Register Polling
/// <summary>
/// Kills the poller completely
/// </summary>
internal void KillPoller () { internal void KillPoller () {
ContinousReaderRunning = false; pollerTaskRunning = false;
pollerTaskStopped = true;
ClearRegisterVals();
}
/// <summary>
/// Pauses the polling and waits for the last message to be sent
/// </summary>
/// <returns></returns>
public async Task PausePollingAsync () {
if (!pollerTaskRunning)
return;
pollerTaskRunning = false;
while (!pollerIsPaused) {
if (pollerIsPaused)
break;
await Task.Delay(10);
}
pollerTaskRunning = false;
}
/// <summary>
/// Resumes the polling
/// </summary>
public void ResumePolling () {
pollerTaskRunning = true;
} }
@@ -31,94 +85,110 @@ namespace MewtocolNet {
/// </summary> /// </summary>
internal void AttachPoller () { internal void AttachPoller () {
if (ContinousReaderRunning) if (pollerTaskRunning)
return; return;
pollerFirstCycle = true;
Task.Factory.StartNew(async () => { Task.Factory.StartNew(async () => {
Logger.Log("Poller is attaching", LogLevel.Info, this); Logger.Log("Poller is attaching", LogLevel.Info, this);
int it = 0; int iteration = 0;
ContinousReaderRunning = true;
while (ContinousReaderRunning) { pollerTaskStopped = false;
pollerTaskRunning = true;
pollerIsPaused = false;
while (!pollerTaskStopped) {
while (pollerTaskRunning) {
if (iteration >= Registers.Count + 1) {
iteration = 0;
//invoke cycle polled event
InvokePolledCycleDone();
continue;
}
if (iteration >= Registers.Count) {
await GetPLCInfoAsync();
iteration++;
continue;
}
var reg = Registers[iteration];
if (reg is NRegister<short> shortReg) {
var lastVal = shortReg.Value;
var readout = (await ReadNumRegister(shortReg)).Register.Value;
if (lastVal != readout) {
InvokeRegisterChanged(shortReg);
}
}
if (reg is NRegister<ushort> ushortReg) {
var lastVal = ushortReg.Value;
var readout = (await ReadNumRegister(ushortReg)).Register.Value;
if (lastVal != readout) {
InvokeRegisterChanged(ushortReg);
}
}
if (reg is NRegister<int> intReg) {
var lastVal = intReg.Value;
var readout = (await ReadNumRegister(intReg)).Register.Value;
if (lastVal != readout) {
InvokeRegisterChanged(intReg);
}
}
if (reg is NRegister<uint> uintReg) {
var lastVal = uintReg.Value;
var readout = (await ReadNumRegister(uintReg)).Register.Value;
if (lastVal != readout) {
InvokeRegisterChanged(uintReg);
}
}
if (reg is NRegister<float> floatReg) {
var lastVal = floatReg.Value;
var readout = (await ReadNumRegister(floatReg)).Register.Value;
if (lastVal != readout) {
InvokeRegisterChanged(floatReg);
}
}
if (reg is NRegister<TimeSpan> tsReg) {
var lastVal = tsReg.Value;
var readout = (await ReadNumRegister(tsReg)).Register.Value;
if (lastVal != readout) {
InvokeRegisterChanged(tsReg);
}
}
if (reg is BRegister boolReg) {
var lastVal = boolReg.Value;
var readout = (await ReadBoolRegister(boolReg)).Register.Value;
if (lastVal != readout) {
InvokeRegisterChanged(boolReg);
}
}
if (reg is SRegister stringReg) {
var lastVal = stringReg.Value;
var readout = (await ReadStringRegister(stringReg)).Register.Value;
if (lastVal != readout) {
InvokeRegisterChanged(stringReg);
}
}
iteration++;
pollerFirstCycle = false;
await Task.Delay(pollerDelayMs);
if (it >= Registers.Count + 1) {
it = 0;
//invoke cycle polled event
InvokePolledCycleDone();
continue;
} }
if (it >= Registers.Count) { pollerIsPaused = !pollerTaskRunning;
await GetPLCInfoAsync();
it++;
continue;
}
var reg = Registers[it];
if (reg is NRegister<short> shortReg) {
var lastVal = shortReg.Value;
var readout = (await ReadNumRegister(shortReg)).Register.Value;
if (lastVal != readout) {
InvokeRegisterChanged(shortReg);
}
}
if (reg is NRegister<ushort> ushortReg) {
var lastVal = ushortReg.Value;
var readout = (await ReadNumRegister(ushortReg)).Register.Value;
if (lastVal != readout) {
InvokeRegisterChanged(ushortReg);
}
}
if (reg is NRegister<int> intReg) {
var lastVal = intReg.Value;
var readout = (await ReadNumRegister(intReg)).Register.Value;
if (lastVal != readout) {
InvokeRegisterChanged(intReg);
}
}
if (reg is NRegister<uint> uintReg) {
var lastVal = uintReg.Value;
var readout = (await ReadNumRegister(uintReg)).Register.Value;
if (lastVal != readout) {
InvokeRegisterChanged(uintReg);
}
}
if (reg is NRegister<float> floatReg) {
var lastVal = floatReg.Value;
var readout = (await ReadNumRegister(floatReg)).Register.Value;
if (lastVal != readout) {
InvokeRegisterChanged(floatReg);
}
}
if (reg is NRegister<TimeSpan> tsReg) {
var lastVal = tsReg.Value;
var readout = (await ReadNumRegister(tsReg)).Register.Value;
if (lastVal != readout) {
InvokeRegisterChanged(tsReg);
}
}
if (reg is BRegister boolReg) {
var lastVal = boolReg.Value;
var readout = (await ReadBoolRegister(boolReg)).Register.Value;
if (lastVal != readout) {
InvokeRegisterChanged(boolReg);
}
}
if (reg is SRegister stringReg) {
var lastVal = stringReg.Value;
var readout = (await ReadStringRegister(stringReg)).Register.Value;
if (lastVal != readout) {
InvokeRegisterChanged(stringReg);
}
}
it++;
} }
pollerIsPaused = false;
}); });
} }

View File

@@ -52,6 +52,26 @@ namespace MewtocolNet {
set { connectTimeout = value; } set { connectTimeout = value; }
} }
private volatile int pollerDelayMs = 0;
/// <summary>
/// Delay for each poller cycle in milliseconds, default = 0
/// </summary>
public int PollerDelayMs {
get => pollerDelayMs;
set {
pollerDelayMs = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(PollerDelayMs)));
}
}
private volatile int queuedMessages;
/// <summary>
/// Currently queued Messages
/// </summary>
public int QueuedMessages {
get => queuedMessages;
}
/// <summary> /// <summary>
/// The host ip endpoint, leave it null to use an automatic interface /// The host ip endpoint, leave it null to use an automatic interface
/// </summary> /// </summary>
@@ -101,6 +121,9 @@ namespace MewtocolNet {
private int stationNumber; private int stationNumber;
private int cycleTimeMs = 25; private int cycleTimeMs = 25;
private int bytesTotalCountedUpstream = 0;
private int bytesTotalCountedDownstream = 0;
/// <summary> /// <summary>
/// The current IP of the PLC connection /// The current IP of the PLC connection
/// </summary> /// </summary>
@@ -125,6 +148,30 @@ namespace MewtocolNet {
} }
} }
private int bytesPerSecondUpstream = 0;
/// <summary>
/// The current transmission speed in bytes per second
/// </summary>
public int BytesPerSecondUpstream {
get { return bytesPerSecondUpstream; }
private set {
bytesPerSecondUpstream = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(BytesPerSecondUpstream)));
}
}
private int bytesPerSecondDownstream = 0;
/// <summary>
/// The current transmission speed in bytes per second
/// </summary>
public int BytesPerSecondDownstream {
get { return bytesPerSecondDownstream; }
private set {
bytesPerSecondDownstream = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(BytesPerSecondDownstream)));
}
}
internal NetworkStream stream; internal NetworkStream stream;
internal TcpClient client; internal TcpClient client;
internal readonly SerialQueue queue = new SerialQueue(); internal readonly SerialQueue queue = new SerialQueue();
@@ -132,6 +179,9 @@ namespace MewtocolNet {
internal int SendExceptionsInRow = 0; internal int SendExceptionsInRow = 0;
internal bool ImportantTaskRunning = false; internal bool ImportantTaskRunning = false;
private Stopwatch speedStopwatchUpstr;
private Stopwatch speedStopwatchDownstr;
#region Initialization #region Initialization
/// <summary> /// <summary>
@@ -345,6 +395,17 @@ namespace MewtocolNet {
} }
private void ClearRegisterVals () {
for (int i = 0; i < Registers.Count; i++) {
var reg = Registers[i];
reg.ClearValue();
}
}
#endregion #endregion
#region Register Collection #region Register Collection
@@ -682,8 +743,13 @@ namespace MewtocolNet {
//send request //send request
try { try {
queuedMessages++;
var response = await queue.Enqueue(() => SendSingleBlock(_msg)); var response = await queue.Enqueue(() => SendSingleBlock(_msg));
if (queuedMessages > 0)
queuedMessages--;
if (response == null) { if (response == null) {
return new CommandResult { return new CommandResult {
Success = false, Success = false,
@@ -736,6 +802,16 @@ namespace MewtocolNet {
var message = _blockString.ToHexASCIIBytes(); var message = _blockString.ToHexASCIIBytes();
//time measuring
if(speedStopwatchUpstr == null) {
speedStopwatchUpstr = Stopwatch.StartNew();
}
if(speedStopwatchUpstr.Elapsed.TotalSeconds >= 1) {
speedStopwatchUpstr.Restart();
bytesTotalCountedUpstream = 0;
}
//send request //send request
using (var sendStream = new MemoryStream(message)) { using (var sendStream = new MemoryStream(message)) {
await sendStream.CopyToAsync(stream); await sendStream.CopyToAsync(stream);
@@ -743,6 +819,13 @@ namespace MewtocolNet {
Logger.Log($"--> OUT MSG: {_blockString}", LogLevel.Critical, this); Logger.Log($"--> OUT MSG: {_blockString}", LogLevel.Critical, this);
} }
//calc upstream speed
bytesTotalCountedUpstream += message.Length;
var perSecUpstream = (double)((bytesTotalCountedUpstream / speedStopwatchUpstr.Elapsed.TotalMilliseconds) * 1000);
if (perSecUpstream <= 10000)
BytesPerSecondUpstream = (int)Math.Round(perSecUpstream, MidpointRounding.AwayFromZero);
//await result //await result
StringBuilder response = new StringBuilder(); StringBuilder response = new StringBuilder();
try { try {
@@ -755,6 +838,17 @@ namespace MewtocolNet {
while (!endLineCode && !startMsgCode) { while (!endLineCode && !startMsgCode) {
do { do {
//time measuring
if (speedStopwatchDownstr == null) {
speedStopwatchDownstr = Stopwatch.StartNew();
}
if (speedStopwatchDownstr.Elapsed.TotalSeconds >= 1) {
speedStopwatchDownstr.Restart();
bytesTotalCountedDownstream = 0;
}
int bytes = await stream.ReadAsync(responseBuffer, 0, responseBuffer.Length); int bytes = await stream.ReadAsync(responseBuffer, 0, responseBuffer.Length);
endLineCode = responseBuffer.Any(x => x == 0x0D); endLineCode = responseBuffer.Any(x => x == 0x0D);
@@ -777,8 +871,18 @@ namespace MewtocolNet {
} }
if(!string.IsNullOrEmpty(response.ToString())) { if(!string.IsNullOrEmpty(response.ToString())) {
Logger.Log($"<-- IN MSG: {response}", LogLevel.Critical, this); Logger.Log($"<-- IN MSG: {response}", LogLevel.Critical, this);
bytesTotalCountedDownstream += Encoding.ASCII.GetByteCount(response.ToString());
var perSecDownstream = (double)((bytesTotalCountedDownstream / speedStopwatchDownstr.Elapsed.TotalMilliseconds) * 1000);
if(perSecUpstream <= 10000)
BytesPerSecondDownstream = (int)Math.Round(perSecUpstream, MidpointRounding.AwayFromZero);
return response.ToString(); return response.ToString();
} else { } else {
return null; return null;
} }

View File

@@ -112,8 +112,9 @@ namespace MewtocolNet {
/// </summary> /// </summary>
/// <param name="start">Start adress</param> /// <param name="start">Start adress</param>
/// <param name="count">Number of bytes to get</param> /// <param name="count">Number of bytes to get</param>
/// <param name="onProgress">Gets invoked when the progress changes, contains the progress as a double</param>
/// <returns>A byte array or null of there was an error</returns> /// <returns>A byte array or null of there was an error</returns>
public async Task<byte[]> ReadByteRange (int start, int count) { public async Task<byte[]> ReadByteRange (int start, int count, Action<double> onProgress = null) {
var byteList = new List<byte>(); var byteList = new List<byte>();
@@ -146,6 +147,9 @@ namespace MewtocolNet {
} }
if(onProgress != null)
onProgress((double)i / wordLength);
} }
return byteList.ToArray(); return byteList.ToArray();

View File

@@ -94,6 +94,38 @@ namespace MewtocolNet.Registers {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Value")); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Value"));
} }
internal void ClearValue () {
if (enumType != null && this is NRegister<int> intEnumReg) {
intEnumReg.SetValueFromPLC((int)0);
}
if (this is NRegister<short> shortReg) {
shortReg.SetValueFromPLC((short)0);
}
if (this is NRegister<ushort> ushortReg) {
ushortReg.SetValueFromPLC((ushort)0);
}
if (this is NRegister<int> intReg) {
intReg.SetValueFromPLC((int)0);
}
if (this is NRegister<uint> uintReg) {
uintReg.SetValueFromPLC((uint)0);
}
if (this is NRegister<float> floatReg) {
floatReg.SetValueFromPLC((float)0);
}
if (this is NRegister<TimeSpan> tsReg) {
tsReg.SetValueFromPLC(TimeSpan.Zero);
}
if (this is BRegister boolReg) {
boolReg.SetValueFromPLC(false);
}
if (this is SRegister stringReg) {
stringReg.SetValueFromPLC(null);
}
}
/// <summary> /// <summary>
/// Gets the starting memory are either numeric or A,B,C,D etc for special areas like inputs /// Gets the starting memory are either numeric or A,B,C,D etc for special areas like inputs
/// </summary> /// </summary>
@@ -115,9 +147,14 @@ namespace MewtocolNet.Registers {
public string GetValueString () { public string GetValueString () {
if (enumType != null && this is NRegister<int> intEnumReg) { if (enumType != null && this is NRegister<int> intEnumReg) {
var dict = new Dictionary<int, string>(); var dict = new Dictionary<int, string>();
foreach (var name in Enum.GetNames(enumType)) { foreach (var name in Enum.GetNames(enumType)) {
dict.Add((int)Enum.Parse(enumType, name), name); int enumKey = (int)Enum.Parse(enumType, name);
if(!dict.ContainsKey(enumKey)) {
dict.Add(enumKey, name);
}
} }
if(dict.ContainsKey(intEnumReg.Value)) { if(dict.ContainsKey(intEnumReg.Value)) {
@@ -125,6 +162,7 @@ namespace MewtocolNet.Registers {
} else { } else {
return $"{intEnumReg.Value} (Missing Enum)"; return $"{intEnumReg.Value} (Missing Enum)";
} }
} }
if (this is NRegister<short> shortReg) { if (this is NRegister<short> shortReg) {
return $"{shortReg.Value}{(isUsedBitwise ? $" [{shortReg.GetBitwise().ToBitString()}]" : "")}"; return $"{shortReg.Value}{(isUsedBitwise ? $" [{shortReg.GetBitwise().ToBitString()}]" : "")}";

View File

@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<PackageId>MewtocolNet</PackageId> <PackageId>Mewtocol.NET</PackageId>
<Version>0.5.1</Version> <Version>0.6.2</Version>
<Authors>Felix Weiss</Authors> <Authors>Felix Weiss</Authors>
<Company>Womed</Company> <Company>Womed</Company>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> <GeneratePackageOnBuild>true</GeneratePackageOnBuild>

View File

@@ -8,47 +8,6 @@ namespace MewtocolNet.Queue {
readonly object _locker = new object(); readonly object _locker = new object();
readonly WeakReference<Task> _lastTask = new WeakReference<Task>(null); readonly WeakReference<Task> _lastTask = new WeakReference<Task>(null);
internal Task Enqueue (Action action) {
return Enqueue<bool>(() => {
action();
return true;
});
}
internal Task<T> Enqueue<T> (Func<T> function) {
lock (_locker) {
Task lastTask;
Task<T> resultTask;
if (_lastTask.TryGetTarget(out lastTask)) {
resultTask = lastTask.ContinueWith(_ => function(), TaskContinuationOptions.ExecuteSynchronously);
} else {
resultTask = Task.Run(function);
}
_lastTask.SetTarget(resultTask);
return resultTask;
}
}
internal Task Enqueue (Func<Task> asyncAction) {
lock (_locker) {
Task lastTask;
Task resultTask;
if (_lastTask.TryGetTarget(out lastTask)) {
resultTask = lastTask.ContinueWith(_ => asyncAction(), TaskContinuationOptions.ExecuteSynchronously).Unwrap();
} else {
resultTask = Task.Run(asyncAction);
}
_lastTask.SetTarget(resultTask);
return resultTask;
}
}
internal Task<T> Enqueue<T> (Func<Task<T>> asyncFunction) { internal Task<T> Enqueue<T> (Func<Task<T>> asyncFunction) {
lock (_locker) { lock (_locker) {
Task lastTask; Task lastTask;

View File

@@ -1,7 +1,6 @@
[![.NET Windows](https://github.com/WOmed/MewtocolNet/actions/workflows/dotnet-windows.yml/badge.svg)](https://github.com/WOmed/MewtocolNet/actions/workflows/dotnet-windows.yml) [![Publish to Nuget](https://github.com/WOmed/MewtocolNet/actions/workflows/publish.yml/badge.svg)](https://github.com/WOmed/MewtocolNet/actions/workflows/publish.yml)
![Nuget](https://img.shields.io/nuget/v/MewtocolNet) [![Nuget](https://img.shields.io/nuget/v/Mewtocol.NET)](https://www.nuget.org/packages/Mewtocol.NET)
![Lines of code](https://img.shields.io/tokei/lines/github/WOmed/MewtocolNet) ![Lines of code](https://img.shields.io/tokei/lines/github/WOmed/MewtocolNet)
![Nuget](https://img.shields.io/nuget/dt/MewtocolNet)
![GitHub](https://img.shields.io/github/license/WOmed/MewtocolNet) ![GitHub](https://img.shields.io/github/license/WOmed/MewtocolNet)
![Status](https://img.shields.io/badge/Status-In%20dev-orange) ![Status](https://img.shields.io/badge/Status-In%20dev-orange)
@@ -51,14 +50,14 @@ Where is the RS232/Serial support?
# Installing # Installing
Install this package by using [Nuget](https://www.nuget.org/packages/MewtocolNet/) or reference Install this package by using [Nuget](https://www.nuget.org/packages/Mewtocol.NET) or reference
```XML ```XML
<PackageReference Include="MewtocolNet" Version="0.5.0" /> <PackageReference Include="Mewtocol.NET" Version="0.6.1"/>
``` ```
in your dependencies. in your dependencies.
Alternatively use the dotnet CLI and run Alternatively use the dotnet CLI and run
```Shell ```Shell
dotnet add package MewtocolNet dotnet add package Mewtocol.NET
``` ```
# Protocol description # Protocol description