use of org.apache.plc4x.java.api.types.PlcResponseCode 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;
}
use of org.apache.plc4x.java.api.types.PlcResponseCode in project plc4x by apache.
the class AbEthProtocolLogic method decodeReadResponse.
private PlcResponse decodeReadResponse(CIPEncapsulationReadResponse plcReadResponse, PlcReadRequest plcReadRequest) {
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);
}
// TODO: Double check if it's really a InternalPlcReadRequest ...
return new DefaultPlcReadResponse(plcReadRequest, values);
}
use of org.apache.plc4x.java.api.types.PlcResponseCode in project plc4x by apache.
the class CANOpenProtocolLogic method writeInternally.
private void writeInternally(DefaultPlcWriteRequest writeRequest, CANOpenSDOField field, CompletableFuture<PlcWriteResponse> response) {
final RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
String fieldName = writeRequest.getFieldNames().iterator().next();
CompletableFuture<PlcResponseCode> callback = new CompletableFuture<>();
callback.whenComplete((code, error) -> {
if (error != null) {
if (error instanceof CANOpenAbortException) {
response.complete(new DefaultPlcWriteResponse(writeRequest, Collections.singletonMap(fieldName, PlcResponseCode.REMOTE_ERROR)));
} else {
response.complete(new DefaultPlcWriteResponse(writeRequest, Collections.singletonMap(fieldName, PlcResponseCode.INTERNAL_ERROR)));
}
transaction.endRequest();
return;
}
response.complete(new DefaultPlcWriteResponse(writeRequest, Collections.singletonMap(fieldName, code)));
transaction.endRequest();
});
PlcValue writeValue = writeRequest.getPlcValues().get(0);
SDODownloadConversation download = new SDODownloadConversation(conversation, field.getNodeId(), field.getAnswerNodeId(), new IndexAddress(field.getIndex(), field.getSubIndex()), writeValue, field.getCanOpenDataType());
transaction.submit(() -> download.execute(callback));
}
use of org.apache.plc4x.java.api.types.PlcResponseCode in project plc4x by apache.
the class GenericCANProtocolLogic method write.
@Override
public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
final RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
CompletableFuture<PlcWriteResponse> response = new CompletableFuture<>();
transaction.submit(() -> {
Map<Integer, WriteBufferByteBased> messages = new LinkedHashMap<>();
Map<Integer, Map<String, PlcResponseCode>> responses = new HashMap<>();
for (String field : writeRequest.getFieldNames()) {
PlcField plcField = writeRequest.getField(field);
if (!(plcField instanceof GenericCANField)) {
responses.computeIfAbsent(-1, (node) -> new HashMap<>()).put(field, PlcResponseCode.UNSUPPORTED);
continue;
}
GenericCANField canField = (GenericCANField) plcField;
WriteBuffer buffer = messages.computeIfAbsent(canField.getNodeId(), (node) -> new WriteBufferByteBased(8, ByteOrder.LITTLE_ENDIAN));
Map<String, PlcResponseCode> statusMap = responses.computeIfAbsent(canField.getNodeId(), (node) -> new HashMap<>());
PlcValue value = writeRequest.getPlcValue(field);
try {
write(buffer, canField, value);
statusMap.put(field, PlcResponseCode.OK);
} catch (SerializationException e) {
statusMap.put(field, PlcResponseCode.INVALID_DATA);
}
}
Map<String, PlcResponseCode> codes = new HashMap<>();
for (Map.Entry<Integer, WriteBufferByteBased> message : messages.entrySet()) {
boolean discarded = false;
for (Map.Entry<String, PlcResponseCode> entry : responses.get(message.getKey()).entrySet()) {
codes.put(entry.getKey(), entry.getValue());
if (!discarded && entry.getValue() != PlcResponseCode.OK) {
logger.info("Discarding writing of frame with field {}. Node {} will not be communicated.", entry.getKey(), message.getKey());
discarded = true;
}
}
if (!discarded) {
byte[] data = message.getValue().getData();
logger.debug("Writing message with id {} and {} bytes of data", message.getKey(), data.length);
context.sendToWire(new GenericFrame(message.getKey(), data));
}
}
response.complete(new DefaultPlcWriteResponse(writeRequest, codes));
transaction.endRequest();
});
return response;
}
use of org.apache.plc4x.java.api.types.PlcResponseCode in project plc4x by apache.
the class EipProtocolLogic method decodeReadResponse.
private PlcResponse decodeReadResponse(CipService p, PlcReadRequest readRequest) {
Map<String, ResponseItem<PlcValue>> values = new HashMap<>();
// only 1 field
if (p instanceof CipReadResponse) {
CipReadResponse resp = (CipReadResponse) p;
String fieldName = readRequest.getFieldNames().iterator().next();
EipField field = (EipField) readRequest.getField(fieldName);
PlcResponseCode code = decodeResponseCode(resp.getStatus());
PlcValue plcValue = null;
CIPDataTypeCode type = resp.getDataType();
ByteBuf data = Unpooled.wrappedBuffer(resp.getData());
if (code == PlcResponseCode.OK) {
plcValue = parsePlcValue(field, data, type);
}
ResponseItem<PlcValue> result = new ResponseItem<>(code, plcValue);
values.put(fieldName, result);
} else // Multiple response
if (p instanceof MultipleServiceResponse) {
MultipleServiceResponse responses = (MultipleServiceResponse) p;
int nb = responses.getServiceNb();
List<CipService> arr = new ArrayList<>(nb);
ReadBufferByteBased read = new ReadBufferByteBased(responses.getServicesData(), org.apache.plc4x.java.spi.generation.ByteOrder.LITTLE_ENDIAN);
int total = (int) read.getTotalBytes();
for (int i = 0; i < nb; i++) {
int length = 0;
// Substract first offset as we only have the service in the buffer (not servicesNb and offsets)
int offset = responses.getOffsets().get(i) - responses.getOffsets().get(0);
if (i == nb - 1) {
// Get the rest if last
length = total - offset;
} else {
// Calculate length with offsets (substracting first offset)
length = responses.getOffsets().get(i + 1) - offset - responses.getOffsets().get(0);
}
ReadBuffer serviceBuf = new ReadBufferByteBased(read.getBytes(offset, offset + length), org.apache.plc4x.java.spi.generation.ByteOrder.LITTLE_ENDIAN);
CipService service = null;
try {
service = CipService.staticParse(read, length);
arr.add(service);
} catch (ParseException e) {
throw new PlcRuntimeException(e);
}
}
Services services = new Services(nb, responses.getOffsets(), arr, -1);
Iterator<String> it = readRequest.getFieldNames().iterator();
for (int i = 0; i < nb && it.hasNext(); i++) {
String fieldName = it.next();
EipField field = (EipField) readRequest.getField(fieldName);
PlcValue plcValue = null;
if (services.getServices().get(i) instanceof CipReadResponse) {
CipReadResponse readResponse = (CipReadResponse) services.getServices().get(i);
PlcResponseCode code;
if (readResponse.getStatus() == 0) {
code = PlcResponseCode.OK;
} else {
code = PlcResponseCode.INTERNAL_ERROR;
}
CIPDataTypeCode type = readResponse.getDataType();
ByteBuf data = Unpooled.wrappedBuffer(readResponse.getData());
if (code == PlcResponseCode.OK) {
plcValue = parsePlcValue(field, data, type);
}
ResponseItem<PlcValue> result = new ResponseItem<>(code, plcValue);
values.put(fieldName, result);
}
}
}
return new DefaultPlcReadResponse(readRequest, values);
}
Aggregations