Search in sources :

Example 21 with PlcReadRequest

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

the class AbEthProtocolLogic method read.

@Override
public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest) {
    // TODO: Warning ... we are senging one request per field ... the result has to be merged back together ...
    for (String fieldName : readRequest.getFieldNames()) {
        PlcField field = readRequest.getField(fieldName);
        if (!(field instanceof AbEthField)) {
            logger.error("The field should have been of type AbEthField");
        }
        AbEthField abEthField = (AbEthField) field;
        DF1RequestProtectedTypedLogicalRead logicalRead = new DF1RequestProtectedTypedLogicalRead(abEthField.getByteSize(), abEthField.getFileNumber(), abEthField.getFileType().getTypeCode(), abEthField.getElementNumber(), // Subelementnumber default to zero
        (short) 0);
        final int transactionCounter = transactionCounterGenerator.incrementAndGet();
        // If we've reached the max value for a 16 bit transaction identifier, reset back to 1
        if (transactionCounterGenerator.get() == 0xFFFF) {
            transactionCounterGenerator.set(1);
        }
        // origin/sender: constant = 5
        DF1RequestMessage requestMessage = new DF1CommandRequestMessage((short) configuration.getStation(), (short) 5, (short) 0, transactionCounter, logicalRead);
        CIPEncapsulationReadRequest read = new CIPEncapsulationReadRequest(sessionHandle, 0, emptySenderContext, 0, requestMessage);
        CompletableFuture<PlcReadResponse> future = new CompletableFuture<>();
        RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
        transaction.submit(() -> context.sendRequest(read).expectResponse(CIPEncapsulationPacket.class, REQUEST_TIMEOUT).onTimeout(future::completeExceptionally).onError((p, e) -> future.completeExceptionally(e)).check(p -> p instanceof CIPEncapsulationReadResponse).unwrap(p -> (CIPEncapsulationReadResponse) p).check(p -> p.getResponse().getTransactionCounter() == transactionCounter).handle(p -> {
            PlcResponse response = decodeReadResponse(p, readRequest);
            // TODO: Not sure how to merge things back together ...
            // future.complete(response);
            // Finish the request-transaction.
            transaction.endRequest();
        // future.complete(((PlcReadResponse) decodeReadResponse(p, ((InternalPlcReadRequest) readRequest))));
        }));
        // TODO: This aborts reading other fields after sending the first fields request ... refactor.
        return future;
    }
    // TODO: Should return an aggregated future ....
    return null;
}
Also used : org.apache.plc4x.java.api.value(org.apache.plc4x.java.api.value) org.apache.plc4x.java.abeth.readwrite(org.apache.plc4x.java.abeth.readwrite) Arrays(java.util.Arrays) LoggerFactory(org.slf4j.LoggerFactory) PlcReadResponse(org.apache.plc4x.java.api.messages.PlcReadResponse) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) DefaultPlcReadResponse(org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse) PlcResponse(org.apache.plc4x.java.api.messages.PlcResponse) AbEthConfiguration(org.apache.plc4x.java.abeth.configuration.AbEthConfiguration) RequestTransactionManager(org.apache.plc4x.java.spi.transaction.RequestTransactionManager) PlcReadRequest(org.apache.plc4x.java.api.messages.PlcReadRequest) PlcINT(org.apache.plc4x.java.spi.values.PlcINT) 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) AbEthField(org.apache.plc4x.java.abeth.field.AbEthField) Logger(org.slf4j.Logger) PlcField(org.apache.plc4x.java.api.model.PlcField) IEC61131ValueHandler(org.apache.plc4x.java.spi.values.IEC61131ValueHandler) HasConfiguration(org.apache.plc4x.java.spi.configuration.HasConfiguration) List(java.util.List) ResponseItem(org.apache.plc4x.java.spi.messages.utils.ResponseItem) PlcField(org.apache.plc4x.java.api.model.PlcField) RequestTransactionManager(org.apache.plc4x.java.spi.transaction.RequestTransactionManager) PlcReadResponse(org.apache.plc4x.java.api.messages.PlcReadResponse) DefaultPlcReadResponse(org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse) CompletableFuture(java.util.concurrent.CompletableFuture) PlcResponse(org.apache.plc4x.java.api.messages.PlcResponse) AbEthField(org.apache.plc4x.java.abeth.field.AbEthField)

Example 22 with PlcReadRequest

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

the class Plc4xAbEthProtocol method encode.

@Override
protected void encode(ChannelHandlerContext ctx, PlcRequestContainer msg, List<Object> out) throws Exception {
    logger.trace("Encoding {}", msg);
    PlcRequest request = msg.getRequest();
    // reset counter since two byte values are possible in DF1
    if (transactionCounterGenerator.get() > 65000) {
        transactionCounterGenerator.set(10);
    }
    if (request instanceof PlcReadRequest) {
        PlcReadRequest readRequest = (PlcReadRequest) msg.getRequest();
        for (String fieldName : readRequest.getFieldNames()) {
            PlcField field = readRequest.getField(fieldName);
            if (!(field instanceof AbEthField)) {
                throw new PlcProtocolException("The field should have been of type AbEthField");
            }
            AbEthField abEthField = (AbEthField) field;
            DF1RequestProtectedTypedLogicalRead logicalRead = new DF1RequestProtectedTypedLogicalRead(abEthField.getByteSize(), abEthField.getFileNumber(), abEthField.getFileType().getTypeCode(), abEthField.getElementNumber(), // Subelementnumber default to zero
            (short) 0);
            // origin/sender: constant = 5
            DF1RequestMessage requestMessage = new DF1CommandRequestMessage((short) station, (short) 5, (short) 0, transactionCounterGenerator.incrementAndGet(), logicalRead);
            CIPEncapsulationReadRequest read = new CIPEncapsulationReadRequest(sessionHandle, 0, emptySenderContext, 0, requestMessage);
            requests.put(requestMessage.getTransactionCounter(), msg);
            out.add(read);
        }
    } else {
        ctx.fireExceptionCaught(new PlcProtocolException("Unsupported request type " + request.getClass().getName()));
    }
}
Also used : PlcProtocolException(org.apache.plc4x.java.api.exceptions.PlcProtocolException) PlcRequest(org.apache.plc4x.java.api.messages.PlcRequest) PlcField(org.apache.plc4x.java.api.model.PlcField) PlcReadRequest(org.apache.plc4x.java.api.messages.PlcReadRequest) AbEthField(org.apache.plc4x.java.abeth.field.AbEthField)

Example 23 with PlcReadRequest

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

the class Plc4xCommunication method getValue.

public DataValue getValue(AttributeFilterContext.GetAttributeContext ctx, String tag, String connectionString) {
    PlcConnection connection = null;
    try {
        // Check if we just polled the connection and it failed. Wait for the backoff counter to expire before we try again.
        if (failedConnectionList.containsKey(connectionString)) {
            if (System.currentTimeMillis() > failedConnectionList.get(connectionString) + DEFAULT_RETRY_BACKOFF) {
                failedConnectionList.remove(connectionString);
            } else {
                logger.debug("Waiting for back off timer - " + ((failedConnectionList.get(connectionString) + DEFAULT_RETRY_BACKOFF) - System.currentTimeMillis()) + " ms left");
                return BAD_RESPONSE;
            }
        }
        // Try to connect to PLC
        try {
            connection = driverManager.getConnection(connectionString);
            logger.debug(connectionString + " Connected");
        } catch (PlcConnectionException e) {
            logger.error("Failed to connect to device, error raised - " + e);
            failedConnectionList.put(connectionString, System.currentTimeMillis());
            return BAD_RESPONSE;
        }
        if (!connection.getMetadata().canRead()) {
            logger.error("This connection doesn't support reading.");
            try {
                connection.close();
            } catch (Exception exception) {
                logger.warn("Closing connection failed with error - " + exception);
            }
            return BAD_RESPONSE;
        }
        long timeout = DEFAULT_TIMEOUT;
        if (monitoredList.containsKey(ctx.getNode().getNodeId())) {
            timeout = (long) monitoredList.get(ctx.getNode().getNodeId()).getSamplingInterval() * 1000;
        }
        // Create a new read request:
        // - Give the single item requested an alias name
        PlcReadRequest.Builder builder = connection.readRequestBuilder();
        builder.addItem("value-1", tag);
        PlcReadRequest readRequest = builder.build();
        PlcReadResponse response = null;
        try {
            response = readRequest.execute().get(timeout, TimeUnit.MICROSECONDS);
        } catch (InterruptedException | ExecutionException | TimeoutException e) {
            logger.warn(e + " Occurred while reading value, using timeout of " + timeout / 1000 + "ms");
            try {
                connection.close();
            } catch (Exception exception) {
                logger.warn("Closing connection failed with error - " + exception);
            }
            return BAD_RESPONSE;
        }
        DataValue resp = BAD_RESPONSE;
        for (String fieldName : response.getFieldNames()) {
            if (response.getResponseCode(fieldName) == PlcResponseCode.OK) {
                int numValues = response.getNumberOfValues(fieldName);
                if (numValues == 1) {
                    if (response.getObject(fieldName) instanceof BigInteger) {
                        resp = new DataValue(new Variant(ulong((BigInteger) response.getObject(fieldName))), StatusCode.GOOD);
                    } else {
                        resp = new DataValue(new Variant(response.getObject(fieldName)), StatusCode.GOOD);
                    }
                } else {
                    Object array = null;
                    if (response.getObject(fieldName, 0) instanceof BigInteger) {
                        array = Array.newInstance(ULong.class, numValues);
                    } else {
                        array = Array.newInstance(response.getObject(fieldName, 0).getClass(), numValues);
                    }
                    for (int i = 0; i < numValues; i++) {
                        if (response.getObject(fieldName, i) instanceof BigInteger) {
                            Array.set(array, i, ulong((BigInteger) response.getObject(fieldName, i)));
                        } else {
                            Array.set(array, i, response.getObject(fieldName, i));
                        }
                    }
                    resp = new DataValue(new Variant(array), StatusCode.GOOD);
                }
            }
        }
        try {
            connection.close();
        } catch (Exception e) {
            failedConnectionList.put(connectionString, System.currentTimeMillis());
            logger.warn("Closing connection failed with error " + e);
        }
        return resp;
    } catch (Exception e) {
        logger.warn("General error reading value " + e.getStackTrace()[0].toString());
        if (connection != null) {
            try {
                connection.close();
            } catch (Exception ex) {
            // Do Nothing
            }
        }
        return BAD_RESPONSE;
    }
}
Also used : ULong(org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.ULong) DataValue(org.eclipse.milo.opcua.stack.core.types.builtin.DataValue) PlcConnection(org.apache.plc4x.java.api.PlcConnection) TimeoutException(java.util.concurrent.TimeoutException) PlcConnectionException(org.apache.plc4x.java.api.exceptions.PlcConnectionException) ExecutionException(java.util.concurrent.ExecutionException) Unsigned.ulong(org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.ulong) Variant(org.eclipse.milo.opcua.stack.core.types.builtin.Variant) PlcReadResponse(org.apache.plc4x.java.api.messages.PlcReadResponse) BigInteger(java.math.BigInteger) PlcConnectionException(org.apache.plc4x.java.api.exceptions.PlcConnectionException) PlcReadRequest(org.apache.plc4x.java.api.messages.PlcReadRequest) ExecutionException(java.util.concurrent.ExecutionException) TimeoutException(java.util.concurrent.TimeoutException)

Example 24 with PlcReadRequest

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

the class Plc4xSourceProcessor method onTrigger.

@Override
public void onTrigger(final ProcessContext context, final ProcessSession session) throws ProcessException {
    // Get an instance of a component able to read from a PLC.
    try (PlcConnection connection = getDriverManager().getConnection(getConnectionString())) {
        // Prepare the request.
        if (!connection.getMetadata().canRead()) {
            throw new ProcessException("Writing not supported by connection");
        }
        FlowFile flowFile = session.create();
        try {
            PlcReadRequest.Builder builder = connection.readRequestBuilder();
            getFields().forEach(field -> {
                String address = getAddress(field);
                if (address != null) {
                    builder.addItem(field, address);
                }
            });
            PlcReadRequest readRequest = builder.build();
            PlcReadResponse response = readRequest.execute().get();
            Map<String, String> attributes = new HashMap<>();
            for (String fieldName : response.getFieldNames()) {
                for (int i = 0; i < response.getNumberOfValues(fieldName); i++) {
                    Object value = response.getObject(fieldName, i);
                    attributes.put(fieldName, String.valueOf(value));
                }
            }
            flowFile = session.putAllAttributes(flowFile, attributes);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new ProcessException(e);
        } catch (ExecutionException e) {
            throw new ProcessException(e);
        }
        session.transfer(flowFile, SUCCESS);
    } 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) HashMap(java.util.HashMap) PlcConnection(org.apache.plc4x.java.api.PlcConnection) ProcessException(org.apache.nifi.processor.exception.ProcessException) ExecutionException(java.util.concurrent.ExecutionException) PlcReadResponse(org.apache.plc4x.java.api.messages.PlcReadResponse) ProcessException(org.apache.nifi.processor.exception.ProcessException) PlcReadRequest(org.apache.plc4x.java.api.messages.PlcReadRequest) ExecutionException(java.util.concurrent.ExecutionException)

Example 25 with PlcReadRequest

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

the class Plc4x2AdsProtocol method encodeReadRequest.

private void encodeReadRequest(PlcRequestContainer<InternalPlcRequest, InternalPlcResponse> msg, List<Object> out) throws PlcException {
    PlcReadRequest readRequest = (PlcReadRequest) msg.getRequest();
    if (readRequest.getFields().size() != 1) {
        throw new PlcProtocolException("Only one item supported");
    }
    PlcField field = readRequest.getFields().get(0);
    if (field instanceof SymbolicAdsField) {
        DirectAdsField mappedField = fieldMapping.get(field);
        if (mappedField == null) {
            throw new PlcProtocolException("No field mapping for " + field);
        }
        LOGGER.debug("Replacing {} with {}", field, mappedField);
        field = mappedField;
    }
    if (!(field instanceof DirectAdsField)) {
        throw new PlcProtocolException("PlcField not of type DirectAdsField: " + field.getClass());
    }
    DirectAdsField directAdsField = (DirectAdsField) field;
    Invoke invokeId = Invoke.of(correlationBuilder.incrementAndGet());
    IndexGroup indexGroup = IndexGroup.of(directAdsField.getIndexGroup());
    IndexOffset indexOffset = IndexOffset.of(directAdsField.getIndexOffset());
    AdsDataType adsDataType = directAdsField.getAdsDataType();
    int numberOfElements = directAdsField.getNumberOfElements();
    int readLength = adsDataType.getTargetByteSize() * numberOfElements;
    Length length = Length.of(readLength);
    AmsPacket amsPacket = AdsReadRequest.of(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, indexGroup, indexOffset, length);
    LOGGER.debug("encoded read request {}", amsPacket);
    out.add(amsPacket);
    requests.put(invokeId.getAsLong(), msg);
}
Also used : PlcProtocolException(org.apache.plc4x.java.api.exceptions.PlcProtocolException) SymbolicAdsField(org.apache.plc4x.java.ads.model.SymbolicAdsField) AdsDataType(org.apache.plc4x.java.ads.model.AdsDataType) PlcField(org.apache.plc4x.java.api.model.PlcField) DirectAdsField(org.apache.plc4x.java.ads.model.DirectAdsField) AmsPacket(org.apache.plc4x.java.ads.api.generic.AmsPacket) PlcReadRequest(org.apache.plc4x.java.api.messages.PlcReadRequest) Invoke(org.apache.plc4x.java.ads.api.generic.types.Invoke)

Aggregations

PlcReadRequest (org.apache.plc4x.java.api.messages.PlcReadRequest)37 PlcReadResponse (org.apache.plc4x.java.api.messages.PlcReadResponse)21 PlcConnection (org.apache.plc4x.java.api.PlcConnection)17 PlcDriverManager (org.apache.plc4x.java.PlcDriverManager)12 PlcWriteRequest (org.apache.plc4x.java.api.messages.PlcWriteRequest)9 PlcField (org.apache.plc4x.java.api.model.PlcField)9 PlcResponseCode (org.apache.plc4x.java.api.types.PlcResponseCode)8 PlcProtocolException (org.apache.plc4x.java.api.exceptions.PlcProtocolException)7 PlcRequest (org.apache.plc4x.java.api.messages.PlcRequest)7 ExecutionException (java.util.concurrent.ExecutionException)5 PlcWriteResponse (org.apache.plc4x.java.api.messages.PlcWriteResponse)5 PlcValue (org.apache.plc4x.java.api.value.PlcValue)5 DefaultPlcReadResponse (org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse)5 Duration (java.time.Duration)4 HashMap (java.util.HashMap)4 Map (java.util.Map)4 CompletableFuture (java.util.concurrent.CompletableFuture)4 PlcConnectionException (org.apache.plc4x.java.api.exceptions.PlcConnectionException)4 DefaultPlcReadRequest (org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest)4 ResponseItem (org.apache.plc4x.java.spi.messages.utils.ResponseItem)4