use of org.apache.plc4x.java.eip.readwrite.field.EipField in project plc4x by apache.
the class EipProtocolLogic method decodeWriteResponse.
private PlcResponse decodeWriteResponse(CipService p, PlcWriteRequest writeRequest) {
Map<String, PlcResponseCode> responses = new HashMap<>();
if (p instanceof CipWriteResponse) {
CipWriteResponse resp = (CipWriteResponse) p;
String fieldName = writeRequest.getFieldNames().iterator().next();
EipField field = (EipField) writeRequest.getField(fieldName);
responses.put(fieldName, decodeResponseCode(resp.getStatus()));
return new DefaultPlcWriteResponse(writeRequest, responses);
} else if (p instanceof MultipleServiceResponse) {
MultipleServiceResponse resp = (MultipleServiceResponse) p;
int nb = resp.getServiceNb();
List<CipService> arr = new ArrayList<>(nb);
ReadBufferByteBased read = new ReadBufferByteBased(resp.getServicesData());
int total = (int) read.getTotalBytes();
for (int i = 0; i < nb; i++) {
int length = 0;
int offset = resp.getOffsets().get(i);
if (offset == nb - 1) {
// Get the rest if last
length = total - offset;
} else {
// Calculate length with offsets
length = resp.getOffsets().get(i + 1) - offset;
}
ReadBuffer serviceBuf = new ReadBufferByteBased(read.getBytes(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, resp.getOffsets(), arr, -1);
Iterator<String> it = writeRequest.getFieldNames().iterator();
for (int i = 0; i < nb && it.hasNext(); i++) {
String fieldName = it.next();
EipField field = (EipField) writeRequest.getField(fieldName);
PlcValue plcValue = null;
if (services.getServices().get(i) instanceof CipWriteResponse) {
CipWriteResponse writeResponse = (CipWriteResponse) services.getServices().get(i);
PlcResponseCode code = decodeResponseCode(writeResponse.getStatus());
responses.put(fieldName, code);
}
}
return new DefaultPlcWriteResponse(writeRequest, responses);
}
return null;
}
use of org.apache.plc4x.java.eip.readwrite.field.EipField in project plc4x by apache.
the class EipProtocolLogic method read.
@Override
public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest) {
DefaultPlcReadRequest request = (DefaultPlcReadRequest) readRequest;
List<CipReadRequest> requests = new ArrayList<>(request.getNumberOfFields());
for (PlcField field : request.getFields()) {
EipField plcField = (EipField) field;
String tag = plcField.getTag();
int elements = 1;
if (plcField.getElementNb() > 1) {
elements = plcField.getElementNb();
}
CipReadRequest req = new CipReadRequest(getRequestSize(tag), toAnsi(tag), elements, -1);
requests.add(req);
}
return toPlcReadResponse(readRequest, readInternal(requests));
}
use of org.apache.plc4x.java.eip.readwrite.field.EipField 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);
}
use of org.apache.plc4x.java.eip.readwrite.field.EipField in project plc4x by apache.
the class EipProtocolLogic method write.
@Override
public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
CompletableFuture<PlcWriteResponse> future = new CompletableFuture<>();
DefaultPlcWriteRequest request = (DefaultPlcWriteRequest) writeRequest;
List<CipWriteRequest> items = new ArrayList<>(writeRequest.getNumberOfFields());
for (String fieldName : request.getFieldNames()) {
final EipField field = (EipField) request.getField(fieldName);
final PlcValue value = request.getPlcValue(fieldName);
String tag = field.getTag();
int elements = 1;
if (field.getElementNb() > 1) {
elements = field.getElementNb();
}
// We need the size of the request in words (0x91, tagLength, ... tag + possible pad)
// Taking half to get word size
boolean isArray = false;
String tagIsolated = tag;
if (tag.contains("[")) {
isArray = true;
tagIsolated = tag.substring(0, tag.indexOf("["));
}
int dataLength = (tagIsolated.length() + 2 + (tagIsolated.length() % 2) + (isArray ? 2 : 0));
byte requestPathSize = (byte) (dataLength / 2);
byte[] data = encodeValue(value, field.getType(), (short) elements);
CipWriteRequest writeReq = new CipWriteRequest(requestPathSize, toAnsi(tag), field.getType(), elements, data, -1);
items.add(writeReq);
}
RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
if (items.size() == 1) {
tm.startRequest();
CipRRData rrdata = new CipRRData(sessionHandle, 0L, senderContext, 0L, new CipExchange(new CipUnconnectedRequest(items.get(0), (byte) configuration.getBackplane(), (byte) configuration.getSlot(), -1), -1), -1);
transaction.submit(() -> context.sendRequest(rrdata).expectResponse(EipPacket.class, REQUEST_TIMEOUT).onTimeout(future::completeExceptionally).onError((p, e) -> future.completeExceptionally(e)).check(p -> p instanceof CipRRData).unwrap(p -> (CipRRData) p).check(p -> p.getSessionHandle() == sessionHandle).check(p -> p.getExchange().getService() instanceof CipWriteResponse).unwrap(p -> (CipWriteResponse) p.getExchange().getService()).handle(p -> {
future.complete((PlcWriteResponse) decodeWriteResponse(p, writeRequest));
transaction.endRequest();
}));
} else {
tm.startRequest();
short nb = (short) items.size();
List<Integer> offsets = new ArrayList<>(nb);
int offset = 2 + nb * 2;
for (int i = 0; i < nb; i++) {
offsets.add(offset);
offset += items.get(i).getLengthInBytes();
}
List<CipService> serviceArr = new ArrayList<>(nb);
for (int i = 0; i < nb; i++) {
serviceArr.add(items.get(i));
}
Services data = new Services(nb, offsets, serviceArr, -1);
// Encapsulate the data
CipRRData pkt = new CipRRData(sessionHandle, 0L, emptySenderContext, 0L, new CipExchange(new CipUnconnectedRequest(new MultipleServiceRequest(data, -1), (byte) configuration.getBackplane(), (byte) configuration.getSlot(), -1), -1), -1);
transaction.submit(() -> context.sendRequest(pkt).expectResponse(EipPacket.class, REQUEST_TIMEOUT).onTimeout(future::completeExceptionally).onError((p, e) -> future.completeExceptionally(e)).check(p -> p instanceof CipRRData).check(p -> p.getSessionHandle() == sessionHandle).unwrap(p -> (CipRRData) p).unwrap(p -> p.getExchange().getService()).check(p -> p instanceof MultipleServiceResponse).unwrap(p -> (MultipleServiceResponse) p).check(p -> p.getServiceNb() == nb).handle(p -> {
future.complete((PlcWriteResponse) decodeWriteResponse(p, writeRequest));
// Finish the request-transaction.
transaction.endRequest();
}));
}
return future;
}
Aggregations