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



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ad3a9d8ae Tue May 1 23:10:22 2018 -0700 at lun oct 28 00:14:14 CET 2019