OpcUaCanOpen
CANopen OPC-UA server
CanBusInterface.cpp
Go to the documentation of this file.
1 //#include "BuildingAutomationTypeIds.h"
2 #include "Ids.h"
3 #include "CanBusInterface.h"
4 #include "AbstractHardware.h"
5 #include "CanNodeObject.h"
6 #include "CanPDOObject.h"
7 #include "CanPDOItem.h"
8 #include "CanSDOObject.h"
9 #include "CanSDOItem.h"
10 #include "CanOpenItem.h"
11 #include "Emergency.h"
12 #include "UaCanBusObject.h"
13 #include "UaCanNodeObject.h"
14 #include "variablehandleuanode.h"
15 #include <thread>
16 #include <memory>
17 #include <boost/assign/std/vector.hpp>
18 
19 using namespace boost::assign;
20 using namespace AddressSpace;
21 
22 
23 unique_ptr<UserDevice::ControlInterface> createControlInterface(void) { return unique_ptr<UserDevice::ControlInterface >(new CanOpen::CanBusInterface()); }
24 
25 //#ifdef WIN32
26 // __declspec(dllexport) ControlInterface *createControlInterface()
27 //#else
28 // ControlInterface *createControlInterface()
29 //#endif
30 // {
31 // ControlInterface *cc;
32 // cc = new CanOpen::CanBusInterface();
33 //
34 // return cc;
35 // }
36 
37 namespace CanOpen {
38 
39  list<UaDeviceMethod<UaControlDeviceGeneric> *> CanBusInterface::m_listInitMethod;
40  list<struct CanBusInterface::InitSet> CanBusInterface::m_listInitSet;
41  vector< AddressSpace::UaCalcItem *> CanBusInterface::m_vCCI;
42  unique_ptr<CanBusAccess> CanBusInterface::g_pCanaccess;
43 
44 // AddressSpace::UaCalcCompiler *CanBusInterface::g_pCompiler;
48  UaStatus CanBusInterface::initialize()
49  {
50  UaStatus ret = OpcUa_Good;
51  // cout << "Initialize Interface" << endl;
52  #ifdef WIN32
53  SetErrorMode(
54  SEM_FAILCRITICALERRORS & SEM_NOGPFAULTERRORBOX & SEM_NOOPENFILEERRORBOX & SEM_NOALIGNMENTFAULTEXCEPT
55  );
56  #endif
57 
58  g_pCanaccess = unique_ptr<CanBusAccess>(new CanBusAccess()); // CAN interface
59 
60 // CanOpen::UaCanTrace::m_CanTraceComponent[lCanTrace] = Log::getComponentHandle("CanModule");
61 // Log::setComponentLogLevel(CanOpen::UaCanTrace::m_CanTraceComponent[lCanTrace], Log::INF);
62 
63  for(list<CanBusObject *>::iterator it = m_CanBusList.begin(); it != m_CanBusList.end(); it++)
64  {
65  try {
66  (*it)->openCanBus();
67 
68  }
69  catch (exception &e) {
70  string bn = (*it)->getCanBusName();
71  LOG(Log::ERR) << "bus=" << bn << " " << e.what() << " " << noExit;
72  if (!noExit)
73  exit(-1);
74  }
75  }
76 
79 // if (!noExit) {
80  for (list<CanBusObject *>::iterator it = m_CanBusList.begin(); it != m_CanBusList.end(); it++)
81  {
82  (*it)->sendInitNmt();
83  (*it)->sendInitNodeNmt();
84  (*it)->startSyncInterval();
85  (*it)->startNodeGuardingInterval();
86 
87  (*it)->initialize();
88  }
89 
90  ret = variableInitSet();
91 
92  std::this_thread::sleep_for(std::chrono::milliseconds(CanOpen::InitTimeout));
93 
94  for (list<CanBusObject *>::iterator it = m_CanBusList.begin(); it != m_CanBusList.end(); it++)
95  {
96  (*it)->waitData();
97  }
98 
99  ret = executeInitMethod();
100 // }
101  return ret;
102  }
103 
104  CanBusInterface::CanBusInterface()
105  {
106  g_pCanaccess = 0;
107  factory[BA_CANBUS] = new DEVICE<CanBusObject,CANBUS>();
109  factory[BA_SDOOBJECT] = new DEVICE<CanSDOObject,SDO>();
113  factory[BA_PDOOBJECT] = new DEVICE<CanPDOObject,PDO>();
114  factory[BA_PDOITEM] = new DEVICE<CanPDOItem,PDOITEM>();
115  factory[BA_EMERGENCY] = new DEVICE<Emergency, NODE>();
116  }
117 
118  CanBusInterface::~CanBusInterface()
119  {
120 // cout << "Delete Interface" << endl;
121 
122 // for_each(m_CanBusList.begin(),m_CanBusList.end(),[](CanBusObject *cbo)
123 // {
125 // delete cbo;
126 // cbo = NULL;
127 // });
128 
129  for(list<CanBusObject *>::iterator it = m_CanBusList.begin(); it != m_CanBusList.end(); it++)
130  {
131  CanBusObject *cbo = (*it);
132  delete cbo;
133  cbo = NULL;
134  }
135 
136  m_CanBusList.clear();
137  cout << "Delete Interface" << endl;
138 
139 // delete g_pCanaccess;
140  }
141 
142  void CanBusInterface::closeInterface()
143  {
144  for (list<CanBusObject *>::iterator it = m_CanBusList.begin(); it != m_CanBusList.end(); it++)
145  {
146  CanBusObject *cbo = (*it);
147  cbo->closeCanBus();
148  }
149  cout << "Close Interface" << endl;
150  }
151 
152  pUserDeviceStruct * CanBusInterface::createInterfaceEntry(pUserDeviceStruct *parent, int code , ::xml_schema::type *conf ,UaNode *pAS)
153  {
154  InterfaceUserDataBase* interf = 0;
155  pUserDeviceStruct *rPointer = 0;
156  UaStatus ret = OpcUa_Good;
157 
158  if (parent == NULL) {
159  if (code == BA_CANBUS) {
160  interf = factory[code]->createHardwareEntry(parent,conf,pAS,code);
161  m_CanBusList.push_back(static_cast<CanBusObject *>(interf));
162  rPointer = new pUserDeviceStruct(interf);
163  }
164  }
165  else {
166  if (factory.find(code) != factory.end() ) {
167  interf = factory[code]->createHardwareEntry(parent,conf,pAS,code);
168  rPointer = new pUserDeviceStruct(interf);
169  }
170  else
171  {
172  InterfaceUserDataBase *parentInterf = static_cast<InterfaceUserDataBase*>(parent->getDevice());
174  interf = newd->createHardwareEntry(parent,conf,pAS,code);
175  ret = parentInterf->connectCode(code, conf, pAS);
176  rPointer = new pUserDeviceStruct(interf);
177  delete newd;
178  }
179  }
180  return rPointer;
181  }
182 
188  UaStatus CanBusInterface::CreateXmlParser(UaString &sXmlFileName/*,UaString &sLogFileName*/)
189  {
190  UaStatus ret = OpcUa_True;
191 
192  m_sXmlFileName = sXmlFileName;
193 // m_sLogFileName = sLogFileName;
194 
195  try {
196  cout << "Config file " << m_sXmlFileName.toUtf8() << endl;
197  auto_ptr< ::CanOpenOpcServerConfig > vDoc( CanOpenOpcServerConfig_(m_sXmlFileName.toUtf8()));
198 
199  m_nodetypes = vDoc->NODETYPE();
200  m_canbuses = vDoc->CANBUS();
201  m_items = vDoc->ITEM();
202  m_regexprisson = vDoc->REGEXPR();
203  m_settings = vDoc->SETTINGS();
204  m_execute = vDoc->atStartup();
205  m_setvalue = vDoc->SET();
206  }
207  catch (const xml_schema::exception& e)
208  {
209  cout << "Parser error " << e << endl;
210 
211  cout << e.what() << " " << e << endl;
212  return OpcUa_Bad;
213  }
214 
215  return ret;
216 
217  }
218 
219 // UaStatus CanBusInterface::CreateAddressSpace(NmBuildingAutomation *nManager)
220  UaStatus CanBusInterface::CreateAddressSpace(AddressSpace::NmBuildingAutomation *nManager, NodeManagerNodeSetXml* pXmlNodeManager, NodeManagerConfig *pDefaultNodeManager)
221 
222  {
223  UaStatus ret;
224  UaString sName;
225  UaStatus Status;
226  OpcUa_UInt32 uMaxTraceEntries = 10000;
227  OpcUa_UInt32 uMaxBackupFiles = 4;
228 
229  cout << "Create Address Space" << endl;
230 
231  m_pNodeManager = nManager;
232  m_pTypeNodeManager = pXmlNodeManager;
233  m_pDefaultNodeManager = pDefaultNodeManager;
234 
235 // g_pCompiler = new UaCalcCompiler(nManager);
236 
237  ret = createNodeTypes();
238  UA_ASSERT(ret.isGood());
239  if (ret.isBad())
240  return ret;
244  OpcUa_UInt16 nIdx = m_pNodeManager->getNameSpaceIndex();
245  UaVariant defaultValue;
246  defaultValue.setUInt32(0);
247 
248 
249  m_Trace= new UaCanTrace(
250  UaNodeId("TraceLevel", nIdx), // NodeId of the Variable
251  "TraceLevel", // Name of the Variable
252  nIdx, // Namespace index of the browse name (same like NodeId)
253  defaultValue, // Initial value
254  Ua_AccessLevel_CurrentRead | Ua_AccessLevel_CurrentWrite, // Access level
255  m_pNodeManager); // Node manager for this variable
256 
257  ret = m_pNodeManager->addNodeAndReference(OpcUaId_ObjectsFolder, m_Trace, OpcUaId_HasComponent);
258  UA_ASSERT(ret.isGood());
259 
260  ret = createCanbuses();
261  UA_ASSERT(ret.isGood());
262  if (ret.isBad())
263  return ret;
264 /*
265  ret = g_pCompiler->CompileItems(m_items,m_regexprisson); //create Calculation Item
266  UA_ASSERT(ret.isGood());
267  if (ret.isBad())
268  return ret;
269 
270  ret = g_pCompiler->CreateItems();
271  UA_ASSERT(ret.isGood());
272  if (ret.isBad())
273  return ret;
274 */
275  ret = CompileItems(NULL, m_items, m_regexprisson, nManager); //create Calculation Item
276  UA_ASSERT(ret.isGood());
277  if (ret.isBad())
278  return ret;
279 
280 
281  ret = createListInitmethod(m_execute,NULL, nManager);
282  UA_ASSERT(ret.isGood());
283  if (ret.isBad())
284  return ret;
285 
286  ret = createListInitSet(m_setvalue, NULL, nManager);
287  UA_ASSERT(ret.isGood());
288  if (ret.isBad())
289  return ret;
290 
291  if (m_settings.present()) {
292  CanOpenOpcServerConfig::SETTINGS_type settingst = m_settings.get();
293 // if (settingst. NGcounter.present()) {
294  CanOpen::CanNodeObject::ngCounter = settingst.NGcounter();// NGcounter.get();
295  cout << "NG repeating counts = " << CanOpen::CanNodeObject::ngCounter << endl;
296 // }
297 
298 // if (settingst.DisconectRecovery.present()) {
300  cout << "Recover after reconnection = " << (bool)CanOpen::CanNodeObject::DisconectRecovery << endl;
301 // }
302 
303 // if (settingst.TypeConversion.present()) {
304  CanOpen::TypeConversion = settingst.TypeConversion(); // .get();
305  cout << "Type Conversion " << (bool)CanOpen::TypeConversion << endl;
306 // }
307 // else
308 // CanOpen::TypeConversion = true;
309 
310 // if (settingst.InitTimeout.present()) {
311  CanOpen::InitTimeout = settingst.InitTimeout(); // .get();
312  cout << "Init Timeout " << (long)CanOpen::InitTimeout << endl;
313 // }
314 // else
315 // CanOpen::InitTimeout = 10;
316 
317  }
318 
319  UaDataValue udt;
320  UaVariant val;
321 
322  UaDateTime sdt = UaDateTime::now();
323 
324  initCalculation();
325  UA_ASSERT(ret.isGood());
326 // delete g_pCompiler;
327 // g_pCompiler = NULL;
328 
329  return ret;
330  }
331 
332  UaStatus CanBusInterface::createNodeTypes()
333  {
334  UaStatus addStatus;
335 
336  UaDeviceNodeType* pCanNodeType = NULL;
337 
338  for(CanOpenOpcServerConfig::NODETYPE_sequence::iterator itnt(m_nodetypes.begin()); itnt != m_nodetypes.end(); itnt++ ) {
339  NODETYPE *nodTyp = &(*itnt);
340 
341  /**************************************************************
342  * Create the CanNode Type
343  **************************************************************/
344 
345  // Add ObjectType "CanNodeType"
346  UaNodeId uTypeNode = UaNodeId(nodTyp->name().c_str(), m_pNodeManager->getNameSpaceIndex());
347  pCanNodeType = new UaDeviceNodeType(
348  nodTyp->name().c_str(), // Used as string in browse name and display name
349  uTypeNode, // NodeId for types
350  m_sLocale, // Default LocaleId for UaLocalizedText strings
351  OpcUa_False); // Abstract object type -> can not be instantiated
352 
353  // Add new node to address space by creating a reference from BaseObjectType to this new node
354  addStatus = m_pNodeManager->addNodeAndReference(OpcUaId_BaseObjectType,pCanNodeType, OpcUaId_HasComponent);
355  UA_ASSERT(addStatus.isGood());
356  UaObjectType* uv = m_pNodeManager->getInstanceDeclarationObjectType(BA_CANNODETYPE);
357  addStatus = m_pNodeManager->addUaReference(pCanNodeType->nodeId(), uv->nodeId(), OpcUaId_HasSubtype);
358  UA_ASSERT(addStatus.isGood());
359  pCanNodeType->setXsdData(nodTyp);
360 
361  }
362  return addStatus;
363  }
364 
365 
366  UaStatus CanBusInterface::createCanbuses()
367  {
368  UaStatus addStatus;
369  UaVariant defaultValue;
370  UaNodeId uaId;
371  UaString newName;
372 
373  OpcUa_UInt16 indx = m_pNodeManager->getNameSpaceIndex();
374 
376 
377  UaString sLocale = ((AddressSpace::NmBuildingAutomation*)m_pNodeManager)->getDefaultLocale();
378 
379  UaControlDeviceGeneric *pcanbus = NULL;
380 
384  for( CanOpenOpcServerConfig::CANBUS_iterator it(m_canbuses.begin()); it != m_canbuses.end(); it++) {
385  CANBUS *canb = (CANBUS *)&(*it);
386 
387  predCanBus pred(canb->port());
388  list<CanBusObject *>::iterator o = find_if(m_CanBusList.begin(), m_CanBusList.end(), pred);
389 
390  if (o == m_CanBusList.end()){
391  UaObjectType *pInstanceDeclarationObject = m_pNodeManager->getInstanceDeclarationObjectType(BA_CANBUS); // take the type
392  pcanbus = new UaControlDeviceGeneric(canb->name().c_str(), UaNodeId(canb->name().c_str(), indx), pNodeManager, pInstanceDeclarationObject, canb, NULL);
393  addStatus = m_pNodeManager->addNodeAndReference(OpcUaId_ObjectsFolder, pcanbus, OpcUaId_Organizes);
394  UA_ASSERT(addStatus.isGood());
395  }
396  else
397  {
398  cerr << "Can Port " << canb->port() << " is duplicated" << endl;
399  exit(-1);
400  }
401 
402  addStatus = createNodes(canb->NODE(),pcanbus); // create CAN Nodes
403  UA_ASSERT(addStatus.isGood());
404 
405  addStatus = CompileItems(pcanbus,canb->ITEM(),canb->REGEXPR(), m_pNodeManager); //create Calculation Item
406  UA_ASSERT(addStatus.isGood());
407  if (addStatus.isBad()) {
408  LOG(Log::ERR) << "Calc Item" << " failed to create Calc Item, for canbus= " << pcanbus->browseName().toString().toUtf8() << " " << addStatus.pDiagnosticInfo()->m_localizedText.toString().toUtf8();
409  cerr << "Error Cacl Item " << pcanbus->browseName().toString().toUtf8() << " " << addStatus.pDiagnosticInfo()->m_localizedText.toString().toUtf8() << endl;
410 
411  exit(-1);
412  }
413 
414  addStatus = createListInitmethod(canb->atStartup(), pcanbus,pNodeManager);
415  UA_ASSERT(addStatus.isGood());
416  addStatus = createListInitSet(m_setvalue, NULL, pNodeManager);
417  UA_ASSERT(addStatus.isGood());
418  if (addStatus.isBad())
419  return addStatus;
420 
421  }
422 
423  return addStatus;
424  }
425 
426 
427  UaStatus CanBusInterface::createNodes(CANBUS::NODE_sequence &nd,UaControlDeviceGeneric *pcanbus)
428  {
429  UaStatus ret;
430 
431  UaCanNodeObject * pcannode;
432  UaString nodeName, typeName;
433  UaNodeId nodeId,nodeTypeId;
434  OpcUa_UInt16 indx = m_pNodeManager->getNameSpaceIndex();
435 
437 
438  for (CANBUS::NODE_iterator it=nd.begin(); it != nd.end(); ++it)
439  {
440  NODE *nodeb = (NODE *)&(*it);
441 
442  nodeName = it->name().c_str();
443  nodeId = pNodeManager->getNewNodeId(pcanbus,nodeName);
444  UaNode *node = pNodeManager->findNode(nodeId);
445  pUserDeviceStruct* cb = static_cast<pUserDeviceStruct*>(pcanbus->getUserData());
446  if (node == NULL) {
447  if (!it->type().present()) {
448 // UaObject *pInstanceDeclarationObject = getInstanceDeclarationObjectType(BA_CANNODETYPE); // take the type
449 
450 // pcannode = new UaCanNodeObject(nodeb, pInstanceDeclarationObject,nodeId,pNodeManager,cb);
451  pcannode = new UaCanNodeObject(nodeb, NULL, nodeId, pNodeManager, cb);
452  }
453  else {
454  // Find Node Type by name
455  typeName = it->type().get().c_str();
456  nodeTypeId = UaNodeId(typeName,indx);
457  UaDeviceNodeType *pNode = (UaDeviceNodeType *)pNodeManager->findNode(UaNodeId(typeName,indx));
458  if (pNode == NULL) {
459  cerr << "Node Type" << it->type().get().c_str() << " has not been defined" << endl;
460  exit(-1);
461  }
462  pcannode = new UaCanNodeObject(nodeb,(UaObject *)pNode, nodeId,pNodeManager,cb);
463  }
464  ret = m_pNodeManager->addNodeAndReference( pcanbus,pcannode, OpcUaId_Organizes);
465  UA_ASSERT(ret.isGood());
466  ret = createListInitmethod(nodeb->atStartup(), pcannode, pNodeManager);
467  UA_ASSERT(ret.isGood());
468  ret = createListInitSet(m_setvalue, NULL, pNodeManager);
469  UA_ASSERT(ret.isGood());
470  if (ret.isBad())
471  return ret;
472  }
473  else {
474  cerr << "Node " << nodeName.toUtf8() << " is duplicated" << endl;
475  exit(-1);
476  }
477  }
478  return ret;
479  }
480 
481  VariableHandle* CanBusInterface::getVariableHandler(Session* session, VariableHandle::ServiceType serviceType, OpcUa_NodeId *nodeid, OpcUa_Int32 attributeId)
482  {
483 
484  OpcUa_ReferenceParameter(session);
485  OpcUa_ReferenceParameter(serviceType);
486 
487  UaNodeId t_uanodeid;
488 
489  VariableHandle* pVariableHandle = NULL;
490 
491  if ( attributeId == OpcUa_Attributes_Value )
492  {
493  OpcUa_UInt32 idt;
494  // The value attribute is requested - we are using the IOManager
495  UaNode *pUaNode = getNodeManager()->findNode(*nodeid);
496  UaNodeId id = pUaNode->typeDefinitionId();
497  if (id.identifierType() == OpcUa_IdentifierType_Numeric) {
498  idt = id.identifierNumeric();
499  if (idt == BA_SDOITEMTYPE ||
500  idt == BA_SDOITEMTYPE1 ||
501  idt == BA_SDOITEMTYPE2 ||
502  idt == BA_SDOITEMTYPE3
503  )
504  {
505  pVariableHandle = new VariableHandleUaNode;
506  t_uanodeid = getCanNodeNodeId(pUaNode);
507  UaNode *pParNode = getNodeManager()->findNode(t_uanodeid);
508  pVariableHandle->m_pIOManager = ((UaCanNodeObject *)pParNode)->getSDOIOManager();
509  pVariableHandle->m_AttributeID = attributeId;
510  ((VariableHandleUaNode *)pVariableHandle)->setUaNode(pUaNode);
511  }
512  /*
513  else {
514  if (idt == Ba_PDOType_Item)
515  {
516  if (((UaVariable *)pUaNode)->accessLevel() == Ua_AccessLevel_CurrentWrite) {
517  pVariableHandle = new VariableHandleUaNode;
518  t_uanodeid = getNodeManager()->getTopNodeId(pUaNode);
519  UaNode *pTopNode = getNodeManager()->findNode(t_uanodeid);
520  pVariableHandle->m_pIOManager = ((UaCanBusObject *)pTopNode)->getPDOIOManager();
521  pVariableHandle->m_AttributeID = attributeId;
522  ((VariableHandleUaNode *)pVariableHandle)->setUaNode(pUaNode);
523  }
524  }
525  }
526  */
527  }
528  }
529  return pVariableHandle;
530  }
531 
532  UaNodeId CanBusInterface::getCanNodeNodeId(UaNode *pNode)
533  {
534  UaNodeId uNodeId;
535  UaNode * uNode;
536  uNode = getNodeManager()->getUpNode(pNode);
537  if (uNode->typeDefinitionId().identifierNumeric() == BA_CANNODETYPE)
538  uNodeId = uNode->nodeId();
539  else {
540  uNode = getNodeManager()->getUpNode(uNode);
541 // printf("NodeId %d\n",uNode->typeDefinitionId().identifierNumeric());
542  if (uNode->typeDefinitionId().identifierNumeric() == BA_CANNODETYPE) {
543  uNodeId = uNode->nodeId();
544  }
545  else uNodeId.clear();
546  }
547  return uNodeId;
548  }
549 
555  IOManager* CanBusInterface::getIOManager(UaNode* pUaNode, OpcUa_Int32 attributeId)
556  {
557 
558  UaNodeId t_uanodeid;
559  if (attributeId == OpcUa_Attributes_Value) {
560  UaNodeId id = pUaNode->typeDefinitionId();
561  if (id.identifierType() == OpcUa_IdentifierType_Numeric) {
562  OpcUa_UInt32 idt = id.identifierNumeric();
563  /*
564  if (idt == Ba_PDOType_Item)
565  {
566  t_uanodeid = m_pNodeManager->getTopNodeId(pUaNode);
567  UaNode *pTopNode = m_pNodeManager->findNode(t_uanodeid);
568  if (((UaControlDeviceItem *)pUaNode)->accessLevel() == Ua_AccessLevel_CurrentWrite)
569  {
570  return ((UaCanBusObject *)pTopNode)->getPDOIOManager(); //PDO thread per bus
571  }
572  }
573  else {
574  */
575  if (idt == BA_SDOITEMTYPE ||
576  idt == BA_SDOITEMTYPE1 ||
577  idt == BA_SDOITEMTYPE2 ||
578  idt == BA_SDOITEMTYPE3
579  )
580  {
581  t_uanodeid = getCanNodeNodeId(pUaNode);
582  UaNode *pParNode = m_pNodeManager->findNode(t_uanodeid);
583  return ((UaCanNodeObject *)pParNode)->getSDOIOManager(); //SDO thread per node
584  }
585  }
586  }
587 
588  return NULL;
589  }
590 
591  UaStatus CanBusInterface::createListInitmethod(CanOpenOpcServerConfig::atStartup_sequence &ex, UaControlDeviceGeneric *parent, NmBuildingAutomation *nManager)
592  {
593 
594  for (CanOpenOpcServerConfig::atStartup_iterator exiter = ex.begin(); exiter != ex.end(); exiter++)
595  {
596  const char *comm = (*exiter).command().get().c_str();
597  UaNodeId uaMethodId = nManager->getNewNodeId(parent, comm);
598 
600  if (dm != NULL)
601  m_listInitMethod.push_front(dm);
602  else
603  {
604  cout << "The command " << comm << " does not define!" << endl;
605  return OpcUa_Bad;
606  }
607  }
608 
609  return OpcUa_Good;
610  }
611 
612  UaStatus CanBusInterface::createListInitSet(CanOpenOpcServerConfig::SET_sequence &ex, UaControlDeviceGeneric *parent, NmBuildingAutomation *nManager)
613  {
614  for (CanOpenOpcServerConfig::SET_iterator exiter = ex.begin(); exiter != ex.end(); exiter++)
615  {
616  const UaString comm = exiter->variable().get().c_str();
617  const UaString vval = exiter->value().get().c_str();
618  UaNodeId uaVarId = nManager->getNewNodeId(parent, comm);
619 
620  OpcUa::BaseDataVariableType *dm = (OpcUa::BaseDataVariableType *)nManager->findNode(uaVarId);
621  if (dm != NULL) {
622  struct InitSet inset;
623  inset.setVar = dm;
624  inset.value = vval;
625  m_listInitSet.push_front(inset);
626  }
627  else
628  {
629  cout << "The variable " << comm << " does not define!" << endl;
630  return OpcUa_Bad;
631  }
632  }
633  return OpcUa_Good;
634  }
635 
636  UaStatus CanBusInterface::executeInitMethod()
637  {
638  UaStatus ret = OpcUa_Good;
639 
640  for (list<UaDeviceMethod<UaControlDeviceGeneric> *>::iterator it = m_listInitMethod.begin(); it != m_listInitMethod.end(); it++)
641  {
642  UaStatus retexec = (*it)->execute();
643  if (retexec.isBad())
644  ret = retexec;
645  }
646  m_listInitMethod.clear();
647  return ret;
648  }
649 
650  UaStatus CanBusInterface::variableInitSet()
651  {
652  UaStatus ret = OpcUa_Good;
653 
654  for (list<struct InitSet> ::iterator it = m_listInitSet.begin(); it != m_listInitSet.end(); it++)
655  {
656  OpcUa::BaseDataVariableType *bvar = it->setVar;
657  OpcUa_Byte acc = bvar->accessLevel();
658  UaString uas = it->value;
659 
660  if (acc & Ua_AccessLevel_CurrentWrite)
661  {
662  UaNodeId uaid = bvar->dataType();
663  OpcUa_Int32 tid = uaid.identifierNumeric();
664  if (tid < 256)
665  {
666  OpcUa_BuiltInType binty = (OpcUa_BuiltInType)tid;
667  UaDataValue udv;
668  UaVariant uav = uas;
669  uav.changeType(binty, false);
670  udv.setValue(uav, false);
671  bvar->setValue(0, udv, true);
672  }
673  }
674  }
675  m_listInitSet.clear();
676  return ret;
677  }
678  UaStatus CanBusInterface::CompileItems(OpcUa::BaseObjectType *pParent, CanOpenOpcServerConfig::ITEM_sequence &itnd, CanOpenOpcServerConfig::REGEXPR_sequence &regex, NmBuildingAutomation *nManager)
679  {
680  UaStatus ret = OpcUa_Good;
681  UaString sName, sFullName, tName;
682  std::string stdName;
683  UaVariant defaultValue;
684  UaDataValue dataValue;
685  UaDateTime udt;
686  UaNodeId uaId;
687  UaVariant val;
688  UaCalcItem* pUaCalcItem;
689 
690  OpcUa_BuiltInType typeName;
691 
692  for (CanOpenOpcServerConfig::ITEM_iterator sit = itnd.begin(); sit != itnd.end(); sit++)
693  {
694  mapDataVariable pVariables;
695  sName = UaString(sit->name().c_str());
696  OpcUa_Int32 minVar = 0xEFFFFFF;
697 
698  ret = createRegVariable((*sit),regex, pVariables, pParent, minVar, nManager);
699 
700  if (ret.isGood()) {
701  if (minVar != INT_MAX) {
702  for (OpcUa_Int32 j = 0; j < minVar; j++)
703  {
704  UaControlVariableMap ucVariables;
705 // UaControlVariableSet ucs;
706  sFullName = UaString("%1_%2").arg(sName).arg(j);
707  uaId = nManager->getNewNodeId(pParent, sFullName);
708  for (mapDataVariable::iterator it = pVariables.begin(); it != pVariables.end(); it++)
709  {
710  string nn = (*it).first;
711  nn.erase(std::remove(nn.begin(), nn.end(), '$'), nn.end());
712  ucVariables[nn] = (*it).second[j];
713  }
714  CanOpenDataAddress::getOpcUaType("double", typeName);
715  UaVariant dv;
716  dv.changeType(typeName, false);
717  pUaCalcItem = new UaCalcItem(sFullName, uaId, pParent, nManager, dv, (*sit), ucVariables, (pParent) ? pParent->getSharedMutex() : NULL);
718  if (pUaCalcItem->fExists()) {
719  pUaCalcItem->setDataType(UaNodeId(typeName));
720  dataValue.setDataValue(dv, OpcUa_False, OpcUa_BadWaitingForInitialData, UaDateTime::now(), UaDateTime::now());
721  pUaCalcItem->setValue(0, dataValue, OpcUa_False);
722  }
723 
724  // ucs.push_back(pUaCalcItem);
725  // pVariables.insert(pair<string, UaControlVariableSet>(sFullName.toUtf8(), ucs));
726  /*
727  bool l = pUaCalcItem->compile();
728  if (!l) {
729  LOG(Log::INF) << "The expression of Item" << sName.toUtf8() << " is wrong!";
730  // cout << "The command " << comm << " does not define!" << endl;
731  return OpcUa_Bad;
732  }
733  */
734  if (pParent == NULL) {
735  ret = nManager->addNodeAndReference(OpcUaId_ObjectsFolder, pUaCalcItem, OpcUaId_HasComponent);
736  }
737  else
738  ret = nManager->addNodeAndReference(pParent, pUaCalcItem, OpcUaId_HasComponent);
739 
740  UA_ASSERT(ret.isGood());
741 
742  addCalcCompilerItem(pUaCalcItem);
743  }
744  }
745  else {
746  UaControlVariableMap ucVariables;
747  // UaControlVariableSet ucs;
748  uaId = nManager->getNewNodeId(pParent, sName);
749  CanOpenDataAddress::getOpcUaType("double", typeName);
750  UaVariant dv;
751  dv.changeType(typeName, false);
752  pUaCalcItem = new UaCalcItem(sName, uaId, pParent, nManager, dv, (*sit), ucVariables, (pParent) ? pParent->getSharedMutex() : NULL);
753  if (pUaCalcItem->fExists()) {
754  pUaCalcItem->setDataType(UaNodeId(typeName));
755  dataValue.setDataValue(dv, OpcUa_False, OpcUa_BadWaitingForInitialData, UaDateTime::now(), UaDateTime::now());
756  pUaCalcItem->setValue(0, dataValue, OpcUa_False);
757  }
758 
759  // ucs.push_back(pUaCalcItem);
760  // pVariables.insert(pair<string, UaControlVariableSet>(sit->name(), ucs));
761  //bool l = pUaCalcItem->compile();
762 
763  //if (!l) {
764  // LOG(Log::INF) << "The expression of Item " << sName.toUtf8() << " is wrong!";
765  // // cout << "The command " << comm << " does not define!" << endl;
766  // return OpcUa_Bad;
767  //}
768  if (pParent == NULL) {
769  ret = nManager->addNodeAndReference(OpcUaId_ObjectsFolder, pUaCalcItem, OpcUaId_HasComponent);
770  }
771  else
772  ret = nManager->addNodeAndReference(pParent, pUaCalcItem, OpcUaId_HasComponent);
773 
774  UA_ASSERT(ret.isGood());
775  addCalcCompilerItem(pUaCalcItem);
776  }
777  }
778 
779  }
780  return ret;
781 
782  }
783 
784  UaStatus CanBusInterface::createRegVariable(ITEM &itemvar, REGEXPR_sequence &regex, mapDataVariable& pvariables, OpcUa::BaseObjectType *pcn, OpcUa_Int32 &minVar, NmBuildingAutomation *nManager)
785 
786  {
787  OpcUa_Int32 nVar = 0;
788  minVar = INT_MAX;
789  // scan throw the formula items to find the pattern
790  for (REGEXPR_sequence::const_iterator it = regex.begin(); it != regex.end(); it++) {
791  UaControlVariableSet ucVariables;
792 // cout << itemvar.value() << " " << (*it).name() << endl;
793  if (itemvar.value().find((*it).name()) != string::npos) {
794  string t = (*it).value();
795  nVar = nManager->findUaVariables(pcn, t, ucVariables);
796  if (nVar == 0) {
797 // LOG(Log::INF) << "Variable " << t << " is not defined!";
798  cout << "Variable " << t << " is not defined!" << endl;
799  return OpcUa_Bad;
800  }
801  if (minVar > nVar) minVar = nVar; // minimum pattern result
802  // if (pvariables.find((*it)) == pvariables.end())
803  pvariables.insert(pair<string, UaControlVariableSet>((*it).name(), ucVariables));
804  }
805  }
806 
807  if (itemvar.when().present()) {
808 
809  for (REGEXPR_sequence::const_iterator it = regex.begin(); it != regex.end(); it++) {
810  UaControlVariableSet ucVariables;
811  string t = itemvar.when().get();
812  if (t.find((*it).name()) != string::npos) {
813  string t = (*it).value();
814  nVar = nManager->findUaVariables(pcn, t, ucVariables);
815 
816  if (nVar == 0) {
817 // LOG(Log::INF) << "Variable " << t << " is not defined!";
818  cout << "Variable " << t << " is not defined!" << endl;
819  return OpcUa_Bad;
820  }
821  if (minVar > nVar) minVar = nVar; // minimum pattern result
822  // if (pvariables.find((*it)) == pvariables.end())
823  pvariables.insert(pair<string, UaControlVariableSet>((*it).name(), ucVariables));
824  }
825  }
826  }
827  if (itemvar.status().present()) {
828 
829  for (REGEXPR_sequence::const_iterator it = regex.begin(); it != regex.end(); it++) {
830  UaControlVariableSet ucVariables;
831  if (itemvar.status().get().find((*it).name()) != string::npos) {
832  string t = (*it).value();
833  nVar = nManager->findUaVariables(pcn, t, ucVariables);
834  if (nVar == 0) {
835 // LOG(Log::INF) << "Variable " << t << " is not defined!";
836  cout << "Variable " << t << " is not defined!" << endl;
837  return OpcUa_Bad;
838  }
839  if (minVar > nVar) minVar = nVar; // minimum pattern result
840  // if (pvariables.find((*it)) == pvariables.end())
841  pvariables.insert(pair<string, UaControlVariableSet>((*it).name(), ucVariables));
842  }
843  }
844  }
845 
846  return OpcUa_Good;
847  }
848 
849 
850  void CanBusInterface::initCalculation()
851  {
852  for (unsigned int i = 0; i < m_vCCI.size(); i++)
853  {
854  AddressSpace::UaCalcItem *uci = m_vCCI[i];
855  uci->compile();
856  }
857  for (unsigned int i = 0; i < m_vCCI.size(); i++)
858  {
859  AddressSpace::UaCalcItem *uci = m_vCCI[i];
860  uci->initCalculation();
861  }
862  m_vCCI.clear();
863  }
864 
865  void CanBusInterface::addCalcCompilerItem(AddressSpace::UaCalcItem *ucci)
866  {
867  m_vCCI.push_back(ucci);
868  }
869 }