MRPT  1.9.9
CWirelessPower.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2020, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "hwdrivers-precomp.h" // Precompiled headers
11 
13 #include <iostream>
14 
15 #ifdef MRPT_OS_LINUX
16 #include <iostream>
17 #include <sstream>
18 #endif
19 
20 #ifdef _WIN32
21 #if defined(__GNUC__)
22 // MinGW: Nothing to do here (yet)
23 #else
24 
25 #include <windows.h>
26 
27 #include <objbase.h>
28 #include <wlanapi.h>
29 #include <wtypes.h>
30 #pragma comment(lib, "Wlanapi.lib")
31 
32 #endif
33 
34 #endif
35 
36 using namespace mrpt::hwdrivers;
37 using namespace std;
38 
40 
41 CWirelessPower::CWirelessPower() { m_sensorLabel = "WIRELESS_POWER"; }
42 #ifdef _WIN32
43 #if defined(__GNUC__)
44 // MinGW: Nothing to do here (yet)
45 #else
46 /*---------------------------------------------------------------
47  ConnectWlanServerW
48  Get a connection to the WLAN server
49  ---------------------------------------------------------------*/
50 
51 /** Gets a connection to the server
52  * \exception std::exception In case there is a failure (happens when WiFi is
53  * not started)
54  */
55 
57 {
58  DWORD dwMaxClient = 2;
59  DWORD dwCurVersion = 0;
60  DWORD dwResult = 0; // Result of the API call
61  HANDLE hClient;
62  // open connection to server
63  dwResult = WlanOpenHandle(dwMaxClient, nullptr, &dwCurVersion, &hClient);
64  if (dwResult != ERROR_SUCCESS)
65  {
66  // if an error ocurred
67  std::stringstream excmsg;
68  excmsg << "WlanOpenHandle failed with error: " << dwResult << std::endl;
69 
70  // You can use FormatMessage here to find out why the function failed
71  THROW_EXCEPTION(excmsg.str());
72  }
73  return (void*)hClient;
74 }
75 
76 /*---------------------------------------------------------------
77  ListInterfacesW
78  Gets a list of the interfaces (Windows)
79  ---------------------------------------------------------------*/
80 
81 /** Gets a list of the interfaces available in the system (in Windows format)
82  * \exception std::exception In case there is a failure
83  * \return std::vector returns handles to the available interfaces
84  */
85 
86 std::vector<PWLAN_INTERFACE_INFO> ListInterfacesW(HANDLE hClient)
87 {
88  // Get a list of the available interfaces
89 
90  std::vector<PWLAN_INTERFACE_INFO> outputVector; // start the output vector
91  PWLAN_INTERFACE_INFO_LIST pIfList = nullptr; // list of WLAN interfaces
92  PWLAN_INTERFACE_INFO pIfInfo =
93  nullptr; // information element for one interface
94  DWORD dwResult = 0;
95 
96  int i;
97 
98  // Call the interface enumeration function of the API
99  dwResult = WlanEnumInterfaces(hClient, nullptr, &pIfList);
100 
101  // check result
102  if (dwResult != ERROR_SUCCESS)
103  {
104  // In case of error, raise an exception
105  std::stringstream excmsg;
106  excmsg << "WlanEnumInterfaces failed with error: " << dwResult
107  << std::endl;
108 
109  THROW_EXCEPTION(excmsg.str());
110  // You can use FormatMessage here to find out why the function failed
111  }
112  else
113  {
114  // iterate throught interfaces to add them to the output vector
115  for (i = 0; i < (int)pIfList->dwNumberOfItems; i++)
116  {
117  pIfInfo = (WLAN_INTERFACE_INFO*)&pIfList->InterfaceInfo[i];
118  outputVector.push_back(pIfInfo);
119  }
120  }
121  return outputVector;
122 }
123 
124 /*---------------------------------------------------------------
125  GUID2Str
126  Gets the GUID of a network based on its handler in Windows
127  ---------------------------------------------------------------*/
128 /** Transforms a GUID structure (in Windows format) to a string
129  * \exception std::exception In case there is a failure
130  * \return std::string returns a string containing the GUID
131  */
132 
133 std::string GUID2Str(const GUID& ifaceGuid)
134 {
135  // Variables
136  int iRet;
137  errno_t wctostr;
138  size_t sizeGUID;
139 
140  WCHAR GuidString[39] = {0};
141  char GuidChar[100];
142 
143  std::string outputString;
144 
145  // Call the API function that gets the name of the GUID as a WCHAR[]
146  iRet = StringFromGUID2(
147  ifaceGuid, (LPOLESTR)&GuidString,
148  sizeof(GuidString) / sizeof(*GuidString));
149  // For c rather than C++ source code, the above line needs to be
150  // iRet = StringFromGUID2(&pIfInfo->InterfaceGuid, (LPOLESTR) &GuidString,
151  // sizeof(GuidString)/sizeof(*GuidString));
152 
153  // translate from a WCHAR to string if no error happened
154  if (iRet == 0)
155  {
156  THROW_EXCEPTION("StringFromGUID2 failed\n");
157  }
158  else
159  {
160  wctostr = wcstombs_s(&sizeGUID, GuidChar, 100, GuidString, 100);
161  if ((wctostr == EINVAL) || (wctostr == ERANGE))
162  {
163  THROW_EXCEPTION("wcstombs_s failed\n");
164  }
165  else
166  {
167  outputString = std::string(GuidChar);
168  }
169  }
170 
171  return outputString;
172 }
173 
174 /*---------------------------------------------------------------
175  GetInterfaceW
176  Gets a handler for the interface (Windows)
177  ---------------------------------------------------------------*/
178 
179 /** Gets a handle to the interface that has been set by setNet() (in Windows
180  * format)
181  * \exception std::exception In case there is a failure
182  * \return PWLAN_INTERFACE_INFO returns a handle to the interface
183  */
184 
185 PWLAN_INTERFACE_INFO GetInterfaceW(std::string guid, HANDLE hClient)
186 {
187  // Get interface given the GUID as a string (by the guid property of the
188  // object)
189 
190  std::vector<PWLAN_INTERFACE_INFO> ifaceList; // interface list
191  std::vector<PWLAN_INTERFACE_INFO>::iterator ifaceIter; // iterator
192  PWLAN_INTERFACE_INFO output = nullptr; // interface info element
193 
194  // get a list of all the interfaces
195  ifaceList = ListInterfacesW(hClient);
196 
197  // search for the interface that has the given GUID
198  for (ifaceIter = ifaceList.begin(); ifaceIter != ifaceList.end();
199  ++ifaceIter)
200  {
201  if (GUID2Str((*ifaceIter)->InterfaceGuid) == guid)
202  {
203  output = *ifaceIter;
204  break;
205  }
206  }
207 
208  return output;
209 }
210 
211 /*---------------------------------------------------------------
212  ListNetworksW
213  Gets a list of the networks available for the interface (in Windows)
214  ---------------------------------------------------------------*/
215 
216 /** Gets a list of the networks available for an interface (in Windows format)
217  * \exception std::exception In case there is a failure
218  * \return std::vector returns handles to the available networks of a given
219  * interface
220  * \param iface handle to the WiFi interface
221  */
222 std::vector<PWLAN_AVAILABLE_NETWORK> ListNetworksW(
223  PWLAN_INTERFACE_INFO iface, HANDLE hClient)
224 {
225  // Start variables
226 
227  DWORD dwResult = 0;
228  PWLAN_AVAILABLE_NETWORK_LIST pBssList =
229  nullptr; // list of available networks
230  PWLAN_AVAILABLE_NETWORK pBssEntry =
231  nullptr; // information element for one interface
232 
233  GUID ifaceGuid = iface->InterfaceGuid; // Get GUID of the interface
234 
235  std::vector<PWLAN_AVAILABLE_NETWORK> outputVector; // output vector
236 
237  // WCHAR GuidString[39] = {0};
238 
239  // Force a scan (to obtain new data)
240  WLAN_RAW_DATA IeData;
241  WlanScan((HANDLE)hClient, &ifaceGuid, nullptr, &IeData, nullptr);
242 
243  // Call the Windows API and get a list of the networks available through the
244  // interface
245  dwResult = WlanGetAvailableNetworkList(
246  (HANDLE)hClient, &ifaceGuid, 0, nullptr, &pBssList);
247 
248  // Check the result of the call
249  if (dwResult != ERROR_SUCCESS)
250  {
251  // In case an error ocurred
252  std::stringstream excmsg;
253  excmsg << "WlanGetAvailableNetworkList failed with error: " << dwResult
254  << std::endl;
255  // THROW_EXCEPTION(excmsg.str();;
256  }
257  else
258  {
259  // for each network, get its info and save it
260  for (unsigned int j = 0; j < pBssList->dwNumberOfItems; j++)
261  {
262  pBssEntry = (WLAN_AVAILABLE_NETWORK*)&pBssList
263  ->Network[j]; // get entry for network
264  outputVector.push_back(pBssEntry); // save entry
265  }
266  }
267 
268  return outputVector;
269 }
270 
271 /*---------------------------------------------------------------
272  GetNetworkW
273  Gets a handler to a wireless network in Windows
274  ---------------------------------------------------------------*/
275 /** Gets a handle to the network that has been set by setNet() (in Windows
276  * format)
277  * \exception std::exception In case there is a failure
278  * \return PWLAN_AVAILABLE_NETWORK returns a handle to the network
279  */
280 PWLAN_AVAILABLE_NETWORK GetNetworkW(
281  HANDLE hClient, const std::string& ssid, const std::string& guid)
282 {
283  // Variables
284  PWLAN_INTERFACE_INFO iface; // interface handler
285  PWLAN_AVAILABLE_NETWORK output; // output network handler
286 
287  // Get a handler to the interface
288  iface = GetInterfaceW(guid, hClient);
289 
290  // Get the list of networks
291  std::vector<PWLAN_AVAILABLE_NETWORK> pBssList =
292  ListNetworksW(iface, hClient);
293 
294  // Iterate through the list and find the network that has the matching SSID
295  std::vector<PWLAN_AVAILABLE_NETWORK>::iterator netIter;
296  for (netIter = pBssList.begin(); netIter != pBssList.end(); ++netIter)
297  {
298  if (std::string((char*)((*netIter)->dot11Ssid.ucSSID)) == ssid)
299  {
300  output = *netIter;
301  break;
302  }
303  }
304 
305  return output;
306 }
307 
308 #endif
309 
310 #endif // end of Windows auxiliary functions definition
311 
312 /*---------------------------------------------------------------
313  ListInterfaces
314  Gets a list of the interfaces
315  ---------------------------------------------------------------*/
316 
317 std::vector<std::string> CWirelessPower::ListInterfaces()
318 {
319  std::vector<std::string> output; // output vector of strings
320 
321 #ifdef MRPT_OS_LINUX
322  // in linux, the command line is used to get all the relevant information
323  FILE* cmdoutput; // file handler for the executed command line
324  char ifaceread[256], *netname; // strings used to read the output of the
325  // command line and get the name of each
326  // network
327 
328  // Run the command line: get the info frim /proc/net/wireless and cut out
329  // the names of the interfaces
330 
331  // commandl << "cat /proc/net/wireless|grep \"wlan\"|cut -d\" \" -f2|cut
332  // -d\":\" -f1";
333  cmdoutput = popen(
334  "cat /proc/net/wireless|grep \"wlan\"|cut -d\" \" -f2|cut -d\":\" -f1",
335  "r");
336  if (!fgets(ifaceread, 3, cmdoutput)) // read output
337  THROW_EXCEPTION("Error reading /proc/net/wireless");
338 
339  // iterate thrugh list and get each interface as a string
340  netname = ::strtok(ifaceread, "\n");
341  while (netname)
342  {
343  output.emplace_back(netname);
344  netname = ::strtok(nullptr, "\n");
345  }
346 #endif
347 
348 #ifdef _WIN32
349 #if defined(__GNUC__)
350  THROW_EXCEPTION("Sorry, method not available for MinGW");
351 #else
352  // In windows, this function is a wrapper to ListInterfacesW
353 
354  std::vector<PWLAN_INTERFACE_INFO>
355  ifaces; // vector containing the interface entries (Windows format)
356  std::vector<PWLAN_INTERFACE_INFO>::iterator
357  ifacesIter; // iterator to run through the previous list
358 
359  // get the list
360  ifaces = ListInterfacesW(hClient);
361 
362  // iterate thrugh list and get each GUID as a string
363  for (ifacesIter = ifaces.begin(); ifacesIter != ifaces.end(); ++ifacesIter)
364  {
365  output.push_back(GUID2Str((*ifacesIter)->InterfaceGuid));
366  }
367 #endif
368 #endif
369 
370  return output;
371 }
372 
373 /*---------------------------------------------------------------
374  ListNetworks
375  Gets a list of the networks available for the interface
376  ---------------------------------------------------------------*/
377 
378 std::vector<std::string> CWirelessPower::ListNetworks()
379 {
380  std::vector<std::string> output; // output vector of strings
381 
382 #ifdef MRPT_OS_LINUX
383 
384  std::stringstream commandl; // command to be executed
385 
386  FILE* cmdoutput;
387  char listread[1024];
388  char* netname;
389 
390  // Run command: get a list of networks and cut out their names. Note: this
391  // must be done as a superuser, so the command is executed with sudo.
392  // Usually it should ask for the password only the first time.
393  // To avoid the inconvenience of having to write the password, it would be
394  // useful to configure sudo to allow the user to run this command. See "man
395  // sudoers"
396  commandl << "sudo iwlist "
397  << "wlan0"
398  << " scan|grep ESSID|cut -d\"\\\"\" -f2";
399  cmdoutput = popen(commandl.str().c_str(), "r");
400  if (!fgets(listread, 3, cmdoutput))
401  THROW_EXCEPTION("Error reading response from iwlist");
402 
403  netname = ::strtok(listread, "\n");
404  while (netname)
405  {
406  output.emplace_back(netname);
407  netname = ::strtok(nullptr, "\n");
408  }
409 
410 #endif
411 
412 #ifdef _WIN32
413 #if defined(__GNUC__)
414  THROW_EXCEPTION("Sorry, method not available for MinGW");
415 #else
416 
417  PWLAN_INTERFACE_INFO iface; // Information element for an interface
418 
419  iface = GetInterfaceW(guid, (HANDLE)hClient); // Get the interface handler
420 
421  // Get the list of networks
422  std::vector<PWLAN_AVAILABLE_NETWORK> pBssList =
423  ListNetworksW(iface, (HANDLE)hClient);
424 
425  // Iterate through the list and save the names as strings
426  std::vector<PWLAN_AVAILABLE_NETWORK>::iterator netIter;
427  for (netIter = pBssList.begin(); netIter != pBssList.end(); ++netIter)
428  {
429  output.push_back(std::string((char*)((*netIter)->dot11Ssid.ucSSID)));
430  }
431 #endif
432 
433 #endif
434 
435  return output;
436 }
437 
438 /*---------------------------------------------------------------
439  GetPower
440  Gets the power of the network
441  ---------------------------------------------------------------*/
443 {
444 #ifdef MRPT_OS_LINUX
445  FILE* cmdoutput;
446  char* powerReadL;
447  std::stringstream commandl;
448  // Run command: get the power of the networks and additional info
449  commandl << "sudo iwlist "
450  << "wlan0"
451  << " scan";
452  cmdoutput = popen(commandl.str().c_str(), "r");
453 
454  std::vector<std::string> powerReadV;
455  size_t readBytes;
456 
457  powerReadL = (char*)malloc(256);
458  std::stringstream ssidLine;
459 
460  ssidLine << "ESSID:\"" << ssid << "\"";
461  if (getline(&powerReadL, &readBytes, cmdoutput) < 0)
462  THROW_EXCEPTION("Error reading response from iwlist");
463 
464  while (!strstr(powerReadL, ssidLine.str().c_str()))
465  {
466  powerReadV.emplace_back(powerReadL);
467  if (getline(&powerReadL, &readBytes, cmdoutput))
468  THROW_EXCEPTION("Error reading response from iwlist");
469  }
470 
471  auto ssiter = powerReadV.end() - 2;
472 
473  char powerLine[256];
474 
475  // now we have a string per output line of iwlist. We must find the line
476  // containing the desired ESSID and read the power from two lines before
477 
478  strcpy(powerLine, (*ssiter).c_str());
479 
480  char level[10];
481  // meaning that the ESSID was found
482  // Example pf the value of poerLine: Quality=57/100 Signal level=57/100
483  char* fraction;
484 
485  ::strtok(powerLine, "=");
486  ::strtok(nullptr, "=");
487  fraction = ::strtok(nullptr, "=");
488  strcpy(level, ::strtok(fraction, "/"));
489 
490  free(powerReadL);
491 
492  return atoi(level);
493 
494 #elif defined(_WIN32)
495 #if defined(__GNUC__)
496  THROW_EXCEPTION("Sorry, method not available for MinGW");
497 #else
498  PWLAN_AVAILABLE_NETWORK wlan; // handler to the network
499 
500  // Get a handler to the network
501  wlan = GetNetworkW((HANDLE)hClient, ssid, guid);
502 
503  return wlan->wlanSignalQuality;
504 #endif
505 #else
506  THROW_EXCEPTION("Method not implemented for this platform/OS!");
507 #endif
508 }
509 
510 /*---------------------------------------------------------------
511  getObservation
512  Get the power of a given network as an observation
513  NOTE: Deprecated, use getObservations. Use this class as
514  GenericSensor. See the CGenericSensor documentation
515  ---------------------------------------------------------------*/
517  mrpt::obs::CObservationWirelessPower& outObservation)
518 {
519  try
520  {
521  // outObservation.m_readings.clear();
522  outObservation.power = (float)GetPower();
523 
524  outObservation.timestamp = mrpt::system::getCurrentTime();
525 
526  outObservation.sensorLabel = m_sensorLabel;
527  // std::cout << "mrpt::hwdrivers::CWirelessPower::getObservation() " <<
528  //"\n\tsensorLabel: " << outObservation.sensorLabel << "\n\ttimestamp: "
529  //<< outObservation.timestamp << "\n\tpower: " << outObservation.power
530  //<< std::endl;
531  return true;
532  }
533  catch (exception& e)
534  {
535  cerr << "[CWirelessPower::getObservation] Returning false due to "
536  "exception: "
537  << endl;
538  cerr << e.what() << endl;
539  return false;
540  }
541 }
542 
544 {
545  // Wrapper to getObservation
546  auto outObservation = mrpt::obs::CObservationWirelessPower::Create();
547  getObservation(*outObservation);
548 
549  appendObservation(
551 }
552 
554  const mrpt::config::CConfigFileBase& configSource,
555  const std::string& iniSection)
556 {
557  MRPT_START
558  pose_x = configSource.read_float(iniSection, "pose_x", 0, true);
559  pose_y = configSource.read_float(iniSection, "pose_y", 0, true);
560  pose_z = configSource.read_float(iniSection, "pose_z", 0, true);
561  pose_roll = configSource.read_float(iniSection, "pose_roll", 0, true);
562  pose_pitch = configSource.read_float(iniSection, "pose_pitch", 0, true);
563  pose_yaw = configSource.read_float(iniSection, "pose_yaw", 0, true);
564 
565  ssid = configSource.read_string(iniSection, "ssid", "", true);
566  guid = configSource.read_string(
567  iniSection, "guid", "", true); // in the case of Linux, the "GUID" is
568  // the interface name (wlanX)
569 
570 #ifdef _WIN32
571 #if defined(__GNUC__)
572  THROW_EXCEPTION("Sorry, method not available for MinGW");
573 #else
574  hClient = ConnectWlanServerW();
575 #endif
576 #endif
577 
578  MRPT_END
579 }
#define MRPT_START
Definition: exceptions.h:241
std::string read_string(const std::string &section, const std::string &name, const std::string &defaultValue, bool failIfNotFound=false) const
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:67
mrpt::system::TTimeStamp getCurrentTime()
Returns the current (UTC) system time.
Definition: datetime.h:82
void * ConnectWlanServerW()
Gets a connection to the server.
PWLAN_AVAILABLE_NETWORK GetNetworkW(HANDLE hClient, const std::string &ssid, const std::string &guid)
Gets a handle to the network that has been set by setNet() (in Windows format)
Contains classes for various device interfaces.
float read_float(const std::string &section, const std::string &name, float defaultValue, bool failIfNotFound=false) const
STL namespace.
char * strcpy(char *dest, size_t destSize, const char *source) noexcept
An OS-independent version of strcpy.
std::vector< PWLAN_INTERFACE_INFO > ListInterfacesW(HANDLE hClient)
Gets a list of the interfaces available in the system (in Windows format)
This class allows loading and storing values and vectors of different types from a configuration text...
bool getObservation(mrpt::obs::CObservationWirelessPower &outObservation)
Gets the power of a given network as a timestamped observation NOTE: Deprecated, use getObservations ...
This class implements a wireless power probe.
char * strtok(char *str, const char *strDelimit, char **context) noexcept
An OS-independent method for tokenizing a string.
double power
The power or signal strength as sensed by the Wifi receiver (In percentage: [0-100]) ...
PWLAN_INTERFACE_INFO GetInterfaceW(std::string guid, HANDLE hClient)
Gets a handle to the interface that has been set by setNet() (in Windows format)
This represents a measurement of the wireless strength perceived by the robot.
#define IMPLEMENTS_GENERIC_SENSOR(class_name, NameSpace)
This must be inserted in all CGenericSensor classes implementation files:
std::string sensorLabel
An arbitrary label that can be used to identify the sensor.
Definition: CObservation.h:62
mrpt::system::TTimeStamp timestamp
The associated UTC time-stamp.
Definition: CObservation.h:60
std::vector< std::string > ListNetworks()
Gets a list of the networks available for an interface.
void loadConfig_sensorSpecific(const mrpt::config::CConfigFileBase &configSource, const std::string &section) override
Loads specific configuration for the device from a given source of configuration parameters, for example, an ".ini" file, loading from the section "[iniSection]" (see config::CConfigFileBase and derived classes)
std::vector< PWLAN_AVAILABLE_NETWORK > ListNetworksW(PWLAN_INTERFACE_INFO iface, HANDLE hClient)
Gets a list of the networks available for an interface (in Windows format)
OBSERVATION_T::Ptr getObservation(mrpt::obs::CSensoryFrame::Ptr &observations, mrpt::obs::CObservation::Ptr &observation, bool priority_to_sf=true)
Given an mrpt::obs::CSensoryFrame and a mrpt::obs::CObservation pointer if a OBSERVATION_T type obser...
Definition: obs_utils.h:31
std::vector< std::string > ListInterfaces()
Gets a list of the interfaces.
#define MRPT_END
Definition: exceptions.h:245
void doProcess() override
This method will be invoked at a minimum rate of "process_rate" (Hz)
int GetPower()
Gets the power of a given network.
std::string GUID2Str(const GUID &ifaceGuid)
Transforms a GUID structure (in Windows format) to a string.



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: c7a3bec24 Sun Mar 29 18:33:13 2020 +0200 at dom mar 29 18:50:38 CEST 2020