can't propagate event through the address space

Questions regarding the use of the C++ SDK for Server or Client development or integration into customer products ...

Moderator: uasdkcpp

Post Reply
sebastien_a
Sr. Member
Sr. Member
Posts: 12
Joined: 13 Apr 2012, 10:23

can't propagate event through the address space

Post by sebastien_a »

Hi Unified Automation Team,

I try to propagate some Alarm Event through my Address Space but if I subscribe to a root folder (meaning a folder which have lot of subfolders with HasNotifier references and registerEventNotifier() call), I can't see the triggered Alarm.

Just to highlight the problem, let's consider this simple structure:

Code: Select all

root
  Object
      Folder_1      (HasNotifier from Folder_1 to Folder)
          Folder_2        (HasNotifier from Folder_2 to Folder 3)
              Folder_3        (HasNotifier from Folder_3 to Folder 4)
                   Folder_4  	  (HasNotifier from Folder_4 to Folder 5)
                         Folder_5	(hasEventSource  from Folder_5 to stateAlarm)
                               stateAlarm      (hasCondition from stateAlarm to MyAlarm)
                               MyAlarm  


The full event Hierarchy is similar to the example given in lesson 6.

If I subscribe to "Folder_5" node, I can see the triggered Alarm.
If I subscribe to "Folder_1" node, the triggered Alarm didn't appears.
If I subscribe to "Server" node, I can see the triggered Alarm even if I don't make HasNotifier references between "Server" node and the Folders or stateAlarm nodes and even if I don't call the registerEventNotifier() (wow, that confused me...)

Could we propagate events in more than just one Level?

Below is the code for this simple example, I think that nothing is missing (references and call to registerEventNotifier() seems OK, based on lesson 6)


Code: Select all

UaStatus MyNodeManager::afterStartUp(){

    this->setFiresEvents(OpcUa_True);

    UaStatus ret;
    /**
     * Create 5 folder/sub-folder recursively to form a tree
     */
    UaNodeId nodeParent = OpcUaId_ObjectsFolder;
    for(unsigned int i = 1; i <= 5 ; i++){
    	char str[80];
    	sprintf(str,"Folder_%i",i);
    	UaAreaFolder* pfolder = new UaAreaFolder(str, UaNodeId(str, getNameSpaceIndex()), m_defaultLocaleId);
    	ret = addNodeAndReference(nodeParent, pfolder, OpcUaId_HasComponent);
    	UA_ASSERT(ret.isGood());

    	ret = addUaReference(nodeParent, pfolder->nodeId(), OpcUaId_HasNotifier);
    	UA_ASSERT(ret.isGood());

    	// Register event notifier tree
    	registerEventNotifier(OpcUaId_Server, pfolder->nodeId());		//MARK 1
    	registerEventNotifier(nodeParent, pfolder->nodeId());		//MARK 2

    	//check that the folder has the EventNotifier attribute set to SubscribeToEvents
    	UA_ASSERT(pfolder->eventNotifier()==Ua_EventNotifier_SubscribeToEvents);

    	nodeParent = pfolder->nodeId();
    }

    /**
     * Now put Source of Alarm in the last folder
     */
    OpcUa::PropertyType* stateAlarm = new OpcUa::PropertyType(UaNodeId("stateAlarm", getNameSpaceIndex()),
    		"stateAlarm",
    		getNameSpaceIndex(),
    		OpcUa_True,
    		1,
    		getNodeManagerConfig());
    ret = addNodeAndReference(nodeParent, stateAlarm, OpcUaId_HasComponent);
    UA_ASSERT(ret.isGood());

    //register event source
    ret = addUaReference(nodeParent, stateAlarm->nodeId(), OpcUaId_HasEventSource);
    UA_ASSERT(ret.isGood());

    //Folder_5 node not notified if I uncomment this line
    registerEventNotifier(nodeParent, stateAlarm->nodeId());    //MARK 3

    /**
     * Now put an Alarm in the last folder
     */
    OpcUa::OffNormalAlarmType* m_pStateOffNormalAlarm = new OpcUa::OffNormalAlarmType(
           UaNodeId("MyStateCondition", getNameSpaceIndex()),  // NodeId
           "MyStateCondition",          // Name of the node used for browse name and display name
           getNameSpaceIndex(),         // Namespace index of the browse name
           this,               			// Node manager responsible for this node
           stateAlarm->nodeId(),        // NodeId of the source node
           "SourceAlarm"); // Name of the source node
     m_pStateOffNormalAlarm->setEventNotifier(Ua_EventNotifier_SubscribeToEvents);

     ret = addNodeAndReference(nodeParent, m_pStateOffNormalAlarm, OpcUaId_HasComponent);
     UA_ASSERT(ret.isGood());

     // Create HasCondition reference from state variable to condition
     ret = addUaReference(stateAlarm, m_pStateOffNormalAlarm, OpcUaId_HasCondition);
     UA_ASSERT(ret.isGood());

     registerEventNotifier(nodeParent, stateAlarm->nodeId());     //MARK 4
     registerEventNotifier(stateAlarm->nodeId(), m_pStateOffNormalAlarm->nodeId());     //MARK 5
     registerEventNotifier(nodeParent, m_pStateOffNormalAlarm->nodeId());     //MARK 6   When in doubt

     /**
      * Now Trigger Alarm
      */
     m_pStateOffNormalAlarm->setConditionName("MyStateCondition");
     m_pStateOffNormalAlarm->setEnabledState(OpcUa_True);
     m_pStateOffNormalAlarm->setAckedState(OpcUa_False);
     m_pStateOffNormalAlarm->setActiveState(OpcUa_True);
     m_pStateOffNormalAlarm->setConfirmedState(OpcUa_True);
     m_pStateOffNormalAlarm->setRetain(OpcUa_True);
     m_pStateOffNormalAlarm->setMessage(UaLocalizedText("en", "Alarm is active"));
     m_pStateOffNormalAlarm->triggerEvent(UaDateTime::now(), UaDateTime::now(), UaByteString());

    return ret;
}

User avatar
Support Team
Hero Member
Hero Member
Posts: 3072
Joined: 18 Mar 2011, 15:09

Re:can't propagate event through the address space

Post by Support Team »

Hi Sebastien,

We found the reason for your issue. The problem was that you used an invalid root node for your notifier tree inside your loop where you are creating the folders. The Server object must be the root for the event notifier tree.

We fixed some other logical problems but they did not cause the issue you described. They did only break OPC UA rules. See the attached code for more details. All changes are marked with "Change Support Team" comments.


Regarding your question "I can see the triggered Alarm even if I don't make HasNotifier references between "Server" node and the Folders or stateAlarm nodes and even if I don't call the registerEventNotifier() (wow, that confused me...)"

All events are provided through the Server object. This is a general rule in OPC UA. Therefore it is not necessary to create any notifier tree to receive events through the Server object.

Best Regards,
Unified Automation Support Team

Code: Select all

    /**
    * Create 5 folder/sub-folder recursively to form a tree
    */
    UaNodeId nodeParent = OpcUaId_ObjectsFolder;
// Begin Change Support Team
    // The event notifier hirarchy starts at the Server object, not at the ObjectsFolder
    UaNodeId eventHirarchyParent = OpcUaId_Server;
// End Change Support Team
    for(unsigned int i = 1; i <= 5 ; i++)
    {
        char str[80];
        sprintf(str,"Folder_%i",i);
        UaAreaFolder* pfolder = new UaAreaFolder(str, UaNodeId(str, getNameSpaceIndex()), m_defaultLocaleId);
        ret = addNodeAndReference(nodeParent, pfolder, OpcUaId_HasComponent);
        UA_ASSERT(ret.isGood());

// Begin Change Support Team
        //ret = addUaReference(nodeParent, pfolder->nodeId(), OpcUaId_HasNotifier);
        // The event notifier hirarchy starts at the Server object
        ret = addUaReference(eventHirarchyParent, pfolder->nodeId(), OpcUaId_HasNotifier);
// End Change Support Team
        UA_ASSERT(ret.isGood());

        // Register event notifier tree
// Begin Change Support Team
        // registerEventNotifier(OpcUaId_Server, pfolder->nodeId());        //MARK 1
        // registerEventNotifier(nodeParent, pfolder->nodeId());        //MARK 2
        // Notifier tree has only one root, the Server object
        // This change already fixes your problem
        registerEventNotifier(eventHirarchyParent, pfolder->nodeId());
// End Change Support Team

        //check that the folder has the EventNotifier attribute set to SubscribeToEvents
        UA_ASSERT(pfolder->eventNotifier()==Ua_EventNotifier_SubscribeToEvents);
        nodeParent = pfolder->nodeId();
// Begin Change Support Team
        // Starting with the first folder, the event hirarchy parent is the same like the node parent
        eventHirarchyParent = nodeParent;
// End Change Support Team
    }

    /**
    * Now put Source of Alarm in the last folder
    */
    OpcUa::PropertyType* stateAlarm = new OpcUa::PropertyType(
        UaNodeId("stateAlarm", getNameSpaceIndex()),
        "stateAlarm",
        getNameSpaceIndex(),
        UaVariant((OpcUa_Boolean)OpcUa_True),
        1,
        getNodeManagerConfig());
    ret = addNodeAndReference(nodeParent, stateAlarm, OpcUaId_HasComponent);
    UA_ASSERT(ret.isGood());

    //register event source
    ret = addUaReference(nodeParent, stateAlarm->nodeId(), OpcUaId_HasEventSource);
    UA_ASSERT(ret.isGood());

// Begin Change Support Team
    //Folder_5 node not notified if I uncomment this line
    //registerEventNotifier(nodeParent, stateAlarm->nodeId());    //MARK 3

    // The stateAlarm property is the event source but can not be an event notifier
    // Only objects can be event notifiers
    registerEventSource(nodeParent, stateAlarm->nodeId());
// End Change Support Team

    /**
    * Now put an Alarm in the last folder
    */
    OpcUa::OffNormalAlarmType* m_pStateOffNormalAlarm = new OpcUa::OffNormalAlarmType(
        UaNodeId("MyStateCondition", getNameSpaceIndex()),  // NodeId
        "MyStateCondition",          // Name of the node used for browse name and display name
        getNameSpaceIndex(),         // Namespace index of the browse name
        this,                           // Node manager responsible for this node
        stateAlarm->nodeId(),        // NodeId of the source node
        "SourceAlarm"); // Name of the source node
// Begin Change Support Team
    // Condition objects are normally not an event notifier
    // m_pStateOffNormalAlarm->setEventNotifier(Ua_EventNotifier_SubscribeToEvents);
// End Change Support Team

    ret = addNodeAndReference(nodeParent, m_pStateOffNormalAlarm, OpcUaId_HasComponent);
    UA_ASSERT(ret.isGood());

    // Create HasCondition reference from state variable to condition
    ret = addUaReference(stateAlarm, m_pStateOffNormalAlarm, OpcUaId_HasCondition);
    UA_ASSERT(ret.isGood());

// Begin Change Support Team
    // This makes no sense for different reasons
    // - Properties can not be notifiers and are not allowed in a notifier tree
    // - Condition objects are not used as notifier, not even as event source
    //registerEventNotifier(nodeParent, stateAlarm->nodeId());     //MARK 4
    //registerEventNotifier(stateAlarm->nodeId(), m_pStateOffNormalAlarm->nodeId());     //MARK 5
    //registerEventNotifier(nodeParent, m_pStateOffNormalAlarm->nodeId());     //MARK 6   When in doubt
// End Change Support Team

    /**
    * Now Trigger Alarm
    */
    m_pStateOffNormalAlarm->setConditionName("MyStateCondition");
    m_pStateOffNormalAlarm->setEnabledState(OpcUa_True);
    m_pStateOffNormalAlarm->setAckedState(OpcUa_False);
    m_pStateOffNormalAlarm->setActiveState(OpcUa_True);
    m_pStateOffNormalAlarm->setConfirmedState(OpcUa_True);
    m_pStateOffNormalAlarm->setRetain(OpcUa_True);
    m_pStateOffNormalAlarm->setMessage(UaLocalizedText("en", "Alarm is active"));
    m_pStateOffNormalAlarm->triggerEvent(UaDateTime::now(), UaDateTime::now(), UaByteString());
Best regards
Unified Automation Support Team

sebastien_a
Sr. Member
Sr. Member
Posts: 12
Joined: 13 Apr 2012, 10:23

Re:can't propagate event through the address space

Post by sebastien_a »

Hi Unified Automation Team,

Great thanks for your help!
That's much clearer in my mind now.

Regards,

Sébastien

Post Reply