All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ar4k.agent.opcua.client.OpcUaGroupManager Maven / Gradle / Ivy

package org.ar4k.agent.opcua.client;

import static com.google.common.collect.Lists.newArrayList;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;

import org.ar4k.agent.core.data.channels.IPublishSubscribeChannel;
import org.ar4k.agent.core.data.messages.IndustrialMessage;
import org.ar4k.agent.core.data.messages.IndustrialPayload;
import org.ar4k.agent.core.data.messages.IndustrialPayload.DataType;
import org.ar4k.agent.core.data.messages.IndustrialPayload.Quality;
import org.ar4k.agent.core.interfaces.EdgeChannel;
import org.ar4k.agent.helper.ConfigHelper;
import org.ar4k.agent.industrial.Enumerator.DataChangeTrigger;
import org.ar4k.agent.industrial.Enumerator.DeadbandType;
import org.ar4k.agent.logger.EdgeLogger;
import org.ar4k.agent.logger.EdgeStaticLoggerBinder;
import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaMonitoredItem;
import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaMonitoredItem.ValueConsumer;
import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaSubscription;
import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaSubscription.ItemCreationCallback;
import org.eclipse.milo.opcua.stack.core.AttributeId;
import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
import org.eclipse.milo.opcua.stack.core.types.builtin.ExtensionObject;
import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
import org.eclipse.milo.opcua.stack.core.types.builtin.QualifiedName;
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
import org.eclipse.milo.opcua.stack.core.types.enumerated.MonitoringMode;
import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
import org.eclipse.milo.opcua.stack.core.types.structured.DataChangeFilter;
import org.eclipse.milo.opcua.stack.core.types.structured.MonitoredItemCreateRequest;
import org.eclipse.milo.opcua.stack.core.types.structured.MonitoringParameters;
import org.eclipse.milo.opcua.stack.core.types.structured.ReadValueId;

public class OpcUaGroupManager implements AutoCloseable {

	private static final EdgeLogger logger = EdgeStaticLoggerBinder.getClassLogger(OpcUaGroupManager.class);

	private final OpcUaClientService opcUaClientService;
	private final UaSubscription uaSubscription;
	private final ValueConsumer valueConsumer;
	private final Map nodeMapConfig = new HashMap<>();
	private final Map nodeMapCallback = new HashMap<>();

	private final String groupName;

	private final Set writeChannels = new HashSet<>();

	public OpcUaGroupManager(String groupName, OpcUaClientService opcUaClientService, UaSubscription uaSubscription) {
		this.groupName = groupName;
		this.opcUaClientService = opcUaClientService;
		this.uaSubscription = uaSubscription;
		this.valueConsumer = new ValueConsumer() {

			@Override
			public void onValueArrived(UaMonitoredItem item, DataValue value) {
				onNewValue(item, value);
			}

		};
	}

	public void addSingleNode(OpcUaClientNodeConfig singleNode) throws InterruptedException, ExecutionException {
		if (singleNode.readChannel != null && !singleNode.readChannel.isEmpty()) {
			addReaderChannel(singleNode);
		}
		if (singleNode.writeChannel != null && !singleNode.writeChannel.isEmpty()) {
			addWriteChannel(singleNode);
		}

	}

	private void addReaderChannel(OpcUaClientNodeConfig singleNode) throws InterruptedException, ExecutionException {
		UInteger clientHandle = uaSubscription.nextClientHandle();
		ReadValueId readValueId = new ReadValueId(NodeId.parse(singleNode.nodeId), AttributeId.Value.uid(), null,
				QualifiedName.NULL_VALUE);

		DataChangeFilter filter = null;
		if (!singleNode.dataChangeTrigger.equals(DataChangeTrigger.statusOrValueOrTimestamp)
				|| !singleNode.deadbandType.equals(DeadbandType.none)) {
			org.eclipse.milo.opcua.stack.core.types.enumerated.DataChangeTrigger dataChange = org.eclipse.milo.opcua.stack.core.types.enumerated.DataChangeTrigger.StatusValueTimestamp;
			org.eclipse.milo.opcua.stack.core.types.enumerated.DeadbandType deadBandType = org.eclipse.milo.opcua.stack.core.types.enumerated.DeadbandType.None;
			switch (singleNode.dataChangeTrigger) {
			case status:
				dataChange = org.eclipse.milo.opcua.stack.core.types.enumerated.DataChangeTrigger.Status;
				break;
			case statusOrValue:
				dataChange = org.eclipse.milo.opcua.stack.core.types.enumerated.DataChangeTrigger.StatusValue;
				break;
			case statusOrValueOrTimestamp:
				dataChange = org.eclipse.milo.opcua.stack.core.types.enumerated.DataChangeTrigger.StatusValueTimestamp;
				break;
			default:
				dataChange = org.eclipse.milo.opcua.stack.core.types.enumerated.DataChangeTrigger.StatusValueTimestamp;
				break;
			}
			switch (singleNode.deadbandType) {
			case absolute:
				deadBandType = org.eclipse.milo.opcua.stack.core.types.enumerated.DeadbandType.Absolute;
				break;
			case none:
				deadBandType = org.eclipse.milo.opcua.stack.core.types.enumerated.DeadbandType.None;
				break;
			case percent:
				deadBandType = org.eclipse.milo.opcua.stack.core.types.enumerated.DeadbandType.Percent;
				break;
			default:
				deadBandType = org.eclipse.milo.opcua.stack.core.types.enumerated.DeadbandType.None;
				break;
			}
			filter = new DataChangeFilter(dataChange, UInteger.valueOf(deadBandType.getValue()),
					singleNode.deadbandValue);
		}

		MonitoringParameters parameters = new MonitoringParameters(clientHandle, singleNode.samplingInterval,
				filter != null
						? ExtensionObject.encode(opcUaClientService.getOpcUaClient().getStaticSerializationContext(),
								filter)
						: null,
				UInteger.valueOf(singleNode.queueSize), singleNode.discardOldest);

		MonitoredItemCreateRequest request = new MonitoredItemCreateRequest(readValueId, MonitoringMode.Reporting,
				parameters);

		UaSubscription.ItemCreationCallback onItemCreated = new ItemCreationCallback() {

			@Override
			public void onItemCreated(UaMonitoredItem item, int index) {
				onSubscriptionValue(item, index);

			}

		};
		nodeMapConfig.put(clientHandle, singleNode);
		uaSubscription.createMonitoredItems(TimestampsToReturn.Both, newArrayList(request), onItemCreated).get();
	}

	private void addWriteChannel(OpcUaClientNodeConfig singleNode) {
		final EdgeChannel channelWrite = opcUaClientService.getDataAddress().createOrGetDataChannel(
				singleNode.writeChannel, IPublishSubscribeChannel.class, "opcua write channel to " + "singleNode.topic",
				singleNode.fatherOfChannels, singleNode.scopeOfChannels,
				ConfigHelper.mergeTags(singleNode.tags, opcUaClientService.getConfiguration().getTags()),
				opcUaClientService);
		final OpcUaWriter opcUaWriter = new OpcUaWriter(opcUaClientService, singleNode);
		((IPublishSubscribeChannel) channelWrite).subscribe(opcUaWriter);
		writeChannels.add(opcUaWriter);
	}

	private void onSubscriptionValue(UaMonitoredItem item, int index) {
		item.setValueConsumer(valueConsumer);
		logger.info("item " + item.getMonitoredItemId() + " [" + item.getReadValueId().getNodeId() + "] added to group "
				+ groupName);
	}

	private void onNewValue(UaMonitoredItem uaMonitoredItem, DataValue dataValue) {
		if (!nodeMapCallback.containsKey(uaMonitoredItem.getClientHandle())) {
			OpcUaClientNodeConfig config = nodeMapConfig.get(uaMonitoredItem.getClientHandle());
			final EdgeChannel channel = opcUaClientService.getDataAddress().createOrGetDataChannel(config.readChannel,
					IPublishSubscribeChannel.class,
					"opcua read data channel from " + uaMonitoredItem.getReadValueId().getNodeId(),
					config.fatherOfChannels, config.scopeOfChannels,
					ConfigHelper.mergeTags(config.tags, opcUaClientService.getConfiguration().getTags()),
					opcUaClientService);
			nodeMapCallback.put(uaMonitoredItem.getClientHandle(), channel);
		}
		final EdgeChannel outputChannel = nodeMapCallback.get(uaMonitoredItem.getClientHandle());
		final IndustrialPayload industrialPayload = new IndustrialPayload();
		final Object value = dataValue.getValue().getValue();
		if (dataValue.getStatusCode().isGood()) {
			industrialPayload.setQuality(Quality.GOOD);
		} else if (dataValue.getStatusCode().isOverflowSet()) {
			industrialPayload.setQuality(Quality.OVERFLOW);
		} else if (dataValue.getStatusCode().isSecurityError()) {
			industrialPayload.setQuality(Quality.SECURITY_ERROR);
		} else if (dataValue.getStatusCode().isUncertain()) {
			industrialPayload.setQuality(Quality.UNKNOW);
		} else if (dataValue.getStatusCode().isBad()) {
			industrialPayload.setQuality(Quality.BAD);
		} else {
			industrialPayload.setQuality(Quality.UNKNOW);
		}
		industrialPayload.setProductionTime(dataValue.getSourceTime().getUtcTime());
		if (value instanceof String) {
			industrialPayload.setDataType(DataType.String);
			industrialPayload.setValue(value.toString());
		} else if (value instanceof Integer) {
			industrialPayload.setDataType(DataType.Integer);
			industrialPayload.setValue(value.toString());
		} else if (value instanceof Boolean) {
			industrialPayload.setDataType(DataType.Boolean);
			industrialPayload.setValue(value.toString());
		} else if (value instanceof Double) {
			industrialPayload.setDataType(DataType.Double);
			industrialPayload.setValue(value.toString());
		} else if (value instanceof Float) {
			industrialPayload.setDataType(DataType.Float);
			industrialPayload.setValue(value.toString());
		} else if (value instanceof java.util.UUID) {
			industrialPayload.setDataType(DataType.UUID);
			industrialPayload.setValue(value.toString());
		} else if (value instanceof Short) {
			industrialPayload.setDataType(DataType.Short);
			industrialPayload.setValue(value.toString());
		} else if (value instanceof Long) {
			industrialPayload.setDataType(DataType.Long);
			industrialPayload.setValue(value.toString());
		} else if (value instanceof Byte) {
			industrialPayload.setDataType(DataType.Byte);
			industrialPayload.setValue(value.toString());
		} else if (value instanceof org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UByte) {
			industrialPayload.setDataType(DataType.UByte);
			industrialPayload.setValue(value.toString());
		} else if (value instanceof org.eclipse.milo.opcua.stack.core.types.builtin.ByteString) {
			industrialPayload.setDataType(DataType.ByteString);
			industrialPayload.setValue(value.toString());
		} else if (value instanceof org.eclipse.milo.opcua.stack.core.types.builtin.DateTime) {
			industrialPayload.setDataType(DataType.DateTime);
			industrialPayload.setValue(value.toString());
		} else if (value instanceof org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UShort) {
			industrialPayload.setDataType(DataType.UShort);
			industrialPayload.setValue(value.toString());
		} else if (value instanceof org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger) {
			industrialPayload.setDataType(DataType.UInteger);
			industrialPayload.setValue(value.toString());
		} else if (value instanceof org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.ULong) {
			industrialPayload.setDataType(DataType.ULong);
			industrialPayload.setValue(value.toString());
		} else if (value instanceof org.eclipse.milo.opcua.stack.core.types.builtin.XmlElement) {
			industrialPayload.setDataType(DataType.XmlElement);
			industrialPayload.setValue(value.toString());
		} else {
			industrialPayload.setDataType(DataType.UNKNOW);
			industrialPayload.setValue(value.toString());
		}
		industrialPayload.setChannel(uaMonitoredItem.getReadValueId().getNodeId().toParseableString());
		final IndustrialMessage message = new IndustrialMessage(industrialPayload);
		outputChannel.getChannel().send(message);
	}

	@Override
	public void close() throws Exception {
		opcUaClientService.getOpcUaClient()
				.deleteSubscriptions(Collections.singletonList(uaSubscription.getSubscriptionId()));

	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy