use of org.apache.plc4x.java.api.messages.PlcReadRequest in project plc4x by apache.
the class AbEthProtocolLogic method read.
@Override
public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest) {
// TODO: Warning ... we are senging one request per field ... the result has to be merged back together ...
for (String fieldName : readRequest.getFieldNames()) {
PlcField field = readRequest.getField(fieldName);
if (!(field instanceof AbEthField)) {
logger.error("The field should have been of type AbEthField");
}
AbEthField abEthField = (AbEthField) field;
DF1RequestProtectedTypedLogicalRead logicalRead = new DF1RequestProtectedTypedLogicalRead(abEthField.getByteSize(), abEthField.getFileNumber(), abEthField.getFileType().getTypeCode(), abEthField.getElementNumber(), // Subelementnumber default to zero
(short) 0);
final int transactionCounter = transactionCounterGenerator.incrementAndGet();
// If we've reached the max value for a 16 bit transaction identifier, reset back to 1
if (transactionCounterGenerator.get() == 0xFFFF) {
transactionCounterGenerator.set(1);
}
// origin/sender: constant = 5
DF1RequestMessage requestMessage = new DF1CommandRequestMessage((short) configuration.getStation(), (short) 5, (short) 0, transactionCounter, logicalRead);
CIPEncapsulationReadRequest read = new CIPEncapsulationReadRequest(sessionHandle, 0, emptySenderContext, 0, requestMessage);
CompletableFuture<PlcReadResponse> future = new CompletableFuture<>();
RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
transaction.submit(() -> context.sendRequest(read).expectResponse(CIPEncapsulationPacket.class, REQUEST_TIMEOUT).onTimeout(future::completeExceptionally).onError((p, e) -> future.completeExceptionally(e)).check(p -> p instanceof CIPEncapsulationReadResponse).unwrap(p -> (CIPEncapsulationReadResponse) p).check(p -> p.getResponse().getTransactionCounter() == transactionCounter).handle(p -> {
PlcResponse response = decodeReadResponse(p, readRequest);
// TODO: Not sure how to merge things back together ...
// future.complete(response);
// Finish the request-transaction.
transaction.endRequest();
// future.complete(((PlcReadResponse) decodeReadResponse(p, ((InternalPlcReadRequest) readRequest))));
}));
// TODO: This aborts reading other fields after sending the first fields request ... refactor.
return future;
}
// TODO: Should return an aggregated future ....
return null;
}
use of org.apache.plc4x.java.api.messages.PlcReadRequest in project plc4x by apache.
the class Plc4xAbEthProtocol method encode.
@Override
protected void encode(ChannelHandlerContext ctx, PlcRequestContainer msg, List<Object> out) throws Exception {
logger.trace("Encoding {}", msg);
PlcRequest request = msg.getRequest();
// reset counter since two byte values are possible in DF1
if (transactionCounterGenerator.get() > 65000) {
transactionCounterGenerator.set(10);
}
if (request instanceof PlcReadRequest) {
PlcReadRequest readRequest = (PlcReadRequest) msg.getRequest();
for (String fieldName : readRequest.getFieldNames()) {
PlcField field = readRequest.getField(fieldName);
if (!(field instanceof AbEthField)) {
throw new PlcProtocolException("The field should have been of type AbEthField");
}
AbEthField abEthField = (AbEthField) field;
DF1RequestProtectedTypedLogicalRead logicalRead = new DF1RequestProtectedTypedLogicalRead(abEthField.getByteSize(), abEthField.getFileNumber(), abEthField.getFileType().getTypeCode(), abEthField.getElementNumber(), // Subelementnumber default to zero
(short) 0);
// origin/sender: constant = 5
DF1RequestMessage requestMessage = new DF1CommandRequestMessage((short) station, (short) 5, (short) 0, transactionCounterGenerator.incrementAndGet(), logicalRead);
CIPEncapsulationReadRequest read = new CIPEncapsulationReadRequest(sessionHandle, 0, emptySenderContext, 0, requestMessage);
requests.put(requestMessage.getTransactionCounter(), msg);
out.add(read);
}
} else {
ctx.fireExceptionCaught(new PlcProtocolException("Unsupported request type " + request.getClass().getName()));
}
}
use of org.apache.plc4x.java.api.messages.PlcReadRequest in project plc4x by apache.
the class Plc4xCommunication method getValue.
public DataValue getValue(AttributeFilterContext.GetAttributeContext ctx, String tag, String connectionString) {
PlcConnection connection = null;
try {
// Check if we just polled the connection and it failed. Wait for the backoff counter to expire before we try again.
if (failedConnectionList.containsKey(connectionString)) {
if (System.currentTimeMillis() > failedConnectionList.get(connectionString) + DEFAULT_RETRY_BACKOFF) {
failedConnectionList.remove(connectionString);
} else {
logger.debug("Waiting for back off timer - " + ((failedConnectionList.get(connectionString) + DEFAULT_RETRY_BACKOFF) - System.currentTimeMillis()) + " ms left");
return BAD_RESPONSE;
}
}
// Try to connect to PLC
try {
connection = driverManager.getConnection(connectionString);
logger.debug(connectionString + " Connected");
} catch (PlcConnectionException e) {
logger.error("Failed to connect to device, error raised - " + e);
failedConnectionList.put(connectionString, System.currentTimeMillis());
return BAD_RESPONSE;
}
if (!connection.getMetadata().canRead()) {
logger.error("This connection doesn't support reading.");
try {
connection.close();
} catch (Exception exception) {
logger.warn("Closing connection failed with error - " + exception);
}
return BAD_RESPONSE;
}
long timeout = DEFAULT_TIMEOUT;
if (monitoredList.containsKey(ctx.getNode().getNodeId())) {
timeout = (long) monitoredList.get(ctx.getNode().getNodeId()).getSamplingInterval() * 1000;
}
// Create a new read request:
// - Give the single item requested an alias name
PlcReadRequest.Builder builder = connection.readRequestBuilder();
builder.addItem("value-1", tag);
PlcReadRequest readRequest = builder.build();
PlcReadResponse response = null;
try {
response = readRequest.execute().get(timeout, TimeUnit.MICROSECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
logger.warn(e + " Occurred while reading value, using timeout of " + timeout / 1000 + "ms");
try {
connection.close();
} catch (Exception exception) {
logger.warn("Closing connection failed with error - " + exception);
}
return BAD_RESPONSE;
}
DataValue resp = BAD_RESPONSE;
for (String fieldName : response.getFieldNames()) {
if (response.getResponseCode(fieldName) == PlcResponseCode.OK) {
int numValues = response.getNumberOfValues(fieldName);
if (numValues == 1) {
if (response.getObject(fieldName) instanceof BigInteger) {
resp = new DataValue(new Variant(ulong((BigInteger) response.getObject(fieldName))), StatusCode.GOOD);
} else {
resp = new DataValue(new Variant(response.getObject(fieldName)), StatusCode.GOOD);
}
} else {
Object array = null;
if (response.getObject(fieldName, 0) instanceof BigInteger) {
array = Array.newInstance(ULong.class, numValues);
} else {
array = Array.newInstance(response.getObject(fieldName, 0).getClass(), numValues);
}
for (int i = 0; i < numValues; i++) {
if (response.getObject(fieldName, i) instanceof BigInteger) {
Array.set(array, i, ulong((BigInteger) response.getObject(fieldName, i)));
} else {
Array.set(array, i, response.getObject(fieldName, i));
}
}
resp = new DataValue(new Variant(array), StatusCode.GOOD);
}
}
}
try {
connection.close();
} catch (Exception e) {
failedConnectionList.put(connectionString, System.currentTimeMillis());
logger.warn("Closing connection failed with error " + e);
}
return resp;
} catch (Exception e) {
logger.warn("General error reading value " + e.getStackTrace()[0].toString());
if (connection != null) {
try {
connection.close();
} catch (Exception ex) {
// Do Nothing
}
}
return BAD_RESPONSE;
}
}
use of org.apache.plc4x.java.api.messages.PlcReadRequest in project plc4x by apache.
the class Plc4xSourceProcessor method onTrigger.
@Override
public void onTrigger(final ProcessContext context, final ProcessSession session) throws ProcessException {
// Get an instance of a component able to read from a PLC.
try (PlcConnection connection = getDriverManager().getConnection(getConnectionString())) {
// Prepare the request.
if (!connection.getMetadata().canRead()) {
throw new ProcessException("Writing not supported by connection");
}
FlowFile flowFile = session.create();
try {
PlcReadRequest.Builder builder = connection.readRequestBuilder();
getFields().forEach(field -> {
String address = getAddress(field);
if (address != null) {
builder.addItem(field, address);
}
});
PlcReadRequest readRequest = builder.build();
PlcReadResponse response = readRequest.execute().get();
Map<String, String> attributes = new HashMap<>();
for (String fieldName : response.getFieldNames()) {
for (int i = 0; i < response.getNumberOfValues(fieldName); i++) {
Object value = response.getObject(fieldName, i);
attributes.put(fieldName, String.valueOf(value));
}
}
flowFile = session.putAllAttributes(flowFile, attributes);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new ProcessException(e);
} catch (ExecutionException e) {
throw new ProcessException(e);
}
session.transfer(flowFile, SUCCESS);
} catch (ProcessException e) {
throw e;
} catch (Exception e) {
throw new ProcessException("Got an error while trying to get a connection", e);
}
}
use of org.apache.plc4x.java.api.messages.PlcReadRequest in project plc4x by apache.
the class Plc4x2AdsProtocol method encodeReadRequest.
private void encodeReadRequest(PlcRequestContainer<InternalPlcRequest, InternalPlcResponse> msg, List<Object> out) throws PlcException {
PlcReadRequest readRequest = (PlcReadRequest) msg.getRequest();
if (readRequest.getFields().size() != 1) {
throw new PlcProtocolException("Only one item supported");
}
PlcField field = readRequest.getFields().get(0);
if (field instanceof SymbolicAdsField) {
DirectAdsField mappedField = fieldMapping.get(field);
if (mappedField == null) {
throw new PlcProtocolException("No field mapping for " + 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());
AdsDataType adsDataType = directAdsField.getAdsDataType();
int numberOfElements = directAdsField.getNumberOfElements();
int readLength = adsDataType.getTargetByteSize() * numberOfElements;
Length length = Length.of(readLength);
AmsPacket amsPacket = AdsReadRequest.of(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, indexGroup, indexOffset, length);
LOGGER.debug("encoded read request {}", amsPacket);
out.add(amsPacket);
requests.put(invokeId.getAsLong(), msg);
}
Aggregations