diff --git a/S7.Net/Conversion.cs b/S7.Net/Conversion.cs index 246ed00..af0a05c 100644 --- a/S7.Net/Conversion.cs +++ b/S7.Net/Conversion.cs @@ -15,15 +15,11 @@ namespace S7.Net /// public static int BinStringToInt32(this string txt) { - int cnt = 0; int ret = 0; - for (cnt = txt.Length - 1; cnt >= 0; cnt += -1) + for (int i = 0; i < txt.Length; i++) { - if (int.Parse(txt.Substring(cnt, 1)) == 1) - { - ret += (int)(Math.Pow(2, (txt.Length - 1 - cnt))); - } + ret = (ret << 1) | ((txt[i] == '1') ? 1 : 0); } return ret; } @@ -35,20 +31,7 @@ namespace S7.Net /// public static byte? BinStringToByte(this string txt) { - int cnt = 0; - int ret = 0; - - if (txt.Length == 8) - { - for (cnt = 7; cnt >= 0; cnt += -1) - { - if (int.Parse(txt.Substring(cnt, 1)) == 1) - { - ret += (int)(Math.Pow(2, (txt.Length - 1 - cnt))); - } - } - return (byte)ret; - } + if (txt.Length == 8) return (byte)BinStringToInt32(txt); return null; } diff --git a/S7.Net/Enums.cs b/S7.Net/Enums.cs index b128285..ccb8941 100644 --- a/S7.Net/Enums.cs +++ b/S7.Net/Enums.cs @@ -163,6 +163,11 @@ /// String, + /// + /// String variable type (variable) + /// + StringEx, + /// /// Timer variable type /// diff --git a/S7.Net/PLC.cs b/S7.Net/PLC.cs index c5b9676..e1a5b8e 100644 --- a/S7.Net/PLC.cs +++ b/S7.Net/PLC.cs @@ -343,6 +343,8 @@ namespace S7.Net return resultBytes.ToArray(); } + + /// /// Read and decode a certain number of bytes of the "VarType" provided. /// This can be used to read multiple consecutive variables of the same type (Word, DWord, Int, etc). @@ -1208,8 +1210,12 @@ namespace S7.Net return Types.Double.FromByteArray(bytes); else return Types.Double.ToArray(bytes); + case VarType.String: return Types.String.FromByteArray(bytes); + case VarType.StringEx: + return Types.StringEx.FromByteArray(bytes); + case VarType.Timer: if (varCount == 1) return Types.Timer.FromByteArray(bytes); @@ -1252,6 +1258,8 @@ namespace S7.Net case VarType.Word: case VarType.Timer: case VarType.Int: + case VarType.StringEx: + return varCount + 2; case VarType.Counter: return varCount * 2; case VarType.DWord: diff --git a/S7.Net/S7.Net.csproj b/S7.Net/S7.Net.csproj index 5356672..ac2ac19 100644 --- a/S7.Net/S7.Net.csproj +++ b/S7.Net/S7.Net.csproj @@ -91,6 +91,7 @@ + diff --git a/S7.Net/Types/Bit.cs b/S7.Net/Types/Bit.cs index 8523cb5..cd36118 100644 --- a/S7.Net/Types/Bit.cs +++ b/S7.Net/Types/Bit.cs @@ -13,8 +13,7 @@ namespace S7.Net.Types /// public static bool FromByte(byte v, byte bitAdr) { - BitArray bitArr = new BitArray(new byte[] { v }); - return bitArr[bitAdr]; + return (((int)v & (1 << bitAdr)) != 0); } /// diff --git a/S7.Net/Types/Boolean.cs b/S7.Net/Types/Boolean.cs index cd9149a..4c93895 100644 --- a/S7.Net/Types/Boolean.cs +++ b/S7.Net/Types/Boolean.cs @@ -12,10 +12,7 @@ namespace S7.Net.Types /// public static bool GetValue(byte value, int bit) { - if ((value & (int)Math.Pow(2, bit)) != 0) - return true; - else - return false; + return (((int)value & (1 << bit)) != 0); } /// @@ -23,7 +20,7 @@ namespace S7.Net.Types /// public static byte SetBit(byte value, int bit) { - return (byte)(value | (byte)Math.Pow(2, bit)); + return (byte)((value | (1 << bit)) & 0xFF); } /// @@ -31,7 +28,7 @@ namespace S7.Net.Types /// public static byte ClearBit(byte value, int bit) { - return (byte)(value & (byte)(~(byte)Math.Pow(2, bit))); + return (byte)((value | (~(1 << bit))) & 0xFF); } } diff --git a/S7.Net/Types/Byte.cs b/S7.Net/Types/Byte.cs index 2727ef6..d52bb45 100644 --- a/S7.Net/Types/Byte.cs +++ b/S7.Net/Types/Byte.cs @@ -12,8 +12,7 @@ namespace S7.Net.Types /// public static byte[] ToByteArray(byte value) { - byte[] bytes = new byte[] { value}; - return bytes; + return new byte[] { value }; ; } /// diff --git a/S7.Net/Types/Counter.cs b/S7.Net/Types/Counter.cs index dfbc6f5..7a56cf7 100644 --- a/S7.Net/Types/Counter.cs +++ b/S7.Net/Types/Counter.cs @@ -18,16 +18,9 @@ namespace S7.Net.Types } // bytes[0] -> HighByte // bytes[1] -> LowByte - return FromBytes(bytes[1], bytes[0]); + return (UInt16)((bytes[0] << 8) | bytes[1]); } - /// - /// Converts a Counter (2 bytes) to ushort (UInt16) - /// - public static UInt16 FromBytes(byte LoVal, byte HiVal) - { - return (UInt16)(HiVal * 256 + LoVal); - } /// /// Converts a ushort (UInt16) to word (2 bytes) @@ -35,16 +28,10 @@ namespace S7.Net.Types public static byte[] ToByteArray(UInt16 value) { byte[] bytes = new byte[2]; - int x = 2; - long valLong = (long)((UInt16)value); - for (int cnt = 0; cnt < x; cnt++) - { - Int64 x1 = (Int64)Math.Pow(256, (cnt)); - Int64 x3 = (Int64)(valLong / x1); - bytes[x - cnt - 1] = (byte)(x3 & 255); - valLong -= bytes[x - cnt - 1] * x1; - } + bytes[0] = (byte)((value << 8) & 0xFF); + bytes[1] = (byte)((value) & 0xFF); + return bytes; } diff --git a/S7.Net/Types/DInt.cs b/S7.Net/Types/DInt.cs index fc3b523..a5b5caa 100644 --- a/S7.Net/Types/DInt.cs +++ b/S7.Net/Types/DInt.cs @@ -16,16 +16,9 @@ namespace S7.Net.Types { throw new ArgumentException("Wrong number of bytes. Bytes array must contain 4 bytes."); } - return FromBytes(bytes[3], bytes[2], bytes[1], bytes[0]); + return bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3]; } - /// - /// Converts a S7 DInt (4 bytes) to int (Int32) - /// - public static Int32 FromBytes(byte v1, byte v2, byte v3, byte v4) - { - return (Int32)(v1 + v2 * Math.Pow(2, 8) + v3 * Math.Pow(2, 16) + v4 * Math.Pow(2, 24)); - } /// /// Converts a int (Int32) to S7 DInt (4 bytes) @@ -33,16 +26,12 @@ namespace S7.Net.Types public static byte[] ToByteArray(Int32 value) { byte[] bytes = new byte[4]; - int x = 4; - long valLong = (long)((Int32)value); - for (int cnt = 0; cnt < x; cnt++) - { - Int64 x1 = (Int64)Math.Pow(256, (cnt)); - Int64 x3 = (Int64)(valLong / x1); - bytes[x - cnt - 1] = (byte)(x3 & 255); - valLong -= bytes[x - cnt - 1] * x1; - } + bytes[0] = (byte)((value >> 24) & 0xFF); + bytes[1] = (byte)((value >> 16) & 0xFF); + bytes[2] = (byte)((value >> 8) & 0xFF); + bytes[3] = (byte)((value) & 0xFF); + return bytes; } @@ -71,18 +60,6 @@ namespace S7.Net.Types return values; } - /// - /// Converts from C# long (Int64) to C# int (Int32) - /// - public static Int32 CDWord(Int64 value) - { - if (value > Int32.MaxValue) - { - value -= (long)Int32.MaxValue + 1; - value = (long)Int32.MaxValue + 1 - value; - value *= -1; - } - return (int)value; - } + } } diff --git a/S7.Net/Types/DWord.cs b/S7.Net/Types/DWord.cs index c735ad1..14bc2a4 100644 --- a/S7.Net/Types/DWord.cs +++ b/S7.Net/Types/DWord.cs @@ -12,36 +12,39 @@ namespace S7.Net.Types /// public static UInt32 FromByteArray(byte[] bytes) { - return FromBytes(bytes[3], bytes[2], bytes[1], bytes[0]); + return (UInt32)(bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3]); } + /// - /// Converts a S7 DWord (4 bytes) to uint (UInt32) + /// Converts 4 bytes to DWord (UInt32) /// - public static UInt32 FromBytes(byte v1, byte v2, byte v3, byte v4) + public static UInt32 FromBytes(byte b1, byte b2, byte b3, byte b4) { - return (UInt32)(v1 + v2 * Math.Pow(2, 8) + v3 * Math.Pow(2, 16) + v4 * Math.Pow(2, 24)); + return (UInt32)((b4 << 24) | (b3 << 16) | (b2 << 8) | b1); } + /// /// Converts a uint (UInt32) to S7 DWord (4 bytes) /// public static byte[] ToByteArray(UInt32 value) { byte[] bytes = new byte[4]; - int x = 4; - long valLong = (long)((UInt32)value); - for (int cnt = 0; cnt < x; cnt++) - { - Int64 x1 = (Int64)Math.Pow(256, (cnt)); - Int64 x3 = (Int64)(valLong / x1); - bytes[x - cnt - 1] = (byte)(x3 & 255); - valLong -= bytes[x - cnt - 1] * x1; - } + bytes[0] = (byte)((value >> 24) & 0xFF); + bytes[1] = (byte)((value >> 16) & 0xFF); + bytes[2] = (byte)((value >> 8) & 0xFF); + bytes[3] = (byte)((value) & 0xFF); + return bytes; } + + + + + /// /// Converts an array of uint (UInt32) to an array of S7 DWord (4 bytes) /// diff --git a/S7.Net/Types/Double.cs b/S7.Net/Types/Double.cs index 85bcbbd..f06385b 100644 --- a/S7.Net/Types/Double.cs +++ b/S7.Net/Types/Double.cs @@ -16,38 +16,15 @@ namespace S7.Net.Types { throw new ArgumentException("Wrong number of bytes. Bytes array must contain 4 bytes."); } - byte v1 = bytes[0]; - byte v2 = bytes[1]; - byte v3 = bytes[2]; - byte v4 = bytes[3]; - if ((int)v1 + v2 + v3 + v4 == 0) + // sps uses bigending so we have to reverse if platform needs + if (BitConverter.IsLittleEndian) { - return 0.0; + // create deep copy of the array and reverse + bytes = new byte[] { bytes[3], bytes[2], bytes[1], bytes[0] }; } - else - { - // nun String bilden - string txt = ValToBinString(v1) + ValToBinString(v2) + ValToBinString(v3) + ValToBinString(v4); - // erstmal das Vorzeichen - int vz = int.Parse(txt.Substring(0, 1)); - int exd = Conversion.BinStringToInt32(txt.Substring(1, 8)); - string ma = txt.Substring(9, 23); - double mantisse = 1; - double faktor = 1.0; - //das ist die Anzahl der restlichen bit's - for (int cnt = 0; cnt <= 22; cnt++) - { - faktor = faktor / 2.0; - //entspricht 2^-y - if (ma.Substring(cnt, 1) == "1") - { - mantisse = mantisse + faktor; - } - } - return Math.Pow((-1), vz) * Math.Pow(2, (exd - 127)) * mantisse; - } + return BitConverter.ToSingle(bytes, 0); } /// @@ -76,48 +53,13 @@ namespace S7.Net.Types /// public static byte[] ToByteArray(double value) { - double wert = (double)value; - string binString = ""; - byte[] bytes = new byte[4]; - if (wert != 0f) - { - if (wert < 0) - { - wert *= -1; - binString = "1"; - } - else - { - binString = "0"; - } - int exponent = (int)Math.Floor((double)Math.Log(wert) / Math.Log(2.0)); - wert = wert / (Math.Pow(2, exponent)) - 1; + byte[] bytes = BitConverter.GetBytes((float)(value)); - binString += ValToBinString((byte)(exponent + 127)); - for (int cnt = 1; cnt <= 23; cnt++) - { - if (!(wert - System.Math.Pow(2, -cnt) < 0)) - { - wert = wert - System.Math.Pow(2, -cnt); - binString += "1"; - } - else - binString += "0"; - } - bytes[0] = (byte)BinStringToByte(binString.Substring(0, 8)); - bytes[1] = (byte)BinStringToByte(binString.Substring(8, 8)); - bytes[2] = (byte)BinStringToByte(binString.Substring(16, 8)); - bytes[3] = (byte)BinStringToByte(binString.Substring(24, 8)); - - } - else - { - bytes[0] = 0; - bytes[1] = 0; - bytes[2] = 0; - bytes[3] = 0; - } - return bytes; + // 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] }; } /// @@ -145,38 +87,5 @@ namespace S7.Net.Types return values; } - - private static string ValToBinString(byte value) - { - string txt = ""; - - for (int cnt = 7; cnt >= 0; cnt += -1) - { - if ((value & (byte)Math.Pow(2, cnt)) > 0) - txt += "1"; - else - txt += "0"; - } - return txt; - } - - private static byte? BinStringToByte(string txt) - { - int cnt = 0; - int ret = 0; - - if (txt.Length == 8) - { - for (cnt = 7; cnt >= 0; cnt += -1) - { - if (int.Parse(txt.Substring(cnt, 1)) == 1) - { - ret += (int)(Math.Pow(2, (txt.Length - 1 - cnt))); - } - } - return (byte)ret; - } - return null; - } } } diff --git a/S7.Net/Types/Int.cs b/S7.Net/Types/Int.cs index f2d7124..468e8b3 100644 --- a/S7.Net/Types/Int.cs +++ b/S7.Net/Types/Int.cs @@ -10,7 +10,7 @@ namespace S7.Net.Types /// /// Converts a S7 Int (2 bytes) to short (Int16) /// - public static Int16 FromByteArray(byte[] bytes) + public static short FromByteArray(byte[] bytes) { if (bytes.Length != 2) { @@ -18,16 +18,9 @@ namespace S7.Net.Types } // bytes[0] -> HighByte // bytes[1] -> LowByte - return FromBytes(bytes[1], bytes[0]); + return (short)((int)(bytes[1]) | ((int)(bytes[0]) << 8)); } - /// - /// Converts a S7 Int (2 bytes) to short (Int16) - /// - public static Int16 FromBytes(byte LoVal, byte HiVal) - { - return (Int16)(HiVal * 256 + LoVal); - } /// /// Converts a short (Int16) to a S7 Int byte array (2 bytes) @@ -35,16 +28,10 @@ namespace S7.Net.Types public static byte[] ToByteArray(Int16 value) { byte[] bytes = new byte[2]; - int x = 2; - long valLong = (long)((Int16)value); - for (int cnt = 0; cnt < x; cnt++) - { - Int64 x1 = (Int64)Math.Pow(256, (cnt)); - Int64 x3 = (Int64)(valLong / x1); - bytes[x - cnt - 1] = (byte)(x3 & 255); - valLong -= bytes[x - cnt - 1] * x1; - } + bytes[1] = (byte)((int)value & 0xFF); + bytes[0] = (byte)((int)value >> 8 & 0xFF); + return bytes; } @@ -53,10 +40,15 @@ namespace S7.Net.Types /// public static byte[] ToByteArray(Int16[] value) { - ByteArray arr = new ByteArray(); - foreach (Int16 val in value) - arr.Add(ToByteArray(val)); - return arr.array; + byte[] bytes = new byte[value.Length * 2]; + int bytesPos = 0; + + for(int i=0; i< value.Length; i++) + { + bytes[bytesPos++] = (byte)((int)value[i] & 0xFF); + bytes[bytesPos++] = (byte)(((int)value[i] >> 8) & 0xFF); + } + return bytes; } /// @@ -64,10 +56,12 @@ namespace S7.Net.Types /// public static Int16[] ToArray(byte[] bytes) { - Int16[] values = new Int16[bytes.Length / 2]; + int shortsCount = bytes.Length / 2; + + Int16[] values = new Int16[shortsCount]; int counter = 0; - for (int cnt = 0; cnt < bytes.Length / 2; cnt++) + for (int cnt = 0; cnt < shortsCount; cnt++) values[cnt] = FromByteArray(new byte[] { bytes[counter++], bytes[counter++] }); return values; diff --git a/S7.Net/Types/String.cs b/S7.Net/Types/String.cs index d2a1d50..d1ca263 100644 --- a/S7.Net/Types/String.cs +++ b/S7.Net/Types/String.cs @@ -3,19 +3,14 @@ /// /// Contains the methods to convert from S7 strings to C# strings /// - public static class String + public class String { /// /// Converts a string to S7 bytes /// public static byte[] ToByteArray(string value) { - string txt = (string)value; - char[] ca = txt.ToCharArray(); - byte[] bytes = new byte[txt.Length]; - for (int cnt = 0; cnt <= ca.Length - 1; cnt++) - bytes[cnt] = (byte)Asc(ca[cnt].ToString()); - return bytes; + return System.Text.Encoding.ASCII.GetBytes(value); } /// @@ -27,13 +22,6 @@ { return System.Text.Encoding.ASCII.GetString(bytes); } - - private static int Asc(string s) - { - byte[] b = System.Text.Encoding.ASCII.GetBytes(s); - if (b.Length > 0) - return b[0]; - return 0; - } + } } diff --git a/S7.Net/Types/StringEx.cs b/S7.Net/Types/StringEx.cs new file mode 100644 index 0000000..e22282b --- /dev/null +++ b/S7.Net/Types/StringEx.cs @@ -0,0 +1,26 @@ +namespace S7.Net.Types +{ + /// + /// Contains the methods to convert from S7 strings to C# strings + /// there are two kinds how strings a send. This one is with a pre of two bytes + /// they contain the length of the string + /// + public static class StringEx + { + /// + /// Converts S7 bytes to a string + /// + /// + /// + public static string FromByteArray(byte[] bytes) + { + if (bytes.Length < 2) return ""; + + int size = bytes[0]; + int length = bytes[1]; + + return System.Text.Encoding.ASCII.GetString(bytes, 2, length); + } + + } +} diff --git a/S7.Net/Types/Timer.cs b/S7.Net/Types/Timer.cs index 167c12f..a95253b 100644 --- a/S7.Net/Types/Timer.cs +++ b/S7.Net/Types/Timer.cs @@ -13,26 +13,30 @@ namespace S7.Net.Types public static double FromByteArray(byte[] bytes) { double wert = 0; - Int16 value = (Int16)Types.Word.FromBytes(bytes[1], bytes[0]); - string txt = Conversion.ValToBinString(value); - wert = Conversion.BinStringToInt32(txt.Substring(4, 4)) * 100.0; - wert += Conversion.BinStringToInt32(txt.Substring(8, 4)) * 10.0; - wert += Conversion.BinStringToInt32(txt.Substring(12, 4)); - switch (txt.Substring(2, 2)) + + wert = ((bytes[0]) & 0x0F) * 100.0; + wert += ((bytes[1] >> 4) & 0x0F) * 10.0; + wert += ((bytes[1]) & 0x0F) * 1.0; + + /// this value is not used... may for a nother exponation + ///int unknown = (bytes[0] >> 6) & 0x03; + + switch ((bytes[0] >> 4) & 0x03) { - case "00": + case 0: wert *= 0.01; break; - case "01": + case 1: wert *= 0.1; break; - case "10": + case 2: wert *= 1.0; break; - case "11": + case 3: wert *= 10.0; break; } + return wert; } @@ -42,16 +46,9 @@ namespace S7.Net.Types public static byte[] ToByteArray(UInt16 value) { byte[] bytes = new byte[2]; - int x = 2; - long valLong = (long)((UInt16)value); - for (int cnt = 0; cnt < x; cnt++) - { - Int64 x1 = (Int64)Math.Pow(256, (cnt)); + bytes[1] = (byte)((int)value & 0xFF); + bytes[0] = (byte)((int)value >> 8 & 0xFF); - Int64 x3 = (Int64)(valLong / x1); - bytes[x - cnt - 1] = (byte)(x3 & 255); - valLong -= bytes[x - cnt - 1] * x1; - } return bytes; } diff --git a/S7.Net/Types/Word.cs b/S7.Net/Types/Word.cs index f0f4347..1631fae 100644 --- a/S7.Net/Types/Word.cs +++ b/S7.Net/Types/Word.cs @@ -16,35 +16,30 @@ namespace S7.Net.Types { throw new ArgumentException("Wrong number of bytes. Bytes array must contain 2 bytes."); } - // bytes[0] -> HighByte - // bytes[1] -> LowByte - return FromBytes(bytes[1], bytes[0]); + + return (UInt16)((bytes[0] << 8) | bytes[1]); } + /// - /// Converts a word (2 bytes) to ushort (UInt16) + /// Converts 2 bytes to ushort (UInt16) /// - public static UInt16 FromBytes(byte LoVal, byte HiVal) + public static UInt16 FromBytes(byte b1, byte b2) { - return (UInt16) (HiVal*256 + LoVal); + return (UInt16)((b2 << 8) | b1); } + /// /// Converts a ushort (UInt16) to word (2 bytes) /// public static byte[] ToByteArray(UInt16 value) { byte[] bytes = new byte[2]; - int x = 2; - long valLong = (long) ((UInt16) value); - for (int cnt = 0; cnt < x; cnt++) - { - Int64 x1 = (Int64) Math.Pow(256, (cnt)); - Int64 x3 = (Int64) (valLong/x1); - bytes[x - cnt - 1] = (byte) (x3 & 255); - valLong -= bytes[x - cnt - 1]*x1; - } + bytes[1] = (byte)(value & 0xFF); + bytes[0] = (byte)((value>>8) & 0xFF); + return bytes; }