9 Commits

Author SHA1 Message Date
Felix Weiß
5cc222abcc Merge branch 'master' of https://github.com/WOmed/MewtocolNet 2022-06-22 09:22:37 +02:00
Felix Weiß
14659ffaad Implemented INotifyPropertyChanged on MewtocolInterface
- added event for disconnect
- counted up version number
2022-06-22 09:21:50 +02:00
Sandoun
ea106416ee Fixed an issue with doc file and build directory path 2022-06-21 18:05:14 +02:00
Felix Weiß
0afa146712 Counted up version number 2022-06-21 16:45:48 +02:00
Felix Weiß
325aa56d8a Added register collection base methods 2022-06-21 16:45:22 +02:00
Felix Weiß
f4fad297fb Merge branch 'master' of https://github.com/WOmed/MewtocolNet 2022-06-21 15:54:31 +02:00
Felix Weiß
664b32b92e Fixed plc info not getting set when reading it
- added auto poll of plc info each 25 cycles
- counted up version
2022-06-21 15:54:24 +02:00
Felix Weiß
a639a8eda8 Update README.md 2022-06-21 14:31:29 +02:00
Felix Weiß
23c2b0efb4 Update README.md 2022-06-21 14:20:25 +02:00
7 changed files with 110 additions and 32 deletions

View File

@@ -45,8 +45,7 @@ namespace Examples {
//corresponds to a DT7012 - DT7013 as a 32bit time value that gets parsed as a timespan (TIME)
//the smallest value to communicate to the PLC is 10ms
[Register(7012)]
public TimeSpan TestTime { get; private set; }
public TimeSpan TestTime { get; private set; }
}
}

View File

@@ -71,6 +71,8 @@ namespace MewtocolNet {
ContinousReaderRunning = true;
int getPLCinfoCycleCount = 0;
while (ContinousReaderRunning) {
//do priority tasks first
@@ -78,6 +80,11 @@ namespace MewtocolNet {
await PriorityTasks.FirstOrDefault(x => !x.IsCompleted);
} else if (getPLCinfoCycleCount > 25) {
await GetPLCInfoAsync();
getPLCinfoCycleCount = 0;
}
foreach (var registerPair in Registers) {
@@ -159,6 +166,8 @@ namespace MewtocolNet {
}
getPLCinfoCycleCount++;
//invoke cycle polled event
InvokePolledCycleDone();

View File

@@ -11,33 +11,58 @@ using MewtocolNet.RegisterAttributes;
using MewtocolNet.Logging;
using System.Collections;
using System.Diagnostics;
using System.ComponentModel;
namespace MewtocolNet {
/// <summary>
/// The PLC com interface class
/// </summary>
public partial class MewtocolInterface {
public partial class MewtocolInterface : INotifyPropertyChanged {
/// <summary>
/// Gets triggered when the PLC connection was established
/// </summary>
public event Action<PLCInfo> Connected;
/// <summary>
/// Gets triggered when the PLC connection was closed or lost
/// </summary>
public event Action Disconnected;
/// <summary>
/// Gets triggered when a registered data register changes its value
/// </summary>
public event Action<Register> RegisterChanged;
/// <summary>
/// Gets triggered when a property of the interface changes
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
private bool isConnected;
/// <summary>
/// The current connection state of the interface
/// </summary>
public bool IsConnected { get; private set; }
public bool IsConnected {
get => isConnected;
private set {
isConnected = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsConnected)));
}
}
private PLCInfo plcInfo;
/// <summary>
/// Generic information about the connected PLC
/// </summary>
public PLCInfo PlcInfo { get; private set; }
public PLCInfo PlcInfo {
get => plcInfo;
private set {
plcInfo = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(PlcInfo)));
}
}
/// <summary>
/// The registered data registers of the PLC
@@ -46,7 +71,7 @@ namespace MewtocolNet {
private string ip;
private int port;
private int stationNumber;
private int stationNumber;
/// <summary>
/// The current IP of the PLC connection
@@ -61,7 +86,20 @@ namespace MewtocolNet {
/// </summary>
public int StationNumber => stationNumber;
internal List<Task> PriorityTasks { get; set; } = new List<Task>();
private int cycleTimeMs;
/// <summary>
/// The duration of the last message cycle
/// </summary>
public int CycleTimeMs {
get { return cycleTimeMs; }
set {
cycleTimeMs = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CycleTimeMs)));
}
}
internal List<Task> PriorityTasks { get; set; } = new List<Task>();
#region Initialization
@@ -72,10 +110,10 @@ namespace MewtocolNet {
/// <param name="_port">Port of the PLC</param>
/// <param name="_station">Station Number of the PLC</param>
public MewtocolInterface (string _ip, int _port = 9094, int _station = 1) {
ip = _ip;
port = _port;
stationNumber = _station;
stationNumber = _station;
Connected += MewtocolInterface_Connected;
@@ -90,7 +128,8 @@ namespace MewtocolNet {
RegisterChanged += (o) => {
string address = $"{o.GetRegisterString()}{o.MemoryAdress}".PadRight(5, (char)32); ;
string address = $"{o.GetRegisterString()}{o.MemoryAdress}".PadRight(5, (char)32);
;
Logger.Log($"{address} " +
$"{(o.Name != null ? $"({o.Name}) " : "")}" +
@@ -144,6 +183,7 @@ namespace MewtocolNet {
if (OnFailed != null) {
OnFailed();
Disconnected?.Invoke();
Logger.Log("Initial connection failed", LogLevel.Info, this);
}
@@ -190,7 +230,7 @@ namespace MewtocolNet {
string propName = prop.Name;
foreach (var attr in attributes) {
if(attr is RegisterAttribute cAttribute) {
if (attr is RegisterAttribute cAttribute) {
if (prop.PropertyType == typeof(bool) && cAttribute.AssignedBitIndex == -1) {
if (cAttribute.SpecialAddress == SpecialAddress.None) {
@@ -227,7 +267,7 @@ namespace MewtocolNet {
//read number as bit array
if (prop.PropertyType == typeof(BitArray)) {
if(cAttribute.BitCount == BitCount.B16) {
if (cAttribute.BitCount == BitCount.B16) {
AddRegister<short>(cAttribute.MemoryArea, _name: propName, _isBitwise: true);
} else {
AddRegister<int>(cAttribute.MemoryArea, _name: propName, _isBitwise: true);
@@ -259,7 +299,7 @@ namespace MewtocolNet {
RegisterChanged += (reg) => {
var foundToUpdate = props.FirstOrDefault(x => x.Name == reg.Name);
if (foundToUpdate != null) {
var foundAttributes = foundToUpdate.GetCustomAttributes(true);
@@ -329,7 +369,7 @@ namespace MewtocolNet {
}
} else if(foundToUpdate.PropertyType == typeof(BitArray)) {
} else if (foundToUpdate.PropertyType == typeof(BitArray)) {
//setting back bit registers
if (reg is NRegister<short> shortReg) {
@@ -356,6 +396,14 @@ namespace MewtocolNet {
};
if (collection != null)
collection.OnInterfaceLinked(this);
Connected += (i) => {
if (collection != null)
collection.OnInterfaceLinkedAndOnline(this);
};
return this;
}
@@ -465,7 +513,7 @@ namespace MewtocolNet {
string response = null;
if(ContinousReaderRunning) {
if (ContinousReaderRunning) {
//if the poller is active then add all messages to a qeueue
@@ -473,7 +521,7 @@ namespace MewtocolNet {
PriorityTasks.Add(awaittask);
awaittask.Wait();
PriorityTasks.Remove(awaittask);
PriorityTasks.Remove(awaittask);
response = awaittask.Result;
} else {
@@ -484,7 +532,7 @@ namespace MewtocolNet {
}
if(response == null) {
if (response == null) {
return new CommandResult {
Success = false,
Error = "0000",
@@ -519,7 +567,7 @@ namespace MewtocolNet {
private async Task<string> SendSingleBlock (string _blockString) {
Stopwatch sw = Stopwatch.StartNew();
Stopwatch sw = Stopwatch.StartNew();
using (TcpClient client = new TcpClient() { ReceiveBufferSize = 64, NoDelay = true, ExclusiveAddressUse = true }) {
@@ -551,15 +599,19 @@ namespace MewtocolNet {
return response.ToString();
}
} catch(Exception) {
} catch (Exception) {
if (IsConnected) {
IsConnected = false;
Disconnected?.Invoke();
}
IsConnected = false;
KillPoller();
Logger.Log("The PLC connection was closed", LogLevel.Error, this);
return null;
}
}
}

View File

@@ -44,6 +44,8 @@ namespace MewtocolNet {
ErrorCode = error,
StationNumber = int.Parse(station ?? "0"),
};
PlcInfo = retInfo;
return retInfo;
}

View File

@@ -10,17 +10,34 @@ using System.Threading.Tasks;
namespace MewtocolNet.RegisterAttributes {
/// <summary>
/// A register collection base with full auto read and notification support built in
/// </summary>
public class RegisterCollectionBase : INotifyPropertyChanged {
/// <summary>
/// Reference to its bound interface
/// </summary>
public MewtocolInterface PLCInterface { get; set; }
/// <summary>
/// Whenever one of its props changes
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
internal void TriggerPropertyChanged (string propertyName = null) {
/// <summary>
/// Triggers a property changed event
/// </summary>
/// <param name="propertyName">Name of the property to trigger for</param>
public void TriggerPropertyChanged (string propertyName = null) {
var handler = PropertyChanged;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public virtual void OnInterfaceLinked (MewtocolInterface plc) { }
public virtual void OnInterfaceLinkedAndOnline (MewtocolInterface plc) { }
}
}

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<PackageId>MewtocolNet</PackageId>
<Version>0.3.0</Version>
<Version>0.3.3</Version>
<Authors>Felix Weiss</Authors>
<Company>Womed</Company>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
@@ -15,7 +15,7 @@
<UserSecretsId>2ccdcc9b-94a3-4e76-8827-453ab889ea33</UserSecretsId>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>C:\Users\Felix Weiß\source\repos\WOmed\MewtocolNet\Builds\MewtocolNet.xml</DocumentationFile>
<OutputPath>C:\Users\Felix Weiß\source\repos\WOmed\MewtocolNet\Builds</OutputPath>
<DocumentationFile>..\Builds\MewtocolNet.xml</DocumentationFile>
<OutputPath>..\Builds</OutputPath>
</PropertyGroup>
</Project>

View File

@@ -18,11 +18,10 @@ This software was written by WOLF Medizintechnik GmbH (@WOmed/dev).
- [x] Read out stats from your PLC
- [x] Read and write registers in real time
- [X] Dynamic register type casting from properties
- [ ] Change run / prog modes
- [ ] Write byte blocks in a whole chain
- [ ] Upload programs to the PLC
- [ ] Download programs from the PLC
- [x] Dynamic register type casting from properties
- [x] Change run / prog modes
- [x] Write / read byte blocks in a whole chain
- [ ] Upload / Download programs to the PLC
- [ ] Reading / writing PLC system registers
# Support
@@ -54,7 +53,7 @@ Where is the RS232/Serial support?
Install this package by using [Nuget](https://www.nuget.org/packages/MewtocolNet/) or reference
```XML
<PackageReference Include="MewtocolNet" Version="0.2.5" />
<PackageReference Include="MewtocolNet" Version="0.3.0" />
```
in your dependencies.
Alternatively use the dotnet CLI and run