Search in sources :

Example 1 with DefaultPlcSubscriptionResponse

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

the class MockDriver method getConnection.

@Override
public PlcConnection getConnection(String url) throws PlcConnectionException {
    // Mock a connection.
    PlcConnection plcConnectionMock = mock(PlcConnection.class, RETURNS_DEEP_STUBS);
    when(plcConnectionMock.getMetadata().canRead()).thenReturn(true);
    when(plcConnectionMock.getMetadata().canWrite()).thenReturn(true);
    when(plcConnectionMock.readRequestBuilder()).thenReturn(mock(PlcReadRequest.Builder.class, RETURNS_DEEP_STUBS));
    when(plcConnectionMock.writeRequestBuilder()).thenReturn(mock(PlcWriteRequest.Builder.class, RETURNS_DEEP_STUBS));
    when(plcConnectionMock.subscriptionRequestBuilder()).thenReturn(mock(PlcSubscriptionRequest.Builder.class, RETURNS_DEEP_STUBS));
    when(plcConnectionMock.unsubscriptionRequestBuilder()).thenReturn(mock(PlcUnsubscriptionRequest.Builder.class, RETURNS_DEEP_STUBS));
    // Mock a typical subscriber.
    PlcSubscriber plcSubscriber = mock(PlcSubscriber.class, RETURNS_DEEP_STUBS);
    when(plcSubscriber.subscribe(any(PlcSubscriptionRequest.class))).thenAnswer(invocation -> {
        LOGGER.info("Received {}", invocation);
        // TODO: Translate this so it actually does something ...
        /*PlcSubscriptionRequest subscriptionRequest = invocation.getArgument(0);
            List<PlcSubscriptionResponse> responseItems =
                subscriptionRequest.getFieldNames().stream().map(
                    fieldName -> subscriptionRequest.getField(fieldName)).map(field -> {
                    Consumer consumer = subscriptionRequestItem.getConsumer();
                    executorService.submit(() -> {
                        while (!Thread.currentThread().isInterrupted()) {
                            consumer.accept(new SubscriptionEventItem<>(null, Calendar.getInstance(), Collections.singletonList("HelloWorld")));
                            try {
                                TimeUnit.MILLISECONDS.sleep(100);
                            } catch (InterruptedException e) {
                                Thread.currentThread().interrupt();
                                throw new RuntimeException(e);
                            }
                        }
                    });
                    return new SubscriptionResponseItem<>(subscriptionRequestItem,
                        mock(PlcSubscriptionHandle.class, RETURNS_DEEP_STUBS), PlcResponseCode.OK);
                }).collect(Collectors.toList());
            PlcSubscriptionResponse response = new PlcSubscriptionResponse(subscriptionRequest, responseItems);*/
        PlcSubscriptionResponse response = new DefaultPlcSubscriptionResponse(mock(PlcSubscriptionRequest.class), new HashMap<>());
        CompletableFuture<PlcSubscriptionResponse> responseFuture = new CompletableFuture<>();
        responseFuture.complete(response);
        return responseFuture;
    });
    return plcConnectionMock;
}
Also used : CompletableFuture(java.util.concurrent.CompletableFuture) DefaultPlcSubscriptionResponse(org.apache.plc4x.java.spi.messages.DefaultPlcSubscriptionResponse) DefaultPlcSubscriptionResponse(org.apache.plc4x.java.spi.messages.DefaultPlcSubscriptionResponse) PlcSubscriber(org.apache.plc4x.java.spi.messages.PlcSubscriber) PlcConnection(org.apache.plc4x.java.api.PlcConnection)

Example 2 with DefaultPlcSubscriptionResponse

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

the class S7ProtocolLogic method decodeEventSubcriptionRequest.

private PlcSubscriptionResponse decodeEventSubcriptionRequest(S7Message responseMessage, PlcSubscriptionRequest plcSubscriptionRequest) throws PlcProtocolException {
    Map<String, ResponseItem<PlcSubscriptionHandle>> values = new HashMap<>();
    short errorClass = 0;
    short errorCode = 0;
    if (responseMessage instanceof S7MessageUserData) {
        S7MessageUserData messageUserData = (S7MessageUserData) responseMessage;
        S7PayloadUserData payload = (S7PayloadUserData) messageUserData.getPayload();
    // errorClass = payload.getItems()[0].
    // errorCode = messageUserData.getParameter().
    } 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 : plcSubscriptionRequest.getFieldNames()) {
                values.put(fieldName, null);
            }
            return new DefaultPlcSubscriptionResponse(plcSubscriptionRequest, values);
        } 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 : plcSubscriptionRequest.getFieldNames()) {
                values.put(fieldName, null);
            }
            return new DefaultPlcSubscriptionResponse(plcSubscriptionRequest, values);
        }
    }
    // In all other cases all went well.
    S7PayloadUserData payload = (S7PayloadUserData) responseMessage.getPayload();
    List<S7PayloadUserDataItem> payloadItems = payload.getItems();
    // Only one item for any number of subscription (4)
    if (payloadItems.size() == 0) {
        throw new PlcProtocolException("The number of requested items doesn't match the number of returned items");
    }
    boolean responseOk = false;
    if (payloadItems.get(0) instanceof S7PayloadUserDataItemCpuFunctionMsgSubscriptionResponse) {
        S7PayloadUserDataItemCpuFunctionMsgSubscriptionResponse item = (S7PayloadUserDataItemCpuFunctionMsgSubscriptionResponse) payloadItems.get(0);
        if ((item.getReturnCode() == DataTransportErrorCode.OK) && (item.getTransportSize() == DataTransportSize.OCTET_STRING)) {
            responseOk = true;
        }
    } else if (payloadItems.get(0) instanceof S7PayloadUserDataItemCpuFunctionMsgSubscriptionSysResponse) {
        S7PayloadUserDataItemCpuFunctionMsgSubscriptionSysResponse item = (S7PayloadUserDataItemCpuFunctionMsgSubscriptionSysResponse) payloadItems.get(0);
        if ((item.getReturnCode() == DataTransportErrorCode.OK) && (item.getTransportSize() == DataTransportSize.OCTET_STRING)) {
            responseOk = true;
        }
    } else if (payloadItems.get(0) instanceof S7PayloadUserDataItemCpuFunctionMsgSubscriptionAlarmResponse) {
        S7PayloadUserDataItemCpuFunctionMsgSubscriptionAlarmResponse item = (S7PayloadUserDataItemCpuFunctionMsgSubscriptionAlarmResponse) payloadItems.get(0);
        if ((item.getReturnCode() == DataTransportErrorCode.OK) && (item.getTransportSize() == DataTransportSize.OCTET_STRING)) {
            responseOk = true;
        }
    }
    if (responseOk) {
        for (String fieldName : plcSubscriptionRequest.getFieldNames()) {
            DefaultPlcSubscriptionField dfield = (DefaultPlcSubscriptionField) plcSubscriptionRequest.getField(fieldName);
            S7SubscriptionField field = (S7SubscriptionField) dfield.getPlcField();
            switch(field.getEventType()) {
                case MODE:
                    values.put(fieldName, new ResponseItem<>(PlcResponseCode.OK, modeHandle));
                    break;
                case SYS:
                    values.put(fieldName, new ResponseItem<>(PlcResponseCode.OK, sysHandle));
                    break;
                case USR:
                    values.put(fieldName, new ResponseItem<>(PlcResponseCode.OK, usrHandle));
                    break;
                case ALM:
                    values.put(fieldName, new ResponseItem<>(PlcResponseCode.OK, almHandle));
                    break;
            }
        }
        return new DefaultPlcSubscriptionResponse(plcSubscriptionRequest, values);
    }
    return null;
}
Also used : S7SubscriptionField(org.apache.plc4x.java.s7.readwrite.field.S7SubscriptionField) PlcProtocolException(org.apache.plc4x.java.api.exceptions.PlcProtocolException) DefaultPlcSubscriptionResponse(org.apache.plc4x.java.spi.messages.DefaultPlcSubscriptionResponse) DefaultPlcSubscriptionField(org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionField) ResponseItem(org.apache.plc4x.java.spi.messages.utils.ResponseItem)

Example 3 with DefaultPlcSubscriptionResponse

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

the class SimulatedConnection method subscribe.

/**
 * Blocking subscribe call
 *
 * @param subscriptionRequest subscription request containing at least one subscription request item.
 * @return the {@code PlcSubscriptionResponse}
 */
@Override
public CompletableFuture<PlcSubscriptionResponse> subscribe(PlcSubscriptionRequest subscriptionRequest) {
    LOGGER.info("subscribing {}", subscriptionRequest);
    Map<String, ResponseItem<PlcSubscriptionHandle>> values = new HashMap<>();
    subscriptionRequest.getFieldNames().forEach(name -> {
        LOGGER.info("creating handle for field name {}", name);
        PlcSubscriptionHandle handle = new DefaultPlcSubscriptionHandle(this);
        final PlcSubscriptionField subscriptionPlcField = subscriptionRequest.getField(name);
        switch(subscriptionPlcField.getPlcSubscriptionType()) {
            case CYCLIC:
                LOGGER.info("Adding cyclic subscription for field name {}", name);
                device.addCyclicSubscription(dispatchSubscriptionEvent(name, handle), handle, subscriptionPlcField, subscriptionPlcField.getDuration().orElseThrow(RuntimeException::new));
                break;
            case CHANGE_OF_STATE:
                LOGGER.info("Adding change of state subscription for field name {}", name);
                device.addChangeOfStateSubscription(dispatchSubscriptionEvent(name, handle), handle, subscriptionPlcField);
                break;
            case EVENT:
                LOGGER.info("Adding event subscription for field name {}", name);
                device.addEventSubscription(dispatchSubscriptionEvent(name, handle), handle, subscriptionPlcField);
                break;
        }
        values.put(name, new ResponseItem<>(PlcResponseCode.OK, handle));
    });
    PlcSubscriptionResponse response = new DefaultPlcSubscriptionResponse(subscriptionRequest, values);
    return CompletableFuture.completedFuture(response);
}
Also used : PlcSubscriptionField(org.apache.plc4x.java.api.model.PlcSubscriptionField) PlcSubscriptionResponse(org.apache.plc4x.java.api.messages.PlcSubscriptionResponse) DefaultPlcSubscriptionResponse(org.apache.plc4x.java.spi.messages.DefaultPlcSubscriptionResponse) HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) DefaultPlcSubscriptionResponse(org.apache.plc4x.java.spi.messages.DefaultPlcSubscriptionResponse) PlcSubscriptionHandle(org.apache.plc4x.java.api.model.PlcSubscriptionHandle) DefaultPlcSubscriptionHandle(org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionHandle) ResponseItem(org.apache.plc4x.java.spi.messages.utils.ResponseItem) DefaultPlcSubscriptionHandle(org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionHandle)

Example 4 with DefaultPlcSubscriptionResponse

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

the class CANOpenProtocolLogic method subscribe.

@Override
public CompletableFuture<PlcSubscriptionResponse> subscribe(PlcSubscriptionRequest request) {
    DefaultPlcSubscriptionRequest rq = (DefaultPlcSubscriptionRequest) request;
    Map<String, ResponseItem<PlcSubscriptionHandle>> answers = new LinkedHashMap<>();
    DefaultPlcSubscriptionResponse response = new DefaultPlcSubscriptionResponse(rq, answers);
    for (String key : rq.getFieldNames()) {
        DefaultPlcSubscriptionField subscription = (DefaultPlcSubscriptionField) rq.getField(key);
        if (subscription.getPlcSubscriptionType() != PlcSubscriptionType.EVENT) {
            answers.put(key, new ResponseItem<>(PlcResponseCode.UNSUPPORTED, null));
        } else if ((subscription.getPlcField() instanceof CANOpenPDOField)) {
            answers.put(key, new ResponseItem<>(PlcResponseCode.OK, new CANOpenSubscriptionHandle(this, key, (CANOpenPDOField) subscription.getPlcField())));
        } else if ((subscription.getPlcField() instanceof CANOpenNMTField)) {
            answers.put(key, new ResponseItem<>(PlcResponseCode.OK, new CANOpenSubscriptionHandle(this, key, (CANOpenNMTField) subscription.getPlcField())));
        } else if ((subscription.getPlcField() instanceof CANOpenHeartbeatField)) {
            answers.put(key, new ResponseItem<>(PlcResponseCode.OK, new CANOpenSubscriptionHandle(this, key, (CANOpenHeartbeatField) subscription.getPlcField())));
        } else {
            answers.put(key, new ResponseItem<>(PlcResponseCode.INVALID_ADDRESS, null));
        }
    }
    return CompletableFuture.completedFuture(response);
}
Also used : DefaultPlcSubscriptionField(org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionField) CANOpenPDOField(org.apache.plc4x.java.canopen.field.CANOpenPDOField) DefaultPlcSubscriptionResponse(org.apache.plc4x.java.spi.messages.DefaultPlcSubscriptionResponse) CANOpenNMTField(org.apache.plc4x.java.canopen.field.CANOpenNMTField) ResponseItem(org.apache.plc4x.java.spi.messages.utils.ResponseItem) DefaultPlcSubscriptionRequest(org.apache.plc4x.java.spi.messages.DefaultPlcSubscriptionRequest) LinkedHashMap(java.util.LinkedHashMap) CANOpenHeartbeatField(org.apache.plc4x.java.canopen.field.CANOpenHeartbeatField)

Aggregations

DefaultPlcSubscriptionResponse (org.apache.plc4x.java.spi.messages.DefaultPlcSubscriptionResponse)4 ResponseItem (org.apache.plc4x.java.spi.messages.utils.ResponseItem)3 DefaultPlcSubscriptionField (org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionField)2 HashMap (java.util.HashMap)1 LinkedHashMap (java.util.LinkedHashMap)1 CompletableFuture (java.util.concurrent.CompletableFuture)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 PlcConnection (org.apache.plc4x.java.api.PlcConnection)1 PlcProtocolException (org.apache.plc4x.java.api.exceptions.PlcProtocolException)1 PlcSubscriptionResponse (org.apache.plc4x.java.api.messages.PlcSubscriptionResponse)1 PlcSubscriptionField (org.apache.plc4x.java.api.model.PlcSubscriptionField)1 PlcSubscriptionHandle (org.apache.plc4x.java.api.model.PlcSubscriptionHandle)1 CANOpenHeartbeatField (org.apache.plc4x.java.canopen.field.CANOpenHeartbeatField)1 CANOpenNMTField (org.apache.plc4x.java.canopen.field.CANOpenNMTField)1 CANOpenPDOField (org.apache.plc4x.java.canopen.field.CANOpenPDOField)1 S7SubscriptionField (org.apache.plc4x.java.s7.readwrite.field.S7SubscriptionField)1 DefaultPlcSubscriptionRequest (org.apache.plc4x.java.spi.messages.DefaultPlcSubscriptionRequest)1 PlcSubscriber (org.apache.plc4x.java.spi.messages.PlcSubscriber)1 DefaultPlcSubscriptionHandle (org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionHandle)1