From 3a7b7879494ab8cde19e39d4b40033216e022759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Wei=C3=9F?= <72068105+Sandoun@users.noreply.github.com> Date: Tue, 18 Jul 2023 17:33:10 +0200 Subject: [PATCH] Fix Rbuild layout --- MewtocolNet/IPlc.cs | 12 +- MewtocolNet/IPlcEthernet.cs | 8 +- MewtocolNet/IPlcSerial.cs | 7 +- MewtocolNet/MewtocolInterface.cs | 12 +- .../MewtocolInterfaceRegisterHandling.cs | 6 +- MewtocolNet/MewtocolInterfaceRequests.cs | 8 + MewtocolNet/MewtocolInterfaceSerial.cs | 8 +- MewtocolNet/MewtocolInterfaceTcp.cs | 4 +- MewtocolNet/RegisterBuilding/RBuildBase.cs | 4 +- MewtocolNet/RegisterBuilding/RBuildMult.cs | 253 ++++++++++++------ MewtocolNet/RegisterBuilding/StepData.cs | 2 +- .../UnderlyingRegisters/MemoryAreaManager.cs | 7 + 12 files changed, 223 insertions(+), 108 deletions(-) diff --git a/MewtocolNet/IPlc.cs b/MewtocolNet/IPlc.cs index 7e0993c..64bc17d 100644 --- a/MewtocolNet/IPlc.cs +++ b/MewtocolNet/IPlc.cs @@ -65,7 +65,9 @@ namespace MewtocolNet { /// /// Tries to establish a connection with the device asynchronously /// - Task ConnectAsync(); + /// A callback for excecuting something right after the plc connected + /// + Task ConnectAsync(Func onConnected = null); /// /// Disconnects the device from its current plc connection @@ -94,6 +96,12 @@ namespace MewtocolNet { /// The success state of the write operation Task SetOperationModeAsync(bool setRun); + /// + /// Restarts the plc program + /// + /// The success state of the write operation + Task RestartProgramAsync(); + /// /// Use this to await the first poll iteration after connecting, /// This also completes if the initial connection fails @@ -105,7 +113,7 @@ namespace MewtocolNet { /// useful if you want to use a custom update frequency /// /// The number of inidvidual mewtocol commands sent - Task RunPollerCylceManualAsync(); + Task UpdateAsync(); /// /// Gets the connection info string diff --git a/MewtocolNet/IPlcEthernet.cs b/MewtocolNet/IPlcEthernet.cs index 9fae5f6..cebb130 100644 --- a/MewtocolNet/IPlcEthernet.cs +++ b/MewtocolNet/IPlcEthernet.cs @@ -1,4 +1,5 @@ -using System.Net; +using System; +using System.Net; using System.Threading.Tasks; namespace MewtocolNet { @@ -23,11 +24,6 @@ namespace MewtocolNet { /// IPEndPoint HostEndpoint { get; set; } - /// - /// Tries to establish a connection with the device asynchronously - /// - Task ConnectAsync(); - /// /// Configures the serial interface /// diff --git a/MewtocolNet/IPlcSerial.cs b/MewtocolNet/IPlcSerial.cs index e378598..81b19c2 100644 --- a/MewtocolNet/IPlcSerial.cs +++ b/MewtocolNet/IPlcSerial.cs @@ -48,12 +48,7 @@ namespace MewtocolNet { /// /// Tries to establish a connection with the device asynchronously /// - Task ConnectAsync(); - - /// - /// Tries to establish a connection with the device asynchronously - /// - Task ConnectAsync(Action onTryingConfig); + Task ConnectAsync(Func callBack, Action onTryingConfig); } diff --git a/MewtocolNet/MewtocolInterface.cs b/MewtocolNet/MewtocolInterface.cs index 10dbc26..0b2bcca 100644 --- a/MewtocolNet/MewtocolInterface.cs +++ b/MewtocolNet/MewtocolInterface.cs @@ -186,7 +186,7 @@ namespace MewtocolNet { } /// - public virtual async Task ConnectAsync() { + public virtual async Task ConnectAsync(Func callBack = null) { isConnectingStage = false; @@ -202,6 +202,14 @@ namespace MewtocolNet { Logger.Log($">> Intial connection end <<", LogLevel.Verbose, this); + if (callBack != null) { + + await Task.Run(callBack); + + Logger.Log($">> OnConnected run complete <<", LogLevel.Verbose, this); + + } + } /// @@ -243,7 +251,7 @@ namespace MewtocolNet { public virtual string GetConnectionInfo() => throw new NotImplementedException(); /// - public async Task SendCommandAsync(string _msg, bool withTerminator = true, int timeoutMs = -1, Action onReceiveProgress = null) { + 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"); diff --git a/MewtocolNet/MewtocolInterfaceRegisterHandling.cs b/MewtocolNet/MewtocolInterfaceRegisterHandling.cs index 27be26b..d4a3e3c 100644 --- a/MewtocolNet/MewtocolInterfaceRegisterHandling.cs +++ b/MewtocolNet/MewtocolInterfaceRegisterHandling.cs @@ -73,11 +73,11 @@ namespace MewtocolNet { /// useful if you want to use a custom update frequency /// /// The number of inidvidual mewtocol commands sent - public async Task RunPollerCylceManualAsync() { + public async Task UpdateAsync() { if (!pollerTaskStopped) throw new NotSupportedException($"The poller is already running, " + - $"please make sure there is no polling active before calling {nameof(RunPollerCylceManualAsync)}"); + $"please make sure there is no polling active before calling {nameof(UpdateAsync)}"); tcpMessagesSentThisCycle = 0; @@ -124,8 +124,6 @@ namespace MewtocolNet { await memoryManager.PollAllAreasAsync(); - await GetPLCInfoAsync(); - sw.Stop(); PollerCycleDurationMs = (int)sw.ElapsedMilliseconds; diff --git a/MewtocolNet/MewtocolInterfaceRequests.cs b/MewtocolNet/MewtocolInterfaceRequests.cs index 51769a2..3f16c2b 100644 --- a/MewtocolNet/MewtocolInterfaceRequests.cs +++ b/MewtocolNet/MewtocolInterfaceRequests.cs @@ -94,6 +94,14 @@ namespace MewtocolNet { } + /// + public async Task RestartProgramAsync () { + + return await SetOperationModeAsync(false) && + await SetOperationModeAsync(true); + + } + #endregion #region Byte range writing / reading to registers diff --git a/MewtocolNet/MewtocolInterfaceSerial.cs b/MewtocolNet/MewtocolInterfaceSerial.cs index 47a91c2..a561a94 100644 --- a/MewtocolNet/MewtocolInterfaceSerial.cs +++ b/MewtocolNet/MewtocolInterfaceSerial.cs @@ -99,10 +99,12 @@ namespace MewtocolNet { } - public override async Task ConnectAsync() => await ConnectAsync(null); + public override async Task ConnectAsync(Func callBack = null) => await ConnectAsyncPriv(callBack); + + public async Task ConnectAsync(Func callBack = null, Action onTryingConfig = null) => await ConnectAsyncPriv(callBack, onTryingConfig); /// - public async Task ConnectAsync(Action onTryingConfig = null) { + private async Task ConnectAsyncPriv(Func callBack, Action onTryingConfig = null) { void OnTryConfig() { onTryingConfig(); @@ -133,7 +135,7 @@ namespace MewtocolNet { if (gotInfo != null) { IsConnected = true; - await base.ConnectAsync(); + await base.ConnectAsync(callBack); OnConnected(gotInfo); } else { diff --git a/MewtocolNet/MewtocolInterfaceTcp.cs b/MewtocolNet/MewtocolInterfaceTcp.cs index b3bb648..e527784 100644 --- a/MewtocolNet/MewtocolInterfaceTcp.cs +++ b/MewtocolNet/MewtocolInterfaceTcp.cs @@ -61,7 +61,7 @@ namespace MewtocolNet { } /// - public override async Task ConnectAsync() { + public override async Task ConnectAsync(Func callBack = null) { try { @@ -112,7 +112,7 @@ namespace MewtocolNet { if (plcinf != null) { IsConnected = true; - await base.ConnectAsync(); + await base.ConnectAsync(callBack); OnConnected(plcinf); } else { diff --git a/MewtocolNet/RegisterBuilding/RBuildBase.cs b/MewtocolNet/RegisterBuilding/RBuildBase.cs index f0d6641..be25c6d 100644 --- a/MewtocolNet/RegisterBuilding/RBuildBase.cs +++ b/MewtocolNet/RegisterBuilding/RBuildBase.cs @@ -559,7 +559,7 @@ namespace MewtocolNet.RegisterBuilding { public class TypedRegister : SBase { - public OptionsRegister SizeHint(int hint) { + internal OptionsRegister SizeHint(int hint) { Data.byteSizeHint = (uint)hint; @@ -567,7 +567,7 @@ namespace MewtocolNet.RegisterBuilding { } - public OptionsRegister PollLevel(int level) { + internal OptionsRegister PollLevel(int level) { Data.pollLevel = level; diff --git a/MewtocolNet/RegisterBuilding/RBuildMult.cs b/MewtocolNet/RegisterBuilding/RBuildMult.cs index 311c1d9..c2683f7 100644 --- a/MewtocolNet/RegisterBuilding/RBuildMult.cs +++ b/MewtocolNet/RegisterBuilding/RBuildMult.cs @@ -3,6 +3,7 @@ using MewtocolNet.RegisterAttributes; using MewtocolNet.Registers; using System; using System.Reflection; +using static MewtocolNet.RegisterBuilding.RBuildMult; namespace MewtocolNet.RegisterBuilding { @@ -22,15 +23,15 @@ namespace MewtocolNet.RegisterBuilding { /// Examples: /// Address("DT100") | Address("R10A") | Address("DDT50", "MyRegisterName") /// - /// Address name formatted as FP-Address like in FP-Winpro + /// Address name formatted as FP-Address like in FP-Winpro /// Custom name for the register to referr to it later - public SAddress Address(string plcAddrName, string name = null) { + public AddressStp Address(string dtAddr, string name = null) { - var data = ParseAddress(plcAddrName, name); + var data = ParseAddress(dtAddr, name); unfinishedList.Add(data); - return new SAddress { + return new AddressStp { Data = data, builder = this, }; @@ -39,23 +40,47 @@ namespace MewtocolNet.RegisterBuilding { //struct constructor - public SAddressStruct Address(string plcAddrName, string name = null) where T : struct { + public StructStp Struct(string dtAddr, string name = null) where T : struct { - var data = ParseAddress(plcAddrName, name); + var data = ParseAddress(dtAddr, name); data.dotnetVarType = typeof(T); unfinishedList.Add(data); - return new SAddressStruct(data) { + return new StructStp(data) { builder = this, }; } - public SAddressString AddressString(string plcAddrName, int sizeHint, string name = null) where T : class { + public StringStp String(string dtAddr, int sizeHint, string name = null) where T : class { - var data = ParseAddress(plcAddrName, name); + var data = ParseAddress(dtAddr, name); + + data.dotnetVarType = typeof(T); + data.byteSizeHint = (uint)sizeHint; + + unfinishedList.Add(data); + + if (typeof(T).IsArray) { + + return new StringStp(data, true) { + Data = data, + builder = this, + }; + + } + + return new StringStp(data) { + builder = this, + }; + + } + + public ArrayStp Array(string dtAddr, string name = null) where T : class { + + var data = ParseAddress(dtAddr, name); data.dotnetVarType = typeof(T); @@ -63,46 +88,23 @@ namespace MewtocolNet.RegisterBuilding { if (typeof(T).IsArray) { - return new SAddressString(data, true) { + return new ArrayStp(data, true) { Data = data, builder = this, }; } - return new SAddressString(data) { - builder = this, - }; - - } - - public SAddressArray AddressArray(string plcAddrName, string name = null) where T : class { - - var data = ParseAddress(plcAddrName, name); - - data.dotnetVarType = typeof(T); - - unfinishedList.Add(data); - - if (typeof(T).IsArray) { - - return new SAddressArray(data, true) { - Data = data, - builder = this, - }; - - } - - return new SAddressArray(data) { + return new ArrayStp(data) { builder = this, }; } //internal use only, adds a type definition (for use when building from attibute) - internal SAddress AddressFromAttribute(string plcAddrName, string typeDef, RegisterCollection regCol, PropertyInfo prop, uint? bytesizeHint = null) { + internal AddressStp AddressFromAttribute(string dtAddr, string typeDef, RegisterCollection regCol, PropertyInfo prop, uint? bytesizeHint = null) { - var built = Address(plcAddrName); + var built = Address(dtAddr); built.Data.typeDef = typeDef; built.Data.buildSource = RegisterBuildSource.Attribute; @@ -119,7 +121,7 @@ namespace MewtocolNet.RegisterBuilding { #region Typing stage //non generic - public new class SAddress : RBuildBase.SAddress { + public new class AddressStp : RBuildBase.SAddress { public new TypedRegister AsType() => new TypedRegister().Map(base.AsType()); @@ -134,9 +136,9 @@ namespace MewtocolNet.RegisterBuilding { } //structs - public class SAddressStruct : RBuildBase.SAddress where T : struct { + public class StructStp : RBuildBase.SAddress where T : struct { - internal SAddressStruct(StepData data) { + internal StructStp(StepData data) { this.Data = data; @@ -144,7 +146,7 @@ namespace MewtocolNet.RegisterBuilding { } - internal SAddressStruct(StepData data, bool arrayed) { + internal StructStp(StepData data, bool arrayed) { this.Data = data; @@ -159,12 +161,60 @@ namespace MewtocolNet.RegisterBuilding { } + public OutStruct PollLevel(int level) { + + Data.pollLevel = level; + + return new OutStruct().Map(this); + + } + + } + + //arrays + public class ArrayStp : RBuildBase.SAddress { + + internal ArrayStp(StepData data) { + + Data = data; + + this.Map(AsType(typeof(T))); + + } + + internal ArrayStp(StepData data, bool arrayed) { + + Data = data; + + } + + public TypedRegisterArray Indices(params int[] indices) { + + if (typeof(T).GetElementType() == typeof(string) && Data.byteSizeHint == null) { + + throw new NotSupportedException($"For string arrays use {nameof(ArrayStp.StrHint)} before setting the indices"); + + } + + Data.arrayIndicies = indices; + + return new TypedRegisterArray().Map(this); + + } + + public TypedRegisterStringArray StrHint(int hint) { + + Data.byteSizeHint = (uint)hint; + return new TypedRegisterStringArray().Map(this); + + } + } //strings - public class SAddressString : RBuildBase.SAddress where T : class { + public class StringStp : RBuildBase.SAddress where T : class { - internal SAddressString(StepData data) { + internal StringStp(StepData data) { this.Data = data; @@ -172,7 +222,7 @@ namespace MewtocolNet.RegisterBuilding { } - internal SAddressString(StepData data, bool arrayed) { + internal StringStp(StepData data, bool arrayed) { this.Data = data; @@ -189,37 +239,6 @@ namespace MewtocolNet.RegisterBuilding { } - //arrays - public class SAddressArray : RBuildBase.SAddress { - - internal SAddressArray(StepData data) { - - this.Data = data; - - this.Map(AsType(typeof(T))); - - } - - internal SAddressArray(StepData data, bool arrayed) { - - this.Data = data; - - } - - public TypedRegister Indicies(params int[] indicies) => new TypedRegister().Map(base.AsTypeArray(indicies)); - - /// - /// Outputs the generated - /// - public void Out(Action> registerOut) { - - Data.registerOut = new Action(o => registerOut((IArrayRegister)o)); - - } - - } - - #endregion #region Typing size hint @@ -236,12 +255,55 @@ namespace MewtocolNet.RegisterBuilding { /// public void Out(Action registerOut) { - Data.registerOut = (Action)registerOut; + Data.registerOut = new Action(o => registerOut((IRegister)o)); } } + public class TypedRegisterString : RBuildBase.TypedRegister where T : class { + + 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 = new Action(o => registerOut((IStringRegister)o)); + + } + + } + + public class TypedRegisterArray : RBuildBase.TypedRegister { + + public new OutArray PollLevel(int level) => new OutArray().Map(base.PollLevel(level)); + + public void Out(Action> registerOut) { + + Data.registerOut = new Action(o => registerOut((IArrayRegister)o)); + + } + + } + + public class TypedRegisterStringArray : RBuildBase.TypedRegister { + + public OptionsRegisterArray Indices(params int[] indices) { + + Data.arrayIndicies = indices; + return new OptionsRegisterArray().Map(this); + + } + + public new OutArray PollLevel(int level) => new OutArray().Map(base.PollLevel(level)); + + } + #endregion #region Options stage @@ -256,7 +318,20 @@ namespace MewtocolNet.RegisterBuilding { /// public void Out(Action registerOut) { - Data.registerOut = (Action)registerOut; + Data.registerOut = new Action(o => registerOut((IRegister)o)); + + } + + } + + public class OptionsRegisterArray : RBuildBase.OptionsRegister { + + /// + public new OutArray PollLevel(int level) => new OutArray().Map(base.PollLevel(level)); + + public void Out(Action> registerOut) { + + Data.registerOut = new Action(o => registerOut((IArrayRegister)o)); } @@ -266,17 +341,35 @@ namespace MewtocolNet.RegisterBuilding { public class OutRegister : SBase { - /// - /// Outputs the generated - /// public void Out(Action registerOut) { - Data.registerOut = (Action)registerOut; + Data.registerOut = new Action(o => registerOut((IRegister)o)); } } + public class OutStruct : SBase where T : struct { + + public void Out(Action> registerOut) { + + Data.registerOut = new Action(o => registerOut((IRegister)o)); + + } + + } + + public class OutArray : SBase { + + public void Out(Action> registerOut) { + + Data.registerOut = new Action(o => registerOut((IArrayRegister)o)); + + } + + } + + } } diff --git a/MewtocolNet/RegisterBuilding/StepData.cs b/MewtocolNet/RegisterBuilding/StepData.cs index 35ee44b..edb2d80 100644 --- a/MewtocolNet/RegisterBuilding/StepData.cs +++ b/MewtocolNet/RegisterBuilding/StepData.cs @@ -35,7 +35,7 @@ namespace MewtocolNet.RegisterBuilding { internal void InvokeBuilt(Register reg) { - registerOut.Invoke(reg); + registerOut?.Invoke(reg); //var selftype = this.GetType(); diff --git a/MewtocolNet/UnderlyingRegisters/MemoryAreaManager.cs b/MewtocolNet/UnderlyingRegisters/MemoryAreaManager.cs index 01b7b93..d477e13 100644 --- a/MewtocolNet/UnderlyingRegisters/MemoryAreaManager.cs +++ b/MewtocolNet/UnderlyingRegisters/MemoryAreaManager.cs @@ -339,6 +339,13 @@ namespace MewtocolNet.UnderlyingRegisters { } + //get the plc status each n iterations + if (pollIteration % 5 == 0) { + + await mewInterface.GetPLCInfoAsync(); + + } + if (pollIteration == uint.MaxValue) { pollIteration = uint.MinValue; } else {