From eb70dac5a81f250f022c344409a65acbb6a1e01d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Felix=20Wei=C3=9F?=
<72068105+Sandoun@users.noreply.github.com>
Date: Mon, 17 Jul 2023 17:44:20 +0200
Subject: [PATCH] Multiple fixes
---
MewtocolNet/Events/PlcConnectionArgs.cs | 13 ++
MewtocolNet/Events/RegisterChanged.cs | 22 +++
MewtocolNet/Exceptions/MewtocolException.cs | 46 ------
MewtocolNet/Helpers/MewtocolHelpers.cs | 15 +-
MewtocolNet/InternalEnums/DynamicSizeState.cs | 17 --
MewtocolNet/Mewtocol.cs | 33 +++-
MewtocolNet/MewtocolInterface.cs | 84 ++++++----
.../MewtocolInterfaceRegisterHandling.cs | 25 ++-
MewtocolNet/MewtocolInterfaceRequests.cs | 49 +++---
MewtocolNet/MewtocolInterfaceSerial.cs | 14 +-
MewtocolNet/MewtocolInterfaceTcp.cs | 13 +-
MewtocolNet/PLCInfo.cs | 90 ++++++++--
.../RegisterAttributes/StringHintAttribute.cs | 20 +++
MewtocolNet/RegisterBuilding/RBuildBase.cs | 154 ++++++++++--------
MewtocolNet/RegisterBuilding/RBuildMult.cs | 102 ++++++------
.../RegisterBuilding/RegBuilderExtensions.cs | 53 ------
.../RegisterBuilding/RegisterAssembler.cs | 42 ++---
MewtocolNet/Registers/ArrayRegister.cs | 87 ++++++++--
MewtocolNet/Registers/Base/IRegister.cs | 3 +-
MewtocolNet/Registers/Base/Register.cs | 12 +-
MewtocolNet/Registers/SingleRegister.cs | 104 +++++-------
MewtocolNet/TypeConversion/Conversions.cs | 9 +-
MewtocolNet/TypeConversion/PlcValueParser.cs | 13 +-
.../TypeConversion/PlcVarTypeConversions.cs | 7 +-
MewtocolNet/UnderlyingRegisters/DTArea.cs | 18 --
.../UnderlyingRegisters/MemoryAreaManager.cs | 29 +---
26 files changed, 584 insertions(+), 490 deletions(-)
create mode 100644 MewtocolNet/Events/PlcConnectionArgs.cs
create mode 100644 MewtocolNet/Events/RegisterChanged.cs
delete mode 100644 MewtocolNet/Exceptions/MewtocolException.cs
delete mode 100644 MewtocolNet/InternalEnums/DynamicSizeState.cs
create mode 100644 MewtocolNet/RegisterAttributes/StringHintAttribute.cs
diff --git a/MewtocolNet/Events/PlcConnectionArgs.cs b/MewtocolNet/Events/PlcConnectionArgs.cs
new file mode 100644
index 0000000..2409f3b
--- /dev/null
+++ b/MewtocolNet/Events/PlcConnectionArgs.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace MewtocolNet.Events {
+
+ public delegate void PlcConnectionEventHandler(object sender, PlcConnectionArgs e);
+
+ public class PlcConnectionArgs : EventArgs {
+
+
+
+ }
+
+}
diff --git a/MewtocolNet/Events/RegisterChanged.cs b/MewtocolNet/Events/RegisterChanged.cs
new file mode 100644
index 0000000..e5e14cf
--- /dev/null
+++ b/MewtocolNet/Events/RegisterChanged.cs
@@ -0,0 +1,22 @@
+using MewtocolNet.Registers;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MewtocolNet.Events {
+
+ public delegate void RegisterChangedEventHandler(object sender, RegisterChangedArgs e);
+
+ public class RegisterChangedArgs : EventArgs {
+
+ public IRegister Register { get; internal set; }
+
+ public object Value { get; internal set; }
+
+ public object PreviousValue { get; internal set; }
+
+ public string PreviousValueString { get; internal set; }
+
+ }
+
+}
diff --git a/MewtocolNet/Exceptions/MewtocolException.cs b/MewtocolNet/Exceptions/MewtocolException.cs
deleted file mode 100644
index 40b8c2c..0000000
--- a/MewtocolNet/Exceptions/MewtocolException.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-using MewtocolNet.Registers;
-using System;
-
-namespace MewtocolNet.Exceptions {
-
- [Serializable]
- public class MewtocolException : Exception {
-
- public MewtocolException() { }
-
- public MewtocolException(string message) : base(message) { }
-
- public MewtocolException(string message, Exception inner) : base(message, inner) { }
-
- protected MewtocolException(
- System.Runtime.Serialization.SerializationInfo info,
- System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
-
- internal static MewtocolException NotConnectedSend() {
-
- return new MewtocolException($"Can not send a message to the PLC if it isn't connected");
-
- }
-
- internal static MewtocolException DupeRegister(Register register) {
-
- return new MewtocolException($"The mewtocol interface already contains this register: {register.GetMewName()}");
-
- }
-
- internal static MewtocolException DupeNameRegister(Register register) {
-
- return new MewtocolException($"The mewtocol interface registers already contains a register with the name: {register.GetMewName()}");
-
- }
-
- internal static MewtocolException OverlappingRegister(Register registerA, Register registerB) {
-
- return new MewtocolException($"The register: {registerA.GetRegisterWordRangeString()} " +
- $"has overlapping addresses with: {registerB.GetRegisterWordRangeString()}");
-
- }
-
- }
-
-}
diff --git a/MewtocolNet/Helpers/MewtocolHelpers.cs b/MewtocolNet/Helpers/MewtocolHelpers.cs
index 0cb7bf4..78d3844 100644
--- a/MewtocolNet/Helpers/MewtocolHelpers.cs
+++ b/MewtocolNet/Helpers/MewtocolHelpers.cs
@@ -19,14 +19,16 @@ namespace MewtocolNet {
#region Byte and string operation helpers
- public static int DetermineTypeByteSize(this Type type) {
+ public static int DetermineTypeByteIntialSize(this Type type) {
//enums can only be of numeric types
if (type.IsEnum) return Marshal.SizeOf(Enum.GetUnderlyingType(type));
//strings get always set with 4 bytes because the first 4 bytes contain the length
if (type == typeof(string)) return 4;
-
+ if (type == typeof(TimeSpan)) return 4;
+ if (type == typeof(DateTime)) return 4;
+
if (type.Namespace.StartsWith("System")) return Marshal.SizeOf(type);
if (typeof(MewtocolExtTypeInit1Word).IsAssignableFrom(type)) return 2;
@@ -157,6 +159,15 @@ namespace MewtocolNet {
}
+ public static string Ellipsis(this string str, int maxLength) {
+
+ if (string.IsNullOrEmpty(str) || str.Length <= maxLength)
+ return str;
+
+ return $"{str.Substring(0, maxLength - 3)}...";
+
+ }
+
///
/// Converts a hex string (AB01C1) to a byte array
///
diff --git a/MewtocolNet/InternalEnums/DynamicSizeState.cs b/MewtocolNet/InternalEnums/DynamicSizeState.cs
deleted file mode 100644
index bdba8e6..0000000
--- a/MewtocolNet/InternalEnums/DynamicSizeState.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace MewtocolNet {
-
- [Flags]
- internal enum DynamicSizeState {
-
- None = 0,
- DynamicallySized = 1,
- NeedsSizeUpdate = 2,
- WasSizeUpdated = 4,
-
- }
-
-}
diff --git a/MewtocolNet/Mewtocol.cs b/MewtocolNet/Mewtocol.cs
index 5e8e44f..3057d37 100644
--- a/MewtocolNet/Mewtocol.cs
+++ b/MewtocolNet/Mewtocol.cs
@@ -1,11 +1,12 @@
-using MewtocolNet.Exceptions;
-using MewtocolNet.RegisterAttributes;
+using MewtocolNet.RegisterAttributes;
+using MewtocolNet.RegisterBuilding;
using MewtocolNet.SetupClasses;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Net;
+using System.Threading.Tasks;
namespace MewtocolNet {
@@ -96,7 +97,7 @@ namespace MewtocolNet {
var portnames = SerialPort.GetPortNames();
if (!portnames.Any(x => x == portName))
- throw new MewtocolException($"The port {portName} is no valid port");
+ throw new NotSupportedException($"The port {portName} is no valid port");
}
@@ -265,6 +266,32 @@ namespace MewtocolNet {
}
+ ///
+ /// A builder for attaching register collections
+ ///
+ public PostInit WithRegisters(Action builder) {
+
+ try {
+
+ var plc = (MewtocolInterface)(object)intf;
+ var assembler = new RegisterAssembler(plc);
+ var regBuilder = new RBuildMult(plc);
+
+ builder.Invoke(regBuilder);
+
+ var registers = assembler.AssembleAll(regBuilder);
+ plc.AddRegisters(registers.ToArray());
+
+ return this;
+
+ } catch {
+
+ throw;
+
+ }
+
+ }
+
///
/// Builds and returns the final plc interface
///
diff --git a/MewtocolNet/MewtocolInterface.cs b/MewtocolNet/MewtocolInterface.cs
index 4a15561..10dbc26 100644
--- a/MewtocolNet/MewtocolInterface.cs
+++ b/MewtocolNet/MewtocolInterface.cs
@@ -1,4 +1,5 @@
-using MewtocolNet.Helpers;
+using MewtocolNet.Events;
+using MewtocolNet.Helpers;
using MewtocolNet.Logging;
using MewtocolNet.Registers;
using MewtocolNet.UnderlyingRegisters;
@@ -17,6 +18,22 @@ namespace MewtocolNet {
public abstract partial class MewtocolInterface : IPlc {
+ #region Events
+
+ ///
+ public event PlcConnectionEventHandler Connected;
+
+ ///
+ public event PlcConnectionEventHandler Disconnected;
+
+ ///
+ public event RegisterChangedEventHandler RegisterChanged;
+
+ ///
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ #endregion
+
#region Private fields
private protected Stream stream;
@@ -40,6 +57,7 @@ namespace MewtocolNet {
private protected Stopwatch speedStopwatchDownstr;
private protected Task firstPollTask = new Task(() => { });
+ private protected bool wasInitialStatusReceived;
private protected MewtocolVersion mewtocolVersion;
#endregion
@@ -56,18 +74,6 @@ namespace MewtocolNet {
#region Public Read Only Properties / Fields
- ///
- public event Action Connected;
-
- ///
- public event Action Disconnected;
-
- ///
- public event Action RegisterChanged;
-
- ///
- public event PropertyChangedEventHandler PropertyChanged;
-
///
public bool Disposed { get; private set; }
@@ -143,7 +149,7 @@ namespace MewtocolNet {
Connected += MewtocolInterface_Connected;
RegisterChanged += OnRegisterChanged;
- void MewtocolInterface_Connected(PLCInfo obj) {
+ void MewtocolInterface_Connected(object sender, PlcConnectionArgs args) {
if (usePoller)
AttachPoller();
@@ -154,29 +160,48 @@ namespace MewtocolNet {
}
- private void OnRegisterChanged(IRegister o) {
+ private void OnRegisterChanged(object sender, RegisterChangedArgs args) {
- var asInternal = (Register)o;
+ var asInternal = (Register)args.Register;
+
+ //log
+ if(IsConnected) {
+
+ var sb = new StringBuilder();
+
+ sb.Append(asInternal.GetMewName());
+ if (asInternal.Name != null) {
+ sb.Append(asInternal.autoGenerated ? $" (Auto)" : $" ({asInternal.Name})");
+ }
+ sb.Append($" {asInternal.underlyingSystemType.Name}");
+ sb.Append($" changed \"{args.PreviousValueString.Ellipsis(25)}\"" +
+ $" => \"{asInternal.GetValueString().Ellipsis(75)}\"");
+
+ Logger.Log(sb.ToString(), LogLevel.Change, this);
- var sb = new StringBuilder();
- sb.Append(asInternal.GetMewName());
- if (asInternal.Name != null) {
- sb.Append(asInternal.autoGenerated ? $" (Auto)" : $" ({o.Name})");
}
- sb.Append($" {asInternal.underlyingSystemType.Name}");
- sb.Append($" changed to \"{asInternal.GetValueString()}\"");
- Logger.Log(sb.ToString(), LogLevel.Change, this);
-
- OnRegisterChangedUpdateProps((Register)o);
+ OnRegisterChangedUpdateProps(asInternal);
}
///
public virtual async Task ConnectAsync() {
+ isConnectingStage = false;
+
await memoryManager.OnPlcConnected();
+ Logger.Log($"PLC: {PlcInfo.TypeName}", LogLevel.Verbose, this);
+ Logger.Log($"TYPE CODE: {PlcInfo.TypeCode.ToString("X")}", LogLevel.Verbose, this);
+ Logger.Log($"OP MODE: {PlcInfo.OperationMode}", LogLevel.Verbose, this);
+ Logger.Log($"PROG CAP: {PlcInfo.ProgramCapacity}k", LogLevel.Verbose, this);
+ Logger.Log($"HW INFO: {PlcInfo.HardwareInformation}", LogLevel.Verbose, this);
+ Logger.Log($"DIAG ERR: {PlcInfo.SelfDiagnosticError}", LogLevel.Verbose, this);
+ Logger.Log($"CPU VER: {PlcInfo.CpuVersion}", LogLevel.Verbose, this);
+
+ Logger.Log($">> Intial connection end <<", LogLevel.Verbose, this);
+
}
///
@@ -220,6 +245,9 @@ namespace MewtocolNet {
///
public async Task SendCommandAsync(string _msg, bool withTerminator = true, int timeoutMs = -1, Action onReceiveProgress = null) {
+ if (!IsConnected && !isConnectingStage)
+ throw new NotSupportedException("The device must be connected to send a message");
+
//send request
queuedMessages++;
@@ -468,11 +496,10 @@ namespace MewtocolNet {
private protected virtual void OnConnected(PLCInfo plcinf) {
Logger.Log("Connected to PLC", LogLevel.Info, this);
- Logger.Log($"{plcinf.ToString()}", LogLevel.Verbose, this);
IsConnected = true;
- Connected?.Invoke(plcinf);
+ Connected?.Invoke(this, new PlcConnectionArgs());
if (!usePoller) {
firstPollTask.RunSynchronously();
@@ -493,11 +520,12 @@ namespace MewtocolNet {
BytesPerSecondDownstream = 0;
BytesPerSecondUpstream = 0;
PollerCycleDurationMs = 0;
+ PlcInfo = null;
IsConnected = false;
ClearRegisterVals();
- Disconnected?.Invoke();
+ Disconnected?.Invoke(this, new PlcConnectionArgs());
KillPoller();
}
diff --git a/MewtocolNet/MewtocolInterfaceRegisterHandling.cs b/MewtocolNet/MewtocolInterfaceRegisterHandling.cs
index b79d981..17d962b 100644
--- a/MewtocolNet/MewtocolInterfaceRegisterHandling.cs
+++ b/MewtocolNet/MewtocolInterfaceRegisterHandling.cs
@@ -1,4 +1,5 @@
-using MewtocolNet.Logging;
+using MewtocolNet.Events;
+using MewtocolNet.Logging;
using MewtocolNet.RegisterAttributes;
using MewtocolNet.RegisterBuilding;
using MewtocolNet.Registers;
@@ -210,19 +211,19 @@ namespace MewtocolNet {
if (attr is RegisterAttribute cAttribute) {
var pollFreqAttr = (PollLevelAttribute)attributes.FirstOrDefault(x => x.GetType() == typeof(PollLevelAttribute));
+ var stringHintAttr = (StringHintAttribute)attributes.FirstOrDefault(x => x.GetType() == typeof(StringHintAttribute));
var dotnetType = prop.PropertyType;
int pollLevel = 1;
+ uint? byteHint = (uint?)stringHintAttr?.size;
if (pollFreqAttr != null) pollLevel = pollFreqAttr.pollLevel;
//add builder item
var stp1 = regBuild
- .AddressFromAttribute(cAttribute.MewAddress, cAttribute.TypeDef)
+ .AddressFromAttribute(cAttribute.MewAddress, cAttribute.TypeDef, collection, prop, byteHint)
.AsType(dotnetType.IsEnum ? dotnetType.UnderlyingSystemType : dotnetType)
- .PollLevel(pollLevel)
- .RegCollection(collection)
- .BoundProp(prop);
+ .PollLevel(pollLevel);
}
@@ -235,7 +236,7 @@ namespace MewtocolNet {
collection.OnInterfaceLinked(this);
}
- Connected += (i) => {
+ Connected += (s,e) => {
if (collection != null)
collection.OnInterfaceLinkedAndOnline(this);
};
@@ -280,6 +281,9 @@ namespace MewtocolNet {
memoryManager.LinkAndMergeRegisters(registers);
+ //run a second iteration
+ //memoryManager.LinkAndMergeRegisters();
+
}
private bool CheckDuplicateRegister(Register instance, out Register foundDupe) {
@@ -383,9 +387,14 @@ namespace MewtocolNet {
}
- internal void InvokeRegisterChanged(Register reg) {
+ internal void InvokeRegisterChanged(Register reg, object preValue, string preValueString) {
- RegisterChanged?.Invoke(reg);
+ RegisterChanged?.Invoke(this, new RegisterChangedArgs {
+ Register = reg,
+ PreviousValue = preValue,
+ PreviousValueString = preValueString,
+ Value = reg.Value,
+ });
}
diff --git a/MewtocolNet/MewtocolInterfaceRequests.cs b/MewtocolNet/MewtocolInterfaceRequests.cs
index 37054c9..7b6c6f2 100644
--- a/MewtocolNet/MewtocolInterfaceRequests.cs
+++ b/MewtocolNet/MewtocolInterfaceRequests.cs
@@ -1,14 +1,16 @@
-using MewtocolNet.Exceptions;
using MewtocolNet.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Net.Sockets;
using System.Threading.Tasks;
namespace MewtocolNet {
public abstract partial class MewtocolInterface {
+ internal bool isConnectingStage = false;
+
internal int maxDataBlocksPerWrite = 8;
#region PLC info getters
@@ -17,20 +19,26 @@ namespace MewtocolNet {
/// Gets generic information about the PLC
///
/// A PLCInfo class
- public async Task GetPLCInfoAsync(int timeout = -1) {
+ public async Task GetPLCInfoAsync(int timeout = -1) {
- var resRT = await SendCommandAsync("%EE#RT", timeoutMs: timeout);
+ MewtocolFrameResponse resRT = await SendCommandAsync("%EE#RT", timeoutMs: timeout);
if (!resRT.Success) {
- //timeouts are ok and dont throw
+ //timeouts are ok and don't throw
if (resRT == MewtocolFrameResponse.Timeout) return null;
- throw new MewtocolException(resRT.Error);
+ throw new Exception(resRT.Error);
}
- var resEXRT = await SendCommandAsync("%EE#EX00RT00", timeoutMs: timeout);
+ MewtocolFrameResponse? resEXRT = null;
+
+ if(isConnectingStage) {
+
+ resEXRT = await SendCommandAsync("%EE#EX00RT00", timeoutMs: timeout);
+
+ }
//timeouts are ok and dont throw
if (!resRT.Success && resRT == MewtocolFrameResponse.Timeout) return null;
@@ -40,20 +48,27 @@ namespace MewtocolNet {
//dont overwrite, use first
if (!PLCInfo.TryFromRT(resRT.Response, out plcInf)) {
- throw new MewtocolException("The RT message could not be parsed");
+ throw new Exception("The RT message could not be parsed");
}
- //overwrite first with EXRT
- if (resEXRT.Success && !plcInf.TryExtendFromEXRT(resEXRT.Response)) {
+ //overwrite first with EXRT only on connecting stage
+ if (isConnectingStage && resEXRT != null && resEXRT.Value.Success && !plcInf.TryExtendFromEXRT(resEXRT.Value.Response)) {
- throw new MewtocolException("The EXRT message could not be parsed");
+ throw new Exception("The EXRT message could not be parsed");
+ }
+
+ if(isConnectingStage) {
+ //set the intial obj
+ PlcInfo = plcInf;
+ } else {
+ //update the obj with RT dynamic values only
+ PlcInfo.SelfDiagnosticError = plcInf.SelfDiagnosticError;
+ PlcInfo.OperationMode = plcInf.OperationMode;
}
- PlcInfo = plcInf;
-
- return plcInf;
+ return PlcInfo;
}
@@ -93,9 +108,6 @@ namespace MewtocolNet {
///
public async Task WriteByteRange(int start, byte[] byteArr) {
- if (!IsConnected)
- throw MewtocolException.NotConnectedSend();
-
string byteString = byteArr.ToHexString();
var wordLength = byteArr.Length / 2;
@@ -121,11 +133,6 @@ namespace MewtocolNet {
/// A byte array of the requested DT area
public async Task ReadByteRangeNonBlocking(int start, int byteCount, Action onProgress = null) {
- if (!IsConnected)
- throw MewtocolException.NotConnectedSend();
-
- onProgress += (p) => Console.WriteLine($"{p * 100:N2}%");
-
//on odd bytes add one word
var wordLength = byteCount / 2;
if (byteCount % 2 != 0) wordLength++;
diff --git a/MewtocolNet/MewtocolInterfaceSerial.cs b/MewtocolNet/MewtocolInterfaceSerial.cs
index 0068424..47a91c2 100644
--- a/MewtocolNet/MewtocolInterfaceSerial.cs
+++ b/MewtocolNet/MewtocolInterfaceSerial.cs
@@ -113,7 +113,10 @@ namespace MewtocolNet {
try {
- PLCInfo? gotInfo = null;
+ Logger.Log($">> Intial connection start <<", LogLevel.Verbose, this);
+ isConnectingStage = true;
+
+ PLCInfo gotInfo = null;
if (autoSerial) {
@@ -129,8 +132,9 @@ namespace MewtocolNet {
if (gotInfo != null) {
+ IsConnected = true;
await base.ConnectAsync();
- OnConnected(gotInfo.Value);
+ OnConnected(gotInfo);
} else {
@@ -145,13 +149,15 @@ namespace MewtocolNet {
OnMajorSocketExceptionWhileConnecting();
+ isConnectingStage = false;
+
}
tryingSerialConfig -= OnTryConfig;
}
- private async Task TryConnectAsyncMulti() {
+ private async Task TryConnectAsyncMulti() {
var baudRates = Enum.GetValues(typeof(BaudRate)).Cast();
@@ -197,7 +203,7 @@ namespace MewtocolNet {
}
- private async Task TryConnectAsyncSingle(string port, int baud, int dbits, Parity par, StopBits sbits) {
+ private async Task TryConnectAsyncSingle(string port, int baud, int dbits, Parity par, StopBits sbits) {
try {
diff --git a/MewtocolNet/MewtocolInterfaceTcp.cs b/MewtocolNet/MewtocolInterfaceTcp.cs
index 4a7269b..b3bb648 100644
--- a/MewtocolNet/MewtocolInterfaceTcp.cs
+++ b/MewtocolNet/MewtocolInterfaceTcp.cs
@@ -1,4 +1,3 @@
-using MewtocolNet.Exceptions;
using MewtocolNet.Logging;
using System;
using System.Net;
@@ -34,7 +33,7 @@ namespace MewtocolNet {
public void ConfigureConnection(string ip, int port = 9094, int station = 0xEE) {
if (!IPAddress.TryParse(ip, out ipAddr))
- throw new MewtocolException($"The ip: {ip} is no valid ip address");
+ throw new NotSupportedException($"The ip: {ip} is no valid ip address");
if (stationNumber != 0xEE && stationNumber > 99)
throw new NotSupportedException("Station number can't be greater than 99");
@@ -66,6 +65,9 @@ namespace MewtocolNet {
try {
+ Logger.Log($">> Intial connection start <<", LogLevel.Verbose, this);
+ isConnectingStage = true;
+
if (HostEndpoint != null) {
client = new TcpClient(HostEndpoint) {
@@ -109,9 +111,9 @@ namespace MewtocolNet {
if (plcinf != null) {
+ IsConnected = true;
await base.ConnectAsync();
-
- OnConnected(plcinf.Value);
+ OnConnected(plcinf);
} else {
@@ -125,8 +127,9 @@ namespace MewtocolNet {
} catch (SocketException) {
OnMajorSocketExceptionWhileConnecting();
+ isConnectingStage = false;
- }
+ }
}
diff --git a/MewtocolNet/PLCInfo.cs b/MewtocolNet/PLCInfo.cs
index 6b0e9fd..e32ea34 100644
--- a/MewtocolNet/PLCInfo.cs
+++ b/MewtocolNet/PLCInfo.cs
@@ -1,4 +1,6 @@
-using System.Globalization;
+using System.ComponentModel;
+using System.Globalization;
+using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
namespace MewtocolNet {
@@ -6,43 +8,85 @@ namespace MewtocolNet {
///
/// Holds various informations about the PLC
///
- public struct PLCInfo {
+ public class PLCInfo : INotifyPropertyChanged {
+ private PlcType typeCode;
+ private string typeName;
+ private OPMode operationMode;
+ private HWInformation hardwareInformation;
+ private string selfDiagnosticError;
+
///
/// The type of the PLC named by Panasonic
///
- public PlcType TypeCode { get; private set; }
+ public PlcType TypeCode {
+ get => typeCode;
+ internal set {
+ typeCode = value;
+ OnPropChange();
+ //update name
+ typeName = typeCode.ToName();
+ OnPropChange(nameof(TypeName));
+ }
+ }
///
- /// Contains information about the PLCs operation modes as flags
+ /// The full qualified name of the PLC
///
- public OPMode OperationMode { get; private set; }
-
- ///
- /// Hardware information flags about the PLC
- ///
- public HWInformation HardwareInformation { get; private set; }
+ public string TypeName => typeName;
///
/// Program capacity in 1K steps
///
- public int ProgramCapacity { get; private set; }
+ public int ProgramCapacity { get; internal set; }
///
/// Version of the cpu
///
- public string CpuVersion { get; private set; }
+ public string CpuVersion { get; internal set; }
+
+ ///
+ /// Contains information about the PLCs operation modes as flags
+ ///
+ public OPMode OperationMode {
+ get => operationMode;
+ internal set {
+ operationMode = value;
+ OnPropChange();
+ OnPropChange(nameof(IsRunMode));
+ }
+ }
+
+ ///
+ /// Hardware information flags about the PLC
+ ///
+ public HWInformation HardwareInformation {
+ get => hardwareInformation;
+ internal set {
+ hardwareInformation = value;
+ OnPropChange();
+
+ }
+ }
///
/// Current error code of the PLC
///
- public string SelfDiagnosticError { get; internal set; }
+ public string SelfDiagnosticError {
+ get => selfDiagnosticError;
+ internal set {
+ selfDiagnosticError = value;
+ OnPropChange();
+ }
+ }
///
/// Quickcheck for the runmode flag
///
public bool IsRunMode => OperationMode.HasFlag(OPMode.RunMode);
+ public event PropertyChangedEventHandler PropertyChanged;
+
internal bool TryExtendFromEXRT(string msg) {
var regexEXRT = new Regex(@"\%EE\$EX00RT00(?..)(?..)..(?..)(?..)..(?..)(?....)(?..)(?..)(?.)(?....)(?....)(?....).*", RegexOptions.IgnoreCase);
@@ -114,7 +158,25 @@ namespace MewtocolNet {
public override string ToString() {
- return $"{TypeCode.ToName()}, OP: {OperationMode}";
+ return $"{TypeName}, OP: {OperationMode}";
+
+ }
+
+ public override bool Equals(object obj) {
+
+ if ((obj == null) || !this.GetType().Equals(obj.GetType())) {
+ return false;
+ } else {
+ return (PLCInfo)obj == this;
+ }
+
+ }
+
+ public override int GetHashCode() => GetHashCode();
+
+ private protected void OnPropChange([CallerMemberName] string propertyName = null) {
+
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
diff --git a/MewtocolNet/RegisterAttributes/StringHintAttribute.cs b/MewtocolNet/RegisterAttributes/StringHintAttribute.cs
new file mode 100644
index 0000000..f7ab9b3
--- /dev/null
+++ b/MewtocolNet/RegisterAttributes/StringHintAttribute.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace MewtocolNet.RegisterAttributes {
+ ///
+ /// Defines a string size hint
+ ///
+ [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
+ public class StringHintAttribute : Attribute {
+
+ internal int size;
+
+ public StringHintAttribute(int size) {
+
+ this.size = size;
+
+ }
+
+ }
+
+}
diff --git a/MewtocolNet/RegisterBuilding/RBuildBase.cs b/MewtocolNet/RegisterBuilding/RBuildBase.cs
index 9db4803..97d6ca2 100644
--- a/MewtocolNet/RegisterBuilding/RBuildBase.cs
+++ b/MewtocolNet/RegisterBuilding/RBuildBase.cs
@@ -305,7 +305,7 @@ namespace MewtocolNet.RegisterBuilding {
///
///
///
- public TempRegister AsType(int? sizeHint = null) {
+ public TypedRegister AsType() {
if (!typeof(T).IsAllowedPlcCastingType()) {
@@ -313,10 +313,9 @@ namespace MewtocolNet.RegisterBuilding {
}
- Data.byteSizeHint = (uint?)sizeHint;
Data.dotnetVarType = typeof(T);
- return new TempRegister(Data, builder);
+ return new TypedRegister().Map(this);
}
@@ -327,7 +326,7 @@ namespace MewtocolNet.RegisterBuilding {
///
///
///
- public TempRegister AsType(Type type) {
+ public TypedRegister AsType(Type type) {
//was ranged syntax array build
if (Data.wasAddressStringRangeBased && type.IsArray && type.GetArrayRank() == 1) {
@@ -344,14 +343,14 @@ namespace MewtocolNet.RegisterBuilding {
}
- int byteSizePerItem = elementType.DetermineTypeByteSize();
+ int byteSizePerItem = elementType.DetermineTypeByteIntialSize();
//check if it fits without remainder
if (Data.byteSizeHint % byteSizePerItem != 0) {
throw new NotSupportedException($"The array element type {elementType} doesn't fit into the adress range");
}
- return (TempRegister)generic.Invoke(this, new object[] {
+ return (TypedRegister)generic.Invoke(this, new object[] {
//element count
new int[] { (int)((Data.byteSizeHint / byteSizePerItem)) }
});
@@ -369,9 +368,9 @@ namespace MewtocolNet.RegisterBuilding {
return AsType(Data.typeDef);
- } else if ((type.IsArray || type == typeof(string)) && Data.typeDef == null) {
+ } else if (type.IsArray && Data.typeDef == null) {
- throw new NotSupportedException("Typedef parameter is needed for array or string types");
+ throw new NotSupportedException("Typedef parameter is needed for array types");
} else if (Data.typeDef != null) {
@@ -389,18 +388,18 @@ namespace MewtocolNet.RegisterBuilding {
Data.dotnetVarType = type;
- return new TempRegister(Data, builder);
+ return new TypedRegister().Map(this);
}
///
/// Sets the register type as a predefined
///
- public TempRegister AsType(PlcVarType type) {
+ public TypedRegister AsType(PlcVarType type) {
Data.dotnetVarType = type.GetDefaultDotnetType();
- return new TempRegister(Data, builder);
+ return new TypedRegister().Map(this);
}
@@ -421,10 +420,13 @@ namespace MewtocolNet.RegisterBuilding {
/// - DWORD32 bit double word interpreted as
///
///
- public TempRegister AsType(string type) {
+ public TypedRegister AsType(string type) {
- var stringMatch = Regex.Match(type, @"STRING *\[(?[0-9]*)\]", RegexOptions.IgnoreCase);
- var arrayMatch = Regex.Match(type, @"ARRAY *\[(?[0-9]*)..(?[0-9]*)(?:\,(?[0-9]*)..(?[0-9]*))?(?:\,(?[0-9]*)..(?[0-9]*))?\] *OF {1,}(?.*)", RegexOptions.IgnoreCase);
+ var regexString = new Regex(@"^STRING *\[(?[0-9]*)\]$", RegexOptions.IgnoreCase);
+ var regexArray = new Regex(@"^ARRAY *\[(?[0-9]*)..(?[0-9]*)(?:\,(?[0-9]*)..(?[0-9]*))?(?:\,(?[0-9]*)..(?[0-9]*))?\] *OF {1,}(?.*)$", RegexOptions.IgnoreCase);
+
+ var stringMatch = regexString.Match(type);
+ var arrayMatch = regexArray.Match(type);
if (Enum.TryParse(type, out var parsed)) {
@@ -440,52 +442,63 @@ namespace MewtocolNet.RegisterBuilding {
//invoke generic AsTypeArray
string arrTypeString = arrayMatch.Groups["t"].Value;
+ Type dotnetArrType = null;
- if (Enum.TryParse(arrTypeString, out var parsedArrType)) {
+ var stringMatchInArray = regexString.Match(arrTypeString);
- var dotnetArrType = parsedArrType.GetDefaultDotnetType();
- var indices = new List();
+ if (Enum.TryParse(arrTypeString, out var parsedArrType) && parsedArrType != PlcVarType.STRING) {
- for (int i = 1; i < 4; i++) {
+ dotnetArrType = parsedArrType.GetDefaultDotnetType();
- var arrStart = arrayMatch.Groups[$"S{i}"]?.Value;
- var arrEnd = arrayMatch.Groups[$"E{i}"]?.Value;
- if (string.IsNullOrEmpty(arrStart) || string.IsNullOrEmpty(arrEnd)) break;
- var arrStartInt = int.Parse(arrStart);
- var arrEndInt = int.Parse(arrEnd);
+ } else if (stringMatchInArray.Success) {
- indices.Add(arrEndInt - arrStartInt + 1);
-
- }
-
- var arr = Array.CreateInstance(dotnetArrType, indices.ToArray());
- var arrType = arr.GetType();
-
- MethodInfo method = typeof(SAddress).GetMethod(nameof(AsTypeArray));
- MethodInfo generic = method.MakeGenericMethod(arrType);
-
- var tmp = (TempRegister)generic.Invoke(this, new object[] {
- indices.ToArray()
- });
-
- tmp.builder = builder;
- tmp.Data = Data;
-
- return tmp;
+ dotnetArrType = typeof(string);
+ //Data.byteSizeHint = uint.Parse(stringMatch.Groups["len"].Value);
} else {
throw new NotSupportedException($"The FP type '{arrTypeString}' was not recognized");
+
}
+ var indices = new List();
+
+ for (int i = 1; i < 4; i++) {
+
+ var arrStart = arrayMatch.Groups[$"S{i}"]?.Value;
+ var arrEnd = arrayMatch.Groups[$"E{i}"]?.Value;
+ if (string.IsNullOrEmpty(arrStart) || string.IsNullOrEmpty(arrEnd)) break;
+
+ var arrStartInt = int.Parse(arrStart);
+ var arrEndInt = int.Parse(arrEnd);
+
+ indices.Add(arrEndInt - arrStartInt + 1);
+
+ }
+
+ var arr = Array.CreateInstance(dotnetArrType, indices.ToArray());
+ var arrType = arr.GetType();
+
+ MethodInfo method = typeof(SAddress).GetMethod(nameof(AsTypeArray));
+ MethodInfo generic = method.MakeGenericMethod(arrType);
+
+ var tmp = (TypedRegister)generic.Invoke(this, new object[] {
+ indices.ToArray()
+ });
+
+ tmp.builder = builder;
+ tmp.Data = Data;
+
+ return tmp;
+
} else {
throw new NotSupportedException($"The FP type '{type}' was not recognized");
}
- return new TempRegister(Data, builder);
+ return new TypedRegister().Map(this);
}
@@ -507,7 +520,7 @@ namespace MewtocolNet.RegisterBuilding {
/// ARRAY [0..2, 0..3, 0..4] OF INT = AsTypeArray<short[,,]>(3,4,5)
/// ARRAY [5..6, 0..2] OF DWORD = AsTypeArray<DWord[,]>(2, 3)
///
- public TempRegister AsTypeArray(params int[] indicies) {
+ public TypedRegister AsTypeArray(params int[] indicies) {
if (!typeof(T).IsArray)
throw new NotSupportedException($"The type {typeof(T)} was no array");
@@ -526,7 +539,7 @@ namespace MewtocolNet.RegisterBuilding {
Data.dotnetVarType = typeof(T);
- int byteSizePerItem = elBaseType.DetermineTypeByteSize();
+ int byteSizePerItem = elBaseType.DetermineTypeByteIntialSize();
int calcedTotalByteSize = indicies.Aggregate((a, x) => a * x) * byteSizePerItem;
Data.byteSizeHint = (uint)calcedTotalByteSize;
@@ -536,7 +549,31 @@ namespace MewtocolNet.RegisterBuilding {
throw new NotSupportedException($"The array element type {elBaseType} doesn't fit into the adress range");
}
- return new TempRegister(Data, builder);
+ return new TypedRegister().Map(this);
+
+ }
+
+ }
+
+ #endregion
+
+ #region Typing size hint
+
+ public class TypedRegister : SBase {
+
+ public OptionsRegister SizeHint(int hint) {
+
+ Data.byteSizeHint = (uint)hint;
+
+ return new OptionsRegister().Map(this);
+
+ }
+
+ public OptionsRegister PollLevel(int level) {
+
+ Data.pollLevel = level;
+
+ return new OptionsRegister().Map(this);
}
@@ -546,37 +583,20 @@ namespace MewtocolNet.RegisterBuilding {
#region Options stage
- public class TempRegister : SBase {
+ public class OptionsRegister : SBase {
- internal TempRegister() { }
+ internal OptionsRegister() { }
- internal TempRegister(StepData data, RBuildBase bldr) : base(data, bldr) { }
+ internal OptionsRegister(StepData data, RBuildBase bldr) : base(data, bldr) { }
///
/// Sets the poll level of the register
///
- public TempRegister PollLevel(int level) {
+ public OptionsRegister PollLevel(int level) {
Data.pollLevel = level;
- return this;
- }
-
- }
-
- public class TempRegister : SBase {
-
- internal TempRegister() { }
-
- internal TempRegister(StepData data, RBuildBase bldr) : base(data, bldr) { }
-
- ///
- /// Sets the poll level of the register
- ///
- public TempRegister PollLevel(int level) {
-
- Data.pollLevel = level;
- return this;
+ return this;
}
diff --git a/MewtocolNet/RegisterBuilding/RBuildMult.cs b/MewtocolNet/RegisterBuilding/RBuildMult.cs
index c832669..84613ba 100644
--- a/MewtocolNet/RegisterBuilding/RBuildMult.cs
+++ b/MewtocolNet/RegisterBuilding/RBuildMult.cs
@@ -34,11 +34,16 @@ namespace MewtocolNet.RegisterBuilding {
}
//internal use only, adds a type definition (for use when building from attibute)
- internal SAddress AddressFromAttribute(string plcAddrName, string typeDef) {
+ internal SAddress AddressFromAttribute(string plcAddrName, string typeDef, RegisterCollection regCol, PropertyInfo prop, uint? bytesizeHint = null) {
var built = Address(plcAddrName);
+
built.Data.typeDef = typeDef;
built.Data.buildSource = RegisterBuildSource.Attribute;
+ built.Data.regCollection = regCol;
+ built.Data.boundProperty = prop;
+ built.Data.byteSizeHint = bytesizeHint;
+
return built;
}
@@ -49,15 +54,38 @@ namespace MewtocolNet.RegisterBuilding {
public new class SAddress : RBuildBase.SAddress {
- public new TempRegister AsType(int? sizeHint = null) => new TempRegister().Map(base.AsType(sizeHint));
+ public new TypedRegister AsType() => new TypedRegister().Map(base.AsType());
- public new TempRegister AsType(Type type) => new TempRegister().Map(base.AsType(type));
+ public new TypedRegister AsType(Type type) => new TypedRegister().Map(base.AsType(type));
- public new TempRegister AsType(PlcVarType type) => new TempRegister().Map(base.AsType(type));
+ public new TypedRegister AsType(PlcVarType type) => new TypedRegister().Map(base.AsType(type));
- public new TempRegister AsType(string type) => new TempRegister().Map(base.AsType(type));
+ public new TypedRegister AsType(string type) => new TypedRegister().Map(base.AsType(type));
- public new TempRegister AsTypeArray(params int[] indicies) => new TempRegister().Map(base.AsTypeArray(indicies));
+ public new TypedRegister AsTypeArray(params int[] indicies) => new TypedRegister().Map(base.AsTypeArray(indicies));
+
+
+ }
+
+ #endregion
+
+ #region Typing size hint
+
+ public new class TypedRegister : RBuildBase.TypedRegister {
+
+ public new OptionsRegister SizeHint(int hint) => new OptionsRegister().Map(base.SizeHint(hint));
+
+ ///
+ public new OutRegister PollLevel(int level) => new OutRegister().Map(base.PollLevel(level));
+
+ ///
+ /// Outputs the generated
+ ///
+ public void Out(Action registerOut) {
+
+ Data.registerOut = registerOut;
+
+ }
}
@@ -65,58 +93,17 @@ namespace MewtocolNet.RegisterBuilding {
#region Options stage
- public new class TempRegister : RBuildBase.TempRegister {
+ public new class OptionsRegister : RBuildBase.OptionsRegister {
- internal TempRegister() { }
-
- internal TempRegister(StepData data, RBuildBase bldr) : base(data, bldr) { }
-
- ///
- public new TempRegister PollLevel(int level) => new TempRegister().Map(base.PollLevel(level));
+ ///
+ public new OutRegister PollLevel(int level) => new OutRegister().Map(base.PollLevel(level));
///
/// Outputs the generated
///
- public TempRegister Out(Action registerOut) {
+ public void Out(Action registerOut) {
Data.registerOut = registerOut;
- return this;
-
- }
-
- }
-
- public new class TempRegister : RBuildBase.TempRegister {
-
- internal TempRegister() { }
-
- internal TempRegister(StepData data, RBuildBase bldr) : base(data, bldr) { }
-
- ///
- public new TempRegister PollLevel(int level) => new TempRegister().Map(base.PollLevel(level));
-
- ///
- /// Outputs the generated
- ///
- public TempRegister Out(Action registerOut) {
-
- Data.registerOut = registerOut;
- return this;
-
- }
-
- //internal use only
- internal TempRegister RegCollection(RegisterCollection col) {
-
- Data.regCollection = col;
- return this;
-
- }
-
- internal TempRegister BoundProp(PropertyInfo prop) {
-
- Data.boundProperty = prop;
- return this;
}
@@ -124,6 +111,19 @@ namespace MewtocolNet.RegisterBuilding {
#endregion
+ public class OutRegister : SBase {
+
+ ///
+ /// Outputs the generated
+ ///
+ public void Out(Action registerOut) {
+
+ Data.registerOut = registerOut;
+
+ }
+
+ }
+
}
}
diff --git a/MewtocolNet/RegisterBuilding/RegBuilderExtensions.cs b/MewtocolNet/RegisterBuilding/RegBuilderExtensions.cs
index 136d3c0..3812246 100644
--- a/MewtocolNet/RegisterBuilding/RegBuilderExtensions.cs
+++ b/MewtocolNet/RegisterBuilding/RegBuilderExtensions.cs
@@ -25,32 +25,6 @@ namespace MewtocolNet.RegisterBuilding {
interf.AddRegisters(registers.ToArray());
- Task.Run(interf.memoryManager.CheckAllDynamicallySizedAreas);
-
- return registers.First();
-
- }
-
- ///
- /// Adds a single register to the plc stack and returns the generated
- /// Waits
- ///
- /// The generated
- public static async Task AddRegisterAsync (this IPlc plc, Action builder) {
-
- var assembler = new RegisterAssembler((MewtocolInterface)plc);
- var regBuilder = new RBuildSingle((MewtocolInterface)plc);
-
- builder.Invoke(regBuilder);
-
- var registers = assembler.AssembleAll(regBuilder);
-
- var interf = (MewtocolInterface)plc;
-
- interf.AddRegisters(registers.ToArray());
-
- await interf.memoryManager.CheckAllDynamicallySizedAreas();
-
return registers.First();
}
@@ -77,33 +51,6 @@ namespace MewtocolNet.RegisterBuilding {
interf.AddRegisters(registers.ToArray());
- Task.Run(interf.memoryManager.CheckAllDynamicallySizedAreas);
-
- return plc;
-
- }
-
- ///
- /// Adds multiple registers to the plc stack at once
- /// Using this over adding each register individually will result in better generation time performance
- /// of the
- /// This waits for the memory manager to size all dynamic registers correctly
- ///
- public static async Task AddRegistersAsync (this IPlc plc, Action builder) {
-
- var assembler = new RegisterAssembler((MewtocolInterface)plc);
- var regBuilder = new RBuildMult((MewtocolInterface)plc);
-
- builder.Invoke(regBuilder);
-
- var registers = assembler.AssembleAll(regBuilder);
-
- var interf = (MewtocolInterface)plc;
-
- interf.AddRegisters(registers.ToArray());
-
- await interf.memoryManager.CheckAllDynamicallySizedAreas();
-
return plc;
}
diff --git a/MewtocolNet/RegisterBuilding/RegisterAssembler.cs b/MewtocolNet/RegisterBuilding/RegisterAssembler.cs
index 9b4c305..0f101fb 100644
--- a/MewtocolNet/RegisterBuilding/RegisterAssembler.cs
+++ b/MewtocolNet/RegisterBuilding/RegisterAssembler.cs
@@ -1,5 +1,4 @@
-using MewtocolNet.Exceptions;
-using MewtocolNet.RegisterAttributes;
+using MewtocolNet.RegisterAttributes;
using MewtocolNet.Registers;
using System;
using System.Collections.Generic;
@@ -50,7 +49,7 @@ namespace MewtocolNet.RegisterBuilding {
Type elementType = data.dotnetVarType.GetElementType();
- uint numericSizePerElement = (uint)elementType.DetermineTypeByteSize();
+ uint numericSizePerElement = (uint)elementType.DetermineTypeByteIntialSize();
if (elementType.IsEnum && numericSizePerElement > 4) {
if (data.boundProperty != null) {
@@ -60,25 +59,10 @@ namespace MewtocolNet.RegisterBuilding {
}
}
- var sizeStateFlags = DynamicSizeState.None;
-
- //string with size hint
- if (elementType == typeof(string) && data.perElementByteSizeHint != null) {
-
- numericSizePerElement = (uint)data.byteSizeHint + 4;
- sizeStateFlags = DynamicSizeState.DynamicallySized | DynamicSizeState.WasSizeUpdated;
-
- } else if (elementType == typeof(string)) {
-
- sizeStateFlags = DynamicSizeState.DynamicallySized | DynamicSizeState.NeedsSizeUpdate;
-
- }
-
var parameters = new object[] {
data.memAddress,
data.byteSizeHint,
data.arrayIndicies,
- sizeStateFlags,
data.name
};
@@ -89,7 +73,6 @@ namespace MewtocolNet.RegisterBuilding {
typeof(uint),
typeof(uint),
typeof(int[]),
- typeof(DynamicSizeState),
typeof(string)
}, null);
@@ -107,7 +90,7 @@ namespace MewtocolNet.RegisterBuilding {
//-------------------------------------------
//as single register
- uint numericSize = (uint)data.dotnetVarType.DetermineTypeByteSize();
+ uint numericSize = (uint)data.dotnetVarType.DetermineTypeByteIntialSize();
if (data.dotnetVarType.IsEnum && numericSize > 4) {
if (data.boundProperty != null) {
@@ -117,17 +100,15 @@ namespace MewtocolNet.RegisterBuilding {
}
}
- var sizeStateFlags = DynamicSizeState.None;
+ if(data.dotnetVarType == typeof(string)) {
- //string with size hint
- if(data.dotnetVarType == typeof(string) && data.byteSizeHint != null) {
+ if(data.byteSizeHint == null)
+ throw new NotSupportedException($"Can't create a STRING register without a string size hint");
- numericSize = (uint)data.byteSizeHint + 4;
- sizeStateFlags = DynamicSizeState.DynamicallySized | DynamicSizeState.WasSizeUpdated;
+ if(data.byteSizeHint < 0)
+ throw new NotSupportedException($"Can't create a STRING register with a string size hint < 0");
- } else if (data.dotnetVarType == typeof(string)) {
-
- sizeStateFlags = DynamicSizeState.DynamicallySized | DynamicSizeState.NeedsSizeUpdate;
+ numericSize = 4 + data.byteSizeHint.Value;
}
@@ -135,13 +116,12 @@ namespace MewtocolNet.RegisterBuilding {
Type paramedClass = typeof(SingleRegister<>).MakeGenericType(data.dotnetVarType);
ConstructorInfo constr = paramedClass.GetConstructor(flags, null, new Type[] {
- typeof(uint), typeof(uint), typeof(DynamicSizeState) ,typeof(string)
+ typeof(uint), typeof(uint) ,typeof(string)
}, null);
var parameters = new object[] {
data.memAddress,
numericSize,
- sizeStateFlags,
data.name
};
@@ -167,7 +147,7 @@ namespace MewtocolNet.RegisterBuilding {
//finalize set for every
if (generatedInstance == null)
- throw new MewtocolException("Failed to build register");
+ throw new ArgumentException("Failed to build register");
if (collectionTarget != null)
generatedInstance.WithRegisterCollection(collectionTarget);
diff --git a/MewtocolNet/Registers/ArrayRegister.cs b/MewtocolNet/Registers/ArrayRegister.cs
index 894f0ec..085f0ec 100644
--- a/MewtocolNet/Registers/ArrayRegister.cs
+++ b/MewtocolNet/Registers/ArrayRegister.cs
@@ -1,6 +1,6 @@
-using MewtocolNet.Exceptions;
-using System;
+using System;
using System.Collections;
+using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -12,7 +12,7 @@ namespace MewtocolNet.Registers {
///
public class ArrayRegister : Register {
- internal int[] indicies;
+ internal int[] indices;
internal uint addressLength;
@@ -25,12 +25,11 @@ namespace MewtocolNet.Registers {
public ArrayRegister() =>
throw new NotSupportedException("Direct register instancing is not supported, use the builder pattern");
- internal ArrayRegister(uint _address, uint _reservedByteSize, int[] _indicies , DynamicSizeState dynamicSizeSt, string _name = null) {
+ internal ArrayRegister(uint _address, uint _reservedByteSize, int[] _indicies, string _name = null) {
name = _name;
memoryAddress = _address;
- dynamicSizeState = dynamicSizeSt;
- indicies = _indicies;
+ indices = _indicies;
//calc mem length
//because one register is always 1 word (2 bytes) long, if the bytecount is uneven we get the trailing word too
@@ -50,7 +49,22 @@ namespace MewtocolNet.Registers {
if (Value == null) return "null";
- return ((byte[])Value).ToHexString("-");
+ if(typeof(T) == typeof(byte[])) {
+
+ return ((byte[])Value).ToHexString("-");
+
+ }
+
+ StringBuilder sb = new StringBuilder();
+ var valueIenum = (IEnumerable)Value;
+
+ foreach (var el in valueIenum) {
+
+ sb.Append($"{el}, ");
+
+ }
+
+ return ArrayToString((Array)Value);
}
@@ -63,9 +77,6 @@ namespace MewtocolNet.Registers {
///
public override async Task WriteAsync(object value) {
- if (!attachedInterface.IsConnected)
- throw MewtocolException.NotConnectedSend();
-
var encoded = PlcValueParser.Encode(this, (T)value);
var res = await attachedInterface.WriteByteRange((int)MemoryAddress, encoded);
@@ -90,9 +101,6 @@ namespace MewtocolNet.Registers {
///
public override async Task