diff --git a/Sharp7.Rx/Exceptions/S7Exception.cs b/Sharp7.Rx/Exceptions/S7Exception.cs index fb836f9..2d8fb44 100644 --- a/Sharp7.Rx/Exceptions/S7Exception.cs +++ b/Sharp7.Rx/Exceptions/S7Exception.cs @@ -11,6 +11,24 @@ public abstract class S7Exception : Exception } } +public class S7CommunicationException : S7Exception +{ + public S7CommunicationException(string message, int s7ErrorCode, string s7ErrorText) : base(message) + { + S7ErrorCode = s7ErrorCode; + S7ErrorText = s7ErrorText; + } + + public S7CommunicationException(string message, Exception innerException, int s7ErrorCode, string s7ErrorText) : base(message, innerException) + { + S7ErrorCode = s7ErrorCode; + S7ErrorText = s7ErrorText; + } + + public int S7ErrorCode { get; } + public string S7ErrorText { get; } +} + public class DataTypeMissmatchException : S7Exception { internal DataTypeMissmatchException(string message, Type type, S7VariableAddress address) : base(message) diff --git a/Sharp7.Rx/Interfaces/IS7Connector.cs b/Sharp7.Rx/Interfaces/IS7Connector.cs index 5f9da81..fe365c1 100644 --- a/Sharp7.Rx/Interfaces/IS7Connector.cs +++ b/Sharp7.Rx/Interfaces/IS7Connector.cs @@ -12,10 +12,10 @@ internal interface IS7Connector : IDisposable Task Connect(); Task Disconnect(); - Task ReadBytes(Operand operand, ushort startByteAddress, ushort bytesToRead, ushort dBNr, CancellationToken token); + Task ReadBytes(Operand operand, ushort startByteAddress, ushort bytesToRead, ushort dbNo, CancellationToken token); - Task WriteBit(Operand operand, ushort startByteAddress, byte bitAdress, bool value, ushort dbNr, CancellationToken token); - Task WriteBytes(Operand operand, ushort startByteAdress, byte[] data, ushort dBNr, CancellationToken token); + Task WriteBit(Operand operand, ushort startByteAddress, byte bitAdress, bool value, ushort dbNo, CancellationToken token); + Task WriteBytes(Operand operand, ushort startByteAddress, byte[] data, ushort dbNo, CancellationToken token); Task> ExecuteMultiVarRequest(IReadOnlyList variableNames); } diff --git a/Sharp7.Rx/Resources/StringResources.Designer.cs b/Sharp7.Rx/Resources/StringResources.Designer.cs index f1d725d..dd88d85 100644 --- a/Sharp7.Rx/Resources/StringResources.Designer.cs +++ b/Sharp7.Rx/Resources/StringResources.Designer.cs @@ -19,7 +19,7 @@ namespace Sharp7.Rx.Resources { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class StringResources { @@ -60,24 +60,6 @@ namespace Sharp7.Rx.Resources { } } - /// - /// Looks up a localized string similar to S7 driver could not be initialized. - /// - internal static string StrErrorS7DriverCouldNotBeInitialized { - get { - return ResourceManager.GetString("StrErrorS7DriverCouldNotBeInitialized", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to S7 driver is not initialized.. - /// - internal static string StrErrorS7DriverNotInitialized { - get { - return ResourceManager.GetString("StrErrorS7DriverNotInitialized", resourceCulture); - } - } - /// /// Looks up a localized string similar to TCP/IP connection established.. /// diff --git a/Sharp7.Rx/Resources/StringResources.resx b/Sharp7.Rx/Resources/StringResources.resx index 3eff273..ee55570 100644 --- a/Sharp7.Rx/Resources/StringResources.resx +++ b/Sharp7.Rx/Resources/StringResources.resx @@ -123,16 +123,10 @@ Communication error discovered. Reconnect is in progress... - - S7 driver is not initialized. - Trying to connect to PLC ({2}) '{0}', CPU slot {1}... TCP/IP connection established. - - S7 driver could not be initialized - \ No newline at end of file diff --git a/Sharp7.Rx/Sharp7Connector.cs b/Sharp7.Rx/Sharp7Connector.cs index efdd014..98f9c74 100644 --- a/Sharp7.Rx/Sharp7Connector.cs +++ b/Sharp7.Rx/Sharp7Connector.cs @@ -55,21 +55,26 @@ internal class Sharp7Connector : IS7Connector public async Task Connect() { if (sharp7 == null) - throw new InvalidOperationException(StringResources.StrErrorS7DriverNotInitialized); + throw new InvalidOperationException("S7 driver is not initialized."); try { var errorCode = await Task.Factory.StartNew(() => sharp7.ConnectTo(ipAddress, rackNr, cpuSlotNr), CancellationToken.None, TaskCreationOptions.None, scheduler); - var success = EvaluateErrorCode(errorCode); - if (success) + if (errorCode == 0) { connectionStateSubject.OnNext(Enums.ConnectionState.Connected); return true; } + else + { + var errorText = EvaluateErrorCode(errorCode); + Logger.LogError("Failed to establish initial connection: {Error}", errorText); + } } catch (Exception ex) { - // TODO: + connectionStateSubject.OnNext(Enums.ConnectionState.ConnectionLost); + Logger.LogError(ex, "Failed to establish initial connection."); } return false; @@ -102,8 +107,8 @@ internal class Sharp7Connector : IS7Connector var result = await Task.Factory.StartNew(() => s7MultiVar.Read(), CancellationToken.None, TaskCreationOptions.None, scheduler); if (result != 0) { - EvaluateErrorCode(result); - throw new InvalidOperationException($"Error in MultiVar request for variables: {string.Join(",", variableNames)}"); + var errorText = EvaluateErrorCode(result); + throw new S7CommunicationException($"Error in MultiVar request for variables: {string.Join(",", variableNames)} ({errorText})", result, errorText); } return buffers.ToDictionary(arg => arg.VariableName, arg => arg.Buffer); @@ -129,13 +134,13 @@ internal class Sharp7Connector : IS7Connector } catch (Exception ex) { - Logger?.LogError(ex, StringResources.StrErrorS7DriverCouldNotBeInitialized); + Logger?.LogError(ex, "S7 driver could not be initialized"); } return Task.FromResult(true); } - public async Task ReadBytes(Operand operand, ushort startByteAddress, ushort bytesToRead, ushort dBNr, CancellationToken token) + public async Task ReadBytes(Operand operand, ushort startByteAddress, ushort bytesToRead, ushort dbNo, CancellationToken token) { EnsureConnectionValid(); @@ -143,20 +148,19 @@ internal class Sharp7Connector : IS7Connector var result = - await Task.Factory.StartNew(() => sharp7.ReadArea(operand.ToArea(), dBNr, startByteAddress, bytesToRead, S7WordLength.Byte, buffer), token, TaskCreationOptions.None, scheduler); + await Task.Factory.StartNew(() => sharp7.ReadArea(operand.ToArea(), dbNo, startByteAddress, bytesToRead, S7WordLength.Byte, buffer), token, TaskCreationOptions.None, scheduler); token.ThrowIfCancellationRequested(); if (result != 0) { - EvaluateErrorCode(result); - var errorText = sharp7.ErrorText(result); - throw new InvalidOperationException($"Error reading {operand}{dBNr}:{startByteAddress}->{bytesToRead} ({errorText})"); + var errorText = EvaluateErrorCode(result); + throw new S7CommunicationException($"Error reading {operand}{dbNo}:{startByteAddress}->{bytesToRead} ({errorText})", result, errorText); } return buffer; } - public async Task WriteBit(Operand operand, ushort startByteAddress, byte bitAdress, bool value, ushort dbNr, CancellationToken token) + public async Task WriteBit(Operand operand, ushort startByteAddress, byte bitAdress, bool value, ushort dbNo, CancellationToken token) { EnsureConnectionValid(); @@ -164,32 +168,28 @@ internal class Sharp7Connector : IS7Connector var offsetStart = (startByteAddress * 8) + bitAdress; - var result = await Task.Factory.StartNew(() => sharp7.WriteArea(operand.ToArea(), dbNr, offsetStart, 1, S7WordLength.Bit, buffer), token, TaskCreationOptions.None, scheduler); + var result = await Task.Factory.StartNew(() => sharp7.WriteArea(operand.ToArea(), dbNo, offsetStart, 1, S7WordLength.Bit, buffer), token, TaskCreationOptions.None, scheduler); token.ThrowIfCancellationRequested(); if (result != 0) { - EvaluateErrorCode(result); - return (false); + var errorText = EvaluateErrorCode(result); + throw new S7CommunicationException($"Error writing {operand}{dbNo}:{startByteAddress} bit {bitAdress} ({errorText})", result, errorText); } - - return (true); } - public async Task WriteBytes(Operand operand, ushort startByteAdress, byte[] data, ushort dBNr, CancellationToken token) + public async Task WriteBytes(Operand operand, ushort startByteAddress, byte[] data, ushort dbNo, CancellationToken token) { EnsureConnectionValid(); - var result = await Task.Factory.StartNew(() => sharp7.WriteArea(operand.ToArea(), dBNr, startByteAdress, data.Length, S7WordLength.Byte, data), token, TaskCreationOptions.None, scheduler); + var result = await Task.Factory.StartNew(() => sharp7.WriteArea(operand.ToArea(), dbNo, startByteAddress, data.Length, S7WordLength.Byte, data), token, TaskCreationOptions.None, scheduler); token.ThrowIfCancellationRequested(); if (result != 0) { - EvaluateErrorCode(result); - return 0; + var errorText = EvaluateErrorCode(result); + throw new S7CommunicationException($"Error writing {operand}{dbNo}:{startByteAddress}.{data.Length} ({errorText})", result, errorText); } - - return (ushort) (data.Length); } @@ -218,7 +218,7 @@ internal class Sharp7Connector : IS7Connector private async Task CloseConnection() { if (sharp7 == null) - throw new InvalidOperationException(StringResources.StrErrorS7DriverNotInitialized); + throw new InvalidOperationException("S7 driver is not initialized."); await Task.Factory.StartNew(() => sharp7.Disconnect(), CancellationToken.None, TaskCreationOptions.None, scheduler); } @@ -229,19 +229,19 @@ internal class Sharp7Connector : IS7Connector throw new ObjectDisposedException("S7Connector"); if (sharp7 == null) - throw new InvalidOperationException(StringResources.StrErrorS7DriverNotInitialized); + throw new InvalidOperationException("S7 driver is not initialized."); if (!IsConnected) throw new InvalidOperationException("Plc is not connected"); } - private bool EvaluateErrorCode(int errorCode) + private string EvaluateErrorCode(int errorCode) { if (errorCode == 0) - return true; + return null; if (sharp7 == null) - throw new InvalidOperationException(StringResources.StrErrorS7DriverNotInitialized); + throw new InvalidOperationException("S7 driver is not initialized."); var errorText = sharp7.ErrorText(errorCode); Logger?.LogError($"Error Code {errorCode} {errorText}"); @@ -249,7 +249,7 @@ internal class Sharp7Connector : IS7Connector if (S7ErrorCodes.AssumeConnectionLost(errorCode)) SetConnectionLostState(); - return false; + return errorText; } private async Task Reconnect() diff --git a/Sharp7.Rx/Sharp7Plc.cs b/Sharp7.Rx/Sharp7Plc.cs index ec6504a..bada2e2 100644 --- a/Sharp7.Rx/Sharp7Plc.cs +++ b/Sharp7.Rx/Sharp7Plc.cs @@ -164,10 +164,7 @@ public class Sharp7Plc : IPlc // Special handling for bools, which are written on a by-bit basis. Writing a complete byte would // overwrite other bits within this byte. - if (address.Bit == null) - throw new InvalidOperationException("Address must have a Bit to write a bool."); - - await s7Connector.WriteBit(address.Operand, address.Start, address.Bit.Value, (bool) (object) value, address.DbNr, token); + await s7Connector.WriteBit(address.Operand, address.Start, address.Bit!.Value, (bool) (object) value, address.DbNr, token); } else {