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;
}