use of org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse 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;
}
use of org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse in project plc4x by apache.
the class Plc4xProtocolLogic method write.
@Override
public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
CompletableFuture<PlcWriteResponse> future = new CompletableFuture<>();
// Prepare the request.
List<Plc4xFieldValueRequest> fields = new ArrayList<>(writeRequest.getNumberOfFields());
for (String fieldName : writeRequest.getFieldNames()) {
final org.apache.plc4x.java.plc4x.field.Plc4xField plc4xField = (org.apache.plc4x.java.plc4x.field.Plc4xField) writeRequest.getField(fieldName);
final Plc4xValueType plc4xValueType = plc4xField.getValueType();
final PlcValue plcValue = writeRequest.getPlcValue(fieldName);
Plc4xFieldValueRequest fieldRequest = new Plc4xFieldValueRequest(new Plc4xField(fieldName, plc4xField.getAddress() + ":" + plc4xField.getPlcDataType()), plc4xValueType, plcValue);
fields.add(fieldRequest);
}
final int requestId = txIdGenerator.getAndIncrement();
Plc4xWriteRequest write = new Plc4xWriteRequest(requestId, connectionId, fields);
// Send the request and await a response.
RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
context.sendRequest(write).expectResponse(Plc4xMessage.class, requestTimeout).onTimeout(future::completeExceptionally).check(p -> p.getRequestId() == requestId).unwrap(plc4xMessage -> (Plc4xWriteResponse) plc4xMessage).check(plc4xReadResponse -> plc4xReadResponse.getConnectionId() == connectionId).handle(plc4xWriteResponse -> {
Map<String, PlcResponseCode> apiResponses = new HashMap<>();
// Create the API response from the incoming message.
for (Plc4xFieldResponse plc4xField : plc4xWriteResponse.getFields()) {
final Plc4xResponseCode plc4xResponseCode = plc4xField.getResponseCode();
final PlcResponseCode apiResponseCode = PlcResponseCode.valueOf(plc4xResponseCode.name());
apiResponses.put(plc4xField.getField().getName(), apiResponseCode);
}
// Send it back to the calling process.
future.complete(new DefaultPlcWriteResponse(writeRequest, apiResponses));
// Finish the request-transaction.
transaction.endRequest();
});
return future;
}
use of org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse 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.spi.messages.DefaultPlcWriteResponse in project plc4x by apache.
the class CANOpenProtocolLogic method writeInternally.
private void writeInternally(DefaultPlcWriteRequest writeRequest, CANOpenSDOField field, CompletableFuture<PlcWriteResponse> response) {
final RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
String fieldName = writeRequest.getFieldNames().iterator().next();
CompletableFuture<PlcResponseCode> callback = new CompletableFuture<>();
callback.whenComplete((code, error) -> {
if (error != null) {
if (error instanceof CANOpenAbortException) {
response.complete(new DefaultPlcWriteResponse(writeRequest, Collections.singletonMap(fieldName, PlcResponseCode.REMOTE_ERROR)));
} else {
response.complete(new DefaultPlcWriteResponse(writeRequest, Collections.singletonMap(fieldName, PlcResponseCode.INTERNAL_ERROR)));
}
transaction.endRequest();
return;
}
response.complete(new DefaultPlcWriteResponse(writeRequest, Collections.singletonMap(fieldName, code)));
transaction.endRequest();
});
PlcValue writeValue = writeRequest.getPlcValues().get(0);
SDODownloadConversation download = new SDODownloadConversation(conversation, field.getNodeId(), field.getAnswerNodeId(), new IndexAddress(field.getIndex(), field.getSubIndex()), writeValue, field.getCanOpenDataType());
transaction.submit(() -> download.execute(callback));
}
use of org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse in project plc4x by apache.
the class S7ProtocolLogic method decodeWriteResponse.
private PlcResponse decodeWriteResponse(S7Message responseMessage, PlcWriteRequest plcWriteRequest) throws PlcProtocolException {
Map<String, PlcResponseCode> responses = new HashMap<>();
short errorClass;
short errorCode;
if (responseMessage instanceof S7MessageResponseData) {
S7MessageResponseData messageResponseData = (S7MessageResponseData) responseMessage;
errorClass = messageResponseData.getErrorClass();
errorCode = messageResponseData.getErrorCode();
} else if (responseMessage instanceof S7MessageResponse) {
S7MessageResponse messageResponse = (S7MessageResponse) responseMessage;
errorClass = messageResponse.getErrorClass();
errorCode = messageResponse.getErrorCode();
} else {
throw new PlcProtocolException("Unsupported message type " + responseMessage.getClass().getName());
}
// If the result contains any form of non-null error code, handle this instead.
if ((errorClass != 0) || (errorCode != 0)) {
// This is usually the case if PUT/GET wasn't enabled on the PLC
if ((errorClass == 129) && (errorCode == 4)) {
logger.warn("Got an error response from the PLC. This particular response code usually indicates " + "that PUT/GET is not enabled on the PLC.");
for (String fieldName : plcWriteRequest.getFieldNames()) {
responses.put(fieldName, PlcResponseCode.ACCESS_DENIED);
}
return new DefaultPlcWriteResponse(plcWriteRequest, responses);
} else {
logger.warn("Got an unknown error response from the PLC. Error Class: {}, Error Code {}. " + "We probably need to implement explicit handling for this, so please file a bug-report " + "on https://issues.apache.org/jira/projects/PLC4X and ideally attach a WireShark dump " + "containing a capture of the communication.", errorClass, errorCode);
for (String fieldName : plcWriteRequest.getFieldNames()) {
responses.put(fieldName, PlcResponseCode.INTERNAL_ERROR);
}
return new DefaultPlcWriteResponse(plcWriteRequest, responses);
}
}
// In all other cases all went well.
S7PayloadWriteVarResponse payload = (S7PayloadWriteVarResponse) responseMessage.getPayload();
// items from the request as this information is not returned by the PLC.
if (plcWriteRequest.getNumberOfFields() != payload.getItems().size()) {
throw new PlcProtocolException("The number of requested items doesn't match the number of returned items");
}
List<S7VarPayloadStatusItem> payloadItems = payload.getItems();
int index = 0;
for (String fieldName : plcWriteRequest.getFieldNames()) {
S7VarPayloadStatusItem payloadItem = payloadItems.get(index);
PlcResponseCode responseCode = decodeResponseCode(payloadItem.getReturnCode());
responses.put(fieldName, responseCode);
index++;
}
return new DefaultPlcWriteResponse(plcWriteRequest, responses);
}
Aggregations