mirror of
https://github.com/OpenLogics/MewtocolNet.git
synced 2025-12-06 11:11:23 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43c7f72ac4 | ||
|
|
2e35ed87af | ||
|
|
a7f97a72ea | ||
|
|
51870166e4 | ||
|
|
b43e9bd201 | ||
|
|
e313dbc3ec | ||
|
|
bdf9f93f97 | ||
|
|
fe816ab78e | ||
|
|
48a5977185 | ||
|
|
c69f63c191 | ||
|
|
6a2f278dd1 | ||
|
|
19159ed183 | ||
|
|
635823a66f |
57
.github/workflows/publish.yml
vendored
Normal file
57
.github/workflows/publish.yml
vendored
Normal 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
|
||||||
@@ -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}");
|
||||||
});
|
});
|
||||||
@@ -46,72 +48,126 @@ class Program {
|
|||||||
|
|
||||||
_ = Task.Factory.StartNew(async () => {
|
_ = Task.Factory.StartNew(async () => {
|
||||||
while (true) {
|
while (true) {
|
||||||
Console.Title = $"Polling Paused: {interf.PollingPaused}, Speed UP: {interf.BytesPerSecondUpstream} B/s, Speed DOWN: {interf.BytesPerSecondDownstream} B/s";
|
if (isProgressReadout) continue;
|
||||||
|
Console.Title = $"Polling Paused: {interf.PollingPaused}, " +
|
||||||
|
$"Poller active: {interf.PollerActive}, " +
|
||||||
|
$"Speed UP: {interf.BytesPerSecondUpstream} B/s, " +
|
||||||
|
$"Speed DOWN: {interf.BytesPerSecondDownstream} B/s, " +
|
||||||
|
$"Poll delay: {interf.PollerDelayMs} ms, " +
|
||||||
|
$"Queued MSGs: {interf.QueuedMessages}";
|
||||||
await Task.Delay(1000);
|
await Task.Delay(1000);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await interf.ConnectAsync(
|
//await interf.ConnectAsync((plcinf) => AfterConnect(interf, registers));
|
||||||
(plcinf) => {
|
|
||||||
|
|
||||||
//reading a value from the register collection
|
bool flip = false;
|
||||||
Console.WriteLine($"BitValue is: {registers.BitValue}");
|
while(true) {
|
||||||
Console.WriteLine($"TestEnum is: {registers.TestEnum}");
|
|
||||||
|
|
||||||
//writing a value to the registers
|
if(!flip) {
|
||||||
Task.Factory.StartNew(async () => {
|
await interf.ConnectAsync();
|
||||||
|
} else {
|
||||||
|
interf.Disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
//set plc to run mode if not already
|
flip = !flip;
|
||||||
await interf.SetOperationMode(OPMode.Run);
|
await Task.Delay(5000);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int startAdress = 10000;
|
});
|
||||||
int entryByteSize = 20 * 20;
|
|
||||||
|
|
||||||
var bytes = await interf.ReadByteRange(startAdress, entryByteSize);
|
}
|
||||||
Console.WriteLine($"Bytes: {string.Join('-', bytes)}");
|
|
||||||
|
|
||||||
await Task.Delay(2000);
|
static void AfterConnect (MewtocolInterface interf, TestRegisters registers) {
|
||||||
|
|
||||||
await interf.SetRegisterAsync(nameof(registers.TestInt32), 100);
|
//reading a value from the register collection
|
||||||
|
Console.WriteLine($"BitValue is: {registers.BitValue}");
|
||||||
|
Console.WriteLine($"TestEnum is: {registers.TestEnum}");
|
||||||
|
|
||||||
//adds 10 each time the plc connects to the PLCs INT regíster
|
_ = Task.Factory.StartNew(async () => {
|
||||||
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
|
while(true) {
|
||||||
|
|
||||||
bool pollerPaused = false;
|
isProgressReadout = true;
|
||||||
|
|
||||||
while(true) {
|
await interf.ReadByteRange(1000, 2000, (p) => {
|
||||||
|
|
||||||
await Task.Delay(5000);
|
var totSteps = 10;
|
||||||
|
var cSteps = totSteps * p;
|
||||||
|
|
||||||
pollerPaused = !pollerPaused;
|
string progBar = "";
|
||||||
|
for (int i = 0; i < totSteps; i++) {
|
||||||
if(pollerPaused) {
|
|
||||||
Console.WriteLine("Pausing poller");
|
|
||||||
await interf.PausePollingAsync();
|
|
||||||
Console.WriteLine("Paused poller");
|
|
||||||
} else {
|
|
||||||
interf.ResumePolling();
|
|
||||||
Console.WriteLine("Resumed poller");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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");
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -19,11 +19,17 @@ namespace MewtocolNet {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool PollingPaused => pollerIsPaused;
|
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 volatile bool pollerTaskRunning;
|
internal volatile bool pollerTaskRunning;
|
||||||
internal volatile bool pollerTaskStopped;
|
internal volatile bool pollerTaskStopped;
|
||||||
internal volatile bool pollerIsPaused;
|
internal volatile bool pollerIsPaused;
|
||||||
|
internal volatile bool pollerFirstCycle = false;
|
||||||
|
|
||||||
internal bool usePoller = false;
|
internal bool usePoller = false;
|
||||||
|
|
||||||
@@ -37,6 +43,8 @@ namespace MewtocolNet {
|
|||||||
pollerTaskRunning = false;
|
pollerTaskRunning = false;
|
||||||
pollerTaskStopped = true;
|
pollerTaskStopped = true;
|
||||||
|
|
||||||
|
ClearRegisterVals();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -80,6 +88,8 @@ namespace MewtocolNet {
|
|||||||
if (pollerTaskRunning)
|
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);
|
||||||
@@ -167,8 +177,9 @@ namespace MewtocolNet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
iteration++;
|
iteration++;
|
||||||
|
pollerFirstCycle = false;
|
||||||
|
|
||||||
await Task.Delay(PollerDelayMs);
|
await Task.Delay(pollerDelayMs);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,13 +52,24 @@ namespace MewtocolNet {
|
|||||||
set { connectTimeout = value; }
|
set { connectTimeout = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private int pollerDelayMs = 0;
|
private volatile int pollerDelayMs = 0;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delay for each poller cycle in milliseconds, default = 0
|
/// Delay for each poller cycle in milliseconds, default = 0
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int PollerDelayMs {
|
public int PollerDelayMs {
|
||||||
get { return pollerDelayMs; }
|
get => pollerDelayMs;
|
||||||
set { pollerDelayMs = value; }
|
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>
|
||||||
@@ -384,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
|
||||||
@@ -721,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,
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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.6</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>
|
||||||
|
|||||||
11
README.md
11
README.md
@@ -1,7 +1,6 @@
|
|||||||
[](https://github.com/WOmed/MewtocolNet/actions/workflows/dotnet-windows.yml)
|
[](https://github.com/WOmed/MewtocolNet/actions/workflows/publish.yml)
|
||||||

|
[](https://www.nuget.org/packages/Mewtocol.NET)
|
||||||

|

|
||||||

|
|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
@@ -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.2" />
|
<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
|
||||||
|
|||||||
Reference in New Issue
Block a user