use of org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse in project plc4x by apache.
the class SimulatedConnection method read.
@Override
public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest) {
Map<String, ResponseItem<PlcValue>> fields = new HashMap<>();
for (String fieldName : readRequest.getFieldNames()) {
SimulatedField field = (SimulatedField) readRequest.getField(fieldName);
Optional<PlcValue> valueOptional = device.get(field);
ResponseItem<PlcValue> fieldPair;
boolean present = valueOptional.isPresent();
fieldPair = present ? new ResponseItem<>(PlcResponseCode.OK, valueOptional.get()) : new ResponseItem<>(PlcResponseCode.NOT_FOUND, null);
fields.put(fieldName, fieldPair);
}
PlcReadResponse response = new DefaultPlcReadResponse(readRequest, fields);
return CompletableFuture.completedFuture(response);
}
use of org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse in project plc4x by apache.
the class PlcEntityInterceptorTest method getTyped_notOkResponse_throws.
@Test
public void getTyped_notOkResponse_throws() {
DefaultPlcReadResponse response = new DefaultPlcReadResponse(null, Collections.singletonMap("field", new ResponseItem<>(PlcResponseCode.NOT_FOUND, null)));
assertThatThrownBy(() -> PlcEntityInterceptor.getTyped(Long.class, response, "field")).isInstanceOf(PlcRuntimeException.class).hasMessage("Unable to read specified field 'field', response code was 'NOT_FOUND'");
}
use of org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse in project plc4x by apache.
the class PlcEntityManagerComplexTest method getPlcEntityManager.
private PlcEntityManager getPlcEntityManager(final Map<String, PlcValue> responses) throws PlcConnectionException {
driverManager = Mockito.mock(PlcDriverManager.class);
PlcDriverManager mock = driverManager;
PlcConnection connection = Mockito.mock(PlcConnection.class);
when(mock.getConnection(ArgumentMatchers.anyString())).thenReturn(connection);
when(connection.getMetadata()).thenReturn(new PlcConnectionMetadata() {
@Override
public boolean canRead() {
return true;
}
@Override
public boolean canWrite() {
return true;
}
@Override
public boolean canSubscribe() {
return true;
}
});
PlcReader reader = readRequest -> {
Map<String, ResponseItem<PlcValue>> map = readRequest.getFieldNames().stream().collect(Collectors.toMap(Function.identity(), s -> new ResponseItem<>(PlcResponseCode.OK, Objects.requireNonNull(responses.get(s), s + " not found"))));
return CompletableFuture.completedFuture(new DefaultPlcReadResponse(readRequest, map));
};
when(connection.readRequestBuilder()).then(invocation -> new DefaultPlcReadRequest.Builder(reader, getFieldHandler()));
PlcWriter writer = writeRequest -> {
Map<String, PlcResponseCode> map = writeRequest.getFieldNames().stream().collect(Collectors.toMap(Function.identity(), s -> PlcResponseCode.OK));
return CompletableFuture.completedFuture(new DefaultPlcWriteResponse(writeRequest, map));
};
when(connection.writeRequestBuilder()).then(invocation -> new DefaultPlcWriteRequest.Builder(writer, getFieldHandler(), getValueHandler()));
return new PlcEntityManager(mock);
}
use of org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse in project plc4x by apache.
the class Plc4XDf1Protocol method decode.
@Override
protected void decode(ChannelHandlerContext ctx, DF1Symbol msg, List<Object> out) throws Exception {
logger.debug("Received DF1 Command incoming {}", msg);
if (msg instanceof DF1SymbolMessageFrameNAK) {
logger.warn("Received a response NAK, notify all requests");
for (Map.Entry<Integer, PlcRequestContainer> entry : requests.entrySet()) {
entry.getValue().getResponseFuture().complete(new DefaultPlcReadResponse((PlcReadRequest) entry.getValue().getRequest(), Collections.singletonMap("erster", new ResponseItem<>(PlcResponseCode.INTERNAL_ERROR, new PlcDINT(-1)))));
}
return;
} else if (msg instanceof DF1SymbolMessageFrameACK) {
logger.warn("Received a response ACK :D");
return;
}
assert msg instanceof DF1SymbolMessageFrame;
DF1Command command = ((DF1SymbolMessageFrame) msg).getCommand();
int transactionId = command.getTransactionCounter();
if (!requests.containsKey(transactionId)) {
logger.warn("Received a response to unknown transaction id {}", transactionId);
ctx.fireExceptionCaught(new RuntimeException("Received a response to unknown transaction id"));
ctx.close();
return;
}
// As every response has a matching request, get this request based on the tpdu.
PlcRequestContainer requestContainer = requests.remove(transactionId);
PlcRequest request = requestContainer.getRequest();
// Handle the response.
PlcResponse response = null;
if (request instanceof PlcReadRequest) {
/*
Things to do
- check response code (if there is something like that?
- cast the bytes to right datatype
- create Response
*/
// We can do this as we have only one fieldName in DF1
final String fieldName = ((PlcReadRequest) request).getFieldNames().iterator().next();
// TODO can there be another code than ok?
final PlcResponseCode responseCode = PlcResponseCode.OK;
// TODO maybe check for different status bytes
final Df1Field field = (Df1Field) ((PlcReadRequest) request).getField(fieldName);
// Cast byte and create response item
PlcValue responseItem = null;
byte[] data = ((DF1UnprotectedReadResponse) command).getData();
switch(field.getDataType()) {
case BIT:
break;
case INTEGER:
// TODO: type conversion is untested
responseItem = new PlcDINT((int) data[0] + ((int) data[1] << 8));
break;
case FLOAT:
break;
case BIT_STRING:
break;
case ARRAY:
break;
// TODO add all other cases here...
default:
throw new NotImplementedException("The DataType " + field.getDataType() + " is currently not implemented!");
}
response = new DefaultPlcReadResponse(((PlcReadRequest) request), Collections.singletonMap(fieldName, new ResponseItem<>(responseCode, responseItem)));
} else if (request instanceof PlcWriteRequest) {
logger.warn("Writing is currently not implemented but received a write response?!");
ctx.close();
throw new NotImplementedException("This is currently not implemented!");
}
// Confirm the response being handled.
if (response != null) {
requestContainer.getResponseFuture().complete(response);
}
}
use of org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse in project plc4x by apache.
the class Plc4xAbEthProtocol method decodeReadResponse.
private PlcResponse decodeReadResponse(CIPEncapsulationReadResponse plcReadResponse, PlcRequestContainer requestContainer) {
PlcReadRequest plcReadRequest = (PlcReadRequest) requestContainer.getRequest();
Map<String, ResponseItem<PlcValue>> values = new HashMap<>();
for (String fieldName : plcReadRequest.getFieldNames()) {
AbEthField field = (AbEthField) plcReadRequest.getField(fieldName);
PlcResponseCode responseCode = decodeResponseCode(plcReadResponse.getResponse().getStatus());
PlcValue plcValue = null;
if (responseCode == PlcResponseCode.OK) {
try {
switch(field.getFileType()) {
case // output as single bytes
INTEGER:
if (plcReadResponse.getResponse() instanceof DF1CommandResponseMessageProtectedTypedLogicalRead) {
DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
List<Short> data = df1PTLR.getData();
if (data.size() == 1) {
plcValue = new PlcINT(data.get(0));
} else {
plcValue = IEC61131ValueHandler.of(data);
}
}
break;
case WORD:
if (plcReadResponse.getResponse() instanceof DF1CommandResponseMessageProtectedTypedLogicalRead) {
DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
List<Short> data = df1PTLR.getData();
if (((data.get(1) >> 7) & 1) == 0) {
// positive number
plcValue = IEC61131ValueHandler.of((data.get(1) << 8) + data.get(0));
} else {
// negative number
plcValue = IEC61131ValueHandler.of((((~data.get(1) & 0b01111111) << 8) + (~(data.get(0) - 1) & 0b11111111)) * -1);
}
}
break;
case DWORD:
if (plcReadResponse.getResponse() instanceof DF1CommandResponseMessageProtectedTypedLogicalRead) {
DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
List<Short> data = df1PTLR.getData();
if (((data.get(3) >> 7) & 1) == 0) {
// positive number
plcValue = IEC61131ValueHandler.of((data.get(3) << 24) + (data.get(2) << 16) + (data.get(1) << 8) + data.get(0));
} else {
// negative number
plcValue = IEC61131ValueHandler.of((((~data.get(3) & 0b01111111) << 24) + ((~(data.get(2) - 1) & 0b11111111) << 16) + ((~(data.get(1) - 1) & 0b11111111) << 8) + (~(data.get(0) - 1) & 0b11111111)) * -1);
}
}
break;
case SINGLEBIT:
if (plcReadResponse.getResponse() instanceof DF1CommandResponseMessageProtectedTypedLogicalRead) {
DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
List<Short> data = df1PTLR.getData();
if (field.getBitNumber() < 8) {
// read from first byte
plcValue = IEC61131ValueHandler.of((data.get(0) & (1 << field.getBitNumber())) != 0);
} else {
// read from second byte
plcValue = IEC61131ValueHandler.of((data.get(1) & (1 << (field.getBitNumber() - 8))) != 0);
}
}
break;
default:
logger.warn("Problem during decoding of field {}: Decoding of file type not implemented; " + "FieldInformation: {}", fieldName, field);
}
} catch (Exception e) {
logger.warn("Some other error occurred casting field {}, FieldInformation: {}", fieldName, field, e);
}
}
ResponseItem<PlcValue> result = new ResponseItem<>(responseCode, plcValue);
values.put(fieldName, result);
}
return new DefaultPlcReadResponse(plcReadRequest, values);
}
Aggregations