-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Included ModelChanged Eventhandling. Fixed update of nodes after reconnection. #368
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are may additional LOG(INFO), are some of them outdated, or do all provide useful information?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ccvca I´m finish with the review
DashboardClient/DashboardClient.cpp
Outdated
} | ||
} | ||
} | ||
//Hotfix clear subscription cache. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this currently a hotfix? What would be a better solution?
if(value && value.get()->getNodeId() == pNode.get()->NodeId) | ||
return; | ||
if(value && value.get()->getNodeId() == pNode.get()->NodeId) { | ||
//LOG(INFO) << "Allready Subscribed" << value.get()->getNodeId(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you remove the comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll Remove the comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@GoetzGoerisch The linter check seems broken?
DashboardClient/DashboardClient.cpp
Outdated
} | ||
} | ||
//Hotfix clear subscription cache. | ||
m_subscribedValues.clear(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this intended to be outside the If's?
if(placeHolderNode == nullptr) { continue;} | ||
std::list<ModelOpcUa::PlaceholderElement> instances = placeHolderNode->getInstances(); | ||
for(auto& el : instances) { | ||
deleteAndUnsubscribeNode(el); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::foreach
if(placeHolderNode != nullptr) { | ||
std::list<ModelOpcUa::PlaceholderElement> instances = placeHolderNode->getInstances(); | ||
for(std::list<ModelOpcUa::PlaceholderElement>::iterator it = instances.begin(); it != instances.end(); it++) { | ||
deleteAndUnsubscribeNode(*it); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::foreach
DashboardClient/DashboardClient.cpp
Outdated
this->updateAddDataSet(sce.refreshNode); | ||
this->Publish(); | ||
}); | ||
t.detach(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is ensured, that the DashboardClient instance is available until this thread is completed. (e.g. when started before a shutdown of the application)
DashboardClient/DashboardClient.cpp
Outdated
} | ||
this -> Publish(); | ||
}); | ||
t.detach(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Object lifetime issues? (this
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please run a memory check, There are propably more memory leaks.
} | ||
this -> Publish(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indentation looks suscious.
A continue
inside should allow to preoces more than 10 Events per seconds (in case of busy OPC UA Servers)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replaced by Threadsafe queue!
|
||
void DashboardClient::updateDeleteDataSet(ModelOpcUa::NodeId_t refreshNodeId) { | ||
auto search = browsedSimpleNodes.find(refreshNodeId); | ||
if( search != browsedSimpleNodes.end()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invert + Return
if( search != browsedSimpleNodes.end()) { | ||
std::shared_ptr<const ModelOpcUa::SimpleNode> simpleNode = search->second; | ||
auto childNodes = simpleNode->ChildNodes; | ||
if(!childNodes.empty()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invert + Return
} | ||
void DashboardClient::deleteAndUnsubscribeNode(const ModelOpcUa::SimpleNode simpleNode) { | ||
const std::list<std::shared_ptr<const ModelOpcUa::Node>> children = simpleNode.ChildNodes; | ||
for(auto node : children) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks identical to the method above? Use a single function for this?
} | ||
void DashboardClient::subscribeEvents() { | ||
auto ecbf = [this](IDashboardDataClient::StructureChangeEvent sce) { | ||
this->m_eventqueue.push(sce); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::queue is not thread safe, mutex required.
} | ||
|
||
contentFilter.elementsSize = 1; | ||
contentFilter.elements = (UA_ContentFilterElement* ) UA_Array_new(contentFilter.elementsSize, &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENT]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UA_ContentFilterElement_new?
if(contentFilterElement.filterOperands) { | ||
contentFilterElement.filterOperands[0] = extensionObject; | ||
} else { | ||
UA_ContentFilterElement_delete(&contentFilterElement); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deleting a stack variable?
item.requestedParameters.filter.content.decoded.type = &UA_TYPES[UA_TYPES_EVENTFILTER]; | ||
|
||
UA_MonitoredItemCreateResult result = UA_Client_MonitoredItems_createEvent(client, subId, UA_TIMESTAMPSTORETURN_BOTH, item, this, handler_events, NULL); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} | ||
UA_DeleteSubscriptionsRequest_clear(&deleteRequest); | ||
UA_DeleteSubscriptionsResponse_clear(&response); | ||
UA_Array_delete(pSubscriptionId, 1, &UA_TYPES[UA_TYPES_UINT32]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this already deleted by the previous UA_DeleteSubscriptionsRequest_clear
?
Dashboard::IDashboardDataClient::eventCallbackFunction_t eventcallback) { | ||
this->eventcallback = eventcallback; | ||
UA_CreateSubscriptionRequest request = UA_CreateSubscriptionRequest_default(); | ||
UA_CreateSubscriptionResponse response = UA_Client_Subscriptions_create(client, request, NULL, NULL, NULL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing _clear
} | ||
|
||
void DashboardClient::startEventThread() { | ||
if (m_eventThreadRunning) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
m_eventThreadRunning is
- a missleading name, more like m_keepEventThreadRunning
- is m_eventThreadRunning synchronized and wrapped by a mutex?
m_eventThread = std::thread(func); | ||
} | ||
void DashboardClient::stopEventThread() { | ||
m_eventThreadRunning = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
m_eventThreadRunning is not protected. Might lead to memory corruption
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replaced by atomic bool.
@@ -25,7 +25,22 @@ namespace Umati | |||
class IDashboardDataClient | |||
{ | |||
public: | |||
/// Struct for handling Events | |||
struct StructureChangeEvent{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can there be more than one true, otherwise use ENUM?
}; | ||
} // namespace OpcUa | ||
} // namespace Umati | ||
void SubscriptionUnsubscribe(UA_Client *client, std::vector<int32_t> monItemIds, std::vector<int32_t> clientHandles){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider moving some parts out to reusable functions?
this->startEventThread(); | ||
} | ||
|
||
DashboardClient::~DashboardClient() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Best practice is following the rule of tree.
|
||
auto func = [this]() { | ||
int cnt = 0; | ||
while (this->m_eventThreadRunning) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not protected by mutex
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replaced by atomic.
std::recursive_mutex m_dataSetMutex; | ||
std::list<std::shared_ptr<DataSetStorage_t>> m_dataSets; | ||
std::map<std::string, LastMessage_t> m_latestMessages; | ||
|
||
bool m_eventThreadRunning; | ||
std::thread m_eventThread; | ||
std::queue<IDashboardDataClient::StructureChangeEvent> m_eventqueue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::queue is not threadsafe! Add mutex/lockfree queue or sth
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replaced by a threadsafe queue.
if(value && value.get()->getNodeId() == pNode.get()->NodeId) | ||
return; | ||
if(value && value.get()->getNodeId() == pNode.get()->NodeId) { | ||
//LOG(INFO) << "Allready Subscribed" << value.get()->getNodeId(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you?
return; | ||
} | ||
auto child = childNodes.front(); | ||
std::shared_ptr<const ModelOpcUa::PlaceholderNode> placeholderNode = std::dynamic_pointer_cast<const ModelOpcUa::PlaceholderNode>(child); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not make data model non-const?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This involves changeing some classes in the model and i the codebase. I want to do this, but maybe it is better to do this in a separate task.
LGTM, after the remaining comments are resolved. |
@mdornaus when could you resolve the remaining comments and rebase? |
… to create open62541cpp::UA_NodeId.
Don't merge, moce to new gateway. |
Added ModelChanged Eventhandling. Refactored Model Changed Eventhandling. Solved Reconnection Issue.