Search in sources :

Example 1 with DefaultPlcWriteRequest

use of org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest in project plc4x by apache.

the class ModbusProtocolLogic 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 : 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) PlcField(org.apache.plc4x.java.api.model.PlcField) 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 2 with DefaultPlcWriteRequest

use of org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest in project plc4x by apache.

the class S7Optimizer method processWriteRequest.

@Override
protected List<PlcRequest> processWriteRequest(PlcWriteRequest writeRequest, DriverContext driverContext) {
    S7DriverContext s7DriverContext = (S7DriverContext) driverContext;
    List<PlcRequest> processedRequests = new LinkedList<>();
    // This calculates the size of the header for the request and response.
    int curRequestSize = EMPTY_WRITE_REQUEST_SIZE;
    // An empty response has the same size as an empty request.
    int curResponseSize = EMPTY_WRITE_RESPONSE_SIZE;
    // List of all items in the current request.
    LinkedHashMap<String, FieldValueItem> curFields = new LinkedHashMap<>();
    for (String fieldName : writeRequest.getFieldNames()) {
        S7Field field = (S7Field) writeRequest.getField(fieldName);
        PlcValue value = writeRequest.getPlcValue(fieldName);
        int writeRequestItemSize = S7_ADDRESS_ANY_SIZE + 4;
        if (field.getDataType() == TransportSize.BOOL) {
            writeRequestItemSize += Math.ceil((double) field.getNumberOfElements() / 8);
        } else {
            writeRequestItemSize += (field.getNumberOfElements() * field.getDataType().getSizeInBytes());
        }
        // If it's an odd number of bytes, add one to make it even
        if (writeRequestItemSize % 2 == 1) {
            writeRequestItemSize++;
        }
        int writeResponseItemSize = 4;
        // If adding the item would not exceed the sizes, add it to the current request.
        if (((curRequestSize + writeRequestItemSize) <= s7DriverContext.getPduSize()) && ((curResponseSize + writeResponseItemSize) <= s7DriverContext.getPduSize())) {
            // Increase the current request sizes.
            curRequestSize += writeRequestItemSize;
            curResponseSize += writeResponseItemSize;
        // Add the item.
        } else // If adding them would exceed, start a new request.
        {
            // Create a new PlcWriteRequest containing the current field item.
            processedRequests.add(new DefaultPlcWriteRequest(((DefaultPlcWriteRequest) writeRequest).getWriter(), curFields));
            // Reset the size and item lists.
            curRequestSize = EMPTY_WRITE_REQUEST_SIZE + writeRequestItemSize;
            curResponseSize = EMPTY_WRITE_RESPONSE_SIZE + writeResponseItemSize;
            curFields = new LinkedHashMap<>();
            // Splitting of huge fields not yet implemented, throw an exception instead.
            if (((curRequestSize + writeRequestItemSize) > s7DriverContext.getPduSize()) && ((curResponseSize + writeResponseItemSize) > s7DriverContext.getPduSize())) {
                throw new PlcRuntimeException("Field size exceeds maximum payload for one item.");
            }
        }
        curFields.put(fieldName, new FieldValueItem(field, value));
    }
    // Create a new PlcWriteRequest from the remaining field items.
    if (!curFields.isEmpty()) {
        processedRequests.add(new DefaultPlcWriteRequest(((DefaultPlcWriteRequest) writeRequest).getWriter(), curFields));
    }
    return processedRequests;
}
Also used : PlcRuntimeException(org.apache.plc4x.java.api.exceptions.PlcRuntimeException) FieldValueItem(org.apache.plc4x.java.spi.messages.utils.FieldValueItem) DefaultPlcWriteRequest(org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest) PlcValue(org.apache.plc4x.java.api.value.PlcValue) S7DriverContext(org.apache.plc4x.java.s7.readwrite.context.S7DriverContext) S7Field(org.apache.plc4x.java.s7.readwrite.field.S7Field)

Example 3 with DefaultPlcWriteRequest

use of org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest in project plc4x by apache.

the class SingleFieldOptimizer method processWriteRequest.

@Override
protected List<PlcRequest> processWriteRequest(PlcWriteRequest writeRequest, DriverContext driverContext) {
    if (writeRequest.getNumberOfFields() == 1) {
        return Collections.singletonList(writeRequest);
    }
    List<PlcRequest> subRequests = new ArrayList<>(writeRequest.getNumberOfFields());
    for (String fieldName : writeRequest.getFieldNames()) {
        PlcField field = writeRequest.getField(fieldName);
        PlcValue value = writeRequest.getPlcValue(fieldName);
        PlcWriteRequest subRequest = new DefaultPlcWriteRequest(((DefaultPlcWriteRequest) writeRequest).getWriter(), new LinkedHashMap<>(Collections.singletonMap(fieldName, new FieldValueItem(field, value))));
        subRequests.add(subRequest);
    }
    return subRequests;
}
Also used : PlcValue(org.apache.plc4x.java.api.value.PlcValue) PlcWriteRequest(org.apache.plc4x.java.api.messages.PlcWriteRequest) DefaultPlcWriteRequest(org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest) FieldValueItem(org.apache.plc4x.java.spi.messages.utils.FieldValueItem) PlcRequest(org.apache.plc4x.java.api.messages.PlcRequest) ArrayList(java.util.ArrayList) PlcField(org.apache.plc4x.java.api.model.PlcField) DefaultPlcWriteRequest(org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest)

Example 4 with DefaultPlcWriteRequest

use of org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest in project plc4x by apache.

the class S7ProtocolLogic method write.

@Override
public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
    CompletableFuture<PlcWriteResponse> future = new CompletableFuture<>();
    DefaultPlcWriteRequest request = (DefaultPlcWriteRequest) writeRequest;
    List<S7VarRequestParameterItem> parameterItems = new ArrayList<>(request.getNumberOfFields());
    List<S7VarPayloadDataItem> payloadItems = new ArrayList<>(request.getNumberOfFields());
    for (String fieldName : request.getFieldNames()) {
        final S7Field field = (S7Field) request.getField(fieldName);
        final PlcValue plcValue = request.getPlcValue(fieldName);
        parameterItems.add(new S7VarRequestParameterItemAddress(encodeS7Address(field)));
        payloadItems.add(serializePlcValue(field, plcValue));
    }
    final int tpduId = tpduGenerator.getAndIncrement();
    // If we've reached the max value for a 16 bit transaction identifier, reset back to 1
    if (tpduGenerator.get() == 0xFFFF) {
        tpduGenerator.set(1);
    }
    TPKTPacket tpktPacket = new TPKTPacket(new COTPPacketData(null, new S7MessageRequest(tpduId, new S7ParameterWriteVarRequest(parameterItems), new S7PayloadWriteVarRequest(payloadItems, null)), true, (short) tpduId, null));
    // Start a new request-transaction (Is ended in the response-handler)
    RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
    transaction.submit(() -> context.sendRequest(tpktPacket).onTimeout(new TransactionErrorCallback<>(future, transaction)).onError(new TransactionErrorCallback<>(future, transaction)).expectResponse(TPKTPacket.class, REQUEST_TIMEOUT).check(p -> p.getPayload() instanceof COTPPacketData).unwrap(p -> ((COTPPacketData) p.getPayload())).unwrap(COTPPacket::getPayload).check(p -> p.getTpduReference() == tpduId).handle(p -> {
        try {
            future.complete(((PlcWriteResponse) decodeWriteResponse(p, writeRequest)));
        } catch (PlcProtocolException e) {
            logger.warn("Error sending 'write' message: '{}'", e.getMessage(), e);
        }
        // Finish the request-transaction.
        transaction.endRequest();
    }));
    return future;
}
Also used : PlcWriteResponse(org.apache.plc4x.java.api.messages.PlcWriteResponse) PlcWriteRequest(org.apache.plc4x.java.api.messages.PlcWriteRequest) DriverContext(org.apache.plc4x.java.spi.context.DriverContext) LoggerFactory(org.slf4j.LoggerFactory) PlcValue(org.apache.plc4x.java.api.value.PlcValue) TimeoutException(java.util.concurrent.TimeoutException) ByteBuffer(java.nio.ByteBuffer) PlcSubscriptionRequest(org.apache.plc4x.java.api.messages.PlcSubscriptionRequest) Unpooled(io.netty.buffer.Unpooled) DefaultPlcWriteResponse(org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse) PlcReadRequest(org.apache.plc4x.java.api.messages.PlcReadRequest) PlcSubscriptionResponse(org.apache.plc4x.java.api.messages.PlcSubscriptionResponse) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) 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) PlcUnsubscriptionRequest(org.apache.plc4x.java.api.messages.PlcUnsubscriptionRequest) PlcProtocolException(org.apache.plc4x.java.api.exceptions.PlcProtocolException) PlcSubscriptionHandle(org.apache.plc4x.java.api.model.PlcSubscriptionHandle) BlockingQueue(java.util.concurrent.BlockingQueue) S7PlcSubscriptionHandle(org.apache.plc4x.java.s7.readwrite.utils.S7PlcSubscriptionHandle) org.apache.plc4x.java.spi.generation(org.apache.plc4x.java.spi.generation) ArrayBlockingQueue(java.util.concurrent.ArrayBlockingQueue) org.apache.plc4x.java.s7.readwrite(org.apache.plc4x.java.s7.readwrite) PlcNull(org.apache.plc4x.java.spi.values.PlcNull) DefaultPlcWriteRequest(org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest) ResponseItem(org.apache.plc4x.java.spi.messages.utils.ResponseItem) org.apache.plc4x.java.s7.readwrite.types(org.apache.plc4x.java.s7.readwrite.types) IntStream(java.util.stream.IntStream) S7StringField(org.apache.plc4x.java.s7.readwrite.field.S7StringField) java.util(java.util) PlcReadResponse(org.apache.plc4x.java.api.messages.PlcReadResponse) CompletableFuture(java.util.concurrent.CompletableFuture) PlcUnsubscriptionResponse(org.apache.plc4x.java.api.messages.PlcUnsubscriptionResponse) DefaultPlcReadResponse(org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse) PlcResponse(org.apache.plc4x.java.api.messages.PlcResponse) S7DriverContext(org.apache.plc4x.java.s7.readwrite.context.S7DriverContext) RequestTransactionManager(org.apache.plc4x.java.spi.transaction.RequestTransactionManager) ByteBuf(io.netty.buffer.ByteBuf) DefaultPlcSubscriptionResponse(org.apache.plc4x.java.spi.messages.DefaultPlcSubscriptionResponse) DefaultPlcSubscriptionField(org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionField) BiConsumer(java.util.function.BiConsumer) Logger(org.slf4j.Logger) DefaultPlcUnsubscriptionRequest(org.apache.plc4x.java.spi.messages.DefaultPlcUnsubscriptionRequest) PlcField(org.apache.plc4x.java.api.model.PlcField) IEC61131ValueHandler(org.apache.plc4x.java.spi.values.IEC61131ValueHandler) Consumer(java.util.function.Consumer) DefaultPlcSubscriptionRequest(org.apache.plc4x.java.spi.messages.DefaultPlcSubscriptionRequest) PlcRuntimeException(org.apache.plc4x.java.api.exceptions.PlcRuntimeException) S7SubscriptionField(org.apache.plc4x.java.s7.readwrite.field.S7SubscriptionField) S7Field(org.apache.plc4x.java.s7.readwrite.field.S7Field) DefaultPlcReadRequest(org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest) PlcWriteResponse(org.apache.plc4x.java.api.messages.PlcWriteResponse) DefaultPlcWriteResponse(org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse) DefaultPlcWriteRequest(org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest) CompletableFuture(java.util.concurrent.CompletableFuture) S7Field(org.apache.plc4x.java.s7.readwrite.field.S7Field) PlcProtocolException(org.apache.plc4x.java.api.exceptions.PlcProtocolException) RequestTransactionManager(org.apache.plc4x.java.spi.transaction.RequestTransactionManager) PlcValue(org.apache.plc4x.java.api.value.PlcValue)

Aggregations

PlcRuntimeException (org.apache.plc4x.java.api.exceptions.PlcRuntimeException)3 PlcField (org.apache.plc4x.java.api.model.PlcField)3 PlcValue (org.apache.plc4x.java.api.value.PlcValue)3 DefaultPlcWriteRequest (org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest)3 Duration (java.time.Duration)2 ArrayList (java.util.ArrayList)2 CompletableFuture (java.util.concurrent.CompletableFuture)2 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)2 PlcWriteRequest (org.apache.plc4x.java.api.messages.PlcWriteRequest)2 PlcResponseCode (org.apache.plc4x.java.api.types.PlcResponseCode)2 S7DriverContext (org.apache.plc4x.java.s7.readwrite.context.S7DriverContext)2 S7Field (org.apache.plc4x.java.s7.readwrite.field.S7Field)2 ConversationContext (org.apache.plc4x.java.spi.ConversationContext)2 Plc4xProtocolBase (org.apache.plc4x.java.spi.Plc4xProtocolBase)2 org.apache.plc4x.java.spi.generation (org.apache.plc4x.java.spi.generation)2 DefaultPlcReadRequest (org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest)2 FieldValueItem (org.apache.plc4x.java.spi.messages.utils.FieldValueItem)2 ByteBuf (io.netty.buffer.ByteBuf)1 Unpooled (io.netty.buffer.Unpooled)1 ByteBuffer (java.nio.ByteBuffer)1