use of org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest in project plc4x by apache.
the class ModbusProtocolLogic 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;
}
use of org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest in project plc4x by apache.
the class S7Optimizer method processWriteRequest.
@Override
protected List<PlcRequest> processWriteRequest(PlcWriteRequest writeRequest, DriverContext driverContext) {
S7DriverContext s7DriverContext = (S7DriverContext) driverContext;
List<PlcRequest> processedRequests = new LinkedList<>();
// This calculates the size of the header for the request and response.
int curRequestSize = EMPTY_WRITE_REQUEST_SIZE;
// An empty response has the same size as an empty request.
int curResponseSize = EMPTY_WRITE_RESPONSE_SIZE;
// List of all items in the current request.
LinkedHashMap<String, FieldValueItem> curFields = new LinkedHashMap<>();
for (String fieldName : writeRequest.getFieldNames()) {
S7Field field = (S7Field) writeRequest.getField(fieldName);
PlcValue value = writeRequest.getPlcValue(fieldName);
int writeRequestItemSize = S7_ADDRESS_ANY_SIZE + 4;
if (field.getDataType() == TransportSize.BOOL) {
writeRequestItemSize += Math.ceil((double) field.getNumberOfElements() / 8);
} else {
writeRequestItemSize += (field.getNumberOfElements() * field.getDataType().getSizeInBytes());
}
// If it's an odd number of bytes, add one to make it even
if (writeRequestItemSize % 2 == 1) {
writeRequestItemSize++;
}
int writeResponseItemSize = 4;
// If adding the item would not exceed the sizes, add it to the current request.
if (((curRequestSize + writeRequestItemSize) <= s7DriverContext.getPduSize()) && ((curResponseSize + writeResponseItemSize) <= s7DriverContext.getPduSize())) {
// Increase the current request sizes.
curRequestSize += writeRequestItemSize;
curResponseSize += writeResponseItemSize;
// Add the item.
} else // If adding them would exceed, start a new request.
{
// Create a new PlcWriteRequest containing the current field item.
processedRequests.add(new DefaultPlcWriteRequest(((DefaultPlcWriteRequest) writeRequest).getWriter(), curFields));
// Reset the size and item lists.
curRequestSize = EMPTY_WRITE_REQUEST_SIZE + writeRequestItemSize;
curResponseSize = EMPTY_WRITE_RESPONSE_SIZE + writeResponseItemSize;
curFields = new LinkedHashMap<>();
// Splitting of huge fields not yet implemented, throw an exception instead.
if (((curRequestSize + writeRequestItemSize) > s7DriverContext.getPduSize()) && ((curResponseSize + writeResponseItemSize) > s7DriverContext.getPduSize())) {
throw new PlcRuntimeException("Field size exceeds maximum payload for one item.");
}
}
curFields.put(fieldName, new FieldValueItem(field, value));
}
// Create a new PlcWriteRequest from the remaining field items.
if (!curFields.isEmpty()) {
processedRequests.add(new DefaultPlcWriteRequest(((DefaultPlcWriteRequest) writeRequest).getWriter(), curFields));
}
return processedRequests;
}
use of org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest in project plc4x by apache.
the class SingleFieldOptimizer method processWriteRequest.
@Override
protected List<PlcRequest> processWriteRequest(PlcWriteRequest writeRequest, DriverContext driverContext) {
if (writeRequest.getNumberOfFields() == 1) {
return Collections.singletonList(writeRequest);
}
List<PlcRequest> subRequests = new ArrayList<>(writeRequest.getNumberOfFields());
for (String fieldName : writeRequest.getFieldNames()) {
PlcField field = writeRequest.getField(fieldName);
PlcValue value = writeRequest.getPlcValue(fieldName);
PlcWriteRequest subRequest = new DefaultPlcWriteRequest(((DefaultPlcWriteRequest) writeRequest).getWriter(), new LinkedHashMap<>(Collections.singletonMap(fieldName, new FieldValueItem(field, value))));
subRequests.add(subRequest);
}
return subRequests;
}
use of org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest in project plc4x by apache.
the class S7ProtocolLogic method write.
@Override
public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
CompletableFuture<PlcWriteResponse> future = new CompletableFuture<>();
DefaultPlcWriteRequest request = (DefaultPlcWriteRequest) writeRequest;
List<S7VarRequestParameterItem> parameterItems = new ArrayList<>(request.getNumberOfFields());
List<S7VarPayloadDataItem> payloadItems = new ArrayList<>(request.getNumberOfFields());
for (String fieldName : request.getFieldNames()) {
final S7Field field = (S7Field) request.getField(fieldName);
final PlcValue plcValue = request.getPlcValue(fieldName);
parameterItems.add(new S7VarRequestParameterItemAddress(encodeS7Address(field)));
payloadItems.add(serializePlcValue(field, plcValue));
}
final int tpduId = tpduGenerator.getAndIncrement();
// If we've reached the max value for a 16 bit transaction identifier, reset back to 1
if (tpduGenerator.get() == 0xFFFF) {
tpduGenerator.set(1);
}
TPKTPacket tpktPacket = new TPKTPacket(new COTPPacketData(null, new S7MessageRequest(tpduId, new S7ParameterWriteVarRequest(parameterItems), new S7PayloadWriteVarRequest(payloadItems, null)), true, (short) tpduId, null));
// Start a new request-transaction (Is ended in the response-handler)
RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
transaction.submit(() -> context.sendRequest(tpktPacket).onTimeout(new TransactionErrorCallback<>(future, transaction)).onError(new TransactionErrorCallback<>(future, transaction)).expectResponse(TPKTPacket.class, REQUEST_TIMEOUT).check(p -> p.getPayload() instanceof COTPPacketData).unwrap(p -> ((COTPPacketData) p.getPayload())).unwrap(COTPPacket::getPayload).check(p -> p.getTpduReference() == tpduId).handle(p -> {
try {
future.complete(((PlcWriteResponse) decodeWriteResponse(p, writeRequest)));
} catch (PlcProtocolException e) {
logger.warn("Error sending 'write' message: '{}'", e.getMessage(), e);
}
// Finish the request-transaction.
transaction.endRequest();
}));
return future;
}
Aggregations