/* ======================================================================== * Copyright (c) 2005-2025 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using System; using System.Collections.Generic; using System.Threading; namespace Opc.Ua.PubSub { /// /// DataStore is a repository where Publisher applications will push data values for nodes + attributes published in data sets /// public class UaPubSubDataStore : IUaPubSubDataStore { private readonly Lock m_lock = new(); private readonly Dictionary> m_store; /// /// Create new instance of /// public UaPubSubDataStore() { m_store = []; } /// /// Write a value to the DataStore. /// The value is identified by node NodeId. /// /// NodeId identifier for value that will be stored. /// The value to be store. The value is NOT copied. /// The status associated with the value. /// The timestamp associated with the value. /// public void WritePublishedDataItem( NodeId nodeId, Variant value, StatusCode? status = null, DateTime? timestamp = null) { if (nodeId.IsNull) { throw new ArgumentException(null, nameof(nodeId)); } lock (m_lock) { var dv = new DataValue( value, status ?? StatusCodes.Good, timestamp ?? DateTimeUtc.Now); if (!m_store.TryGetValue(nodeId, out Dictionary? dictionary)) { dictionary = []; m_store.Add(nodeId, dictionary); } dictionary[Attributes.Value] = dv; } } /// /// Write a DataValue to the DataStore. /// The DataValue is identified by node NodeId and Attribute. /// /// NodeId identifier for DataValue that will be stored /// Default value is . /// Default value is null. /// public void WritePublishedDataItem( NodeId nodeId, uint attributeId = Attributes.Value, DataValue dataValue = default) { if (nodeId.IsNull) { throw new ArgumentException(null, nameof(nodeId)); } if (attributeId == 0) { attributeId = Attributes.Value; } if (!Attributes.IsValid(attributeId)) { throw new ArgumentException(null, nameof(attributeId)); } lock (m_lock) { if (m_store.TryGetValue(nodeId, out Dictionary? value)) { value[attributeId] = dataValue; } else { var dictionary = new Dictionary { { attributeId, dataValue } }; m_store.Add(nodeId, dictionary); } } } /// /// Try to read the DataValue stored for a specific NodeId and Attribute. /// /// NodeId identifier of node /// Default value is /// The stored DataValue when this method returns true. /// true if a DataValue is stored for the given NodeId and Attribute; otherwise false. /// public bool TryReadPublishedDataItem(NodeId nodeId, uint attributeId, out DataValue dataValue) { if (nodeId.IsNull) { throw new ArgumentException(null, nameof(nodeId)); } if (attributeId == 0) { attributeId = Attributes.Value; } if (!Attributes.IsValid(attributeId)) { throw new ArgumentException(null, nameof(attributeId)); } lock (m_lock) { if (m_store.TryGetValue(nodeId, out Dictionary? dictionary) && dictionary.TryGetValue(attributeId, out DataValue value)) { dataValue = value; return true; } } dataValue = default; return false; } /// /// Updates the metadata. /// public void UpdateMetaData(PublishedDataSetDataType publishedDataSet) { } } }