Search in sources :

Example 6 with DefaultPlcWriteResponse

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;
}
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) ModbusTcpConfiguration(org.apache.plc4x.java.modbus.tcp.config.ModbusTcpConfiguration) 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 7 with DefaultPlcWriteResponse

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;
}
Also used : Logger(org.slf4j.Logger) Plc4xConfiguration(org.apache.plc4x.java.plc4x.config.Plc4xConfiguration) LoggerFactory(org.slf4j.LoggerFactory) PlcValue(org.apache.plc4x.java.api.value.PlcValue) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) DefaultPlcReadResponse(org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse) ArrayList(java.util.ArrayList) org.apache.plc4x.java.plc4x.readwrite(org.apache.plc4x.java.plc4x.readwrite) HasConfiguration(org.apache.plc4x.java.spi.configuration.HasConfiguration) DefaultPlcWriteResponse(org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse) RequestTransactionManager(org.apache.plc4x.java.spi.transaction.RequestTransactionManager) List(java.util.List) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ConversationContext(org.apache.plc4x.java.spi.ConversationContext) Duration(java.time.Duration) Map(java.util.Map) PlcResponseCode(org.apache.plc4x.java.api.types.PlcResponseCode) Plc4xProtocolBase(org.apache.plc4x.java.spi.Plc4xProtocolBase) ResponseItem(org.apache.plc4x.java.spi.messages.utils.ResponseItem) org.apache.plc4x.java.api.messages(org.apache.plc4x.java.api.messages) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) DefaultPlcWriteResponse(org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse) CompletableFuture(java.util.concurrent.CompletableFuture) DefaultPlcWriteResponse(org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse) RequestTransactionManager(org.apache.plc4x.java.spi.transaction.RequestTransactionManager) PlcResponseCode(org.apache.plc4x.java.api.types.PlcResponseCode) PlcValue(org.apache.plc4x.java.api.value.PlcValue)

Example 8 with DefaultPlcWriteResponse

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;
}
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 9 with DefaultPlcWriteResponse

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));
}
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 10 with DefaultPlcWriteResponse

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);
}
Also used : PlcProtocolException(org.apache.plc4x.java.api.exceptions.PlcProtocolException) PlcResponseCode(org.apache.plc4x.java.api.types.PlcResponseCode) DefaultPlcWriteResponse(org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse)

Aggregations

DefaultPlcWriteResponse (org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse)11 PlcResponseCode (org.apache.plc4x.java.api.types.PlcResponseCode)10 CompletableFuture (java.util.concurrent.CompletableFuture)7 PlcValue (org.apache.plc4x.java.api.value.PlcValue)7 DefaultPlcReadResponse (org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse)6 ResponseItem (org.apache.plc4x.java.spi.messages.utils.ResponseItem)6 RequestTransactionManager (org.apache.plc4x.java.spi.transaction.RequestTransactionManager)6 Duration (java.time.Duration)5 PlcRuntimeException (org.apache.plc4x.java.api.exceptions.PlcRuntimeException)5 HasConfiguration (org.apache.plc4x.java.spi.configuration.HasConfiguration)5 DefaultPlcReadRequest (org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest)5 DefaultPlcWriteRequest (org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest)5 Collections (java.util.Collections)4 PlcField (org.apache.plc4x.java.api.model.PlcField)4 org.apache.plc4x.java.modbus.readwrite (org.apache.plc4x.java.modbus.readwrite)4 HashMap (java.util.HashMap)3 PlcReadRequest (org.apache.plc4x.java.api.messages.PlcReadRequest)3 PlcWriteResponse (org.apache.plc4x.java.api.messages.PlcWriteResponse)3 ArrayList (java.util.ArrayList)2 Arrays (java.util.Arrays)2