package javaforce.controls.s7; /** * * @author pquiring */ import javaforce.*; public class S7Params { public byte func; public byte[] funcData; //varies based on func //funcs public static final byte READ = 0x04; public static final byte WRITE = 0x05; public static final byte CONNECT = (byte)0xf0; /** Create a packet to setup communications (connect) . */ public void makeConnect() { func = CONNECT; funcData = new byte[7]; funcData[0] = 1; //res funcData[1] = 0; funcData[2] = 1; //max AmQ calling funcData[3] = 1; funcData[4] = 1; //max AmQ called funcData[5] = 1; funcData[6] = (byte)0xe0; //PDU length } /** Create a packet to read single tag. */ public void makeRead(S7Data s7) { func = READ; funcData = new byte[13]; funcData[0] = 1; //count funcData[1] = 0x12; //var def funcData[2] = 10; //length of def funcData[3] = 0x10; //S7ANY funcData[4] = s7.data_type; //INT, BYTE, etc. BE.setuint16(funcData, 5, 1); //length (# of elements) BE.setuint16(funcData, 7, s7.block_number); //DBxx funcData[9] = s7.block_type; //DB, I, Q, etc. //BE.setuint24(data, 9, off); funcData[10] = (byte)((s7.offset & 0xff0000) >> 16); funcData[11] = (byte)((s7.offset & 0xff00) >> 8); funcData[12] = (byte)(s7.offset & 0xff); } /** Create a packet to read multiple tags. */ public void makeRead(S7Data s7s[]) { func = READ; byte cnt = (byte)s7s.length; funcData = new byte[1 + cnt * 12]; funcData[0] = cnt; //count int offset = 1; for(byte a=0;a<cnt;a++) { S7Data s7 = s7s[a]; funcData[offset++] = 0x12; //var def funcData[offset++] = 10; //length of def funcData[offset++] = 0x10; //S7ANY funcData[offset++] = s7.data_type; //INT, BYTE, etc. BE.setuint16(funcData, offset, 1); //length (# of elements) offset += 2; BE.setuint16(funcData, offset, s7.block_number); //DBxx offset += 2; funcData[offset++] = s7.block_type; //DB, I, Q, etc. //BE.setuint24(data, 9, off); funcData[offset++] = (byte)((s7.offset & 0xff0000) >> 16); funcData[offset++] = (byte)((s7.offset & 0xff00) >> 8); funcData[offset++] = (byte)(s7.offset & 0xff); } } //transport types private static final byte TT_UNKNOWN = 0; private static final byte TT_BIT = 3; private static final byte TT_UINT = 4; private static final byte TT_SINT = 5; //6 private static final byte TT_REAL = 7; //8 private static final byte TT_CHAR = 9; private byte getTransportType(byte data_type) { switch (data_type) { case S7Types.BIT: return TT_BIT; case S7Types.BYTE: case S7Types.WORD: case S7Types.DWORD: return TT_UINT; case S7Types.CHAR: return TT_CHAR; case S7Types.INT: case S7Types.DINT: return TT_SINT; case S7Types.REAL: return TT_REAL; default: return TT_UNKNOWN; } } /** Create a packet to write data. */ public void makeWrite(byte block_type, short block_number, byte data_type, int off/*24bit*/, short len, byte data[]) { func = WRITE; funcData = new byte[13 + 4 + data.length]; funcData[0] = 1; //count funcData[1] = 0x12; //var def funcData[2] = 10; //length of def funcData[3] = 0x10; //S7ANY funcData[4] = data_type; //INT, BYTE, etc. BE.setuint16(funcData, 5, 1); //length (# of elements) BE.setuint16(funcData, 7, block_number); //DBxx funcData[9] = block_type; //DB, I, Q, etc. //BE.setuint24(data, 9, off); funcData[10] = (byte)((off & 0xff0000) >> 16); funcData[11] = (byte)((off & 0xff00) >> 8); funcData[12] = (byte)(off & 0xff); funcData[13] = 0x00; //res funcData[14] = getTransportType(data_type); //transport type if (len > 1) len <<= 3; //length in bits BE.setuint16(funcData, 15, len); System.arraycopy(data, 0, funcData, 17, data.length); } /** Returns size of params. */ public int size() { return 1 + funcData.length; } /** Write params to packet. */ public void write(byte data[], int offset) { data[offset++] = func; System.arraycopy(funcData, 0, data, offset, funcData.length); } private boolean isBits(byte transport_type) { switch (transport_type) { case TT_BIT: return true; case TT_UINT: return true; case TT_SINT: return true; case TT_REAL: return false; case TT_CHAR: return false; default: return false; } } /** Reads params from packet and fills in S7Data. */ public boolean read(byte data[], int offset, S7Data out) throws Exception { func = data[offset++]; byte count = data[offset++]; for(int a=0;a<count;a++) { byte success = data[offset++]; if (success != (byte)0xff) { JFLog.log("Error:success=" + success); return false; } if (func == READ) { byte transport_type = data[offset++]; int len = BE.getuint16(data, offset); if (isBits(transport_type)) { len = (len + 7) >> 3; //divide by 8 } offset += 2; if (a == 0) { out.data = new byte[len]; System.arraycopy(data,offset,out.data,0,len); } offset += len; if (len % 2 == 1) { offset++; //fill byte } } } return true; } /** Reads params from packet and fills in S7Data. */ public boolean read(byte data[], int offset, S7Data outs[]) throws Exception { func = data[offset++]; byte count = data[offset++]; for(int a=0;a<count;a++) { S7Data out = outs[a]; byte success = data[offset++]; if (success != (byte)0xff) { JFLog.log("Error:success=" + success); return false; } if (func == READ) { byte transport_type = data[offset++]; int len = BE.getuint16(data, offset); if (isBits(transport_type)) { len = (len + 7) >> 3; //divide by 8 } offset += 2; out.data = new byte[len]; System.arraycopy(data,offset,out.data,0,len); offset += len; if (len % 2 == 1) { offset++; //fill byte } } } return true; } }