Search in sources :

Example 11 with PlcWriteRequest

use of org.apache.plc4x.java.api.messages.PlcWriteRequest 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 12 with PlcWriteRequest

use of org.apache.plc4x.java.api.messages.PlcWriteRequest in project plc4x by apache.

the class Plc4xSinkProcessor method onTrigger.

@Override
public void onTrigger(final ProcessContext context, final ProcessSession session) throws ProcessException {
    FlowFile flowFile = session.get();
    // Abort if there's nothing to do.
    if (flowFile == null) {
        return;
    }
    // Get an instance of a component able to write to a PLC.
    try (PlcConnection connection = getDriverManager().getConnection(getConnectionString())) {
        if (!connection.getMetadata().canWrite()) {
            throw new ProcessException("Writing not supported by connection");
        }
        // Prepare the request.
        PlcWriteRequest.Builder builder = connection.writeRequestBuilder();
        flowFile.getAttributes().forEach((field, value) -> {
            String address = getAddress(field);
            if (address != null) {
                // TODO: Convert the String into the right type ...
                builder.addItem(field, address, Boolean.valueOf(value));
            }
        });
        PlcWriteRequest writeRequest = builder.build();
        // Send the request to the PLC.
        try {
            final PlcWriteResponse plcWriteResponse = writeRequest.execute().get();
            // TODO: Evaluate the response and create flow files for successful and unsuccessful updates
            session.transfer(flowFile, SUCCESS);
        } catch (Exception e) {
            flowFile = session.putAttribute(flowFile, "exception", e.getLocalizedMessage());
            session.transfer(flowFile, FAILURE);
        }
    } catch (ProcessException e) {
        throw e;
    } catch (Exception e) {
        throw new ProcessException("Got an error while trying to get a connection", e);
    }
}
Also used : FlowFile(org.apache.nifi.flowfile.FlowFile) ProcessException(org.apache.nifi.processor.exception.ProcessException) PlcWriteRequest(org.apache.plc4x.java.api.messages.PlcWriteRequest) PlcWriteResponse(org.apache.plc4x.java.api.messages.PlcWriteResponse) PlcConnection(org.apache.plc4x.java.api.PlcConnection) ProcessException(org.apache.nifi.processor.exception.ProcessException)

Example 13 with PlcWriteRequest

use of org.apache.plc4x.java.api.messages.PlcWriteRequest in project plc4x by apache.

the class Plc4xSinkTask method put.

@Override
public void put(Collection<SinkRecord> records) {
    if (records.isEmpty()) {
        return;
    }
    PlcConnection connection = null;
    try {
        connection = driverManager.getConnection(plc4xConnectionString);
    } catch (PlcConnectionException e) {
        log.warn("Failed to Open Connection {}", plc4xConnectionString);
        remainingRetries--;
        if (remainingRetries > 0) {
            if (context != null) {
                context.timeout(plc4xTimeout);
            }
            throw new RetriableException("Failed to Write to " + plc4xConnectionString + " retrying records that haven't expired");
        }
        log.warn("Failed to write after {} retries", plc4xRetries);
        return;
    }
    PlcWriteRequest writeRequest;
    final PlcWriteRequest.Builder builder = connection.writeRequestBuilder();
    int validCount = 0;
    for (SinkRecord r : records) {
        Struct record = (Struct) r.value();
        String topic = r.topic();
        Struct plcFields = record.getStruct(Constants.FIELDS_CONFIG);
        Schema plcFieldsSchema = plcFields.schema();
        for (Field plcField : plcFieldsSchema.fields()) {
            String field = plcField.name();
            Object value = plcFields.get(field);
            if (value != null) {
                Long timestamp = record.getInt64("timestamp");
                Long expiresOffset = record.getInt64("expires");
                Long expires = 0L;
                if (expiresOffset != null) {
                    expires = expiresOffset + timestamp;
                }
                // Discard records we are not or no longer interested in.
                if (!topic.equals(plc4xTopic) || plc4xTopic.equals("")) {
                    log.debug("Ignoring write request received on wrong topic");
                } else if (!fields.containsKey(field)) {
                    log.warn("Unable to find address for field " + field);
                } else if ((System.currentTimeMillis() > expires) & !(expires == 0)) {
                    log.warn("Write request has expired {} - {}, discarding {}", expires, System.currentTimeMillis(), field);
                } else {
                    String address = fields.get(field);
                    try {
                        // If an array value is passed instead of a single value then convert to a String array
                        if (value instanceof String) {
                            String sValue = (String) value;
                            if ((sValue.charAt(0) == '[') && (sValue.charAt(sValue.length() - 1) == ']')) {
                                String[] values = sValue.substring(1, sValue.length() - 1).split(",");
                                builder.addItem(address, address, values);
                            } else {
                                builder.addItem(address, address, value);
                            }
                        } else {
                            builder.addItem(address, address, value);
                        }
                        validCount += 1;
                    } catch (Exception e) {
                        // When building a request we want to discard the write if there is an error.
                        log.warn("Invalid Address format for protocol {}", address);
                    }
                }
            }
        }
    }
    if (validCount > 0) {
        try {
            writeRequest = builder.build();
            writeRequest.execute().get();
            log.debug("Wrote records to {}", plc4xConnectionString);
        } catch (Exception e) {
            remainingRetries--;
            if (remainingRetries > 0) {
                if (context != null) {
                    context.timeout(plc4xTimeout);
                }
                try {
                    connection.close();
                } catch (Exception f) {
                    log.warn("Failed to Close {} on RetriableException", plc4xConnectionString);
                }
                throw new RetriableException("Failed to Write to " + plc4xConnectionString + " retrying records that haven't expired");
            }
            log.warn("Failed to write after {} retries", plc4xRetries);
        }
    }
    try {
        connection.close();
    } catch (Exception e) {
        log.warn("Failed to Close {}", plc4xConnectionString);
    }
    remainingRetries = plc4xRetries;
    return;
}
Also used : SinkRecord(org.apache.kafka.connect.sink.SinkRecord) PlcConnection(org.apache.plc4x.java.api.PlcConnection) RetriableException(org.apache.kafka.connect.errors.RetriableException) PlcConnectionException(org.apache.plc4x.java.api.exceptions.PlcConnectionException) PlcWriteRequest(org.apache.plc4x.java.api.messages.PlcWriteRequest) PlcConnectionException(org.apache.plc4x.java.api.exceptions.PlcConnectionException) RetriableException(org.apache.kafka.connect.errors.RetriableException)

Example 14 with PlcWriteRequest

use of org.apache.plc4x.java.api.messages.PlcWriteRequest in project plc4x by apache.

the class Plc4x2AdsProtocol method encode.

@Override
protected void encode(ChannelHandlerContext ctx, PlcRequestContainer<InternalPlcRequest, InternalPlcResponse> msg, List<Object> out) throws Exception {
    LOGGER.trace("(<--OUT): {}, {}, {}", ctx, msg, out);
    PlcRequest request = msg.getRequest();
    if (request instanceof PlcReadRequest) {
        encodeReadRequest(msg, out);
    } else if (request instanceof PlcWriteRequest) {
        encodeWriteRequest(msg, out);
    } else if (request instanceof PlcProprietaryRequest) {
        encodeProprietaryRequest(msg, out);
    } else {
        throw new PlcProtocolException("Unknown type " + request.getClass());
    }
}
Also used : PlcWriteRequest(org.apache.plc4x.java.api.messages.PlcWriteRequest) PlcProtocolException(org.apache.plc4x.java.api.exceptions.PlcProtocolException) PlcRequest(org.apache.plc4x.java.api.messages.PlcRequest) PlcReadRequest(org.apache.plc4x.java.api.messages.PlcReadRequest)

Example 15 with PlcWriteRequest

use of org.apache.plc4x.java.api.messages.PlcWriteRequest in project plc4x by apache.

the class OpcuaPlcDriverTest method writeVariables.

@Test
public void writeVariables() throws Exception {
    PlcConnection opcuaConnection = new PlcDriverManager().getConnection(tcpConnectionAddress);
    assert opcuaConnection.isConnected();
    PlcWriteRequest.Builder builder = opcuaConnection.writeRequestBuilder();
    builder.addItem("Bool", BOOL_IDENTIFIER_READ_WRITE, true);
    builder.addItem("Byte", BYTE_IDENTIFIER_READ_WRITE + ";BYTE", 255);
    builder.addItem("Double", DOUBLE_IDENTIFIER_READ_WRITE, 0.5d);
    builder.addItem("Float", FLOAT_IDENTIFIER_READ_WRITE, 0.5f);
    builder.addItem("Int16", INT16_IDENTIFIER_READ_WRITE + ";INT", 32000);
    builder.addItem("Int32", INT32_IDENTIFIER_READ_WRITE, 42);
    builder.addItem("Int64", INT64_IDENTIFIER_READ_WRITE, 42L);
    builder.addItem("Integer", INTEGER_IDENTIFIER_READ_WRITE, 42);
    builder.addItem("SByte", SBYTE_IDENTIFIER_READ_WRITE + ";USINT", 100);
    builder.addItem("String", STRING_IDENTIFIER_READ_WRITE, "Helllo Toddy!");
    builder.addItem("UInt16", UINT16_IDENTIFIER_READ_WRITE + ";UINT", 65535);
    builder.addItem("UInt32", UINT32_IDENTIFIER_READ_WRITE + ";UDINT", 100);
    builder.addItem("UInt64", UINT64_IDENTIFIER_READ_WRITE + ";ULINT", new BigInteger("1337"));
    builder.addItem("UInteger", UINTEGER_IDENTIFIER_READ_WRITE + ";UDINT", 100);
    builder.addItem("DoesNotExists", DOES_NOT_EXIST_IDENTIFIER_READ_WRITE, "Sad Toddy");
    PlcWriteRequest request = builder.build();
    PlcWriteResponse response = request.execute().get();
    assert response.getResponseCode("Bool").equals(PlcResponseCode.OK);
    assert response.getResponseCode("Byte").equals(PlcResponseCode.OK);
    assert response.getResponseCode("Double").equals(PlcResponseCode.OK);
    assert response.getResponseCode("Float").equals(PlcResponseCode.OK);
    assert response.getResponseCode("Int16").equals(PlcResponseCode.OK);
    assert response.getResponseCode("Int32").equals(PlcResponseCode.OK);
    assert response.getResponseCode("Int64").equals(PlcResponseCode.OK);
    assert response.getResponseCode("Integer").equals(PlcResponseCode.OK);
    assert response.getResponseCode("SByte").equals(PlcResponseCode.OK);
    assert response.getResponseCode("String").equals(PlcResponseCode.OK);
    assert response.getResponseCode("UInt16").equals(PlcResponseCode.OK);
    assert response.getResponseCode("UInt32").equals(PlcResponseCode.OK);
    assert response.getResponseCode("UInt64").equals(PlcResponseCode.OK);
    assert response.getResponseCode("UInteger").equals(PlcResponseCode.OK);
    assert response.getResponseCode("DoesNotExists").equals(PlcResponseCode.NOT_FOUND);
    opcuaConnection.close();
    assert !opcuaConnection.isConnected();
}
Also used : PlcWriteRequest(org.apache.plc4x.java.api.messages.PlcWriteRequest) BigInteger(java.math.BigInteger) PlcWriteResponse(org.apache.plc4x.java.api.messages.PlcWriteResponse) PlcDriverManager(org.apache.plc4x.java.PlcDriverManager) PlcConnection(org.apache.plc4x.java.api.PlcConnection)

Aggregations

PlcWriteRequest (org.apache.plc4x.java.api.messages.PlcWriteRequest)17 PlcReadRequest (org.apache.plc4x.java.api.messages.PlcReadRequest)10 PlcWriteResponse (org.apache.plc4x.java.api.messages.PlcWriteResponse)10 PlcConnection (org.apache.plc4x.java.api.PlcConnection)8 PlcValue (org.apache.plc4x.java.api.value.PlcValue)8 PlcResponseCode (org.apache.plc4x.java.api.types.PlcResponseCode)7 PlcField (org.apache.plc4x.java.api.model.PlcField)6 PlcReadResponse (org.apache.plc4x.java.api.messages.PlcReadResponse)5 DefaultPlcReadResponse (org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse)5 DefaultPlcWriteRequest (org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest)5 Duration (java.time.Duration)4 CompletableFuture (java.util.concurrent.CompletableFuture)4 PlcDriverManager (org.apache.plc4x.java.PlcDriverManager)4 PlcProtocolException (org.apache.plc4x.java.api.exceptions.PlcProtocolException)4 PlcRequest (org.apache.plc4x.java.api.messages.PlcRequest)4 BigInteger (java.math.BigInteger)3 Collections (java.util.Collections)3 PlcRuntimeException (org.apache.plc4x.java.api.exceptions.PlcRuntimeException)3 DefaultPlcReadRequest (org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest)3 DefaultPlcWriteResponse (org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse)3