diff --git a/Examples/Program.cs b/Examples/Program.cs
index de1c005..f142896 100644
--- a/Examples/Program.cs
+++ b/Examples/Program.cs
@@ -33,6 +33,9 @@ namespace Examples {
//writing a value to the registers
Task.Factory.StartNew(async () => {
+ //set plc to run mode if not already
+ await interf.SetOperationMode(OPMode.Run);
+
await Task.Delay(2000);
//inverts the boolean register
diff --git a/MewtocolNet/Mewtocol/CpuInfo.cs b/MewtocolNet/Mewtocol/CpuInfo.cs
index ff6ecc8..124ce2a 100644
--- a/MewtocolNet/Mewtocol/CpuInfo.cs
+++ b/MewtocolNet/Mewtocol/CpuInfo.cs
@@ -1,49 +1,7 @@
using System;
namespace MewtocolNet.Registers {
- public class CpuInfo {
- ///
- /// CPU type of the PLC
- ///
- public enum CpuType {
- ///
- /// FP 0 / FP 2.7K
- ///
- FP0_FP1_2_7K,
- ///
- /// FP0 / FP1, 5K / 10K
- ///
- FP0_FP1_5K_10K,
- ///
- /// FP1 M 0.9K
- ///
- FP1_M_0_9K,
- ///
- /// FP2 16k / 32k
- ///
- FP2_16K_32K,
- ///
- /// FP3 C 10K
- ///
- FP3_C_10K,
- ///
- /// FP3 C 16K
- ///
- FP3_C_16K,
- ///
- /// FP5 16K
- ///
- FP5_16K,
- ///
- /// FP 5 24K
- ///
- FP5_24K,
- ///
- /// Includes panasonic FPX, FPX-H, Sigma
- ///
- FP_Sigma_X_H_30K_60K_120K
-
- }
+ public partial class CpuInfo {
public CpuType Cputype { get; set; }
public int ProgramCapacity { get; set; }
diff --git a/MewtocolNet/Mewtocol/DynamicInterface.cs b/MewtocolNet/Mewtocol/DynamicInterface.cs
index 266fee9..03880ef 100644
--- a/MewtocolNet/Mewtocol/DynamicInterface.cs
+++ b/MewtocolNet/Mewtocol/DynamicInterface.cs
@@ -24,7 +24,7 @@ namespace MewtocolNet {
internal void KillPoller () {
ContinousReaderRunning = false;
- cTokenAutoUpdater.Cancel();
+ cTokenAutoUpdater?.Cancel();
}
@@ -86,7 +86,7 @@ namespace MewtocolNet {
if (reg is NRegister shortReg) {
var lastVal = shortReg.Value;
- var readout = (await ReadNumRegister(shortReg, stationNumber)).Register.Value;
+ var readout = (await ReadNumRegister(shortReg)).Register.Value;
if (lastVal != readout) {
shortReg.LastValue = readout;
InvokeRegisterChanged(shortReg);
@@ -95,7 +95,7 @@ namespace MewtocolNet {
}
if (reg is NRegister ushortReg) {
var lastVal = ushortReg.Value;
- var readout = (await ReadNumRegister(ushortReg, stationNumber)).Register.Value;
+ var readout = (await ReadNumRegister(ushortReg)).Register.Value;
if (lastVal != readout) {
ushortReg.LastValue = readout;
InvokeRegisterChanged(ushortReg);
@@ -104,7 +104,7 @@ namespace MewtocolNet {
}
if (reg is NRegister intReg) {
var lastVal = intReg.Value;
- var readout = (await ReadNumRegister(intReg, stationNumber)).Register.Value;
+ var readout = (await ReadNumRegister(intReg)).Register.Value;
if (lastVal != readout) {
intReg.LastValue = readout;
InvokeRegisterChanged(intReg);
@@ -113,7 +113,7 @@ namespace MewtocolNet {
}
if (reg is NRegister uintReg) {
var lastVal = uintReg.Value;
- var readout = (await ReadNumRegister(uintReg, stationNumber)).Register.Value;
+ var readout = (await ReadNumRegister(uintReg)).Register.Value;
if (lastVal != readout) {
uintReg.LastValue = readout;
InvokeRegisterChanged(uintReg);
@@ -122,7 +122,7 @@ namespace MewtocolNet {
}
if (reg is NRegister floatReg) {
var lastVal = floatReg.Value;
- var readout = (await ReadNumRegister(floatReg, stationNumber)).Register.Value;
+ var readout = (await ReadNumRegister(floatReg)).Register.Value;
if (lastVal != readout) {
floatReg.LastValue = readout;
InvokeRegisterChanged(floatReg);
@@ -131,7 +131,7 @@ namespace MewtocolNet {
}
if (reg is NRegister tsReg) {
var lastVal = tsReg.Value;
- var readout = (await ReadNumRegister(tsReg, stationNumber)).Register.Value;
+ var readout = (await ReadNumRegister(tsReg)).Register.Value;
if (lastVal != readout) {
tsReg.LastValue = readout;
InvokeRegisterChanged(tsReg);
@@ -140,7 +140,7 @@ namespace MewtocolNet {
}
if (reg is BRegister boolReg) {
var lastVal = boolReg.Value;
- var readout = (await ReadBoolRegister(boolReg, stationNumber)).Register.Value;
+ var readout = (await ReadBoolRegister(boolReg)).Register.Value;
if (lastVal != readout) {
boolReg.LastValue = readout;
InvokeRegisterChanged(boolReg);
@@ -149,7 +149,7 @@ namespace MewtocolNet {
}
if (reg is SRegister stringReg) {
var lastVal = stringReg.Value;
- var readout = (await ReadStringRegister(stringReg, stationNumber)).Register.Value;
+ var readout = (await ReadStringRegister(stringReg)).Register.Value;
if (lastVal != readout) {
InvokeRegisterChanged(stringReg);
stringReg.TriggerNotifyChange();
diff --git a/MewtocolNet/Mewtocol/MewtocolHelpers.cs b/MewtocolNet/Mewtocol/MewtocolHelpers.cs
index ae1dbb1..5868c63 100644
--- a/MewtocolNet/Mewtocol/MewtocolHelpers.cs
+++ b/MewtocolNet/Mewtocol/MewtocolHelpers.cs
@@ -159,19 +159,42 @@ namespace MewtocolNet {
internal static byte[] HexStringToByteArray(this string hex) {
return Enumerable.Range(0, hex.Length)
- .Where(x => x % 2 == 0)
- .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
- .ToArray();
+ .Where(x => x % 2 == 0)
+ .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
+ .ToArray();
}
internal static string ToHexString (this byte[] arr) {
StringBuilder sb = new StringBuilder();
- foreach (var b in arr) {
+ for (int i = 0; i < arr.Length; i++) {
+ byte b = arr[i];
sb.Append(b.ToString("X2"));
}
return sb.ToString();
}
+ internal static byte[] BigToMixedEndian (this byte[] arr) {
+
+ List oldBL = new List(arr);
+
+ List tempL = new List();
+
+ //make the input list even
+ if(arr.Length % 2 != 0)
+ oldBL.Add((byte)0);
+
+ for (int i = 0; i < oldBL.Count; i+=2) {
+ byte firstByte = oldBL[i];
+ byte lastByte = oldBL[i + 1];
+ tempL.Add(lastByte);
+ tempL.Add(firstByte);
+
+ }
+
+ return tempL.ToArray();
+
+ }
+
}
}
\ No newline at end of file
diff --git a/MewtocolNet/Mewtocol/MewtocolInterface.cs b/MewtocolNet/Mewtocol/MewtocolInterface.cs
index 5092e07..cf330ad 100644
--- a/MewtocolNet/Mewtocol/MewtocolInterface.cs
+++ b/MewtocolNet/Mewtocol/MewtocolInterface.cs
@@ -115,6 +115,8 @@ namespace MewtocolNet {
///
public async Task ConnectAsync (Action OnConnected = null, Action OnFailed = null) {
+ Logger.Log("Connecting to PLC...", LogLevel.Info, this);
+
var plcinf = await GetPLCInfoAsync();
if (plcinf != null) {
@@ -394,49 +396,49 @@ namespace MewtocolNet {
if (foundRegister.GetType() == typeof(BRegister)) {
- return await WriteBoolRegister((BRegister)foundRegister, (bool)value, StationNumber);
+ return await WriteBoolRegister((BRegister)foundRegister, (bool)value);
}
if (foundRegister.GetType() == typeof(NRegister)) {
- return await WriteNumRegister((NRegister)foundRegister, (short)value, StationNumber);
+ return await WriteNumRegister((NRegister)foundRegister, (short)value);
}
if (foundRegister.GetType() == typeof(NRegister)) {
- return await WriteNumRegister((NRegister)foundRegister, (ushort)value, StationNumber);
+ return await WriteNumRegister((NRegister)foundRegister, (ushort)value);
}
if (foundRegister.GetType() == typeof(NRegister)) {
- return await WriteNumRegister((NRegister)foundRegister, (int)value, StationNumber);
+ return await WriteNumRegister((NRegister)foundRegister, (int)value);
}
if (foundRegister.GetType() == typeof(NRegister)) {
- return await WriteNumRegister((NRegister)foundRegister, (uint)value, StationNumber);
+ return await WriteNumRegister((NRegister)foundRegister, (uint)value);
}
if (foundRegister.GetType() == typeof(NRegister)) {
- return await WriteNumRegister((NRegister)foundRegister, (float)value, StationNumber);
+ return await WriteNumRegister((NRegister)foundRegister, (float)value);
}
if (foundRegister.GetType() == typeof(NRegister)) {
- return await WriteNumRegister((NRegister)foundRegister, (TimeSpan)value, StationNumber);
+ return await WriteNumRegister((NRegister)foundRegister, (TimeSpan)value);
}
if (foundRegister.GetType() == typeof(SRegister)) {
- return await WriteStringRegister((SRegister)foundRegister, (string)value, StationNumber);
+ return await WriteStringRegister((SRegister)foundRegister, (string)value);
}
diff --git a/MewtocolNet/Mewtocol/MewtocolInterfaceRequests.cs b/MewtocolNet/Mewtocol/MewtocolInterfaceRequests.cs
index 12ced99..9f5cc76 100644
--- a/MewtocolNet/Mewtocol/MewtocolInterfaceRequests.cs
+++ b/MewtocolNet/Mewtocol/MewtocolInterfaceRequests.cs
@@ -8,6 +8,7 @@ using System.Threading.Tasks;
using MewtocolNet.Registers;
using System.Linq;
using System.Globalization;
+using MewtocolNet.Logging;
namespace MewtocolNet {
@@ -51,16 +52,101 @@ namespace MewtocolNet {
#endregion
+ #region Operation mode changing
+
+ ///
+ /// Changes the PLCs operation mode to the given one
+ ///
+ /// The mode to change to
+ /// The success state of the write operation
+ public async Task SetOperationMode (OPMode mode) {
+
+ string modeChar = mode == OPMode.Prog ? "P" : "R";
+
+ string requeststring = $"%{GetStationNumber()}#RM{modeChar}";
+ var result = await SendCommandAsync(requeststring);
+
+ if (result.Success) {
+ Logger.Log($"operation mode was changed to {mode}", LogLevel.Info, this);
+ } else {
+ Logger.Log("Operation mode change failed", LogLevel.Error, this);
+ }
+
+ return result.Success;
+
+ }
+
+ #endregion
+
+ #region Byte range writingv / reading to registers
+
+ ///
+ /// Writes a byte array to a span over multiple registers at once,
+ /// Rembember the plc can only store word so in order to write to a word array
+ /// your byte array should be double the size
+ ///
+ /// /// start address of the array
+ ///
+ ///
+ public async Task WriteByteRange (int start, byte[] byteArr) {
+
+ string byteString = byteArr.BigToMixedEndian().ToHexString();
+ var wordLength = byteArr.Length / 2;
+ if (byteArr.Length % 2 != 0)
+ wordLength++;
+
+ string startStr = start.ToString().PadLeft(5, '0');
+ string endStr = (start + wordLength - 1).ToString().PadLeft(5, '0');
+
+ string requeststring = $"%{GetStationNumber()}#WDD{startStr}{endStr}{byteString}";
+ var result = await SendCommandAsync(requeststring);
+
+ return result.Success;
+
+ }
+
+ ///
+ /// Reads the bytes from the start adress for counts byte length
+ ///
+ /// Start adress
+ /// Number of bytes to get
+ /// A byte array or null of there was an error
+ public async Task ReadByteRange (int start, int count) {
+
+ string startStr = start.ToString().PadLeft(5, '0');
+ var wordLength = count / 2;
+ bool wasOdd = false;
+ if (count % 2 != 0)
+ wordLength++;
+
+ string endStr = (start + wordLength - 1).ToString().PadLeft(5, '0');
+
+ string requeststring = $"%{GetStationNumber()}#RDD{startStr}{endStr}";
+ var result = await SendCommandAsync(requeststring);
+
+ if(result.Success && !string.IsNullOrEmpty(result.Response)) {
+
+ var bytes = result.Response.ParseDTByteString(wordLength * 4).HexStringToByteArray();
+
+ return bytes.BigToMixedEndian().Take(count).ToArray();
+
+ }
+
+ return null;
+
+ }
+
+ #endregion
+
#region Bool register reading / writing
///
/// Reads the given boolean register from the PLC
///
/// The register to read
- /// Station number to access
- public async Task ReadBoolRegister (BRegister _toRead, int _stationNumber = 1) {
+ public async Task ReadBoolRegister (BRegister _toRead) {
- string requeststring = $"%{_stationNumber.ToString().PadLeft(2, '0')}#RCS{_toRead.BuildMewtocolIdent()}";
+ string requeststring = $"%{GetStationNumber()}#RCS{_toRead.BuildMewtocolIdent()}";
var result = await SendCommandAsync(requeststring);
if(!result.Success) {
@@ -88,15 +174,14 @@ namespace MewtocolNet {
/// Writes to the given bool register on the PLC
///
/// The register to write to
- /// Station number to access
/// The success state of the write operation
- public async Task WriteBoolRegister (BRegister _toWrite, bool value, int _stationNumber = 1) {
+ public async Task WriteBoolRegister (BRegister _toWrite, bool value) {
- string requeststring = $"%{_stationNumber.ToString().PadLeft(2, '0')}#WCS{_toWrite.BuildMewtocolIdent()}{(value ? "1" : "0")}";
+ string requeststring = $"%{GetStationNumber()}#WCS{_toWrite.BuildMewtocolIdent()}{(value ? "1" : "0")}";
var result = await SendCommandAsync(requeststring);
- return result.Success && result.Response.StartsWith($"%{ _stationNumber.ToString().PadLeft(2, '0')}#WC");
+ return result.Success && result.Response.StartsWith($"%{ GetStationNumber()}#WC");
}
@@ -111,11 +196,11 @@ namespace MewtocolNet {
/// The register to read
/// Station number to access
/// A result with the given NumberRegister containing the readback value and a result struct
- public async Task> ReadNumRegister (NRegister _toRead, int _stationNumber = 1) {
+ public async Task> ReadNumRegister (NRegister _toRead) {
Type numType = typeof(T);
- string requeststring = $"%{_stationNumber.ToString().PadLeft(2, '0')}#RD{_toRead.BuildMewtocolIdent()}";
+ string requeststring = $"%{GetStationNumber()}#RD{_toRead.BuildMewtocolIdent()}";
var result = await SendCommandAsync(requeststring);
if(!result.Success || string.IsNullOrEmpty(result.Response)) {
@@ -188,7 +273,7 @@ namespace MewtocolNet {
/// The register to write
/// Station number to access
/// The success state of the write operation
- public async Task WriteNumRegister (NRegister _toWrite, T _value, int _stationNumber = 1) {
+ public async Task WriteNumRegister (NRegister _toWrite, T _value) {
byte[] toWriteVal;
Type numType = typeof(T);
@@ -222,11 +307,11 @@ namespace MewtocolNet {
toWriteVal = null;
}
- string requeststring = $"%{_stationNumber.ToString().PadLeft(2, '0')}#WD{_toWrite.BuildMewtocolIdent()}{toWriteVal.ToHexString()}";
+ string requeststring = $"%{GetStationNumber()}#WD{_toWrite.BuildMewtocolIdent()}{toWriteVal.ToHexString()}";
var result = await SendCommandAsync(requeststring);
- return result.Success && result.Response.StartsWith($"%{ _stationNumber.ToString().PadLeft(2, '0')}#WD");
+ return result.Success && result.Response.StartsWith($"%{ GetStationNumber()}#WD");
}
@@ -249,7 +334,7 @@ namespace MewtocolNet {
///
public async Task ReadStringRegister (SRegister _toRead, int _stationNumber = 1) {
- string requeststring = $"%{_stationNumber.ToString().PadLeft(2, '0')}#RD{_toRead.BuildMewtocolIdent()}";
+ string requeststring = $"%{GetStationNumber()}#RD{_toRead.BuildMewtocolIdent()}";
var result = await SendCommandAsync(requeststring);
if (result.Success)
_toRead.SetValueFromPLC(result.Response.ParseDTString());
@@ -273,7 +358,7 @@ namespace MewtocolNet {
throw new ArgumentException("Write string size cannot be longer than reserved string size");
}
- string stationNum = _stationNumber.ToString().PadLeft(2, '0');
+ string stationNum = GetStationNumber();
string dataString = _value.BuildDTString(_toWrite.ReservedSize);
string dataArea = _toWrite.BuildCustomIdent(dataString.Length / 4);
@@ -282,7 +367,18 @@ namespace MewtocolNet {
var result = await SendCommandAsync(requeststring);
- return result.Success && result.Response.StartsWith($"%{ _stationNumber.ToString().PadLeft(2, '0')}#WD");
+ return result.Success && result.Response.StartsWith($"%{ GetStationNumber()}#WD");
+ }
+
+ #endregion
+
+ #region Helpers
+
+ internal string GetStationNumber () {
+
+ return StationNumber.ToString().PadLeft(2, '0');
+
+
}
#endregion
diff --git a/MewtocolNet/Mewtocol/PLCEnums/CpuType.cs b/MewtocolNet/Mewtocol/PLCEnums/CpuType.cs
new file mode 100644
index 0000000..9312177
--- /dev/null
+++ b/MewtocolNet/Mewtocol/PLCEnums/CpuType.cs
@@ -0,0 +1,46 @@
+namespace MewtocolNet {
+
+ ///
+ /// CPU type of the PLC
+ ///
+ public enum CpuType {
+ ///
+ /// FP 0 / FP 2.7K
+ ///
+ FP0_FP1_2_7K,
+ ///
+ /// FP0 / FP1, 5K / 10K
+ ///
+ FP0_FP1_5K_10K,
+ ///
+ /// FP1 M 0.9K
+ ///
+ FP1_M_0_9K,
+ ///
+ /// FP2 16k / 32k
+ ///
+ FP2_16K_32K,
+ ///
+ /// FP3 C 10K
+ ///
+ FP3_C_10K,
+ ///
+ /// FP3 C 16K
+ ///
+ FP3_C_16K,
+ ///
+ /// FP5 16K
+ ///
+ FP5_16K,
+ ///
+ /// FP 5 24K
+ ///
+ FP5_24K,
+ ///
+ /// Includes panasonic FPX, FPX-H, Sigma
+ ///
+ FP_Sigma_X_H_30K_60K_120K
+
+ }
+
+}
\ No newline at end of file
diff --git a/MewtocolNet/Mewtocol/PLCEnums/OPMode.cs b/MewtocolNet/Mewtocol/PLCEnums/OPMode.cs
new file mode 100644
index 0000000..150338c
--- /dev/null
+++ b/MewtocolNet/Mewtocol/PLCEnums/OPMode.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MewtocolNet {
+
+ ///
+ /// CPU type of the PLC
+ ///
+ public enum OPMode {
+ ///
+ /// PLC run mode
+ ///
+ Run,
+ ///
+ /// PLC programming mode
+ ///
+ Prog,
+ }
+
+}
\ No newline at end of file
diff --git a/MewtocolNet/MewtocolNet.csproj b/MewtocolNet/MewtocolNet.csproj
index 9e3221a..368dd07 100644
--- a/MewtocolNet/MewtocolNet.csproj
+++ b/MewtocolNet/MewtocolNet.csproj
@@ -1,11 +1,18 @@
netstandard2.0
- AppLogger
+ MewtocolNet
0.2.5
Felix Weiss
Womed
true
+ A Mewtocol protocol library to interface with Panasonic PLCs over TCP/Serial.
+ Copyright (c) 2022 WOLF Medizintechnik GmbH
+ https://github.com/WOmed/MewtocolNet
+ https://github.com/WOmed/MewtocolNet
+ plc;panasonic;mewtocol;automation;
+ MIT
+ 2ccdcc9b-94a3-4e76-8827-453ab889ea33
C:\Users\Felix Weiß\source\repos\WOmed\MewtocolNet\Builds\MewtocolNet.xml