Skip to content

Commit

Permalink
add plc4j s7 driver
Browse files Browse the repository at this point in the history
  • Loading branch information
pquiring committed Jan 6, 2025
1 parent 36b96ce commit 960ee48
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 64 deletions.
3 changes: 3 additions & 0 deletions build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,10 @@
<antcall target="jar-batik-all"/>
<antcall target="jar-xmlgraphics-commons"/>
<antcall target="jar-xml-apis-ext"/>
<antcall target="jar-commons-lang3"/>
<antcall target="jar-plc4j-api"/>
<antcall target="jar-plc4j-spi"/>
<antcall target="jar-plc4j-driver-s7"/>
</target>

<target name="compile" depends="depjars" description="compile the source">
Expand Down
12 changes: 12 additions & 0 deletions get-jars.xml
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,16 @@
<maven name="plc4j-api" path="org/apache/plc4x" version="${plc4j-version}"/>
</target>

<available property="have-plc4j-spi" file="${lib}/plc4j-spi-${plc4j-version}.jar"/>
<target name="get-plc4j-spi" unless="have-plc4j-spi">
<maven name="plc4j-spi" path="org/apache/plc4x" version="${plc4j-version}"/>
</target>

<available property="have-plc4j-driver-s7" file="${lib}/plc4j-driver-s7-${plc4j-version}.jar"/>
<target name="get-plc4j-driver-s7" unless="have-plc4j-driver-s7">
<maven name="plc4j-driver-s7" path="org/apache/plc4x" version="${plc4j-version}"/>
</target>

<target name="getjars">
<!-- depends via antcalls -->
<antcall target="get-twelvemonkeys-common-lang"/>
Expand Down Expand Up @@ -255,5 +265,7 @@
<antcall target="get-xmlgraphics-commons"/>
<antcall target="get-xml-apis-ext"/>
<antcall target="get-plc4j-api"/>
<antcall target="get-plc4j-spi"/>
<antcall target="get-plc4j-driver-s7"/>
</target>
</project>
8 changes: 8 additions & 0 deletions install-jars.xml
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,12 @@
<target name="jar-plc4j-api">
<copyjar name="plc4j-api" version="${plc4j-version}" path="${jarpath}"/>
</target>

<target name="jar-plc4j-spi">
<copyjar name="plc4j-spi" version="${plc4j-version}" path="${jarpath}"/>
</target>

<target name="jar-plc4j-driver-s7">
<copyjar name="plc4j-driver-s7" version="${plc4j-version}" path="${jarpath}"/>
</target>
</project>
118 changes: 97 additions & 21 deletions src/javaforce/controls/Controller.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.*;

import javaforce.*;
import javaforce.controls.s7.*;
Expand All @@ -21,13 +22,20 @@
import javaforce.media.*;

import org.apache.plc4x.java.api.*;
import org.apache.plc4x.java.api.messages.*;
import org.apache.plc4x.java.api.model.*;
import org.apache.plc4x.java.api.types.*;
import org.apache.plc4x.java.api.value.*;

public class Controller {
private boolean connected;
private Socket socket;
private InputStream is;
private OutputStream os;
private int plc;
private PlcConnection plcConn;
private PlcDriver plcDrv;
private int plcType;
private int plcSubType;
private DAQmx daq;
private Object lock = new Object(); //read/write lock
private static Object s7_connect_lock = new Object();
Expand Down Expand Up @@ -56,15 +64,13 @@ public void setTimeout(int ms) {
timeout = ms;
}

/** Connects to a PLC. */

/*
/** Connects to a PLC.
*
* url = "S7:host"
* url = "MODBUS:host"
* url = "AB:host"
* url = "NI:device/options"
* url = "MIC:name" (int16 data type , <default> will use default mic)
* url = "S7://host"
* url = "MODBUS://host"
* url = "AB://host"
* url = "NI://device/options"
* url = "MIC://name" (int16 data type , %lt;default%gt; will use default mic)
*
*/
public boolean connect(String url) {
Expand All @@ -74,8 +80,26 @@ public boolean connect(String url) {
JFLog.log("Controller:connect():url == null");
return false;
}
if (url.contains("://")) {
//Apache PLC4J
plcType = ControllerType.PLC4J;
int idx = url.indexOf(':');
String driver = url.substring(0, idx).toUpperCase();
switch (driver) {
case "S7": plcSubType = ControllerType.S7; break;
case "AB": plcSubType = ControllerType.AB; break;
}
try {
plcConn = PlcDriverManager.getDefault().getConnectionManager().getConnection(url);
plcDrv = PlcDriverManager.getDefault().getDriver(driver);
return true;
} catch (Exception e) {
JFLog.log(e);
return false;
}
}
if (url.startsWith("S7:")) {
plc = ControllerType.S7;
plcType = ControllerType.S7;
String host = url.substring(3);
synchronized(s7_connect_lock) {
try {
Expand Down Expand Up @@ -121,7 +145,7 @@ public boolean connect(String url) {
return true;
}
if (url.startsWith("MODBUS:")) {
plc = ControllerType.MB;
plcType = ControllerType.MB;
String host = url.substring(7);
try {
connect(host, 502);
Expand All @@ -137,7 +161,7 @@ public boolean connect(String url) {
}
if (url.startsWith("AB:")) {
ab_context = new ABContext();
plc = ControllerType.AB;
plcType = ControllerType.AB;
String host = url.substring(3);
try {
connect(host, 44818);
Expand Down Expand Up @@ -170,7 +194,7 @@ public boolean connect(String url) {
return true;
}
if (url.startsWith("NI:")) {
plc = ControllerType.NI;
plcType = ControllerType.NI;
daq = new DAQmx();
connected = daq.connect(url.substring(3));
if (!connected) {
Expand All @@ -180,7 +204,7 @@ public boolean connect(String url) {
return connected;
}
if (url.startsWith("MIC:")) {
plc = ControllerType.MIC;
plcType = ControllerType.MIC;
mic = new AudioInput();
micBufferSize = (int)(44100.0 / (1000.0 / rate));
micBuffer = new short[micBufferSize];
Expand Down Expand Up @@ -217,7 +241,7 @@ public void setSOCKS(String host) {
/** Disconnects from PLC. */
public boolean disconnect() {
if (!connected) return false;
switch (plc) {
switch (plcType) {
case ControllerType.S7:
case ControllerType.MB:
case ControllerType.AB:
Expand Down Expand Up @@ -288,7 +312,7 @@ public boolean write(String addr, byte[] data, datatype type) {
addr = addr.toUpperCase();
synchronized(lock) {
if (!connected) return false;
switch (plc) {
switch (plcType) {
case ControllerType.S7: {
S7Data s7 = S7Packet.decodeAddress(addr);
if (s7.data_type == S7Types.BIT) {
Expand Down Expand Up @@ -428,7 +452,27 @@ public byte[] read(String addr) {
addr = addr.toUpperCase();
synchronized(lock) {
if (!connected) return null;
switch (plc) {
switch (plcType) {
case ControllerType.PLC4J:
try {
PlcReadRequest.Builder reader = plcConn.readRequestBuilder();
switch (plcSubType) {
case ControllerType.S7: if (!addr.startsWith("%")) addr = "%" + addr; break;
}
//why is plcConn.parseTagAddress() @deprecated ?
PlcTag plcTag = plcDrv.prepareTag(addr);
reader.addTag("tag0", plcTag);
PlcReadResponse data = reader.build().execute().get(5000, TimeUnit.MILLISECONDS);
PlcValue value = data.getPlcValue("tag0");
if (value != null) {
return value.getRaw();
} else {
return empty;
}
} catch (Exception e) {
JFLog.log(e);
}
break;
case ControllerType.S7: {
S7Data s7 = S7Packet.decodeAddress(addr);
if (s7 == null) return null;
Expand Down Expand Up @@ -545,13 +589,45 @@ public byte[] read(String addr) {
}
}

private static byte[] empty = new byte[0];

/** Reads multiple data tags from PLC. (only S7 is currently supported) */
public byte[][] read(String[] addr) {
if (!connected) return null;
for(int a=0;a<addr.length;a++) {
addr[a] = addr[a].toUpperCase();
}
switch (plc) {
switch (plcType) {
case ControllerType.PLC4J:
try {
PlcReadRequest.Builder reader = plcConn.readRequestBuilder();
int idx = 0;
for(String tag : addr) {
switch (plcSubType) {
case ControllerType.S7: if (!tag.startsWith("%")) tag = "%" + tag; break;
}
//why is plcConn.parseTagAddress() @deprecated ?
PlcTag plcTag = plcDrv.prepareTag(tag);
reader.addTag("tag" + idx, plcTag);
idx++;
}
PlcReadResponse data = reader.build().execute().get(5000, TimeUnit.MILLISECONDS);
byte[][] ret = new byte[addr.length][];
idx = 0;
for(String tag : data.getTagNames()) {
PlcValue value = data.getPlcValue("tag" + idx);
if (value != null) {
ret[idx] = value.getRaw();
} else {
ret[idx] = empty;
}
idx++;
}
return ret;
} catch (Exception e) {
JFLog.log(e);
}
break;
case ControllerType.S7: {
S7Data[] s7 = new S7Data[addr.length];
for(int a=0;a<addr.length;a++) {
Expand Down Expand Up @@ -667,9 +743,9 @@ public byte[][] read(String[] addr) {
}

public boolean isConnected() {
if (plc == 0) return false;
if (plcType == 0) return false;
try {
switch (plc) {
switch (plcType) {
case ControllerType.S7:
case ControllerType.AB:
case ControllerType.MB:
Expand All @@ -688,7 +764,7 @@ public boolean isConnected() {

/** Returns true is controller is Big Endian byte order. */
public boolean isBE() {
switch (plc) {
switch (plcType) {
case ControllerType.JF: return false;
case ControllerType.S7: return true;
case ControllerType.AB: return false;
Expand Down
1 change: 1 addition & 0 deletions src/javaforce/controls/ControllerType.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ public class ControllerType {
public static final int MB = 4;
public static final int NI = 5;
public static final int MIC = 6;
public static final int PLC4J = 7;
}
36 changes: 21 additions & 15 deletions src/javaforce/controls/ReadTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,34 @@
* @author pquiring
*/

import javaforce.*;

public class ReadTag {
public static void main(String[] args) {
if (args.length != 2) {
System.out.println("Usage: ReadTag HOST TAG");
System.out.println(" Host: S7:IP AB:IP MODBUS:IP NI:device/opts etc.");
return;
}
String url = args[0];
String tag = args[1];
Controller c = new Controller();
if (!c.connect(url)) {
System.out.println("Connection failed");
return;
}
byte[] data = c.read(tag);
if (data == null) {
System.out.println("read failed");
return;
}
System.out.println("Size:" + data.length);
for(int a=0;a<data.length;a++) {
System.out.print(String.format("%02d,", data[a] & 0xff));
try {
String url = args[0];
String tag = args[1];
Controller c = new Controller();
if (!c.connect(url)) {
System.out.println("Connection failed");
return;
}
byte[] data = c.read(tag);
if (data == null) {
System.out.println("read failed");
return;
}
System.out.println("Size:" + data.length);
for(int a=0;a<data.length;a++) {
System.out.print(String.format("%02d,", data[a] & 0xff));
}
} catch (Throwable t) {
JFLog.log(t);
}
}
}
Loading

0 comments on commit 960ee48

Please sign in to comment.