Return S7CommunicationException

This commit is contained in:
Peter Butzhammer
2024-02-08 18:30:49 +01:00
parent 5d85823167
commit b43a595e13
6 changed files with 53 additions and 62 deletions

View File

@@ -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 public class DataTypeMissmatchException : S7Exception
{ {
internal DataTypeMissmatchException(string message, Type type, S7VariableAddress address) : base(message) internal DataTypeMissmatchException(string message, Type type, S7VariableAddress address) : base(message)

View File

@@ -12,10 +12,10 @@ internal interface IS7Connector : IDisposable
Task<bool> Connect(); Task<bool> Connect();
Task Disconnect(); Task Disconnect();
Task<byte[]> ReadBytes(Operand operand, ushort startByteAddress, ushort bytesToRead, ushort dBNr, CancellationToken token); Task<byte[]> ReadBytes(Operand operand, ushort startByteAddress, ushort bytesToRead, ushort dbNo, CancellationToken token);
Task<bool> WriteBit(Operand operand, ushort startByteAddress, byte bitAdress, bool value, ushort dbNr, CancellationToken token); Task WriteBit(Operand operand, ushort startByteAddress, byte bitAdress, bool value, ushort dbNo, CancellationToken token);
Task<ushort> WriteBytes(Operand operand, ushort startByteAdress, byte[] data, ushort dBNr, CancellationToken token); Task WriteBytes(Operand operand, ushort startByteAddress, byte[] data, ushort dbNo, CancellationToken token);
Task<Dictionary<string, byte[]>> ExecuteMultiVarRequest(IReadOnlyList<string> variableNames); Task<Dictionary<string, byte[]>> ExecuteMultiVarRequest(IReadOnlyList<string> variableNames);
} }

View File

@@ -19,7 +19,7 @@ namespace Sharp7.Rx.Resources {
// class via a tool like ResGen or Visual Studio. // class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen // To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project. // 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.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class StringResources { internal class StringResources {
@@ -60,24 +60,6 @@ namespace Sharp7.Rx.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to S7 driver could not be initialized.
/// </summary>
internal static string StrErrorS7DriverCouldNotBeInitialized {
get {
return ResourceManager.GetString("StrErrorS7DriverCouldNotBeInitialized", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to S7 driver is not initialized..
/// </summary>
internal static string StrErrorS7DriverNotInitialized {
get {
return ResourceManager.GetString("StrErrorS7DriverNotInitialized", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to TCP/IP connection established.. /// Looks up a localized string similar to TCP/IP connection established..
/// </summary> /// </summary>

View File

@@ -123,16 +123,10 @@
<data name="StrLogWarningCommunictionErrorReconnecting" xml:space="preserve"> <data name="StrLogWarningCommunictionErrorReconnecting" xml:space="preserve">
<value>Communication error discovered. Reconnect is in progress...</value> <value>Communication error discovered. Reconnect is in progress...</value>
</data> </data>
<data name="StrErrorS7DriverNotInitialized" xml:space="preserve">
<value>S7 driver is not initialized.</value>
</data>
<data name="StrInfoTryConnecting" xml:space="preserve"> <data name="StrInfoTryConnecting" xml:space="preserve">
<value>Trying to connect to PLC ({2}) '{0}', CPU slot {1}...</value> <value>Trying to connect to PLC ({2}) '{0}', CPU slot {1}...</value>
</data> </data>
<data name="StrInfoConnectionEstablished" xml:space="preserve"> <data name="StrInfoConnectionEstablished" xml:space="preserve">
<value>TCP/IP connection established.</value> <value>TCP/IP connection established.</value>
</data> </data>
<data name="StrErrorS7DriverCouldNotBeInitialized" xml:space="preserve">
<value>S7 driver could not be initialized</value>
</data>
</root> </root>

View File

@@ -55,21 +55,26 @@ internal class Sharp7Connector : IS7Connector
public async Task<bool> Connect() public async Task<bool> Connect()
{ {
if (sharp7 == null) if (sharp7 == null)
throw new InvalidOperationException(StringResources.StrErrorS7DriverNotInitialized); throw new InvalidOperationException("S7 driver is not initialized.");
try try
{ {
var errorCode = await Task.Factory.StartNew(() => sharp7.ConnectTo(ipAddress, rackNr, cpuSlotNr), CancellationToken.None, TaskCreationOptions.None, scheduler); var errorCode = await Task.Factory.StartNew(() => sharp7.ConnectTo(ipAddress, rackNr, cpuSlotNr), CancellationToken.None, TaskCreationOptions.None, scheduler);
var success = EvaluateErrorCode(errorCode); if (errorCode == 0)
if (success)
{ {
connectionStateSubject.OnNext(Enums.ConnectionState.Connected); connectionStateSubject.OnNext(Enums.ConnectionState.Connected);
return true; return true;
} }
else
{
var errorText = EvaluateErrorCode(errorCode);
Logger.LogError("Failed to establish initial connection: {Error}", errorText);
}
} }
catch (Exception ex) catch (Exception ex)
{ {
// TODO: connectionStateSubject.OnNext(Enums.ConnectionState.ConnectionLost);
Logger.LogError(ex, "Failed to establish initial connection.");
} }
return false; return false;
@@ -102,8 +107,8 @@ internal class Sharp7Connector : IS7Connector
var result = await Task.Factory.StartNew(() => s7MultiVar.Read(), CancellationToken.None, TaskCreationOptions.None, scheduler); var result = await Task.Factory.StartNew(() => s7MultiVar.Read(), CancellationToken.None, TaskCreationOptions.None, scheduler);
if (result != 0) if (result != 0)
{ {
EvaluateErrorCode(result); var errorText = EvaluateErrorCode(result);
throw new InvalidOperationException($"Error in MultiVar request for variables: {string.Join(",", variableNames)}"); throw new S7CommunicationException($"Error in MultiVar request for variables: {string.Join(",", variableNames)} ({errorText})", result, errorText);
} }
return buffers.ToDictionary(arg => arg.VariableName, arg => arg.Buffer); return buffers.ToDictionary(arg => arg.VariableName, arg => arg.Buffer);
@@ -129,13 +134,13 @@ internal class Sharp7Connector : IS7Connector
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger?.LogError(ex, StringResources.StrErrorS7DriverCouldNotBeInitialized); Logger?.LogError(ex, "S7 driver could not be initialized");
} }
return Task.FromResult(true); return Task.FromResult(true);
} }
public async Task<byte[]> ReadBytes(Operand operand, ushort startByteAddress, ushort bytesToRead, ushort dBNr, CancellationToken token) public async Task<byte[]> ReadBytes(Operand operand, ushort startByteAddress, ushort bytesToRead, ushort dbNo, CancellationToken token)
{ {
EnsureConnectionValid(); EnsureConnectionValid();
@@ -143,20 +148,19 @@ internal class Sharp7Connector : IS7Connector
var result = 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(); token.ThrowIfCancellationRequested();
if (result != 0) if (result != 0)
{ {
EvaluateErrorCode(result); var errorText = EvaluateErrorCode(result);
var errorText = sharp7.ErrorText(result); throw new S7CommunicationException($"Error reading {operand}{dbNo}:{startByteAddress}->{bytesToRead} ({errorText})", result, errorText);
throw new InvalidOperationException($"Error reading {operand}{dBNr}:{startByteAddress}->{bytesToRead} ({errorText})");
} }
return buffer; return buffer;
} }
public async Task<bool> 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(); EnsureConnectionValid();
@@ -164,32 +168,28 @@ internal class Sharp7Connector : IS7Connector
var offsetStart = (startByteAddress * 8) + bitAdress; 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(); token.ThrowIfCancellationRequested();
if (result != 0) if (result != 0)
{ {
EvaluateErrorCode(result); var errorText = EvaluateErrorCode(result);
return (false); throw new S7CommunicationException($"Error writing {operand}{dbNo}:{startByteAddress} bit {bitAdress} ({errorText})", result, errorText);
} }
return (true);
} }
public async Task<ushort> 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(); 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(); token.ThrowIfCancellationRequested();
if (result != 0) if (result != 0)
{ {
EvaluateErrorCode(result); var errorText = EvaluateErrorCode(result);
return 0; 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() private async Task CloseConnection()
{ {
if (sharp7 == null) 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); await Task.Factory.StartNew(() => sharp7.Disconnect(), CancellationToken.None, TaskCreationOptions.None, scheduler);
} }
@@ -229,19 +229,19 @@ internal class Sharp7Connector : IS7Connector
throw new ObjectDisposedException("S7Connector"); throw new ObjectDisposedException("S7Connector");
if (sharp7 == null) if (sharp7 == null)
throw new InvalidOperationException(StringResources.StrErrorS7DriverNotInitialized); throw new InvalidOperationException("S7 driver is not initialized.");
if (!IsConnected) if (!IsConnected)
throw new InvalidOperationException("Plc is not connected"); throw new InvalidOperationException("Plc is not connected");
} }
private bool EvaluateErrorCode(int errorCode) private string EvaluateErrorCode(int errorCode)
{ {
if (errorCode == 0) if (errorCode == 0)
return true; return null;
if (sharp7 == null) if (sharp7 == null)
throw new InvalidOperationException(StringResources.StrErrorS7DriverNotInitialized); throw new InvalidOperationException("S7 driver is not initialized.");
var errorText = sharp7.ErrorText(errorCode); var errorText = sharp7.ErrorText(errorCode);
Logger?.LogError($"Error Code {errorCode} {errorText}"); Logger?.LogError($"Error Code {errorCode} {errorText}");
@@ -249,7 +249,7 @@ internal class Sharp7Connector : IS7Connector
if (S7ErrorCodes.AssumeConnectionLost(errorCode)) if (S7ErrorCodes.AssumeConnectionLost(errorCode))
SetConnectionLostState(); SetConnectionLostState();
return false; return errorText;
} }
private async Task<bool> Reconnect() private async Task<bool> Reconnect()

View File

@@ -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 // Special handling for bools, which are written on a by-bit basis. Writing a complete byte would
// overwrite other bits within this byte. // overwrite other bits within this byte.
if (address.Bit == null) await s7Connector.WriteBit(address.Operand, address.Start, address.Bit!.Value, (bool) (object) value, address.DbNr, token);
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);
} }
else else
{ {