/// <summary> /// Initializes the object with the containing subscription object. /// </summary> public ComDaDataCallback(ComDaGroup group) { // save group. m_group = group; // create connection point. m_connectionPoint = new ConnectionPoint(group.Unknown, typeof(OpcRcw.Da.IOPCDataCallback).GUID); // advise. m_connectionPoint.Advise(this); }
/// <summary> /// Initializes a new instance of the <see cref="ComDaGroupItem"/> class. /// </summary> public ComDaGroupItem(ComDaGroup group, string itemId) { m_group = group; m_itemId = itemId; m_serverHandle = 0; m_active = true; m_euType = -1; m_samplingRate = -1; m_bufferEnabled = false; m_deadband = -1; }
/// <summary> /// Recovers the session context. /// </summary> /// <param name="group">The group.</param> public void RecoverSessionContext(ComDaGroup group) { // create a new subscription and copy existing one. Subscription discardSubscription = group.Subscription; Subscription subscription = new Subscription(); subscription.DisplayName = discardSubscription.DisplayName; subscription.PublishingInterval = discardSubscription.PublishingInterval; subscription.KeepAliveCount = discardSubscription.KeepAliveCount; subscription.LifetimeCount = discardSubscription.LifetimeCount; subscription.MaxNotificationsPerPublish = discardSubscription.MaxNotificationsPerPublish; subscription.Priority = discardSubscription.Priority; subscription.PublishingEnabled = discardSubscription.PublishingEnabled; subscription.DisableMonitoredItemCache = discardSubscription.DisableMonitoredItemCache; try { discardSubscription.Dispose(); } catch (Exception) { } m_session.AddSubscription(subscription); try { // create the initial subscription. subscription.Create(); // set the keep alive interval to 30 seconds and the the lifetime interval to 5 minutes. subscription.KeepAliveCount = (uint)((30000 / (int)subscription.CurrentPublishingInterval) + 1); subscription.LifetimeCount = (uint)((600000 / (int)subscription.CurrentPublishingInterval) + 1); // update the subscription. subscription.Modify(); } catch (Exception e) { m_session.RemoveSubscription(subscription); throw ComUtils.CreateComException(e, ResultIds.E_FAIL); } // update the group. group.ActualUpdateRate = (int)(subscription.CurrentPublishingInterval * 2); group.Subscription = subscription; group.RecreateItems(); }
/// <summary> /// Returns the current set of groups. /// </summary> /// <returns>The list of groups.</returns> public ComDaGroup[] GetGroups() { TraceState("GetGroups"); lock (m_lock) { ComDaGroup[] groups = new ComDaGroup[m_groups.Count]; for (int ii = 0; ii < m_groups.Count; ii++) { groups[ii] = m_groups[ii]; } return(groups); } }
/// <summary> /// Gets the group by handle. /// </summary> /// <param name="serverHandle">The server handle.</param> /// <returns>The group.</returns> public ComDaGroup GetGroupByHandle(int serverHandle) { TraceState("GetGroupByHandle", serverHandle); lock (m_lock) { for (int ii = 0; ii < m_groups.Count; ii++) { ComDaGroup group = m_groups[ii]; if (group.ServerHandle == serverHandle) { return(group); } } return(null); } }
/// <summary> /// Gets the group with the specified name. /// </summary> /// <param name="groupName">Name of the group.</param> /// <returns>The group. Null if it does not exist.</returns> public ComDaGroup GetGroupByName(string groupName) { TraceState("GetGroupByName", groupName); lock (m_lock) { for (int ii = 0; ii < m_groups.Count; ii++) { ComDaGroup group = m_groups[ii]; if (group.Name == groupName) { return(group); } } return(null); } }
/// <summary> /// Removes the group. /// </summary> /// <param name="group">The group.</param> public void RemoveGroup(ComDaGroup group) { TraceState("RemoveGroup", group.Name); lock (m_lock) { for (int ii = 0; ii < m_groups.Count; ii++) { if (Object.ReferenceEquals(group, m_groups[ii])) { m_groups.RemoveAt(ii); if (group.Subscription != null && group.Subscription.Session != null) { group.Subscription.Session.RemoveSubscription(group.Subscription); } } } group.Dispose(); } }
/// <summary> /// Clones the item. /// </summary> /// <param name="group">The group.</param> /// <returns>The new item.</returns> public ComDaGroupItem CloneItem(ComDaGroup group) { ComDaGroupItem copy = new ComDaGroupItem(group, this.ItemId); copy.m_nodeId = this.m_nodeId; copy.m_serverHandle = this.m_serverHandle; copy.m_clientHandle = this.m_clientHandle; copy.m_active = this.m_active; copy.m_requestedDataType = this.m_requestedDataType; copy.m_canonicalDataType = this.m_canonicalDataType; copy.m_accessRights = this.m_accessRights; copy.m_euType = this.m_euType; copy.m_euInfo = this.m_euInfo; copy.m_samplingRate = this.m_samplingRate; copy.m_bufferEnabled = this.m_bufferEnabled; copy.m_actualSamplingRate = this.m_actualSamplingRate; copy.m_deadband = this.m_deadband; // create new monitored item and use its client handle as the server handle. copy.m_monitoredItem = new MonitoredItem(this.MonitoredItem); return(copy); }
/// <summary> /// Sets the name. /// </summary> /// <param name="group">The group.</param> /// <param name="groupName">Name of the group.</param> public void SetGroupName(ComDaGroup group, string groupName) { TraceState("SetGroupName", group.Name, groupName); if (String.IsNullOrEmpty(groupName)) { throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); } lock (m_lock) { for (int ii = 0; ii < m_groups.Count; ii++) { ComDaGroup target = m_groups[ii]; if (target.ServerHandle != group.ServerHandle && target.Name == groupName) { throw ComUtils.CreateComException(ResultIds.E_DUPLICATENAME); } group.Name = groupName; } } }
/// <summary> /// Validates the items by reading the attributes required to add them to the group. /// </summary> /// <param name="session">The session.</param> /// <param name="group">The group.</param> /// <param name="requests">The requests.</param> /// <param name="items">The items.</param> /// <param name="start">The start index.</param> /// <param name="count">The number of items to process.</param> private void ValidateItems( Session session, ComDaGroup group, ComDaCreateItemRequest[] requests, ComDaGroupItem[] items, int start, int count) { // build list of the UA attributes that need to be read. ReadValueIdCollection attributesToRead = new ReadValueIdCollection(); for (int ii = start; ii < start + count && ii < requests.Length; ii++) { // create the group item. ComDaCreateItemRequest request = requests[ii]; ComDaGroupItem item = items[ii] = new ComDaGroupItem(group, request.ItemId); item.NodeId = m_mapper.GetRemoteNodeId(request.ItemId); item.Active = request.Active; item.ClientHandle = request.ClientHandle; item.RequestedDataType = request.RequestedDataType; item.SamplingRate = -1; item.Deadband = -1; // add attributes. ReadValueId attributeToRead; attributeToRead = new ReadValueId(); attributeToRead.NodeId = item.NodeId; attributeToRead.AttributeId = Attributes.NodeClass; attributesToRead.Add(attributeToRead); attributeToRead = new ReadValueId(); attributeToRead.NodeId = item.NodeId; attributeToRead.AttributeId = Attributes.DataType; attributesToRead.Add(attributeToRead); attributeToRead = new ReadValueId(); attributeToRead.NodeId = item.NodeId; attributeToRead.AttributeId = Attributes.ValueRank; attributesToRead.Add(attributeToRead); attributeToRead = new ReadValueId(); attributeToRead.NodeId = item.NodeId; attributeToRead.AttributeId = Attributes.UserAccessLevel; attributesToRead.Add(attributeToRead); } // read attribute values from the server. DataValueCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; try { session.Read( null, 0, TimestampsToReturn.Neither, attributesToRead, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, attributesToRead); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, attributesToRead); } catch (Exception e) { Utils.Trace(e, "Unexpected error reading attributes for items."); // set default values on error. for (int ii = start; ii < start + count && ii < requests.Length; ii++) { requests[ii].Error = ResultIds.E_INVALIDITEMID; } return; } // process results. int first = 0; for (int ii = start; ii < start + count && ii < requests.Length; ii++, first += 4) { ComDaGroupItem item = items[ii]; // verify node class. NodeClass nodeClass = (NodeClass)results[first].GetValue <int>((int)NodeClass.Unspecified); if (nodeClass != NodeClass.Variable) { requests[ii].Error = ResultIds.E_INVALIDITEMID; continue; } // verify data type. NodeId dataTypeId = results[first + 1].GetValue <NodeId>(null); if (dataTypeId == null) { requests[ii].Error = ResultIds.E_INVALIDITEMID; continue; } // get value rank. int valueRank = results[first + 2].GetValue <int>(ValueRanks.Scalar); // update datatypes. BuiltInType builtInType = DataTypes.GetBuiltInType(dataTypeId, session.TypeTree); item.RemoteDataType = new TypeInfo(builtInType, valueRank); item.CanonicalDataType = (short)ComUtils.GetVarType(item.RemoteDataType); // update access rights. byte userAccessLevel = results[first + 3].GetValue <byte>(0); if ((userAccessLevel & AccessLevels.CurrentRead) != 0) { item.AccessRights |= OpcRcw.Da.Constants.OPC_READABLE; } if ((userAccessLevel & AccessLevels.CurrentWrite) != 0) { item.AccessRights |= OpcRcw.Da.Constants.OPC_WRITEABLE; } } }
/// <summary> /// Validates the items. /// </summary> /// <param name="group">The group.</param> /// <param name="requests">The requests.</param> /// <returns>The items. May contain null is validation failed.</returns> public ComDaGroupItem[] ValidateItems(ComDaGroup group, ComDaCreateItemRequest[] requests) { TraceState("ValidateItems", group.Name); // get the session to use for the operation. Session session = m_session; if (session == null) { throw ComUtils.CreateComException(ResultIds.E_FAIL); } // validate items. ComDaGroupItem[] items = new ComDaGroupItem[requests.Length]; for (int ii = 0; ii < requests.Length; ii += 10000) { ValidateItems(session, group, requests, items, ii, 10000); } // process results. for (int ii = 0; ii < requests.Length; ii++) { // check for the results. ComDaCreateItemRequest request = requests[ii]; if (request.Error < 0) { items[ii] = null; continue; } // check access path. if (!String.IsNullOrEmpty(request.AccessPath)) { items[ii] = null; request.Error = ResultIds.E_UNKNOWNPATH; continue; } ComDaGroupItem item = items[ii]; // validate the datatype. if (request.RequestedDataType != 0) { NodeId dataTypeId = ComUtils.GetDataTypeId(request.RequestedDataType); if (NodeId.IsNull(dataTypeId)) { items[ii] = null; request.Error = ResultIds.E_BADTYPE; continue; } bool reqTypeIsArray = (request.RequestedDataType & (short)VarEnum.VT_ARRAY) != 0; bool actualTypeIsArray = (item.CanonicalDataType & (short)VarEnum.VT_ARRAY) != 0; if (reqTypeIsArray != actualTypeIsArray) { items[ii] = null; request.Error = ResultIds.E_BADTYPE; continue; } } // create a new monitored item. MonitoredItem monitoredItem = new MonitoredItem(); monitoredItem.StartNodeId = item.NodeId; monitoredItem.RelativePath = null; monitoredItem.AttributeId = Attributes.Value; monitoredItem.MonitoringMode = (request.Active)?MonitoringMode.Reporting:MonitoringMode.Disabled; monitoredItem.SamplingInterval = group.UpdateRate / 2; monitoredItem.QueueSize = 0; monitoredItem.DiscardOldest = true; monitoredItem.Filter = null; // update item. item.ServerHandle = (int)monitoredItem.ClientHandle; item.MonitoredItem = monitoredItem; // link the monitored item back to the group item. monitoredItem.Handle = item; // update return parameters. request.ServerHandle = item.ServerHandle; request.CanonicalDataType = item.CanonicalDataType; request.AccessRights = item.AccessRights; request.Error = ResultIds.S_OK; } return(items); }
/// <summary> /// Updates the EUInfo for the items. /// </summary> /// <param name="group">The group.</param> /// <param name="items">The items. Null entries are ignored.</param> public void UpdateItemEuInfo( ComDaGroup group, IList <ComDaGroupItem> items) { // get the session to use for the operation. Session session = m_session; if (session == null) { throw ComUtils.CreateComException(ResultIds.E_FAIL); } // build list of properties that need to be read. BrowsePathCollection browsePaths = new BrowsePathCollection(); for (int ii = 0; ii < items.Count; ii++) { ComDaGroupItem item = (ComDaGroupItem)items[ii]; // ignore invalid items or items which have already checked their EU type. if (item == null || item.EuType >= 0) { continue; } BrowsePath browsePath = new BrowsePath(); browsePath.StartingNode = item.NodeId; RelativePathElement element = new RelativePathElement(); element.ReferenceTypeId = ReferenceTypeIds.HasProperty; element.IsInverse = false; element.IncludeSubtypes = false; element.TargetName = Opc.Ua.BrowseNames.EURange; browsePath.RelativePath.Elements.Add(element); browsePath.Handle = item; browsePaths.Add(browsePath); browsePath = new BrowsePath(); browsePath.StartingNode = item.NodeId; element = new RelativePathElement(); element.ReferenceTypeId = ReferenceTypeIds.HasProperty; element.IsInverse = false; element.IncludeSubtypes = false; element.TargetName = Opc.Ua.BrowseNames.EnumStrings; browsePath.RelativePath.Elements.Add(element); browsePath.Handle = item; browsePaths.Add(browsePath); } // check if nothing to do. if (browsePaths.Count == 0) { return; } // translate browse paths. BrowsePathResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; try { session.TranslateBrowsePathsToNodeIds( null, browsePaths, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, browsePaths); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, browsePaths); } catch (Exception) { for (int ii = 0; ii < browsePaths.Count; ii++) { ComDaGroupItem item = (ComDaGroupItem)browsePaths[ii].Handle; item.EuType = 0; } return; } // build list of properties that need to be read. ReadValueIdCollection propertiesToRead = new ReadValueIdCollection(); for (int ii = 0; ii < results.Count; ii++) { ComDaGroupItem item = (ComDaGroupItem)browsePaths[ii].Handle; BrowsePathResult result = results[ii]; if (StatusCode.IsBad(result.StatusCode)) { if (item.EuType < 0 && result.StatusCode == StatusCodes.BadNoMatch) { item.EuType = (int)OpcRcw.Da.OPCEUTYPE.OPC_NOENUM; } continue; } if (result.Targets.Count == 0 || result.Targets[0].TargetId.IsAbsolute) { if (item.EuType < 0) { item.EuType = (int)OpcRcw.Da.OPCEUTYPE.OPC_NOENUM; } continue; } ReadValueId propertyToRead = new ReadValueId(); propertyToRead.NodeId = (NodeId)result.Targets[0].TargetId; propertyToRead.AttributeId = Attributes.Value; propertyToRead.Handle = item; propertiesToRead.Add(propertyToRead); if (browsePaths[ii].RelativePath.Elements[0].TargetName.Name == Opc.Ua.BrowseNames.EURange) { item.EuType = (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG; } else { item.EuType = (int)OpcRcw.Da.OPCEUTYPE.OPC_ENUMERATED; } } // check if nothing to do. if (propertiesToRead.Count == 0) { return; } // read attribute values from the server. DataValueCollection values = null; try { session.Read( null, 0, TimestampsToReturn.Neither, propertiesToRead, out values, out diagnosticInfos); ClientBase.ValidateResponse(values, propertiesToRead); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, propertiesToRead); } catch (Exception) { for (int ii = 0; ii < propertiesToRead.Count; ii++) { ComDaGroupItem item = (ComDaGroupItem)propertiesToRead[ii].Handle; item.EuType = 0; } return; } // process results. for (int ii = 0; ii < values.Count; ii++) { ComDaGroupItem item = (ComDaGroupItem)propertiesToRead[ii].Handle; if (StatusCode.IsBad(values[ii].StatusCode)) { item.EuType = 0; continue; } if (item.EuType == (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG) { Range range = (Range)values[ii].GetValue <Range>(null); if (range == null) { item.EuType = 0; continue; } item.EuInfo = new double[] { range.Low, range.High }; continue; } if (item.EuType == (int)OpcRcw.Da.OPCEUTYPE.OPC_ENUMERATED) { LocalizedText[] texts = (LocalizedText[])values[ii].GetValue <LocalizedText[]>(null); if (texts == null) { item.EuType = 0; continue; } string[] strings = new string[texts.Length]; for (int jj = 0; jj < strings.Length; jj++) { if (!LocalizedText.IsNullOrEmpty(texts[jj])) { strings[jj] = texts[jj].Text; } } item.EuInfo = strings; continue; } } }
/// <summary> /// Reads the item values and stores the results in the request object. /// </summary> /// <param name="requests">The requests.</param> private void Da20ReadItemValues(List<ReadRequest> requests) { // lock (m_groupLock) { // if (m_group == null) //{ ComDaGroup m_group = new ComDaGroup(this, false); //} try { int count1 = 0; GroupItem[] items = new GroupItem[requests.Count]; ReadRequest[] addItemRequests = new ReadRequest[requests.Count]; // create the items in the temporary group. for (int ii = 0; ii < requests.Count; ii++) { ReadRequest request = requests[ii]; if (request == null) { continue; } if (!request.ValueRequired) { continue; } // add the item. items[count1] = m_group.CreateItem(request.ItemId, 0, 0, true); addItemRequests[count1] = request; count1++; } // create the items on the server. m_group.ApplyChanges(); // build the list of values to write. int count2 = 0; int[] serverHandles = new int[count1]; ReadRequest[] readRequests = new ReadRequest[count1]; for (int ii = 0; ii < count1; ii++) { // check for error on create. GroupItem item = items[ii]; ReadRequest request = addItemRequests[ii]; if (item.ErrorId < 0) { request.Value = new DaValue(); request.Value.Error = item.ErrorId; continue; } serverHandles[count2] = item.ServerHandle; readRequests[count2] = request; count2++; } if (count2 > 0) { // write values to the server. DaValue[] values = m_group.SyncRead(serverHandles, count2); // read the values. for (int ii = 0; ii < count2; ii++) { if (values != null && values.Length > ii) { readRequests[ii].Value = values[ii]; } else { readRequests[ii].Value = new DaValue() { Error = ResultIds.E_FAIL, Timestamp = DateTime.UtcNow }; } } // delete the items. for (int ii = 0; ii < count1; ii++) { GroupItem item = items[ii]; if (item.ErrorId >= 0) { m_group.RemoveItem(item); } } m_group.ApplyChanges(); } } finally { // delete the group and items. m_group.Delete(); } } }
/// <summary> /// Removes the group. /// </summary> /// <param name="group">The group.</param> public void RemoveGroup(ComDaGroup group) { m_groupManager.RemoveGroup(group); }
/// <summary> /// Reads the item values and stores the results in the request object. /// </summary> /// <param name="requests">The requests.</param> public void ReadItemValues(List<ReadRequest> requests) { ComDaGroup group = new ComDaGroup(this, false); try { int count1 = 0; GroupItem[] items = new GroupItem[requests.Count]; ReadRequest[] addItemRequests = new ReadRequest[requests.Count]; // create the items in the temporary group. for (int ii = 0; ii < requests.Count; ii++) { ReadRequest request = requests[ii]; if (request == null) { continue; } if (!request.ValueRequired) { continue; } // add the item. items[count1] = group.CreateItem(request.ItemId, 0, 0, true); addItemRequests[count1] = request; count1++; } // create the items on the server. group.ApplyChanges(); // build the list of values to write. int count2 = 0; int[] serverHandles = new int[count1]; ReadRequest[] readRequests = new ReadRequest[count1]; for (int ii = 0; ii < count1; ii++) { // check for error on create. GroupItem item = items[ii]; ReadRequest request = addItemRequests[ii]; if (item.ErrorId < 0) { request.Value.Error = item.ErrorId; continue; } serverHandles[count2] = item.ServerHandle; readRequests[count2] = request; count2++; } // write values to the server. DaValue[] values = group.SyncRead(serverHandles, count2); // read the values. for (int ii = 0; ii < count2; ii++) { readRequests[ii].Value = values[ii]; } } finally { // delete the group and items. group.Delete(); } }
/// <summary> /// Writes the item values to servers. /// </summary> /// <param name="requests">The requests.</param> private void WriteItemValues(List<WriteRequest> requests) { ComDaGroup group = new ComDaGroup(this, false); try { int count1 = 0; GroupItem[] items = new GroupItem[requests.Count]; WriteRequest[] addItemRequests = new WriteRequest[requests.Count]; // create the items in the temporary group. for (int ii = 0; ii < requests.Count; ii++) { WriteRequest request = requests[ii]; if (request == null) { continue; } // status code writes not supported. if (request.Value.StatusCode != StatusCodes.Good) { request.Error = ResultIds.E_NOTSUPPORTED; continue; } // timestamp writes not supported. if (request.Value.SourceTimestamp != DateTime.MinValue) { request.Error = ResultIds.E_NOTSUPPORTED; continue; } // add the item. items[count1] = group.CreateItem(request.ItemId, 0, 0, true); addItemRequests[count1] = request; count1++; } // create the items on the server. group.ApplyChanges(); // build the list of values to write. int count2 = 0; int[] serverHandles = new int[count1]; object[] values = new object[count1]; WriteRequest[] writeRequests = new WriteRequest[count1]; for (int ii = 0; ii < count1; ii++) { // check for error on create. GroupItem item = items[ii]; WriteRequest request = addItemRequests[ii]; if (item.ErrorId < 0) { request.Error = item.ErrorId; continue; } serverHandles[count2] = item.ServerHandle; values[count2] = ComUtils.GetVARIANT(request.Value.Value); writeRequests[count2] = request; count2++; } // write values to the server. int[] errors = group.SyncWrite(serverHandles, values, count2); // read the errors. for (int ii = 0; ii < count2; ii++) { writeRequests[ii].Error = errors[ii]; } } finally { // delete the group and items. group.Delete(); } }
/// <summary> /// Adds the group. /// </summary> /// <param name="groupName">The group name.</param> /// <param name="active">if set to <c>true</c> the group is active.</param> /// <param name="updateRate">The update rate.</param> /// <param name="clientHandle">The client handle.</param> /// <param name="timeBias">The time bias.</param> /// <param name="deadband">The deadband.</param> /// <param name="lcid">The lcid.</param> /// <returns>The new group.</returns> public ComDaGroup AddGroup( string groupName, bool active, int updateRate, int clientHandle, int timeBias, float deadband, int lcid) { TraceState("AddGroup", groupName, active, updateRate, clientHandle, timeBias, deadband, lcid); // check for valid session. Session session = m_session; if (session == null) { throw ComUtils.CreateComException(ResultIds.E_FAIL); } ComDaGroup group = null; // check for duplicate name. lock (m_lock) { // ensure the name is unique. if (!String.IsNullOrEmpty(groupName)) { if (GetGroupByName(groupName) != null) { throw ComUtils.CreateComException(ResultIds.E_DUPLICATENAME); } } // assign a unique name. else { groupName = Utils.Format("Group{0}", m_groupCounter + 1); } // validate the deadband. if (deadband < 0 || deadband > 100) { throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); } // create the group. group = new ComDaGroup(this, groupName, ++m_groupCounter); m_groups.Add(group); group.ClientHandle = clientHandle; group.Active = active; group.UpdateRate = updateRate; group.TimeBias = timeBias; group.Deadband = deadband; group.Lcid = lcid; if (updateRate < 100) { updateRate = 100; } // create a new subscription. Subscription subscription = new Subscription(); subscription.DisplayName = groupName; subscription.PublishingInterval = updateRate / 2; subscription.KeepAliveCount = 30; subscription.LifetimeCount = 600; subscription.MaxNotificationsPerPublish = 10000; subscription.Priority = 1; subscription.PublishingEnabled = active; subscription.DisableMonitoredItemCache = true; // create the subscription on the server. session.AddSubscription(subscription); try { // create the initial subscription. subscription.Create(); // set the keep alive interval to 30 seconds and the the lifetime interval to 5 minutes. subscription.KeepAliveCount = (uint)((30000 / (int)subscription.CurrentPublishingInterval) + 1); subscription.LifetimeCount = (uint)((600000 / (int)subscription.CurrentPublishingInterval) + 1); // update the subscription. subscription.Modify(); } catch (Exception e) { session.RemoveSubscription(subscription); Utils.Trace((int)Utils.TraceMasks.Error, "Create subscription failed: {0}", e.Message); throw ComUtils.CreateComException(e, ResultIds.E_FAIL); } // update the group. group.ActualUpdateRate = (int)(subscription.CurrentPublishingInterval * 2); group.Subscription = subscription; } return(group); }
/// <summary> /// Writes the item values to servers. /// </summary> /// <param name="requests">The requests.</param> private void Da20WriteItemValues(List<WriteRequest> requests) { //lock (m_groupLock) { //if (m_group == null) //{ ComDaGroup m_group = new ComDaGroup(this, false); //} try { int count1 = 0; GroupItem[] items = new GroupItem[requests.Count]; WriteRequest[] addItemRequests = new WriteRequest[requests.Count]; object[] convertedValues = new object[requests.Count]; // create the items in the temporary group. for (int ii = 0; ii < requests.Count; ii++) { WriteRequest request = requests[ii]; if (request == null) { continue; } // status code writes not supported. if (request.Value.StatusCode != StatusCodes.Good) { request.Error = ResultIds.E_NOTSUPPORTED; continue; } // timestamp writes not supported. if (request.Value.ServerTimestamp != DateTime.MinValue) { request.Error = ResultIds.E_NOTSUPPORTED; continue; } // timestamp writes not supported. if (request.Value.SourceTimestamp != DateTime.MinValue) { request.Error = ResultIds.E_NOTSUPPORTED; continue; } // convert to a DA compatible type. object convertedValue = null; request.Error = ComDaClientNodeManager.LocalToRemoteValue(request.Value.WrappedValue, out convertedValue); if (request.Error < 0) { continue; } // add the item. items[count1] = m_group.CreateItem(request.ItemId, 0, 0, true); addItemRequests[count1] = request; convertedValues[count1] = convertedValue; count1++; } // create the items on the server. m_group.ApplyChanges(); // build the list of values to write. int count2 = 0; int[] serverHandles = new int[count1]; object[] values = new object[count1]; WriteRequest[] writeRequests = new WriteRequest[count1]; for (int ii = 0; ii < count1; ii++) { // check for error on create. GroupItem item = items[ii]; WriteRequest request = addItemRequests[ii]; if (item.ErrorId < 0) { request.Error = item.ErrorId; continue; } serverHandles[count2] = item.ServerHandle; values[count2] = convertedValues[ii]; writeRequests[count2] = request; count2++; } if (count2 > 0) { // write values to the server. int[] errors = m_group.SyncWrite(serverHandles, values, count2); // read the errors. for (int ii = 0; ii < count2; ii++) { if (errors != null && errors.Length > ii) { writeRequests[ii].Error = errors[ii]; } else { writeRequests[ii].Error = ResultIds.E_FAIL; } } // delete the items. for (int ii = 0; ii < count1; ii++) { GroupItem item = items[ii]; if (item.ErrorId >= 0) { m_group.RemoveItem(item); } } m_group.ApplyChanges(); } } finally { // delete the group and items. m_group.Delete(); } } }