PLC4X 0.6 + ADS with an extra work to read symbol table.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/python3 | |
import pyads | |
from pyads import * | |
SENDER_AMS = '192.168.2.106.1.1' | |
PLC_IP = '192.168.2.221' | |
USERNAME = 'Administrator' | |
PASSWORD = '1' | |
ROUTE_NAME = 'RouteToMyPC' | |
HOSTNAME = '192.168.2.106' | |
PLC_AMS_ID = '192.168.2.221.1.1' | |
add_route_to_plc(SENDER_AMS, HOSTNAME, PLC_IP, USERNAME, PASSWORD, route_name=ROUTE_NAME) | |
with AdsDevice(amsTarget="192.168.2.221.1.1:801", amsSource='192.168.2.106.1.1:32455', targetIP="192.168.2.221") as device: | |
info = device.ReadDeviceInfo() | |
print(info) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.nio.ByteBuffer; | |
import java.nio.ByteOrder; | |
import java.nio.charset.StandardCharsets; | |
import java.util.Arrays; | |
import java.util.List; | |
import java.util.concurrent.CompletableFuture; | |
import org.apache.commons.codec.binary.Hex; | |
import org.apache.plc4x.java.PlcDriverManager; | |
import org.apache.plc4x.java.api.PlcConnection; | |
import org.apache.plc4x.java.api.messages.PlcReadRequest; | |
import org.apache.plc4x.java.api.messages.PlcReadResponse; | |
import org.apache.plc4x.java.api.messages.PlcSubscriptionResponse; | |
import org.apache.plc4x.java.api.messages.PlcWriteRequest; | |
import org.apache.plc4x.java.api.messages.PlcWriteResponse; | |
import org.apache.plc4x.java.api.model.PlcSubscriptionHandle; | |
import org.apache.plc4x.java.api.types.PlcResponseCode; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
public class Main { | |
private static Logger logger = LoggerFactory.getLogger(Main.class); | |
public static void main(String[] args) throws Exception { | |
List<String> addresses = Arrays.asList("MAIN.PLCBoolVar:BOOL"); | |
String targetIp = "10.10.10.246"; | |
//String targetIp = "192.168.2.221"; | |
String targetAmsId = "192.168.2.221.1.1"; | |
String targetAmsPort = "851"; | |
// host ip address | |
String sourceAmsId = "192.168.2.106.1.1"; | |
String sourceAmsPort = "30000"; | |
String connectionString = "ads:tcp://" + targetIp + "/" + targetAmsId + ":" + targetAmsPort + "/" + sourceAmsId + ":" + sourceAmsPort; | |
// Establish a connection to the plc using the url provided as first argument | |
try (PlcConnection plcConnection = new PlcDriverManager().getConnection(connectionString)) { | |
System.err.println(plcConnection.getMetadata()); | |
// // Check if this connection support reading of data. | |
// if (!plcConnection.getMetadata().canRead()) { | |
// logger.error("This connection doesn't support reading."); | |
// return; | |
// } | |
// | |
// PlcSubscriptionRequest subscriptionRequest = plcConnection.subscriptionRequestBuilder() | |
// .addChangeOfStateField("Input 001", "0xF021/0x0:BOOL").build(); | |
// | |
// CompletableFuture<? extends PlcSubscriptionResponse> completableFuture = subscriptionRequest.execute(); | |
// completableFuture.handleAsync((response, error) -> { | |
// if (error != null) { | |
// error.printStackTrace(); | |
// return null; | |
// } | |
// | |
// for (PlcSubscriptionHandle handle : response.getSubscriptionHandles()) { | |
// System.out.println("Register event listener " + handle); | |
// handle.register(new Consumer<PlcSubscriptionEvent>() { | |
// @Override public void accept(PlcSubscriptionEvent plcSubscriptionEvent) { | |
// System.out.println("Zmiana stanu " + plcSubscriptionEvent.getFieldNames()); | |
// } | |
// }); | |
// } | |
// return true; | |
// }); | |
PlcReadRequest.Builder readRequestBuilder = plcConnection.readRequestBuilder(); | |
for (String address : addresses) { | |
readRequestBuilder.addItem(address, address).build(); | |
} | |
CompletableFuture<? extends PlcReadResponse> response = readRequestBuilder.build().execute(); | |
PlcReadResponse readResponse = response.get(); | |
printResponse(readResponse); | |
String firstInput = addresses.get(0); | |
Boolean state = readResponse.getBoolean(firstInput); | |
state = state != true; | |
System.out.println("Set input state to " + state); | |
PlcWriteRequest.Builder writeRequestBuilder = plcConnection.writeRequestBuilder(); | |
writeRequestBuilder.addItem(firstInput, firstInput, state).build(); | |
CompletableFuture<? extends PlcWriteResponse> writeResponse = writeRequestBuilder.build().execute(); | |
//printWriteResponse(writeResponse.get()); | |
response = readRequestBuilder.build().execute(); | |
readResponse = response.get(); | |
printResponse(readResponse); | |
// read symbols | |
System.err.println("Reading symbol info"); | |
readRequestBuilder = plcConnection.readRequestBuilder(); | |
PlcReadRequest request = readRequestBuilder.addItem("symbol", "0xf00f/0x0:BYTE[30]").build(); | |
PlcReadResponse rsp = request.execute().get(); | |
ByteBuffer buffer = toBuffer(rsp, "symbol"); | |
System.err.println(Hex.encodeHexString(buffer.array())); | |
int symbolAnswerSize = buffer.getInt(4); | |
System.err.println("Len " + symbolAnswerSize); | |
request = plcConnection.readRequestBuilder().addItem("symbol", "0xf00b/0x0:BYTE[" + symbolAnswerSize + "]").build(); | |
readResponse = request.execute().get(); | |
buffer = toBuffer(readResponse, "symbol"); | |
//System.err.println(Hex.encodeHex(buffer)); | |
int index = 0; | |
int pos = 0; | |
while (buffer.remaining() > 0) { | |
int sectionLen = buffer.getInt(); | |
System.err.println("Symbol " + index++ + ", data length: " + sectionLen + " " + buffer.position()); | |
System.err.println("Index Group " + buffer.getInt()); | |
System.err.println("Index Offset " + buffer.getInt()); | |
System.err.println("Symbol size " + buffer.getInt()); | |
System.err.println("Symbol type " + buffer.getInt()); | |
System.err.println("Symbol ??? " + buffer.getInt()); | |
short nameLength = (short) (buffer.getShort() + 1); | |
short typeLength = (short) (buffer.getShort() + 1); | |
short commentLength = (short) (buffer.getShort() + 1); | |
System.err.println("Name length " + nameLength); | |
System.err.println("Type length " + typeLength); | |
System.err.println("Comment length " + commentLength); | |
System.err.println("Name " + slice(buffer, nameLength)); | |
System.err.println("Type " + slice(buffer, typeLength)); | |
System.err.println("Comment " + slice(buffer, commentLength)); | |
pos += sectionLen; | |
buffer.position(pos); | |
//break; | |
System.err.println("==="); | |
} | |
} | |
} | |
private static String slice(ByteBuffer buffer, short length) { | |
byte[] arr = new byte[length]; | |
buffer.get(arr); | |
return new String(arr, StandardCharsets.UTF_8); | |
} | |
private static ByteBuffer toBuffer(PlcReadResponse rsp, String fieldName) { | |
System.err.println(rsp.getFieldNames() + " " + rsp.getField(fieldName) + " " + rsp.getResponseCode(fieldName)); | |
List<Short> symbols = (List<Short>) rsp.getObject(fieldName); | |
ByteBuffer buffer = ByteBuffer.allocate(symbols.size()).order(ByteOrder.LITTLE_ENDIAN); | |
for (Short symbol : symbols) { | |
byte byteValue = symbol.byteValue(); | |
//System.err.println("data " + Hex.encodeHexString(new byte[] {byteValue})); | |
buffer.put(byteValue); | |
} | |
buffer.rewind(); | |
return buffer; | |
} | |
private static void printResponse(PlcSubscriptionResponse plcSubscriptionResponse) { | |
for (PlcSubscriptionHandle subscriptionHandle : plcSubscriptionResponse.getSubscriptionHandles()) { | |
subscriptionHandle.register(e -> { | |
System.out.println(e); | |
}); | |
} | |
} | |
private static void printResponse(PlcReadResponse response) { | |
System.out.println("Read response"); | |
for (String fieldName : response.getFieldNames()) { | |
if (response.getResponseCode(fieldName) == PlcResponseCode.OK) { | |
int numValues = response.getNumberOfValues(fieldName); | |
// If it's just one element, output just one single line. | |
if (numValues == 1) { | |
System.out.println("Value[" + fieldName + "]: " + response.getObject(fieldName)); | |
} | |
// If it's more than one element, output each in a single row. | |
else { | |
System.out.println("Value[" + fieldName + "]:"); | |
for (int i = 0; i < numValues; i++) { | |
System.out.println(" - " + response.getObject(fieldName, i)); | |
} | |
} | |
} | |
// Something went wrong, to output an error message instead. | |
else { | |
System.out.println("Error[" + fieldName + "]: " + response.getResponseCode(fieldName).name()); | |
} | |
} | |
} | |
private static void printWriteResponse(PlcWriteResponse response) { | |
System.out.println("Write response"); | |
for (String fieldName : response.getFieldNames()) { | |
System.out.println(fieldName + " " + response.getResponseCode(fieldName)); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment