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

View File

@@ -12,10 +12,10 @@ internal interface IS7Connector : IDisposable
Task<bool> Connect();
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<ushort> 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<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.
// 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 {
}
}
/// <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>
/// Looks up a localized string similar to TCP/IP connection established..
/// </summary>

View File

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

View File

@@ -55,21 +55,26 @@ internal class Sharp7Connector : IS7Connector
public async Task<bool> 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<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();
@@ -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<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();
@@ -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<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();
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<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
// 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
{