Merge pull request #298 from scamille/fb-real

Add LReal support, kill old "Double" sham.
This commit is contained in:
Michael Croes
2020-09-04 21:03:00 +02:00
committed by GitHub
15 changed files with 301 additions and 207 deletions

View File

@@ -35,12 +35,12 @@ namespace S7.Net.UnitTest.Helpers
/// <summary>
/// DB1.DBD4
/// </summary>
public double RealVariableDouble { get; set; }
public double LRealVariable { get; set; }
/// <summary>
/// DB1.DBD8
/// </summary>
public float RealVariableFloat { get; set; }
public float RealVariable { get; set; }
/// <summary>
/// DB1.DBD12

View File

@@ -35,12 +35,12 @@ namespace S7.Net.UnitTest.Helpers
/// <summary>
/// DB1.DBD4
/// </summary>
public double RealVariableDouble;
public double LRealVariable;
/// <summary>
/// DB1.DBD8
/// </summary>
public float RealVariableFloat;
public float RealVariable;
/// <summary>
/// DB1.DBD12

View File

@@ -101,20 +101,13 @@ namespace S7.Net.UnitTest
/// <summary>
/// Read/Write a single REAL with a single request.
/// Test that writing a double and reading it gives the correct value.
/// Test that writing a float and reading it gives the correct value.
/// </summary>
[TestMethod]
public async Task Test_Async_WriteAndReadRealVariables()
{
Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
// Reading and writing a double is quite complicated, because it needs to be converted to DWord before the write,
// then reconvert to double after the read.
double val = 35.68729;
await plc.WriteAsync("DB1.DBD40", val.ConvertToUInt());
double result = ((uint)await plc.ReadAsync("DB1.DBD40")).ConvertToDouble();
Assert.AreEqual(val, Math.Round(result, 5)); // float lose precision, so i need to round it
// Reading and writing a float is quite complicated, because it needs to be converted to DWord before the write,
// then reconvert to float after the read. Float values can contain only 7 digits, so no precision is lost.
float val2 = 1234567;
@@ -162,8 +155,8 @@ namespace S7.Net.UnitTest
BitVariable10 = true,
DIntVariable = -100000,
IntVariable = -15000,
RealVariableDouble = -154.789,
RealVariableFloat = -154.789f,
LRealVariable = -154.789,
RealVariable = -154.789f,
DWordVariable = 850
};
@@ -175,8 +168,8 @@ namespace S7.Net.UnitTest
Assert.AreEqual(tc.BitVariable10, tc2.BitVariable10);
Assert.AreEqual(tc.DIntVariable, tc2.DIntVariable);
Assert.AreEqual(tc.IntVariable, tc2.IntVariable);
Assert.AreEqual(tc.RealVariableDouble, Math.Round(tc2.RealVariableDouble, 3));
Assert.AreEqual(tc.RealVariableFloat, tc2.RealVariableFloat);
Assert.AreEqual(tc.LRealVariable, tc2.LRealVariable);
Assert.AreEqual(tc.RealVariable, tc2.RealVariable);
Assert.AreEqual(tc.DWordVariable, tc2.DWordVariable);
}
@@ -219,8 +212,8 @@ namespace S7.Net.UnitTest
BitVariable10 = true,
DIntVariable = -100000,
IntVariable = -15000,
RealVariableDouble = -154.789,
RealVariableFloat = -154.789f,
LRealVariable = -154.789,
RealVariable = -154.789f,
DWordVariable = 850
};
plc.WriteStruct(tc, DB2);
@@ -230,8 +223,8 @@ namespace S7.Net.UnitTest
Assert.AreEqual(tc.BitVariable10, tc2.BitVariable10);
Assert.AreEqual(tc.DIntVariable, tc2.DIntVariable);
Assert.AreEqual(tc.IntVariable, tc2.IntVariable);
Assert.AreEqual(tc.RealVariableDouble, Math.Round(tc2.RealVariableDouble, 3));
Assert.AreEqual(tc.RealVariableFloat, tc2.RealVariableFloat);
Assert.AreEqual(tc.LRealVariable, tc2.LRealVariable);
Assert.AreEqual(tc.RealVariable, tc2.RealVariable);
Assert.AreEqual(tc.DWordVariable, tc2.DWordVariable);
}
@@ -584,8 +577,8 @@ namespace S7.Net.UnitTest
BitVariable10 = true,
DIntVariable = -100000,
IntVariable = -15000,
RealVariableDouble = -154.789,
RealVariableFloat = -154.789f,
LRealVariable = -154.789,
RealVariable = -154.789f,
DWordVariable = 850
};
@@ -599,8 +592,8 @@ namespace S7.Net.UnitTest
Assert.AreEqual(tc.BitVariable10, tc2.BitVariable10);
Assert.AreEqual(tc.DIntVariable, tc2.DIntVariable);
Assert.AreEqual(tc.IntVariable, tc2.IntVariable);
Assert.AreEqual(tc.RealVariableDouble, tc2.RealVariableDouble, 0.1);
Assert.AreEqual(tc.RealVariableFloat, tc2.RealVariableFloat);
Assert.AreEqual(tc.LRealVariable, tc2.LRealVariable, 0.1);
Assert.AreEqual(tc.RealVariable, tc2.RealVariable);
Assert.AreEqual(tc.DWordVariable, tc2.DWordVariable);
Assert.AreEqual(TestClassWithPrivateSetters.PRIVATE_SETTER_VALUE, tc2.PrivateSetterProperty);
@@ -632,8 +625,8 @@ namespace S7.Net.UnitTest
BitVariable10 = true,
DIntVariable = -100000,
IntVariable = -15000,
RealVariableDouble = -154.789,
RealVariableFloat = -154.789f,
LRealVariable = -154.789,
RealVariable = -154.789f,
DWordVariable = 850
};
@@ -649,8 +642,8 @@ namespace S7.Net.UnitTest
Assert.AreEqual(tc2.BitVariable10, tc2Generic.BitVariable10);
Assert.AreEqual(tc2.DIntVariable, tc2Generic.DIntVariable);
Assert.AreEqual(tc2.IntVariable, tc2Generic.IntVariable);
Assert.AreEqual(Math.Round(tc2.RealVariableDouble, 3), Math.Round(tc2Generic.RealVariableDouble, 3));
Assert.AreEqual(tc2.RealVariableFloat, tc2Generic.RealVariableFloat);
Assert.AreEqual(Math.Round(tc2.LRealVariable, 3), Math.Round(tc2Generic.LRealVariable, 3));
Assert.AreEqual(tc2.RealVariable, tc2Generic.RealVariable);
Assert.AreEqual(tc2.DWordVariable, tc2Generic.DWordVariable);
}
@@ -675,8 +668,8 @@ namespace S7.Net.UnitTest
BitVariable10 = true,
DIntVariable = -100000,
IntVariable = -15000,
RealVariableDouble = -154.789,
RealVariableFloat = -154.789f,
LRealVariable = -154.789,
RealVariable = -154.789f,
DWordVariable = 850
};
@@ -689,8 +682,8 @@ namespace S7.Net.UnitTest
Assert.AreEqual(tc2Generic.BitVariable00, tc2GenericWithClassFactory.BitVariable00);
Assert.AreEqual(tc2Generic.BitVariable10, tc2GenericWithClassFactory.BitVariable10);
Assert.AreEqual(tc2Generic.DIntVariable, tc2GenericWithClassFactory.DIntVariable);
Assert.AreEqual(Math.Round(tc2Generic.RealVariableDouble, 3), Math.Round(tc2GenericWithClassFactory.RealVariableDouble, 3));
Assert.AreEqual(tc2Generic.RealVariableFloat, tc2GenericWithClassFactory.RealVariableFloat);
Assert.AreEqual(Math.Round(tc2Generic.LRealVariable, 3), Math.Round(tc2GenericWithClassFactory.LRealVariable, 3));
Assert.AreEqual(tc2Generic.RealVariable, tc2GenericWithClassFactory.RealVariable);
Assert.AreEqual(tc2Generic.DWordVariable, tc2GenericWithClassFactory.DWordVariable);
}
@@ -747,8 +740,8 @@ namespace S7.Net.UnitTest
BitVariable10 = true,
DIntVariable = -100000,
IntVariable = -15000,
RealVariableDouble = -154.789,
RealVariableFloat = -154.789f,
LRealVariable = -154.789,
RealVariable = -154.789f,
DWordVariable = 850
};
@@ -763,8 +756,8 @@ namespace S7.Net.UnitTest
Assert.AreEqual(ts2.BitVariable10, ts2Generic.BitVariable10);
Assert.AreEqual(ts2.DIntVariable, ts2Generic.DIntVariable);
Assert.AreEqual(ts2.IntVariable, ts2Generic.IntVariable);
Assert.AreEqual(Math.Round(ts2.RealVariableDouble, 3), Math.Round(ts2Generic.RealVariableDouble, 3));
Assert.AreEqual(ts2.RealVariableFloat, ts2Generic.RealVariableFloat);
Assert.AreEqual(ts2.LRealVariable, ts2Generic.LRealVariable);
Assert.AreEqual(ts2.RealVariable, ts2Generic.RealVariable);
Assert.AreEqual(ts2.DWordVariable, ts2Generic.DWordVariable);
}
@@ -792,8 +785,8 @@ namespace S7.Net.UnitTest
BitVariable10 = true,
DIntVariable = -100000,
IntVariable = -15000,
RealVariableDouble = -154.789,
RealVariableFloat = -154.789f,
LRealVariable = -154.789,
RealVariable = -154.789f,
DWordVariable = 850
};
plc.WriteClass(tc, DB2);
@@ -883,17 +876,6 @@ namespace S7.Net.UnitTest
Assert.AreEqual(tc.CustomTypes[1].Bools[1], tc2.CustomTypes[1].Bools[1]);
}
[TestMethod]
public async Task Test_Async_ReadWriteDouble()
{
double test_value = 55.66;
await plc.WriteAsync("DB1.DBD0", test_value);
var helper = await plc.ReadAsync("DB1.DBD0");
double test_value2 = Conversion.ConvertToDouble((uint)helper);
Assert.AreEqual(test_value, test_value2, 0.01, "Compare Write/Read"); //Need delta here because S7 only has 32 bit reals
}
[TestMethod]
public async Task Test_Async_ReadWriteSingle()
{

View File

@@ -146,20 +146,13 @@ namespace S7.Net.UnitTest
/// <summary>
/// Read/Write a single REAL with a single request.
/// Test that writing a double and reading it gives the correct value.
/// Test that writing a float and reading it gives the correct value.
/// </summary>
[TestMethod]
public void T03_WriteAndReadRealVariables()
{
Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
// Reading and writing a double is quite complicated, because it needs to be converted to DWord before the write,
// then reconvert to double after the read.
double val = 35.68729;
plc.Write("DB1.DBD40", val.ConvertToUInt());
double result = ((uint)plc.Read("DB1.DBD40")).ConvertToDouble();
Assert.AreEqual(val, Math.Round(result, 5)); // float lose precision, so i need to round it
// Reading and writing a float is quite complicated, because it needs to be converted to DWord before the write,
// then reconvert to float after the read. Float values can contain only 7 digits, so no precision is lost.
float val2 = 1234567;
@@ -186,8 +179,8 @@ namespace S7.Net.UnitTest
tc.BitVariable10 = true;
tc.DIntVariable = -100000;
tc.IntVariable = -15000;
tc.RealVariableDouble = -154.789;
tc.RealVariableFloat = -154.789f;
tc.LRealVariable = -154.789;
tc.RealVariable = -154.789f;
tc.DWordVariable = 850;
plc.WriteClass(tc, DB2);
TestClass tc2 = new TestClass();
@@ -197,8 +190,8 @@ namespace S7.Net.UnitTest
Assert.AreEqual(tc.BitVariable10, tc2.BitVariable10);
Assert.AreEqual(tc.DIntVariable, tc2.DIntVariable);
Assert.AreEqual(tc.IntVariable, tc2.IntVariable);
Assert.AreEqual(Math.Round(tc.RealVariableDouble, 3), Math.Round(tc2.RealVariableDouble, 3));
Assert.AreEqual(tc.RealVariableFloat, tc2.RealVariableFloat);
Assert.AreEqual(tc.LRealVariable, tc2.LRealVariable);
Assert.AreEqual(tc.RealVariable, tc2.RealVariable);
Assert.AreEqual(tc.DWordVariable, tc2.DWordVariable);
}
@@ -215,8 +208,8 @@ namespace S7.Net.UnitTest
tc.BitVariable10 = true;
tc.DIntVariable = -100000;
tc.IntVariable = -15000;
tc.RealVariableDouble = -154.789;
tc.RealVariableFloat = -154.789f;
tc.LRealVariable = -154.789;
tc.RealVariable = -154.789f;
tc.DWordVariable = 850;
plc.WriteStruct(tc, DB2);
// Values that are read from a struct are stored in a new struct, returned by the funcion ReadStruct
@@ -225,8 +218,8 @@ namespace S7.Net.UnitTest
Assert.AreEqual(tc.BitVariable10, tc2.BitVariable10);
Assert.AreEqual(tc.DIntVariable, tc2.DIntVariable);
Assert.AreEqual(tc.IntVariable, tc2.IntVariable);
Assert.AreEqual(tc.RealVariableDouble, Math.Round(tc2.RealVariableDouble, 3));
Assert.AreEqual(tc.RealVariableFloat, tc2.RealVariableFloat);
Assert.AreEqual(tc.LRealVariable, tc2.LRealVariable);
Assert.AreEqual(tc.RealVariable, tc2.RealVariable);
Assert.AreEqual(tc.DWordVariable, tc2.DWordVariable);
}
@@ -575,8 +568,8 @@ namespace S7.Net.UnitTest
tc.BitVariable10 = true;
tc.DIntVariable = -100000;
tc.IntVariable = -15000;
tc.RealVariableDouble = -154.789;
tc.RealVariableFloat = -154.789f;
tc.LRealVariable = -154.789;
tc.RealVariable = -154.789f;
tc.DWordVariable = 850;
plc.WriteClass(tc, DB2);
@@ -588,8 +581,8 @@ namespace S7.Net.UnitTest
Assert.AreEqual(tc.BitVariable10, tc2.BitVariable10);
Assert.AreEqual(tc.DIntVariable, tc2.DIntVariable);
Assert.AreEqual(tc.IntVariable, tc2.IntVariable);
Assert.AreEqual(Math.Round(tc.RealVariableDouble, 3), Math.Round(tc2.RealVariableDouble, 3));
Assert.AreEqual(tc.RealVariableFloat, tc2.RealVariableFloat);
Assert.AreEqual(tc.LRealVariable, tc2.LRealVariable);
Assert.AreEqual(tc.RealVariable, tc2.RealVariable);
Assert.AreEqual(tc.DWordVariable, tc2.DWordVariable);
Assert.AreEqual(TestClassWithPrivateSetters.PRIVATE_SETTER_VALUE, tc2.PrivateSetterProperty);
@@ -620,8 +613,8 @@ namespace S7.Net.UnitTest
tc.BitVariable10 = true;
tc.DIntVariable = -100000;
tc.IntVariable = -15000;
tc.RealVariableDouble = -154.789;
tc.RealVariableFloat = -154.789f;
tc.LRealVariable = -154.789;
tc.RealVariable = -154.789f;
tc.DWordVariable = 850;
plc.WriteClass(tc, DB2);
@@ -635,8 +628,8 @@ namespace S7.Net.UnitTest
Assert.AreEqual(tc2.BitVariable10, tc2Generic.BitVariable10);
Assert.AreEqual(tc2.DIntVariable, tc2Generic.DIntVariable);
Assert.AreEqual(tc2.IntVariable, tc2Generic.IntVariable);
Assert.AreEqual(Math.Round(tc2.RealVariableDouble, 3), Math.Round(tc2Generic.RealVariableDouble, 3));
Assert.AreEqual(tc2.RealVariableFloat, tc2Generic.RealVariableFloat);
Assert.AreEqual(Math.Round(tc2.LRealVariable, 3), Math.Round(tc2Generic.LRealVariable, 3));
Assert.AreEqual(tc2.RealVariable, tc2Generic.RealVariable);
Assert.AreEqual(tc2.DWordVariable, tc2Generic.DWordVariable);
}
@@ -663,8 +656,8 @@ namespace S7.Net.UnitTest
tc.BitVariable10 = true;
tc.DIntVariable = -100000;
tc.IntVariable = -15000;
tc.RealVariableDouble = -154.789;
tc.RealVariableFloat = -154.789f;
tc.LRealVariable = -154.789;
tc.RealVariable = -154.789f;
tc.DWordVariable = 850;
plc.WriteClass(tc, DB2);
@@ -677,8 +670,8 @@ namespace S7.Net.UnitTest
Assert.AreEqual(tc2Generic.BitVariable10, tc2GenericWithClassFactory.BitVariable10);
Assert.AreEqual(tc2Generic.DIntVariable, tc2GenericWithClassFactory.DIntVariable);
Assert.AreEqual(tc2Generic.IntVariable, tc2GenericWithClassFactory.IntVariable);
Assert.AreEqual(Math.Round(tc2Generic.RealVariableDouble, 3), Math.Round(tc2GenericWithClassFactory.RealVariableDouble, 3));
Assert.AreEqual(tc2Generic.RealVariableFloat, tc2GenericWithClassFactory.RealVariableFloat);
Assert.AreEqual(Math.Round(tc2Generic.LRealVariable, 3), Math.Round(tc2GenericWithClassFactory.LRealVariable, 3));
Assert.AreEqual(tc2Generic.RealVariable, tc2GenericWithClassFactory.RealVariable);
Assert.AreEqual(tc2Generic.DWordVariable, tc2GenericWithClassFactory.DWordVariable);
}
@@ -786,8 +779,8 @@ namespace S7.Net.UnitTest
ts.BitVariable10 = true;
ts.DIntVariable = -100000;
ts.IntVariable = -15000;
ts.RealVariableDouble = -154.789;
ts.RealVariableFloat = -154.789f;
ts.LRealVariable = -154.789;
ts.RealVariable = -154.789f;
ts.DWordVariable = 850;
plc.WriteStruct(ts, DB2);
@@ -800,8 +793,8 @@ namespace S7.Net.UnitTest
Assert.AreEqual(ts2.BitVariable10, ts2Generic.BitVariable10);
Assert.AreEqual(ts2.DIntVariable, ts2Generic.DIntVariable);
Assert.AreEqual(ts2.IntVariable, ts2Generic.IntVariable);
Assert.AreEqual(Math.Round(ts2.RealVariableDouble, 3), Math.Round(ts2Generic.RealVariableDouble, 3));
Assert.AreEqual(ts2.RealVariableFloat, ts2Generic.RealVariableFloat);
Assert.AreEqual(ts2.LRealVariable, ts2Generic.LRealVariable);
Assert.AreEqual(ts2.RealVariable, ts2Generic.RealVariable);
Assert.AreEqual(ts2.DWordVariable, ts2Generic.DWordVariable);
}
@@ -831,8 +824,8 @@ namespace S7.Net.UnitTest
tc.BitVariable10 = true;
tc.DIntVariable = -100000;
tc.IntVariable = -15000;
tc.RealVariableDouble = -154.789;
tc.RealVariableFloat = -154.789f;
tc.LRealVariable = -154.789;
tc.RealVariable = -154.789f;
tc.DWordVariable = 850;
plc.WriteClass(tc, DB2);
@@ -948,11 +941,10 @@ namespace S7.Net.UnitTest
public void T26_ReadWriteDouble()
{
double test_value = 55.66;
plc.Write("DB1.DBD0", test_value);
var helper = plc.Read("DB1.DBD0");
double test_value2 = Conversion.ConvertToDouble((uint)helper);
plc.Write(DataType.DataBlock, 1, 0, test_value);
var result = (double)plc.Read(DataType.DataBlock, 1, 0, VarType.LReal, 1);
Assert.AreEqual(test_value, test_value2, 0.01, "Compare Write/Read"); //Need delta here because S7 only has 32 bit reals
Assert.AreEqual(test_value, result, "Compare Write/Read");
}
[TestMethod]

View File

@@ -199,19 +199,6 @@ namespace S7.Net
return output;
}
/// <summary>
/// Converts from double to DWord (DBD)
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[Obsolete("Double support is obsolete. Use ConvertToUInt(float) instead.")]
public static UInt32 ConvertToUInt(this double input)
{
uint output;
output = S7.Net.Types.DWord.FromByteArray(S7.Net.Types.Double.ToByteArray(input));
return output;
}
/// <summary>
/// Converts from float to DWord (DBD)
/// </summary>
@@ -220,20 +207,7 @@ namespace S7.Net
public static UInt32 ConvertToUInt(this float input)
{
uint output;
output = S7.Net.Types.DWord.FromByteArray(S7.Net.Types.Single.ToByteArray(input));
return output;
}
/// <summary>
/// Converts from DWord (DBD) to double
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[Obsolete("Double support is obsolete. Use ConvertToFloat(uint) instead.")]
public static double ConvertToDouble(this uint input)
{
double output;
output = S7.Net.Types.Double.FromByteArray(S7.Net.Types.DWord.ToByteArray(input));
output = S7.Net.Types.DWord.FromByteArray(S7.Net.Types.Real.ToByteArray(input));
return output;
}
@@ -245,7 +219,7 @@ namespace S7.Net
public static float ConvertToFloat(this uint input)
{
float output;
output = S7.Net.Types.Single.FromByteArray(S7.Net.Types.DWord.ToByteArray(input));
output = S7.Net.Types.Real.FromByteArray(S7.Net.Types.DWord.ToByteArray(input));
return output;
}
}

View File

@@ -163,6 +163,11 @@
/// </summary>
Real,
/// <summary>
/// LReal variable type (64 bits, 8 bytes)
/// </summary>
LReal,
/// <summary>
/// String variable type (variable)
/// </summary>

View File

@@ -111,9 +111,14 @@ namespace S7.Net
return DInt.ToArray(bytes);
case VarType.Real:
if (varCount == 1)
return Types.Single.FromByteArray(bytes);
return Types.Real.FromByteArray(bytes);
else
return Types.Single.ToArray(bytes);
return Types.Real.ToArray(bytes);
case VarType.LReal:
if (varCount == 1)
return Types.LReal.FromByteArray(bytes);
else
return Types.LReal.ToArray(bytes);
case VarType.String:
return Types.String.FromByteArray(bytes);
@@ -192,6 +197,7 @@ namespace S7.Net
case VarType.DInt:
case VarType.Real:
return varCount * 4;
case VarType.LReal:
case VarType.DateTime:
return varCount * 8;
case VarType.DateTimeLong:

View File

@@ -37,10 +37,10 @@ namespace S7.Net.Protocol
return Types.DInt.ToByteArray((Int32)value);
case "UInt32":
return Types.DWord.ToByteArray((UInt32)value);
case "Double":
return Types.Double.ToByteArray((double)value);
case "Single":
return Types.Single.ToByteArray((float)value);
return Types.Real.ToByteArray((float)value);
case "Double":
return Types.LReal.ToByteArray((double)value);
case "DateTime":
return Types.DateTime.ToByteArray((System.DateTime) value);
case "Byte[]":
@@ -53,10 +53,10 @@ namespace S7.Net.Protocol
return Types.DInt.ToByteArray((Int32[])value);
case "UInt32[]":
return Types.DWord.ToByteArray((UInt32[])value);
case "Double[]":
return Types.Double.ToByteArray((double[])value);
case "Single[]":
return Types.Single.ToByteArray((float[])value);
return Types.Real.ToByteArray((float[])value);
case "Double[]":
return Types.LReal.ToByteArray((double[])value);
case "String":
// Hack: This is backwards compatible with the old code, but functionally it's broken
// if the consumer does not pay attention to string length.

View File

@@ -51,12 +51,17 @@ namespace S7.Net.Types
numBytes += 4;
break;
case "Single":
case "Double":
numBytes = Math.Ceiling(numBytes);
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
numBytes++;
numBytes += 4;
break;
case "Double":
numBytes = Math.Ceiling(numBytes);
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
numBytes++;
numBytes += 8;
break;
default:
var propertyClass = Activator.CreateInstance(type);
numBytes = GetClassSize(propertyClass, numBytes, true);
@@ -168,12 +173,12 @@ namespace S7.Net.Types
bytes[(int)numBytes + 3]);
numBytes += 4;
break;
case "Double":
case "Single":
numBytes = Math.Ceiling(numBytes);
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
numBytes++;
// hier auswerten
value = Double.FromByteArray(
value = Real.FromByteArray(
new byte[] {
bytes[(int)numBytes],
bytes[(int)numBytes + 1],
@@ -181,18 +186,15 @@ namespace S7.Net.Types
bytes[(int)numBytes + 3] });
numBytes += 4;
break;
case "Single":
case "Double":
numBytes = Math.Ceiling(numBytes);
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
numBytes++;
var buffer = new byte[8];
Array.Copy(bytes, (int)numBytes, buffer, 0, 8);
// hier auswerten
value = Single.FromByteArray(
new byte[] {
bytes[(int)numBytes],
bytes[(int)numBytes + 1],
bytes[(int)numBytes + 2],
bytes[(int)numBytes + 3] });
numBytes += 4;
value = LReal.FromByteArray(buffer);
numBytes += 8;
break;
default:
var propClass = Activator.CreateInstance(propertyType);
@@ -277,11 +279,11 @@ namespace S7.Net.Types
case "UInt32":
bytes2 = DWord.ToByteArray((UInt32)propertyValue);
break;
case "Double":
bytes2 = Double.ToByteArray((double)propertyValue);
break;
case "Single":
bytes2 = Single.ToByteArray((float)propertyValue);
bytes2 = Real.ToByteArray((float)propertyValue);
break;
case "Double":
bytes2 = LReal.ToByteArray((double)propertyValue);
break;
default:
numBytes = ToBytes(propertyValue, bytes, numBytes);

View File

@@ -5,27 +5,13 @@ namespace S7.Net.Types
/// <summary>
/// Contains the conversion methods to convert Real from S7 plc to C# double.
/// </summary>
[Obsolete("Class Double is obsolete. Use Real instead for 32bit floating point, or LReal for 64bit floating point.")]
public static class Double
{
/// <summary>
/// Converts a S7 Real (4 bytes) to double
/// </summary>
public static double FromByteArray(byte[] bytes)
{
if (bytes.Length != 4)
{
throw new ArgumentException("Wrong number of bytes. Bytes array must contain 4 bytes.");
}
// sps uses bigending so we have to reverse if platform needs
if (BitConverter.IsLittleEndian)
{
// create deep copy of the array and reverse
bytes = new byte[] { bytes[3], bytes[2], bytes[1], bytes[0] };
}
return BitConverter.ToSingle(bytes, 0);
}
public static double FromByteArray(byte[] bytes) => Real.FromByteArray(bytes);
/// <summary>
/// Converts a S7 DInt to double
@@ -51,16 +37,7 @@ namespace S7.Net.Types
/// <summary>
/// Converts a double to S7 Real (4 bytes)
/// </summary>
public static byte[] ToByteArray(double value)
{
byte[] bytes = BitConverter.GetBytes((float)(value));
// sps uses bigending so we have to check if platform is same
if (!BitConverter.IsLittleEndian) return bytes;
// create deep copy of the array and reverse
return new byte[] { bytes[3], bytes[2], bytes[1], bytes[0] };
}
public static byte[] ToByteArray(double value) => Real.ToByteArray((float)value);
/// <summary>
/// Converts an array of double to an array of bytes

57
S7.Net/Types/LReal.cs Normal file
View File

@@ -0,0 +1,57 @@
using System;
using System.IO;
namespace S7.Net.Types
{
/// <summary>
/// Contains the conversion methods to convert Real from S7 plc to C# double.
/// </summary>
public static class LReal
{
/// <summary>
/// Converts a S7 LReal (8 bytes) to double
/// </summary>
public static double FromByteArray(byte[] bytes)
{
if (bytes.Length != 8)
{
throw new ArgumentException("Wrong number of bytes. Bytes array must contain 8 bytes.");
}
var buffer = bytes;
// sps uses bigending so we have to reverse if platform needs
if (BitConverter.IsLittleEndian)
{
Array.Reverse(buffer);
}
return BitConverter.ToDouble(buffer, 0);
}
/// <summary>
/// Converts a double to S7 LReal (8 bytes)
/// </summary>
public static byte[] ToByteArray(double value)
{
var bytes = BitConverter.GetBytes(value);
// sps uses bigending so we have to check if platform is same
if (BitConverter.IsLittleEndian)
{
Array.Reverse(bytes);
}
return bytes;
}
/// <summary>
/// Converts an array of double to an array of bytes
/// </summary>
public static byte[] ToByteArray(double[] value) => TypeHelper.ToByteArray(value, ToByteArray);
/// <summary>
/// Converts an array of S7 LReal to an array of double
/// </summary>
public static double[] ToArray(byte[] bytes) => TypeHelper.ToArray(bytes, FromByteArray);
}
}

75
S7.Net/Types/Real.cs Normal file
View File

@@ -0,0 +1,75 @@
using System;
using System.IO;
namespace S7.Net.Types
{
/// <summary>
/// Contains the conversion methods to convert Real from S7 plc to C# double.
/// </summary>
public static class Real
{
/// <summary>
/// Converts a S7 Real (4 bytes) to float
/// </summary>
public static float FromByteArray(byte[] bytes)
{
if (bytes.Length != 4)
{
throw new ArgumentException("Wrong number of bytes. Bytes array must contain 4 bytes.");
}
// sps uses bigending so we have to reverse if platform needs
if (BitConverter.IsLittleEndian)
{
// create deep copy of the array and reverse
bytes = new byte[] { bytes[3], bytes[2], bytes[1], bytes[0] };
}
return BitConverter.ToSingle(bytes, 0);
}
/// <summary>
/// Converts a float to S7 Real (4 bytes)
/// </summary>
public static byte[] ToByteArray(float value)
{
byte[] bytes = BitConverter.GetBytes(value);
// sps uses bigending so we have to check if platform is same
if (!BitConverter.IsLittleEndian) return bytes;
// create deep copy of the array and reverse
return new byte[] { bytes[3], bytes[2], bytes[1], bytes[0] };
}
/// <summary>
/// Converts an array of float to an array of bytes
/// </summary>
public static byte[] ToByteArray(float[] value)
{
var buffer = new byte[4 * value.Length];
var stream = new MemoryStream(buffer);
foreach (var val in value)
{
stream.Write(ToByteArray(val), 0, 4);
}
return buffer;
}
/// <summary>
/// Converts an array of S7 Real to an array of float
/// </summary>
public static float[] ToArray(byte[] bytes)
{
var values = new float[bytes.Length / 4];
int counter = 0;
for (int cnt = 0; cnt < bytes.Length / 4; cnt++)
values[cnt] = FromByteArray(new byte[] { bytes[counter++], bytes[counter++], bytes[counter++], bytes[counter++] });
return values;
}
}
}

View File

@@ -5,27 +5,13 @@ namespace S7.Net.Types
/// <summary>
/// Contains the conversion methods to convert Real from S7 plc to C# float.
/// </summary>
[Obsolete("Class Single is obsolete. Use Real instead.")]
public static class Single
{
/// <summary>
/// Converts a S7 Real (4 bytes) to float
/// </summary>
public static float FromByteArray(byte[] bytes)
{
if (bytes.Length != 4)
{
throw new ArgumentException("Wrong number of bytes. Bytes array must contain 4 bytes.");
}
// sps uses bigending so we have to reverse if platform needs
if (BitConverter.IsLittleEndian)
{
// create deep copy of the array and reverse
bytes = new byte[] { bytes[3], bytes[2], bytes[1], bytes[0] };
}
return BitConverter.ToSingle(bytes, 0);
}
public static float FromByteArray(byte[] bytes) => Real.FromByteArray(bytes);
/// <summary>
/// Converts a S7 DInt to float
@@ -51,16 +37,7 @@ namespace S7.Net.Types
/// <summary>
/// Converts a double to S7 Real (4 bytes)
/// </summary>
public static byte[] ToByteArray(float value)
{
byte[] bytes = BitConverter.GetBytes((float)(value));
// sps uses bigending so we have to check if platform is same
if (!BitConverter.IsLittleEndian) return bytes;
// create deep copy of the array and reverse
return new byte[] { bytes[3], bytes[2], bytes[1], bytes[0] };
}
public static byte[] ToByteArray(float value) => Real.ToByteArray(value);
/// <summary>
/// Converts an array of float to an array of bytes

View File

@@ -50,12 +50,17 @@ namespace S7.Net.Types
numBytes += 4;
break;
case "Single":
case "Double":
numBytes = Math.Ceiling(numBytes);
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
numBytes++;
numBytes += 4;
break;
case "Double":
numBytes = Math.Ceiling(numBytes);
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
numBytes++;
numBytes += 8;
break;
default:
numBytes += GetStructSize(info.FieldType);
break;
@@ -152,28 +157,27 @@ namespace S7.Net.Types
bytes[(int)numBytes + 3]));
numBytes += 4;
break;
case "Double":
numBytes = Math.Ceiling(numBytes);
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
numBytes++;
// hier auswerten
info.SetValue(structValue, Double.FromByteArray(new byte[] { bytes[(int)numBytes],
bytes[(int)numBytes + 1],
bytes[(int)numBytes + 2],
bytes[(int)numBytes + 3] }));
numBytes += 4;
break;
case "Single":
numBytes = Math.Ceiling(numBytes);
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
numBytes++;
// hier auswerten
info.SetValue(structValue, Single.FromByteArray(new byte[] { bytes[(int)numBytes],
info.SetValue(structValue, Real.FromByteArray(new byte[] { bytes[(int)numBytes],
bytes[(int)numBytes + 1],
bytes[(int)numBytes + 2],
bytes[(int)numBytes + 3] }));
numBytes += 4;
break;
case "Double":
numBytes = Math.Ceiling(numBytes);
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
numBytes++;
// hier auswerten
var data = new byte[8];
Array.Copy(bytes, (int)numBytes, data, 0, 8);
info.SetValue(structValue, LReal.FromByteArray(data));
numBytes += 8;
break;
default:
var buffer = new byte[GetStructSize(info.FieldType)];
if (buffer.Length == 0)
@@ -244,11 +248,11 @@ namespace S7.Net.Types
case "UInt32":
bytes2 = DWord.ToByteArray((UInt32)info.GetValue(structValue));
break;
case "Double":
bytes2 = Double.ToByteArray((double)info.GetValue(structValue));
break;
case "Single":
bytes2 = Single.ToByteArray((float)info.GetValue(structValue));
bytes2 = Real.ToByteArray((float)info.GetValue(structValue));
break;
case "Double":
bytes2 = LReal.ToByteArray((double)info.GetValue(structValue));
break;
}
if (bytes2 != null)

View File

@@ -0,0 +1,43 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace S7.Net.Types
{
internal static class TypeHelper
{
/// <summary>
/// Converts an array of T to an array of bytes
/// </summary>
public static byte[] ToByteArray<T>(T[] value, Func<T, byte[]> converter) where T : struct
{
var buffer = new byte[Marshal.SizeOf(default(T)) * value.Length];
var stream = new MemoryStream(buffer);
foreach (var val in value)
{
stream.Write(converter(val), 0, 4);
}
return buffer;
}
/// <summary>
/// Converts an array of T repesented as S7 binary data to an array of T
/// </summary>
public static T[] ToArray<T>(byte[] bytes, Func<byte[], T> converter)
{
var typeSize = Marshal.SizeOf(default(T));
var entries = bytes.Length / typeSize;
var values = new T[entries];
for(int i = 0; i < entries; ++i)
{
var buffer = new byte[typeSize];
Array.Copy(bytes, i * typeSize, buffer, 0, typeSize);
values[i] = converter(buffer);
}
return values;
}
}
}