OpcUaCanOpen
CANopen OPC-UA server
IOManagerSDO.cpp
Go to the documentation of this file.
1 #include "IOManagerSDO.h"
2 #include "OpcServer.h"
4 #include "srvtrace.h"
5 #include "uabase.h"
6 #include "UaControlDeviceItem.h"
7 
8 //extern unique_ptr<OpcServer> pServer ;
9 extern OpcServer* pServer;
10 using namespace AddressSpace;
11 
12 namespace CanOpen
13 {
18  {
19  m_pCanNode = pCanNode;
20 
21  OpcUa_Boolean nEnab,bBlOnAdd;
22  OpcUa_Int32 iMinThr =1,iMaxThr=10,iMaxJobs=20;
23  OpcUa_UInt32 nTimeout;
24  pServer->getServerConfig()->getStackThreadPoolSettings(nEnab,iMinThr,iMaxThr,iMaxJobs,bBlOnAdd,nTimeout);
25 // cout << "ThreadPollParameters " << nEnab << " " << iMinThr << " " << iMaxThr << " " << iMaxJobs << " " << bBlOnAdd << " " << nTimeout << endl;
26  m_pThreadPool = new UaThreadPool(iMinThr,iMaxThr);
27 
28  m_pSamplingEngine = new SamplingEngine();
29  }
30 
33  {
34  delete m_pSamplingEngine;
35  delete m_pThreadPool;
36  }
37 
60  IOManagerCallback* pCallback,
61  const ServiceContext& serviceContext, // ToDo handle timeout hint and diagnostic info
62  OpcUa_UInt32 hTransaction,
63  OpcUa_UInt32 totalItemCountHint,
64  OpcUa_Double maxAge,
65  OpcUa_TimestampsToReturn timestampsToReturn,
66  TransactionType transactionType,
67  OpcUa_Handle& hIOManagerContext)
68  {
69  TRACE1_INOUT(SERVER_CORE, UA_T"--> IOManagerSDO::beginTransaction %d",transactionType);
70  UaStatus ret = OpcUa_Good;
71 
73  pTransaction->setSession(serviceContext.pSession());
74  pTransaction->m_pCallback = pCallback;
75  pTransaction->m_hTransaction = hTransaction;
76  pTransaction->m_maxAge = maxAge;
77  pTransaction->m_timestampsToReturn = timestampsToReturn;
78  pTransaction->m_totalItemCountHint = totalItemCountHint;
79  pTransaction->m_transactionType = transactionType;
80  pTransaction->m_nAsyncCount = 0;
81  pTransaction->m_pIOManager = this;
82 
83  if (transactionType == IOManager::TransactionWrite)
84  {
85  pTransaction->m_arrWriteValues.create(totalItemCountHint);
86  }
87  if ((transactionType == IOManager::TransactionMonitorBegin) ||
88  (transactionType == IOManager::TransactionMonitorModify) ||
89  (transactionType == IOManager::TransactionMonitorStop) )
90  {
91  pTransaction->m_arrSamplingHandles.create(totalItemCountHint);
92  }
93  if ( (transactionType == IOManager::TransactionRead) ||
94  (transactionType == IOManager::TransactionWrite) ||
95  (transactionType == IOManager::TransactionMonitorBegin))
96  {
97 
98  pTransaction->m_arrUaVariableHandles.create(totalItemCountHint);
99  }
100  pTransaction->m_arrCallbackHandles.create(totalItemCountHint);
101 
102  hIOManagerContext = (OpcUa_Handle)pTransaction;
103  TRACE1_INOUT(SERVER_CORE, UA_T"<-- IOManagerSDO::beginTransaction [ret=0x%lx]", ret.statusCode());
104  return ret;
105  }
106 
111  UaStatus IOManagerSDO::finishTransaction(OpcUa_Handle hIOManagerContext)
112  {
113  TRACE0_INOUT(SERVER_CORE, UA_T"--> IOManagerSDO::finishTransaction");
114  UaStatus ret = OpcUa_Good;
115  OpcUa_UInt32 mMaxPoolSize, mMumberOfJobsInPool;
116  IOTransactionContextSDO* pTransaction = (IOTransactionContextSDO*)hIOManagerContext;
117 
118  if(pTransaction)
119  {
120  OpcUa_UInt32 mThread, uThread;
121 
122  m_pThreadPool->getCapacity(mThread, uThread ,mMaxPoolSize,mMumberOfJobsInPool);
123 // cout << "getCapacity " << mThread << " " << uThread << " " << mMaxPoolSize << " " << mMumberOfJobsInPool << endl;
124  if ((uThread < mThread) || (mMumberOfJobsInPool < mMaxPoolSize)) {
125 
126  IOManagerSDOJob* pIOManagerSDOJob = new IOManagerSDOJob(pTransaction);
127  if (pTransaction->m_totalItemCountHint > pTransaction->m_nAsyncCount)
128  {
129  pTransaction->m_arrCallbackHandles.resize(pTransaction->m_nAsyncCount);
130  if (pTransaction->m_arrUaVariableHandles.length() > 0)
131  {
132  pTransaction->m_arrUaVariableHandles.resize(pTransaction->m_nAsyncCount);
133  }
134  if (pTransaction->m_arrWriteValues.length() > 0)
135  {
136  pTransaction->m_arrWriteValues.resize(pTransaction->m_nAsyncCount);
137  }
138  if (pTransaction->m_arrSamplingHandles.length() > 0)
139  {
140  pTransaction->m_arrSamplingHandles.resize(pTransaction->m_nAsyncCount);
141  }
142  }
143  ret = m_pThreadPool->addJob(pIOManagerSDOJob,false,true);
144  }
145  else {
146  LOG(Log::DBG) << "The number of SDO job exceeds maximum !";
147  ret = OpcUa_BadResourceUnavailable;
148  }
149  /*
150  switch ( pTransaction->m_transactionType )
151  {
152  case IOManager::READ:
153  {
154  executeRead(pTransaction);
155  break;
156  }
157  case IOManager::WRITE:
158  {
159  executeWrite(pTransaction);
160  break;
161  }
162  case IOManager::MONITOR_BEGIN:
163  {
164  break;
165  }
166  case IOManager::MONITOR_MODIFY:
167  {
168  break;
169  }
170  case IOManager::MONITOR_STOP:
171  {
172  break;
173  }
174  default:
175  break;
176  }
177  */
178 
179  }
180 
181  TRACE1_INOUT(SERVER_CORE, UA_T"<-- IOManagerSDO::finishTransaction [ret=0x%lx]", ret.statusCode());
182  return ret;
183  }
184 
186  {
189  {
190  case IOManager::TransactionRead:
191  {
192  currentIoManager->executeRead(m_pTransactionContext);
193  break;
194  }
195  case IOManager::TransactionWrite:
196  {
197  currentIoManager->executeWrite(m_pTransactionContext);
198  break;
199  }
200  case IOManager::TransactionMonitorBegin:
201  {
202 // currentIoManager->executeMonitorBegin(m_pTransactionContext);
203  break;
204  }
205  case IOManager::TransactionMonitorModify:
206  {
207 // currentIoManager->executeMonitorModify(m_pTransactionContext);
208  break;
209  }
210  case IOManager::TransactionMonitorStop:
211  {
212 // currentIoManager->executeMonitorStop(m_pTransactionContext);
213  break;
214  }
215  default:
216  break;
217  }
218  }
219 
229  OpcUa_Handle hIOManagerContext,
230  OpcUa_UInt32 callbackHandle,
231  VariableHandle* pVariableHandle,
232  OpcUa_ReadValueId* pReadValueId) // ToDo handle index range
233  {
234  OpcUa_ReferenceParameter(pReadValueId);
235  UaStatus ret = OpcUa_Good;
236  UaDataValue uaDataValue;
237 
238  IOTransactionContextSDO* pTransaction = (IOTransactionContextSDO*)hIOManagerContext;
239 
240  if(pTransaction)
241  {
242  if ( pTransaction->m_transactionType == IOManager::TransactionRead )
243  {
244  pTransaction->m_arrCallbackHandles[pTransaction->m_nAsyncCount] = callbackHandle;
245  pTransaction->m_arrUaVariableHandles[pTransaction->m_nAsyncCount] = (VariableHandleUaNode*)pVariableHandle;
246  pVariableHandle->addReference();
247  pTransaction->m_nAsyncCount++;
248  }
249  else
250  {
251  UA_ASSERT(false);
252  ret = OpcUa_BadNotReadable;
253  }
254  }
255  else
256  {
257  UA_ASSERT(false);
258  ret = OpcUa_BadInvalidArgument;
259  }
260 
261  return ret;
262  }
272  OpcUa_Handle hIOManagerContext,
273  OpcUa_UInt32 callbackHandle,
274  VariableHandle* pVariableHandle,
275  OpcUa_WriteValue* pWriteValue)
276  {
277  UaStatus ret = OpcUa_Good;
278 
279  IOTransactionContextSDO* pTransaction = (IOTransactionContextSDO*)hIOManagerContext;
280 
281  if(pTransaction)
282  {
283  if (pTransaction->m_transactionType == IOManager::TransactionWrite)
284  {
285  pTransaction->m_arrCallbackHandles[pTransaction->m_nAsyncCount] = callbackHandle;
286  pTransaction->m_arrUaVariableHandles[pTransaction->m_nAsyncCount] = (VariableHandleUaNode*)pVariableHandle;
287  pTransaction->m_arrWriteValues[pTransaction->m_nAsyncCount] = &pWriteValue->Value;
288  pVariableHandle->addReference();
289  pTransaction->m_nAsyncCount++;
290  }
291  else
292  {
293  UA_ASSERT(false);
294  ret = OpcUa_BadNotWritable;
295  }
296  }
297  else
298  {
299  assert(false);
300  ret = OpcUa_BadInvalidArgument;
301  }
302 
303  return ret;
304  }
315  OpcUa_Handle hIOManagerContext,
316  OpcUa_UInt32 callbackHandle,
317  IOVariableCallback* pIOVariableCallback,
318  VariableHandle* pVariableHandle,
319  MonitoringContext& monitoringContext)
320  {
321  OpcUa_ReferenceParameter(hIOManagerContext);
322  OpcUa_ReferenceParameter(callbackHandle);
323  OpcUa_ReferenceParameter(pIOVariableCallback);
324  OpcUa_ReferenceParameter(pVariableHandle);
325  OpcUa_ReferenceParameter(monitoringContext);
326  return OpcUa_BadNotSupported;
327  }
328 
329  /*
330 
331  UaStatus ret = OpcUa_Good;
332  TRACE1_INOUT(SERVER_CORE, UA_T"--> IOManagerSDO::startMonitoring %d",(OpcUa_UInt32)monitoringContext.samplingInterval);
333 
334  IOTransactionContextSDO* pTransaction = (IOTransactionContextSDO*)hIOManagerContext;
335 
336  // OPC Data Access does not support absolute deadband
337  if ( monitoringContext.isAbsoluteDeadband != OpcUa_False )
338  {
339  monitoringContext.sdkMustHandleAbsoluteDeadband = OpcUa_True;
340  }
341 
342  if(pTransaction)
343  {
344  if ( pTransaction->m_transactionType == IOManager::MONITOR_BEGIN )
345  {
346  UaMutexLocker lock(&m_mutexsdo);
347  pTransaction->m_arrCallbackHandles[pTransaction->m_nAsyncCount] = callbackHandle;
348  pTransaction->m_arrUaVariableHandles[pTransaction->m_nAsyncCount] = (VariableHandleUaNode*)pVariableHandle;
349  pVariableHandle->addReference();
350  // Create the management object in this IOManager for the monitored item
351  SamplingSDO* pSampleSDOItem = new SamplingSDO;
352 
353  pSampleSDOItem->m_nSamplingInterval = (OpcUa_UInt32)monitoringContext.samplingInterval;
354 
355  // Assign right subscription based on sampling interval
356 
357  pSampleSDOItem->m_pUaCanSDOItem = (UaCanSDOItem *)((VariableHandleUaNode*)pVariableHandle)->pUaNode();
358  pSampleSDOItem->m_pIOVariableCallback = pIOVariableCallback;
359 
360  pTransaction->m_arrSamplingHandles[pTransaction->m_nAsyncCount] = m_handlesSampleItems.add(pSampleSDOItem);
361 
362  pTransaction->m_nAsyncCount++;
363  }
364  else
365  {
366  UA_ASSERT(false);
367  ret = OpcUa_BadInternalError;
368  }
369  }
370  else
371  {
372  assert(false);
373  ret = OpcUa_BadInvalidArgument;
374  }
375 
376  return ret;
377 
378  }
379  */
389  OpcUa_Handle hIOManagerContext,
390  OpcUa_UInt32 callbackHandle,
391  OpcUa_UInt32 hIOVariable,
392  MonitoringContext& monitoringContext)
393  {
394  OpcUa_ReferenceParameter(hIOManagerContext);
395  OpcUa_ReferenceParameter(callbackHandle);
396  OpcUa_ReferenceParameter(hIOVariable);
397  OpcUa_ReferenceParameter(monitoringContext);
398  return OpcUa_BadNotSupported;
399  }
400 
401  /*
402 
403  UaStatus ret = OpcUa_Good;
404 
405  IOTransactionContextSDO* pTransaction = (IOTransactionContextSDO*)hIOManagerContext;
406 
407  if ( monitoringContext.isAbsoluteDeadband != OpcUa_False )
408  {
409  monitoringContext.sdkMustHandleAbsoluteDeadband = OpcUa_True;
410  }
411 
412  if(pTransaction)
413  {
414  if ( pTransaction->m_transactionType == IOManager::MONITOR_MODIFY )
415  {
416  pTransaction->m_arrCallbackHandles[pTransaction->m_nAsyncCount] = callbackHandle;
417  pTransaction->m_arrSamplingHandles[pTransaction->m_nAsyncCount] = hIOVariable;
418  pTransaction->m_nAsyncCount++;
419  SamplingSDO* pSampleSDOItem = m_handlesSampleItems.get(hIOVariable);
420  // Assign right subscription based on sampling interval
421 
422  m_pSamplingEngine->removeItemFromSampling(pSampleSDOItem,pSampleSDOItem->m_nSamplingInterval);
423 
424  pSampleSDOItem->m_nSamplingInterval = (OpcUa_UInt32)monitoringContext.samplingInterval;
425 
426 
427  }
428  else
429  {
430  UA_ASSERT(false);
431  ret = OpcUa_BadInternalError;
432  }
433  }
434  else
435  {
436  assert(false);
437  ret = OpcUa_BadInvalidArgument;
438  }
439 
440  return ret;
441 
442  }
443 */
453  OpcUa_Handle hIOManagerContext,
454  OpcUa_UInt32 callbackHandle,
455  OpcUa_UInt32 hIOVariable)
456  {
457  OpcUa_ReferenceParameter(hIOManagerContext);
458  OpcUa_ReferenceParameter(callbackHandle);
459  OpcUa_ReferenceParameter(hIOVariable);
460  return OpcUa_BadNotSupported;
461  }
462 /*
463  UaStatus ret = OpcUa_Good;
464 
465  IOTransactionContextSDO* pTransaction = (IOTransactionContextSDO*)hIOManagerContext;
466 
467  if(pTransaction)
468  {
469  if ( pTransaction->m_transactionType == IOManager::MONITOR_STOP )
470  {
471  pTransaction->m_arrCallbackHandles[pTransaction->m_nAsyncCount] = callbackHandle;
472  pTransaction->m_arrSamplingHandles[pTransaction->m_nAsyncCount] = hIOVariable;
473  pTransaction->m_nAsyncCount++;
474  }
475  else
476  {
477  UA_ASSERT(false);
478  ret = OpcUa_BadInternalError;
479  }
480  }
481  else
482  {
483  assert(false);
484  ret = OpcUa_BadInvalidArgument;
485  }
486 
487  return ret;
488 
489  }
490 */
492  {
493  UaDataValue dataValue;
494 
495  for( OpcUa_UInt32 i = 0; i < m_pTransactionContext->m_arrUaVariableHandles.length(); i++)
496  {
497  UaStatus ret;
498  VariableHandleUaNode *vhuanode = m_pTransactionContext->m_arrUaVariableHandles[i];
499  UaControlDeviceItem *csdo = (UaControlDeviceItem *)vhuanode->pUaNode();
500 
501  if (csdo->accessLevel() & Ua_AccessLevel_CurrentRead) {
502  ret = csdo->read();
503  if (ret.isGood()) {
504  csdo->getAttributeValue(m_pTransactionContext->pSession(),vhuanode->m_AttributeID,dataValue);
505  TRACE2_INOUT(SERVER_CORE, UA_T"<-- IOManagerSDO::Read %s [value=%s]",csdo->displayName(m_pTransactionContext->pSession()).toFullString().toUtf8() ,UaVariant(*dataValue.value()).toFullString().toUtf8() );
506  }
507  else {
508  dataValue.setStatusCode(ret.statusCode());
509  dataValue.setServerTimestamp(UaDateTime::now());
510  dataValue.setSourceTimestamp(UaDateTime::now());
511  }
512  }
513  else {
514  dataValue.setStatusCode(OpcUa_BadNotReadable);
515  dataValue.setServerTimestamp(UaDateTime::now());
516  dataValue.setSourceTimestamp(UaDateTime::now());
517  }
518  m_pTransactionContext->m_pCallback->finishRead(
519  m_pTransactionContext->m_hTransaction,
520  m_pTransactionContext->m_arrCallbackHandles[i],
521  dataValue,
522  OpcUa_True,
523  OpcUa_True);
524  }
525  }
526 
528  {
529  UaDataValue dataValue;
530  for( OpcUa_UInt32 i = 0; i < m_pTransactionContext->m_arrUaVariableHandles.length(); i++)
531  {
532  UaStatus ret;
533  VariableHandleUaNode *vhuanode = m_pTransactionContext->m_arrUaVariableHandles[i];
534  UaControlDeviceItem *csdo = (UaControlDeviceItem *)vhuanode->pUaNode();;
535  dataValue.setValue(m_pTransactionContext->m_arrWriteValues[i]->Value,OpcUa_False);
536 
537  if (csdo->accessLevel() & Ua_AccessLevel_CurrentWrite) {
538 
539  ret = csdo->write(dataValue);
540  if (ret.isGood()) {
541  TRACE2_INOUT(SERVER_CORE, UA_T"<-- IOManagerSDO::write successful %s [value=%s]", csdo->displayName(m_pTransactionContext->pSession()).toFullString().toUtf8(), UaVariant(*dataValue.value()).toFullString().toUtf8());
542  }
543  else {
544  dataValue.setStatusCode(ret.statusCode());
545  dataValue.setServerTimestamp(UaDateTime::now());
546  dataValue.setSourceTimestamp(UaDateTime::now());
547  }
548 
549  }
550  else {
551  dataValue.setStatusCode(OpcUa_BadNotWritable);
552  dataValue.setServerTimestamp(UaDateTime::now());
553  dataValue.setSourceTimestamp(UaDateTime::now());
554  }
555 
556  m_pTransactionContext->m_pCallback->finishWrite(
557  m_pTransactionContext->m_hTransaction,
558  m_pTransactionContext->m_arrCallbackHandles[i],
559  ret,
560  OpcUa_True);
561 
562  }
563  }
564 /*
565  void IOManagerSDO::executeMonitorBegin(IOTransactionContextSDO* pTransactionContext)
566  {
567  OpcUa_UInt32 count = pTransactionContext->m_nAsyncCount;
568  SamplingSDO* pSampleItem;
569 
570  OpcUa_StatusCode retCode = OpcUa_BadInternalError;
571 
572  // Assign items to different subscriptions
573  UaMutexLocker lock(&m_mutex);
574  for( OpcUa_UInt32 i = 0; i < count; i++)
575  {
576  // Get the sample item
577  pSampleItem = m_handlesSampleItems.get(pTransactionContext->m_arrSamplingHandles[i]);
578  if ( pSampleItem != NULL ) {
579  m_pSamplingEngine->addItemToSampling(pSampleItem,pSampleItem->m_nSamplingInterval);
580  retCode = OpcUa_Good;
581  }
582  pTransactionContext->m_pCallback->finishStartMonitoring(
583  pTransactionContext->m_hTransaction,
584  pTransactionContext->m_arrCallbackHandles[i],
585  pTransactionContext->m_arrSamplingHandles[i],
586  0,
587  OpcUa_False,
588  UaDataValue(),
589  retCode);
590  }
591  lock.unlock();
592  }
593 
594  void IOManagerSDO::executeMonitorModify(IOTransactionContextSDO* pTransactionContext)
595  {
596  OpcUa_UInt32 i;
597  OpcUa_UInt32 count = pTransactionContext->m_nAsyncCount;
598  SamplingSDO* pSampleItem;
599  OpcUa_StatusCode retCode = OpcUa_BadInternalError;
600 
601  // Assign items to different subscriptions
602  UaMutexLocker lock(&m_mutex);
603  for ( i=0; i < count; i++ )
604  {
605  // Get the sample item
606  pSampleItem = m_handlesSampleItems.get(pTransactionContext->m_arrSamplingHandles[i]);
607  if ( pSampleItem != NULL )
608  {
609  pSampleItem = m_handlesSampleItems.get(pTransactionContext->m_arrSamplingHandles[i]);
610  m_pSamplingEngine->addItemToSampling(pSampleItem,pSampleItem->m_nSamplingInterval);
611  retCode = OpcUa_Good;
612  }
613  pTransactionContext->m_pCallback->finishStopMonitoring(
614  pTransactionContext->m_hTransaction,
615  pTransactionContext->m_arrCallbackHandles[i],
616  retCode);
617 
618  }
619  lock.unlock();
620  }
621 
622  void IOManagerSDO::executeMonitorStop(IOTransactionContextSDO* pTransactionContext)
623  {
624  OpcUa_UInt32 i;
625  OpcUa_UInt32 count = pTransactionContext->m_nAsyncCount;
626  SamplingSDO* pSampleItem;
627  OpcUa_StatusCode retCode = OpcUa_BadInternalError;
628 
629  // Assign items to different subscriptions
630  UaMutexLocker lock(&m_mutex);
631  for ( i=0; i < count; i++ )
632  {
633  // Get the sample item
634  pSampleItem = m_handlesSampleItems.get(pTransactionContext->m_arrSamplingHandles[i]);
635  if ( pSampleItem != NULL )
636  {
637  pSampleItem = m_handlesSampleItems.get(pTransactionContext->m_arrSamplingHandles[i]);
638  m_pSamplingEngine->removeItemFromSampling(pSampleItem,pSampleItem->m_nSamplingInterval);
639  m_handlesSampleItems.remove(pTransactionContext->m_arrSamplingHandles[i]);
640  retCode = OpcUa_Good;
641  }
642  pTransactionContext->m_pCallback->finishStopMonitoring(
643  pTransactionContext->m_hTransaction,
644  pTransactionContext->m_arrCallbackHandles[i],
645  retCode);
646  }
647  lock.unlock();
648  }
649  */
650 }