package javaforce.controls.s7;
/** S7 Data Packet
*
* Reference : snap7.sf.net
*
* @author pquiring
*/
public class S7Packet {
/** Creates a packet to connect at COTP level (connect step1). */
public static byte[] makeConnectPacket1() {
TPKT tpkt = new TPKT();
COTP cotp = new COTP(COTP.type_connect);
byte data[];
int size = tpkt.size() + cotp.size();
data = new byte[size];
int dataoff = 0;
tpkt.write(data, dataoff, (short)size);
dataoff += tpkt.size();
cotp.write(data, dataoff);
return data;
}
/** Creates a packet to connect at S7 level (connect step2). */
public static byte[] makeConnectPacket2() {
TPKT tpkt = new TPKT();
COTP cotp = new COTP(COTP.type_data);
S7Header header = new S7Header();
S7Params params = new S7Params();
byte data[];
params.makeConnect();
int size = tpkt.size() + cotp.size() + header.size() + params.size();
data = new byte[size];
int dataoff = 0;
tpkt.write(data, dataoff, (short)size);
dataoff += tpkt.size();
cotp.write(data, dataoff);
dataoff += cotp.size();
header.write(data, dataoff, (short)params.size(), (short)0);
dataoff += header.size();
params.write(data, dataoff);
return data;
}
/** Creates a packet to read data from S7. */
public static byte[] makeReadPacket(S7Data s7) {
TPKT tpkt = new TPKT();
COTP cotp = new COTP(COTP.type_data);
S7Header header = new S7Header();
S7Params params = new S7Params();
byte data[];
params.makeRead(s7);
int size = tpkt.size() + cotp.size() + header.size() + params.size();
data = new byte[size];
int dataoff = 0;
tpkt.write(data, dataoff, (short)size);
dataoff += tpkt.size();
cotp.write(data, dataoff);
dataoff += cotp.size();
header.write(data, dataoff, (short)params.size(), (short)0);
dataoff += header.size();
params.write(data, dataoff);
return data;
}
/** Creates a packet to read data from S7. */
public static byte[] makeReadPacket(S7Data s7[]) {
TPKT tpkt = new TPKT();
COTP cotp = new COTP(COTP.type_data);
S7Header header = new S7Header();
S7Params params = new S7Params();
byte data[];
params.makeRead(s7);
int size = tpkt.size() + cotp.size() + header.size() + params.size();
data = new byte[size];
int dataoff = 0;
tpkt.write(data, dataoff, (short)size);
dataoff += tpkt.size();
cotp.write(data, dataoff);
dataoff += cotp.size();
header.write(data, dataoff, (short)params.size(), (short)0);
dataoff += header.size();
params.write(data, dataoff);
return data;
}
/** Creates a packet to write data to S7. */
public static byte[] makeWritePacket(S7Data type) {
TPKT tpkt = new TPKT();
COTP cotp = new COTP(COTP.type_data);
S7Header header = new S7Header();
S7Params params = new S7Params();
byte data[];
params.makeWrite(type.block_type, type.block_number, type.data_type, type.offset, type.length, type.data);
int size = tpkt.size() + cotp.size() + header.size() + params.size();
data = new byte[size];
int dataoff = 0;
tpkt.write(data, dataoff, (short)size);
dataoff += tpkt.size();
cotp.write(data, dataoff);
dataoff += cotp.size();
header.write(data, dataoff, (short)(params.size() - 4 - type.length), (short)(4 + type.length));
dataoff += header.size();
params.write(data, dataoff);
return data;
}
/** Decodes S7 Address.
*
* Supports: DB,M,I,Q
*
* Does not support ranges yet.
*/
public static S7Data decodeAddress(String addr) {
//DB##.DB?##[.#]
//M[?]##[.#]
//I[?]##[.#]
//Q[?]##[.#]
S7Data data = new S7Data();
if (addr.startsWith("DB")) {
data.block_type = S7Types.DB;
int idx = addr.indexOf('.');
data.block_number = Short.valueOf(addr.substring(2, idx));
addr = addr.substring(idx+2); //B?##[.#]
} else if (addr.startsWith("M")) {
data.block_type = S7Types.M;
} else if (addr.startsWith("I")) {
data.block_type = S7Types.I;
} else if (addr.startsWith("Q")) {
data.block_type = S7Types.Q;
} else {
return null;
}
data.data_type = S7Types.getType(addr.charAt(1));
short offset;
int idx = addr.indexOf('.');
if (idx == -1) idx = addr.length();
if (data.data_type == 0) {
//no type present (assume bit)
offset = Short.valueOf(addr.substring(1, idx));
data.data_type = S7Types.BIT;
} else {
offset = Short.valueOf(addr.substring(2, idx));
}
data.offset = (short)(offset << 3);
if (data.data_type == S7Types.BIT) {
byte bit = Byte.valueOf(addr.substring(idx+1));
data.offset += bit;
}
data.length = 1; //S7Types.getTypeSize(data.data_type, (short)1);
return data;
}
/** Decodes a packet and returns any data returned. */
public static S7Data decodePacket(byte packet[]) {
try {
S7Data data = new S7Data();
int offset = 0;
TPKT tpkt = new TPKT();
tpkt.read(packet, offset);
offset += tpkt.size();
COTP cotp = new COTP();
cotp.read(packet, offset);
if (cotp.PDU_type == COTP.type_connect) return data;
if (cotp.PDU_type == COTP.type_connect_ack) return data;
offset += cotp.size();
S7Header header = new S7Header();
header.read(packet, offset);
offset += header.size();
S7Params params = new S7Params();
params.read(packet, offset, data);
return data;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/** Decodes a packet and returns any data returned. */
public static S7Data[] decodeMultiPacket(byte packet[], int count) {
try {
S7Data data[] = new S7Data[count];
for(int a=0;a<count;a++) {
data[a] = new S7Data();
}
int offset = 0;
TPKT tpkt = new TPKT();
tpkt.read(packet, offset);
offset += tpkt.size();
COTP cotp = new COTP();
cotp.read(packet, offset);
if (cotp.PDU_type == COTP.type_connect) return data;
if (cotp.PDU_type == COTP.type_connect_ack) return data;
offset += cotp.size();
S7Header header = new S7Header();
header.read(packet, offset);
offset += header.size();
S7Params params = new S7Params();
params.read(packet, offset, data);
return data;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static boolean isPacketComplete(byte packet[]) {
return decodePacket(packet) != null;
}
}