use of org.apache.plc4x.java.api.messages.PlcWriteRequest in project plc4x by apache.
the class ModbusAsciiProtocolLogic 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));
ModbusAsciiADU modbusAsciiADU = new ModbusAsciiADU(unitIdentifier, requestPdu, false);
RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
transaction.submit(() -> context.sendRequest(modbusAsciiADU).expectResponse(ModbusAsciiADU.class, requestTimeout).onTimeout(future::completeExceptionally).onError((p, e) -> future.completeExceptionally(e)).unwrap(ModbusAsciiADU::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 Plc4xSinkProcessor method onTrigger.
@Override
public void onTrigger(final ProcessContext context, final ProcessSession session) throws ProcessException {
FlowFile flowFile = session.get();
// Abort if there's nothing to do.
if (flowFile == null) {
return;
}
// Get an instance of a component able to write to a PLC.
try (PlcConnection connection = getDriverManager().getConnection(getConnectionString())) {
if (!connection.getMetadata().canWrite()) {
throw new ProcessException("Writing not supported by connection");
}
// Prepare the request.
PlcWriteRequest.Builder builder = connection.writeRequestBuilder();
flowFile.getAttributes().forEach((field, value) -> {
String address = getAddress(field);
if (address != null) {
// TODO: Convert the String into the right type ...
builder.addItem(field, address, Boolean.valueOf(value));
}
});
PlcWriteRequest writeRequest = builder.build();
// Send the request to the PLC.
try {
final PlcWriteResponse plcWriteResponse = writeRequest.execute().get();
// TODO: Evaluate the response and create flow files for successful and unsuccessful updates
session.transfer(flowFile, SUCCESS);
} catch (Exception e) {
flowFile = session.putAttribute(flowFile, "exception", e.getLocalizedMessage());
session.transfer(flowFile, FAILURE);
}
} catch (ProcessException e) {
throw e;
} catch (Exception e) {
throw new ProcessException("Got an error while trying to get a connection", e);
}
}
use of org.apache.plc4x.java.api.messages.PlcWriteRequest in project plc4x by apache.
the class Plc4xSinkTask method put.
@Override
public void put(Collection<SinkRecord> records) {
if (records.isEmpty()) {
return;
}
PlcConnection connection = null;
try {
connection = driverManager.getConnection(plc4xConnectionString);
} catch (PlcConnectionException e) {
log.warn("Failed to Open Connection {}", plc4xConnectionString);
remainingRetries--;
if (remainingRetries > 0) {
if (context != null) {
context.timeout(plc4xTimeout);
}
throw new RetriableException("Failed to Write to " + plc4xConnectionString + " retrying records that haven't expired");
}
log.warn("Failed to write after {} retries", plc4xRetries);
return;
}
PlcWriteRequest writeRequest;
final PlcWriteRequest.Builder builder = connection.writeRequestBuilder();
int validCount = 0;
for (SinkRecord r : records) {
Struct record = (Struct) r.value();
String topic = r.topic();
Struct plcFields = record.getStruct(Constants.FIELDS_CONFIG);
Schema plcFieldsSchema = plcFields.schema();
for (Field plcField : plcFieldsSchema.fields()) {
String field = plcField.name();
Object value = plcFields.get(field);
if (value != null) {
Long timestamp = record.getInt64("timestamp");
Long expiresOffset = record.getInt64("expires");
Long expires = 0L;
if (expiresOffset != null) {
expires = expiresOffset + timestamp;
}
// Discard records we are not or no longer interested in.
if (!topic.equals(plc4xTopic) || plc4xTopic.equals("")) {
log.debug("Ignoring write request received on wrong topic");
} else if (!fields.containsKey(field)) {
log.warn("Unable to find address for field " + field);
} else if ((System.currentTimeMillis() > expires) & !(expires == 0)) {
log.warn("Write request has expired {} - {}, discarding {}", expires, System.currentTimeMillis(), field);
} else {
String address = fields.get(field);
try {
// If an array value is passed instead of a single value then convert to a String array
if (value instanceof String) {
String sValue = (String) value;
if ((sValue.charAt(0) == '[') && (sValue.charAt(sValue.length() - 1) == ']')) {
String[] values = sValue.substring(1, sValue.length() - 1).split(",");
builder.addItem(address, address, values);
} else {
builder.addItem(address, address, value);
}
} else {
builder.addItem(address, address, value);
}
validCount += 1;
} catch (Exception e) {
// When building a request we want to discard the write if there is an error.
log.warn("Invalid Address format for protocol {}", address);
}
}
}
}
}
if (validCount > 0) {
try {
writeRequest = builder.build();
writeRequest.execute().get();
log.debug("Wrote records to {}", plc4xConnectionString);
} catch (Exception e) {
remainingRetries--;
if (remainingRetries > 0) {
if (context != null) {
context.timeout(plc4xTimeout);
}
try {
connection.close();
} catch (Exception f) {
log.warn("Failed to Close {} on RetriableException", plc4xConnectionString);
}
throw new RetriableException("Failed to Write to " + plc4xConnectionString + " retrying records that haven't expired");
}
log.warn("Failed to write after {} retries", plc4xRetries);
}
}
try {
connection.close();
} catch (Exception e) {
log.warn("Failed to Close {}", plc4xConnectionString);
}
remainingRetries = plc4xRetries;
return;
}
use of org.apache.plc4x.java.api.messages.PlcWriteRequest in project plc4x by apache.
the class Plc4x2AdsProtocol method encode.
@Override
protected void encode(ChannelHandlerContext ctx, PlcRequestContainer<InternalPlcRequest, InternalPlcResponse> msg, List<Object> out) throws Exception {
LOGGER.trace("(<--OUT): {}, {}, {}", ctx, msg, out);
PlcRequest request = msg.getRequest();
if (request instanceof PlcReadRequest) {
encodeReadRequest(msg, out);
} else if (request instanceof PlcWriteRequest) {
encodeWriteRequest(msg, out);
} else if (request instanceof PlcProprietaryRequest) {
encodeProprietaryRequest(msg, out);
} else {
throw new PlcProtocolException("Unknown type " + request.getClass());
}
}
use of org.apache.plc4x.java.api.messages.PlcWriteRequest in project plc4x by apache.
the class OpcuaPlcDriverTest method writeVariables.
@Test
public void writeVariables() throws Exception {
PlcConnection opcuaConnection = new PlcDriverManager().getConnection(tcpConnectionAddress);
assert opcuaConnection.isConnected();
PlcWriteRequest.Builder builder = opcuaConnection.writeRequestBuilder();
builder.addItem("Bool", BOOL_IDENTIFIER_READ_WRITE, true);
builder.addItem("Byte", BYTE_IDENTIFIER_READ_WRITE + ";BYTE", 255);
builder.addItem("Double", DOUBLE_IDENTIFIER_READ_WRITE, 0.5d);
builder.addItem("Float", FLOAT_IDENTIFIER_READ_WRITE, 0.5f);
builder.addItem("Int16", INT16_IDENTIFIER_READ_WRITE + ";INT", 32000);
builder.addItem("Int32", INT32_IDENTIFIER_READ_WRITE, 42);
builder.addItem("Int64", INT64_IDENTIFIER_READ_WRITE, 42L);
builder.addItem("Integer", INTEGER_IDENTIFIER_READ_WRITE, 42);
builder.addItem("SByte", SBYTE_IDENTIFIER_READ_WRITE + ";USINT", 100);
builder.addItem("String", STRING_IDENTIFIER_READ_WRITE, "Helllo Toddy!");
builder.addItem("UInt16", UINT16_IDENTIFIER_READ_WRITE + ";UINT", 65535);
builder.addItem("UInt32", UINT32_IDENTIFIER_READ_WRITE + ";UDINT", 100);
builder.addItem("UInt64", UINT64_IDENTIFIER_READ_WRITE + ";ULINT", new BigInteger("1337"));
builder.addItem("UInteger", UINTEGER_IDENTIFIER_READ_WRITE + ";UDINT", 100);
builder.addItem("DoesNotExists", DOES_NOT_EXIST_IDENTIFIER_READ_WRITE, "Sad Toddy");
PlcWriteRequest request = builder.build();
PlcWriteResponse response = request.execute().get();
assert response.getResponseCode("Bool").equals(PlcResponseCode.OK);
assert response.getResponseCode("Byte").equals(PlcResponseCode.OK);
assert response.getResponseCode("Double").equals(PlcResponseCode.OK);
assert response.getResponseCode("Float").equals(PlcResponseCode.OK);
assert response.getResponseCode("Int16").equals(PlcResponseCode.OK);
assert response.getResponseCode("Int32").equals(PlcResponseCode.OK);
assert response.getResponseCode("Int64").equals(PlcResponseCode.OK);
assert response.getResponseCode("Integer").equals(PlcResponseCode.OK);
assert response.getResponseCode("SByte").equals(PlcResponseCode.OK);
assert response.getResponseCode("String").equals(PlcResponseCode.OK);
assert response.getResponseCode("UInt16").equals(PlcResponseCode.OK);
assert response.getResponseCode("UInt32").equals(PlcResponseCode.OK);
assert response.getResponseCode("UInt64").equals(PlcResponseCode.OK);
assert response.getResponseCode("UInteger").equals(PlcResponseCode.OK);
assert response.getResponseCode("DoesNotExists").equals(PlcResponseCode.NOT_FOUND);
opcuaConnection.close();
assert !opcuaConnection.isConnected();
}
Aggregations