device.cc
Go to the documentation of this file.
1 /*
2  * This file is part of the rc_genicam_api package.
3  *
4  * Copyright (c) 2017 Roboception GmbH
5  * All rights reserved
6  *
7  * Author: Heiko Hirschmueller
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the copyright holder nor the names of its contributors
20  * may be used to endorse or promote products derived from this software without
21  * specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #include "device.h"
37 #include "stream.h"
38 
39 #include "gentl_wrapper.h"
40 #include "exception.h"
41 #include "cport.h"
42 
43 #include <iostream>
44 
45 namespace rcg
46 {
47 
48 Device::Device(const std::shared_ptr<Interface> &_parent,
49  const std::shared_ptr<const GenTLWrapper> &_gentl, const char *_id)
50 {
51  parent=_parent;
52  gentl=_gentl;
53  id=_id;
54 
55  n_open=0;
56  dev=0;
57  rp=0;
58 }
59 
61 {
62  if (n_open > 0)
63  {
64  try
65  {
66  gentl->DevClose(dev);
67  }
68  catch (...) // do not throw exceptions in destructor
69  { }
70 
71  parent->close();
72  }
73 }
74 
75 std::shared_ptr<Interface> Device::getParent() const
76 {
77  return parent;
78 }
79 
80 const std::string &Device::getID() const
81 {
82  return id;
83 }
84 
85 void Device::open(ACCESS access)
86 {
87  std::lock_guard<std::mutex> lock(mtx);
88 
89  if (n_open == 0)
90  {
91  parent->open();
92 
93  // convert access mode to GenTL flags
94 
97 
98  int i=0;
99  switch (access)
100  {
101  case READONLY:
102  i=0;
103  break;
104 
105  case CONTROL:
106  i=1;
107  break;
108 
109  default:
110  case EXCLUSIVE:
111  i=2;
112  break;
113  }
114 
115  // open device (if readonly fails, try control; if control fails try
116  // exclusive)
117 
119  while (err == GenTL::GC_ERR_NOT_IMPLEMENTED && i < 3)
120  {
121  err=gentl->IFOpenDevice(parent->getHandle(), id.c_str(), mode[i], &dev);
122  i++;
123  }
124 
125  // check if open was successful
126 
127  if (err != GenTL::GC_ERR_SUCCESS)
128  {
129  parent->close();
130  throw GenTLException("Device::open() failed", gentl);
131  }
132  }
133 
134  n_open++;
135 }
136 
138 {
139  std::lock_guard<std::mutex> lock(mtx);
140 
141  if (n_open > 0)
142  {
143  n_open--;
144 
145  if (n_open == 0)
146  {
147  gentl->DevClose(dev);
148  dev=0;
149  rp=0;
150 
151  nodemap=0;
152  rnodemap=0;
153 
154  cport=0;
155  rport=0;
156 
157  parent->close();
158  }
159  }
160 }
161 
162 namespace
163 {
164 
165 int find(const std::vector<std::shared_ptr<Stream> > &list, const std::string &id)
166 {
167  for (size_t i=0; i<list.size(); i++)
168  {
169  if (list[i]->getID() == id)
170  {
171  return static_cast<int>(i);
172  }
173  }
174 
175  return -1;
176 }
177 
178 }
179 
180 std::vector<std::shared_ptr<Stream> > Device::getStreams()
181 {
182  std::lock_guard<std::mutex> lock(mtx);
183 
184  std::vector<std::shared_ptr<Stream> > ret;
185 
186  if (dev != 0)
187  {
188  // get list of previously requested streams that are still in use
189 
190  std::vector<std::shared_ptr<Stream> > current;
191 
192  for (size_t i=0; i<slist.size(); i++)
193  {
194  std::shared_ptr<Stream> p=slist[i].lock();
195  if (p)
196  {
197  current.push_back(p);
198  }
199  }
200 
201  // create list of streams, using either existing streams or
202  // instantiating new ones
203 
204  uint32_t n=0;
205  if (gentl->DevGetNumDataStreams(dev, &n) != GenTL::GC_ERR_SUCCESS)
206  {
207  throw GenTLException("Device::getStreams()", gentl);
208  }
209 
210  for (uint32_t i=0; i<n; i++)
211  {
212  char tmp[256]="";
213  size_t size=sizeof(tmp);
214 
215  if (gentl->DevGetDataStreamID(dev, i, tmp, &size) != GenTL::GC_ERR_SUCCESS)
216  {
217  throw GenTLException("Device::getStreams()", gentl);
218  }
219 
220  int k=find(current, tmp);
221 
222  if (k >= 0)
223  {
224  ret.push_back(current[static_cast<size_t>(k)]);
225  }
226  else
227  {
228  ret.push_back(std::shared_ptr<Stream>(new Stream(shared_from_this(), gentl, tmp)));
229  }
230  }
231 
232  // update internal list of streams for reusage on next call
233 
234  slist.clear();
235  for (size_t i=0; i<ret.size(); i++)
236  {
237  slist.push_back(ret[i]);
238  }
239  }
240 
241  return ret;
242 
243 }
244 
245 namespace
246 {
247 
248 std::string cDevGetInfo(const Device *obj, const std::shared_ptr<const GenTLWrapper> &gentl,
250 {
251  std::string ret;
252 
254  char tmp[1024]="";
255  size_t tmp_size=sizeof(tmp);
257 
258  if (obj->getHandle() != 0)
259  {
260  err=gentl->DevGetInfo(obj->getHandle(), info, &type, tmp, &tmp_size);
261  }
262  else if (obj->getParent()->getHandle() != 0)
263  {
264  err=gentl->IFGetDeviceInfo(obj->getParent()->getHandle(), obj->getID().c_str(), info, &type,
265  tmp, &tmp_size);
266  }
267 
269  {
270  for (size_t i=0; i<tmp_size && tmp[i] != '\0'; i++)
271  {
272  ret.push_back(tmp[i]);
273  }
274  }
275 
276  return ret;
277 }
278 
279 }
280 
281 std::string Device::getVendor()
282 {
283  std::lock_guard<std::mutex> lock(mtx);
284  return cDevGetInfo(this, gentl, GenTL::DEVICE_INFO_VENDOR);
285 }
286 
287 std::string Device::getModel()
288 {
289  std::lock_guard<std::mutex> lock(mtx);
290  return cDevGetInfo(this, gentl, GenTL::DEVICE_INFO_MODEL);
291 }
292 
293 std::string Device::getTLType()
294 {
295  std::lock_guard<std::mutex> lock(mtx);
296  return cDevGetInfo(this, gentl, GenTL::DEVICE_INFO_TLTYPE);
297 }
298 
300 {
301  std::lock_guard<std::mutex> lock(mtx);
302 
303  // return user defined name if available, otherwise the display name that
304  // the producer provides
305 
306  std::string ret=cDevGetInfo(this, gentl, GenTL::DEVICE_INFO_USER_DEFINED_NAME);
307 
308  if (ret.size() == 0)
309  {
310  ret=cDevGetInfo(this, gentl, GenTL::DEVICE_INFO_DISPLAYNAME);
311  }
312 
313  return ret;
314 }
315 
317 {
318  std::lock_guard<std::mutex> lock(mtx);
319  std::string ret;
320 
322  int32_t status=-1;
323  size_t size=sizeof(status);
325 
326  if (dev != 0)
327  {
328  err=gentl->DevGetInfo(dev, GenTL::DEVICE_INFO_ACCESS_STATUS, &type, &status, &size);
329  }
330  else if (parent->getHandle() != 0)
331  {
332  err=gentl->IFGetDeviceInfo(getParent()->getHandle(), id.c_str(),
333  GenTL::DEVICE_INFO_ACCESS_STATUS, &type, &status, &size);
334  }
335 
336  if (err == GenTL::GC_ERR_SUCCESS)
337  {
338  if (type == GenTL::INFO_DATATYPE_INT32)
339  {
340  switch (status)
341  {
343  ret="ReadWrite";
344  break;
345 
347  ret="ReadOnly";
348  break;
349 
351  ret="NoAccess";
352  break;
353 
355  ret="Busy";
356  break;
357 
359  ret="OpenReadWrite";
360  break;
361 
363  ret="OpenReadWrite";
364  break;
365 
366  default:
367  ret="Unknown";
368  break;
369  }
370  }
371  }
372 
373  return ret;
374 }
375 
377 {
378  std::lock_guard<std::mutex> lock(mtx);
379  return cDevGetInfo(this, gentl, GenTL::DEVICE_INFO_USER_DEFINED_NAME);
380 }
381 
383 {
384  std::lock_guard<std::mutex> lock(mtx);
385  return cDevGetInfo(this, gentl, GenTL::DEVICE_INFO_SERIAL_NUMBER);
386 }
387 
388 std::string Device::getVersion()
389 {
390  std::lock_guard<std::mutex> lock(mtx);
391  return cDevGetInfo(this, gentl, GenTL::DEVICE_INFO_VERSION);
392 }
393 
395 {
396  std::lock_guard<std::mutex> lock(mtx);
398  uint64_t freq=0;
399  size_t size=sizeof(freq);
400 
401  if (dev != 0)
402  {
403  gentl->DevGetInfo(dev, GenTL::DEVICE_INFO_TIMESTAMP_FREQUENCY, &type, &freq, &size);
404  }
405  else if (parent->getHandle() != 0)
406  {
407  gentl->IFGetDeviceInfo(getParent()->getHandle(), id.c_str(),
408  GenTL::DEVICE_INFO_TIMESTAMP_FREQUENCY, &type, &freq, &size);
409  }
410 
411  return freq;
412 }
413 
414 std::shared_ptr<GenApi::CNodeMapRef> Device::getNodeMap()
415 {
416  std::lock_guard<std::mutex> lock(mtx);
417 
418  if (dev != 0 && !nodemap)
419  {
420  cport=std::shared_ptr<CPort>(new CPort(gentl, &dev));
422  }
423 
424  return nodemap;
425 }
426 
427 std::shared_ptr<GenApi::CNodeMapRef> Device::getRemoteNodeMap(const char *xml)
428 {
429  std::lock_guard<std::mutex> lock(mtx);
430 
431  if (dev != 0 && !rnodemap)
432  {
433  if (gentl->DevGetPort(dev, &rp) == GenTL::GC_ERR_SUCCESS)
434  {
435  rport=std::shared_ptr<CPort>(new CPort(gentl, &rp));
436  rnodemap=allocNodeMap(gentl, rp, rport.get(), xml);
437  }
438  }
439 
440  return rnodemap;
441 }
442 
443 void *Device::getHandle() const
444 {
445  return dev;
446 }
447 
448 std::vector<std::shared_ptr<Device> > getDevices()
449 {
450  std::vector<std::shared_ptr<Device> > ret;
451 
452  std::vector<std::shared_ptr<System> > system=System::getSystems();
453 
454  for (size_t i=0; i<system.size(); i++)
455  {
456  system[i]->open();
457 
458  std::vector<std::shared_ptr<Interface> > interf=system[i]->getInterfaces();
459 
460  for (size_t k=0; k<interf.size(); k++)
461  {
462  interf[k]->open();
463 
464  std::vector<std::shared_ptr<Device> > device=interf[k]->getDevices();
465 
466  for (size_t j=0; j<device.size(); j++)
467  {
468  ret.push_back(device[j]);
469  }
470 
471  interf[k]->close();
472  }
473 
474  system[i]->close();
475  }
476 
477  return ret;
478 }
479 
480 std::shared_ptr<Device> getDevice(const char *id)
481 {
482  int found=0;
483  std::shared_ptr<Device> ret;
484 
485  if (id != 0 && *id != '\0')
486  {
487  // split into interface and device id
488 
489  std::string interfid;
490  std::string devid=id;
491 
492  size_t p=devid.find(':');
493  if (p != std::string::npos)
494  {
495  interfid=devid.substr(0, p);
496  devid=devid.substr(p+1);
497  }
498 
499  // go through all systems
500 
501  std::vector<std::shared_ptr<System> > system=System::getSystems();
502 
503  for (size_t i=0; i<system.size(); i++)
504  {
505  system[i]->open();
506 
507  // get all interfaces
508 
509  std::vector<std::shared_ptr<Interface> > interf=system[i]->getInterfaces();
510 
511  if (interfid.size() > 0)
512  {
513  // if an interface is defined, then only search this interface
514 
515  for (size_t k=0; k<interf.size(); k++)
516  {
517  if (interf[k]->getID() == interfid)
518  {
519  interf[k]->open();
520 
521  std::shared_ptr<Device> dev=interf[k]->getDevice(devid.c_str());
522 
523  if (dev)
524  {
525  ret=dev;
526  found++;
527  }
528 
529  interf[k]->close();
530  }
531  }
532  }
533  else
534  {
535  // if interface is not defined, then check all interfaces
536 
537  std::shared_ptr<Device> dev;
538  for (size_t k=0; k<interf.size() && !dev; k++)
539  {
540  interf[k]->open();
541 
542  dev=interf[k]->getDevice(devid.c_str());
543 
544  if (dev)
545  {
546  ret=dev;
547  found++;
548  }
549 
550  interf[k]->close();
551  }
552  }
553 
554  system[i]->close();
555  }
556  }
557 
558  if (found > 1)
559  {
560  std::cerr << "ERROR: Finding device '" << id << "' through different producers."
561  << std::endl;
562  ret.reset();
563  }
564 
565  return ret;
566 }
567 
568 }
std::vector< std::shared_ptr< Stream > > getStreams()
Returns the currently available streams of this device.
Definition: device.cc:180
std::shared_ptr< Device > getDevice(const char *id)
Searches across all transport layers and interfaces for a device.
Definition: device.cc:480
std::string getDisplayName()
Returns the display name of the device.
Definition: device.cc:299
This is the port definition that connects GenAPI to GenTL.
Definition: cport.h:52
int32_t DEVICE_ACCESS_FLAGS
Definition: GenTL_v1_6.h:310
void open(ACCESS access)
Opens the device for working with it.
Definition: device.cc:85
static std::vector< std::shared_ptr< System > > getSystems()
This function creates systems for all producers that can be found.
Definition: system.cc:201
std::shared_ptr< CPort > rport
Definition: device.h:267
void * rp
Definition: device.h:265
std::string getVendor()
Returns the vendor of the device.
Definition: device.cc:281
std::string getUserDefinedName()
Returns the user defined name of the device.
Definition: device.cc:376
std::shared_ptr< GenApi::CNodeMapRef > rnodemap
Definition: device.h:268
std::shared_ptr< const GenTLWrapper > gentl
Definition: device.h:258
std::mutex mtx
Definition: device.h:261
std::string getSerialNumber()
Returns the serial number of the device.
Definition: device.cc:382
std::shared_ptr< GenApi::CNodeMapRef > getRemoteNodeMap(const char *xml=0)
Returns the node map of the remote device.
Definition: device.cc:427
std::shared_ptr< Interface > getParent() const
Returns the pointer to the parent interface object.
Definition: device.cc:75
Device(const std::shared_ptr< Interface > &parent, const std::shared_ptr< const GenTLWrapper > &gentl, const char *id)
Constructs a device class.
Definition: device.cc:48
const std::string & getID() const
Get the internal ID of this device.
Definition: device.cc:80
int32_t INFO_DATATYPE
Definition: GenTL_v1_6.h:261
std::shared_ptr< GenApi::CNodeMapRef > allocNodeMap(std::shared_ptr< const GenTLWrapper > gentl, void *port, CPort *cport, const char *xml)
Convenience function that returns a GenICam node map from the given port.
Definition: cport.cc:156
int32_t GC_ERROR
Definition: GenTL_v1_6.h:185
std::shared_ptr< CPort > cport
Definition: device.h:267
std::shared_ptr< GenApi::CNodeMapRef > getNodeMap()
Returns the node map of this object.
Definition: device.cc:414
int n_open
Definition: device.h:263
void * dev
Definition: device.h:264
std::string getTLType()
Returns the transport layer type of the device.
Definition: device.cc:293
Definition: buffer.cc:47
void * getHandle() const
Get internal interface handle.
Definition: device.cc:443
std::string getModel()
Returns the model of the device.
Definition: device.cc:287
std::shared_ptr< GenApi::CNodeMapRef > nodemap
Definition: device.h:268
std::vector< std::shared_ptr< Device > > getDevices()
Returns a list of all devices that are available across all transport layers and interfaces.
Definition: device.cc:448
int32_t DEVICE_INFO_CMD
Definition: GenTL_v1_6.h:343
std::string id
Definition: device.h:259
uint64_t getTimestampFrequency()
Returns the timestamp frequency of the device.
Definition: device.cc:394
std::string getVersion()
Returns the version of the device.
Definition: device.cc:388
std::vector< std::weak_ptr< Stream > > slist
Definition: device.h:270
std::shared_ptr< Interface > parent
Definition: device.h:257
The device class encapsulates a Genicam device.
Definition: device.h:54
The stream class encapsulates a Genicam stream.
Definition: stream.h:55
std::string getAccessStatus()
Returns the access status of the device.
Definition: device.cc:316
void close()
Closes the device.
Definition: device.cc:137


rc_genicam_api
Author(s): Heiko Hirschmueller
autogenerated on Sun Jun 18 2023 02:43:55