use of org.apache.plc4x.java.api.types.PlcResponseCode in project plc4x by apache.
the class OpcuaProtocolLogic method readResponse.
public Map<String, ResponseItem<PlcValue>> readResponse(LinkedHashSet<String> fieldNames, List<DataValue> results) {
PlcResponseCode responseCode = PlcResponseCode.OK;
Map<String, ResponseItem<PlcValue>> response = new HashMap<>();
int count = 0;
for (String field : fieldNames) {
PlcValue value = null;
if (results.get(count).getValueSpecified()) {
Variant variant = results.get(count).getValue();
LOGGER.trace("Response of type {}", variant.getClass().toString());
if (variant instanceof VariantBoolean) {
byte[] array = ((VariantBoolean) variant).getValue();
int length = array.length;
Boolean[] tmpValue = new Boolean[length];
for (int i = 0; i < length; i++) {
tmpValue[i] = array[i] != 0;
}
value = IEC61131ValueHandler.of(tmpValue);
} else if (variant instanceof VariantSByte) {
byte[] array = ((VariantSByte) variant).getValue();
value = IEC61131ValueHandler.of(array);
} else if (variant instanceof VariantByte) {
List<Short> array = ((VariantByte) variant).getValue();
Short[] tmpValue = array.toArray(new Short[0]);
value = IEC61131ValueHandler.of(tmpValue);
} else if (variant instanceof VariantInt16) {
List<Short> array = ((VariantInt16) variant).getValue();
Short[] tmpValue = array.toArray(new Short[0]);
value = IEC61131ValueHandler.of(tmpValue);
} else if (variant instanceof VariantUInt16) {
List<Integer> array = ((VariantUInt16) variant).getValue();
Integer[] tmpValue = array.toArray(new Integer[0]);
value = IEC61131ValueHandler.of(tmpValue);
} else if (variant instanceof VariantInt32) {
List<Integer> array = ((VariantInt32) variant).getValue();
Integer[] tmpValue = array.toArray(new Integer[0]);
value = IEC61131ValueHandler.of(tmpValue);
} else if (variant instanceof VariantUInt32) {
List<Long> array = ((VariantUInt32) variant).getValue();
Long[] tmpValue = array.toArray(new Long[0]);
value = IEC61131ValueHandler.of(tmpValue);
} else if (variant instanceof VariantInt64) {
List<Long> array = ((VariantInt64) variant).getValue();
Long[] tmpValue = array.toArray(new Long[0]);
value = IEC61131ValueHandler.of(tmpValue);
} else if (variant instanceof VariantUInt64) {
value = IEC61131ValueHandler.of(((VariantUInt64) variant).getValue());
} else if (variant instanceof VariantFloat) {
List<Float> array = ((VariantFloat) variant).getValue();
Float[] tmpValue = array.toArray(new Float[0]);
value = IEC61131ValueHandler.of(tmpValue);
} else if (variant instanceof VariantDouble) {
List<Double> array = ((VariantDouble) variant).getValue();
Double[] tmpValue = array.toArray(new Double[0]);
value = IEC61131ValueHandler.of(tmpValue);
} else if (variant instanceof VariantString) {
int length = ((VariantString) variant).getValue().size();
List<PascalString> stringArray = ((VariantString) variant).getValue();
String[] tmpValue = new String[length];
for (int i = 0; i < length; i++) {
tmpValue[i] = stringArray.get(i).getStringValue();
}
value = IEC61131ValueHandler.of(tmpValue);
} else if (variant instanceof VariantDateTime) {
List<Long> array = ((VariantDateTime) variant).getValue();
int length = array.size();
LocalDateTime[] tmpValue = new LocalDateTime[length];
for (int i = 0; i < length; i++) {
tmpValue[i] = LocalDateTime.ofInstant(Instant.ofEpochMilli(getDateTime(array.get(i))), ZoneOffset.UTC);
}
value = IEC61131ValueHandler.of(tmpValue);
} else if (variant instanceof VariantGuid) {
List<GuidValue> array = ((VariantGuid) variant).getValue();
int length = array.size();
String[] tmpValue = new String[length];
for (int i = 0; i < length; i++) {
// These two data section aren't little endian like the rest.
byte[] data4Bytes = array.get(i).getData4();
int data4 = 0;
for (byte data4Byte : data4Bytes) {
data4 = (data4 << 8) + (data4Byte & 0xff);
}
byte[] data5Bytes = array.get(i).getData5();
long data5 = 0;
for (byte data5Byte : data5Bytes) {
data5 = (data5 << 8) + (data5Byte & 0xff);
}
tmpValue[i] = Long.toHexString(array.get(i).getData1()) + "-" + Integer.toHexString(array.get(i).getData2()) + "-" + Integer.toHexString(array.get(i).getData3()) + "-" + Integer.toHexString(data4) + "-" + Long.toHexString(data5);
}
value = IEC61131ValueHandler.of(tmpValue);
} else if (variant instanceof VariantXmlElement) {
int length = ((VariantXmlElement) variant).getValue().size();
List<PascalString> strings = ((VariantXmlElement) variant).getValue();
String[] tmpValue = new String[length];
for (int i = 0; i < length; i++) {
tmpValue[i] = strings.get(i).getStringValue();
}
value = IEC61131ValueHandler.of(tmpValue);
} else if (variant instanceof VariantLocalizedText) {
int length = ((VariantLocalizedText) variant).getValue().size();
List<LocalizedText> strings = ((VariantLocalizedText) variant).getValue();
String[] tmpValue = new String[length];
for (int i = 0; i < length; i++) {
tmpValue[i] = "";
tmpValue[i] += strings.get(i).getLocaleSpecified() ? strings.get(i).getLocale().getStringValue() + "|" : "";
tmpValue[i] += strings.get(i).getTextSpecified() ? strings.get(i).getText().getStringValue() : "";
}
value = IEC61131ValueHandler.of(tmpValue);
} else if (variant instanceof VariantQualifiedName) {
int length = ((VariantQualifiedName) variant).getValue().size();
List<QualifiedName> strings = ((VariantQualifiedName) variant).getValue();
String[] tmpValue = new String[length];
for (int i = 0; i < length; i++) {
tmpValue[i] = "ns=" + strings.get(i).getNamespaceIndex() + ";s=" + strings.get(i).getName().getStringValue();
}
value = IEC61131ValueHandler.of(tmpValue);
} else if (variant instanceof VariantExtensionObject) {
int length = ((VariantExtensionObject) variant).getValue().size();
List<ExtensionObject> strings = ((VariantExtensionObject) variant).getValue();
String[] tmpValue = new String[length];
for (int i = 0; i < length; i++) {
tmpValue[i] = strings.get(i).toString();
}
value = IEC61131ValueHandler.of(tmpValue);
} else if (variant instanceof VariantNodeId) {
int length = ((VariantNodeId) variant).getValue().size();
List<NodeId> strings = ((VariantNodeId) variant).getValue();
String[] tmpValue = new String[length];
for (int i = 0; i < length; i++) {
tmpValue[i] = strings.get(i).toString();
}
value = IEC61131ValueHandler.of(tmpValue);
} else if (variant instanceof VariantStatusCode) {
int length = ((VariantStatusCode) variant).getValue().size();
List<StatusCode> strings = ((VariantStatusCode) variant).getValue();
String[] tmpValue = new String[length];
for (int i = 0; i < length; i++) {
tmpValue[i] = strings.get(i).toString();
}
value = IEC61131ValueHandler.of(tmpValue);
} else if (variant instanceof VariantByteString) {
PlcList plcList = new PlcList();
List<ByteStringArray> array = ((VariantByteString) variant).getValue();
for (int k = 0; k < array.size(); k++) {
int length = array.get(k).getValue().size();
Short[] tmpValue = new Short[length];
for (int i = 0; i < length; i++) {
tmpValue[i] = array.get(k).getValue().get(i);
}
plcList.add(IEC61131ValueHandler.of(tmpValue));
}
value = plcList;
} else {
responseCode = PlcResponseCode.UNSUPPORTED;
LOGGER.error("Data type - " + variant.getClass() + " is not supported ");
}
} else {
if (results.get(count).getStatusCode().getStatusCode() == OpcuaStatusCode.BadNodeIdUnknown.getValue()) {
responseCode = PlcResponseCode.NOT_FOUND;
} else {
responseCode = PlcResponseCode.UNSUPPORTED;
}
LOGGER.error("Error while reading value from OPC UA server error code:- " + results.get(count).getStatusCode().toString());
}
count++;
response.put(field, new ResponseItem<>(responseCode, value));
}
return response;
}
use of org.apache.plc4x.java.api.types.PlcResponseCode in project plc4x by apache.
the class KnxNetIpProtocolLogic method write.
@Override
public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
CompletableFuture<PlcWriteResponse> future = new CompletableFuture<>();
DefaultPlcWriteRequest request = (DefaultPlcWriteRequest) writeRequest;
// As the KNX driver is using the SingleFieldOptimizer, each request here will have
// only one item.
final Optional<String> first = request.getFieldNames().stream().findFirst();
if (first.isPresent()) {
String fieldName = first.get();
final KnxNetIpField field = (KnxNetIpField) request.getField(fieldName);
byte[] destinationAddress = toKnxAddressData(field);
if (sequenceCounter.get() == Short.MAX_VALUE) {
sequenceCounter.set(0);
}
// Convert the PlcValue to byte data.
final PlcValue value = request.getPlcValue(fieldName);
byte dataFirstByte = 0;
byte[] data = null;
final EtsModel etsModel = knxNetIpDriverContext.getEtsModel();
if (etsModel != null) {
final String destinationAddressString = etsModel.parseGroupAddress(destinationAddress);
final GroupAddress groupAddress = etsModel.getGroupAddresses().get(destinationAddressString);
if ((groupAddress == null) || (groupAddress.getType() == null)) {
future.completeExceptionally(new PlcRuntimeException("ETS5 model didn't specify group address '" + destinationAddressString + "' or didn't define a type for it."));
return future;
}
// Use the data in the ets model to correctly check and serialize the PlcValue
try {
final WriteBufferByteBased writeBuffer = new WriteBufferByteBased(KnxDatapoint.getLengthInBytes(value, groupAddress.getType()));
KnxDatapoint.staticSerialize(writeBuffer, value, groupAddress.getType());
final byte[] serialized = writeBuffer.getData();
dataFirstByte = serialized[0];
data = new byte[serialized.length - 1];
System.arraycopy(serialized, 1, data, 0, serialized.length - 1);
} catch (SerializationException e) {
future.completeExceptionally(new PlcRuntimeException("Error serializing PlcValue.", e));
return future;
}
} else {
if (value.isByte()) {
if ((value.getByte() > 63) || (value.getByte() < 0)) {
future.completeExceptionally(new PlcRuntimeException("If no ETS5 model is provided, value of the first byte must be between 0 and 63."));
return future;
}
dataFirstByte = value.getByte();
} else if (value.isList()) {
// Check each item of the list, if it's also a byte.
List<? extends PlcValue> list = value.getList();
// TODO: This could cause an exception.
data = new byte[list.size() - 1];
boolean allValuesAreBytes = !list.isEmpty();
int numByte = 0;
for (PlcValue plcValue : list) {
if (numByte == 0) {
if (!plcValue.isByte() && (plcValue.getByte() > 63) || (plcValue.getByte() < 0)) {
allValuesAreBytes = false;
break;
}
dataFirstByte = plcValue.getByte();
} else {
if (!plcValue.isByte()) {
allValuesAreBytes = false;
break;
}
data[numByte - 1] = plcValue.getByte();
}
numByte++;
}
if (!allValuesAreBytes) {
future.completeExceptionally(new PlcRuntimeException("If no ETS5 model is provided, the only supported type for writing data is writing of single byte or list of bytes and the value of the first byte must be between 0 and 63."));
return future;
}
} else {
future.completeExceptionally(new PlcRuntimeException("If no ETS5 model is provided, the only supported type for writing data is writing of single byte or list of bytes."));
return future;
}
}
final short communicationChannelId = knxNetIpDriverContext.getCommunicationChannelId();
// Prepare the knx request message.
TunnelingRequest knxRequest = new TunnelingRequest(new TunnelingRequestDataBlock(communicationChannelId, (short) sequenceCounter.getAndIncrement()), new LDataReq((short) 0, new ArrayList<>(0), new LDataExtended(false, false, CEMIPriority.LOW, false, false, true, (byte) 6, (byte) 0, knxNetIpDriverContext.getClientKnxAddress(), destinationAddress, new ApduDataContainer(true, (byte) 0, new ApduDataGroupValueWrite(dataFirstByte, data, (short) -1), (short) -1)), -1), -1);
// Start a new request-transaction (Is ended in the response-handler)
RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
// Start a new request-transaction (Is ended in the response-handler)
transaction.submit(() -> context.sendRequest(knxRequest).expectResponse(KnxNetIpMessage.class, REQUEST_TIMEOUT).onTimeout(future::completeExceptionally).onError((tr, e) -> future.completeExceptionally(e)).check(tr -> tr instanceof TunnelingResponse).unwrap(tr -> ((TunnelingResponse) tr)).check(tr -> tr.getTunnelingResponseDataBlock().getCommunicationChannelId() == knxRequest.getTunnelingRequestDataBlock().getCommunicationChannelId()).check(tr -> tr.getTunnelingResponseDataBlock().getSequenceCounter() == knxRequest.getTunnelingRequestDataBlock().getSequenceCounter()).handle(tr -> {
PlcResponseCode responseCode;
// In this case all went well.
if (tr.getTunnelingResponseDataBlock().getStatus() == Status.NO_ERROR) {
responseCode = PlcResponseCode.OK;
} else // TODO: Should probably differentiate a bit on this and not treat everything as internal error.
{
responseCode = PlcResponseCode.INTERNAL_ERROR;
}
// Prepare the response.
PlcWriteResponse response = new DefaultPlcWriteResponse(request, Collections.singletonMap(fieldName, responseCode));
future.complete(response);
// Finish the request-transaction.
transaction.endRequest();
}));
}
return future;
}
use of org.apache.plc4x.java.api.types.PlcResponseCode in project plc4x by apache.
the class ModbusTcpProtocolLogic 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));
int transactionIdentifier = transactionIdentifierGenerator.getAndIncrement();
// If we've reached the max value for a 16 bit transaction identifier, reset back to 1
if (transactionIdentifierGenerator.get() == 0xFFFF) {
transactionIdentifierGenerator.set(1);
}
ModbusTcpADU modbusTcpADU = new ModbusTcpADU(transactionIdentifier, unitIdentifier, requestPdu, false);
RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
transaction.submit(() -> context.sendRequest(modbusTcpADU).expectResponse(ModbusTcpADU.class, requestTimeout).onTimeout(future::completeExceptionally).onError((p, e) -> future.completeExceptionally(e)).check(p -> p.getTransactionIdentifier() == transactionIdentifier).unwrap(ModbusTcpADU::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 Plc4xProtocolLogic method read.
@Override
public CompletableFuture<PlcReadResponse> read(PlcReadRequest apiReadRequest) {
CompletableFuture<PlcReadResponse> future = new CompletableFuture<>();
// Prepare the request.
List<Plc4xFieldRequest> plc4xFields = new ArrayList<>(apiReadRequest.getNumberOfFields());
for (String fieldName : apiReadRequest.getFieldNames()) {
final org.apache.plc4x.java.plc4x.field.Plc4xField plc4xField = (org.apache.plc4x.java.plc4x.field.Plc4xField) apiReadRequest.getField(fieldName);
Plc4xFieldRequest plc4xFieldRequest = new Plc4xFieldRequest(new Plc4xField(fieldName, plc4xField.getAddress() + ":" + plc4xField.getPlcDataType()));
plc4xFields.add(plc4xFieldRequest);
}
final int requestId = txIdGenerator.getAndIncrement();
Plc4xReadRequest plc4xReadRequest = new Plc4xReadRequest(requestId, connectionId, plc4xFields);
// Send the request and await a response.
RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
context.sendRequest(plc4xReadRequest).expectResponse(Plc4xMessage.class, requestTimeout).onTimeout(future::completeExceptionally).check(plc4xMessage -> plc4xMessage.getRequestId() == requestId).unwrap(plc4xMessage -> (Plc4xReadResponse) plc4xMessage).check(plc4xReadResponse -> plc4xReadResponse.getConnectionId() == connectionId).handle(plc4xReadResponse -> {
Map<String, ResponseItem<PlcValue>> apiResponses = new HashMap<>();
// Create the API response from the incoming message.
for (Plc4xFieldValueResponse plc4xField : plc4xReadResponse.getFields()) {
final Plc4xResponseCode plc4xResponseCode = plc4xField.getResponseCode();
final PlcResponseCode apiResponseCode = PlcResponseCode.valueOf(plc4xResponseCode.name());
apiResponses.put(plc4xField.getField().getName(), new ResponseItem<>(apiResponseCode, plc4xField.getValue()));
}
// Send it back to the calling process.
future.complete(new DefaultPlcReadResponse(apiReadRequest, apiResponses));
// Finish the request-transaction.
transaction.endRequest();
});
return future;
}
use of org.apache.plc4x.java.api.types.PlcResponseCode in project plc4x by apache.
the class Plc4xProtocolLogic method write.
@Override
public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
CompletableFuture<PlcWriteResponse> future = new CompletableFuture<>();
// Prepare the request.
List<Plc4xFieldValueRequest> fields = new ArrayList<>(writeRequest.getNumberOfFields());
for (String fieldName : writeRequest.getFieldNames()) {
final org.apache.plc4x.java.plc4x.field.Plc4xField plc4xField = (org.apache.plc4x.java.plc4x.field.Plc4xField) writeRequest.getField(fieldName);
final Plc4xValueType plc4xValueType = plc4xField.getValueType();
final PlcValue plcValue = writeRequest.getPlcValue(fieldName);
Plc4xFieldValueRequest fieldRequest = new Plc4xFieldValueRequest(new Plc4xField(fieldName, plc4xField.getAddress() + ":" + plc4xField.getPlcDataType()), plc4xValueType, plcValue);
fields.add(fieldRequest);
}
final int requestId = txIdGenerator.getAndIncrement();
Plc4xWriteRequest write = new Plc4xWriteRequest(requestId, connectionId, fields);
// Send the request and await a response.
RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
context.sendRequest(write).expectResponse(Plc4xMessage.class, requestTimeout).onTimeout(future::completeExceptionally).check(p -> p.getRequestId() == requestId).unwrap(plc4xMessage -> (Plc4xWriteResponse) plc4xMessage).check(plc4xReadResponse -> plc4xReadResponse.getConnectionId() == connectionId).handle(plc4xWriteResponse -> {
Map<String, PlcResponseCode> apiResponses = new HashMap<>();
// Create the API response from the incoming message.
for (Plc4xFieldResponse plc4xField : plc4xWriteResponse.getFields()) {
final Plc4xResponseCode plc4xResponseCode = plc4xField.getResponseCode();
final PlcResponseCode apiResponseCode = PlcResponseCode.valueOf(plc4xResponseCode.name());
apiResponses.put(plc4xField.getField().getName(), apiResponseCode);
}
// Send it back to the calling process.
future.complete(new DefaultPlcWriteResponse(writeRequest, apiResponses));
// Finish the request-transaction.
transaction.endRequest();
});
return future;
}
Aggregations