manager.cpp
Go to the documentation of this file.
1 //
2 // manager.cpp
3 //
4 
5 #include "manager.hpp"
6 #include "tools/errorhandler.hpp"
7 #include "tools/toolbox.hpp"
8 
9 // The devices
10 #include "devices/LD_MRS.hpp"
11 
12 // The applications
13 #include "application/LdmrsApp.hpp"
18 
19 using namespace application;
20 using namespace devices;
21 
22 // ****************************************************************************
23 // The Manager of the system
24 // ****************************************************************************
26  : m_beVerbose(false)
27  , m_nextSourceId(0)
28 {
29  infoMessage("Manager: Starting constructor.", m_beVerbose);
30 
31  // Max. size of the device-data-buffer
32  m_sourceBuffer.setLimit(5000000);
33 
34  infoMessage("Manager: Constructor done.", m_beVerbose);
35 }
36 
37 //
38 // Destructor.
39 // Close all applications and devices.
40 //
42 {
43  infoMessage("~Manager(): Destructor called.", m_beVerbose);
44 
46 
47  // Delete all applications
48  while (m_appList.size() > 0)
49  {
51  a = m_appList.back();
52  delete a;
53  m_appList.pop_back();
54  }
55 
56  // Delete all devices
57  while (m_deviceList.size() > 0)
58  {
59  BasicDevice* p;
60  p = m_deviceList.back();
61  delete p;
62  m_deviceList.pop_back();
63  }
64 
65  infoMessage("~Manager(): Destructor is done.", m_beVerbose);
66 }
67 
68 
69 //
70 // Provides the next unique ID. Such an ID is set for all devices and all
71 // applications, to identify data generated by them.
72 //
74 {
75  UINT16 sourceId = m_nextSourceId;
77 
78  if (m_nextSourceId == 0x0000)
79  {
80  dieWithError("Manager::getNextSourceId(): We are out of source IDs - exiting.");
81  }
82  return sourceId;
83 }
84 
85 
86 //
87 // Add a new device at runtime.
88 //
89 // It would be nice to add an ID-handling, to make the IDs safely unique!
90 //
91 bool Manager::addAndRunDevice(Sourcetype deviceType, std::string deviceName, UINT16 wantedId)
92 {
93  BasicDevice* device;
94 
95  // Device erzeugen
96  switch (deviceType)
97  {
98  case Sourcetype_LDMRS:
99  device = new LDMRS(this);
100  break;
101  default:
102  printError("Manager::addAndRunDevice: Unknown device (Type=" + toString((UINT16)deviceType) +
103  " , Name=" + deviceName + "). Ignoring this call!");
104  return false;
105  }
106  return addAndRunDevice(device, deviceName, wantedId);
107 }
108 
109 //
110 // Add a external created device object.
111 //
112 // Note that device needs to be on the heap and will automatically be deleted when the manager is destructed.
113 //
114 bool Manager::addAndRunDevice(devices::BasicDevice* device, std::string deviceName, UINT16 wantedId)
115 {
116  bool beVerboseHere = true | m_beVerbose;
117 
118  // ID erzeugen
119  UINT16 id = wantedId;
120  if (id == 0xFFFF)
121  {
122  id = getNextSourceId();
123  }
124  device->setSourceId(id);
125 
126  // Namen setzen
127  device->setDeviceName(deviceName);
128 
129  // Device speichern
130  m_deviceList.push_back(device);
131 
132  std::string text = "Manager::addAndRunDevice: Created Device of type " +
133  toString(device->getDevicetype()) +
134  " with Name " + deviceName +
135  " under the ID " +
136  toString(device->getSourceId()) + ". Now initializing the device.";
137  printInfoMessage(text, beVerboseHere);
138 
139  // Device initialisieren
140  bool result = device->init();
141  if (result == true)
142  {
143  printInfoMessage("Manager::addAndRunDevice: Device is initialized.", beVerboseHere);
144  }
145  else
146  {
147  printError("Manager::addAndRunDevice: Failed to initialize the device, aborting.");
148  return false;
149  }
150 
151  // Device starten
152  result = device->run();
153  if (result == true)
154  {
155  printInfoMessage("Manager::addAndRunDevice: Device is running.", beVerboseHere);
156  }
157  else
158  {
159  printError("Manager::addAndRunDevice: Failed to run device, aborting.");
160  return false;
161  }
162 
163  if (m_sourceThread.isRunning() == false)
164  {
165  printInfoMessage("Manager::addAndRunDevice: Added device, now running source thread.", beVerboseHere);
166  m_sourceThread.run(this);
167  }
168 
169  printInfoMessage("Manager::addAndRunDevice: All done, leaving.", beVerboseHere);
170  return result;
171 }
172 
173 //
174 // Eine neue Applikation dynamisch, d.h. zur Laufzeit, hinzufuegen.
175 //
176 // It would be nice to add an ID-handling, to make the IDs safely unique!
177 //
178 bool Manager::addApplication(Sourcetype appType, std::string appName, UINT16 wantedId)
179 {
180  BasicApplication* app;
181 
182  // Device erzeugen
183  switch (appType)
184  {
185  case Sourcetype_MrsApp:
186  app = new LdmrsApp(this);
187  break;
189  app = new LdmrsFieldApp(this);
190  break;
192  app = new LdmrsSectorChangeApp(this);
193  break;
195  app = new LdmrsNtpTimeApp(this);
196  break;
198  app = new LdmrsScanpointCoordinateApp(this);
199  break;
200  default:
201  printError("Manager::addApplication: Unknown application (Type=" + toString((UINT16)appType) +
202  " , Name=" + appName + "). Ignoring this call!");
203  return false;
204  }
205 
206  // Namen setzen
207  app->setApplicationName(appName);
208 
209  return addApplication(app, wantedId);
210 }
211 
213 {
214  // ID erzeugen
215  UINT16 id = wantedId;
216  if (id == 0xFFFF)
217  {
218  id = getNextSourceId();
219  }
220  app->setSourceId(id);
221 
222  // Device speichern
223  m_appList.push_back(app);
224 
225  std::string text = "Manager::addApplication: Created application " +
226  toString(app->getApplicationType()) +
227  " with Name " + app->getApplicationName() +
228  " under the ID " +
229  toString(app->getSourceId()) + ". Now running the device.";
231 
232  return true;
233 }
234 
235 
236 
241 {
242  std::string text;
243 
244  for (UINT32 i=0; i<m_deviceList.size(); i++)
245  {
246  BasicDevice* device;
247  device = m_deviceList.at(i);
248 
249  text = "Manager: Running device with ID " + toString(device->getSourceId()) + ".";
250  infoMessage(text, m_beVerbose);
251 
252  device->run();
253  }
254 
255  // Start the data distribution
256  if (m_sourceThread.isRunning() == false)
257  {
258  m_sourceThread.run(this);
259  }
260 
261  return true;
262 }
263 
264 
265 //
266 // Stop!
267 //
269 {
270  std::string text;
271 
272  for (UINT32 i=0; i<m_deviceList.size(); i++)
273  {
274  BasicDevice* device;
275  device = m_deviceList.at(i);
276 
277  text = "Manager::stopAllDevices: Stopping device with ID " + toString(device->getSourceId()) + ".";
278  infoMessage(text, m_beVerbose);
279 
280  device->stop();
281 
282  infoMessage("Manager::stopAllDevices: Device stopped.", m_beVerbose);
283  }
284 }
285 
286 //
287 // Receiver for data from the devices. The data is forwarded to the applications.
288 //
289 // Note: In the buffer, only the data pointers are stored!
290 //
292 {
293  // Hier in einen Puffer schreiben!
294  ScopedLock lock(&m_sourceBufferMutex); // Wg. der folgenden Textmeldung. Der Puffer selber ist sicher...
295  bool result = m_sourceBuffer.pushData(data);
296  if (result == true)
297  {
298  // Datum wurde hinzugefuegt
299  if (m_beVerbose == true)
300  {
301  std::string text;
302  text = "Manager::setDeviceData(): Added data. Device data buffer size is now " +
303  toString(m_sourceBuffer.getBufferSize()) + " Elements (" + toString(m_sourceBuffer.getUsedBytes()) + " bytes).";
304  infoMessage(text, m_beVerbose);
305  }
306  }
307  else
308  {
309  // Datum konnte nicht hinzugefuegt werden
310  std::string text;
311  text = "Manager::setDeviceData(): Failed to add data. Device data buffer size is currently " +
313  " bytes), and the buffer refused to add " + toString(data->getUsedMemory()) + " bytes.";
314  printWarning(text);
315 
316  // Datum loeschen!
317  delete data;
318  return;
319  }
320 }
321 
333 void Manager::sourceThreadFunction(bool& endThread, UINT16& waitTimeMs)
334 {
335  infoMessage("Manager: sourceThreadFunction() called.", m_beVerbose);
336 
337  //
338  // Pruefe, ob Daten verteilt werden muessen
339  //
340  // Hole den Zeiger auf die naechsten Daten im Puffer, falls welche da sind.
341  // Zugriffsschutz hier nicht erforderlich, da der Buffer selber Thread-Safe ist.
342  BasicData* data = NULL;
343  data = m_sourceBuffer.popData();
344 
345  // Verteile die Daten, falls welche da waren
346  if (data != NULL)
347  {
348  // DEBUG
349  if (m_beVerbose == true)
350  {
351  std::string text;
352  text = "Manager::sourceThreadFunction(): Popped a dataset of type " + toString(data->getDatatype()) +
353  ", created from Source-ID " + toString(data->getSourceId()) + ".";
354  infoMessage(text, m_beVerbose);
355  }
356 
357 
358  // Einfach an jede Applikation verteilen
359  for (UINT32 i=0; i<m_appList.size(); i++)
360  {
361  BasicApplication* a;
362  a = m_appList.at(i);
363  a->setData(*data);
364  }
365 
366  // Datensatz wird nicht mehr benoetigt, loeschen
367  delete data;
368  data = NULL;
369  }
370 
371  //
372  // Naechsten Aufruf vorbereiten
373  //
374  endThread = false;
375  if (m_sourceBuffer.getBufferSize() > 0)
376  {
377  // Es sind bereits jetzt neue Daten da, also nur kurz unterbrechen
378  waitTimeMs = 0;
379 // infoMessage("Source fill level: " + toString(m_sourceBuffer.getBufferSize()) + ".", true);
380  }
381  else
382  {
383  // Es sind aktuell keine weiteren Daten da, also ruhig etwas laenger schlafen
384  waitTimeMs = 2;
385  }
386 }
387 
388 //
389 // Get a pointer to the device identified by its ID.
390 // Returns NULL if no such device could be found.
391 //
393 {
394  devices::BasicDevice* device = NULL;
395 
396  for (DeviceList::iterator iter = m_deviceList.begin(); iter != m_deviceList.end(); ++iter)
397  {
398  if ((*iter)->getSourceId() == id)
399  {
400  device = *iter;
401  break;
402  }
403  }
404 
405  return device;
406 }
407 
408 //
409 // Get a pointer to the first device of the given type.
410 // Returns NULL if no such device could be found.
411 //
413 {
414  devices::BasicDevice* device = NULL;
415 
416  for (DeviceList::iterator iter = m_deviceList.begin(); iter != m_deviceList.end(); ++iter)
417  {
418  if ((*iter)->getDevicetype() == type)
419  {
420  device = *iter;
421  break;
422  }
423  }
424 
425  return device;
426 }
427 
void printError(std::string message)
std::string toString(const PositionWGS84::PositionWGS84SourceType &type)
void sourceThreadFunction(bool &endThread, UINT16 &waitTimeMs)
Definition: manager.cpp:333
bool m_beVerbose
Definition: manager.hpp:39
uint16_t UINT16
~Manager()
Destructor.
Definition: manager.cpp:41
virtual const UINT32 getUsedMemory() const =0
Mutex m_sourceBufferMutex
Definition: manager.hpp:55
devices::BasicDevice * getFirstDeviceByType(Sourcetype type)
Definition: manager.cpp:412
bool addAndRunDevice(Sourcetype deviceType, std::string deviceName, UINT16 wantedId=0xFFFF)
Definition: manager.cpp:91
void stopAllDevices()
Definition: manager.cpp:268
void setDeviceName(std::string name)
Definition: BasicDevice.cpp:66
#define printInfoMessage(a, b)
uint32_t UINT32
virtual bool init()
Definition: BasicDevice.hpp:29
bool addApplication(Sourcetype appType, std::string appName, UINT16 wantedId=0xFFFF)
Definition: manager.cpp:178
bool pushData(BasicData *data)
void run(void *classptr)
Definition: SickThread.hpp:26
void dieWithError(std::string errorMessage)
void setSourceId(UINT16 applicationId)
SickThread< Manager,&Manager::sourceThreadFunction > m_sourceThread
Definition: manager.hpp:54
Sourcetype
void infoMessage(std::string message, bool print)
DeviceList m_deviceList
Definition: manager.hpp:45
void setSourceId(UINT16 deviceId)
Definition: BasicDevice.cpp:58
virtual bool stop()=0
BasicDataBuffer m_sourceBuffer
Definition: manager.hpp:52
Manager()
Default constructor.
Definition: manager.cpp:25
void setLimit(UINT32 maxBytesToBeUsed)
BasicData * popData()
virtual void setData(BasicData &data)=0
virtual bool run()=0
devices::BasicDevice * getDeviceById(UINT32 id)
Definition: manager.cpp:392
UINT16 m_nextSourceId
Definition: manager.hpp:41
UINT16 getNextSourceId()
Definition: manager.cpp:73
bool runAllDevices()
Definition: manager.cpp:240
void printWarning(std::string message)
void setApplicationName(std::string appName)
ApplicationList m_appList
Definition: manager.hpp:49
void setDeviceData(BasicData *data)
Definition: manager.cpp:291


libsick_ldmrs
Author(s): SICK AG , Martin Günther , Jochen Sprickerhof
autogenerated on Sat Jun 8 2019 17:57:33