Search in sources :

Example 21 with PlcResponseCode

use of org.apache.plc4x.java.api.types.PlcResponseCode 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;
}
Also used : PlcWriteResponse(org.apache.plc4x.java.api.messages.PlcWriteResponse) PlcWriteRequest(org.apache.plc4x.java.api.messages.PlcWriteRequest) ParseException(org.apache.plc4x.java.spi.generation.ParseException) ModbusAsciiConfiguration(org.apache.plc4x.java.modbus.ascii.config.ModbusAsciiConfiguration) ModbusProtocolLogic(org.apache.plc4x.java.modbus.base.protocol.ModbusProtocolLogic) org.apache.plc4x.java.modbus.readwrite(org.apache.plc4x.java.modbus.readwrite) PlcValue(org.apache.plc4x.java.api.value.PlcValue) PlcReadResponse(org.apache.plc4x.java.api.messages.PlcReadResponse) CompletableFuture(java.util.concurrent.CompletableFuture) PlcField(org.apache.plc4x.java.api.model.PlcField) ModbusField(org.apache.plc4x.java.modbus.base.field.ModbusField) DefaultPlcReadResponse(org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse) ModbusRtuConfiguration(org.apache.plc4x.java.modbus.rtu.config.ModbusRtuConfiguration) HasConfiguration(org.apache.plc4x.java.spi.configuration.HasConfiguration) DefaultPlcWriteResponse(org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse) RequestTransactionManager(org.apache.plc4x.java.spi.transaction.RequestTransactionManager) PlcRuntimeException(org.apache.plc4x.java.api.exceptions.PlcRuntimeException) PlcReadRequest(org.apache.plc4x.java.api.messages.PlcReadRequest) Duration(java.time.Duration) PlcResponseCode(org.apache.plc4x.java.api.types.PlcResponseCode) DefaultPlcWriteRequest(org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest) DefaultPlcReadRequest(org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest) Collections(java.util.Collections) ResponseItem(org.apache.plc4x.java.spi.messages.utils.ResponseItem) PlcRuntimeException(org.apache.plc4x.java.api.exceptions.PlcRuntimeException) PlcField(org.apache.plc4x.java.api.model.PlcField) PlcWriteResponse(org.apache.plc4x.java.api.messages.PlcWriteResponse) DefaultPlcWriteResponse(org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse) RequestTransactionManager(org.apache.plc4x.java.spi.transaction.RequestTransactionManager) DefaultPlcWriteRequest(org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest) PlcResponseCode(org.apache.plc4x.java.api.types.PlcResponseCode) CompletableFuture(java.util.concurrent.CompletableFuture) DefaultPlcWriteResponse(org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse)

Example 22 with PlcResponseCode

use of org.apache.plc4x.java.api.types.PlcResponseCode 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 23 with PlcResponseCode

use of org.apache.plc4x.java.api.types.PlcResponseCode 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));
}
Also used : CompletableFuture(java.util.concurrent.CompletableFuture) PlcValue(org.apache.plc4x.java.api.value.PlcValue) DefaultPlcWriteResponse(org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse) IndexAddress(org.apache.plc4x.java.canopen.readwrite.IndexAddress) CANOpenAbortException(org.apache.plc4x.java.canopen.transport.CANOpenAbortException) RequestTransactionManager(org.apache.plc4x.java.spi.transaction.RequestTransactionManager) PlcResponseCode(org.apache.plc4x.java.api.types.PlcResponseCode) SDODownloadConversation(org.apache.plc4x.java.canopen.api.conversation.canopen.SDODownloadConversation)

Example 24 with PlcResponseCode

use of org.apache.plc4x.java.api.types.PlcResponseCode in project plc4x by apache.

the class GenericCANProtocolLogic method write.

@Override
public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
    final RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
    CompletableFuture<PlcWriteResponse> response = new CompletableFuture<>();
    transaction.submit(() -> {
        Map<Integer, WriteBufferByteBased> messages = new LinkedHashMap<>();
        Map<Integer, Map<String, PlcResponseCode>> responses = new HashMap<>();
        for (String field : writeRequest.getFieldNames()) {
            PlcField plcField = writeRequest.getField(field);
            if (!(plcField instanceof GenericCANField)) {
                responses.computeIfAbsent(-1, (node) -> new HashMap<>()).put(field, PlcResponseCode.UNSUPPORTED);
                continue;
            }
            GenericCANField canField = (GenericCANField) plcField;
            WriteBuffer buffer = messages.computeIfAbsent(canField.getNodeId(), (node) -> new WriteBufferByteBased(8, ByteOrder.LITTLE_ENDIAN));
            Map<String, PlcResponseCode> statusMap = responses.computeIfAbsent(canField.getNodeId(), (node) -> new HashMap<>());
            PlcValue value = writeRequest.getPlcValue(field);
            try {
                write(buffer, canField, value);
                statusMap.put(field, PlcResponseCode.OK);
            } catch (SerializationException e) {
                statusMap.put(field, PlcResponseCode.INVALID_DATA);
            }
        }
        Map<String, PlcResponseCode> codes = new HashMap<>();
        for (Map.Entry<Integer, WriteBufferByteBased> message : messages.entrySet()) {
            boolean discarded = false;
            for (Map.Entry<String, PlcResponseCode> entry : responses.get(message.getKey()).entrySet()) {
                codes.put(entry.getKey(), entry.getValue());
                if (!discarded && entry.getValue() != PlcResponseCode.OK) {
                    logger.info("Discarding writing of frame with field {}. Node {} will not be communicated.", entry.getKey(), message.getKey());
                    discarded = true;
                }
            }
            if (!discarded) {
                byte[] data = message.getValue().getData();
                logger.debug("Writing message with id {} and {} bytes of data", message.getKey(), data.length);
                context.sendToWire(new GenericFrame(message.getKey(), data));
            }
        }
        response.complete(new DefaultPlcWriteResponse(writeRequest, codes));
        transaction.endRequest();
    });
    return response;
}
Also used : PlcSubscriptionType(org.apache.plc4x.java.api.types.PlcSubscriptionType) java.util(java.util) DriverContext(org.apache.plc4x.java.spi.context.DriverContext) LoggerFactory(org.slf4j.LoggerFactory) PlcValue(org.apache.plc4x.java.api.value.PlcValue) DefaultPlcConsumerRegistration(org.apache.plc4x.java.spi.model.DefaultPlcConsumerRegistration) CompletableFuture(java.util.concurrent.CompletableFuture) PlcConsumerRegistration(org.apache.plc4x.java.api.model.PlcConsumerRegistration) RequestTransactionManager(org.apache.plc4x.java.spi.transaction.RequestTransactionManager) ConversationContext(org.apache.plc4x.java.spi.ConversationContext) DefaultPlcSubscriptionField(org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionField) PlcResponseCode(org.apache.plc4x.java.api.types.PlcResponseCode) Logger(org.slf4j.Logger) PlcSubscriptionHandle(org.apache.plc4x.java.api.model.PlcSubscriptionHandle) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) org.apache.plc4x.java.spi.messages(org.apache.plc4x.java.spi.messages) Instant(java.time.Instant) DefaultPlcSubscriptionHandle(org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionHandle) PlcField(org.apache.plc4x.java.api.model.PlcField) DataItem(org.apache.plc4x.java.genericcan.readwrite.DataItem) org.apache.plc4x.java.spi.generation(org.apache.plc4x.java.spi.generation) Consumer(java.util.function.Consumer) Plc4xCANProtocolBase(org.apache.plc4x.java.can.adapter.Plc4xCANProtocolBase) GenericFrame(org.apache.plc4x.java.can.generic.transport.GenericFrame) GenericCANField(org.apache.plc4x.java.can.generic.field.GenericCANField) Entry(java.util.Map.Entry) ResponseItem(org.apache.plc4x.java.spi.messages.utils.ResponseItem) org.apache.plc4x.java.api.messages(org.apache.plc4x.java.api.messages) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) PlcField(org.apache.plc4x.java.api.model.PlcField) CompletableFuture(java.util.concurrent.CompletableFuture) GenericCANField(org.apache.plc4x.java.can.generic.field.GenericCANField) RequestTransactionManager(org.apache.plc4x.java.spi.transaction.RequestTransactionManager) PlcResponseCode(org.apache.plc4x.java.api.types.PlcResponseCode) PlcValue(org.apache.plc4x.java.api.value.PlcValue) GenericFrame(org.apache.plc4x.java.can.generic.transport.GenericFrame) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Example 25 with PlcResponseCode

use of org.apache.plc4x.java.api.types.PlcResponseCode in project plc4x by apache.

the class EipProtocolLogic method decodeReadResponse.

private PlcResponse decodeReadResponse(CipService p, PlcReadRequest readRequest) {
    Map<String, ResponseItem<PlcValue>> values = new HashMap<>();
    // only 1 field
    if (p instanceof CipReadResponse) {
        CipReadResponse resp = (CipReadResponse) p;
        String fieldName = readRequest.getFieldNames().iterator().next();
        EipField field = (EipField) readRequest.getField(fieldName);
        PlcResponseCode code = decodeResponseCode(resp.getStatus());
        PlcValue plcValue = null;
        CIPDataTypeCode type = resp.getDataType();
        ByteBuf data = Unpooled.wrappedBuffer(resp.getData());
        if (code == PlcResponseCode.OK) {
            plcValue = parsePlcValue(field, data, type);
        }
        ResponseItem<PlcValue> result = new ResponseItem<>(code, plcValue);
        values.put(fieldName, result);
    } else // Multiple response
    if (p instanceof MultipleServiceResponse) {
        MultipleServiceResponse responses = (MultipleServiceResponse) p;
        int nb = responses.getServiceNb();
        List<CipService> arr = new ArrayList<>(nb);
        ReadBufferByteBased read = new ReadBufferByteBased(responses.getServicesData(), org.apache.plc4x.java.spi.generation.ByteOrder.LITTLE_ENDIAN);
        int total = (int) read.getTotalBytes();
        for (int i = 0; i < nb; i++) {
            int length = 0;
            // Substract first offset as we only have the service in the buffer (not servicesNb and offsets)
            int offset = responses.getOffsets().get(i) - responses.getOffsets().get(0);
            if (i == nb - 1) {
                // Get the rest if last
                length = total - offset;
            } else {
                // Calculate length with offsets (substracting first offset)
                length = responses.getOffsets().get(i + 1) - offset - responses.getOffsets().get(0);
            }
            ReadBuffer serviceBuf = new ReadBufferByteBased(read.getBytes(offset, offset + length), org.apache.plc4x.java.spi.generation.ByteOrder.LITTLE_ENDIAN);
            CipService service = null;
            try {
                service = CipService.staticParse(read, length);
                arr.add(service);
            } catch (ParseException e) {
                throw new PlcRuntimeException(e);
            }
        }
        Services services = new Services(nb, responses.getOffsets(), arr, -1);
        Iterator<String> it = readRequest.getFieldNames().iterator();
        for (int i = 0; i < nb && it.hasNext(); i++) {
            String fieldName = it.next();
            EipField field = (EipField) readRequest.getField(fieldName);
            PlcValue plcValue = null;
            if (services.getServices().get(i) instanceof CipReadResponse) {
                CipReadResponse readResponse = (CipReadResponse) services.getServices().get(i);
                PlcResponseCode code;
                if (readResponse.getStatus() == 0) {
                    code = PlcResponseCode.OK;
                } else {
                    code = PlcResponseCode.INTERNAL_ERROR;
                }
                CIPDataTypeCode type = readResponse.getDataType();
                ByteBuf data = Unpooled.wrappedBuffer(readResponse.getData());
                if (code == PlcResponseCode.OK) {
                    plcValue = parsePlcValue(field, data, type);
                }
                ResponseItem<PlcValue> result = new ResponseItem<>(code, plcValue);
                values.put(fieldName, result);
            }
        }
    }
    return new DefaultPlcReadResponse(readRequest, values);
}
Also used : PlcRuntimeException(org.apache.plc4x.java.api.exceptions.PlcRuntimeException) EipField(org.apache.plc4x.java.eip.readwrite.field.EipField) ByteBuf(io.netty.buffer.ByteBuf) PlcResponseCode(org.apache.plc4x.java.api.types.PlcResponseCode) ReadBuffer(org.apache.plc4x.java.spi.generation.ReadBuffer) ReadBufferByteBased(org.apache.plc4x.java.spi.generation.ReadBufferByteBased) ResponseItem(org.apache.plc4x.java.spi.messages.utils.ResponseItem) ParseException(org.apache.plc4x.java.spi.generation.ParseException)

Aggregations

PlcResponseCode (org.apache.plc4x.java.api.types.PlcResponseCode)31 ResponseItem (org.apache.plc4x.java.spi.messages.utils.ResponseItem)20 PlcValue (org.apache.plc4x.java.api.value.PlcValue)19 DefaultPlcReadResponse (org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse)16 CompletableFuture (java.util.concurrent.CompletableFuture)15 DefaultPlcWriteResponse (org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse)15 PlcRuntimeException (org.apache.plc4x.java.api.exceptions.PlcRuntimeException)14 RequestTransactionManager (org.apache.plc4x.java.spi.transaction.RequestTransactionManager)13 Duration (java.time.Duration)11 PlcReadRequest (org.apache.plc4x.java.api.messages.PlcReadRequest)11 PlcField (org.apache.plc4x.java.api.model.PlcField)11 PlcWriteRequest (org.apache.plc4x.java.api.messages.PlcWriteRequest)10 HasConfiguration (org.apache.plc4x.java.spi.configuration.HasConfiguration)10 DefaultPlcReadRequest (org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest)9 DefaultPlcWriteRequest (org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest)9 Collections (java.util.Collections)8 PlcWriteResponse (org.apache.plc4x.java.api.messages.PlcWriteResponse)8 org.apache.plc4x.java.modbus.readwrite (org.apache.plc4x.java.modbus.readwrite)8 ParseException (org.apache.plc4x.java.spi.generation.ParseException)8 List (java.util.List)7