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;
}
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;
}
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);
}
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);
}
Aggregations