23 #include "open62541/plugin/log_stdout.h"
28 static UA_StatusCode fireVoidEvent(void_observer_data* data,
const string& pv_name,
const UA_Logger*
logger) {
30 UA_NodeId void_event_NodeId = UA_NODEID_STRING(1,
const_cast<char*
>(
"VoidEventType"));
31 UA_StatusCode retval = UA_Server_createEvent(data->mappedServer, void_event_NodeId, &outId);
32 if(retval != UA_STATUSCODE_GOOD) {
33 string error_message =
"Creation of the void Event failed with StatusCode ";
34 error_message.append(UA_StatusCode_name(retval));
35 throw std::logic_error(error_message);
37 auto pv = data->csManager->getProcessVariable(pv_name);
38 auto eventValidity =
static_cast<UA_Int32
>(pv->dataValidity());
39 retval = UA_Server_writeObjectProperty_scalar(data->mappedServer, outId,
40 UA_QUALIFIEDNAME(1,
const_cast<char*
>(
"Validity")), &eventValidity, &UA_TYPES[UA_TYPES_INT32]);
41 if(retval != UA_STATUSCODE_GOOD) {
42 string error_message =
"Setting void event validity failed with StatusCode ";
43 error_message.append(UA_StatusCode_name(retval));
44 throw std::logic_error(error_message);
46 UA_String eventSourceName = UA_String_fromChars(pv_name.c_str());
47 retval = UA_Server_writeObjectProperty_scalar(data->mappedServer, outId,
48 UA_QUALIFIEDNAME(0,
const_cast<char*
>(
"SourceName")), &eventSourceName, &UA_TYPES[UA_TYPES_STRING]);
49 if(retval != UA_STATUSCODE_GOOD) {
50 string error_message =
"Setting void event SourceName failed with StatusCode ";
51 error_message.append(UA_StatusCode_name(retval));
52 throw std::logic_error(error_message);
54 UA_String_clear(&eventSourceName);
55 UA_LocalizedText eventMessage =
56 UA_LOCALIZEDTEXT(
const_cast<char*
>(
"en-US"),
const_cast<char*
>(
"ChimeraTK::Void written."));
57 retval = UA_Server_writeObjectProperty_scalar(data->mappedServer, outId,
58 UA_QUALIFIEDNAME(0,
const_cast<char*
>(
"Message")), &eventMessage, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
59 if(retval != UA_STATUSCODE_GOOD) {
60 string error_message =
"Setting void event Message failed with StatusCode ";
61 error_message.append(UA_StatusCode_name(retval));
62 throw std::logic_error(error_message);
64 UA_UInt16 eventSeverity = 100;
65 retval = UA_Server_writeObjectProperty_scalar(data->mappedServer, outId,
66 UA_QUALIFIEDNAME(0,
const_cast<char*
>(
"Severity")), &eventSeverity, &UA_TYPES[UA_TYPES_UINT16]);
67 if(retval != UA_STATUSCODE_GOOD) {
68 string error_message =
"Setting void event Severity failed with StatusCode ";
69 error_message.append(UA_StatusCode_name(retval));
70 throw std::logic_error(error_message);
72 UA_UInt16_clear(&eventSeverity);
75 id.namespaceIndex = 1;
76 id.identifierType = UA_NODEIDTYPE_STRING;
77 id.identifier.string = UA_String_fromChars((data->rootFolder + pv_name).c_str());
78 retval = UA_Server_writeObjectProperty_scalar(
79 data->mappedServer, outId, UA_QUALIFIEDNAME(1,
const_cast<char*
>(
"cs_path")), &
id, &UA_TYPES[UA_TYPES_NODEID]);
80 if(retval != UA_STATUSCODE_GOOD) {
81 string error_message =
"Setting void event cs_path failed with StatusCode ";
82 error_message.append(UA_StatusCode_name(retval));
83 throw std::logic_error(error_message);
86 UA_String eventDescription = UA_String_fromChars(pv->getDescription().c_str());
87 const UA_String null_str = UA_STRING_NULL;
88 if(UA_String_equal(&eventDescription, &null_str) !=
true) {
89 retval = UA_Server_writeObjectProperty_scalar(data->mappedServer, outId,
90 UA_QUALIFIEDNAME(1,
const_cast<char*
>(
"Description")), &eventDescription, &UA_TYPES[UA_TYPES_STRING]);
91 if(retval != UA_STATUSCODE_GOOD) {
92 string error_message =
"Setting void event description failed with StatusCode ";
93 error_message.append(UA_StatusCode_name(retval));
94 throw std::logic_error(error_message);
97 UA_String_clear(&eventDescription);
98 UA_String eventType = UA_String_fromChars(
"Void");
99 retval = UA_Server_writeObjectProperty_scalar(data->mappedServer, outId,
100 UA_QUALIFIEDNAME(1,
const_cast<char*
>(
"Type")), &eventType, &UA_TYPES[UA_TYPES_STRING]);
101 if(retval != UA_STATUSCODE_GOOD) {
102 string error_message =
"Setting void event Type failed with StatusCode ";
103 error_message.append(UA_StatusCode_name(retval));
104 throw std::logic_error(error_message);
106 UA_String_clear(&eventType);
107 UA_DateTime eventTime = UA_DateTime_now();
108 retval = UA_Server_writeObjectProperty_scalar(data->mappedServer, outId,
109 UA_QUALIFIEDNAME(0,
const_cast<char*
>(
"Time")), &eventTime, &UA_TYPES[UA_TYPES_DATETIME]);
110 if(retval != UA_STATUSCODE_GOOD) {
111 string error_message =
"Setting void event Time failed with StatusCode ";
112 error_message.append(UA_StatusCode_name(retval));
113 throw std::logic_error(error_message);
115 UA_DateTime_clear(&eventTime);
117 retval = UA_Server_triggerEvent(data->mappedServer, outId, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER),
nullptr, UA_TRUE);
118 if(retval != UA_STATUSCODE_GOOD) {
119 string error_message =
"Triggering void event failed with StatusCode ";
120 error_message.append(UA_StatusCode_name(retval));
121 throw std::logic_error(error_message);
123 UA_LOG_DEBUG(
logger, UA_LOGCATEGORY_USERLAND,
"Fire Void Event for PV with ID %s", pv_name.c_str());
127 static void updateLoop(void_observer_data* data,
const UA_Logger*
logger) {
130 std::map<TransferElementID, std::string> idToNameMap;
131 for(
auto pv : data->pvs) {
132 group.add(data->csManager->getProcessArray<Void>(pv));
133 idToNameMap[data->csManager->getProcessArray<Void>(pv)->getId()] = pv;
154 while(data->adapter->isRunning()) {
156 auto id = group.readAny();
157 fireVoidEvent(data, idToNameMap.at(
id),
logger);
159 UA_LOG_INFO(
logger, UA_LOGCATEGORY_USERLAND,
"Void observer thread terminated.");
162 catch(boost::thread_interrupted&) {
163 UA_LOG_INFO(
logger, UA_LOGCATEGORY_USERLAND,
"Void observer thread terminated.");
175 UA_StatusCode
addEventProperty(UA_Server* server, UA_NodeId eventNodeId,
char* property_name, UA_NodeId dtype) {
176 UA_NodeId propertyNodeId;
177 UA_VariableAttributes vattr = UA_VariableAttributes_default;
178 vattr.dataType = dtype;
179 vattr.displayName = UA_LOCALIZEDTEXT(
const_cast<char*
>(
"en-us"), property_name);
180 vattr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
181 UA_StatusCode retval = UA_Server_addVariableNode(server, UA_NODEID_NULL, eventNodeId,
182 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), UA_QUALIFIEDNAME(1, property_name),
183 UA_NODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE), vattr,
nullptr, &propertyNodeId);
184 if(retval != UA_STATUSCODE_GOOD) {
185 string error_message =
"Failed to add the property ";
186 error_message.append(property_name);
187 error_message.append(
" with StatusCode ");
188 error_message.append(UA_StatusCode_name(retval));
189 throw std::logic_error(error_message);
191 retval = UA_Server_addReference(server, propertyNodeId, UA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE),
192 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_MODELLINGRULE_MANDATORY),
true);
193 if(retval != UA_STATUSCODE_GOOD) {
194 string error_message =
"Failed to set the reference to property ";
195 error_message.append(property_name);
196 error_message.append(
" mandatory with StatusCode ");
197 error_message.append(UA_StatusCode_name(retval));
198 throw std::logic_error(error_message);
204 UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
205 attr.displayName = UA_LOCALIZEDTEXT(
const_cast<char*
>(
"en-US"),
const_cast<char*
>(
"VoidEventType"));
206 attr.description = UA_LOCALIZEDTEXT(
const_cast<char*
>(
"en-US"),
const_cast<char*
>(
"The EventType for void nodes"));
207 UA_NodeId void_event_NodeId = UA_NODEID_STRING(1,
const_cast<char*
>(
"VoidEventType"));
208 UA_StatusCode retval = UA_Server_addObjectTypeNode(server, void_event_NodeId,
209 UA_NODEID_NUMERIC(0, UA_NS0ID_BASEEVENTTYPE), UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
210 UA_QUALIFIEDNAME(1,
const_cast<char*
>(
"VoidEventType")), attr,
nullptr,
nullptr);
211 if(retval != UA_STATUSCODE_GOOD) {
212 string error_message =
"Failed to add the VoidEventType with StatusCode ";
213 error_message.append(UA_StatusCode_name(retval));
214 throw std::logic_error(error_message);
217 addEventProperty(server, void_event_NodeId,
const_cast<char*
>(
"cs_path"), UA_TYPES[UA_TYPES_NODEID].typeId);
219 addEventProperty(server, void_event_NodeId,
const_cast<char*
>(
"Description"), UA_TYPES[UA_TYPES_STRING].typeId);
220 retval |=
addEventProperty(server, void_event_NodeId,
const_cast<char*
>(
"Type"), UA_TYPES[UA_TYPES_STRING].typeId);
222 addEventProperty(server, void_event_NodeId,
const_cast<char*
>(
"Validity"), UA_TYPES[UA_TYPES_INT32].typeId);