use of org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse in project plc4x by apache.
the class AbEthProtocolLogic method decodeReadResponse.
private PlcResponse decodeReadResponse(CIPEncapsulationReadResponse plcReadResponse, PlcReadRequest plcReadRequest) {
Map<String, ResponseItem<PlcValue>> values = new HashMap<>();
for (String fieldName : plcReadRequest.getFieldNames()) {
AbEthField field = (AbEthField) plcReadRequest.getField(fieldName);
PlcResponseCode responseCode = decodeResponseCode(plcReadResponse.getResponse().getStatus());
PlcValue plcValue = null;
if (responseCode == PlcResponseCode.OK) {
try {
switch(field.getFileType()) {
case // output as single bytes
INTEGER:
if (plcReadResponse.getResponse() instanceof DF1CommandResponseMessageProtectedTypedLogicalRead) {
DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
List<Short> data = df1PTLR.getData();
if (data.size() == 1) {
plcValue = new PlcINT(data.get(0));
} else {
plcValue = IEC61131ValueHandler.of(data);
}
}
break;
case WORD:
if (plcReadResponse.getResponse() instanceof DF1CommandResponseMessageProtectedTypedLogicalRead) {
DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
List<Short> data = df1PTLR.getData();
if (((data.get(1) >> 7) & 1) == 0) {
// positive number
plcValue = IEC61131ValueHandler.of((data.get(1) << 8) + data.get(0));
} else {
// negative number
plcValue = IEC61131ValueHandler.of((((~data.get(1) & 0b01111111) << 8) + (~(data.get(0) - 1) & 0b11111111)) * -1);
}
}
break;
case DWORD:
if (plcReadResponse.getResponse() instanceof DF1CommandResponseMessageProtectedTypedLogicalRead) {
DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
List<Short> data = df1PTLR.getData();
if (((data.get(3) >> 7) & 1) == 0) {
// positive number
plcValue = IEC61131ValueHandler.of((data.get(3) << 24) + (data.get(2) << 16) + (data.get(1) << 8) + data.get(0));
} else {
// negative number
plcValue = IEC61131ValueHandler.of((((~data.get(3) & 0b01111111) << 24) + ((~(data.get(2) - 1) & 0b11111111) << 16) + ((~(data.get(1) - 1) & 0b11111111) << 8) + (~(data.get(0) - 1) & 0b11111111)) * -1);
}
}
break;
case SINGLEBIT:
if (plcReadResponse.getResponse() instanceof DF1CommandResponseMessageProtectedTypedLogicalRead) {
DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
List<Short> data = df1PTLR.getData();
if (field.getBitNumber() < 8) {
// read from first byte
plcValue = IEC61131ValueHandler.of((data.get(0) & (1 << field.getBitNumber())) != 0);
} else {
// read from second byte
plcValue = IEC61131ValueHandler.of((data.get(1) & (1 << (field.getBitNumber() - 8))) != 0);
}
}
break;
default:
logger.warn("Problem during decoding of field {}: Decoding of file type not implemented; " + "FieldInformation: {}", fieldName, field);
}
} catch (Exception e) {
logger.warn("Some other error occurred casting field {}, FieldInformation: {}", fieldName, field, e);
}
}
ResponseItem<PlcValue> result = new ResponseItem<>(responseCode, plcValue);
values.put(fieldName, result);
}
// TODO: Double check if it's really a InternalPlcReadRequest ...
return new DefaultPlcReadResponse(plcReadRequest, values);
}
use of org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse in project plc4x by apache.
the class CANOpenProtocolLogic method readInternally.
private void readInternally(PlcReadRequest readRequest, CANOpenSDOField field, CompletableFuture<PlcReadResponse> response) {
String fieldName = readRequest.getFieldNames().iterator().next();
final RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
CompletableFuture<PlcValue> callback = new CompletableFuture<>();
callback.whenComplete((value, error) -> {
if (error != null) {
Map<String, ResponseItem<PlcValue>> fields = new HashMap<>();
if (error instanceof CANOpenAbortException) {
fields.put(fieldName, new ResponseItem<>(PlcResponseCode.REMOTE_ERROR, new PlcLINT(((CANOpenAbortException) error).getAbortCode())));
} else {
fields.put(fieldName, new ResponseItem<>(PlcResponseCode.REMOTE_ERROR, null));
}
response.complete(new DefaultPlcReadResponse(readRequest, fields));
transaction.endRequest();
return;
}
Map<String, ResponseItem<PlcValue>> fields = new HashMap<>();
fields.put(fieldName, new ResponseItem<>(PlcResponseCode.OK, value));
response.complete(new DefaultPlcReadResponse(readRequest, fields));
transaction.endRequest();
});
SDOUploadConversation upload = new SDOUploadConversation(conversation, field.getNodeId(), field.getAnswerNodeId(), new IndexAddress(field.getIndex(), field.getSubIndex()), field.getCanOpenDataType());
transaction.submit(() -> upload.execute(callback));
}
use of org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse in project plc4x by apache.
the class S7ProtocolLogic method decodeReadResponse.
private PlcResponse decodeReadResponse(S7Message responseMessage, PlcReadRequest plcReadRequest) throws PlcProtocolException {
Map<String, ResponseItem<PlcValue>> values = 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 : plcReadRequest.getFieldNames()) {
ResponseItem<PlcValue> result = new ResponseItem<>(PlcResponseCode.ACCESS_DENIED, new PlcNull());
values.put(fieldName, result);
}
return new DefaultPlcReadResponse(plcReadRequest, values);
} 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 : plcReadRequest.getFieldNames()) {
ResponseItem<PlcValue> result = new ResponseItem<>(PlcResponseCode.INTERNAL_ERROR, new PlcNull());
values.put(fieldName, result);
}
return new DefaultPlcReadResponse(plcReadRequest, values);
}
}
// In all other cases all went well.
S7PayloadReadVarResponse payload = (S7PayloadReadVarResponse) responseMessage.getPayload();
// items from the request as this information is not returned by the PLC.
if (plcReadRequest.getNumberOfFields() != payload.getItems().size()) {
throw new PlcProtocolException("The number of requested items doesn't match the number of returned items");
}
List<S7VarPayloadDataItem> payloadItems = payload.getItems();
int index = 0;
for (String fieldName : plcReadRequest.getFieldNames()) {
S7Field field = (S7Field) plcReadRequest.getField(fieldName);
S7VarPayloadDataItem payloadItem = payloadItems.get(index);
PlcResponseCode responseCode = decodeResponseCode(payloadItem.getReturnCode());
PlcValue plcValue = null;
ByteBuf data = Unpooled.wrappedBuffer(payloadItem.getData());
if (responseCode == PlcResponseCode.OK) {
try {
plcValue = parsePlcValue(field, data);
} catch (Exception e) {
throw new PlcProtocolException("Error decoding PlcValue", e);
}
}
ResponseItem<PlcValue> result = new ResponseItem<>(responseCode, plcValue);
values.put(fieldName, result);
index++;
}
return new DefaultPlcReadResponse(plcReadRequest, values);
}
use of org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse in project plc4x by apache.
the class ModbusProtocolLogic method read.
@Override
public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest) {
CompletableFuture<PlcReadResponse> future = new CompletableFuture<>();
DefaultPlcReadRequest request = (DefaultPlcReadRequest) readRequest;
// Example for sending a request ...
if (request.getFieldNames().size() == 1) {
String fieldName = request.getFieldNames().iterator().next();
ModbusField field = (ModbusField) request.getField(fieldName);
final ModbusPDU requestPdu = getReadRequestPdu(field);
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) && (p.getUnitIdentifier() == unitIdentifier))).unwrap(ModbusTcpADU::getPdu).handle(responsePdu -> {
// Try to decode the response data based on the corresponding request.
PlcValue plcValue = null;
PlcResponseCode responseCode;
// Check if the response was an error response.
if (responsePdu instanceof ModbusPDUError) {
ModbusPDUError errorResponse = (ModbusPDUError) responsePdu;
responseCode = getErrorCode(errorResponse);
} else {
try {
plcValue = toPlcValue(requestPdu, responsePdu, field.getDataType());
responseCode = PlcResponseCode.OK;
} catch (ParseException e) {
// Add an error response code ...
responseCode = PlcResponseCode.INTERNAL_ERROR;
}
}
// Prepare the response.
PlcReadResponse response = new DefaultPlcReadResponse(request, Collections.singletonMap(fieldName, new ResponseItem<>(responseCode, plcValue)));
// 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