mirror of
https://github.com/S7NetPlus/s7netplus.git
synced 2026-02-17 22:38:27 +08:00
Merge pull request #293 from scamille/fb-nullable
Add nullable support throughout the whole library.
This commit is contained in:
@@ -591,15 +591,13 @@ namespace S7.Net.UnitTest
|
||||
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(NullReferenceException))]
|
||||
public async Task Test_Async_ReadBytesReturnsNullIfPlcIsNotConnected()
|
||||
{
|
||||
using (var notConnectedPlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 0))
|
||||
{
|
||||
Assert.IsFalse(notConnectedPlc.IsConnected);
|
||||
TestClass tc = new TestClass();
|
||||
var res = await notConnectedPlc.ReadClassAsync(tc, DB2);
|
||||
Assert.Fail();
|
||||
await Assert.ThrowsExceptionAsync<PlcException>(async () => await notConnectedPlc.ReadClassAsync(tc, DB2));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -637,13 +635,12 @@ namespace S7.Net.UnitTest
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(NullReferenceException))]
|
||||
public async Task Test_Async_ReadClassWithGenericReturnsNullIfPlcIsNotConnected()
|
||||
{
|
||||
using (var notConnectedPlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 0))
|
||||
{
|
||||
Assert.IsFalse(notConnectedPlc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
|
||||
TestClass tc = await notConnectedPlc.ReadClassAsync<TestClass>(DB2);
|
||||
await Assert.ThrowsExceptionAsync<PlcException>(async () => await notConnectedPlc.ReadClassAsync<TestClass>(DB2));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -678,13 +675,12 @@ namespace S7.Net.UnitTest
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(NullReferenceException))]
|
||||
public async Task Test_Async_ReadClassWithGenericAndClassFactoryThrowsExceptionPlcIsNotConnected()
|
||||
{
|
||||
using (var notConnectedPlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 0))
|
||||
{
|
||||
Assert.IsFalse(notConnectedPlc.IsConnected);
|
||||
TestClass tc = await notConnectedPlc.ReadClassAsync(() => new TestClass(), DB2);
|
||||
await Assert.ThrowsExceptionAsync<PlcException>(async () => await notConnectedPlc.ReadClassAsync(() => new TestClass(), DB2));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -711,13 +707,12 @@ namespace S7.Net.UnitTest
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(NullReferenceException))]
|
||||
public async Task Test_Async_ReadStructThrowsExceptionPlcIsNotConnected()
|
||||
{
|
||||
using (var notConnectedPlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 0))
|
||||
{
|
||||
Assert.IsFalse(notConnectedPlc.IsConnected);
|
||||
object tsObj = await notConnectedPlc.ReadStructAsync(typeof(TestStruct), DB2);
|
||||
await Assert.ThrowsExceptionAsync<PlcException>(async () => await notConnectedPlc.ReadStructAsync(typeof(TestStruct), DB2));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -754,13 +749,12 @@ namespace S7.Net.UnitTest
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(NullReferenceException))]
|
||||
public async Task Test_Async_ReadStructWithGenericThrowsExceptionIfPlcIsNotConnected()
|
||||
{
|
||||
using (var notConnectedPlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 0))
|
||||
{
|
||||
Assert.IsFalse(notConnectedPlc.IsConnected);
|
||||
object tsObj = await notConnectedPlc.ReadStructAsync<TestStruct>(DB2);
|
||||
await Assert.ThrowsExceptionAsync<PlcException>(async () => await notConnectedPlc.ReadStructAsync<TestStruct>(DB2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,8 +54,11 @@ namespace S7.Net
|
||||
public static TPDU Read(Stream stream)
|
||||
{
|
||||
var tpkt = TPKT.Read(stream);
|
||||
if (tpkt.Length > 0) return new TPDU(tpkt);
|
||||
return null;
|
||||
if (tpkt.Length == 0)
|
||||
{
|
||||
throw new TPDUInvalidException("No protocol data received");
|
||||
}
|
||||
return new TPDU(tpkt);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -67,8 +70,11 @@ namespace S7.Net
|
||||
public static async Task<TPDU> ReadAsync(Stream stream)
|
||||
{
|
||||
var tpkt = await TPKT.ReadAsync(stream);
|
||||
if (tpkt.Length > 0) return new TPDU(tpkt);
|
||||
return null;
|
||||
if (tpkt.Length == 0)
|
||||
{
|
||||
throw new TPDUInvalidException("No protocol data received");
|
||||
}
|
||||
return new TPDU(tpkt);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
@@ -98,7 +104,6 @@ namespace S7.Net
|
||||
public static byte[] Read(Stream stream)
|
||||
{
|
||||
var segment = TPDU.Read(stream);
|
||||
if (segment == null) return null;
|
||||
|
||||
var buffer = new byte[segment.Data.Length];
|
||||
var output = new MemoryStream(buffer);
|
||||
@@ -125,7 +130,6 @@ namespace S7.Net
|
||||
public static async Task<byte[]> ReadAsync(Stream stream)
|
||||
{
|
||||
var segment = await TPDU.ReadAsync(stream);
|
||||
if (segment == null) return null;
|
||||
|
||||
var buffer = new byte[segment.Data.Length];
|
||||
var output = new MemoryStream(buffer);
|
||||
|
||||
@@ -15,8 +15,8 @@ namespace S7.Net
|
||||
private const int CONNECTION_TIMED_OUT_ERROR_CODE = 10060;
|
||||
|
||||
//TCP connection to device
|
||||
private TcpClient tcpClient;
|
||||
private NetworkStream stream;
|
||||
private TcpClient? tcpClient;
|
||||
private NetworkStream? _stream;
|
||||
|
||||
private int readTimeout = System.Threading.Timeout.Infinite;
|
||||
private int writeTimeout = System.Threading.Timeout.Infinite;
|
||||
@@ -24,27 +24,27 @@ namespace S7.Net
|
||||
/// <summary>
|
||||
/// IP address of the PLC
|
||||
/// </summary>
|
||||
public string IP { get; private set; }
|
||||
public string IP { get; }
|
||||
|
||||
/// <summary>
|
||||
/// PORT Number of the PLC, default is 102
|
||||
/// </summary>
|
||||
public int Port { get; private set; }
|
||||
public int Port { get; }
|
||||
|
||||
/// <summary>
|
||||
/// CPU type of the PLC
|
||||
/// </summary>
|
||||
public CpuType CPU { get; private set; }
|
||||
public CpuType CPU { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Rack of the PLC
|
||||
/// </summary>
|
||||
public Int16 Rack { get; private set; }
|
||||
public Int16 Rack { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Slot of the CPU of the PLC
|
||||
/// </summary>
|
||||
public Int16 Slot { get; private set; }
|
||||
public Int16 Slot { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Max PDU size this cpu supports
|
||||
|
||||
@@ -89,4 +89,25 @@ namespace S7.Net
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
internal class TPDUInvalidException : Exception
|
||||
{
|
||||
public TPDUInvalidException() : base()
|
||||
{
|
||||
}
|
||||
|
||||
public TPDUInvalidException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public TPDUInvalidException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
#if NET_FULL
|
||||
protected TPDUInvalidException(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace S7.Net
|
||||
/// <param name="varCount"></param>
|
||||
/// <param name="bitAdr"></param>
|
||||
/// <returns></returns>
|
||||
private object ParseBytes(VarType varType, byte[] bytes, int varCount, byte bitAdr = 0)
|
||||
private object? ParseBytes(VarType varType, byte[] bytes, int varCount, byte bitAdr = 0)
|
||||
{
|
||||
if (bytes == null || bytes.Length == 0)
|
||||
return null;
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
using S7.Net.Protocol;
|
||||
using System.IO;
|
||||
|
||||
namespace S7.Net
|
||||
{
|
||||
@@ -20,9 +21,14 @@ namespace S7.Net
|
||||
public async Task OpenAsync()
|
||||
{
|
||||
await ConnectAsync();
|
||||
var stream = GetStreamIfAvailable();
|
||||
|
||||
await stream.WriteAsync(ConnectionRequest.GetCOTPConnectionRequest(CPU, Rack, Slot), 0, 22);
|
||||
var response = await COTP.TPDU.ReadAsync(stream);
|
||||
if (response == null)
|
||||
{
|
||||
throw new Exception("Error reading Connection Confirm. Malformed TPDU packet");
|
||||
}
|
||||
if (response.PDUType != 0xd0) //Connect Confirm
|
||||
{
|
||||
throw new InvalidDataException("Error reading Connection Confirm", response.TPkt.Data, 1, 0x0d);
|
||||
@@ -46,9 +52,10 @@ namespace S7.Net
|
||||
tcpClient = new TcpClient();
|
||||
ConfigureConnection();
|
||||
await tcpClient.ConnectAsync(IP, Port);
|
||||
stream = tcpClient.GetStream();
|
||||
_stream = tcpClient.GetStream();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reads a number of bytes from a DB starting from a specified index. This handles more than 200 bytes with multiple requests.
|
||||
/// If the read was not successful, check LastErrorCode or LastErrorString.
|
||||
@@ -87,7 +94,7 @@ namespace S7.Net
|
||||
/// <param name="varType">Type of the variable/s that you are reading</param>
|
||||
/// <param name="bitAdr">Address of bit. If you want to read DB1.DBX200.6, set 6 to this parameter.</param>
|
||||
/// <param name="varCount"></param>
|
||||
public async Task<object> ReadAsync(DataType dataType, int db, int startByteAdr, VarType varType, int varCount, byte bitAdr = 0)
|
||||
public async Task<object?> ReadAsync(DataType dataType, int db, int startByteAdr, VarType varType, int varCount, byte bitAdr = 0)
|
||||
{
|
||||
int cntBytes = VarTypeToByteLength(varType, varCount);
|
||||
byte[] bytes = await ReadBytesAsync(dataType, db, startByteAdr, cntBytes);
|
||||
@@ -100,7 +107,7 @@ namespace S7.Net
|
||||
/// </summary>
|
||||
/// <param name="variable">Input strings like "DB1.DBX0.0", "DB20.DBD200", "MB20", "T45", etc.</param>
|
||||
/// <returns>Returns an object that contains the value. This object must be cast accordingly.</returns>
|
||||
public async Task<object> ReadAsync(string variable)
|
||||
public async Task<object?> ReadAsync(string variable)
|
||||
{
|
||||
var adr = new PLCAddress(variable);
|
||||
return await ReadAsync(adr.DataType, adr.DbNumber, adr.StartByte, adr.VarType, 1, (byte)adr.BitNumber);
|
||||
@@ -113,7 +120,7 @@ namespace S7.Net
|
||||
/// <param name="db">Address of the DB.</param>
|
||||
/// <param name="startByteAdr">Start byte address. If you want to read DB1.DBW200, this is 200.</param>
|
||||
/// <returns>Returns a struct that must be cast.</returns>
|
||||
public async Task<object> ReadStructAsync(Type structType, int db, int startByteAdr = 0)
|
||||
public async Task<object?> ReadStructAsync(Type structType, int db, int startByteAdr = 0)
|
||||
{
|
||||
int numBytes = Types.Struct.GetStructSize(structType);
|
||||
// now read the package
|
||||
@@ -168,7 +175,7 @@ namespace S7.Net
|
||||
/// <param name="db">Index of the DB; es.: 1 is for DB1</param>
|
||||
/// <param name="startByteAdr">Start byte address. If you want to read DB1.DBW200, this is 200.</param>
|
||||
/// <returns>An instance of the class with the values read from the PLC. If no data has been read, null will be returned</returns>
|
||||
public async Task<T> ReadClassAsync<T>(int db, int startByteAdr = 0) where T : class
|
||||
public async Task<T?> ReadClassAsync<T>(int db, int startByteAdr = 0) where T : class
|
||||
{
|
||||
return await ReadClassAsync(() => Activator.CreateInstance<T>(), db, startByteAdr);
|
||||
}
|
||||
@@ -182,7 +189,7 @@ namespace S7.Net
|
||||
/// <param name="db">Index of the DB; es.: 1 is for DB1</param>
|
||||
/// <param name="startByteAdr">Start byte address. If you want to read DB1.DBW200, this is 200.</param>
|
||||
/// <returns>An instance of the class with the values read from the PLC. If no data has been read, null will be returned</returns>
|
||||
public async Task<T> ReadClassAsync<T>(Func<T> classFactory, int db, int startByteAdr = 0) where T : class
|
||||
public async Task<T?> ReadClassAsync<T>(Func<T> classFactory, int db, int startByteAdr = 0) where T : class
|
||||
{
|
||||
var instance = classFactory();
|
||||
var res = await ReadClassAsync(instance, db, startByteAdr);
|
||||
@@ -208,7 +215,9 @@ namespace S7.Net
|
||||
//Snap7 seems to choke on PDU sizes above 256 even if snap7
|
||||
//replies with bigger PDU size in connection setup.
|
||||
AssertPduSizeForRead(dataItems);
|
||||
|
||||
|
||||
var stream = GetStreamIfAvailable();
|
||||
|
||||
try
|
||||
{
|
||||
// first create the header
|
||||
@@ -376,6 +385,8 @@ namespace S7.Net
|
||||
|
||||
private async Task<byte[]> ReadBytesWithSingleRequestAsync(DataType dataType, int db, int startByteAdr, int count)
|
||||
{
|
||||
var stream = GetStreamIfAvailable();
|
||||
|
||||
byte[] bytes = new byte[count];
|
||||
|
||||
// first create the header
|
||||
@@ -406,6 +417,8 @@ namespace S7.Net
|
||||
{
|
||||
AssertPduSizeForWrite(dataItems);
|
||||
|
||||
var stream = GetStreamIfAvailable();
|
||||
|
||||
var message = new ByteArray();
|
||||
var length = S7WriteMultiple.CreateRequest(message, dataItems);
|
||||
await stream.WriteAsync(message.Array, 0, length).ConfigureAwait(false);
|
||||
@@ -424,6 +437,8 @@ namespace S7.Net
|
||||
/// <returns>A task that represents the asynchronous write operation.</returns>
|
||||
private async Task WriteBytesWithASingleRequestAsync(DataType dataType, int db, int startByteAdr, byte[] value)
|
||||
{
|
||||
var stream = GetStreamIfAvailable();
|
||||
|
||||
byte[] bReceive = new byte[513];
|
||||
int varCount = 0;
|
||||
|
||||
@@ -469,6 +484,8 @@ namespace S7.Net
|
||||
|
||||
private async Task WriteBitWithASingleRequestAsync(DataType dataType, int db, int startByteAdr, int bitAdr, bool bitValue)
|
||||
{
|
||||
var stream = GetStreamIfAvailable();
|
||||
|
||||
byte[] bReceive = new byte[513];
|
||||
int varCount = 0;
|
||||
|
||||
@@ -510,5 +527,14 @@ namespace S7.Net
|
||||
throw new PlcException(ErrorCode.WriteData, exc);
|
||||
}
|
||||
}
|
||||
|
||||
private Stream GetStreamIfAvailable()
|
||||
{
|
||||
if (_stream == null)
|
||||
{
|
||||
throw new PlcException(ErrorCode.ConnectionError, "Plc is not connected");
|
||||
}
|
||||
return _stream;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace S7.Net
|
||||
|
||||
try
|
||||
{
|
||||
var stream = GetStreamIfAvailable();
|
||||
stream.Write(ConnectionRequest.GetCOTPConnectionRequest(CPU, Rack, Slot), 0, 22);
|
||||
var response = COTP.TPDU.Read(stream);
|
||||
if (response.PDUType != 0xd0) //Connect Confirm
|
||||
@@ -52,7 +53,7 @@ namespace S7.Net
|
||||
tcpClient = new TcpClient();
|
||||
ConfigureConnection();
|
||||
tcpClient.Connect(IP, Port);
|
||||
stream = tcpClient.GetStream();
|
||||
_stream = tcpClient.GetStream();
|
||||
}
|
||||
catch (SocketException sex)
|
||||
{
|
||||
@@ -106,7 +107,7 @@ namespace S7.Net
|
||||
/// <param name="varType">Type of the variable/s that you are reading</param>
|
||||
/// <param name="bitAdr">Address of bit. If you want to read DB1.DBX200.6, set 6 to this parameter.</param>
|
||||
/// <param name="varCount"></param>
|
||||
public object Read(DataType dataType, int db, int startByteAdr, VarType varType, int varCount, byte bitAdr = 0)
|
||||
public object? Read(DataType dataType, int db, int startByteAdr, VarType varType, int varCount, byte bitAdr = 0)
|
||||
{
|
||||
int cntBytes = VarTypeToByteLength(varType, varCount);
|
||||
byte[] bytes = ReadBytes(dataType, db, startByteAdr, cntBytes);
|
||||
@@ -119,8 +120,8 @@ namespace S7.Net
|
||||
/// If the read was not successful, check LastErrorCode or LastErrorString.
|
||||
/// </summary>
|
||||
/// <param name="variable">Input strings like "DB1.DBX0.0", "DB20.DBD200", "MB20", "T45", etc.</param>
|
||||
/// <returns>Returns an object that contains the value. This object must be cast accordingly.</returns>
|
||||
public object Read(string variable)
|
||||
/// <returns>Returns an object that contains the value. This object must be cast accordingly. If no data has been read, null will be returned</returns>
|
||||
public object? Read(string variable)
|
||||
{
|
||||
var adr = new PLCAddress(variable);
|
||||
return Read(adr.DataType, adr.DbNumber, adr.StartByte, adr.VarType, 1, (byte)adr.BitNumber);
|
||||
@@ -132,8 +133,8 @@ namespace S7.Net
|
||||
/// <param name="structType">Type of the struct to be readed (es.: TypeOf(MyStruct)).</param>
|
||||
/// <param name="db">Address of the DB.</param>
|
||||
/// <param name="startByteAdr">Start byte address. If you want to read DB1.DBW200, this is 200.</param>
|
||||
/// <returns>Returns a struct that must be cast.</returns>
|
||||
public object ReadStruct(Type structType, int db, int startByteAdr = 0)
|
||||
/// <returns>Returns a struct that must be cast. If no data has been read, null will be returned</returns>
|
||||
public object? ReadStruct(Type structType, int db, int startByteAdr = 0)
|
||||
{
|
||||
int numBytes = Struct.GetStructSize(structType);
|
||||
// now read the package
|
||||
@@ -188,7 +189,7 @@ namespace S7.Net
|
||||
/// <param name="db">Index of the DB; es.: 1 is for DB1</param>
|
||||
/// <param name="startByteAdr">Start byte address. If you want to read DB1.DBW200, this is 200.</param>
|
||||
/// <returns>An instance of the class with the values read from the PLC. If no data has been read, null will be returned</returns>
|
||||
public T ReadClass<T>(int db, int startByteAdr = 0) where T : class
|
||||
public T? ReadClass<T>(int db, int startByteAdr = 0) where T : class
|
||||
{
|
||||
return ReadClass(() => Activator.CreateInstance<T>(), db, startByteAdr);
|
||||
}
|
||||
@@ -202,7 +203,7 @@ namespace S7.Net
|
||||
/// <param name="db">Index of the DB; es.: 1 is for DB1</param>
|
||||
/// <param name="startByteAdr">Start byte address. If you want to read DB1.DBW200, this is 200.</param>
|
||||
/// <returns>An instance of the class with the values read from the PLC. If no data has been read, null will be returned</returns>
|
||||
public T ReadClass<T>(Func<T> classFactory, int db, int startByteAdr = 0) where T : class
|
||||
public T? ReadClass<T>(Func<T> classFactory, int db, int startByteAdr = 0) where T : class
|
||||
{
|
||||
var instance = classFactory();
|
||||
int readBytes = ReadClass(instance, db, startByteAdr);
|
||||
@@ -340,6 +341,7 @@ namespace S7.Net
|
||||
|
||||
private byte[] ReadBytesWithSingleRequest(DataType dataType, int db, int startByteAdr, int count)
|
||||
{
|
||||
var stream = GetStreamIfAvailable();
|
||||
byte[] bytes = new byte[count];
|
||||
try
|
||||
{
|
||||
@@ -375,6 +377,8 @@ namespace S7.Net
|
||||
{
|
||||
AssertPduSizeForWrite(dataItems);
|
||||
|
||||
var stream = GetStreamIfAvailable();
|
||||
|
||||
var message = new ByteArray();
|
||||
var length = S7WriteMultiple.CreateRequest(message, dataItems);
|
||||
stream.Write(message.Array, 0, length);
|
||||
@@ -385,6 +389,7 @@ namespace S7.Net
|
||||
|
||||
private void WriteBytesWithASingleRequest(DataType dataType, int db, int startByteAdr, byte[] value)
|
||||
{
|
||||
var stream = GetStreamIfAvailable();
|
||||
int varCount = 0;
|
||||
try
|
||||
{
|
||||
@@ -429,6 +434,7 @@ namespace S7.Net
|
||||
|
||||
private void WriteBitWithASingleRequest(DataType dataType, int db, int startByteAdr, int bitAdr, bool bitValue)
|
||||
{
|
||||
var stream = GetStreamIfAvailable();
|
||||
int varCount = 0;
|
||||
|
||||
try
|
||||
@@ -484,6 +490,8 @@ namespace S7.Net
|
||||
//replies with bigger PDU size in connection setup.
|
||||
AssertPduSizeForRead(dataItems);
|
||||
|
||||
var stream = GetStreamIfAvailable();
|
||||
|
||||
try
|
||||
{
|
||||
// first create the header
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace S7.Net.Protocol
|
||||
|
||||
IList<byte> itemResults = new ArraySegment<byte>(message, 14, dataItems.Length);
|
||||
|
||||
List<Exception> errors = null;
|
||||
List<Exception>? errors = null;
|
||||
|
||||
for (int i = 0; i < dataItems.Length; i++)
|
||||
{
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<PackageTags>PLC Siemens Communication S7</PackageTags>
|
||||
<Copyright>Derek Heiser 2015</Copyright>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<Nullable>Enable</Nullable>
|
||||
<DebugType>portable</DebugType>
|
||||
<EmbedAllSources>true</EmbedAllSources>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
|
||||
@@ -10,10 +10,19 @@ namespace S7.Net
|
||||
/// </summary>
|
||||
internal class TPKT
|
||||
{
|
||||
|
||||
|
||||
public byte Version;
|
||||
public byte Reserved1;
|
||||
public int Length;
|
||||
public byte[] Data;
|
||||
private TPKT(byte version, byte reserved1, int length, byte[] data)
|
||||
{
|
||||
Version = version;
|
||||
Reserved1 = reserved1;
|
||||
Length = length;
|
||||
Data = data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a TPKT from the socket
|
||||
@@ -24,21 +33,28 @@ namespace S7.Net
|
||||
{
|
||||
var buf = new byte[4];
|
||||
int len = stream.Read(buf, 0, 4);
|
||||
if (len < 4) throw new TPKTInvalidException("TPKT is incomplete / invalid");
|
||||
var pkt = new TPKT
|
||||
if (len < 4) throw new TPKTInvalidException("TPKT header incomplete / invalid");
|
||||
var version = buf[0];
|
||||
var reserved1 = buf[1];
|
||||
var length = buf[2] * 256 + buf[3]; //BigEndian
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
Version = buf[0],
|
||||
Reserved1 = buf[1],
|
||||
Length = buf[2] * 256 + buf[3] //BigEndian
|
||||
};
|
||||
if (pkt.Length > 0)
|
||||
{
|
||||
pkt.Data = new byte[pkt.Length - 4];
|
||||
len = stream.Read(pkt.Data, 0, pkt.Length - 4);
|
||||
if (len < pkt.Length - 4)
|
||||
throw new TPKTInvalidException("TPKT is incomplete / invalid");
|
||||
throw new TPKTInvalidException("TPKT payload length is zero");
|
||||
}
|
||||
return pkt;
|
||||
|
||||
var data = new byte[length - 4];
|
||||
len = stream.Read(data, 0, length - 4);
|
||||
if (len < length - 4)
|
||||
throw new TPKTInvalidException("TPKT payload incomplete / invalid");
|
||||
|
||||
return new TPKT
|
||||
(
|
||||
version: version,
|
||||
reserved1: reserved1,
|
||||
length: length,
|
||||
data: data
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -50,20 +66,28 @@ namespace S7.Net
|
||||
{
|
||||
var buf = new byte[4];
|
||||
int len = await stream.ReadAsync(buf, 0, 4);
|
||||
if (len < 4) throw new TPKTInvalidException("TPKT is incomplete / invalid");
|
||||
var pkt = new TPKT
|
||||
if (len < 4) throw new TPKTInvalidException("TPKT header incomplete / invalid");
|
||||
var version = buf[0];
|
||||
var reserved1 = buf[1];
|
||||
var length = buf[2] * 256 + buf[3]; //BigEndian
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
Version = buf[0],
|
||||
Reserved1 = buf[1],
|
||||
Length = buf[2] * 256 + buf[3] //BigEndian
|
||||
};
|
||||
if (pkt.Length > 0)
|
||||
{
|
||||
pkt.Data = new byte[pkt.Length - 4];
|
||||
len = await stream.ReadAsync(pkt.Data, 0, pkt.Length - 4);
|
||||
if (len < pkt.Length - 4) throw new TPKTInvalidException("TPKT is incomplete / invalid");
|
||||
throw new TPKTInvalidException("TPKT payload length is zero");
|
||||
}
|
||||
return pkt;
|
||||
|
||||
var data = new byte[length - 4];
|
||||
len = await stream.ReadAsync(data, 0, length - 4);
|
||||
if (len < length - 4)
|
||||
throw new TPKTInvalidException("TPKT payload incomplete / invalid");
|
||||
|
||||
return new TPKT
|
||||
(
|
||||
version: version,
|
||||
reserved1: reserved1,
|
||||
length: length,
|
||||
data: data
|
||||
);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
||||
@@ -106,9 +106,9 @@ namespace S7.Net.Types
|
||||
return numBytes;
|
||||
}
|
||||
|
||||
private static object GetPropertyValue(Type propertyType, byte[] bytes, ref double numBytes)
|
||||
private static object? GetPropertyValue(Type propertyType, byte[] bytes, ref double numBytes)
|
||||
{
|
||||
object value = null;
|
||||
object? value = null;
|
||||
|
||||
switch (propertyType.Name)
|
||||
{
|
||||
@@ -245,7 +245,7 @@ namespace S7.Net.Types
|
||||
{
|
||||
int bytePos = 0;
|
||||
int bitPos = 0;
|
||||
byte[] bytes2 = null;
|
||||
byte[]? bytes2 = null;
|
||||
|
||||
switch (propertyValue.GetType().Name)
|
||||
{
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace S7.Net.Types
|
||||
/// <summary>
|
||||
/// Contains the value of the memory area after the read has been executed
|
||||
/// </summary>
|
||||
public object Value { get; set; }
|
||||
public object? Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance of DataItem
|
||||
@@ -83,7 +83,14 @@ namespace S7.Net.Types
|
||||
var dataItem = FromAddress(address);
|
||||
dataItem.Value = value;
|
||||
|
||||
if (typeof(T).IsArray) dataItem.Count = ((Array) dataItem.Value).Length;
|
||||
if (typeof(T).IsArray)
|
||||
{
|
||||
var array = ((Array?)dataItem.Value);
|
||||
if ( array != null)
|
||||
{
|
||||
dataItem.Count = array.Length;
|
||||
}
|
||||
}
|
||||
|
||||
return dataItem;
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace S7.Net.Types
|
||||
/// <param name="structType">The struct type</param>
|
||||
/// <param name="bytes">The array of bytes</param>
|
||||
/// <returns>The object depending on the struct type or null if fails(array-length != struct-length</returns>
|
||||
public static object FromBytes(Type structType, byte[] bytes)
|
||||
public static object? FromBytes(Type structType, byte[] bytes)
|
||||
{
|
||||
if (bytes == null)
|
||||
return null;
|
||||
@@ -198,7 +198,7 @@ namespace S7.Net.Types
|
||||
|
||||
int size = Struct.GetStructSize(type);
|
||||
byte[] bytes = new byte[size];
|
||||
byte[] bytes2 = null;
|
||||
byte[]? bytes2 = null;
|
||||
|
||||
int bytePos = 0;
|
||||
int bitPos = 0;
|
||||
|
||||
Reference in New Issue
Block a user