Search in sources :

Example 11 with DefaultPlcReadResponse

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);
}
Also used : HashMap(java.util.HashMap) PlcINT(org.apache.plc4x.java.spi.values.PlcINT) PlcResponseCode(org.apache.plc4x.java.api.types.PlcResponseCode) DefaultPlcReadResponse(org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse) ResponseItem(org.apache.plc4x.java.spi.messages.utils.ResponseItem) AbEthField(org.apache.plc4x.java.abeth.field.AbEthField)

Example 12 with DefaultPlcReadResponse

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));
}
Also used : ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) CANOpenAbortException(org.apache.plc4x.java.canopen.transport.CANOpenAbortException) RequestTransactionManager(org.apache.plc4x.java.spi.transaction.RequestTransactionManager) PlcValue(org.apache.plc4x.java.api.value.PlcValue) CompletableFuture(java.util.concurrent.CompletableFuture) SDOUploadConversation(org.apache.plc4x.java.canopen.api.conversation.canopen.SDOUploadConversation) IndexAddress(org.apache.plc4x.java.canopen.readwrite.IndexAddress) DefaultPlcReadResponse(org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse) ResponseItem(org.apache.plc4x.java.spi.messages.utils.ResponseItem) PlcLINT(org.apache.plc4x.java.spi.values.PlcLINT)

Example 13 with DefaultPlcReadResponse

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);
}
Also used : PlcProtocolException(org.apache.plc4x.java.api.exceptions.PlcProtocolException) ByteBuf(io.netty.buffer.ByteBuf) TimeoutException(java.util.concurrent.TimeoutException) PlcProtocolException(org.apache.plc4x.java.api.exceptions.PlcProtocolException) InvocationTargetException(java.lang.reflect.InvocationTargetException) PlcRuntimeException(org.apache.plc4x.java.api.exceptions.PlcRuntimeException) PlcResponseCode(org.apache.plc4x.java.api.types.PlcResponseCode) PlcValue(org.apache.plc4x.java.api.value.PlcValue) PlcNull(org.apache.plc4x.java.spi.values.PlcNull) DefaultPlcReadResponse(org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse) ResponseItem(org.apache.plc4x.java.spi.messages.utils.ResponseItem) S7Field(org.apache.plc4x.java.s7.readwrite.field.S7Field)

Example 14 with DefaultPlcReadResponse

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;
}
Also used : org.apache.plc4x.java.api.value(org.apache.plc4x.java.api.value) PlcList(org.apache.plc4x.java.spi.values.PlcList) Arrays(java.util.Arrays) ArrayUtils(org.apache.commons.lang3.ArrayUtils) CompletableFuture(java.util.concurrent.CompletableFuture) DefaultPlcReadResponse(org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse) ArrayList(java.util.ArrayList) ModbusFieldDiscreteInput(org.apache.plc4x.java.modbus.field.ModbusFieldDiscreteInput) DefaultPlcWriteResponse(org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse) RequestTransactionManager(org.apache.plc4x.java.spi.transaction.RequestTransactionManager) ModbusField(org.apache.plc4x.java.modbus.field.ModbusField) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ModbusFieldCoil(org.apache.plc4x.java.modbus.field.ModbusFieldCoil) ConversationContext(org.apache.plc4x.java.spi.ConversationContext) Duration(java.time.Duration) PlcResponseCode(org.apache.plc4x.java.api.types.PlcResponseCode) Plc4xProtocolBase(org.apache.plc4x.java.spi.Plc4xProtocolBase) ModbusFieldInputRegister(org.apache.plc4x.java.modbus.field.ModbusFieldInputRegister) ModbusExtendedRegister(org.apache.plc4x.java.modbus.field.ModbusExtendedRegister) org.apache.plc4x.java.modbus.readwrite(org.apache.plc4x.java.modbus.readwrite) ModbusConfiguration(org.apache.plc4x.java.modbus.config.ModbusConfiguration) PlcField(org.apache.plc4x.java.api.model.PlcField) HasConfiguration(org.apache.plc4x.java.spi.configuration.HasConfiguration) org.apache.plc4x.java.spi.generation(org.apache.plc4x.java.spi.generation) List(java.util.List) PlcRuntimeException(org.apache.plc4x.java.api.exceptions.PlcRuntimeException) PlcBOOL(org.apache.plc4x.java.spi.values.PlcBOOL) ModbusFieldHoldingRegister(org.apache.plc4x.java.modbus.field.ModbusFieldHoldingRegister) DefaultPlcWriteRequest(org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest) DefaultPlcReadRequest(org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest) BitSet(java.util.BitSet) Collections(java.util.Collections) ResponseItem(org.apache.plc4x.java.spi.messages.utils.ResponseItem) org.apache.plc4x.java.api.messages(org.apache.plc4x.java.api.messages) PlcRuntimeException(org.apache.plc4x.java.api.exceptions.PlcRuntimeException) RequestTransactionManager(org.apache.plc4x.java.spi.transaction.RequestTransactionManager) ModbusField(org.apache.plc4x.java.modbus.field.ModbusField) PlcResponseCode(org.apache.plc4x.java.api.types.PlcResponseCode) DefaultPlcReadResponse(org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse) CompletableFuture(java.util.concurrent.CompletableFuture) DefaultPlcReadRequest(org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest) DefaultPlcReadResponse(org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse)

Aggregations

DefaultPlcReadResponse (org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse)14 ResponseItem (org.apache.plc4x.java.spi.messages.utils.ResponseItem)13 PlcResponseCode (org.apache.plc4x.java.api.types.PlcResponseCode)11 PlcValue (org.apache.plc4x.java.api.value.PlcValue)9 CompletableFuture (java.util.concurrent.CompletableFuture)7 PlcRuntimeException (org.apache.plc4x.java.api.exceptions.PlcRuntimeException)6 DefaultPlcWriteResponse (org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse)6 RequestTransactionManager (org.apache.plc4x.java.spi.transaction.RequestTransactionManager)6 Duration (java.time.Duration)5 HashMap (java.util.HashMap)5 PlcReadRequest (org.apache.plc4x.java.api.messages.PlcReadRequest)5 HasConfiguration (org.apache.plc4x.java.spi.configuration.HasConfiguration)5 Collections (java.util.Collections)4 PlcReadResponse (org.apache.plc4x.java.api.messages.PlcReadResponse)4 PlcWriteRequest (org.apache.plc4x.java.api.messages.PlcWriteRequest)4 PlcField (org.apache.plc4x.java.api.model.PlcField)4 DefaultPlcReadRequest (org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest)4 DefaultPlcWriteRequest (org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest)4 Map (java.util.Map)3 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)3