/// <summary> /// Initializes a COM-patible ONEVENTSTRUCT ready to be sent to subscribing clients /// </summary> /// <param name="oes"></param> /// <param name="pOnEventClass"></param> private void CopyToOnEventStruct(ref ONEVENTSTRUCT oes, OnEventClass pOnEventClass) { try { oes = pOnEventClass.InternalOES; ReturnedAttributeList attrIds; if (m_ReturnedAttributes.TryGetValue(oes.dwEventCategory, out attrIds) == true) { int retAttrCount = attrIds.Count; int i = 0; object[] attrVals = new object[retAttrCount]; foreach (int attrId in attrIds) { attrVals[i++] = pOnEventClass.EventAttributes[attrId]; } oes.dwNumEventAttrs = retAttrCount; oes.pEventAttributes = ComUtils.GetVARIANTs(attrVals, false); } } catch (Exception e) { Utils.Trace(e, "Unexpected error in CopyToOnEventStruct"); } }
/// <summary> /// Sends the queued events in blocks. /// </summary> private void SendInBlocks(IComAeEventCallback callback, Queue <AeEvent> events, uint blockSize, bool refreshFlag) { if (callback == null) { return; } if (blockSize == 0) { blockSize = (uint)events.Count; } while (events.Count > 0) { List <ONEVENTSTRUCT> eventsInBlock = new List <ONEVENTSTRUCT>(); try { for (int ii = 0; ii < blockSize && events.Count > 0; ii++) { // warning - Translate() allocates unmanaged memory that is deleted in the finally block. eventsInBlock.Add(Translate(events.Dequeue())); } // invoke callback. callback.OnEvent( ClientHandle, refreshFlag, (refreshFlag)?events.Count == 0:false, eventsInBlock.ToArray()); } finally { // must deallocate attributes on exit. for (int ii = 0; ii < eventsInBlock.Count; ii++) { IntPtr pAttributes = eventsInBlock[ii].pEventAttributes; ComUtils.GetVARIANTs(ref pAttributes, eventsInBlock[ii].dwNumEventAttrs, true); } } } }
/// <summary> /// Dispatches the event. /// </summary> private BaseEventState DispatchEvent(ONEVENTSTRUCT e) { NodeId typeId = AeParsedNodeId.Construct(e.dwEventType, e.dwEventCategory, e.szConditionName, m_namespaceIndex); // find the type. AeEventTypeState eventType = m_cache.FindType(m_defaultContext, typeId); if (eventType == null) { return(null); } // create a new instance. BaseEventState instance = m_cache.CreateInstance(m_defaultContext, eventType); if (instance == null) { return(null); } // fill in fields. UpdateBaseEvent(instance, eventType.EventType, e); if (instance is AuditEventState) { UpdateAuditEvent((AuditEventState)instance, eventType.EventType, e); } if (instance is AlarmConditionState) { UpdateAlarm((AlarmConditionState)instance, eventType.EventType, e); } if (instance is ExclusiveLimitAlarmState) { UpdateExclusiveLimitAlarm((ExclusiveLimitAlarmState)instance, eventType.EventType, e); } else if (instance is NonExclusiveLimitAlarmState) { UpdateNonExclusiveLimitAlarm((NonExclusiveLimitAlarmState)instance, eventType.EventType, e); } // process attributes. bool ackCommentFound = false; object[] values = ComUtils.GetVARIANTs(ref e.pEventAttributes, e.dwNumEventAttrs, false); for (int ii = 0; ii < eventType.EventType.Attributes.Count; ii++) { EventAttribute attribute = eventType.EventType.Attributes[ii]; if (ii >= e.dwNumEventAttrs) { continue; } if (!ackCommentFound && AeTypeCache.IsKnownName(attribute.Description, "ACK COMMENT")) { ConditionState condition = instance as ConditionState; if (condition != null) { condition.Comment = new ConditionVariableState <LocalizedText>(condition); condition.Comment.BrowseName = Opc.Ua.BrowseNames.Comment; condition.Comment.Value = new LocalizedText(values[ii] as string); } ackCommentFound = true; continue; } PropertyState property = new PropertyState(instance); property.SymbolicName = attribute.Description; property.BrowseName = new QualifiedName(property.SymbolicName, m_namespaceIndex); property.Value = values[ii]; instance.AddChild(property); } return(instance); }
/// <summary> /// Marshals an event for return to the client. /// </summary> private OpcRcw.Ae.ONEVENTSTRUCT Translate(AeEvent e) { OpcRcw.Ae.ONEVENTSTRUCT e2 = new ONEVENTSTRUCT(); e2.wNewState = 0; e2.wChangeMask = 0xFF; e2.szSource = e.SourceName; e2.wQuality = ComUtils.GetQualityCode(e.Quality); e2.dwEventType = e.Category.EventType; e2.dwEventCategory = (int)e.Category.LocalId; e2.bAckRequired = 0; e2.dwSeverity = e.Severity; e2.ftTime = ComUtils.GetFILETIME(e.Time); e2.szMessage = (e.Message != null) ? e.Message.Text : null; e2.szActorID = e.AuditUserId; e2.dwCookie = e.Cookie; if (e.AttributeValues != null && e.AttributeValues.Length > 0) { e2.dwNumEventAttrs = e.AttributeValues.Length; e2.pEventAttributes = ComUtils.GetVARIANTs(e.AttributeValues, true); } if ((e2.dwEventType & OpcRcw.Ae.Constants.CONDITION_EVENT) != 0) { e2.szConditionName = e.ConditionName; e2.ftActiveTime = ComUtils.GetFILETIME(e.ActiveTime); e2.bAckRequired = (e.AckedState)?0:1; // set the condition state. e2.wNewState = 0; if (e.EnabledState) { e2.wNewState |= OpcRcw.Ae.Constants.CONDITION_ENABLED; } if (e.AckedState) { e2.wNewState |= OpcRcw.Ae.Constants.CONDITION_ACKED; } if (e.ActiveState) { e2.wNewState |= OpcRcw.Ae.Constants.CONDITION_ACTIVE; } // set the subcondition if available. if (!LocalizedText.IsNullOrEmpty(e.LowState)) { e2.szSubconditionName = e.LowState.Text; } if (!LocalizedText.IsNullOrEmpty(e.HighState)) { e2.szSubconditionName = e.HighState.Text; } if (!LocalizedText.IsNullOrEmpty(e.LowLowState)) { e2.szSubconditionName = e.LowLowState.Text; } if (!LocalizedText.IsNullOrEmpty(e.HighHighState)) { e2.szSubconditionName = e.HighHighState.Text; } if (!LocalizedText.IsNullOrEmpty(e.LimitState)) { e2.szSubconditionName = e.LimitState.Text; } } if (e2.szMessage == null) { e2.szMessage = String.Empty; } if (e2.szSource == null) { e2.szSource = String.Empty; } if (e2.szConditionName == null) { e2.szConditionName = String.Empty; } if (e2.szSubconditionName == null) { e2.szSubconditionName = String.Empty; } if (e2.szActorID == null) { e2.szActorID = String.Empty; } return(e2); }
/// <summary> /// Reads the values of the properties from the server. /// </summary> /// <param name="itemId">The item id.</param> /// <param name="propertyIds">The list of property ids to read. All properties are read if null.</param> /// <returns>True if the element has properies.</returns> private DaValue[] ReadPropertyValues(string itemId, params int[] propertyIds) { string methodName = "IOPCItemProperties.GetItemProperties"; // check for trivial case. if (propertyIds == null) { return(null); } int count = propertyIds.Length; DaValue[] results = new DaValue[count]; // check for empty list. if (count == 0) { return(results); } // get the values from the server. IntPtr pValues = IntPtr.Zero; IntPtr pErrors = IntPtr.Zero; try { IOPCItemProperties server = BeginComCall <IOPCItemProperties>(methodName, true); server.GetItemProperties( itemId, count, propertyIds, out pValues, out pErrors); } catch (Exception e) { if (ComUtils.IsUnknownError(e, ResultIds.E_FAIL, ResultIds.E_UNKNOWNITEMID, ResultIds.E_INVALIDITEMID)) { ComUtils.TraceComError(e, methodName); return(null); } for (int ii = 0; ii < count; ii++) { DaValue result = results[ii] = new DaValue(); result.Value = null; result.Quality = OpcRcw.Da.Qualities.OPC_QUALITY_GOOD; result.Timestamp = DateTime.UtcNow; result.Error = Marshal.GetHRForException(e); } return(results); } finally { EndComCall(methodName); } // unmarshal results. object[] values = ComUtils.GetVARIANTs(ref pValues, count, true); int[] errors = ComUtils.GetInt32s(ref pErrors, count, true); for (int ii = 0; ii < count; ii++) { DaValue result = results[ii] = new DaValue(); result.Value = ComUtils.ProcessComValue(values[ii]); result.Quality = OpcRcw.Da.Qualities.OPC_QUALITY_GOOD; result.Timestamp = DateTime.UtcNow; result.Error = errors[ii]; } return(results); }