OpcUaCanOpen
CANopen OPC-UA server
CanNodeObject.cpp
Go to the documentation of this file.
1 #include "CanNodeObject.h"
2 #include "CanSDOObject.h"
3 #include "CanBusObject.h"
4 #include "Ids.h"
5 
8 
9 
10 namespace CanOpen
11 {
12 
13  CanNodeObject::CanNodeObject(pUserDeviceStruct *interf,NODE *ca,UaNode *blink,OpcUa_UInt32 code)
14  : CanObject(interf, ca, blink, code), m_state(0), m_iBootupCounter(0), m_EmergencyCounter(0)
15  {
16  m_requestedSDO = 0;
17  CanBusObject * pcanbus = static_cast<CanBusObject *>(interf->getDevice());
18  m_CanNodeId = ca->nodeid();
19  setInitLive();
20  setInitNmt((ca->nmt() == NULL) ? string() : ca->nmt().get());
21  pcanbus->addNode(this);
22  if (m_pCommIf) m_pCommIf = pcanbus->getCanBusInterface();
23 
24  m_pIOManager = new IOManagerSDO((UaCanNodeObject*)blink); // Input/Output manager for SDO operation
25  }
26 
28  {
29 
30  }
31 
33  {
34  if (m_requestedSDO) {
36  m_requestedSDO->pass(cms);
37  }
38  }
39  }
40 
41 
42  UaStatus CanNodeObject::sendDeviceMessage(OpcUa_UInt32 code, UaDataValue *value)
43  {
44  UaStatus ret = OpcUa_Good;
45  string nameMethod;
46 
47  lock();
48  switch (code) {
49  case BA_CANOBJECT_START:
50  sendNMT(start);
51  nameMethod = "NMT Start";
52  break;
53  case BA_CANOBJECT_STOP:
54  sendNMT(stop);
55  nameMethod = "NMT Stop";
56  break;
59  nameMethod = "NMT PreOperation";
60  break;
61  case BA_CANOBJECT_RESET:
62  sendNMT(reset);
63  nameMethod = "NMT Reset";
64  break;
65  case BA_CANOBJECT_NMT:
66  {
67  OpcUa_Byte command = value->value()->Value.Byte;
68  sendNMT((::NMTcommand)command);
69  nameMethod = "NMT " + command;
70  }
71  break;
72 
73  default:
74  ret = OpcUa_Bad;
75  }
76  unlock();
77 
78  LOG(Log::DBG, NMTMessage) << " bus=" << ((CanBusObject*)getParentDevice())->getCanBusName() << "node=" << getCanNodeId() << " phase=" << nameMethod ;
79 
80  return ret;
81  }
82 
84  {
85  UaDataValue dataValue;
86  UaDateTime udt,sdt;
87  UaVariant val;
88  UaStatus Status;
89 
90  udt = UaDateTime::fromTime_t(cms->c_time.tv_sec); // Time from can message
91  udt.addMilliSecs(cms->c_time.tv_usec/1000);
92  sdt = UaDateTime::now(); // server time
93 
94  OpcUa_Byte st = cms->c_data[0] & 0x7F; //set state of the node from NG message
95 
96  NGComing(st);
97 
98  if (st > 0) {
99  // Write to state date variable
100  if (m_state) {
101  val.setByte(cms->c_data[0]);
102  dataValue.setDataValue(val,OpcUa_False,OpcUa_Good,udt,sdt);
103  Status = m_state->setValue(NULL, dataValue, OpcUa_False);
104  }
105  }
106  else {
107  // increase Bootup item by 1
108  OpcUa_UInt32 bcount;
109  if (m_iBootupCounter) {
110  dataValue = m_iBootupCounter->value(0);
111  val = *dataValue.value();
112  val.toUInt32(bcount);
113  bcount +=1;
114  val.setUInt32(bcount);
115  dataValue.setDataValue(val,OpcUa_False,OpcUa_Good,udt,sdt);
116  Status = m_iBootupCounter->setValue(NULL, dataValue, OpcUa_False);
117 
118  // Boot up message
119  // Create event
120  /*
121  BootupEvent eventData(browseName().namespaceIndex());
122  // Create unique event id
123  UaByteString eventId;
124  EventManagerUaNode::buildEventId( UaByteString(), eventId);
125  eventData.m_EventId.setByteString(eventId, OpcUa_True);
126 
127  // Fill all default event fields
128  eventData.m_SourceNode.setNodeId(nodeId());
129  eventData.m_SourceName.setString(browseName().toString());
130  eventData.m_Time.setDateTime(udt);
131  eventData.m_ReceiveTime.setDateTime(sdt);
132  UaString messageText;
133  messageText = UaString("The Bootup Message from Node %1 (%2)has come").arg(browseName().toString()).arg(getCanNodeId());
134  eventData.m_Message.setLocalizedText(UaLocalizedText("en", messageText));
135  eventData.m_Severity.setUInt16(500);
136 
137  // Fire the event
138  m_pNodeConfig->getEventManagerUaNode()->fireEvent(&eventData);
139  */
140  }
141  }
142  }
143 
148  {
149  UaDataValue dataValue;
150  UaDateTime udt,sdt;
151  UaVariant val;
152  UaStatus Status;
153  OpcUa_UInt32 st;
154 
155  udt = UaDateTime::fromTime_t(cms->c_time.tv_sec); // Time from can message
156  udt.addMilliSecs(cms->c_time.tv_usec/1000);
157  sdt = UaDateTime::now(); // server time
158 
159  OpcUa_UInt16 serr = cms->c_data[1];
160  serr = (serr << 8) + cms->c_data[0];
161  val.setUInt16(serr);
162  dataValue.setDataValue(val,OpcUa_False,OpcUa_Good,udt,sdt);
163  Status = m_EmergencyErrorCode->setValue(NULL, dataValue, OpcUa_False);
164 
165  dataValue = m_EmergencyCounter->value(0);
166  val = *dataValue.value();
167  val.toUInt32(st);
168  st += 1;
169  val.setUInt32(st);
170  dataValue.setDataValue(val, OpcUa_False, OpcUa_Good, udt, sdt);
171  Status = m_EmergencyCounter->setValue(NULL, dataValue, OpcUa_False);
172 
173  val.setByte(cms->c_data[2]);
174  dataValue.setDataValue(val,OpcUa_False,OpcUa_Good,udt,sdt);
175  Status = m_Error->setValue(NULL, dataValue, OpcUa_False);
176 
177  val.setByte(cms->c_data[3]);
178  dataValue.setDataValue(val,OpcUa_False,OpcUa_Good,udt,sdt);
179  Status = m_SpecificErrorCodeByte1->setValue(NULL, dataValue, OpcUa_False);
180 
181  val.setByte(cms->c_data[4]);
182  dataValue.setDataValue(val,OpcUa_False,OpcUa_Good,udt,sdt);
183  Status = m_SpecificErrorCodeByte2->setValue(NULL, dataValue, OpcUa_False);
184 
185  val.setByte(cms->c_data[5]);
186  dataValue.setDataValue(val,OpcUa_False,OpcUa_Good,udt,sdt);
187  Status = m_SpecificErrorCodeByte3->setValue(NULL, dataValue, OpcUa_False);
188 
189  val.setByte(cms->c_data[6]);
190  dataValue.setDataValue(val,OpcUa_False,OpcUa_Good,udt,sdt);
191  Status = m_SpecificErrorCodeByte4->setValue(NULL, dataValue, OpcUa_False);
192 
193  val.setByte(cms->c_data[7]);
194  dataValue.setDataValue(val,OpcUa_False,OpcUa_Good,udt,sdt);
195  Status = m_SpecificErrorCodeByte5->setValue(NULL, dataValue, OpcUa_False);
196 
197  }
198 
201  {
202  if( m_pCommIf ) {
203  LOG(Log::DBG, NGMessage) << "bus=" << ((CanBusObject*)getParentDevice())->getCanBusName() << " direction=send " << "node=" << std::hex << (int)getCanNodeId();
204 
205  // tNGMessage("NG send nodeId = %X",getCanNodeId());
207  }
208  }
209 
210  UaStatus CanNodeObject::connectCode(OpcUa_UInt32 code,::xsd::cxx::tree::type *conf,UaNode *blink)
211  {
212  UaDataValue udt;
213  UaVariant val;
214  UaDateTime sdt = UaDateTime::now();
215  NODE *nodeb = (NODE *)conf;
216 
217  switch (code) {
218  case BA_CANOBJECT_NMT:
219  ((OpcUa::BaseDataVariableType *)blink)->setDataType(OpcUaType_UInt32);
220  val.setUInt32(0);
221  udt.setDataValue(val, OpcUa_False, OpcUa_Good, sdt, sdt);
222  ((OpcUa::BaseDataVariableType *)blink)->setValue(0, udt, OpcUa_False);
223  ((OpcUa::BaseDataVariableType *)blink)->setValueHandling(UaVariable_Value_Cache);
224  break;
225  case BA_CANNODETYPE_STATE:
226  m_state = (OpcUa::BaseVariableType *)blink;
227  break;
228  case BA_CANNODETYPE_BOOTUP:
229  val.setInt16(0);
230  udt.setDataValue(val,OpcUa_False,OpcUa_Good,sdt,sdt);
231  ((OpcUa::BaseDataVariableType *)blink)->setValue(0,udt,OpcUa_False);
232  m_iBootupCounter = (OpcUa::BaseVariableType *)blink;
233  break;
235  m_EmergencyErrorCode = (OpcUa::BaseVariableType *)blink;
236  break;
238  val.setUInt32(0);
239  udt.setDataValue(val, OpcUa_False, OpcUa_Good, sdt, sdt);
240  ((OpcUa::BaseDataVariableType *)blink)->setValue(0, udt, OpcUa_False);
241  m_EmergencyCounter = (OpcUa::BaseVariableType *)blink;
242  break;
243  case BA_EMERGENCY_ERROR:
244  m_Error = (OpcUa::BaseVariableType *)blink;
245  break;
247  m_SpecificErrorCodeByte1 = (OpcUa::BaseVariableType *)blink;
248  break;
250  m_SpecificErrorCodeByte2 = (OpcUa::BaseVariableType *)blink;
251  break;
253  m_SpecificErrorCodeByte3 = (OpcUa::BaseVariableType *)blink;
254  break;
256  m_SpecificErrorCodeByte4 = (OpcUa::BaseVariableType *)blink;
257  break;
259  m_SpecificErrorCodeByte5 = (OpcUa::BaseVariableType *)blink;
260  break;
261  //case BA_CANNODETYPE_TYPE:
262  // if (nodeb != NULL)
263  // if (nodeb->type().present()) {
264  // val.setString(UaString(nodeb->type().get().c_str()));
265  // udt.setDataValue(val, OpcUa_False, OpcUa_Good, sdt, sdt);
266  // ((OpcUa::BaseDataVariableType *)blink)->setValue(0, udt, OpcUa_False);
267  // }
268  // break;
269  //case BA_CANNODETYPE_NODEID:
270  //{
271  // OpcUa_UInt16 n = nodeb->nodeid();
272  // val.setUInt16(n);
273  // udt.setDataValue(val, OpcUa_False, OpcUa_Good, sdt, sdt);
274  // ((OpcUa::BaseDataVariableType *)blink)->setValue(0, udt, OpcUa_False);
275  //}
276  // break;
277  default: return OpcUa_Bad;
278  }
279  return OpcUa_Good;
280  }
281 
283  {
284  UaVariant val;
285  val.clear();
286  NODE *nodeb = (NODE *)conf;
287 
288  switch (code) {
289  case BA_CANNODETYPE_TYPE:
290  if (nodeb != NULL)
291  if (nodeb->type().present()) {
292  val.setString(UaString(nodeb->type().get().c_str()));
293  }
294  break;
296  {
297  OpcUa_UInt16 n = nodeb->nodeid();
298  val.setUInt16(n);
299  }
300  break;
301  }
302  return val;
303  }
304 
305 
307  {
308  OpcUa_Byte st;
309  if (isAlive())
310  st = m_currentState;
311  else st = m_lastState;
312  UaThread::usleep(100);
313  UaNode * discPDO = static_cast<UaNode *>(getAddressSpaceEntry());
314  setStateRecursevely(discPDO, true);
315  switch (st)
316  {
317  case NMT_STOPPED:
318  sendNMT(stop);
319  break;
320  case NMT_OPERATIONAL:
321  sendNMT(start);
322  break;
323 
324  case NMT_PREOPERATIONAL:
326  break;
327  default: break;
328  }
329  }
330 
332  {
333  UaDataValue dataValue;
334  UaDateTime udt,sdt;
335  UaVariant val;
336  UaStatus Status;
337 
340 
341  udt = UaDateTime::now(); // Time from can message
342  sdt = UaDateTime::now(); // server time
343 
344  val.setByte(NMT_DISCONNECTED);
345  dataValue.setDataValue(val,OpcUa_False,OpcUa_Good,udt,sdt);
346  Status = m_state->setValue(NULL, dataValue, OpcUa_False);
347 //
348  UaNode * discPDO = static_cast<UaNode *>(getAddressSpaceEntry());
349  setStateRecursevely(discPDO, false);
350 
351 // printf("Set Disconnect state %d %d\n",m_lastState , m_currentState);
352 
353  }
354 
355  void CanNodeObject::setStateRecursevely(UaNode *p, bool state)
356  {
357  UaReferenceLists *rl = p->getUaReferenceLists();
358  for (UaReference *ur = const_cast<UaReference *>(rl->pTargetNodes()); ur != NULL; ur = ur->pNextForwardReference())
359  {
360  OpcUa_UInt32 refType = ur->referenceTypeId().identifierNumeric();
361  if (refType == OpcUaId_HasComponent) {
362  UaNode *pNode = ur->pTargetNode();
363  int t = pNode->nodeClass();
364  if (t == OpcUa_NodeClass_Object)
365  setStateRecursevely(pNode, state);
366  else
367  if (t == OpcUa_NodeClass_Variable)
368  {
369  UaDataValue udv = (static_cast<UaVariable *>(pNode))->value(0);
370 
371  if (state)
372  {
373  udv.setStatusCode(OpcUa_Good);
374  }
375  else
376  {
377  udv.setStatusCode(OpcUa_BadNoCommunication);
378  }
379  udv.setServerTimestamp(UaDateTime::now());
380  udv.setSourceTimestamp(UaDateTime::now());
381 
382  UaStatus us = (static_cast<UaVariable *>(pNode))->setValue(0,udv,OpcUa_False);
383 // cout << pNode->displayName(0).toString().toUtf8() << " " << state << " " << us.toString().toUtf8() << endl;
384  }
385  }
386  }
387  }
388 
389 }