use of org.apache.plc4x.java.api.messages.PlcWriteRequest in project plc4x by apache.
the class Plc4xCommunication method setValue.
public void setValue(String tag, String value, String connectionString) {
PlcConnection connection = null;
try {
connection = driverManager.getConnection(connectionString);
if (connection.isConnected() == false) {
logger.debug("getConnection() returned a connection that isn't connected");
connection.connect();
}
} catch (PlcConnectionException e) {
logger.warn("Failed" + e);
}
if (!connection.getMetadata().canWrite()) {
logger.error("This connection doesn't support writing.");
try {
connection.close();
} catch (Exception e) {
logger.warn("Closing connection failed with error " + e);
}
return;
}
// Create a new read request:
// - Give the single item requested an alias name
final PlcWriteRequest.Builder builder = connection.writeRequestBuilder();
// If an array value is passed instead of a single value then convert to a String array
if ((value.charAt(0) == '[') && (value.charAt(value.length() - 1) == ']')) {
String[] values = value.substring(1, value.length() - 1).split(",");
logger.info("Adding Tag " + Arrays.toString(values));
builder.addItem(tag, tag, values);
} else {
builder.addItem(tag, tag, value);
}
PlcWriteRequest writeRequest = builder.build();
try {
writeRequest.execute().get();
} catch (InterruptedException | ExecutionException e) {
logger.warn("Failed" + e);
}
try {
connection.close();
} catch (Exception e) {
logger.warn("Closing Connection Failed with error " + e);
}
return;
}
use of org.apache.plc4x.java.api.messages.PlcWriteRequest in project plc4x by apache.
the class ModbusRtuProtocolLogic method write.
@Override
public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
CompletableFuture<PlcWriteResponse> future = new CompletableFuture<>();
DefaultPlcWriteRequest request = (DefaultPlcWriteRequest) writeRequest;
// 2. Split up into multiple sub-requests
if (request.getFieldNames().size() == 1) {
String fieldName = request.getFieldNames().iterator().next();
PlcField field = request.getField(fieldName);
final ModbusPDU requestPdu = getWriteRequestPdu(field, writeRequest.getPlcValue(fieldName));
ModbusRtuADU modbusRtuADU = new ModbusRtuADU(unitIdentifier, requestPdu, false);
RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
transaction.submit(() -> context.sendRequest(modbusRtuADU).expectResponse(ModbusRtuADU.class, requestTimeout).onTimeout(future::completeExceptionally).onError((p, e) -> future.completeExceptionally(e)).unwrap(ModbusRtuADU::getPdu).handle(responsePdu -> {
// Try to decode the response data based on the corresponding request.
PlcResponseCode responseCode;
// Check if the response was an error response.
if (responsePdu instanceof ModbusPDUError) {
ModbusPDUError errorResponse = (ModbusPDUError) responsePdu;
responseCode = getErrorCode(errorResponse);
} else {
responseCode = PlcResponseCode.OK;
// TODO: Check the correct number of elements were written.
if (responsePdu instanceof ModbusPDUWriteSingleCoilResponse) {
ModbusPDUWriteSingleCoilResponse response = (ModbusPDUWriteSingleCoilResponse) responsePdu;
ModbusPDUWriteSingleCoilRequest requestSingleCoil = (ModbusPDUWriteSingleCoilRequest) requestPdu;
if (!((response.getValue() == requestSingleCoil.getValue()) && (response.getAddress() == requestSingleCoil.getAddress()))) {
responseCode = PlcResponseCode.REMOTE_ERROR;
}
}
}
// Prepare the response.
PlcWriteResponse response = new DefaultPlcWriteResponse(request, Collections.singletonMap(fieldName, responseCode));
// Pass the response back to the application.
future.complete(response);
// Finish the request-transaction.
transaction.endRequest();
}));
} else {
future.completeExceptionally(new PlcRuntimeException("Modbus only supports single filed requests"));
}
return future;
}
use of org.apache.plc4x.java.api.messages.PlcWriteRequest in project plc4x by apache.
the class Plc4XDf1Protocol method decode.
@Override
protected void decode(ChannelHandlerContext ctx, DF1Symbol msg, List<Object> out) throws Exception {
logger.debug("Received DF1 Command incoming {}", msg);
if (msg instanceof DF1SymbolMessageFrameNAK) {
logger.warn("Received a response NAK, notify all requests");
for (Map.Entry<Integer, PlcRequestContainer> entry : requests.entrySet()) {
entry.getValue().getResponseFuture().complete(new DefaultPlcReadResponse((PlcReadRequest) entry.getValue().getRequest(), Collections.singletonMap("erster", new ResponseItem<>(PlcResponseCode.INTERNAL_ERROR, new PlcDINT(-1)))));
}
return;
} else if (msg instanceof DF1SymbolMessageFrameACK) {
logger.warn("Received a response ACK :D");
return;
}
assert msg instanceof DF1SymbolMessageFrame;
DF1Command command = ((DF1SymbolMessageFrame) msg).getCommand();
int transactionId = command.getTransactionCounter();
if (!requests.containsKey(transactionId)) {
logger.warn("Received a response to unknown transaction id {}", transactionId);
ctx.fireExceptionCaught(new RuntimeException("Received a response to unknown transaction id"));
ctx.close();
return;
}
// As every response has a matching request, get this request based on the tpdu.
PlcRequestContainer requestContainer = requests.remove(transactionId);
PlcRequest request = requestContainer.getRequest();
// Handle the response.
PlcResponse response = null;
if (request instanceof PlcReadRequest) {
/*
Things to do
- check response code (if there is something like that?
- cast the bytes to right datatype
- create Response
*/
// We can do this as we have only one fieldName in DF1
final String fieldName = ((PlcReadRequest) request).getFieldNames().iterator().next();
// TODO can there be another code than ok?
final PlcResponseCode responseCode = PlcResponseCode.OK;
// TODO maybe check for different status bytes
final Df1Field field = (Df1Field) ((PlcReadRequest) request).getField(fieldName);
// Cast byte and create response item
PlcValue responseItem = null;
byte[] data = ((DF1UnprotectedReadResponse) command).getData();
switch(field.getDataType()) {
case BIT:
break;
case INTEGER:
// TODO: type conversion is untested
responseItem = new PlcDINT((int) data[0] + ((int) data[1] << 8));
break;
case FLOAT:
break;
case BIT_STRING:
break;
case ARRAY:
break;
// TODO add all other cases here...
default:
throw new NotImplementedException("The DataType " + field.getDataType() + " is currently not implemented!");
}
response = new DefaultPlcReadResponse(((PlcReadRequest) request), Collections.singletonMap(fieldName, new ResponseItem<>(responseCode, responseItem)));
} else if (request instanceof PlcWriteRequest) {
logger.warn("Writing is currently not implemented but received a write response?!");
ctx.close();
throw new NotImplementedException("This is currently not implemented!");
}
// Confirm the response being handled.
if (response != null) {
requestContainer.getResponseFuture().complete(response);
}
}
use of org.apache.plc4x.java.api.messages.PlcWriteRequest in project plc4x by apache.
the class OpcuaPlcDriverTest method multipleThreads.
/*
Test added to test the syncronized Trnasactionhandler.
The test originally failed one out of every 5 or so.
*/
public void multipleThreads() {
class ReadWorker extends Thread {
private PlcConnection connection;
public ReadWorker(PlcConnection opcuaConnection) {
this.connection = opcuaConnection;
}
@Override
public void run() {
try {
PlcReadRequest.Builder read_builder = connection.readRequestBuilder();
read_builder.addItem("Bool", BOOL_IDENTIFIER_READ_WRITE);
PlcReadRequest read_request = read_builder.build();
for (int i = 0; i < 100; i++) {
PlcReadResponse read_response = read_request.execute().get();
assertThat(read_response.getResponseCode("Bool")).isEqualTo(PlcResponseCode.OK);
}
} catch (ExecutionException executionException) {
executionException.printStackTrace();
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
}
}
class WriteWorker extends Thread {
private PlcConnection connection;
public WriteWorker(PlcConnection opcuaConnection) {
this.connection = opcuaConnection;
}
@Override
public void run() {
try {
PlcWriteRequest.Builder write_builder = connection.writeRequestBuilder();
write_builder.addItem("Bool", BOOL_IDENTIFIER_READ_WRITE, true);
PlcWriteRequest write_request = write_builder.build();
for (int i = 0; i < 100; i++) {
PlcWriteResponse write_response = write_request.execute().get();
assertThat(write_response.getResponseCode("Bool")).isEqualTo(PlcResponseCode.OK);
}
} catch (ExecutionException executionException) {
executionException.printStackTrace();
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
}
}
try {
PlcConnection opcuaConnection = new PlcDriverManager().getConnection(tcpConnectionAddress);
Condition<PlcConnection> is_connected = new Condition<>(PlcConnection::isConnected, "is connected");
assertThat(opcuaConnection).is(is_connected);
ReadWorker read_worker = new ReadWorker(opcuaConnection);
WriteWorker write_worker = new WriteWorker(opcuaConnection);
read_worker.start();
write_worker.start();
read_worker.join();
write_worker.join();
opcuaConnection.close();
assert !opcuaConnection.isConnected();
} catch (Exception e) {
fail("Exception during readVariables Test EXCEPTION: " + e.getMessage());
}
}
use of org.apache.plc4x.java.api.messages.PlcWriteRequest in project plc4x by apache.
the class ModbusTcpProtocolLogic method write.
@Override
public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
CompletableFuture<PlcWriteResponse> future = new CompletableFuture<>();
DefaultPlcWriteRequest request = (DefaultPlcWriteRequest) writeRequest;
// 2. Split up into multiple sub-requests
if (request.getFieldNames().size() == 1) {
String fieldName = request.getFieldNames().iterator().next();
PlcField field = request.getField(fieldName);
final ModbusPDU requestPdu = getWriteRequestPdu(field, writeRequest.getPlcValue(fieldName));
int transactionIdentifier = transactionIdentifierGenerator.getAndIncrement();
// If we've reached the max value for a 16 bit transaction identifier, reset back to 1
if (transactionIdentifierGenerator.get() == 0xFFFF) {
transactionIdentifierGenerator.set(1);
}
ModbusTcpADU modbusTcpADU = new ModbusTcpADU(transactionIdentifier, unitIdentifier, requestPdu, false);
RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
transaction.submit(() -> context.sendRequest(modbusTcpADU).expectResponse(ModbusTcpADU.class, requestTimeout).onTimeout(future::completeExceptionally).onError((p, e) -> future.completeExceptionally(e)).check(p -> p.getTransactionIdentifier() == transactionIdentifier).unwrap(ModbusTcpADU::getPdu).handle(responsePdu -> {
// Try to decode the response data based on the corresponding request.
PlcResponseCode responseCode;
// Check if the response was an error response.
if (responsePdu instanceof ModbusPDUError) {
ModbusPDUError errorResponse = (ModbusPDUError) responsePdu;
responseCode = getErrorCode(errorResponse);
} else {
responseCode = PlcResponseCode.OK;
// TODO: Check the correct number of elements were written.
if (responsePdu instanceof ModbusPDUWriteSingleCoilResponse) {
ModbusPDUWriteSingleCoilResponse response = (ModbusPDUWriteSingleCoilResponse) responsePdu;
ModbusPDUWriteSingleCoilRequest requestSingleCoil = (ModbusPDUWriteSingleCoilRequest) requestPdu;
if (!((response.getValue() == requestSingleCoil.getValue()) && (response.getAddress() == requestSingleCoil.getAddress()))) {
responseCode = PlcResponseCode.REMOTE_ERROR;
}
}
}
// Prepare the response.
PlcWriteResponse response = new DefaultPlcWriteResponse(request, Collections.singletonMap(fieldName, responseCode));
// Pass the response back to the application.
future.complete(response);
// Finish the request-transaction.
transaction.endRequest();
}));
} else {
future.completeExceptionally(new PlcRuntimeException("Modbus only supports single filed requests"));
}
return future;
}
Aggregations