use of org.apache.plc4x.java.api.value.PlcValue in project plc4x by apache.
the class CANOpenProtocolLogic method writeInternally.
private void writeInternally(DefaultPlcWriteRequest writeRequest, CANOpenPDOField field, CompletableFuture<PlcWriteResponse> response) {
PlcValue writeValue = writeRequest.getPlcValues().get(0);
try {
String fieldName = writeRequest.getFieldNames().iterator().next();
WriteBufferByteBased writeBuffer = new WriteBufferByteBased(DataItem.getLengthInBytes(writeValue, field.getCanOpenDataType(), writeValue.getLength()), ByteOrder.LITTLE_ENDIAN);
DataItem.staticSerialize(writeBuffer, writeValue, field.getCanOpenDataType(), writeValue.getLength(), ByteOrder.LITTLE_ENDIAN);
final CANOpenPDOPayload payload = new CANOpenPDOPayload(new CANOpenPDO(writeBuffer.getData()));
context.sendToWire(new CANOpenFrame((short) field.getNodeId(), field.getService(), payload));
response.complete(new DefaultPlcWriteResponse(writeRequest, Collections.singletonMap(fieldName, PlcResponseCode.OK)));
} catch (Exception e) {
response.completeExceptionally(e);
}
}
use of org.apache.plc4x.java.api.value.PlcValue in project plc4x by apache.
the class Plc4x2AdsProtocol method decodeReadResponse.
@SuppressWarnings("unchecked")
private InternalPlcResponse decodeReadResponse(AdsReadResponse responseMessage, PlcRequestContainer<InternalPlcRequest, InternalPlcResponse> requestContainer) {
InternalPlcReadRequest plcReadRequest = (InternalPlcReadRequest) requestContainer.getRequest();
// TODO: only single requests supported for now
AdsField field = (AdsField) plcReadRequest.getFields().get(0);
PlcResponseCode responseCode = decodeResponseCode(responseMessage.getResult());
byte[] bytes = responseMessage.getData().getBytes();
PlcValue value = decodeData(field.getAdsDataType(), bytes);
// TODO: does every item has the same ads response or is this whole aggregation broken?
Map<String, Pair<PlcResponseCode, PlcValue>> responseItems = plcReadRequest.getFieldNames().stream().collect(Collectors.toMap(fieldName -> fieldName, ignore -> Pair.of(responseCode, value)));
return new DefaultPlcReadResponse(plcReadRequest, responseItems);
}
use of org.apache.plc4x.java.api.value.PlcValue in project plc4x by apache.
the class Plc4x2AdsProtocol method encodeWriteRequest.
private void encodeWriteRequest(PlcRequestContainer<InternalPlcRequest, InternalPlcResponse> msg, List<Object> out) throws PlcException {
InternalPlcWriteRequest writeRequest = (InternalPlcWriteRequest) msg.getRequest();
if (writeRequest.getFields().size() != 1) {
throw new PlcProtocolException("Only one item supported");
}
PlcField field = writeRequest.getFields().get(0);
if (field instanceof SymbolicAdsField) {
DirectAdsField mappedField = fieldMapping.get(field);
LOGGER.debug("Replacing {} with {}", field, mappedField);
field = mappedField;
}
if (!(field instanceof DirectAdsField)) {
throw new PlcProtocolException("PlcField not of type DirectAdsField: " + field.getClass());
}
DirectAdsField directAdsField = (DirectAdsField) field;
Invoke invokeId = Invoke.of(correlationBuilder.incrementAndGet());
IndexGroup indexGroup = IndexGroup.of(directAdsField.getIndexGroup());
IndexOffset indexOffset = IndexOffset.of(directAdsField.getIndexOffset());
Object[] plcValues;
PlcValue plcValue = writeRequest.getPlcValues().get(0);
if (plcValue instanceof PlcList) {
plcValues = ((PlcList) plcValue).getList().toArray(new Object[0]);
} else {
plcValues = new Object[] { plcValue.getObject() };
}
byte[] bytes = encodeData(directAdsField.getAdsDataType(), plcValues);
int bytesToBeWritten = bytes.length;
int maxTheoreticalSize = directAdsField.getAdsDataType().getTargetByteSize() * directAdsField.getNumberOfElements();
if (bytesToBeWritten > maxTheoreticalSize) {
LOGGER.debug("Requested AdsDatatype {} is exceeded by number of bytes {}. Limit {}.", directAdsField.getAdsDataType(), bytesToBeWritten, maxTheoreticalSize);
throw new PlcProtocolPayloadTooBigException("ADS", maxTheoreticalSize, bytesToBeWritten, plcValues);
}
Data data = Data.of(bytes);
AmsPacket amsPacket = AdsWriteRequest.of(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, indexGroup, indexOffset, data);
LOGGER.debug("encoded write request {}", amsPacket);
out.add(amsPacket);
requests.put(invokeId.getAsLong(), msg);
}
use of org.apache.plc4x.java.api.value.PlcValue 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.api.value.PlcValue in project plc4x by apache.
the class S7Optimizer method processWriteRequest.
@Override
protected List<PlcRequest> processWriteRequest(PlcWriteRequest writeRequest, DriverContext driverContext) {
S7DriverContext s7DriverContext = (S7DriverContext) driverContext;
List<PlcRequest> processedRequests = new LinkedList<>();
// This calculates the size of the header for the request and response.
int curRequestSize = EMPTY_WRITE_REQUEST_SIZE;
// An empty response has the same size as an empty request.
int curResponseSize = EMPTY_WRITE_RESPONSE_SIZE;
// List of all items in the current request.
LinkedHashMap<String, FieldValueItem> curFields = new LinkedHashMap<>();
for (String fieldName : writeRequest.getFieldNames()) {
S7Field field = (S7Field) writeRequest.getField(fieldName);
PlcValue value = writeRequest.getPlcValue(fieldName);
int writeRequestItemSize = S7_ADDRESS_ANY_SIZE + 4;
if (field.getDataType() == TransportSize.BOOL) {
writeRequestItemSize += Math.ceil((double) field.getNumberOfElements() / 8);
} else {
writeRequestItemSize += (field.getNumberOfElements() * field.getDataType().getSizeInBytes());
}
// If it's an odd number of bytes, add one to make it even
if (writeRequestItemSize % 2 == 1) {
writeRequestItemSize++;
}
int writeResponseItemSize = 4;
// If adding the item would not exceed the sizes, add it to the current request.
if (((curRequestSize + writeRequestItemSize) <= s7DriverContext.getPduSize()) && ((curResponseSize + writeResponseItemSize) <= s7DriverContext.getPduSize())) {
// Increase the current request sizes.
curRequestSize += writeRequestItemSize;
curResponseSize += writeResponseItemSize;
// Add the item.
} else // If adding them would exceed, start a new request.
{
// Create a new PlcWriteRequest containing the current field item.
processedRequests.add(new DefaultPlcWriteRequest(((DefaultPlcWriteRequest) writeRequest).getWriter(), curFields));
// Reset the size and item lists.
curRequestSize = EMPTY_WRITE_REQUEST_SIZE + writeRequestItemSize;
curResponseSize = EMPTY_WRITE_RESPONSE_SIZE + writeResponseItemSize;
curFields = new LinkedHashMap<>();
// Splitting of huge fields not yet implemented, throw an exception instead.
if (((curRequestSize + writeRequestItemSize) > s7DriverContext.getPduSize()) && ((curResponseSize + writeResponseItemSize) > s7DriverContext.getPduSize())) {
throw new PlcRuntimeException("Field size exceeds maximum payload for one item.");
}
}
curFields.put(fieldName, new FieldValueItem(field, value));
}
// Create a new PlcWriteRequest from the remaining field items.
if (!curFields.isEmpty()) {
processedRequests.add(new DefaultPlcWriteRequest(((DefaultPlcWriteRequest) writeRequest).getWriter(), curFields));
}
return processedRequests;
}
Aggregations