mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
3cc162bf7e
Signed-off-by: Jan N. Klug <jan.n.klug@rub.de>
3793 lines
136 KiB
Diff
3793 lines
136 KiB
Diff
diff U3 IntByRef.java IntByRef.java
|
|
--- IntByRef.java Thu Mar 23 15:34:52 2017
|
|
+++ IntByRef.java Tue Aug 08 18:53:37 2017
|
|
@@ -1,40 +1,40 @@
|
|
-/*=============================================================================|
|
|
-| PROJECT Moka7 1.0.2 |
|
|
-|==============================================================================|
|
|
-| Copyright (C) 2013, 2016 Davide Nardella |
|
|
-| All rights reserved. |
|
|
-|==============================================================================|
|
|
-| SNAP7 is free software: you can redistribute it and/or modify |
|
|
-| it under the terms of the Lesser GNU General Public License as published by |
|
|
-| the Free Software Foundation, either version 3 of the License, or under |
|
|
-| EPL Eclipse Public License 1.0. |
|
|
-| |
|
|
-| This means that you have to chose in advance which take before you import |
|
|
-| the library into your project. |
|
|
-| |
|
|
-| SNAP7 is distributed in the hope that it will be useful, |
|
|
-| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you |
|
|
-| decide to adopt. |
|
|
-| |
|
|
-|=============================================================================*/
|
|
-
|
|
-package Moka7;
|
|
-
|
|
-/**
|
|
- * Quick class to pass an integer by reference
|
|
- * @author Davide
|
|
- */
|
|
-
|
|
-public class IntByRef {
|
|
-
|
|
- public IntByRef(int Val)
|
|
- {
|
|
- this.Value=Val;
|
|
- }
|
|
- public IntByRef()
|
|
- {
|
|
- this.Value=0;
|
|
- }
|
|
- public int Value;
|
|
-}
|
|
+/*=============================================================================|
|
|
+| PROJECT Moka7 1.0.2 |
|
|
+|==============================================================================|
|
|
+| Copyright (C) 2013, 2016 Davide Nardella |
|
|
+| All rights reserved. |
|
|
+|==============================================================================|
|
|
+| SNAP7 is free software: you can redistribute it and/or modify |
|
|
+| it under the terms of the Lesser GNU General Public License as published by |
|
|
+| the Free Software Foundation, either version 3 of the License, or under |
|
|
+| EPL Eclipse Public License 1.0. |
|
|
+| |
|
|
+| This means that you have to chose in advance which take before you import |
|
|
+| the library into your project. |
|
|
+| |
|
|
+| SNAP7 is distributed in the hope that it will be useful, |
|
|
+| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you |
|
|
+| decide to adopt. |
|
|
+| |
|
|
+|=============================================================================*/
|
|
+
|
|
+package Moka7;
|
|
+
|
|
+/**
|
|
+ * Quick class to pass an integer by reference
|
|
+ * @author Davide Nardella
|
|
+ */
|
|
+
|
|
+public class IntByRef {
|
|
+
|
|
+ public IntByRef(int Val)
|
|
+ {
|
|
+ this.Value=Val;
|
|
+ }
|
|
+ public IntByRef()
|
|
+ {
|
|
+ this.Value=0;
|
|
+ }
|
|
+ public int Value;
|
|
+}
|
|
diff U3 S7.java S7.java
|
|
--- S7.java Thu Mar 23 15:34:52 2017
|
|
+++ S7.java Tue Aug 08 18:53:37 2017
|
|
@@ -1,287 +1,287 @@
|
|
-/*=============================================================================|
|
|
-| PROJECT Moka7 1.0.2 |
|
|
-|==============================================================================|
|
|
-| Copyright (C) 2013, 2016 Davide Nardella |
|
|
-| All rights reserved. |
|
|
-|==============================================================================|
|
|
-| SNAP7 is free software: you can redistribute it and/or modify |
|
|
-| it under the terms of the Lesser GNU General Public License as published by |
|
|
-| the Free Software Foundation, either version 3 of the License, or under |
|
|
-| EPL Eclipse Public License 1.0. |
|
|
-| |
|
|
-| This means that you have to chose in advance which take before you import |
|
|
-| the library into your project. |
|
|
-| |
|
|
-| SNAP7 is distributed in the hope that it will be useful, |
|
|
-| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you |
|
|
-| decide to adopt. |
|
|
-| |
|
|
-|=============================================================================*/
|
|
-package Moka7;
|
|
-
|
|
-import java.io.UnsupportedEncodingException;
|
|
-import java.util.Date;
|
|
-import java.util.Calendar;
|
|
-
|
|
-/**
|
|
- *
|
|
- * @author Davide
|
|
- */
|
|
-
|
|
-
|
|
-// Step 7 Constants and Conversion helper class
|
|
-public class S7 {
|
|
- // S7 ID Area (Area that we want to read/write)
|
|
- public static final int S7AreaPE = 0x81;
|
|
- public static final int S7AreaPA = 0x82;
|
|
- public static final int S7AreaMK = 0x83;
|
|
- public static final int S7AreaDB = 0x84;
|
|
- public static final int S7AreaCT = 0x1C;
|
|
- public static final int S7AreaTM = 0x1D;
|
|
- // Connection types
|
|
- public static final byte PG = 0x01;
|
|
- public static final byte OP = 0x02;
|
|
- public static final byte S7_BASIC = 0x03;
|
|
- // Block type
|
|
- public static final int Block_OB = 0x38;
|
|
- public static final int Block_DB = 0x41;
|
|
- public static final int Block_SDB = 0x42;
|
|
- public static final int Block_FC = 0x43;
|
|
- public static final int Block_SFC = 0x44;
|
|
- public static final int Block_FB = 0x45;
|
|
- public static final int Block_SFB = 0x46;
|
|
- // Sub Block Type
|
|
- public static final int SubBlk_OB = 0x08;
|
|
- public static final int SubBlk_DB = 0x0A;
|
|
- public static final int SubBlk_SDB = 0x0B;
|
|
- public static final int SubBlk_FC = 0x0C;
|
|
- public static final int SubBlk_SFC = 0x0D;
|
|
- public static final int SubBlk_FB = 0x0E;
|
|
- public static final int SubBlk_SFB = 0x0F;
|
|
- // Block languages
|
|
- public static final int BlockLangAWL = 0x01;
|
|
- public static final int BlockLangKOP = 0x02;
|
|
- public static final int BlockLangFUP = 0x03;
|
|
- public static final int BlockLangSCL = 0x04;
|
|
- public static final int BlockLangDB = 0x05;
|
|
- public static final int BlockLangGRAPH = 0x06;
|
|
- // PLC Status
|
|
- public static final int S7CpuStatusUnknown = 0x00;
|
|
- public static final int S7CpuStatusRun = 0x08;
|
|
- public static final int S7CpuStatusStop = 0x04;
|
|
- // Type Var
|
|
- public static final int S7TypeBool = 1;
|
|
- public static final int S7TypeInt = 1;
|
|
-
|
|
- // Returns the bit at Pos.Bit
|
|
- public static boolean GetBitAt(byte[] Buffer, int Pos, int Bit)
|
|
- {
|
|
- int Value = Buffer[Pos] & 0x0FF;
|
|
- byte[] Mask = {
|
|
- (byte)0x01,(byte)0x02,(byte)0x04,(byte)0x08,
|
|
- (byte)0x10,(byte)0x20,(byte)0x40,(byte)0x80
|
|
- };
|
|
- if (Bit<0) Bit=0;
|
|
- if (Bit>7) Bit=7;
|
|
-
|
|
- return (Value & Mask[Bit])!=0;
|
|
- }
|
|
- /**
|
|
- * Returns a 16 bit unsigned value : from 0 to 65535 (2^16-1)
|
|
- * @param Buffer
|
|
- * @param Pos start position
|
|
- * @return
|
|
- */
|
|
- public static int GetWordAt(byte[] Buffer, int Pos)
|
|
- {
|
|
- int hi = (Buffer[Pos] & 0x00FF);
|
|
- int lo = (Buffer[Pos+1] & 0x00FF);
|
|
- return (hi<<8)+lo;
|
|
- }
|
|
-
|
|
- // Returns a 16 bit signed value : from -32768 to 32767
|
|
- public static int GetShortAt(byte[] Buffer, int Pos)
|
|
- {
|
|
- int hi = (Buffer[Pos]);
|
|
- int lo = (Buffer[Pos+1] & 0x00FF);
|
|
- return ((hi<<8)+lo);
|
|
- }
|
|
-
|
|
- // Returns a 32 bit unsigned value : from 0 to 4294967295 (2^32-1)
|
|
- public static long GetDWordAt(byte[] Buffer, int Pos)
|
|
- {
|
|
- long Result;
|
|
- Result=(long)(Buffer[Pos] & 0x0FF);
|
|
- Result<<=8;
|
|
- Result+=(long)(Buffer[Pos+1] & 0x0FF);
|
|
- Result<<=8;
|
|
- Result+=(long)(Buffer[Pos+2] & 0x0FF);
|
|
- Result<<=8;
|
|
- Result+=(long)(Buffer[Pos+3] & 0x0FF);
|
|
- return Result;
|
|
- }
|
|
-
|
|
- // Returns a 32 bit signed value : from 0 to 4294967295 (2^32-1)
|
|
- public static int GetDIntAt(byte[] Buffer, int Pos)
|
|
- {
|
|
- int Result;
|
|
- Result= Buffer[Pos];
|
|
- Result<<=8;
|
|
- Result+=(Buffer[Pos+1] & 0x0FF);
|
|
- Result<<=8;
|
|
- Result+=(Buffer[Pos+2] & 0x0FF);
|
|
- Result<<=8;
|
|
- Result+=(Buffer[Pos+3] & 0x0FF);
|
|
- return Result;
|
|
- }
|
|
-
|
|
- // Returns a 32 bit floating point
|
|
- public static float GetFloatAt(byte[] Buffer, int Pos)
|
|
- {
|
|
- int IntFloat = GetDIntAt(Buffer, Pos);
|
|
- return Float.intBitsToFloat(IntFloat);
|
|
- }
|
|
-
|
|
- // Returns an ASCII string
|
|
- public static String GetStringAt(byte[] Buffer, int Pos, int MaxLen)
|
|
- {
|
|
- byte[] StrBuffer = new byte[MaxLen];
|
|
- System.arraycopy(Buffer, Pos, StrBuffer, 0, MaxLen);
|
|
- String S;
|
|
- try {
|
|
- S = new String(StrBuffer, "UTF-8"); // the charset is UTF-8
|
|
- } catch (UnsupportedEncodingException ex) {
|
|
- S = "";
|
|
- }
|
|
- return S;
|
|
- }
|
|
-
|
|
- public static String GetPrintableStringAt(byte[] Buffer, int Pos, int MaxLen)
|
|
- {
|
|
- byte[] StrBuffer = new byte[MaxLen];
|
|
- System.arraycopy(Buffer, Pos, StrBuffer, 0, MaxLen);
|
|
- for (int c = 0; c < MaxLen; c++)
|
|
- {
|
|
- if ((StrBuffer[c]<31) || (StrBuffer[c]>126))
|
|
- StrBuffer[c]=46; // '.'
|
|
- }
|
|
- String S;
|
|
- try {
|
|
- S = new String(StrBuffer, "UTF-8"); // the charset is UTF-8
|
|
- } catch (UnsupportedEncodingException ex) {
|
|
- S = "";
|
|
- }
|
|
- return S;
|
|
- }
|
|
-
|
|
- public static Date GetDateAt(byte[] Buffer, int Pos)
|
|
- {
|
|
- int Year, Month, Day, Hour, Min, Sec;
|
|
- Calendar S7Date = Calendar.getInstance();
|
|
-
|
|
- Year = S7.BCDtoByte(Buffer[Pos]);
|
|
- if (Year<90)
|
|
- Year+=2000;
|
|
- else
|
|
- Year+=1900;
|
|
-
|
|
- Month=S7.BCDtoByte(Buffer[Pos+1])-1;
|
|
- Day =S7.BCDtoByte(Buffer[Pos+2]);
|
|
- Hour =S7.BCDtoByte(Buffer[Pos+3]);
|
|
- Min =S7.BCDtoByte(Buffer[Pos+4]);
|
|
- Sec =S7.BCDtoByte(Buffer[Pos+5]);
|
|
-
|
|
- S7Date.set(Year, Month, Day, Hour, Min, Sec);
|
|
-
|
|
- return S7Date.getTime();
|
|
- }
|
|
-
|
|
- public static void SetBitAt(byte[] Buffer, int Pos, int Bit, boolean Value)
|
|
- {
|
|
- byte[] Mask = {
|
|
- (byte)0x01,(byte)0x02,(byte)0x04,(byte)0x08,
|
|
- (byte)0x10,(byte)0x20,(byte)0x40,(byte)0x80
|
|
- };
|
|
- if (Bit<0) Bit=0;
|
|
- if (Bit>7) Bit=7;
|
|
-
|
|
- if (Value)
|
|
- Buffer[Pos]= (byte) (Buffer[Pos] | Mask[Bit]);
|
|
- else
|
|
- Buffer[Pos]= (byte) (Buffer[Pos] & ~Mask[Bit]);
|
|
- }
|
|
-
|
|
- public static void SetWordAt(byte[] Buffer, int Pos, int Value)
|
|
- {
|
|
- int Word = Value & 0x0FFFF;
|
|
- Buffer[Pos] = (byte) (Word >> 8);
|
|
- Buffer[Pos+1] = (byte) (Word & 0x00FF);
|
|
- }
|
|
-
|
|
- public static void SetShortAt(byte[] Buffer, int Pos, int Value)
|
|
- {
|
|
- Buffer[Pos] = (byte) (Value >> 8);
|
|
- Buffer[Pos+1] = (byte) (Value & 0x00FF);
|
|
- }
|
|
- public static void SetDWordAt(byte[] Buffer, int Pos, long Value)
|
|
- {
|
|
- long DWord = Value &0x0FFFFFFFF;
|
|
- Buffer[Pos+3] = (byte) (DWord &0xFF);
|
|
- Buffer[Pos+2] = (byte) ((DWord >> 8) &0xFF);
|
|
- Buffer[Pos+1] = (byte) ((DWord >> 16) &0xFF);
|
|
- Buffer[Pos] = (byte) ((DWord >> 24) &0xFF);
|
|
- }
|
|
-
|
|
- public static void SetDIntAt(byte[] Buffer, int Pos, int Value)
|
|
- {
|
|
- Buffer[Pos+3] = (byte) (Value &0xFF);
|
|
- Buffer[Pos+2] = (byte) ((Value >> 8) &0xFF);
|
|
- Buffer[Pos+1] = (byte) ((Value >> 16) &0xFF);
|
|
- Buffer[Pos] = (byte) ((Value >> 24) &0xFF);
|
|
- }
|
|
-
|
|
- public static void SetFloatAt(byte[] Buffer, int Pos, float Value)
|
|
- {
|
|
- int DInt = Float.floatToIntBits(Value);
|
|
- SetDIntAt(Buffer, Pos, DInt);
|
|
- }
|
|
-
|
|
- public static void SetDateAt(byte[] Buffer, int Pos, Date DateTime)
|
|
- {
|
|
- int Year, Month, Day, Hour, Min, Sec, Dow;
|
|
- Calendar S7Date = Calendar.getInstance();
|
|
- S7Date.setTime(DateTime);
|
|
-
|
|
- Year = S7Date.get(Calendar.YEAR);
|
|
- Month = S7Date.get(Calendar.MONTH)+1;
|
|
- Day = S7Date.get(Calendar.DAY_OF_MONTH);
|
|
- Hour = S7Date.get(Calendar.HOUR_OF_DAY);
|
|
- Min = S7Date.get(Calendar.MINUTE);
|
|
- Sec = S7Date.get(Calendar.SECOND);
|
|
- Dow = S7Date.get(Calendar.DAY_OF_WEEK);
|
|
-
|
|
- if (Year>1999)
|
|
- Year-=2000;
|
|
-
|
|
- Buffer[Pos] =ByteToBCD(Year);
|
|
- Buffer[Pos+1]=ByteToBCD(Month);
|
|
- Buffer[Pos+2]=ByteToBCD(Day);
|
|
- Buffer[Pos+3]=ByteToBCD(Hour);
|
|
- Buffer[Pos+4]=ByteToBCD(Min);
|
|
- Buffer[Pos+5]=ByteToBCD(Sec);
|
|
- Buffer[Pos+6]=0;
|
|
- Buffer[Pos+7]=ByteToBCD(Dow);
|
|
- }
|
|
-
|
|
- public static int BCDtoByte(byte B)
|
|
- {
|
|
- return ((B >> 4) * 10) + (B & 0x0F);
|
|
- }
|
|
-
|
|
- public static byte ByteToBCD(int Value)
|
|
- {
|
|
- return (byte) (((Value / 10) << 4) | (Value % 10));
|
|
- }
|
|
-
|
|
-}
|
|
+/*=============================================================================|
|
|
+| PROJECT Moka7 1.0.2 |
|
|
+|==============================================================================|
|
|
+| Copyright (C) 2013, 2016 Davide Nardella |
|
|
+| All rights reserved. |
|
|
+|==============================================================================|
|
|
+| SNAP7 is free software: you can redistribute it and/or modify |
|
|
+| it under the terms of the Lesser GNU General Public License as published by |
|
|
+| the Free Software Foundation, either version 3 of the License, or under |
|
|
+| EPL Eclipse Public License 1.0. |
|
|
+| |
|
|
+| This means that you have to chose in advance which take before you import |
|
|
+| the library into your project. |
|
|
+| |
|
|
+| SNAP7 is distributed in the hope that it will be useful, |
|
|
+| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you |
|
|
+| decide to adopt. |
|
|
+| |
|
|
+|=============================================================================*/
|
|
+package Moka7;
|
|
+
|
|
+import java.io.UnsupportedEncodingException;
|
|
+import java.util.Date;
|
|
+import java.util.Calendar;
|
|
+
|
|
+/**
|
|
+ *
|
|
+ * @author Davide Nardella
|
|
+ */
|
|
+
|
|
+
|
|
+// Step 7 Constants and Conversion helper class
|
|
+public class S7 {
|
|
+ // S7 ID Area (Area that we want to read/write)
|
|
+ public static final int S7AreaPE = 0x81;
|
|
+ public static final int S7AreaPA = 0x82;
|
|
+ public static final int S7AreaMK = 0x83;
|
|
+ public static final int S7AreaDB = 0x84;
|
|
+ public static final int S7AreaCT = 0x1C;
|
|
+ public static final int S7AreaTM = 0x1D;
|
|
+ // Connection types
|
|
+ public static final byte PG = 0x01;
|
|
+ public static final byte OP = 0x02;
|
|
+ public static final byte S7_BASIC = 0x03;
|
|
+ // Block type
|
|
+ public static final int Block_OB = 0x38;
|
|
+ public static final int Block_DB = 0x41;
|
|
+ public static final int Block_SDB = 0x42;
|
|
+ public static final int Block_FC = 0x43;
|
|
+ public static final int Block_SFC = 0x44;
|
|
+ public static final int Block_FB = 0x45;
|
|
+ public static final int Block_SFB = 0x46;
|
|
+ // Sub Block Type
|
|
+ public static final int SubBlk_OB = 0x08;
|
|
+ public static final int SubBlk_DB = 0x0A;
|
|
+ public static final int SubBlk_SDB = 0x0B;
|
|
+ public static final int SubBlk_FC = 0x0C;
|
|
+ public static final int SubBlk_SFC = 0x0D;
|
|
+ public static final int SubBlk_FB = 0x0E;
|
|
+ public static final int SubBlk_SFB = 0x0F;
|
|
+ // Block languages
|
|
+ public static final int BlockLangAWL = 0x01;
|
|
+ public static final int BlockLangKOP = 0x02;
|
|
+ public static final int BlockLangFUP = 0x03;
|
|
+ public static final int BlockLangSCL = 0x04;
|
|
+ public static final int BlockLangDB = 0x05;
|
|
+ public static final int BlockLangGRAPH = 0x06;
|
|
+ // PLC Status
|
|
+ public static final int S7CpuStatusUnknown = 0x00;
|
|
+ public static final int S7CpuStatusRun = 0x08;
|
|
+ public static final int S7CpuStatusStop = 0x04;
|
|
+ // Type Var
|
|
+ public static final int S7TypeBool = 1;
|
|
+ public static final int S7TypeInt = 1;
|
|
+
|
|
+ // Returns the bit at Pos.Bit
|
|
+ public static boolean GetBitAt(byte[] Buffer, int Pos, int Bit)
|
|
+ {
|
|
+ int Value = Buffer[Pos] & 0x0FF;
|
|
+ byte[] Mask = {
|
|
+ (byte)0x01,(byte)0x02,(byte)0x04,(byte)0x08,
|
|
+ (byte)0x10,(byte)0x20,(byte)0x40,(byte)0x80
|
|
+ };
|
|
+ if (Bit<0) Bit=0;
|
|
+ if (Bit>7) Bit=7;
|
|
+
|
|
+ return (Value & Mask[Bit])!=0;
|
|
+ }
|
|
+ /**
|
|
+ * Returns a 16 bit unsigned value : from 0 to 65535 (2^16-1)
|
|
+ * @param Buffer
|
|
+ * @param Pos start position
|
|
+ * @return
|
|
+ */
|
|
+ public static int GetWordAt(byte[] Buffer, int Pos)
|
|
+ {
|
|
+ int hi = (Buffer[Pos] & 0x00FF);
|
|
+ int lo = (Buffer[Pos+1] & 0x00FF);
|
|
+ return (hi<<8)+lo;
|
|
+ }
|
|
+
|
|
+ // Returns a 16 bit signed value : from -32768 to 32767
|
|
+ public static int GetShortAt(byte[] Buffer, int Pos)
|
|
+ {
|
|
+ int hi = (Buffer[Pos]);
|
|
+ int lo = (Buffer[Pos+1] & 0x00FF);
|
|
+ return ((hi<<8)+lo);
|
|
+ }
|
|
+
|
|
+ // Returns a 32 bit unsigned value : from 0 to 4294967295 (2^32-1)
|
|
+ public static long GetDWordAt(byte[] Buffer, int Pos)
|
|
+ {
|
|
+ long Result;
|
|
+ Result=(long)(Buffer[Pos] & 0x0FF);
|
|
+ Result<<=8;
|
|
+ Result+=(long)(Buffer[Pos+1] & 0x0FF);
|
|
+ Result<<=8;
|
|
+ Result+=(long)(Buffer[Pos+2] & 0x0FF);
|
|
+ Result<<=8;
|
|
+ Result+=(long)(Buffer[Pos+3] & 0x0FF);
|
|
+ return Result;
|
|
+ }
|
|
+
|
|
+ // Returns a 32 bit signed value : from 0 to 4294967295 (2^32-1)
|
|
+ public static int GetDIntAt(byte[] Buffer, int Pos)
|
|
+ {
|
|
+ int Result;
|
|
+ Result= Buffer[Pos];
|
|
+ Result<<=8;
|
|
+ Result+=(Buffer[Pos+1] & 0x0FF);
|
|
+ Result<<=8;
|
|
+ Result+=(Buffer[Pos+2] & 0x0FF);
|
|
+ Result<<=8;
|
|
+ Result+=(Buffer[Pos+3] & 0x0FF);
|
|
+ return Result;
|
|
+ }
|
|
+
|
|
+ // Returns a 32 bit floating point
|
|
+ public static float GetFloatAt(byte[] Buffer, int Pos)
|
|
+ {
|
|
+ int IntFloat = GetDIntAt(Buffer, Pos);
|
|
+ return Float.intBitsToFloat(IntFloat);
|
|
+ }
|
|
+
|
|
+ // Returns an ASCII string
|
|
+ public static String GetStringAt(byte[] Buffer, int Pos, int MaxLen)
|
|
+ {
|
|
+ byte[] StrBuffer = new byte[MaxLen];
|
|
+ System.arraycopy(Buffer, Pos, StrBuffer, 0, MaxLen);
|
|
+ String S;
|
|
+ try {
|
|
+ S = new String(StrBuffer, "UTF-8"); // the charset is UTF-8
|
|
+ } catch (UnsupportedEncodingException ex) {
|
|
+ S = "";
|
|
+ }
|
|
+ return S;
|
|
+ }
|
|
+
|
|
+ public static String GetPrintableStringAt(byte[] Buffer, int Pos, int MaxLen)
|
|
+ {
|
|
+ byte[] StrBuffer = new byte[MaxLen];
|
|
+ System.arraycopy(Buffer, Pos, StrBuffer, 0, MaxLen);
|
|
+ for (int c = 0; c < MaxLen; c++)
|
|
+ {
|
|
+ if ((StrBuffer[c]<31) || (StrBuffer[c]>126))
|
|
+ StrBuffer[c]=46; // '.'
|
|
+ }
|
|
+ String S;
|
|
+ try {
|
|
+ S = new String(StrBuffer, "UTF-8"); // the charset is UTF-8
|
|
+ } catch (UnsupportedEncodingException ex) {
|
|
+ S = "";
|
|
+ }
|
|
+ return S;
|
|
+ }
|
|
+
|
|
+ public static Date GetDateAt(byte[] Buffer, int Pos)
|
|
+ {
|
|
+ int Year, Month, Day, Hour, Min, Sec;
|
|
+ Calendar S7Date = Calendar.getInstance();
|
|
+
|
|
+ Year = S7.BCDtoByte(Buffer[Pos]);
|
|
+ if (Year<90)
|
|
+ Year+=2000;
|
|
+ else
|
|
+ Year+=1900;
|
|
+
|
|
+ Month=S7.BCDtoByte(Buffer[Pos+1])-1;
|
|
+ Day =S7.BCDtoByte(Buffer[Pos+2]);
|
|
+ Hour =S7.BCDtoByte(Buffer[Pos+3]);
|
|
+ Min =S7.BCDtoByte(Buffer[Pos+4]);
|
|
+ Sec =S7.BCDtoByte(Buffer[Pos+5]);
|
|
+
|
|
+ S7Date.set(Year, Month, Day, Hour, Min, Sec);
|
|
+
|
|
+ return S7Date.getTime();
|
|
+ }
|
|
+
|
|
+ public static void SetBitAt(byte[] Buffer, int Pos, int Bit, boolean Value)
|
|
+ {
|
|
+ byte[] Mask = {
|
|
+ (byte)0x01,(byte)0x02,(byte)0x04,(byte)0x08,
|
|
+ (byte)0x10,(byte)0x20,(byte)0x40,(byte)0x80
|
|
+ };
|
|
+ if (Bit<0) Bit=0;
|
|
+ if (Bit>7) Bit=7;
|
|
+
|
|
+ if (Value)
|
|
+ Buffer[Pos]= (byte) (Buffer[Pos] | Mask[Bit]);
|
|
+ else
|
|
+ Buffer[Pos]= (byte) (Buffer[Pos] & ~Mask[Bit]);
|
|
+ }
|
|
+
|
|
+ public static void SetWordAt(byte[] Buffer, int Pos, int Value)
|
|
+ {
|
|
+ int Word = Value & 0x0FFFF;
|
|
+ Buffer[Pos] = (byte) (Word >> 8);
|
|
+ Buffer[Pos+1] = (byte) (Word & 0x00FF);
|
|
+ }
|
|
+
|
|
+ public static void SetShortAt(byte[] Buffer, int Pos, int Value)
|
|
+ {
|
|
+ Buffer[Pos] = (byte) (Value >> 8);
|
|
+ Buffer[Pos+1] = (byte) (Value & 0x00FF);
|
|
+ }
|
|
+ public static void SetDWordAt(byte[] Buffer, int Pos, long Value)
|
|
+ {
|
|
+ long DWord = Value &0x0FFFFFFFF;
|
|
+ Buffer[Pos+3] = (byte) (DWord &0xFF);
|
|
+ Buffer[Pos+2] = (byte) ((DWord >> 8) &0xFF);
|
|
+ Buffer[Pos+1] = (byte) ((DWord >> 16) &0xFF);
|
|
+ Buffer[Pos] = (byte) ((DWord >> 24) &0xFF);
|
|
+ }
|
|
+
|
|
+ public static void SetDIntAt(byte[] Buffer, int Pos, int Value)
|
|
+ {
|
|
+ Buffer[Pos+3] = (byte) (Value &0xFF);
|
|
+ Buffer[Pos+2] = (byte) ((Value >> 8) &0xFF);
|
|
+ Buffer[Pos+1] = (byte) ((Value >> 16) &0xFF);
|
|
+ Buffer[Pos] = (byte) ((Value >> 24) &0xFF);
|
|
+ }
|
|
+
|
|
+ public static void SetFloatAt(byte[] Buffer, int Pos, float Value)
|
|
+ {
|
|
+ int DInt = Float.floatToIntBits(Value);
|
|
+ SetDIntAt(Buffer, Pos, DInt);
|
|
+ }
|
|
+
|
|
+ public static void SetDateAt(byte[] Buffer, int Pos, Date DateTime)
|
|
+ {
|
|
+ int Year, Month, Day, Hour, Min, Sec, Dow;
|
|
+ Calendar S7Date = Calendar.getInstance();
|
|
+ S7Date.setTime(DateTime);
|
|
+
|
|
+ Year = S7Date.get(Calendar.YEAR);
|
|
+ Month = S7Date.get(Calendar.MONTH)+1;
|
|
+ Day = S7Date.get(Calendar.DAY_OF_MONTH);
|
|
+ Hour = S7Date.get(Calendar.HOUR_OF_DAY);
|
|
+ Min = S7Date.get(Calendar.MINUTE);
|
|
+ Sec = S7Date.get(Calendar.SECOND);
|
|
+ Dow = S7Date.get(Calendar.DAY_OF_WEEK);
|
|
+
|
|
+ if (Year>1999)
|
|
+ Year-=2000;
|
|
+
|
|
+ Buffer[Pos] =ByteToBCD(Year);
|
|
+ Buffer[Pos+1]=ByteToBCD(Month);
|
|
+ Buffer[Pos+2]=ByteToBCD(Day);
|
|
+ Buffer[Pos+3]=ByteToBCD(Hour);
|
|
+ Buffer[Pos+4]=ByteToBCD(Min);
|
|
+ Buffer[Pos+5]=ByteToBCD(Sec);
|
|
+ Buffer[Pos+6]=0;
|
|
+ Buffer[Pos+7]=ByteToBCD(Dow);
|
|
+ }
|
|
+
|
|
+ public static int BCDtoByte(byte B)
|
|
+ {
|
|
+ return ((B >> 4) * 10) + (B & 0x0F);
|
|
+ }
|
|
+
|
|
+ public static byte ByteToBCD(int Value)
|
|
+ {
|
|
+ return (byte) (((Value / 10) << 4) | (Value % 10));
|
|
+ }
|
|
+
|
|
+}
|
|
diff U3 S7BlockInfo.java S7BlockInfo.java
|
|
--- S7BlockInfo.java Thu Mar 23 15:34:52 2017
|
|
+++ S7BlockInfo.java Tue Aug 08 18:53:37 2017
|
|
@@ -1,101 +1,101 @@
|
|
-/*=============================================================================|
|
|
-| PROJECT Moka7 1.0.2 |
|
|
-|==============================================================================|
|
|
-| Copyright (C) 2013, 2016 Davide Nardella |
|
|
-| All rights reserved. |
|
|
-|==============================================================================|
|
|
-| SNAP7 is free software: you can redistribute it and/or modify |
|
|
-| it under the terms of the Lesser GNU General Public License as published by |
|
|
-| the Free Software Foundation, either version 3 of the License, or under |
|
|
-| EPL Eclipse Public License 1.0. |
|
|
-| |
|
|
-| This means that you have to chose in advance which take before you import |
|
|
-| the library into your project. |
|
|
-| |
|
|
-| SNAP7 is distributed in the hope that it will be useful, |
|
|
-| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you |
|
|
-| decide to adopt. |
|
|
-| |
|
|
-|=============================================================================*/
|
|
-package Moka7;
|
|
-import java.util.Date;
|
|
-/**
|
|
- *
|
|
- * @author Davide
|
|
- */
|
|
-public class S7BlockInfo {
|
|
-
|
|
- private final int BufSize = 96;
|
|
- // MilliSeconds between 1970/1/1 (Java time base) and 1984/1/1 (Siemens base)
|
|
- private final long DeltaMilliSecs = 441763200000L;
|
|
- protected byte[] Buffer = new byte[BufSize];
|
|
-
|
|
- protected void Update(byte[] Src, int Pos)
|
|
- {
|
|
- System.arraycopy(Src, Pos, Buffer, 0, BufSize);
|
|
- }
|
|
- public int BlkType()
|
|
- {
|
|
- return Buffer[2];
|
|
- }
|
|
- public int BlkNumber()
|
|
- {
|
|
- return S7.GetWordAt(Buffer, 3);
|
|
- }
|
|
- public int BlkLang()
|
|
- {
|
|
- return Buffer[1];
|
|
- }
|
|
- public int BlkFlags()
|
|
- {
|
|
- return Buffer[0];
|
|
- }
|
|
- public int MC7Size() // The real size in bytes
|
|
- {
|
|
- return S7.GetWordAt(Buffer, 31);
|
|
- }
|
|
- public int LoadSize()
|
|
- {
|
|
- return S7.GetDIntAt(Buffer, 5);
|
|
- }
|
|
- public int LocalData()
|
|
- {
|
|
- return S7.GetWordAt(Buffer, 29);
|
|
- }
|
|
- public int SBBLength()
|
|
- {
|
|
- return S7.GetWordAt(Buffer, 25);
|
|
- }
|
|
- public int Checksum()
|
|
- {
|
|
- return S7.GetWordAt(Buffer, 59);
|
|
- }
|
|
- public int Version()
|
|
- {
|
|
- return Buffer[57];
|
|
- }
|
|
- public Date CodeDate()
|
|
- {
|
|
- long BlockDate = ((long)S7.GetWordAt(Buffer, 17))*86400000L+DeltaMilliSecs;
|
|
- return new Date(BlockDate);
|
|
- }
|
|
- public Date IntfDate()
|
|
- {
|
|
- long BlockDate = ((long)S7.GetWordAt(Buffer, 23))*86400000L+DeltaMilliSecs;
|
|
- return new Date(BlockDate);
|
|
- }
|
|
- public String Author()
|
|
- {
|
|
- return S7.GetStringAt(Buffer,33,8);
|
|
- }
|
|
- public String Family()
|
|
- {
|
|
- return S7.GetStringAt(Buffer,41,8);
|
|
- }
|
|
- public String Header()
|
|
- {
|
|
- return S7.GetStringAt(Buffer,49,8);
|
|
- }
|
|
-
|
|
-}
|
|
+/*=============================================================================|
|
|
+| PROJECT Moka7 1.0.2 |
|
|
+|==============================================================================|
|
|
+| Copyright (C) 2013, 2016 Davide Nardella |
|
|
+| All rights reserved. |
|
|
+|==============================================================================|
|
|
+| SNAP7 is free software: you can redistribute it and/or modify |
|
|
+| it under the terms of the Lesser GNU General Public License as published by |
|
|
+| the Free Software Foundation, either version 3 of the License, or under |
|
|
+| EPL Eclipse Public License 1.0. |
|
|
+| |
|
|
+| This means that you have to chose in advance which take before you import |
|
|
+| the library into your project. |
|
|
+| |
|
|
+| SNAP7 is distributed in the hope that it will be useful, |
|
|
+| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you |
|
|
+| decide to adopt. |
|
|
+| |
|
|
+|=============================================================================*/
|
|
+package Moka7;
|
|
+import java.util.Date;
|
|
+/**
|
|
+ *
|
|
+ * @author Davide Nardella
|
|
+ */
|
|
+public class S7BlockInfo {
|
|
+
|
|
+ private final int BufSize = 96;
|
|
+ // MilliSeconds between 1970/1/1 (Java time base) and 1984/1/1 (Siemens base)
|
|
+ private final long DeltaMilliSecs = 441763200000L;
|
|
+ protected byte[] Buffer = new byte[BufSize];
|
|
+
|
|
+ protected void Update(byte[] Src, int Pos)
|
|
+ {
|
|
+ System.arraycopy(Src, Pos, Buffer, 0, BufSize);
|
|
+ }
|
|
+ public int BlkType()
|
|
+ {
|
|
+ return Buffer[2];
|
|
+ }
|
|
+ public int BlkNumber()
|
|
+ {
|
|
+ return S7.GetWordAt(Buffer, 3);
|
|
+ }
|
|
+ public int BlkLang()
|
|
+ {
|
|
+ return Buffer[1];
|
|
+ }
|
|
+ public int BlkFlags()
|
|
+ {
|
|
+ return Buffer[0];
|
|
+ }
|
|
+ public int MC7Size() // The real size in bytes
|
|
+ {
|
|
+ return S7.GetWordAt(Buffer, 31);
|
|
+ }
|
|
+ public int LoadSize()
|
|
+ {
|
|
+ return S7.GetDIntAt(Buffer, 5);
|
|
+ }
|
|
+ public int LocalData()
|
|
+ {
|
|
+ return S7.GetWordAt(Buffer, 29);
|
|
+ }
|
|
+ public int SBBLength()
|
|
+ {
|
|
+ return S7.GetWordAt(Buffer, 25);
|
|
+ }
|
|
+ public int Checksum()
|
|
+ {
|
|
+ return S7.GetWordAt(Buffer, 59);
|
|
+ }
|
|
+ public int Version()
|
|
+ {
|
|
+ return Buffer[57];
|
|
+ }
|
|
+ public Date CodeDate()
|
|
+ {
|
|
+ long BlockDate = ((long)S7.GetWordAt(Buffer, 17))*86400000L+DeltaMilliSecs;
|
|
+ return new Date(BlockDate);
|
|
+ }
|
|
+ public Date IntfDate()
|
|
+ {
|
|
+ long BlockDate = ((long)S7.GetWordAt(Buffer, 23))*86400000L+DeltaMilliSecs;
|
|
+ return new Date(BlockDate);
|
|
+ }
|
|
+ public String Author()
|
|
+ {
|
|
+ return S7.GetStringAt(Buffer,33,8);
|
|
+ }
|
|
+ public String Family()
|
|
+ {
|
|
+ return S7.GetStringAt(Buffer,41,8);
|
|
+ }
|
|
+ public String Header()
|
|
+ {
|
|
+ return S7.GetStringAt(Buffer,49,8);
|
|
+ }
|
|
+
|
|
+}
|
|
diff U3 S7Client.java S7Client.java
|
|
--- S7Client.java Thu Mar 23 15:34:52 2017
|
|
+++ S7Client.java Tue Aug 08 18:53:37 2017
|
|
@@ -1,1214 +1,1233 @@
|
|
-/*=============================================================================|
|
|
-| PROJECT Moka7 1.0.2 |
|
|
-|==============================================================================|
|
|
-| Copyright (C) 2013, 2016 Davide Nardella |
|
|
-| All rights reserved. |
|
|
-|==============================================================================|
|
|
-| SNAP7 is free software: you can redistribute it and/or modify |
|
|
-| it under the terms of the Lesser GNU General Public License as published by |
|
|
-| the Free Software Foundation, either version 3 of the License, or under |
|
|
-| EPL Eclipse Public License 1.0. |
|
|
-| |
|
|
-| This means that you have to chose in advance which take before you import |
|
|
-| the library into your project. |
|
|
-| |
|
|
-| SNAP7 is distributed in the hope that it will be useful, |
|
|
-| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you |
|
|
-| decide to adopt. |
|
|
-| |
|
|
-|=============================================================================*/
|
|
-package Moka7;
|
|
-
|
|
-import java.io.DataInputStream;
|
|
-import java.io.DataOutputStream;
|
|
-import java.io.IOException;
|
|
-import java.io.UnsupportedEncodingException;
|
|
-import java.net.InetSocketAddress;
|
|
-import java.net.Socket;
|
|
-import java.net.SocketAddress;
|
|
-import java.util.Date;
|
|
-
|
|
-
|
|
-/**
|
|
- *
|
|
- * @author Dave Nardella
|
|
- */
|
|
-public class S7Client
|
|
-{
|
|
- // WordLength
|
|
- private static final byte S7WLByte =0x02;
|
|
- private static final byte S7WLCounter =0x1C;
|
|
- private static final byte S7WLTimer =0x1D;
|
|
- // Error Codes
|
|
- public static final int errTCPConnectionFailed = 0x0001;
|
|
- public static final int errTCPDataSend = 0x0002;
|
|
- public static final int errTCPDataRecv = 0x0003;
|
|
- public static final int errTCPDataRecvTout = 0x0004;
|
|
- public static final int errTCPConnectionReset = 0x0005;
|
|
- public static final int errISOInvalidPDU = 0x0006;
|
|
- public static final int errISOConnectionFailed = 0x0007;
|
|
- public static final int errISONegotiatingPDU = 0x0008;
|
|
- public static final int errS7InvalidPDU = 0x0009;
|
|
- public static final int errS7DataRead = 0x000A;
|
|
- public static final int errS7DataWrite = 0x000B;
|
|
- public static final int errS7BufferTooSmall = 0x000C;
|
|
- public static final int errS7FunctionError = 0x000D;
|
|
- public static final int errS7InvalidParams = 0x000E;
|
|
-
|
|
- // Public fields
|
|
- public boolean Connected = false;
|
|
- public int LastError = 0;
|
|
- public int RecvTimeout = 2000;
|
|
-
|
|
- // Privates
|
|
- private static final int ISOTCP = 102; // ISOTCP Port
|
|
- private static final int MinPduSize = 16;
|
|
- private static final int DefaultPduSizeRequested = 480;
|
|
- private static final int IsoHSize = 7; // TPKT+COTP Header Size
|
|
- private static final int MaxPduSize = DefaultPduSizeRequested+IsoHSize;
|
|
-
|
|
-
|
|
- private Socket TCPSocket;
|
|
- private final byte[] PDU = new byte[2048];
|
|
-
|
|
- private DataInputStream InStream = null;
|
|
- private DataOutputStream OutStream = null;
|
|
-
|
|
- private String IPAddress;
|
|
-
|
|
- private byte LocalTSAP_HI;
|
|
- private byte LocalTSAP_LO;
|
|
- private byte RemoteTSAP_HI;
|
|
- private byte RemoteTSAP_LO;
|
|
- private byte LastPDUType;
|
|
-
|
|
- private short ConnType = S7.PG;
|
|
- private int _PDULength = 0;
|
|
-
|
|
- // Telegrams
|
|
- // ISO Connection Request telegram (contains also ISO Header and COTP Header)
|
|
- private static final byte ISO_CR[] = {
|
|
- // TPKT (RFC1006 Header)
|
|
- (byte)0x03, // RFC 1006 ID (3)
|
|
- (byte)0x00, // Reserved, always 0
|
|
- (byte)0x00, // High part of packet lenght (entire frame, payload and TPDU included)
|
|
- (byte)0x16, // Low part of packet lenght (entire frame, payload and TPDU included)
|
|
- // COTP (ISO 8073 Header)
|
|
- (byte)0x11, // PDU Size Length
|
|
- (byte)0xE0, // CR - Connection Request ID
|
|
- (byte)0x00, // Dst Reference HI
|
|
- (byte)0x00, // Dst Reference LO
|
|
- (byte)0x00, // Src Reference HI
|
|
- (byte)0x01, // Src Reference LO
|
|
- (byte)0x00, // Class + Options Flags
|
|
- (byte)0xC0, // PDU Max Length ID
|
|
- (byte)0x01, // PDU Max Length HI
|
|
- (byte)0x0A, // PDU Max Length LO
|
|
- (byte)0xC1, // Src TSAP Identifier
|
|
- (byte)0x02, // Src TSAP Length (2 bytes)
|
|
- (byte)0x01, // Src TSAP HI (will be overwritten)
|
|
- (byte)0x00, // Src TSAP LO (will be overwritten)
|
|
- (byte)0xC2, // Dst TSAP Identifier
|
|
- (byte)0x02, // Dst TSAP Length (2 bytes)
|
|
- (byte)0x01, // Dst TSAP HI (will be overwritten)
|
|
- (byte)0x02 // Dst TSAP LO (will be overwritten)
|
|
- };
|
|
-
|
|
- // S7 PDU Negotiation Telegram (contains also ISO Header and COTP Header)
|
|
- private static final byte S7_PN[] = {
|
|
- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x19,
|
|
- (byte)0x02, (byte)0xf0, (byte)0x80, // TPKT + COTP (see above for info)
|
|
- (byte)0x32, (byte)0x01, (byte)0x00, (byte)0x00,
|
|
- (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x08,
|
|
- (byte)0x00, (byte)0x00, (byte)0xf0, (byte)0x00,
|
|
- (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x01,
|
|
- (byte)0x00, (byte)0x1e // PDU Length Requested = HI-LO 480 bytes
|
|
- };
|
|
-
|
|
- // S7 Read/Write Request Header (contains also ISO Header and COTP Header)
|
|
- private static final byte S7_RW[] = { // 31-35 bytes
|
|
- (byte)0x03,(byte)0x00,
|
|
- (byte)0x00,(byte)0x1f, // Telegram Length (Data Size + 31 or 35)
|
|
- (byte)0x02,(byte)0xf0, (byte)0x80, // COTP (see above for info)
|
|
- (byte)0x32, // S7 Protocol ID
|
|
- (byte)0x01, // Job Type
|
|
- (byte)0x00,(byte)0x00, // Redundancy identification
|
|
- (byte)0x05,(byte)0x00, // PDU Reference
|
|
- (byte)0x00,(byte)0x0e, // Parameters Length
|
|
- (byte)0x00,(byte)0x00, // Data Length = Size(bytes) + 4
|
|
- (byte)0x04, // Function 4 Read Var, 5 Write Var
|
|
- (byte)0x01, // Items count
|
|
- (byte)0x12, // Var spec.
|
|
- (byte)0x0a, // Length of remaining bytes
|
|
- (byte)0x10, // Syntax ID
|
|
- S7WLByte, // Transport Size
|
|
- (byte)0x00,(byte)0x00, // Num Elements
|
|
- (byte)0x00,(byte)0x00, // DB Number (if any, else 0)
|
|
- (byte)0x84, // Area Type
|
|
- (byte)0x00,(byte)0x00,(byte)0x00, // Area Offset
|
|
- // WR area
|
|
- (byte)0x00, // Reserved
|
|
- (byte)0x04, // Transport size
|
|
- (byte)0x00,(byte)0x00, // Data Length * 8 (if not timer or counter)
|
|
- };
|
|
- private static final int Size_RD = 31;
|
|
- private static final int Size_WR = 35;
|
|
-
|
|
- // S7 Get Block Info Request Header (contains also ISO Header and COTP Header)
|
|
- private static final byte S7_BI[] = {
|
|
- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x25,
|
|
- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32,
|
|
- (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x05,
|
|
- (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00,
|
|
- (byte)0x0c, (byte)0x00, (byte)0x01, (byte)0x12,
|
|
- (byte)0x04, (byte)0x11, (byte)0x43, (byte)0x03,
|
|
- (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00,
|
|
- (byte)0x08, (byte)0x30,
|
|
- (byte)0x41, // Block Type
|
|
- (byte)0x30, (byte)0x30, (byte)0x30, (byte)0x30, (byte)0x30, // ASCII Block Number
|
|
- (byte)0x41
|
|
- };
|
|
-
|
|
- // SZL First telegram request
|
|
- private static final byte S7_SZL_FIRST[] = {
|
|
- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21,
|
|
- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32,
|
|
- (byte)0x07, (byte)0x00, (byte)0x00,
|
|
- (byte)0x05, (byte)0x00, // Sequence out
|
|
- (byte)0x00, (byte)0x08, (byte)0x00,
|
|
- (byte)0x08, (byte)0x00, (byte)0x01, (byte)0x12,
|
|
- (byte)0x04, (byte)0x11, (byte)0x44, (byte)0x01,
|
|
- (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00,
|
|
- (byte)0x04,
|
|
- (byte)0x00, (byte)0x00, // ID (29)
|
|
- (byte)0x00, (byte)0x00 // Index (31)
|
|
- };
|
|
-
|
|
- // SZL Next telegram request
|
|
- private static final byte S7_SZL_NEXT[] = {
|
|
- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21,
|
|
- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32,
|
|
- (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x06,
|
|
- (byte)0x00, (byte)0x00, (byte)0x0c, (byte)0x00,
|
|
- (byte)0x04, (byte)0x00, (byte)0x01, (byte)0x12,
|
|
- (byte)0x08, (byte)0x12, (byte)0x44, (byte)0x01,
|
|
- (byte)0x01, // Sequence
|
|
- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
|
|
- (byte)0x0a, (byte)0x00, (byte)0x00, (byte)0x00
|
|
- };
|
|
-
|
|
- // Get Date/Time request
|
|
- private static final byte S7_GET_DT[] = {
|
|
- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x1d,
|
|
- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32,
|
|
- (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x38,
|
|
- (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00,
|
|
- (byte)0x04, (byte)0x00, (byte)0x01, (byte)0x12,
|
|
- (byte)0x04, (byte)0x11, (byte)0x47, (byte)0x01,
|
|
- (byte)0x00, (byte)0x0a, (byte)0x00, (byte)0x00,
|
|
- (byte)0x00
|
|
- };
|
|
-
|
|
- // Set Date/Time command
|
|
- private static final byte S7_SET_DT[] = {
|
|
- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x27,
|
|
- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32,
|
|
- (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x89,
|
|
- (byte)0x03, (byte)0x00, (byte)0x08, (byte)0x00,
|
|
- (byte)0x0e, (byte)0x00, (byte)0x01, (byte)0x12,
|
|
- (byte)0x04, (byte)0x11, (byte)0x47, (byte)0x02,
|
|
- (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00,
|
|
- (byte)0x0a, (byte)0x00, (byte)0x19, // Hi part of Year
|
|
- (byte)0x13, // Lo part of Year
|
|
- (byte)0x12, // Month
|
|
- (byte)0x06, // Day
|
|
- (byte)0x17, // Hour
|
|
- (byte)0x37, // Min
|
|
- (byte)0x13, // Sec
|
|
- (byte)0x00, (byte)0x01 // ms + Day of week
|
|
- };
|
|
-
|
|
- // S7 STOP request
|
|
- private static final byte S7_STOP[] = {
|
|
- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21,
|
|
- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32,
|
|
- (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x0e,
|
|
- (byte)0x00, (byte)0x00, (byte)0x10, (byte)0x00,
|
|
- (byte)0x00, (byte)0x29, (byte)0x00, (byte)0x00,
|
|
- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x09,
|
|
- (byte)0x50, (byte)0x5f, (byte)0x50, (byte)0x52,
|
|
- (byte)0x4f, (byte)0x47, (byte)0x52, (byte)0x41,
|
|
- (byte)0x4d
|
|
- };
|
|
-
|
|
- // S7 HOT Start request
|
|
- private static final byte S7_HOT_START[] = {
|
|
- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x25,
|
|
- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32,
|
|
- (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x0c,
|
|
- (byte)0x00, (byte)0x00, (byte)0x14, (byte)0x00,
|
|
- (byte)0x00, (byte)0x28, (byte)0x00, (byte)0x00,
|
|
- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
|
|
- (byte)0xfd, (byte)0x00, (byte)0x00, (byte)0x09,
|
|
- (byte)0x50, (byte)0x5f, (byte)0x50, (byte)0x52,
|
|
- (byte)0x4f, (byte)0x47, (byte)0x52, (byte)0x41,
|
|
- (byte)0x4d
|
|
- };
|
|
-
|
|
- // S7 COLD Start request
|
|
- private static final byte S7_COLD_START[] = {
|
|
- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x27,
|
|
- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32,
|
|
- (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x0f,
|
|
- (byte)0x00, (byte)0x00, (byte)0x16, (byte)0x00,
|
|
- (byte)0x00, (byte)0x28, (byte)0x00, (byte)0x00,
|
|
- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
|
|
- (byte)0xfd, (byte)0x00, (byte)0x02, (byte)0x43,
|
|
- (byte)0x20, (byte)0x09, (byte)0x50, (byte)0x5f,
|
|
- (byte)0x50, (byte)0x52, (byte)0x4f, (byte)0x47,
|
|
- (byte)0x52, (byte)0x41, (byte)0x4d
|
|
- };
|
|
-
|
|
- // S7 Get PLC Status
|
|
- private static final byte S7_GET_STAT[] = {
|
|
- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21,
|
|
- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32,
|
|
- (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x2c,
|
|
- (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00,
|
|
- (byte)0x08, (byte)0x00, (byte)0x01, (byte)0x12,
|
|
- (byte)0x04, (byte)0x11, (byte)0x44, (byte)0x01,
|
|
- (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00,
|
|
- (byte)0x04, (byte)0x04, (byte)0x24, (byte)0x00,
|
|
- (byte)0x00
|
|
- };
|
|
-
|
|
- // S7 Set Session Password
|
|
- private static final byte S7_SET_PWD[] = {
|
|
- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x25,
|
|
- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32,
|
|
- (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x27,
|
|
- (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00,
|
|
- (byte)0x0c, (byte)0x00, (byte)0x01, (byte)0x12,
|
|
- (byte)0x04, (byte)0x11, (byte)0x45, (byte)0x01,
|
|
- (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00,
|
|
- (byte)0x08,
|
|
- // 8 Char Encoded Password
|
|
- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
|
|
- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00
|
|
- };
|
|
-
|
|
- // S7 Clear Session Password
|
|
- private static final byte S7_CLR_PWD[] = {
|
|
- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x1d,
|
|
- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32,
|
|
- (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x29,
|
|
- (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00,
|
|
- (byte)0x04, (byte)0x00, (byte)0x01, (byte)0x12,
|
|
- (byte)0x04, (byte)0x11, (byte)0x45, (byte)0x02,
|
|
- (byte)0x00, (byte)0x0a, (byte)0x00, (byte)0x00,
|
|
- (byte)0x00
|
|
- };
|
|
-
|
|
- public S7Client()
|
|
- {
|
|
- // Placeholder for future implementations
|
|
- }
|
|
-
|
|
- public static String ErrorText(int Error)
|
|
- {
|
|
- switch (Error)
|
|
- {
|
|
- case errTCPConnectionFailed :
|
|
- return "TCP Connection failed.";
|
|
- case errTCPDataSend :
|
|
- return "TCP Sending error.";
|
|
- case errTCPDataRecv :
|
|
- return "TCP Receiving error.";
|
|
- case errTCPDataRecvTout :
|
|
- return "Data Receiving timeout.";
|
|
- case errTCPConnectionReset :
|
|
- return "Connection reset by the peer.";
|
|
- case errISOInvalidPDU :
|
|
- return "Invalid ISO PDU received.";
|
|
- case errISOConnectionFailed :
|
|
- return "ISO connection refused by the CPU.";
|
|
- case errISONegotiatingPDU :
|
|
- return "ISO error negotiating the PDU length.";
|
|
- case errS7InvalidPDU :
|
|
- return "Invalid S7 PDU received.";
|
|
- case errS7DataRead :
|
|
- return "S7 Error reading data from the CPU.";
|
|
- case errS7DataWrite :
|
|
- return "S7 Error writing data to the CPU.";
|
|
- case errS7BufferTooSmall :
|
|
- return "The Buffer supplied to the function is too small.";
|
|
- case errS7FunctionError :
|
|
- return "S7 function refused by the CPU.";
|
|
- case errS7InvalidParams :
|
|
- return "Invalid parameters supplied to the function.";
|
|
- default :
|
|
- return "Unknown error : 0x"+Integer.toHexString(Error);
|
|
- }
|
|
- }
|
|
-
|
|
- private int TCPConnect()
|
|
- {
|
|
- SocketAddress sockaddr = new InetSocketAddress(IPAddress, ISOTCP);
|
|
- LastError=0;
|
|
- try {
|
|
- TCPSocket = new Socket();
|
|
- TCPSocket.connect(sockaddr ,5000);
|
|
- TCPSocket.setTcpNoDelay(true);
|
|
- InStream = new DataInputStream(TCPSocket.getInputStream());
|
|
- OutStream = new DataOutputStream(TCPSocket.getOutputStream());
|
|
- }
|
|
- catch (IOException e) {
|
|
- LastError=errTCPConnectionFailed;
|
|
- }
|
|
- return LastError;
|
|
- }
|
|
-
|
|
- private int WaitForData(int Size, int Timeout)
|
|
- {
|
|
- int cnt = 0;
|
|
- LastError=0;
|
|
- int SizeAvail;
|
|
- boolean Expired = false;
|
|
- try
|
|
- {
|
|
- SizeAvail=InStream.available();
|
|
- while ((SizeAvail<Size) && (!Expired) && (LastError==0))
|
|
- {
|
|
-
|
|
- cnt++;
|
|
- try {
|
|
- Thread.sleep(1);
|
|
- }
|
|
- catch (InterruptedException ex) {
|
|
- LastError=errTCPDataRecvTout;
|
|
- }
|
|
- SizeAvail=InStream.available();
|
|
- Expired=cnt>Timeout;
|
|
- // If timeout we clean the buffer
|
|
- if (Expired && (SizeAvail>0) && (LastError==0))
|
|
- InStream.read(PDU, 0, SizeAvail);
|
|
- }
|
|
- }
|
|
- catch (IOException ex)
|
|
- {
|
|
- LastError=errTCPDataRecvTout;
|
|
- }
|
|
- if (cnt>=Timeout)
|
|
- {
|
|
- LastError=errTCPDataRecvTout;
|
|
- }
|
|
- return LastError;
|
|
- }
|
|
-
|
|
- private int RecvPacket(byte[] Buffer, int Start, int Size)
|
|
- {
|
|
- int BytesRead=0;
|
|
- LastError=WaitForData(Size,RecvTimeout);
|
|
- if (LastError==0)
|
|
- {
|
|
- try {
|
|
- BytesRead = InStream.read(Buffer, Start, Size);
|
|
- } catch (IOException ex) {
|
|
- LastError=errTCPDataRecv;
|
|
- }
|
|
- if (BytesRead==0)
|
|
- LastError=errTCPConnectionReset;
|
|
- }
|
|
- return LastError;
|
|
- }
|
|
-
|
|
- private void SendPacket(byte[] Buffer, int Len)
|
|
- {
|
|
- LastError = 0;
|
|
- try {
|
|
- OutStream.write(Buffer,0,Len);
|
|
- OutStream.flush();
|
|
- } catch (IOException ex) {
|
|
- LastError = errTCPDataSend;
|
|
- }
|
|
- }
|
|
- private void SendPacket(byte[] Buffer)
|
|
- {
|
|
- SendPacket(Buffer,Buffer.length);
|
|
- }
|
|
-
|
|
- private int RecvIsoPacket()
|
|
- {
|
|
- Boolean Done = false;
|
|
- int Size = 0;
|
|
- while ((LastError==0) && !Done)
|
|
- {
|
|
- // Get TPKT (4 bytes)
|
|
- RecvPacket(PDU, 0, 4);
|
|
- if (LastError==0)
|
|
- {
|
|
- Size=S7.GetWordAt(PDU,2);
|
|
- // Check 0 bytes Data Packet (only TPKT+COTP = 7 bytes)
|
|
- if (Size==IsoHSize)
|
|
- RecvPacket(PDU,4, 3); // Skip remaining 3 bytes and Done is still false
|
|
- else
|
|
- {
|
|
- if ((Size>MaxPduSize) || (Size<MinPduSize))
|
|
- LastError=errISOInvalidPDU;
|
|
- else
|
|
- Done = true; // a valid Length !=7 && >16 && <247
|
|
- }
|
|
- }
|
|
- }
|
|
- if (LastError==0)
|
|
- {
|
|
- RecvPacket(PDU,4, 3); // Skip remaining 3 COTP bytes
|
|
- LastPDUType=PDU[5]; // Stores PDU Type, we need it
|
|
- // Receives the S7 Payload
|
|
- RecvPacket(PDU, 7, Size-IsoHSize);
|
|
- }
|
|
- if (LastError==0)
|
|
- return Size;
|
|
- else
|
|
- return 0;
|
|
- }
|
|
-
|
|
- private int ISOConnect()
|
|
- {
|
|
- int Size;
|
|
- ISO_CR[16]=LocalTSAP_HI;
|
|
- ISO_CR[17]=LocalTSAP_LO;
|
|
- ISO_CR[20]=RemoteTSAP_HI;
|
|
- ISO_CR[21]=RemoteTSAP_LO;
|
|
-
|
|
- // Sends the connection request telegram
|
|
- SendPacket(ISO_CR);
|
|
- if (LastError==0)
|
|
- {
|
|
- // Gets the reply (if any)
|
|
- Size=RecvIsoPacket();
|
|
- if (LastError==0)
|
|
- {
|
|
- if (Size==22)
|
|
- {
|
|
- if (LastPDUType!=(byte)0xD0) // 0xD0 = CC Connection confirm
|
|
- LastError=errISOConnectionFailed;
|
|
- }
|
|
- else
|
|
- LastError=errISOInvalidPDU;
|
|
- }
|
|
- }
|
|
- return LastError;
|
|
- }
|
|
-
|
|
- private int NegotiatePduLength()
|
|
- {
|
|
- int Length;
|
|
- // Set PDU Size Requested
|
|
- S7.SetWordAt(S7_PN,23,DefaultPduSizeRequested);
|
|
- // Sends the connection request telegram
|
|
- SendPacket(S7_PN);
|
|
- if (LastError==0)
|
|
- {
|
|
- Length=RecvIsoPacket();
|
|
- if (LastError==0)
|
|
- {
|
|
- // check S7 Error
|
|
- if ((Length==27) && (PDU[17]==0) && (PDU[18]==0)) // 20 = size of Negotiate Answer
|
|
- {
|
|
- // Get PDU Size Negotiated
|
|
- _PDULength = S7.GetWordAt(PDU,25);
|
|
- if (_PDULength>0)
|
|
- return 0;
|
|
- else
|
|
- LastError=errISONegotiatingPDU;
|
|
- }
|
|
- else
|
|
- LastError=errISONegotiatingPDU;
|
|
- }
|
|
- }
|
|
- return LastError;
|
|
- }
|
|
-
|
|
- public void SetConnectionType(short ConnectionType)
|
|
- {
|
|
- ConnType=ConnectionType;
|
|
- }
|
|
-
|
|
- public int Connect()
|
|
- {
|
|
- LastError=0;
|
|
- if (!Connected)
|
|
- {
|
|
- TCPConnect();
|
|
- if (LastError==0) // First stage : TCP Connection
|
|
- {
|
|
- ISOConnect();
|
|
- if (LastError==0) // Second stage : ISOTCP (ISO 8073) Connection
|
|
- {
|
|
- LastError=NegotiatePduLength(); // Third stage : S7 PDU negotiation
|
|
- }
|
|
- }
|
|
- }
|
|
- Connected=LastError==0;
|
|
-
|
|
- // In case the connection is not completely established (TCP connection + ISO connection + PDU negotiation)
|
|
- // we close the socket and its IO streams to revert the object back to pre-Connect() state
|
|
- if (!Connected)
|
|
- {
|
|
- if (TCPSocket != null) {
|
|
- try {
|
|
- TCPSocket.close();
|
|
- } catch (IOException ex) {
|
|
- }
|
|
- }
|
|
- if (InStream != null) {
|
|
- try {
|
|
- InStream.close();
|
|
- } catch (IOException ex) {
|
|
- }
|
|
- }
|
|
- if (OutStream != null) {
|
|
- try {
|
|
- OutStream.close();
|
|
- } catch (IOException ex) {
|
|
- }
|
|
- }
|
|
- _PDULength = 0;
|
|
- }
|
|
-
|
|
- return LastError;
|
|
- }
|
|
-
|
|
- public void Disconnect()
|
|
- {
|
|
- if (Connected)
|
|
- {
|
|
- try {
|
|
- OutStream.close();
|
|
- InStream.close();
|
|
- TCPSocket.close();
|
|
- _PDULength=0;
|
|
- } catch (IOException ex) {
|
|
- }
|
|
- Connected=false;
|
|
- }
|
|
- }
|
|
-
|
|
- public int ConnectTo(String Address, int Rack, int Slot)
|
|
- {
|
|
- int RemoteTSAP=(ConnType<<8)+ (Rack * 0x20) + Slot;
|
|
- SetConnectionParams(Address, 0x0100, RemoteTSAP);
|
|
- return Connect();
|
|
- }
|
|
-
|
|
- public int PDULength()
|
|
- {
|
|
- return _PDULength;
|
|
- }
|
|
-
|
|
- public void SetConnectionParams(String Address, int LocalTSAP, int RemoteTSAP)
|
|
- {
|
|
- int LocTSAP = LocalTSAP & 0x0000FFFF;
|
|
- int RemTSAP = RemoteTSAP & 0x0000FFFF;
|
|
- IPAddress = Address;
|
|
- LocalTSAP_HI = (byte) (LocTSAP>>8);
|
|
- LocalTSAP_LO = (byte) (LocTSAP & 0x00FF);
|
|
- RemoteTSAP_HI= (byte) (RemTSAP>>8);
|
|
- RemoteTSAP_LO= (byte) (RemTSAP & 0x00FF);
|
|
- }
|
|
-
|
|
- public int ReadArea(int Area, int DBNumber, int Start, int Amount, byte[] Data)
|
|
- {
|
|
- int Address;
|
|
- int NumElements;
|
|
- int MaxElements;
|
|
- int TotElements;
|
|
- int SizeRequested;
|
|
- int Length;
|
|
- int Offset = 0;
|
|
- int WordSize = 1;
|
|
-
|
|
- LastError=0;
|
|
-
|
|
- // If we are addressing Timers or counters the element size is 2
|
|
- if ((Area==S7.S7AreaCT) || (Area==S7.S7AreaTM))
|
|
- WordSize = 2;
|
|
-
|
|
- MaxElements=(_PDULength-18) / WordSize; // 18 = Reply telegram header
|
|
- TotElements=Amount;
|
|
-
|
|
- while ((TotElements>0) && (LastError==0))
|
|
- {
|
|
- NumElements=TotElements;
|
|
- if (NumElements>MaxElements)
|
|
- NumElements=MaxElements;
|
|
-
|
|
- SizeRequested = NumElements * WordSize;
|
|
-
|
|
- // Setup the telegram
|
|
- System.arraycopy(S7_RW, 0, PDU, 0, Size_RD);
|
|
- // Set DB Number
|
|
- PDU[27] = (byte) Area;
|
|
- // Set Area
|
|
- if (Area==S7.S7AreaDB)
|
|
- S7.SetWordAt(PDU,25,DBNumber);
|
|
-
|
|
- // Adjusts Start and word length
|
|
- if ((Area==S7.S7AreaCT) || (Area==S7.S7AreaTM))
|
|
- {
|
|
- Address = Start;
|
|
- if (Area==S7.S7AreaCT)
|
|
- PDU[22]=S7WLCounter;
|
|
- else
|
|
- PDU[22]=S7WLTimer;
|
|
- }
|
|
- else
|
|
- Address = Start<<3;
|
|
-
|
|
- // Num elements
|
|
- S7.SetWordAt(PDU,23,NumElements);
|
|
-
|
|
- // Address into the PLC (only 3 bytes)
|
|
- PDU[30] = (byte) (Address & 0x0FF);
|
|
- Address = Address >> 8;
|
|
- PDU[29] = (byte) (Address & 0x0FF);
|
|
- Address = Address >> 8;
|
|
- PDU[28] = (byte) (Address & 0x0FF);
|
|
-
|
|
- SendPacket(PDU, Size_RD);
|
|
- if (LastError==0)
|
|
- {
|
|
- Length=RecvIsoPacket();
|
|
- if (LastError==0)
|
|
- {
|
|
- if (Length>=25)
|
|
- {
|
|
- if ((Length-25==SizeRequested) && (PDU[21]==(byte)0xFF))
|
|
- {
|
|
- System.arraycopy(PDU, 25, Data, Offset, SizeRequested);
|
|
- Offset+=SizeRequested;
|
|
- }
|
|
- else
|
|
- LastError = errS7DataRead;
|
|
- }
|
|
- else
|
|
- LastError = errS7InvalidPDU;
|
|
- }
|
|
- }
|
|
-
|
|
- TotElements -= NumElements;
|
|
- Start += NumElements*WordSize;
|
|
- }
|
|
- return LastError;
|
|
- }
|
|
-
|
|
- public int WriteArea(int Area, int DBNumber, int Start, int Amount, byte[] Data)
|
|
- {
|
|
- int Address;
|
|
- int NumElements;
|
|
- int MaxElements;
|
|
- int TotElements;
|
|
- int DataSize;
|
|
- int IsoSize;
|
|
- int Length;
|
|
- int Offset = 0;
|
|
- int WordSize = 1;
|
|
-
|
|
- LastError=0;
|
|
-
|
|
- // If we are addressing Timers or counters the element size is 2
|
|
- if ((Area==S7.S7AreaCT) || (Area==S7.S7AreaTM))
|
|
- WordSize = 2;
|
|
-
|
|
- MaxElements=(_PDULength-35) / WordSize; // 18 = Reply telegram header
|
|
- TotElements=Amount;
|
|
-
|
|
- while ((TotElements>0) && (LastError==0))
|
|
- {
|
|
- NumElements=TotElements;
|
|
- if (NumElements>MaxElements)
|
|
- NumElements=MaxElements;
|
|
-
|
|
- DataSize = NumElements * WordSize;
|
|
- IsoSize = Size_WR + DataSize;
|
|
-
|
|
- // Setup the telegram
|
|
- System.arraycopy(S7_RW, 0, PDU, 0, Size_WR);
|
|
- // Whole telegram Size
|
|
- S7.SetWordAt(PDU,2,IsoSize);
|
|
- // Data Length
|
|
- Length=DataSize+4;
|
|
- S7.SetWordAt(PDU,15,Length);
|
|
- // Function
|
|
- PDU[17]= (byte) 0x05;
|
|
- // Set DB Number
|
|
- PDU[27] = (byte) Area;
|
|
- if (Area==S7.S7AreaDB)
|
|
- S7.SetWordAt(PDU,25,DBNumber);
|
|
-
|
|
- // Adjusts Start and word length
|
|
- if ((Area==S7.S7AreaCT) || (Area==S7.S7AreaTM))
|
|
- {
|
|
- Address = Start;
|
|
- Length = DataSize;
|
|
- if (Area==S7.S7AreaCT)
|
|
- PDU[22]=S7WLCounter;
|
|
- else
|
|
- PDU[22]=S7WLTimer;
|
|
- }
|
|
- else
|
|
- {
|
|
- Address = Start<<3;
|
|
- Length = DataSize<<3;
|
|
- }
|
|
- // Num elements
|
|
- S7.SetWordAt(PDU,23,NumElements);
|
|
- // Address into the PLC
|
|
- PDU[30] = (byte) (Address & 0x0FF);
|
|
- Address = Address >> 8;
|
|
- PDU[29] = (byte) (Address & 0x0FF);
|
|
- Address = Address >> 8;
|
|
- PDU[28] = (byte) (Address & 0x0FF);
|
|
- // Length
|
|
- S7.SetWordAt(PDU,33,Length);
|
|
-
|
|
- // Copies the Data
|
|
- System.arraycopy(Data, Offset, PDU, 35, DataSize);
|
|
-
|
|
- SendPacket(PDU, IsoSize);
|
|
- if (LastError==0)
|
|
- {
|
|
- Length=RecvIsoPacket();
|
|
- if (LastError==0)
|
|
- {
|
|
- if (Length==22)
|
|
- {
|
|
- if ((S7.GetWordAt(PDU,17)!=0) || (PDU[21]!=(byte)0xFF))
|
|
- LastError = errS7DataWrite;
|
|
- }
|
|
- else
|
|
- LastError = errS7InvalidPDU;
|
|
- }
|
|
- }
|
|
-
|
|
- Offset+=DataSize;
|
|
- TotElements -= NumElements;
|
|
- Start += NumElements*WordSize;
|
|
- }
|
|
- return LastError;
|
|
- }
|
|
-
|
|
- public int GetAgBlockInfo(int BlockType, int BlockNumber, S7BlockInfo Block)
|
|
- {
|
|
- int Length;
|
|
- LastError=0;
|
|
- // Block Type
|
|
- S7_BI[30] = (byte) BlockType;
|
|
- // Block Number
|
|
- S7_BI[31]=(byte) ((BlockNumber / 10000)+0x30);
|
|
- BlockNumber=BlockNumber % 10000;
|
|
- S7_BI[32]=(byte) ((BlockNumber / 1000)+0x30);
|
|
- BlockNumber=BlockNumber % 1000;
|
|
- S7_BI[33]=(byte) ((BlockNumber / 100)+0x30);
|
|
- BlockNumber=BlockNumber % 100;
|
|
- S7_BI[34]=(byte) ((BlockNumber / 10)+0x30);
|
|
- BlockNumber=BlockNumber % 10;
|
|
- S7_BI[35]=(byte) ((BlockNumber / 1)+0x30);
|
|
-
|
|
- SendPacket(S7_BI);
|
|
- if (LastError==0)
|
|
- {
|
|
- Length=RecvIsoPacket();
|
|
- if (Length > 32) // the minimum expected
|
|
- {
|
|
- if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF))
|
|
- {
|
|
- Block.Update(PDU, 42);
|
|
- }
|
|
- else
|
|
- LastError = errS7FunctionError;
|
|
- }
|
|
- else
|
|
- LastError = errS7InvalidPDU;
|
|
- }
|
|
-
|
|
- return LastError;
|
|
- }
|
|
- /**
|
|
- *
|
|
- * @param DBNumber DB Number
|
|
- * @param Buffer Destination buffer
|
|
- * @param SizeRead How many bytes were read
|
|
- * @return
|
|
- */
|
|
- public int DBGet(int DBNumber, byte[] Buffer, IntByRef SizeRead)
|
|
- {
|
|
- S7BlockInfo Block = new S7BlockInfo();
|
|
- // Query the DB Length
|
|
- LastError = GetAgBlockInfo(S7.Block_DB, DBNumber, Block);
|
|
- if (LastError==0)
|
|
- {
|
|
- int SizeToRead = Block.MC7Size();
|
|
- // Checks the room
|
|
- if (SizeToRead<=Buffer.length)
|
|
- {
|
|
- LastError=ReadArea(S7.S7AreaDB, DBNumber, 0, SizeToRead, Buffer);
|
|
- if (LastError==0)
|
|
- SizeRead.Value=SizeToRead;
|
|
- }
|
|
- else
|
|
- LastError=errS7BufferTooSmall;
|
|
- }
|
|
- return LastError;
|
|
- }
|
|
-
|
|
- public int ReadSZL(int ID, int Index, S7Szl SZL)
|
|
- {
|
|
- int Length;
|
|
- int DataSZL;
|
|
- int Offset = 0;
|
|
- boolean Done = false;
|
|
- boolean First = true;
|
|
- byte Seq_in =0x00;
|
|
- int Seq_out =0x0000;
|
|
-
|
|
- LastError=0;
|
|
- SZL.DataSize=0;
|
|
- do
|
|
- {
|
|
- if (First)
|
|
- {
|
|
- S7.SetWordAt(S7_SZL_FIRST, 11, ++Seq_out);
|
|
- S7.SetWordAt(S7_SZL_FIRST, 29, ID);
|
|
- S7.SetWordAt(S7_SZL_FIRST, 31, Index);
|
|
- SendPacket(S7_SZL_FIRST);
|
|
- }
|
|
- else
|
|
- {
|
|
- S7.SetWordAt(S7_SZL_NEXT, 11, ++Seq_out);
|
|
- PDU[24] = (byte)Seq_in;
|
|
- SendPacket(S7_SZL_NEXT);
|
|
- }
|
|
- if (LastError!=0)
|
|
- return LastError;
|
|
-
|
|
- Length=RecvIsoPacket();
|
|
- if (LastError==0)
|
|
- {
|
|
- if (First)
|
|
- {
|
|
- if (Length > 32) // the minimum expected
|
|
- {
|
|
- if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF))
|
|
- {
|
|
- // Gets Amount of this slice
|
|
- DataSZL=S7.GetWordAt(PDU,31)-8; // Skips extra params (ID, Index ...)
|
|
- Done=PDU[26]==0x00;
|
|
- Seq_in=(byte)PDU[24]; // Slice sequence
|
|
-
|
|
- SZL.LENTHDR=S7.GetWordAt(PDU, 37);
|
|
- SZL.N_DR=S7.GetWordAt(PDU, 39);
|
|
- SZL.Copy(PDU, 41, Offset, DataSZL);
|
|
- Offset+=DataSZL;
|
|
- SZL.DataSize+=DataSZL;
|
|
- }
|
|
- else
|
|
- LastError = errS7FunctionError;
|
|
- }
|
|
- else
|
|
- LastError = errS7InvalidPDU;
|
|
- }
|
|
- else
|
|
- {
|
|
- if (Length > 32) // the minimum expected
|
|
- {
|
|
- if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF))
|
|
- {
|
|
- // Gets Amount of this slice
|
|
- DataSZL=S7.GetWordAt(PDU,31);
|
|
- Done=PDU[26]==0x00;
|
|
- Seq_in=(byte)PDU[24]; // Slice sequence
|
|
- SZL.Copy(PDU, 37, Offset, DataSZL);
|
|
- Offset+=DataSZL;
|
|
- SZL.DataSize+=DataSZL;
|
|
- }
|
|
- else
|
|
- LastError = errS7FunctionError;
|
|
- }
|
|
- else
|
|
- LastError = errS7InvalidPDU;
|
|
- }
|
|
- }
|
|
- First=false;
|
|
- }
|
|
- while(!Done && (LastError==0));
|
|
-
|
|
- return LastError;
|
|
- }
|
|
-
|
|
-
|
|
- public int GetCpuInfo(S7CpuInfo Info)
|
|
- {
|
|
- S7Szl SZL = new S7Szl(1024);
|
|
-
|
|
- LastError = ReadSZL(0x001C, 0x0000, SZL);
|
|
- if (LastError==0)
|
|
- {
|
|
- Info.Update(SZL.Data, 0);
|
|
- }
|
|
- return LastError;
|
|
- }
|
|
-
|
|
- public int GetCpInfo(S7CpInfo Info)
|
|
- {
|
|
- S7Szl SZL = new S7Szl(1024);
|
|
-
|
|
- LastError = ReadSZL(0x0131, 0x0001, SZL);
|
|
- if (LastError==0)
|
|
- {
|
|
- Info.Update(SZL.Data, 0);
|
|
- }
|
|
- return LastError;
|
|
- }
|
|
-
|
|
- public int GetOrderCode(S7OrderCode Code)
|
|
- {
|
|
- S7Szl SZL = new S7Szl(1024);
|
|
-
|
|
- LastError = ReadSZL(0x0011, 0x0000, SZL);
|
|
- if (LastError==0)
|
|
- {
|
|
- Code.Update(SZL.Data, 0, SZL.DataSize);
|
|
- }
|
|
- return LastError;
|
|
- }
|
|
-
|
|
- public int GetPlcDateTime(Date DateTime)
|
|
- {
|
|
- int Length;
|
|
-
|
|
- LastError = 0;
|
|
- SendPacket(S7_GET_DT);
|
|
- if (LastError==0)
|
|
- {
|
|
- Length=RecvIsoPacket();
|
|
- if (Length > 30) // the minimum expected
|
|
- {
|
|
- if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF))
|
|
- {
|
|
- DateTime=S7.GetDateAt(PDU, 34);
|
|
- }
|
|
- else
|
|
- LastError = errS7FunctionError;
|
|
- }
|
|
- else
|
|
- LastError = errS7InvalidPDU;
|
|
- }
|
|
-
|
|
- return LastError;
|
|
- }
|
|
-
|
|
- public int SetPlcDateTime(Date DateTime)
|
|
- {
|
|
- int Length;
|
|
-
|
|
- LastError = 0;
|
|
- S7.SetDateAt(S7_SET_DT, 31, DateTime);
|
|
-
|
|
- SendPacket(S7_SET_DT);
|
|
- if (LastError==0)
|
|
- {
|
|
- Length=RecvIsoPacket();
|
|
- if (Length > 30) // the minimum expected
|
|
- {
|
|
- if (S7.GetWordAt(PDU,27)!=0)
|
|
- LastError = errS7FunctionError;
|
|
- }
|
|
- else
|
|
- LastError = errS7InvalidPDU;
|
|
- }
|
|
-
|
|
- return LastError;
|
|
- }
|
|
-
|
|
- public int SetPlcSystemDateTime()
|
|
- {
|
|
- return SetPlcDateTime(new Date());
|
|
- }
|
|
-
|
|
- public int PlcStop()
|
|
- {
|
|
- int Length;
|
|
-
|
|
- LastError = 0;
|
|
- SendPacket(S7_STOP);
|
|
- if (LastError==0)
|
|
- {
|
|
- Length=RecvIsoPacket();
|
|
- if (Length > 18) // 18 is the minimum expected
|
|
- {
|
|
- if (S7.GetWordAt(PDU,17)!=0)
|
|
- LastError = errS7FunctionError;
|
|
- }
|
|
- else
|
|
- LastError = errS7InvalidPDU;
|
|
- }
|
|
- return LastError;
|
|
- }
|
|
-
|
|
- public int PlcHotStart()
|
|
- {
|
|
- int Length;
|
|
-
|
|
- LastError = 0;
|
|
- SendPacket(S7_HOT_START);
|
|
- if (LastError==0)
|
|
- {
|
|
- Length=RecvIsoPacket();
|
|
- if (Length > 18) // the minimum expected
|
|
- {
|
|
- if (S7.GetWordAt(PDU,17)!=0)
|
|
- LastError = errS7FunctionError;
|
|
- }
|
|
- else
|
|
- LastError = errS7InvalidPDU;
|
|
- }
|
|
- return LastError;
|
|
- }
|
|
-
|
|
- public int PlcColdStart()
|
|
- {
|
|
- int Length;
|
|
-
|
|
- LastError = 0;
|
|
- SendPacket(S7_COLD_START);
|
|
- if (LastError==0)
|
|
- {
|
|
- Length=RecvIsoPacket();
|
|
- if (Length > 18) // the minimum expected
|
|
- {
|
|
- if (S7.GetWordAt(PDU,17)!=0)
|
|
- LastError = errS7FunctionError;
|
|
- }
|
|
- else
|
|
- LastError = errS7InvalidPDU;
|
|
- }
|
|
- return LastError;
|
|
- }
|
|
-
|
|
- public int GetPlcStatus(IntByRef Status)
|
|
- {
|
|
- int Length;
|
|
-
|
|
- LastError = 0;
|
|
- SendPacket(S7_GET_STAT);
|
|
- if (LastError==0)
|
|
- {
|
|
- Length=RecvIsoPacket();
|
|
- if (Length > 30) // the minimum expected
|
|
- {
|
|
- if (S7.GetWordAt(PDU,27)==0)
|
|
- {
|
|
- switch (PDU[44])
|
|
- {
|
|
- case S7.S7CpuStatusUnknown :
|
|
- case S7.S7CpuStatusRun :
|
|
- case S7.S7CpuStatusStop : Status.Value=PDU[44];
|
|
- break;
|
|
- default :
|
|
- // Since RUN status is always 0x08 for all CPUs and CPs, STOP status
|
|
- // sometime can be coded as 0x03 (especially for old cpu...)
|
|
- Status.Value=S7.S7CpuStatusStop;
|
|
- }
|
|
- }
|
|
- else
|
|
- LastError = errS7FunctionError;
|
|
- }
|
|
- else
|
|
- LastError = errS7InvalidPDU;
|
|
- }
|
|
- return LastError;
|
|
- }
|
|
-
|
|
- public int SetSessionPassword(String Password)
|
|
- {
|
|
- byte[] pwd = {0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20};
|
|
- int Length;
|
|
-
|
|
- LastError = 0;
|
|
- // Adjusts the Password length to 8
|
|
- if (Password.length()>8)
|
|
- Password=Password.substring(0, 8);
|
|
- else
|
|
- {
|
|
- while (Password.length()<8)
|
|
- Password=Password+" ";
|
|
- }
|
|
-
|
|
- try {
|
|
- pwd = Password.getBytes("UTF-8");
|
|
- } catch (UnsupportedEncodingException ex) {
|
|
- LastError = errS7InvalidParams;
|
|
- }
|
|
- if (LastError==0)
|
|
- {
|
|
- // Encodes the password
|
|
- pwd[0]=(byte) (pwd[0] ^ 0x55);
|
|
- pwd[1]=(byte) (pwd[1] ^ 0x55);
|
|
- for (int c = 2; c < 8; c++)
|
|
- {
|
|
- pwd[c]=(byte) (pwd[c] ^ 0x55 ^ pwd[c-2]);
|
|
- }
|
|
- System.arraycopy(pwd, 0, S7_SET_PWD, 29, 8);
|
|
- // Sends the telegrem
|
|
- SendPacket(S7_SET_PWD);
|
|
- if (LastError==0)
|
|
- {
|
|
- Length=RecvIsoPacket();
|
|
- if (Length > 32) // the minimum expected
|
|
- {
|
|
- if (S7.GetWordAt(PDU,27)!=0)
|
|
- LastError = errS7FunctionError;
|
|
- }
|
|
- else
|
|
- LastError = errS7InvalidPDU;
|
|
- }
|
|
- }
|
|
- return LastError;
|
|
- }
|
|
-
|
|
- public int ClearSessionPassword()
|
|
- {
|
|
- int Length;
|
|
-
|
|
- LastError = 0;
|
|
- SendPacket(S7_CLR_PWD);
|
|
- if (LastError==0)
|
|
- {
|
|
- Length=RecvIsoPacket();
|
|
- if (Length > 30) // the minimum expected
|
|
- {
|
|
- if (S7.GetWordAt(PDU,27)!=0)
|
|
- LastError = errS7FunctionError;
|
|
- }
|
|
- else
|
|
- LastError = errS7InvalidPDU;
|
|
- }
|
|
- return LastError;
|
|
- }
|
|
-
|
|
- public int GetProtection(S7Protection Protection)
|
|
- {
|
|
- S7Szl SZL = new S7Szl(256);
|
|
-
|
|
- LastError = ReadSZL(0x0232, 0x0004, SZL);
|
|
- if (LastError==0)
|
|
- {
|
|
- Protection.Update(SZL.Data);
|
|
- }
|
|
- return LastError;
|
|
- }
|
|
-
|
|
-}
|
|
+/*=============================================================================|
|
|
+| PROJECT Moka7 1.0.2 |
|
|
+|==============================================================================|
|
|
+| Copyright (C) 2013, 2016 Davide Nardella |
|
|
+| All rights reserved. |
|
|
+|==============================================================================|
|
|
+| SNAP7 is free software: you can redistribute it and/or modify |
|
|
+| it under the terms of the Lesser GNU General Public License as published by |
|
|
+| the Free Software Foundation, either version 3 of the License, or under |
|
|
+| EPL Eclipse Public License 1.0. |
|
|
+| |
|
|
+| This means that you have to chose in advance which take before you import |
|
|
+| the library into your project. |
|
|
+| |
|
|
+| SNAP7 is distributed in the hope that it will be useful, |
|
|
+| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you |
|
|
+| decide to adopt. |
|
|
+| |
|
|
+|=============================================================================*/
|
|
+package Moka7;
|
|
+
|
|
+import java.io.DataInputStream;
|
|
+import java.io.DataOutputStream;
|
|
+import java.io.IOException;
|
|
+import java.io.UnsupportedEncodingException;
|
|
+import java.net.InetSocketAddress;
|
|
+import java.net.Socket;
|
|
+import java.net.SocketAddress;
|
|
+import java.util.Date;
|
|
+
|
|
+
|
|
+/**
|
|
+ *
|
|
+ * @author Davide Nardella
|
|
+ */
|
|
+public class S7Client
|
|
+{
|
|
+ // WordLength
|
|
+ public static final int S7WLBit = 0x01;
|
|
+ public static final int S7WLByte = 0x02;
|
|
+ public static final int S7WLCounter = 0x1C;
|
|
+ public static final int S7WLTimer = 0x1D;
|
|
+
|
|
+ // Error Codes
|
|
+ public static final int errTCPConnectionFailed = 0x0001;
|
|
+ public static final int errTCPDataSend = 0x0002;
|
|
+ public static final int errTCPDataRecv = 0x0003;
|
|
+ public static final int errTCPDataRecvTout = 0x0004;
|
|
+ public static final int errTCPConnectionReset = 0x0005;
|
|
+ public static final int errISOInvalidPDU = 0x0006;
|
|
+ public static final int errISOConnectionFailed = 0x0007;
|
|
+ public static final int errISONegotiatingPDU = 0x0008;
|
|
+ public static final int errS7InvalidPDU = 0x0009;
|
|
+ public static final int errS7DataRead = 0x000A;
|
|
+ public static final int errS7DataWrite = 0x000B;
|
|
+ public static final int errS7BufferTooSmall = 0x000C;
|
|
+ public static final int errS7FunctionError = 0x000D;
|
|
+ public static final int errS7InvalidParams = 0x000E;
|
|
+
|
|
+ // Public fields
|
|
+ public boolean Connected = false;
|
|
+ public int LastError = 0;
|
|
+ public int RecvTimeout = 2000;
|
|
+
|
|
+ // Privates
|
|
+ private static final int ISOTCP = 102; // ISOTCP Port
|
|
+ private static final int MinPduSize = 16;
|
|
+ private static final int DefaultPduSizeRequested = 480;
|
|
+ private static final int IsoHSize = 7; // TPKT+COTP Header Size
|
|
+ private static final int MaxPduSize = DefaultPduSizeRequested+IsoHSize;
|
|
+
|
|
+ private Socket TCPSocket;
|
|
+ private final byte[] PDU = new byte[2048];
|
|
+
|
|
+ private DataInputStream InStream = null;
|
|
+ private DataOutputStream OutStream = null;
|
|
+
|
|
+ private String IPAddress;
|
|
+
|
|
+ private byte LocalTSAP_HI;
|
|
+ private byte LocalTSAP_LO;
|
|
+ private byte RemoteTSAP_HI;
|
|
+ private byte RemoteTSAP_LO;
|
|
+ private byte LastPDUType;
|
|
+
|
|
+ private short ConnType = S7.PG;
|
|
+ private int _PDULength = 0;
|
|
+
|
|
+ // Telegrams
|
|
+ // ISO Connection Request telegram (contains also ISO Header and COTP Header)
|
|
+ private static final byte ISO_CR[] = {
|
|
+ // TPKT (RFC1006 Header)
|
|
+ (byte)0x03, // RFC 1006 ID (3)
|
|
+ (byte)0x00, // Reserved, always 0
|
|
+ (byte)0x00, // High part of packet lenght (entire frame, payload and TPDU included)
|
|
+ (byte)0x16, // Low part of packet lenght (entire frame, payload and TPDU included)
|
|
+ // COTP (ISO 8073 Header)
|
|
+ (byte)0x11, // PDU Size Length
|
|
+ (byte)0xE0, // CR - Connection Request ID
|
|
+ (byte)0x00, // Dst Reference HI
|
|
+ (byte)0x00, // Dst Reference LO
|
|
+ (byte)0x00, // Src Reference HI
|
|
+ (byte)0x01, // Src Reference LO
|
|
+ (byte)0x00, // Class + Options Flags
|
|
+ (byte)0xC0, // PDU Max Length ID
|
|
+ (byte)0x01, // PDU Max Length HI
|
|
+ (byte)0x0A, // PDU Max Length LO
|
|
+ (byte)0xC1, // Src TSAP Identifier
|
|
+ (byte)0x02, // Src TSAP Length (2 bytes)
|
|
+ (byte)0x01, // Src TSAP HI (will be overwritten)
|
|
+ (byte)0x00, // Src TSAP LO (will be overwritten)
|
|
+ (byte)0xC2, // Dst TSAP Identifier
|
|
+ (byte)0x02, // Dst TSAP Length (2 bytes)
|
|
+ (byte)0x01, // Dst TSAP HI (will be overwritten)
|
|
+ (byte)0x02 // Dst TSAP LO (will be overwritten)
|
|
+ };
|
|
+
|
|
+ // S7 PDU Negotiation Telegram (contains also ISO Header and COTP Header)
|
|
+ private static final byte S7_PN[] = {
|
|
+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x19,
|
|
+ (byte)0x02, (byte)0xf0, (byte)0x80, // TPKT + COTP (see above for info)
|
|
+ (byte)0x32, (byte)0x01, (byte)0x00, (byte)0x00,
|
|
+ (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x08,
|
|
+ (byte)0x00, (byte)0x00, (byte)0xf0, (byte)0x00,
|
|
+ (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x01,
|
|
+ (byte)0x00, (byte)0x1e // PDU Length Requested = HI-LO 480 bytes
|
|
+ };
|
|
+
|
|
+ // S7 Read/Write Request Header (contains also ISO Header and COTP Header)
|
|
+ private static final byte S7_RW[] = { // 31-35 bytes
|
|
+ (byte)0x03,(byte)0x00,
|
|
+ (byte)0x00,(byte)0x1f, // Telegram Length (Data Size + 31 or 35)
|
|
+ (byte)0x02,(byte)0xf0, (byte)0x80, // COTP (see above for info)
|
|
+ (byte)0x32, // S7 Protocol ID
|
|
+ (byte)0x01, // Job Type
|
|
+ (byte)0x00,(byte)0x00, // Redundancy identification
|
|
+ (byte)0x05,(byte)0x00, // PDU Reference
|
|
+ (byte)0x00,(byte)0x0e, // Parameters Length
|
|
+ (byte)0x00,(byte)0x00, // Data Length = Size(bytes) + 4
|
|
+ (byte)0x04, // Function 4 Read Var, 5 Write Var
|
|
+ (byte)0x01, // Items count
|
|
+ (byte)0x12, // Var spec.
|
|
+ (byte)0x0a, // Length of remaining bytes
|
|
+ (byte)0x10, // Syntax ID
|
|
+ S7WLByte, // Transport Size
|
|
+ (byte)0x00,(byte)0x00, // Num Elements
|
|
+ (byte)0x00,(byte)0x00, // DB Number (if any, else 0)
|
|
+ (byte)0x84, // Area Type
|
|
+ (byte)0x00,(byte)0x00,(byte)0x00, // Area Offset
|
|
+ // WR area
|
|
+ (byte)0x00, // Reserved
|
|
+ (byte)0x04, // Transport size
|
|
+ (byte)0x00,(byte)0x00, // Data Length * 8 (if not timer or counter)
|
|
+ };
|
|
+ private static final int Size_RD = 31;
|
|
+ private static final int Size_WR = 35;
|
|
+
|
|
+ // S7 Get Block Info Request Header (contains also ISO Header and COTP Header)
|
|
+ private static final byte S7_BI[] = {
|
|
+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x25,
|
|
+ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32,
|
|
+ (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x05,
|
|
+ (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00,
|
|
+ (byte)0x0c, (byte)0x00, (byte)0x01, (byte)0x12,
|
|
+ (byte)0x04, (byte)0x11, (byte)0x43, (byte)0x03,
|
|
+ (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00,
|
|
+ (byte)0x08, (byte)0x30,
|
|
+ (byte)0x41, // Block Type
|
|
+ (byte)0x30, (byte)0x30, (byte)0x30, (byte)0x30, (byte)0x30, // ASCII Block Number
|
|
+ (byte)0x41
|
|
+ };
|
|
+
|
|
+ // SZL First telegram request
|
|
+ private static final byte S7_SZL_FIRST[] = {
|
|
+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21,
|
|
+ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32,
|
|
+ (byte)0x07, (byte)0x00, (byte)0x00,
|
|
+ (byte)0x05, (byte)0x00, // Sequence out
|
|
+ (byte)0x00, (byte)0x08, (byte)0x00,
|
|
+ (byte)0x08, (byte)0x00, (byte)0x01, (byte)0x12,
|
|
+ (byte)0x04, (byte)0x11, (byte)0x44, (byte)0x01,
|
|
+ (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00,
|
|
+ (byte)0x04,
|
|
+ (byte)0x00, (byte)0x00, // ID (29)
|
|
+ (byte)0x00, (byte)0x00 // Index (31)
|
|
+ };
|
|
+
|
|
+ // SZL Next telegram request
|
|
+ private static final byte S7_SZL_NEXT[] = {
|
|
+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21,
|
|
+ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32,
|
|
+ (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x06,
|
|
+ (byte)0x00, (byte)0x00, (byte)0x0c, (byte)0x00,
|
|
+ (byte)0x04, (byte)0x00, (byte)0x01, (byte)0x12,
|
|
+ (byte)0x08, (byte)0x12, (byte)0x44, (byte)0x01,
|
|
+ (byte)0x01, // Sequence
|
|
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
|
|
+ (byte)0x0a, (byte)0x00, (byte)0x00, (byte)0x00
|
|
+ };
|
|
+
|
|
+ // Get Date/Time request
|
|
+ private static final byte S7_GET_DT[] = {
|
|
+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x1d,
|
|
+ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32,
|
|
+ (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x38,
|
|
+ (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00,
|
|
+ (byte)0x04, (byte)0x00, (byte)0x01, (byte)0x12,
|
|
+ (byte)0x04, (byte)0x11, (byte)0x47, (byte)0x01,
|
|
+ (byte)0x00, (byte)0x0a, (byte)0x00, (byte)0x00,
|
|
+ (byte)0x00
|
|
+ };
|
|
+
|
|
+ // Set Date/Time command
|
|
+ private static final byte S7_SET_DT[] = {
|
|
+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x27,
|
|
+ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32,
|
|
+ (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x89,
|
|
+ (byte)0x03, (byte)0x00, (byte)0x08, (byte)0x00,
|
|
+ (byte)0x0e, (byte)0x00, (byte)0x01, (byte)0x12,
|
|
+ (byte)0x04, (byte)0x11, (byte)0x47, (byte)0x02,
|
|
+ (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00,
|
|
+ (byte)0x0a, (byte)0x00, (byte)0x19, // Hi part of Year
|
|
+ (byte)0x13, // Lo part of Year
|
|
+ (byte)0x12, // Month
|
|
+ (byte)0x06, // Day
|
|
+ (byte)0x17, // Hour
|
|
+ (byte)0x37, // Min
|
|
+ (byte)0x13, // Sec
|
|
+ (byte)0x00, (byte)0x01 // ms + Day of week
|
|
+ };
|
|
+
|
|
+ // S7 STOP request
|
|
+ private static final byte S7_STOP[] = {
|
|
+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21,
|
|
+ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32,
|
|
+ (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x0e,
|
|
+ (byte)0x00, (byte)0x00, (byte)0x10, (byte)0x00,
|
|
+ (byte)0x00, (byte)0x29, (byte)0x00, (byte)0x00,
|
|
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x09,
|
|
+ (byte)0x50, (byte)0x5f, (byte)0x50, (byte)0x52,
|
|
+ (byte)0x4f, (byte)0x47, (byte)0x52, (byte)0x41,
|
|
+ (byte)0x4d
|
|
+ };
|
|
+
|
|
+ // S7 HOT Start request
|
|
+ private static final byte S7_HOT_START[] = {
|
|
+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x25,
|
|
+ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32,
|
|
+ (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x0c,
|
|
+ (byte)0x00, (byte)0x00, (byte)0x14, (byte)0x00,
|
|
+ (byte)0x00, (byte)0x28, (byte)0x00, (byte)0x00,
|
|
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
|
|
+ (byte)0xfd, (byte)0x00, (byte)0x00, (byte)0x09,
|
|
+ (byte)0x50, (byte)0x5f, (byte)0x50, (byte)0x52,
|
|
+ (byte)0x4f, (byte)0x47, (byte)0x52, (byte)0x41,
|
|
+ (byte)0x4d
|
|
+ };
|
|
+
|
|
+ // S7 COLD Start request
|
|
+ private static final byte S7_COLD_START[] = {
|
|
+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x27,
|
|
+ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32,
|
|
+ (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x0f,
|
|
+ (byte)0x00, (byte)0x00, (byte)0x16, (byte)0x00,
|
|
+ (byte)0x00, (byte)0x28, (byte)0x00, (byte)0x00,
|
|
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
|
|
+ (byte)0xfd, (byte)0x00, (byte)0x02, (byte)0x43,
|
|
+ (byte)0x20, (byte)0x09, (byte)0x50, (byte)0x5f,
|
|
+ (byte)0x50, (byte)0x52, (byte)0x4f, (byte)0x47,
|
|
+ (byte)0x52, (byte)0x41, (byte)0x4d
|
|
+ };
|
|
+
|
|
+ // S7 Get PLC Status
|
|
+ private static final byte S7_GET_STAT[] = {
|
|
+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21,
|
|
+ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32,
|
|
+ (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x2c,
|
|
+ (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00,
|
|
+ (byte)0x08, (byte)0x00, (byte)0x01, (byte)0x12,
|
|
+ (byte)0x04, (byte)0x11, (byte)0x44, (byte)0x01,
|
|
+ (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00,
|
|
+ (byte)0x04, (byte)0x04, (byte)0x24, (byte)0x00,
|
|
+ (byte)0x00
|
|
+ };
|
|
+
|
|
+ // S7 Set Session Password
|
|
+ private static final byte S7_SET_PWD[] = {
|
|
+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x25,
|
|
+ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32,
|
|
+ (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x27,
|
|
+ (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00,
|
|
+ (byte)0x0c, (byte)0x00, (byte)0x01, (byte)0x12,
|
|
+ (byte)0x04, (byte)0x11, (byte)0x45, (byte)0x01,
|
|
+ (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00,
|
|
+ (byte)0x08,
|
|
+ // 8 Char Encoded Password
|
|
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
|
|
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00
|
|
+ };
|
|
+
|
|
+ // S7 Clear Session Password
|
|
+ private static final byte S7_CLR_PWD[] = {
|
|
+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x1d,
|
|
+ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32,
|
|
+ (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x29,
|
|
+ (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00,
|
|
+ (byte)0x04, (byte)0x00, (byte)0x01, (byte)0x12,
|
|
+ (byte)0x04, (byte)0x11, (byte)0x45, (byte)0x02,
|
|
+ (byte)0x00, (byte)0x0a, (byte)0x00, (byte)0x00,
|
|
+ (byte)0x00
|
|
+ };
|
|
+
|
|
+ public S7Client()
|
|
+ {
|
|
+ // Placeholder for future implementations
|
|
+ }
|
|
+
|
|
+ public static String ErrorText(int Error)
|
|
+ {
|
|
+ switch (Error)
|
|
+ {
|
|
+ case errTCPConnectionFailed :
|
|
+ return "TCP Connection failed.";
|
|
+ case errTCPDataSend :
|
|
+ return "TCP Sending error.";
|
|
+ case errTCPDataRecv :
|
|
+ return "TCP Receiving error.";
|
|
+ case errTCPDataRecvTout :
|
|
+ return "Data Receiving timeout.";
|
|
+ case errTCPConnectionReset :
|
|
+ return "Connection reset by the peer.";
|
|
+ case errISOInvalidPDU :
|
|
+ return "Invalid ISO PDU received.";
|
|
+ case errISOConnectionFailed :
|
|
+ return "ISO connection refused by the CPU.";
|
|
+ case errISONegotiatingPDU :
|
|
+ return "ISO error negotiating the PDU length.";
|
|
+ case errS7InvalidPDU :
|
|
+ return "Invalid S7 PDU received.";
|
|
+ case errS7DataRead :
|
|
+ return "S7 Error reading data from the CPU.";
|
|
+ case errS7DataWrite :
|
|
+ return "S7 Error writing data to the CPU.";
|
|
+ case errS7BufferTooSmall :
|
|
+ return "The Buffer supplied to the function is too small.";
|
|
+ case errS7FunctionError :
|
|
+ return "S7 function refused by the CPU.";
|
|
+ case errS7InvalidParams :
|
|
+ return "Invalid parameters supplied to the function.";
|
|
+ default :
|
|
+ return "Unknown error : 0x"+Integer.toHexString(Error);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private int TCPConnect()
|
|
+ {
|
|
+ SocketAddress sockaddr = new InetSocketAddress(IPAddress, ISOTCP);
|
|
+ LastError=0;
|
|
+ try {
|
|
+ TCPSocket = new Socket();
|
|
+ TCPSocket.connect(sockaddr ,5000);
|
|
+ TCPSocket.setTcpNoDelay(true);
|
|
+ InStream = new DataInputStream(TCPSocket.getInputStream());
|
|
+ OutStream = new DataOutputStream(TCPSocket.getOutputStream());
|
|
+ }
|
|
+ catch (IOException e) {
|
|
+ LastError=errTCPConnectionFailed;
|
|
+ }
|
|
+ return LastError;
|
|
+ }
|
|
+
|
|
+ private int WaitForData(int Size, int Timeout)
|
|
+ {
|
|
+ int cnt = 0;
|
|
+ LastError=0;
|
|
+ int SizeAvail;
|
|
+ boolean Expired = false;
|
|
+ try
|
|
+ {
|
|
+ SizeAvail=InStream.available();
|
|
+ while ((SizeAvail<Size) && (!Expired) && (LastError==0))
|
|
+ {
|
|
+ cnt++;
|
|
+ try {
|
|
+ Thread.sleep(1);
|
|
+ }
|
|
+ catch (InterruptedException ex) {
|
|
+ LastError=errTCPDataRecvTout;
|
|
+ }
|
|
+ SizeAvail=InStream.available();
|
|
+ Expired=cnt>Timeout;
|
|
+ // If timeout we clean the buffer
|
|
+ if (Expired && (SizeAvail>0) && (LastError==0))
|
|
+ InStream.read(PDU, 0, SizeAvail);
|
|
+ }
|
|
+ }
|
|
+ catch (IOException ex)
|
|
+ {
|
|
+ LastError=errTCPDataRecvTout;
|
|
+ }
|
|
+ if (cnt>=Timeout)
|
|
+ {
|
|
+ LastError=errTCPDataRecvTout;
|
|
+ }
|
|
+ return LastError;
|
|
+ }
|
|
+
|
|
+ private int RecvPacket(byte[] Buffer, int Start, int Size)
|
|
+ {
|
|
+ int BytesRead=0;
|
|
+ LastError=WaitForData(Size,RecvTimeout);
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ try {
|
|
+ BytesRead = InStream.read(Buffer, Start, Size);
|
|
+ } catch (IOException ex) {
|
|
+ LastError=errTCPDataRecv;
|
|
+ }
|
|
+ if (BytesRead==0)
|
|
+ LastError=errTCPConnectionReset;
|
|
+ }
|
|
+ return LastError;
|
|
+ }
|
|
+
|
|
+ private void SendPacket(byte[] Buffer, int Len)
|
|
+ {
|
|
+ LastError = 0;
|
|
+ try {
|
|
+ OutStream.write(Buffer,0,Len);
|
|
+ OutStream.flush();
|
|
+ } catch (IOException ex) {
|
|
+ LastError = errTCPDataSend;
|
|
+ }
|
|
+ }
|
|
+ private void SendPacket(byte[] Buffer)
|
|
+ {
|
|
+ SendPacket(Buffer,Buffer.length);
|
|
+ }
|
|
+
|
|
+ private int RecvIsoPacket()
|
|
+ {
|
|
+ Boolean Done = false;
|
|
+ int Size = 0;
|
|
+ while ((LastError==0) && !Done)
|
|
+ {
|
|
+ // Get TPKT (4 bytes)
|
|
+ RecvPacket(PDU, 0, 4);
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ Size=S7.GetWordAt(PDU,2);
|
|
+ // Check 0 bytes Data Packet (only TPKT+COTP = 7 bytes)
|
|
+ if (Size==IsoHSize)
|
|
+ RecvPacket(PDU,4, 3); // Skip remaining 3 bytes and Done is still false
|
|
+ else
|
|
+ {
|
|
+ if ((Size>MaxPduSize) || (Size<MinPduSize))
|
|
+ LastError=errISOInvalidPDU;
|
|
+ else
|
|
+ Done = true; // a valid Length !=7 && >16 && <247
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ RecvPacket(PDU,4, 3); // Skip remaining 3 COTP bytes
|
|
+ LastPDUType=PDU[5]; // Stores PDU Type, we need it
|
|
+ // Receives the S7 Payload
|
|
+ RecvPacket(PDU, 7, Size-IsoHSize);
|
|
+ }
|
|
+ if (LastError==0)
|
|
+ return Size;
|
|
+ else
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ private int ISOConnect()
|
|
+ {
|
|
+ int Size;
|
|
+ ISO_CR[16]=LocalTSAP_HI;
|
|
+ ISO_CR[17]=LocalTSAP_LO;
|
|
+ ISO_CR[20]=RemoteTSAP_HI;
|
|
+ ISO_CR[21]=RemoteTSAP_LO;
|
|
+
|
|
+ // Sends the connection request telegram
|
|
+ SendPacket(ISO_CR);
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ // Gets the reply (if any)
|
|
+ Size=RecvIsoPacket();
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ if (Size==22)
|
|
+ {
|
|
+ if (LastPDUType!=(byte)0xD0) // 0xD0 = CC Connection confirm
|
|
+ LastError=errISOConnectionFailed;
|
|
+ }
|
|
+ else
|
|
+ LastError=errISOInvalidPDU;
|
|
+ }
|
|
+ }
|
|
+ return LastError;
|
|
+ }
|
|
+
|
|
+ private int NegotiatePduLength()
|
|
+ {
|
|
+ int Length;
|
|
+ // Set PDU Size Requested
|
|
+ S7.SetWordAt(S7_PN,23,DefaultPduSizeRequested);
|
|
+ // Sends the connection request telegram
|
|
+ SendPacket(S7_PN);
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ Length=RecvIsoPacket();
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ // check S7 Error
|
|
+ if ((Length==27) && (PDU[17]==0) && (PDU[18]==0)) // 20 = size of Negotiate Answer
|
|
+ {
|
|
+ // Get PDU Size Negotiated
|
|
+ _PDULength = S7.GetWordAt(PDU,25);
|
|
+ if (_PDULength>0)
|
|
+ return 0;
|
|
+ else
|
|
+ LastError=errISONegotiatingPDU;
|
|
+ }
|
|
+ else
|
|
+ LastError=errISONegotiatingPDU;
|
|
+ }
|
|
+ }
|
|
+ return LastError;
|
|
+ }
|
|
+
|
|
+ public void SetConnectionType(short ConnectionType)
|
|
+ {
|
|
+ ConnType=ConnectionType;
|
|
+ }
|
|
+
|
|
+ public int Connect()
|
|
+ {
|
|
+ LastError=0;
|
|
+ if (!Connected)
|
|
+ {
|
|
+ TCPConnect();
|
|
+ if (LastError==0) // First stage : TCP Connection
|
|
+ {
|
|
+ ISOConnect();
|
|
+ if (LastError==0) // Second stage : ISOTCP (ISO 8073) Connection
|
|
+ {
|
|
+ LastError=NegotiatePduLength(); // Third stage : S7 PDU negotiation
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ Connected=LastError==0;
|
|
+
|
|
+ // In case the connection is not completely established (TCP connection + ISO connection + PDU negotiation)
|
|
+ // we close the socket and its IO streams to revert the object back to pre-Connect() state
|
|
+ if (!Connected)
|
|
+ {
|
|
+ if (TCPSocket != null) {
|
|
+ try {
|
|
+ TCPSocket.close();
|
|
+ } catch (IOException ex) {
|
|
+ }
|
|
+ }
|
|
+ if (InStream != null) {
|
|
+ try {
|
|
+ InStream.close();
|
|
+ } catch (IOException ex) {
|
|
+ }
|
|
+ }
|
|
+ if (OutStream != null) {
|
|
+ try {
|
|
+ OutStream.close();
|
|
+ } catch (IOException ex) {
|
|
+ }
|
|
+ }
|
|
+ _PDULength = 0;
|
|
+ }
|
|
+
|
|
+ return LastError;
|
|
+ }
|
|
+
|
|
+ public void Disconnect()
|
|
+ {
|
|
+ if (Connected)
|
|
+ {
|
|
+ try {
|
|
+ OutStream.close();
|
|
+ InStream.close();
|
|
+ TCPSocket.close();
|
|
+ _PDULength=0;
|
|
+ } catch (IOException ex) {
|
|
+ }
|
|
+ Connected=false;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public int ConnectTo(String Address, int Rack, int Slot)
|
|
+ {
|
|
+ int RemoteTSAP=(ConnType<<8)+ (Rack * 0x20) + Slot;
|
|
+ SetConnectionParams(Address, 0x0100, RemoteTSAP);
|
|
+ return Connect();
|
|
+ }
|
|
+
|
|
+ public int PDULength()
|
|
+ {
|
|
+ return _PDULength;
|
|
+ }
|
|
+
|
|
+ public void SetConnectionParams(String Address, int LocalTSAP, int RemoteTSAP)
|
|
+ {
|
|
+ int LocTSAP = LocalTSAP & 0x0000FFFF;
|
|
+ int RemTSAP = RemoteTSAP & 0x0000FFFF;
|
|
+ IPAddress = Address;
|
|
+ LocalTSAP_HI = (byte) (LocTSAP>>8);
|
|
+ LocalTSAP_LO = (byte) (LocTSAP & 0x00FF);
|
|
+ RemoteTSAP_HI= (byte) (RemTSAP>>8);
|
|
+ RemoteTSAP_LO= (byte) (RemTSAP & 0x00FF);
|
|
+ }
|
|
+
|
|
+ public int ReadArea(int Area, int DBNumber, int Start, int Amount, int WordLength, byte[] Data)
|
|
+ {
|
|
+ int Address;
|
|
+ int NumElements;
|
|
+ int MaxElements;
|
|
+ int TotElements;
|
|
+ int SizeRequested;
|
|
+ int Length;
|
|
+ int Offset = 0;
|
|
+ byte WordSize = 1;
|
|
+
|
|
+ LastError=0;
|
|
+
|
|
+ // If we are addressing Timers or counters the element size is 2
|
|
+ if ((Area==S7.S7AreaCT) || (Area==S7.S7AreaTM))
|
|
+ WordSize = 2;
|
|
+
|
|
+ MaxElements=(_PDULength-18) / WordSize; // 18 = Reply telegram header
|
|
+ TotElements=Amount;
|
|
+
|
|
+ while ((TotElements>0) && (LastError==0))
|
|
+ {
|
|
+ NumElements=TotElements;
|
|
+ if (NumElements>MaxElements)
|
|
+ NumElements=MaxElements;
|
|
+
|
|
+ SizeRequested = NumElements * WordSize;
|
|
+
|
|
+ // Setup the telegram
|
|
+ System.arraycopy(S7_RW, 0, PDU, 0, Size_RD);
|
|
+ // Set DB Number
|
|
+ PDU[27] = (byte) Area;
|
|
+ // Set Area
|
|
+ if (Area==S7.S7AreaDB)
|
|
+ S7.SetWordAt(PDU,25,DBNumber);
|
|
+
|
|
+ PDU[22] = (byte) WordLength;
|
|
+ // Adjusts Start and word length
|
|
+ if ((WordLength==S7WLBit) || (WordLength==S7WLTimer) || (WordLength==S7WLCounter))
|
|
+ {
|
|
+ Address = Start;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ Address = Start<<3;
|
|
+ }
|
|
+
|
|
+ // Num elements
|
|
+ S7.SetWordAt(PDU,23,NumElements);
|
|
+
|
|
+ // Address into the PLC (only 3 bytes)
|
|
+ PDU[30] = (byte) (Address & 0x0FF);
|
|
+ Address = Address >> 8;
|
|
+ PDU[29] = (byte) (Address & 0x0FF);
|
|
+ Address = Address >> 8;
|
|
+ PDU[28] = (byte) (Address & 0x0FF);
|
|
+
|
|
+ // Transport Size
|
|
+ PDU[32] = 0x04;
|
|
+ if (WordLength==S7WLBit)
|
|
+ {
|
|
+ PDU[32] = 0x03;
|
|
+ }
|
|
+ else if ((WordLength==S7WLTimer) || (WordLength==S7WLCounter))
|
|
+ {
|
|
+ PDU[32] = 0x09;
|
|
+ }
|
|
+
|
|
+ SendPacket(PDU, Size_RD);
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ Length=RecvIsoPacket();
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ if (Length>=25)
|
|
+ {
|
|
+ if ((Length-25==SizeRequested) && (PDU[21]==(byte)0xFF))
|
|
+ {
|
|
+ System.arraycopy(PDU, 25, Data, Offset, SizeRequested);
|
|
+ Offset+=SizeRequested;
|
|
+ }
|
|
+ else
|
|
+ LastError = errS7DataRead;
|
|
+ }
|
|
+ else
|
|
+ LastError = errS7InvalidPDU;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ TotElements -= NumElements;
|
|
+ Start += NumElements*WordSize;
|
|
+ }
|
|
+ return LastError;
|
|
+ }
|
|
+
|
|
+ public int WriteArea(int Area, int DBNumber, int Start, int Amount, int WordLength, byte[] Data)
|
|
+ {
|
|
+ int Address;
|
|
+ int NumElements;
|
|
+ int MaxElements;
|
|
+ int TotElements;
|
|
+ int DataSize;
|
|
+ int IsoSize;
|
|
+ int Length;
|
|
+ int Offset = 0;
|
|
+ byte WordSize = 1;
|
|
+
|
|
+ LastError=0;
|
|
+
|
|
+ // If we are addressing Timers or counters the element size is 2
|
|
+ if ((Area==S7.S7AreaCT) || (Area==S7.S7AreaTM))
|
|
+ WordSize = 2;
|
|
+
|
|
+ MaxElements=(_PDULength-35) / WordSize; // 35 = Reply telegram header
|
|
+ TotElements=Amount;
|
|
+
|
|
+ while ((TotElements>0) && (LastError==0))
|
|
+ {
|
|
+ NumElements=TotElements;
|
|
+ if (NumElements>MaxElements)
|
|
+ NumElements=MaxElements;
|
|
+
|
|
+ DataSize = NumElements * WordSize;
|
|
+ IsoSize = Size_WR + DataSize;
|
|
+
|
|
+ // Setup the telegram
|
|
+ System.arraycopy(S7_RW, 0, PDU, 0, Size_WR);
|
|
+ // Whole telegram Size
|
|
+ S7.SetWordAt(PDU,2,IsoSize);
|
|
+ // Data Length
|
|
+ Length=DataSize+4;
|
|
+ S7.SetWordAt(PDU,15,Length);
|
|
+ // Function
|
|
+ PDU[17]= (byte) 0x05;
|
|
+ // Set DB Number
|
|
+ PDU[27] = (byte) Area;
|
|
+ if (Area==S7.S7AreaDB)
|
|
+ S7.SetWordAt(PDU,25,DBNumber);
|
|
+
|
|
+ PDU[22] = (byte) WordLength;
|
|
+ // Adjusts Start and word length
|
|
+ if ((WordLength==S7WLBit) || (WordLength==S7WLTimer) || (WordLength==S7WLCounter))
|
|
+ {
|
|
+ Address = Start;
|
|
+ Length = DataSize;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ Address = Start<<3;
|
|
+ Length = DataSize<<3;
|
|
+ }
|
|
+
|
|
+ // Num elements
|
|
+ S7.SetWordAt(PDU,23,NumElements);
|
|
+ // Address into the PLC
|
|
+ PDU[30] = (byte) (Address & 0x0FF);
|
|
+ Address = Address >> 8;
|
|
+ PDU[29] = (byte) (Address & 0x0FF);
|
|
+ Address = Address >> 8;
|
|
+ PDU[28] = (byte) (Address & 0x0FF);
|
|
+
|
|
+ // Transport Size
|
|
+ PDU[32] = 0x04;
|
|
+ if (WordLength==S7WLBit)
|
|
+ {
|
|
+ PDU[32] = 0x03;
|
|
+ }
|
|
+ else if ((WordLength==S7WLTimer) || (WordLength==S7WLCounter))
|
|
+ {
|
|
+ PDU[32] = 0x09;
|
|
+ }
|
|
+
|
|
+ // Length
|
|
+ S7.SetWordAt(PDU,33,Length);
|
|
+
|
|
+ // Copies the Data
|
|
+ System.arraycopy(Data, Offset, PDU, 35, DataSize);
|
|
+
|
|
+ SendPacket(PDU, IsoSize);
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ Length=RecvIsoPacket();
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ if (Length==22)
|
|
+ {
|
|
+ if ((S7.GetWordAt(PDU,17)!=0) || (PDU[21]!=(byte)0xFF))
|
|
+ LastError = errS7DataWrite;
|
|
+ }
|
|
+ else
|
|
+ LastError = errS7InvalidPDU;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ Offset+=DataSize;
|
|
+ TotElements -= NumElements;
|
|
+ Start += NumElements*WordSize;
|
|
+ }
|
|
+ return LastError;
|
|
+ }
|
|
+
|
|
+ public int GetAgBlockInfo(int BlockType, int BlockNumber, S7BlockInfo Block)
|
|
+ {
|
|
+ int Length;
|
|
+ LastError=0;
|
|
+ // Block Type
|
|
+ S7_BI[30] = (byte) BlockType;
|
|
+ // Block Number
|
|
+ S7_BI[31]=(byte) ((BlockNumber / 10000)+0x30);
|
|
+ BlockNumber=BlockNumber % 10000;
|
|
+ S7_BI[32]=(byte) ((BlockNumber / 1000)+0x30);
|
|
+ BlockNumber=BlockNumber % 1000;
|
|
+ S7_BI[33]=(byte) ((BlockNumber / 100)+0x30);
|
|
+ BlockNumber=BlockNumber % 100;
|
|
+ S7_BI[34]=(byte) ((BlockNumber / 10)+0x30);
|
|
+ BlockNumber=BlockNumber % 10;
|
|
+ S7_BI[35]=(byte) ((BlockNumber / 1)+0x30);
|
|
+
|
|
+ SendPacket(S7_BI);
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ Length=RecvIsoPacket();
|
|
+ if (Length > 32) // the minimum expected
|
|
+ {
|
|
+ if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF))
|
|
+ {
|
|
+ Block.Update(PDU, 42);
|
|
+ }
|
|
+ else
|
|
+ LastError = errS7FunctionError;
|
|
+ }
|
|
+ else
|
|
+ LastError = errS7InvalidPDU;
|
|
+ }
|
|
+
|
|
+ return LastError;
|
|
+ }
|
|
+ /**
|
|
+ *
|
|
+ * @param DBNumber DB Number
|
|
+ * @param Buffer Destination buffer
|
|
+ * @param SizeRead How many bytes were read
|
|
+ * @return
|
|
+ */
|
|
+ public int DBGet(int DBNumber, byte[] Buffer, IntByRef SizeRead)
|
|
+ {
|
|
+ S7BlockInfo Block = new S7BlockInfo();
|
|
+ // Query the DB Length
|
|
+ LastError = GetAgBlockInfo(S7.Block_DB, DBNumber, Block);
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ int SizeToRead = Block.MC7Size();
|
|
+ // Checks the room
|
|
+ if (SizeToRead<=Buffer.length)
|
|
+ {
|
|
+ LastError=ReadArea(S7.S7AreaDB, DBNumber, 0, SizeToRead, S7WLByte, Buffer);
|
|
+ if (LastError==0)
|
|
+ SizeRead.Value=SizeToRead;
|
|
+ }
|
|
+ else
|
|
+ LastError=errS7BufferTooSmall;
|
|
+ }
|
|
+ return LastError;
|
|
+ }
|
|
+
|
|
+ public int ReadSZL(int ID, int Index, S7Szl SZL)
|
|
+ {
|
|
+ int Length;
|
|
+ int DataSZL;
|
|
+ int Offset = 0;
|
|
+ boolean Done = false;
|
|
+ boolean First = true;
|
|
+ byte Seq_in =0x00;
|
|
+ int Seq_out =0x0000;
|
|
+
|
|
+ LastError=0;
|
|
+ SZL.DataSize=0;
|
|
+ do
|
|
+ {
|
|
+ if (First)
|
|
+ {
|
|
+ S7.SetWordAt(S7_SZL_FIRST, 11, ++Seq_out);
|
|
+ S7.SetWordAt(S7_SZL_FIRST, 29, ID);
|
|
+ S7.SetWordAt(S7_SZL_FIRST, 31, Index);
|
|
+ SendPacket(S7_SZL_FIRST);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ S7.SetWordAt(S7_SZL_NEXT, 11, ++Seq_out);
|
|
+ PDU[24] = (byte)Seq_in;
|
|
+ SendPacket(S7_SZL_NEXT);
|
|
+ }
|
|
+ if (LastError!=0)
|
|
+ return LastError;
|
|
+
|
|
+ Length=RecvIsoPacket();
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ if (First)
|
|
+ {
|
|
+ if (Length > 32) // the minimum expected
|
|
+ {
|
|
+ if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF))
|
|
+ {
|
|
+ // Gets Amount of this slice
|
|
+ DataSZL=S7.GetWordAt(PDU,31)-8; // Skips extra params (ID, Index ...)
|
|
+ Done=PDU[26]==0x00;
|
|
+ Seq_in=(byte)PDU[24]; // Slice sequence
|
|
+
|
|
+ SZL.LENTHDR=S7.GetWordAt(PDU, 37);
|
|
+ SZL.N_DR=S7.GetWordAt(PDU, 39);
|
|
+ SZL.Copy(PDU, 41, Offset, DataSZL);
|
|
+ Offset+=DataSZL;
|
|
+ SZL.DataSize+=DataSZL;
|
|
+ }
|
|
+ else
|
|
+ LastError = errS7FunctionError;
|
|
+ }
|
|
+ else
|
|
+ LastError = errS7InvalidPDU;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if (Length > 32) // the minimum expected
|
|
+ {
|
|
+ if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF))
|
|
+ {
|
|
+ // Gets Amount of this slice
|
|
+ DataSZL=S7.GetWordAt(PDU,31);
|
|
+ Done=PDU[26]==0x00;
|
|
+ Seq_in=(byte)PDU[24]; // Slice sequence
|
|
+ SZL.Copy(PDU, 37, Offset, DataSZL);
|
|
+ Offset+=DataSZL;
|
|
+ SZL.DataSize+=DataSZL;
|
|
+ }
|
|
+ else
|
|
+ LastError = errS7FunctionError;
|
|
+ }
|
|
+ else
|
|
+ LastError = errS7InvalidPDU;
|
|
+ }
|
|
+ }
|
|
+ First=false;
|
|
+ }
|
|
+ while(!Done && (LastError==0));
|
|
+
|
|
+ return LastError;
|
|
+ }
|
|
+
|
|
+ public int GetCpuInfo(S7CpuInfo Info)
|
|
+ {
|
|
+ S7Szl SZL = new S7Szl(1024);
|
|
+
|
|
+ LastError = ReadSZL(0x001C, 0x0000, SZL);
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ Info.Update(SZL.Data, 0);
|
|
+ }
|
|
+ return LastError;
|
|
+ }
|
|
+
|
|
+ public int GetCpInfo(S7CpInfo Info)
|
|
+ {
|
|
+ S7Szl SZL = new S7Szl(1024);
|
|
+
|
|
+ LastError = ReadSZL(0x0131, 0x0001, SZL);
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ Info.Update(SZL.Data, 0);
|
|
+ }
|
|
+ return LastError;
|
|
+ }
|
|
+
|
|
+ public int GetOrderCode(S7OrderCode Code)
|
|
+ {
|
|
+ S7Szl SZL = new S7Szl(1024);
|
|
+
|
|
+ LastError = ReadSZL(0x0011, 0x0000, SZL);
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ Code.Update(SZL.Data, 0, SZL.DataSize);
|
|
+ }
|
|
+ return LastError;
|
|
+ }
|
|
+
|
|
+ public int GetPlcDateTime(Date DateTime)
|
|
+ {
|
|
+ int Length;
|
|
+
|
|
+ LastError = 0;
|
|
+ SendPacket(S7_GET_DT);
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ Length=RecvIsoPacket();
|
|
+ if (Length > 30) // the minimum expected
|
|
+ {
|
|
+ if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF))
|
|
+ {
|
|
+ DateTime=S7.GetDateAt(PDU, 34);
|
|
+ }
|
|
+ else
|
|
+ LastError = errS7FunctionError;
|
|
+ }
|
|
+ else
|
|
+ LastError = errS7InvalidPDU;
|
|
+ }
|
|
+
|
|
+ return LastError;
|
|
+ }
|
|
+
|
|
+ public int SetPlcDateTime(Date DateTime)
|
|
+ {
|
|
+ int Length;
|
|
+
|
|
+ LastError = 0;
|
|
+ S7.SetDateAt(S7_SET_DT, 31, DateTime);
|
|
+
|
|
+ SendPacket(S7_SET_DT);
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ Length=RecvIsoPacket();
|
|
+ if (Length > 30) // the minimum expected
|
|
+ {
|
|
+ if (S7.GetWordAt(PDU,27)!=0)
|
|
+ LastError = errS7FunctionError;
|
|
+ }
|
|
+ else
|
|
+ LastError = errS7InvalidPDU;
|
|
+ }
|
|
+
|
|
+ return LastError;
|
|
+ }
|
|
+
|
|
+ public int SetPlcSystemDateTime()
|
|
+ {
|
|
+ return SetPlcDateTime(new Date());
|
|
+ }
|
|
+
|
|
+ public int PlcStop()
|
|
+ {
|
|
+ int Length;
|
|
+
|
|
+ LastError = 0;
|
|
+ SendPacket(S7_STOP);
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ Length=RecvIsoPacket();
|
|
+ if (Length > 18) // 18 is the minimum expected
|
|
+ {
|
|
+ if (S7.GetWordAt(PDU,17)!=0)
|
|
+ LastError = errS7FunctionError;
|
|
+ }
|
|
+ else
|
|
+ LastError = errS7InvalidPDU;
|
|
+ }
|
|
+ return LastError;
|
|
+ }
|
|
+
|
|
+ public int PlcHotStart()
|
|
+ {
|
|
+ int Length;
|
|
+
|
|
+ LastError = 0;
|
|
+ SendPacket(S7_HOT_START);
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ Length=RecvIsoPacket();
|
|
+ if (Length > 18) // the minimum expected
|
|
+ {
|
|
+ if (S7.GetWordAt(PDU,17)!=0)
|
|
+ LastError = errS7FunctionError;
|
|
+ }
|
|
+ else
|
|
+ LastError = errS7InvalidPDU;
|
|
+ }
|
|
+ return LastError;
|
|
+ }
|
|
+
|
|
+ public int PlcColdStart()
|
|
+ {
|
|
+ int Length;
|
|
+
|
|
+ LastError = 0;
|
|
+ SendPacket(S7_COLD_START);
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ Length=RecvIsoPacket();
|
|
+ if (Length > 18) // the minimum expected
|
|
+ {
|
|
+ if (S7.GetWordAt(PDU,17)!=0)
|
|
+ LastError = errS7FunctionError;
|
|
+ }
|
|
+ else
|
|
+ LastError = errS7InvalidPDU;
|
|
+ }
|
|
+ return LastError;
|
|
+ }
|
|
+
|
|
+ public int GetPlcStatus(IntByRef Status)
|
|
+ {
|
|
+ int Length;
|
|
+
|
|
+ LastError = 0;
|
|
+ SendPacket(S7_GET_STAT);
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ Length=RecvIsoPacket();
|
|
+ if (Length > 30) // the minimum expected
|
|
+ {
|
|
+ if (S7.GetWordAt(PDU,27)==0)
|
|
+ {
|
|
+ switch (PDU[44])
|
|
+ {
|
|
+ case S7.S7CpuStatusUnknown :
|
|
+ case S7.S7CpuStatusRun :
|
|
+ case S7.S7CpuStatusStop : Status.Value=PDU[44];
|
|
+ break;
|
|
+ default :
|
|
+ // Since RUN status is always 0x08 for all CPUs and CPs, STOP status
|
|
+ // sometime can be coded as 0x03 (especially for old cpu...)
|
|
+ Status.Value=S7.S7CpuStatusStop;
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ LastError = errS7FunctionError;
|
|
+ }
|
|
+ else
|
|
+ LastError = errS7InvalidPDU;
|
|
+ }
|
|
+ return LastError;
|
|
+ }
|
|
+
|
|
+ public int SetSessionPassword(String Password)
|
|
+ {
|
|
+ byte[] pwd = {0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20};
|
|
+ int Length;
|
|
+
|
|
+ LastError = 0;
|
|
+ // Adjusts the Password length to 8
|
|
+ if (Password.length()>8)
|
|
+ Password=Password.substring(0, 8);
|
|
+ else
|
|
+ {
|
|
+ while (Password.length()<8)
|
|
+ Password=Password+" ";
|
|
+ }
|
|
+
|
|
+ try {
|
|
+ pwd = Password.getBytes("UTF-8");
|
|
+ } catch (UnsupportedEncodingException ex) {
|
|
+ LastError = errS7InvalidParams;
|
|
+ }
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ // Encodes the password
|
|
+ pwd[0]=(byte) (pwd[0] ^ 0x55);
|
|
+ pwd[1]=(byte) (pwd[1] ^ 0x55);
|
|
+ for (int c = 2; c < 8; c++)
|
|
+ {
|
|
+ pwd[c]=(byte) (pwd[c] ^ 0x55 ^ pwd[c-2]);
|
|
+ }
|
|
+ System.arraycopy(pwd, 0, S7_SET_PWD, 29, 8);
|
|
+ // Sends the telegrem
|
|
+ SendPacket(S7_SET_PWD);
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ Length=RecvIsoPacket();
|
|
+ if (Length > 32) // the minimum expected
|
|
+ {
|
|
+ if (S7.GetWordAt(PDU,27)!=0)
|
|
+ LastError = errS7FunctionError;
|
|
+ }
|
|
+ else
|
|
+ LastError = errS7InvalidPDU;
|
|
+ }
|
|
+ }
|
|
+ return LastError;
|
|
+ }
|
|
+
|
|
+ public int ClearSessionPassword()
|
|
+ {
|
|
+ int Length;
|
|
+
|
|
+ LastError = 0;
|
|
+ SendPacket(S7_CLR_PWD);
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ Length=RecvIsoPacket();
|
|
+ if (Length > 30) // the minimum expected
|
|
+ {
|
|
+ if (S7.GetWordAt(PDU,27)!=0)
|
|
+ LastError = errS7FunctionError;
|
|
+ }
|
|
+ else
|
|
+ LastError = errS7InvalidPDU;
|
|
+ }
|
|
+ return LastError;
|
|
+ }
|
|
+
|
|
+ public int GetProtection(S7Protection Protection)
|
|
+ {
|
|
+ S7Szl SZL = new S7Szl(256);
|
|
+
|
|
+ LastError = ReadSZL(0x0232, 0x0004, SZL);
|
|
+ if (LastError==0)
|
|
+ {
|
|
+ Protection.Update(SZL.Data);
|
|
+ }
|
|
+ return LastError;
|
|
+ }
|
|
+
|
|
+}
|
|
diff U3 S7CpInfo.java S7CpInfo.java
|
|
--- S7CpInfo.java Thu Mar 23 15:34:52 2017
|
|
+++ S7CpInfo.java Tue Aug 08 18:53:37 2017
|
|
@@ -1,41 +1,41 @@
|
|
-/*=============================================================================|
|
|
-| PROJECT Moka7 1.0.2 |
|
|
-|==============================================================================|
|
|
-| Copyright (C) 2013, 2016 Davide Nardella |
|
|
-| All rights reserved. |
|
|
-|==============================================================================|
|
|
-| SNAP7 is free software: you can redistribute it and/or modify |
|
|
-| it under the terms of the Lesser GNU General Public License as published by |
|
|
-| the Free Software Foundation, either version 3 of the License, or under |
|
|
-| EPL Eclipse Public License 1.0. |
|
|
-| |
|
|
-| This means that you have to chose in advance which take before you import |
|
|
-| the library into your project. |
|
|
-| |
|
|
-| SNAP7 is distributed in the hope that it will be useful, |
|
|
-| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you |
|
|
-| decide to adopt. |
|
|
-| |
|
|
-|=============================================================================*/
|
|
-package Moka7;
|
|
-
|
|
-/**
|
|
- *
|
|
- * @author Davide
|
|
- */
|
|
-public class S7CpInfo {
|
|
-
|
|
- public int MaxPduLength;
|
|
- public int MaxConnections;
|
|
- public int MaxMpiRate;
|
|
- public int MaxBusRate;
|
|
-
|
|
- protected void Update(byte[] Src, int Pos)
|
|
- {
|
|
- MaxPduLength = S7.GetShortAt(Src, 2);
|
|
- MaxConnections = S7.GetShortAt(Src, 4);
|
|
- MaxMpiRate = S7.GetDIntAt(Src, 6);
|
|
- MaxBusRate = S7.GetDIntAt(Src, 10);
|
|
- }
|
|
-}
|
|
+/*=============================================================================|
|
|
+| PROJECT Moka7 1.0.2 |
|
|
+|==============================================================================|
|
|
+| Copyright (C) 2013, 2016 Davide Nardella |
|
|
+| All rights reserved. |
|
|
+|==============================================================================|
|
|
+| SNAP7 is free software: you can redistribute it and/or modify |
|
|
+| it under the terms of the Lesser GNU General Public License as published by |
|
|
+| the Free Software Foundation, either version 3 of the License, or under |
|
|
+| EPL Eclipse Public License 1.0. |
|
|
+| |
|
|
+| This means that you have to chose in advance which take before you import |
|
|
+| the library into your project. |
|
|
+| |
|
|
+| SNAP7 is distributed in the hope that it will be useful, |
|
|
+| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you |
|
|
+| decide to adopt. |
|
|
+| |
|
|
+|=============================================================================*/
|
|
+package Moka7;
|
|
+
|
|
+/**
|
|
+ *
|
|
+ * @author Davide Nardella
|
|
+ */
|
|
+public class S7CpInfo {
|
|
+
|
|
+ public int MaxPduLength;
|
|
+ public int MaxConnections;
|
|
+ public int MaxMpiRate;
|
|
+ public int MaxBusRate;
|
|
+
|
|
+ protected void Update(byte[] Src, int Pos)
|
|
+ {
|
|
+ MaxPduLength = S7.GetShortAt(Src, 2);
|
|
+ MaxConnections = S7.GetShortAt(Src, 4);
|
|
+ MaxMpiRate = S7.GetDIntAt(Src, 6);
|
|
+ MaxBusRate = S7.GetDIntAt(Src, 10);
|
|
+ }
|
|
+}
|
|
diff U3 S7CpuInfo.java S7CpuInfo.java
|
|
--- S7CpuInfo.java Thu Mar 23 15:34:52 2017
|
|
+++ S7CpuInfo.java Tue Aug 08 18:53:37 2017
|
|
@@ -1,57 +1,57 @@
|
|
-/*=============================================================================|
|
|
-| PROJECT Moka7 1.0.2 |
|
|
-|==============================================================================|
|
|
-| Copyright (C) 2013, 2016 Davide Nardella |
|
|
-| All rights reserved. |
|
|
-|==============================================================================|
|
|
-| SNAP7 is free software: you can redistribute it and/or modify |
|
|
-| it under the terms of the Lesser GNU General Public License as published by |
|
|
-| the Free Software Foundation, either version 3 of the License, or under |
|
|
-| EPL Eclipse Public License 1.0. |
|
|
-| |
|
|
-| This means that you have to chose in advance which take before you import |
|
|
-| the library into your project. |
|
|
-| |
|
|
-| SNAP7 is distributed in the hope that it will be useful, |
|
|
-| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you |
|
|
-| decide to adopt. |
|
|
-| |
|
|
-|=============================================================================*/
|
|
-package Moka7;
|
|
-
|
|
-/**
|
|
- *
|
|
- * @author Davide
|
|
- */
|
|
-public class S7CpuInfo {
|
|
-
|
|
- private final int BufSize = 256;
|
|
- protected byte[] Buffer = new byte[BufSize];
|
|
-
|
|
- protected void Update(byte[] Src, int Pos)
|
|
- {
|
|
- System.arraycopy(Src, Pos, Buffer, 0, BufSize);
|
|
- }
|
|
-
|
|
- public String ModuleTypeName()
|
|
- {
|
|
- return S7.GetStringAt(Buffer,172,32);
|
|
- }
|
|
- public String SerialNumber()
|
|
- {
|
|
- return S7.GetStringAt(Buffer,138,24);
|
|
- }
|
|
- public String ASName()
|
|
- {
|
|
- return S7.GetStringAt(Buffer,2,24);
|
|
- }
|
|
- public String Copyright()
|
|
- {
|
|
- return S7.GetStringAt(Buffer,104,26);
|
|
- }
|
|
- public String ModuleName()
|
|
- {
|
|
- return S7.GetStringAt(Buffer,36,24);
|
|
- }
|
|
-}
|
|
+/*=============================================================================|
|
|
+| PROJECT Moka7 1.0.2 |
|
|
+|==============================================================================|
|
|
+| Copyright (C) 2013, 2016 Davide Nardella |
|
|
+| All rights reserved. |
|
|
+|==============================================================================|
|
|
+| SNAP7 is free software: you can redistribute it and/or modify |
|
|
+| it under the terms of the Lesser GNU General Public License as published by |
|
|
+| the Free Software Foundation, either version 3 of the License, or under |
|
|
+| EPL Eclipse Public License 1.0. |
|
|
+| |
|
|
+| This means that you have to chose in advance which take before you import |
|
|
+| the library into your project. |
|
|
+| |
|
|
+| SNAP7 is distributed in the hope that it will be useful, |
|
|
+| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you |
|
|
+| decide to adopt. |
|
|
+| |
|
|
+|=============================================================================*/
|
|
+package Moka7;
|
|
+
|
|
+/**
|
|
+ *
|
|
+ * @author Davide Nardella
|
|
+ */
|
|
+public class S7CpuInfo {
|
|
+
|
|
+ private final int BufSize = 256;
|
|
+ protected byte[] Buffer = new byte[BufSize];
|
|
+
|
|
+ protected void Update(byte[] Src, int Pos)
|
|
+ {
|
|
+ System.arraycopy(Src, Pos, Buffer, 0, BufSize);
|
|
+ }
|
|
+
|
|
+ public String ModuleTypeName()
|
|
+ {
|
|
+ return S7.GetStringAt(Buffer,172,32);
|
|
+ }
|
|
+ public String SerialNumber()
|
|
+ {
|
|
+ return S7.GetStringAt(Buffer,138,24);
|
|
+ }
|
|
+ public String ASName()
|
|
+ {
|
|
+ return S7.GetStringAt(Buffer,2,24);
|
|
+ }
|
|
+ public String Copyright()
|
|
+ {
|
|
+ return S7.GetStringAt(Buffer,104,26);
|
|
+ }
|
|
+ public String ModuleName()
|
|
+ {
|
|
+ return S7.GetStringAt(Buffer,36,24);
|
|
+ }
|
|
+}
|
|
diff U3 S7OrderCode.java S7OrderCode.java
|
|
--- S7OrderCode.java Thu Mar 23 15:34:52 2017
|
|
+++ S7OrderCode.java Tue Aug 08 18:53:37 2017
|
|
@@ -1,46 +1,46 @@
|
|
-/*=============================================================================|
|
|
-| PROJECT Moka7 1.0.2 |
|
|
-|==============================================================================|
|
|
-| Copyright (C) 2013, 2016 Davide Nardella |
|
|
-| All rights reserved. |
|
|
-|==============================================================================|
|
|
-| SNAP7 is free software: you can redistribute it and/or modify |
|
|
-| it under the terms of the Lesser GNU General Public License as published by |
|
|
-| the Free Software Foundation, either version 3 of the License, or under |
|
|
-| EPL Eclipse Public License 1.0. |
|
|
-| |
|
|
-| This means that you have to chose in advance which take before you import |
|
|
-| the library into your project. |
|
|
-| |
|
|
-| SNAP7 is distributed in the hope that it will be useful, |
|
|
-| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you |
|
|
-| decide to adopt. |
|
|
-| |
|
|
-|=============================================================================*/
|
|
-package Moka7;
|
|
-
|
|
-/**
|
|
- *
|
|
- * @author Davide
|
|
- */
|
|
-public class S7OrderCode {
|
|
-
|
|
- public int V1;
|
|
- public int V2;
|
|
- public int V3;
|
|
- protected byte[] Buffer = new byte[1024];
|
|
-
|
|
- protected void Update(byte[] Src, int Pos, int Size)
|
|
- {
|
|
- System.arraycopy(Src, Pos, Buffer, 0, Size);
|
|
- V1 = (byte) Src[Size-3];
|
|
- V2 = (byte) Src[Size-2];
|
|
- V3 = (byte) Src[Size-1];
|
|
- }
|
|
-
|
|
- public String Code()
|
|
- {
|
|
- return S7.GetStringAt(Buffer, 2, 20);
|
|
- }
|
|
-}
|
|
+/*=============================================================================|
|
|
+| PROJECT Moka7 1.0.2 |
|
|
+|==============================================================================|
|
|
+| Copyright (C) 2013, 2016 Davide Nardella |
|
|
+| All rights reserved. |
|
|
+|==============================================================================|
|
|
+| SNAP7 is free software: you can redistribute it and/or modify |
|
|
+| it under the terms of the Lesser GNU General Public License as published by |
|
|
+| the Free Software Foundation, either version 3 of the License, or under |
|
|
+| EPL Eclipse Public License 1.0. |
|
|
+| |
|
|
+| This means that you have to chose in advance which take before you import |
|
|
+| the library into your project. |
|
|
+| |
|
|
+| SNAP7 is distributed in the hope that it will be useful, |
|
|
+| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you |
|
|
+| decide to adopt. |
|
|
+| |
|
|
+|=============================================================================*/
|
|
+package Moka7;
|
|
+
|
|
+/**
|
|
+ *
|
|
+ * @author Davide Nardella
|
|
+ */
|
|
+public class S7OrderCode {
|
|
+
|
|
+ public int V1;
|
|
+ public int V2;
|
|
+ public int V3;
|
|
+ protected byte[] Buffer = new byte[1024];
|
|
+
|
|
+ protected void Update(byte[] Src, int Pos, int Size)
|
|
+ {
|
|
+ System.arraycopy(Src, Pos, Buffer, 0, Size);
|
|
+ V1 = (byte) Src[Size-3];
|
|
+ V2 = (byte) Src[Size-2];
|
|
+ V3 = (byte) Src[Size-1];
|
|
+ }
|
|
+
|
|
+ public String Code()
|
|
+ {
|
|
+ return S7.GetStringAt(Buffer, 2, 20);
|
|
+ }
|
|
+}
|
|
diff U3 S7Protection.java S7Protection.java
|
|
--- S7Protection.java Thu Mar 23 15:34:52 2017
|
|
+++ S7Protection.java Tue Aug 08 18:53:37 2017
|
|
@@ -1,38 +1,43 @@
|
|
-/*=============================================================================|
|
|
-| PROJECT Moka7 1.0.2 |
|
|
-|==============================================================================|
|
|
-| Copyright (C) 2013, 2016 Davide Nardella |
|
|
-| All rights reserved. |
|
|
-|==============================================================================|
|
|
-| SNAP7 is free software: you can redistribute it and/or modify |
|
|
-| it under the terms of the Lesser GNU General Public License as published by |
|
|
-| the Free Software Foundation, either version 3 of the License, or under |
|
|
-| EPL Eclipse Public License 1.0. |
|
|
-| |
|
|
-| This means that you have to chose in advance which take before you import |
|
|
-| the library into your project. |
|
|
-| |
|
|
-| SNAP7 is distributed in the hope that it will be useful, |
|
|
-| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you |
|
|
-| decide to adopt. |
|
|
-| |
|
|
-|=============================================================================*/
|
|
-package Moka7;
|
|
-
|
|
-// See §33.19 of "System Software for S7-300/400 System and Standard Functions"
|
|
-public class S7Protection {
|
|
- public int sch_schal;
|
|
- public int sch_par;
|
|
- public int sch_rel;
|
|
- public int bart_sch;
|
|
- public int anl_sch;
|
|
- protected void Update(byte[] Src)
|
|
- {
|
|
- sch_schal = S7.GetWordAt(Src,2);
|
|
- sch_par = S7.GetWordAt(Src,4);
|
|
- sch_rel = S7.GetWordAt(Src,6);
|
|
- bart_sch = S7.GetWordAt(Src,8);
|
|
- anl_sch = S7.GetWordAt(Src,10);
|
|
- }
|
|
-}
|
|
+/*=============================================================================|
|
|
+| PROJECT Moka7 1.0.2 |
|
|
+|==============================================================================|
|
|
+| Copyright (C) 2013, 2016 Davide Nardella |
|
|
+| All rights reserved. |
|
|
+|==============================================================================|
|
|
+| SNAP7 is free software: you can redistribute it and/or modify |
|
|
+| it under the terms of the Lesser GNU General Public License as published by |
|
|
+| the Free Software Foundation, either version 3 of the License, or under |
|
|
+| EPL Eclipse Public License 1.0. |
|
|
+| |
|
|
+| This means that you have to chose in advance which take before you import |
|
|
+| the library into your project. |
|
|
+| |
|
|
+| SNAP7 is distributed in the hope that it will be useful, |
|
|
+| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you |
|
|
+| decide to adopt. |
|
|
+| |
|
|
+|=============================================================================*/
|
|
+package Moka7;
|
|
+
|
|
+/**
|
|
+ *
|
|
+ * @author Davide Nardella
|
|
+ */
|
|
+
|
|
+// See §33.19 of "System Software for S7-300/400 System and Standard Functions"
|
|
+public class S7Protection {
|
|
+ public int sch_schal;
|
|
+ public int sch_par;
|
|
+ public int sch_rel;
|
|
+ public int bart_sch;
|
|
+ public int anl_sch;
|
|
+ protected void Update(byte[] Src)
|
|
+ {
|
|
+ sch_schal = S7.GetWordAt(Src,2);
|
|
+ sch_par = S7.GetWordAt(Src,4);
|
|
+ sch_rel = S7.GetWordAt(Src,6);
|
|
+ bart_sch = S7.GetWordAt(Src,8);
|
|
+ anl_sch = S7.GetWordAt(Src,10);
|
|
+ }
|
|
+}
|
|
diff U3 S7Szl.java S7Szl.java
|
|
--- S7Szl.java Thu Mar 23 15:34:52 2017
|
|
+++ S7Szl.java Tue Aug 08 18:53:37 2017
|
|
@@ -1,42 +1,42 @@
|
|
-/*=============================================================================|
|
|
-| PROJECT Moka7 1.0.2 |
|
|
-|==============================================================================|
|
|
-| Copyright (C) 2013, 2016 Davide Nardella |
|
|
-| All rights reserved. |
|
|
-|==============================================================================|
|
|
-| SNAP7 is free software: you can redistribute it and/or modify |
|
|
-| it under the terms of the Lesser GNU General Public License as published by |
|
|
-| the Free Software Foundation, either version 3 of the License, or under |
|
|
-| EPL Eclipse Public License 1.0. |
|
|
-| |
|
|
-| This means that you have to chose in advance which take before you import |
|
|
-| the library into your project. |
|
|
-| |
|
|
-| SNAP7 is distributed in the hope that it will be useful, |
|
|
-| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you |
|
|
-| decide to adopt. |
|
|
-| |
|
|
-|=============================================================================*/
|
|
-package Moka7;
|
|
-
|
|
-/**
|
|
- *
|
|
- * @author Davide
|
|
- */
|
|
-public class S7Szl {
|
|
-
|
|
- public int LENTHDR;
|
|
- public int N_DR;
|
|
- public int DataSize;
|
|
- public byte Data[];
|
|
-
|
|
- public S7Szl(int BufferSize)
|
|
- {
|
|
- Data = new byte[BufferSize];
|
|
- }
|
|
- protected void Copy(byte[] Src, int SrcPos, int DestPos, int Size)
|
|
- {
|
|
- System.arraycopy(Src, SrcPos, Data, DestPos, Size);
|
|
- }
|
|
-}
|
|
+/*=============================================================================|
|
|
+| PROJECT Moka7 1.0.2 |
|
|
+|==============================================================================|
|
|
+| Copyright (C) 2013, 2016 Davide Nardella |
|
|
+| All rights reserved. |
|
|
+|==============================================================================|
|
|
+| SNAP7 is free software: you can redistribute it and/or modify |
|
|
+| it under the terms of the Lesser GNU General Public License as published by |
|
|
+| the Free Software Foundation, either version 3 of the License, or under |
|
|
+| EPL Eclipse Public License 1.0. |
|
|
+| |
|
|
+| This means that you have to chose in advance which take before you import |
|
|
+| the library into your project. |
|
|
+| |
|
|
+| SNAP7 is distributed in the hope that it will be useful, |
|
|
+| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you |
|
|
+| decide to adopt. |
|
|
+| |
|
|
+|=============================================================================*/
|
|
+package Moka7;
|
|
+
|
|
+/**
|
|
+ *
|
|
+ * @author Davide Nardella
|
|
+ */
|
|
+public class S7Szl {
|
|
+
|
|
+ public int LENTHDR;
|
|
+ public int N_DR;
|
|
+ public int DataSize;
|
|
+ public byte Data[];
|
|
+
|
|
+ public S7Szl(int BufferSize)
|
|
+ {
|
|
+ Data = new byte[BufferSize];
|
|
+ }
|
|
+ protected void Copy(byte[] Src, int SrcPos, int DestPos, int Size)
|
|
+ {
|
|
+ System.arraycopy(Src, SrcPos, Data, DestPos, Size);
|
|
+ }
|
|
+}
|