use of org.eclipse.milo.opcua.sdk.core.AccessLevel in project milo by eclipse.
the class SubscriptionManager method createMonitoredItem.
private BaseMonitoredItem<?> createMonitoredItem(MonitoredItemCreateRequest request, Subscription subscription, TimestampsToReturn timestamps, Map<NodeId, AttributeGroup> attributeGroups) throws UaException {
NodeId nodeId = request.getItemToMonitor().getNodeId();
UInteger attributeId = request.getItemToMonitor().getAttributeId();
QualifiedName dataEncoding = request.getItemToMonitor().getDataEncoding();
if (!AttributeId.isValid(attributeId)) {
throw new UaException(StatusCodes.Bad_AttributeIdInvalid);
}
if (dataEncoding.isNotNull()) {
if (!AttributeId.Value.isEqual(attributeId)) {
throw new UaException(StatusCodes.Bad_DataEncodingInvalid);
}
if (!dataEncoding.equals(DEFAULT_BINARY_ENCODING) && !dataEncoding.equals(DEFAULT_XML_ENCODING)) {
throw new UaException(StatusCodes.Bad_DataEncodingUnsupported);
}
}
AttributeGroup attributeGroup = attributeGroups.get(nodeId);
if (attributeId.equals(AttributeId.EventNotifier.uid())) {
UByte eventNotifier = attributeGroup.getEventNotifier();
// Verify that the SubscribeToEvents bit is set
if (eventNotifier == null || (eventNotifier.intValue() & 1) == 0) {
throw new UaException(StatusCodes.Bad_AttributeIdInvalid);
}
Object filterObject = request.getRequestedParameters().getFilter().decode(server.getSerializationContext());
MonitoringFilter filter = validateEventItemFilter(filterObject, attributeGroup);
UInteger requestedQueueSize = request.getRequestedParameters().getQueueSize();
AtomicReference<UInteger> revisedQueueSize = new AtomicReference<>(requestedQueueSize);
try {
server.getAddressSpaceManager().onCreateEventItem(request.getItemToMonitor(), requestedQueueSize, revisedQueueSize::set);
} catch (Throwable t) {
throw new UaException(StatusCodes.Bad_InternalError, t);
}
MonitoredEventItem monitoredEventItem = new MonitoredEventItem(server, session, uint(subscription.nextItemId()), subscription.getId(), request.getItemToMonitor(), request.getMonitoringMode(), timestamps, request.getRequestedParameters().getClientHandle(), 0.0, revisedQueueSize.get(), request.getRequestedParameters().getDiscardOldest());
monitoredEventItem.installFilter(filter);
return monitoredEventItem;
} else {
if (attributeId.equals(AttributeId.Value.uid())) {
UByte accessLevel = attributeGroup.getAccessLevel();
if (accessLevel == null)
accessLevel = ubyte(0);
UByte userAccessLevel = attributeGroup.getUserAccessLevel();
if (userAccessLevel == null)
userAccessLevel = ubyte(0);
EnumSet<AccessLevel> accessLevels = AccessLevel.fromValue(accessLevel);
EnumSet<AccessLevel> userAccessLevels = AccessLevel.fromValue(userAccessLevel);
if (!accessLevels.contains(AccessLevel.CurrentRead)) {
throw new UaException(StatusCodes.Bad_NotReadable);
}
if (!userAccessLevels.contains(AccessLevel.CurrentRead)) {
throw new UaException(StatusCodes.Bad_UserAccessDenied);
}
}
// Validate the requested index range by parsing it.
String indexRange = request.getItemToMonitor().getIndexRange();
if (indexRange != null)
NumericRange.parse(indexRange);
Double minimumSamplingInterval = -1.0;
try {
minimumSamplingInterval = attributeGroup.getMinimumSamplingInterval();
if (minimumSamplingInterval == null) {
minimumSamplingInterval = server.getConfig().getLimits().getMinSupportedSampleRate();
}
} catch (UaException e) {
if (e.getStatusCode().getValue() != StatusCodes.Bad_AttributeIdInvalid) {
throw e;
}
}
MonitoringFilter filter = MonitoredDataItem.DEFAULT_FILTER;
try {
ExtensionObject filterXo = request.getRequestedParameters().getFilter();
if (filterXo != null && !filterXo.isNull()) {
Object filterObject = filterXo.decode(server.getSerializationContext());
filter = validateDataItemFilter(filterObject, attributeId, attributeGroup);
}
} catch (UaSerializationException e) {
logger.debug("error decoding MonitoringFilter", e);
throw new UaException(StatusCodes.Bad_MonitoredItemFilterInvalid, e);
}
double requestedSamplingInterval = getSamplingInterval(subscription, minimumSamplingInterval, request.getRequestedParameters().getSamplingInterval());
UInteger requestedQueueSize = request.getRequestedParameters().getQueueSize();
AtomicReference<Double> revisedSamplingInterval = new AtomicReference<>(requestedSamplingInterval);
AtomicReference<UInteger> revisedQueueSize = new AtomicReference<>(requestedQueueSize);
try {
server.getAddressSpaceManager().onCreateDataItem(request.getItemToMonitor(), requestedSamplingInterval, requestedQueueSize, (rsi, rqs) -> {
revisedSamplingInterval.set(rsi);
revisedQueueSize.set(rqs);
});
} catch (Throwable t) {
throw new UaException(StatusCodes.Bad_InternalError, t);
}
MonitoredDataItem monitoredDataItem = new MonitoredDataItem(server, session, uint(subscription.nextItemId()), subscription.getId(), request.getItemToMonitor(), request.getMonitoringMode(), timestamps, request.getRequestedParameters().getClientHandle(), revisedSamplingInterval.get(), revisedQueueSize.get(), request.getRequestedParameters().getDiscardOldest());
monitoredDataItem.installFilter(filter);
return monitoredDataItem;
}
}
use of org.eclipse.milo.opcua.sdk.core.AccessLevel in project milo by eclipse.
the class AttributeWriter method writeAttribute.
public static void writeAttribute(AttributeContext context, UaServerNode node, AttributeId attributeId, DataValue value, @Nullable String indexRange) throws UaException {
AttributeContext internalContext = new AttributeContext(context.getServer());
NodeClass nodeClass = node.getNodeClass();
if (attributeId == AttributeId.Value && nodeClass == NodeClass.Variable) {
Set<AccessLevel> accessLevels = getAccessLevels(node, internalContext);
if (!accessLevels.contains(AccessLevel.CurrentWrite)) {
throw new UaException(StatusCodes.Bad_NotWritable);
}
Set<AccessLevel> userAccessLevels = getUserAccessLevels(node, context);
if (!userAccessLevels.contains(AccessLevel.CurrentWrite)) {
throw new UaException(StatusCodes.Bad_UserAccessDenied);
}
} else {
WriteMask writeMask = writeMaskForAttribute(attributeId);
Set<WriteMask> writeMasks = getWriteMasks(node, internalContext);
if (!writeMasks.contains(writeMask)) {
throw new UaException(StatusCodes.Bad_NotWritable);
}
Set<WriteMask> userWriteMasks = getUserWriteMasks(node, context);
if (!userWriteMasks.contains(writeMask)) {
throw new UaException(StatusCodes.Bad_UserAccessDenied);
}
}
Variant updateVariant = value.getValue();
if (indexRange != null) {
NumericRange range = NumericRange.parse(indexRange);
DataValue current = node.getAttribute(internalContext, attributeId);
Variant currentVariant = current.getValue();
Object valueAtRange = NumericRange.writeToValueAtRange(currentVariant, updateVariant, range);
updateVariant = new Variant(valueAtRange);
}
DateTime sourceTime = value.getSourceTime();
DateTime serverTime = value.getServerTime();
value = new DataValue(updateVariant, value.getStatusCode(), (sourceTime == null || sourceTime.isNull()) ? DateTime.now() : sourceTime, (serverTime == null || serverTime.isNull()) ? DateTime.now() : serverTime);
if (attributeId == AttributeId.Value) {
NodeId dataType = extract(node.getAttribute(internalContext, AttributeId.DataType));
if (dataType != null) {
value = validateDataType(context.getServer(), dataType, value);
}
Integer valueRank = extract(node.getAttribute(internalContext, AttributeId.ValueRank));
if (valueRank == null)
valueRank = 0;
if (valueRank > 0) {
UInteger[] arrayDimensions = extract(node.getAttribute(context, AttributeId.ArrayDimensions));
validateArrayType(valueRank, arrayDimensions, value);
}
}
node.setAttribute(context, attributeId, value);
}
use of org.eclipse.milo.opcua.sdk.core.AccessLevel in project milo by eclipse.
the class AttributeReader method readAttribute.
public static DataValue readAttribute(AttributeContext context, UaServerNode node, AttributeId attributeId, @Nullable TimestampsToReturn timestamps, @Nullable String indexRange, @Nullable QualifiedName encodingName) {
try {
AttributeContext internalContext = new AttributeContext(context.getServer());
NodeClass nodeClass = node.getNodeClass();
if (attributeId == AttributeId.Value && nodeClass == NodeClass.Variable) {
Set<AccessLevel> accessLevels = getAccessLevels(node, internalContext);
if (!accessLevels.contains(AccessLevel.CurrentRead)) {
throw new UaException(StatusCodes.Bad_NotReadable);
}
Set<AccessLevel> userAccessLevels = getUserAccessLevels(node, context);
if (!userAccessLevels.contains(AccessLevel.CurrentRead)) {
throw new UaException(StatusCodes.Bad_UserAccessDenied);
}
}
if (encodingName != null && encodingName.isNotNull()) {
if (attributeId != AttributeId.Value) {
throw new UaException(StatusCodes.Bad_DataEncodingInvalid);
}
NodeId dataTypeId;
if (node instanceof VariableNode) {
dataTypeId = ((VariableNode) node).getDataType();
} else if (node instanceof VariableTypeNode) {
dataTypeId = ((VariableTypeNode) node).getDataType();
} else {
throw new UaException(StatusCodes.Bad_DataEncodingInvalid);
}
boolean structured = isStructureSubtype(context.getServer(), dataTypeId);
if (!structured) {
throw new UaException(StatusCodes.Bad_DataEncodingInvalid);
}
}
final DataValue.Builder dvb = node.getAttribute(context, attributeId).copy();
// Maybe transcode the structure...
if (dvb.value.isNotNull()) {
final Object valueObject = dvb.value.getValue();
Class<?> valueClazz = valueObject.getClass();
if (valueClazz.isArray() && ArrayUtil.getType(valueObject) == ExtensionObject.class) {
Object newValue = transformArray(valueObject, (ExtensionObject xo) -> transcode(context, node, xo, encodingName), ExtensionObject.class);
dvb.setValue(new Variant(newValue));
} else if (valueClazz == ExtensionObject.class) {
ExtensionObject xo = (ExtensionObject) valueObject;
Object newValue = transcode(context, node, xo, encodingName);
dvb.setValue(new Variant(newValue));
}
}
// Apply index range if provided...
if (indexRange != null) {
NumericRange range = NumericRange.parse(indexRange);
Object valueAtRange = NumericRange.readFromValueAtRange(dvb.value, range);
dvb.setValue(new Variant(valueAtRange));
}
// Add or remove timestamps based on TimestampsToReturn...
if (timestamps != null) {
dvb.applyTimestamps(attributeId, timestamps);
}
return dvb.build();
} catch (UaException e) {
return new DataValue(e.getStatusCode());
}
}
Aggregations