YARP
Yet Another Robot Platform
DeviceGroup.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT)
3  * Copyright (C) 2006-2010 RobotCub Consortium
4  * All rights reserved.
5  *
6  * This software may be modified and distributed under the terms of the
7  * BSD-3-Clause license. See the accompanying LICENSE file for details.
8  */
9 
10 #include "DeviceGroup.h"
11 
12 #include <cstdio>
13 #include <yarp/os/Time.h>
14 #include <yarp/os/LogComponent.h>
15 #include <yarp/dev/Drivers.h>
17 
19 
20 #include <mutex>
21 #include <vector>
22 
23 using namespace yarp::os;
24 using namespace yarp::sig;
25 using namespace yarp::dev;
26 
27 namespace {
28 YARP_LOG_COMPONENT(DEVICEGROUP, "yarp.devices.DeviceGroup")
29 }
30 
31 #define HELPER(x) (*((DeviceGroupHelper*)(x)))
32 
33 
35 {
36 private:
37  std::vector<PolyDriver *> drivers;
38  std::vector<std::string> names;
39  std::vector<bool> needDrive;
40  std::mutex mutex;
41 public:
42  bool needDriveSummary{false};
43 
44  void clear()
45  {
46  mutex.lock();
47  std::vector<PolyDriver *>& lst = drivers;
48  for (unsigned int i=0; i<lst.size(); i++) {
49  yCInfo(DEVICEGROUP, "*** Removing %s",names[i].c_str());
50  Drivers::factory().remove(names[i].c_str());
51  yCTrace(DEVICEGROUP, "*** removed %s",names[i].c_str());
52  delete lst[i];
53  yCTrace(DEVICEGROUP, "*** deleted %s",names[i].c_str());
54  }
55  lst.clear();
56  names.clear();
57  mutex.unlock();
58  }
59 
60  void update()
61  {
62  mutex.lock();
63  std::vector<PolyDriver *>& lst = drivers;
64  for (unsigned int i=0; i<lst.size(); i++) {
65  if (needDrive[i]) {
66  IService *service;
67  lst[i]->view(service);
68  if (service!=nullptr) {
69  service->updateService();
70  }
71  }
72  }
73  mutex.unlock();
74  }
75 
76  bool close()
77  {
78  yCTrace(DEVICEGROUP, "*** Device group closing");
79  clear();
80  yCTrace(DEVICEGROUP, "*** Device group closed");
81  return true;
82  }
83 
85  {
86  clear();
87  }
88 
89  bool add(const std::string& name, yarp::os::Searchable& config)
90  {
91  yCTrace(DEVICEGROUP, "ADDING %s", config.toString().c_str());
92  auto* pd = new PolyDriver();
93  yCAssert(DEVICEGROUP, pd!=nullptr);
94  bool result = pd->open(config);
95  if (!result) {
96  delete pd;
97  return false;
98  }
99  drivers.push_back(pd);
100  names.push_back(name);
101  IService *service = nullptr;
102  pd->view(service);
103  bool backgrounded = true;
104  if (service!=nullptr) {
105  backgrounded = service->startService();
106  if (backgrounded) {
107  // we don't need to poll this, so forget about the
108  // service interface
109  yCInfo(DEVICEGROUP, "group: service backgrounded");
110  service = nullptr;
111  }
112  }
113  needDrive.push_back(!backgrounded);
114  needDriveSummary = needDriveSummary || (!backgrounded);
115  Drivers::factory().add(new DriverLinkCreator(name,*pd));
116  return true;
117  }
118 
119 };
120 
121 
122 
123 
125 {
126  if (implementation==nullptr) {
128  }
129  if (implementation==nullptr) {
130  yCError(DEVICEGROUP, "Out of memory");
131  return false;
132  }
133 
134  if (config.check("part","a list of section names, with each section containing a device")) {
135  Bottle bot = config.findGroup("part").tail();
136  yCInfo(DEVICEGROUP, "Assembly of: %s", bot.toString().c_str());
137  for (size_t i=0; i<bot.size(); i++) {
138  std::string name = bot.get(i).asString();
139  yCInfo(DEVICEGROUP, " %s -> %s", name.c_str(),
140  config.findGroup(name).toString().c_str());
141  bool result = HELPER(implementation).add(name,
142  config.findGroup(name));
143  if (!result) {
144  HELPER(implementation).close();
145  return false;
146  }
147  }
148  return true;
149  }
150  return false;
151 }
152 
153 
154 bool DeviceGroup::open(const char *key, PolyDriver& poly,
155  yarp::os::Searchable& config, const char *comment)
156 {
157  Value *name;
158  if (config.check(key,name,comment)) {
159  if (name->isString()) {
160  // maybe user isn't doing nested configuration
162  p.setMonitor(config.getMonitor(),
163  name->toString().c_str()); // pass on any monitoring
164  p.fromString(config.toString());
165  p.put("device",name->toString());
166  p.unput("subdevice");
167  p.unput("wrapped");
168  poly.open(p);
169  } else {
170  Bottle subdevice = config.findGroup(key).tail();
171  poly.open(subdevice);
172  }
173  if (!poly.isValid()) {
174  yCError(DEVICEGROUP, "cannot make <%s>", name->toString().c_str());
175  return false;
176  }
177  } else {
178  yCError(DEVICEGROUP, "\"--%s <name>\" not set", key);
179  return false;
180  }
181  return true;
182 }
183 
184 
185 bool DeviceGroup::closeMain()
186 {
187  yCInfo(DEVICEGROUP, "Devices closing");
188  HELPER(implementation).close();
189  source.close();
190  sink.close();
191  return true;
192 }
193 
195 {
196  return !HELPER(implementation).needDriveSummary;
197 }
198 
199 
201 {
202  HELPER(implementation).update();
203  return true;
204 }
205 
206 
208 {
209  if (implementation!=nullptr) {
210  delete &HELPER(implementation);
211  implementation = nullptr;
212  }
213 }
#define HELPER(x)
Definition: DeviceGroup.cpp:31
RandScalar * implementation(void *t)
Definition: RandnScalar.cpp:20
bool add(const std::string &name, yarp::os::Searchable &config)
Definition: DeviceGroup.cpp:89
bool open(yarp::os::Searchable &config) override
Open the DeviceDriver.
bool updateService() override
Give the service the chance to run for a while.
bool startService() override
Initiate the service, whatever it is.
~DeviceGroup() override
A factory for creating links to a driver that has already been created.
Common interface for devices that act like services (by which we mean they do something for remote us...
virtual bool startService()
Initiate the service, whatever it is.
virtual bool updateService()
Give the service the chance to run for a while.
A container for a device driver.
Definition: PolyDriver.h:27
bool isValid() const
Check if device is valid.
Definition: PolyDriver.cpp:199
bool open(const std::string &txt)
Construct and configure a device by its common name.
Definition: PolyDriver.cpp:143
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:73
size_type size() const
Gets the number of elements in the bottle.
Definition: Bottle.cpp:254
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition: Bottle.cpp:249
Bottle tail() const
Get all but the first element of a bottle.
Definition: Bottle.cpp:391
std::string toString() const override
Gives a human-readable textual representation of the bottle.
Definition: Bottle.cpp:214
A class for storing options and configuration information.
Definition: Property.h:37
void fromString(const std::string &txt, bool wipe=true)
Interprets a string as a list of properties.
Definition: Property.cpp:1046
void put(const std::string &key, const std::string &value)
Associate the given key with the given string.
Definition: Property.cpp:998
void unput(const std::string &key)
Remove the association from the given key to a value, if present.
Definition: Property.cpp:1029
A base class for nested structures that can be searched.
Definition: Searchable.h:69
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
virtual std::string toString() const =0
Return a standard text representation of the content of the object.
virtual Bottle & findGroup(const std::string &key) const =0
Gets a list corresponding to a given keyword.
A single value (typically within a Bottle).
Definition: Value.h:47
virtual bool isString() const
Checks if value is a string.
Definition: Value.cpp:159
std::string toString() const override
Return a standard text representation of the content of the object.
Definition: Value.cpp:359
virtual std::string asString() const
Get string value.
Definition: Value.cpp:237
#define yCInfo(component,...)
Definition: LogComponent.h:135
#define yCError(component,...)
Definition: LogComponent.h:157
#define yCAssert(component, x)
Definition: LogComponent.h:172
#define yCTrace(component,...)
Definition: LogComponent.h:88
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:80
An interface for the device drivers.
An interface to the operating system, including Port based communication.
Signal processing.
Definition: Image.h:25