PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
ClariusWifi.cxx
Go to the documentation of this file.
1 // local includes
2 #include "ClariusWifi.h"
3 
4 // STL includes
5 #include <chrono>
6 #include <thread>
7 
8 // Need to link with wlanapi.lib and ole32.lib
9 #pragma comment(lib, "wlanapi.lib")
10 #pragma comment(lib, "ole32.lib")
11 
12 // max time ClariusWifi will wait for the Clarius network to become
13 // available during call to CONNECT
14 static const float MAX_NETWORK_READY_WAIT_TIME_SEC = 25.0;
15 
16 // max time ClariusWifi will wait for the Clarius network to become
17 // connected during call to CONNECT
18 static const float MAX_NETWORK_CONNECTED_WAIT_TIME_SEC = 10.0;
19 
20 //-------------------------------------------------------------------------------------------------
22  : Connected(false)
23  , HClient(NULL)
24  , CurApiVersion(0)
25 {
26 }
27 
28 //-------------------------------------------------------------------------------------------------
30 {
31  // enforce disconnection & de-initialization
33  this->DeInitialize();
34 }
35 
36 //-------------------------------------------------------------------------------------------------
38 {
39  // already initialized, return failure
40  if (this->HClient != NULL)
41  {
42  LOG_ERROR("ClariusWifi already intialized, this initialization call was rejected");
43  return PLUS_FAIL;
44  }
45 
46  DWORD maxClientVersion = 2;
47  DWORD res = WlanOpenHandle(maxClientVersion, NULL, &this->CurApiVersion, &this->HClient);
48  if (res != ERROR_SUCCESS)
49  {
50  LOG_ERROR("Failed to open WLAN API client handle");
51  return PLUS_FAIL;
52  }
53 
54  return PLUS_SUCCESS;
55 }
56 
57 //-------------------------------------------------------------------------------------------------
59 {
60  // already de-initialized, return success
61  if (this->HClient == NULL)
62  {
63  return PLUS_SUCCESS;
64  }
65 
66  DWORD res = WlanCloseHandle(this->HClient, NULL);
67  if (res != ERROR_SUCCESS)
68  {
69  LOG_ERROR("Failed to close WLAN API client handle");
70  return PLUS_FAIL;
71  }
72 
73  this->HClient = NULL;
74  return PLUS_SUCCESS;
75 }
76 
77 //-------------------------------------------------------------------------------------------------
79 {
80  // check ClariusWifi was initialized
81  if (this->HClient == NULL)
82  {
83  LOG_ERROR("ClariusWifi must be initialized before calling IsClariusNetworkReady");
84  return PLUS_FAIL;
85  }
86 
87  PWLAN_INTERFACE_INFO_LIST interfaces = NULL;
88  PWLAN_INTERFACE_INFO if_info = NULL;
89  DWORD res = WlanEnumInterfaces(this->HClient, NULL, &interfaces);
90  if (res != ERROR_SUCCESS)
91  {
92  LOG_ERROR("Failed to enumerate WLAN interfaces");
93  return PLUS_FAIL;
94  }
95 
96  for (int i = 0; i < interfaces->dwNumberOfItems; i++)
97  {
98  if_info = (WLAN_INTERFACE_INFO*)&interfaces->InterfaceInfo[i];
99 
100  PWLAN_RAW_DATA data;
101  res = WlanScan(this->HClient, &if_info->InterfaceGuid, NULL, NULL, NULL);
102  if (res != ERROR_SUCCESS)
103  {
104  LOG_ERROR("Failed to scan for networks");
105  }
106 
107  PWLAN_AVAILABLE_NETWORK_LIST networks = NULL;
108  PWLAN_AVAILABLE_NETWORK nw_info = NULL;
109  res = WlanGetAvailableNetworkList(this->HClient, &if_info->InterfaceGuid,
110  0, NULL, &networks);
111  if (res != ERROR_SUCCESS)
112  {
113  LOG_WARNING("Failed to list available networks for interface: " << if_info->strInterfaceDescription);
114  continue;
115  }
116 
117  for (int j = 0; j < networks->dwNumberOfItems; j++)
118  {
119  nw_info = (WLAN_AVAILABLE_NETWORK*)&networks->Network[j];
120 
121  std::string candidate_ssid = (char*)nw_info->dot11Ssid.ucSSID;
122  if (ssid.compare(candidate_ssid) == 0)
123  {
124  this->InterfaceGuid = if_info->InterfaceGuid;
125  return PLUS_SUCCESS;
126  }
127  }
128 
129  // free networks memory
130  if (networks != NULL)
131  {
132  WlanFreeMemory(networks);
133  networks = NULL;
134  }
135  }
136 
137  // free interfaces memory
138  if (interfaces != NULL)
139  {
140  WlanFreeMemory(interfaces);
141  interfaces = NULL;
142  }
143 
144  return PLUS_FAIL;
145 }
146 
147 //-------------------------------------------------------------------------------------------------
149 {
150  // check ClariusWifi was initialized
151  if (this->HClient == NULL)
152  {
153  LOG_ERROR("ClariusWifi must be initialized before calling IsClariusNetworkReady");
154  return PLUS_FAIL;
155  }
156 
157  PWLAN_INTERFACE_INFO_LIST interfaces = NULL;
158  PWLAN_INTERFACE_INFO if_info = NULL;
159  DWORD res = WlanEnumInterfaces(this->HClient, NULL, &interfaces);
160  if (res != ERROR_SUCCESS)
161  {
162  LOG_ERROR("Failed to enumerate WLAN interfaces");
163  return PLUS_FAIL;
164  }
165 
166  WLAN_INTERFACE_STATE state = wlan_interface_state_not_ready;
167  for (int i = 0; i < interfaces->dwNumberOfItems; i++)
168  {
169  if_info = (WLAN_INTERFACE_INFO*)&interfaces->InterfaceInfo[i];
170  if (if_info->InterfaceGuid == this->InterfaceGuid)
171  {
172  // not the interface we are looking for
173  state = if_info->isState;
174  break;
175  }
176  }
177 
178  // free interfaces memory
179  if (interfaces != NULL)
180  {
181  WlanFreeMemory(interfaces);
182  interfaces = NULL;
183  }
184 
185  switch (state)
186  {
187  case wlan_interface_state_not_ready:
188  LOG_DEBUG("WiFi state: Not ready");
189  break;
190  case wlan_interface_state_connected:
191  LOG_DEBUG("WiFi state: Connected");
192  break;
193  case wlan_interface_state_ad_hoc_network_formed:
194  LOG_DEBUG("WiFi state: Ad hoc network formed");
195  break;
196  case wlan_interface_state_disconnecting:
197  LOG_DEBUG("WiFi state: Disconnecting");
198  break;
199  case wlan_interface_state_disconnected:
200  LOG_DEBUG("WiFi state: Disconnected");
201  break;
202  case wlan_interface_state_associating:
203  LOG_DEBUG("WiFi state: Associating");
204  break;
205  case wlan_interface_state_discovering:
206  LOG_DEBUG("WiFi state: Discovering");
207  break;
208  case wlan_interface_state_authenticating:
209  LOG_DEBUG("WiFi state: Authenticating");
210  break;
211  default:
212  LOG_DEBUG("WiFi state: Unknown state");
213  break;
214  }
215 
216  return state == wlan_interface_state_connected ? PLUS_SUCCESS : PLUS_FAIL;
217 }
218 
219 //-------------------------------------------------------------------------------------------------
221 {
222  // already connected, return failure
223  if (this->Connected)
224  {
225  LOG_ERROR("ClariusWifi already connected to Clarius network, this connection call was rejected");
226  }
227 
228  // check ClariusWifi was initialized
229  if (this->HClient == NULL)
230  {
231  LOG_ERROR("ClariusWifi must be initialized before calling IsClariusNetworkReady");
232  return PLUS_FAIL;
233  }
234 
235  // wait for Clarius network being ready
236  std::chrono::steady_clock::time_point start_time = std::chrono::steady_clock::now();
237  PlusStatus network_ready = PLUS_FAIL;
238  while (network_ready != PLUS_SUCCESS)
239  {
240  // check we haven't exceeded the maximum wait time for Clarius network
241  // to be ready
242  std::chrono::steady_clock::time_point t = std::chrono::steady_clock::now();
243  std::chrono::duration<double> dur = t - start_time;
244  if (dur.count() > MAX_NETWORK_READY_WAIT_TIME_SEC)
245  {
246  LOG_ERROR("Waiting for Clarius wifi network to be ready timed out.");
247  return PLUS_FAIL;
248  }
249 
250  // pause for 500ms, to avoid overhead of checking wifi availability at high
251  // refresh rate
252  std::this_thread::sleep_for(std::chrono::milliseconds(500));
253 
254  // refresh network_ready state
255  network_ready = this->IsClariusNetworkReady(ssid);
256  }
257 
258  if (this->UpdateClariusWifiProfile(ssid, password) != PLUS_SUCCESS)
259  {
260  LOG_ERROR("Failed to update Clarius wifi profile");
261  return PLUS_FAIL;
262  }
263 
264  // Convert ssid string to DOT11_SSID
265  DOT11_SSID dot11_ssid = { 0 };
266  if (this->StringToSsid(ssid, &dot11_ssid) != PLUS_SUCCESS)
267  {
268  LOG_ERROR("Failed to convert ssid string to DOT11_SSID type");
269  return PLUS_FAIL;
270  }
271 
272  // Connect
273  std::wstring w_ssid = std::wstring(ssid.begin(), ssid.end());
274  WLAN_CONNECTION_PARAMETERS wlan_params;
275  wlan_params.pDot11Ssid = NULL;
276  wlan_params.strProfile = w_ssid.c_str();
277  wlan_params.wlanConnectionMode = wlan_connection_mode_profile;
278  wlan_params.pDesiredBssidList = NULL;
279  wlan_params.dot11BssType = this->BssType;
280  wlan_params.dwFlags = 0;
281 
282  DWORD res = WlanConnect(this->HClient, &this->InterfaceGuid, &wlan_params, NULL);
283  if (res != ERROR_SUCCESS)
284  {
285  LOG_ERROR("Failed to connect to Clarius wifi network: Error code " << res);
286  return PLUS_FAIL;
287  }
288 
289  start_time = std::chrono::steady_clock::now();
290  PlusStatus network_connected = PLUS_FAIL;
291  while (network_connected != PLUS_SUCCESS)
292  {
293  // check we haven't exceeded the maximum wait time for Clarius network
294  // to be connected
295  std::chrono::steady_clock::time_point t = std::chrono::steady_clock::now();
296  std::chrono::duration<double> dur = t - start_time;
297  if (dur.count() > MAX_NETWORK_CONNECTED_WAIT_TIME_SEC)
298  {
299  LOG_ERROR("Waiting for Clarius wifi network to be ready timed out.");
300  return PLUS_FAIL;
301  }
302 
303  // pause for 1000ms, to avoid overhead of checking wifi availability at high
304  // refresh rate
305  std::this_thread::sleep_for(std::chrono::milliseconds(1000));
306 
307  // refresh network_connected state
308  network_connected = this->IsClariusNetworkConnected();
309  }
310 
311  this->Connected = true;
312  return PLUS_SUCCESS;
313 }
314 
315 //-------------------------------------------------------------------------------------------------
317 {
318  bool profileUpdated = false;
319 
320  PWLAN_AVAILABLE_NETWORK_LIST networks = NULL;
321  PWLAN_AVAILABLE_NETWORK nw_info = NULL;
322  DWORD res = WlanGetAvailableNetworkList(this->HClient, &this->InterfaceGuid,
323  0, NULL, &networks);
324  if (res != ERROR_SUCCESS)
325  {
326  LOG_WARNING("Failed to list available networks");
327  return PLUS_FAIL;
328  }
329 
330  for (int j = 0; j < networks->dwNumberOfItems; j++)
331  {
332  nw_info = (WLAN_AVAILABLE_NETWORK*)&networks->Network[j];
333 
334  std::string candidate_ssid = (char*)nw_info->dot11Ssid.ucSSID;
335  if (ssid.compare(candidate_ssid) != 0)
336  {
337  continue;
338  }
339 
340  std::wstring authenticationAlgorithm;
341  switch (nw_info->dot11DefaultAuthAlgorithm)
342  {
343  case DOT11_AUTH_ALGO_80211_OPEN:
344  authenticationAlgorithm = L"OPEN";
345  break;
346  case DOT11_AUTH_ALGO_80211_SHARED_KEY:
347  authenticationAlgorithm = L"SHARED";
348  break;
349  case DOT11_AUTH_ALGO_WPA:
350  case DOT11_AUTH_ALGO_WPA_PSK:
351  case DOT11_AUTH_ALGO_WPA_NONE:
352  authenticationAlgorithm = L"WPAPSK";
353  break;
354  case DOT11_AUTH_ALGO_RSNA:
355  case DOT11_AUTH_ALGO_RSNA_PSK:
356  authenticationAlgorithm = L"WPA2PSK";
357  break;
358  default:
359  authenticationAlgorithm = L"UNKNOWN";
360  }
361 
362  std::wstring encryptionAlgorithm;
363  std::wstring keyType = L"passPhrase";
364  switch (nw_info->dot11DefaultCipherAlgorithm)
365  {
366  case DOT11_CIPHER_ALGO_NONE:
367  encryptionAlgorithm = L"NONE";
368  break;
369  case DOT11_CIPHER_ALGO_TKIP:
370  encryptionAlgorithm = L"TKIP";
371  break;
372 
373  case DOT11_CIPHER_ALGO_CCMP:
374  encryptionAlgorithm = L"AES";
375  break;
376  default:
377  encryptionAlgorithm = L"WEP";
378  keyType = L"networkKey";
379  }
380 
381  std::wstringstream ss_w_clarius_profile_xml;
382  ss_w_clarius_profile_xml << "<?xml version=\"1.0\" encoding=\"US-ASCII\"?>" << std::endl;
383  ss_w_clarius_profile_xml << "<WLANProfile xmlns=\"http://www.microsoft.com/networking/WLAN/profile/v1\">" << std::endl;
384  ss_w_clarius_profile_xml << " <name>" << std::wstring(ssid.begin(), ssid.end()) << "</name>" << std::endl;
385  ss_w_clarius_profile_xml << " <SSIDConfig>" << std::endl;
386  ss_w_clarius_profile_xml << " <SSID>" << std::endl;
387  ss_w_clarius_profile_xml << " <name>" << std::wstring(ssid.begin(), ssid.end()) << "</name>" << std::endl;
388  ss_w_clarius_profile_xml << " </SSID>" << std::endl;
389  ss_w_clarius_profile_xml << " </SSIDConfig>" << std::endl;
390  ss_w_clarius_profile_xml << " <connectionType>ESS</connectionType>" << std::endl;
391  ss_w_clarius_profile_xml << " <connectionMode>auto</connectionMode>" << std::endl;
392  ss_w_clarius_profile_xml << " <autoSwitch>false</autoSwitch>" << std::endl;
393  ss_w_clarius_profile_xml << " <MSM>" << std::endl;
394  ss_w_clarius_profile_xml << " <security>" << std::endl;
395  ss_w_clarius_profile_xml << " <authEncryption>" << std::endl;
396  ss_w_clarius_profile_xml << " <authentication>" << authenticationAlgorithm << "</authentication>" << std::endl;
397  ss_w_clarius_profile_xml << " <encryption>" << encryptionAlgorithm << "</encryption>" << std::endl;
398  ss_w_clarius_profile_xml << " <useOneX>false</useOneX>" << std::endl;
399  ss_w_clarius_profile_xml << " </authEncryption>" << std::endl;
400  if (nw_info->dot11DefaultCipherAlgorithm != DOT11_CIPHER_ALGO_NONE)
401  {
402  ss_w_clarius_profile_xml << " <sharedKey>" << std::endl;
403  ss_w_clarius_profile_xml << " <keyType>" << keyType << "</keyType>" << std::endl;
404  ss_w_clarius_profile_xml << " <protected>false</protected>" << std::endl;
405  ss_w_clarius_profile_xml << " <keyMaterial>" << std::wstring(password.begin(), password.end()) << "</keyMaterial>" << std::endl;
406  ss_w_clarius_profile_xml << " </sharedKey>" << std::endl;
407  }
408  ss_w_clarius_profile_xml << " </security>" << std::endl;
409  ss_w_clarius_profile_xml << " </MSM>" << std::endl;
410  ss_w_clarius_profile_xml << "</WLANProfile>";
411  std::wstring w_clarius_profile_xml = ss_w_clarius_profile_xml.str();
412  LOG_DEBUG_W(L"WLAN Profile: \n" << ss_w_clarius_profile_xml.str());
413 
414  // Create/update the Wi-Fi profile
415  DWORD reasonCode = 0;
416  res = WlanSetProfile(this->HClient, &this->InterfaceGuid, 0, w_clarius_profile_xml.c_str(), NULL, TRUE, NULL, &reasonCode);
417  if (res != ERROR_SUCCESS)
418  {
419  WCHAR reasonCodeStr[256] = L"\0";
420  WlanReasonCodeToString(reasonCode, 256, reasonCodeStr, NULL);
421  LOG_ERROR("Failed to set Wi-Fi profile: " << nw_info->strProfileName);
422  LOG_ERROR("Error code: " << res);
423  LOG_ERROR_W(L"Reason: (" << reasonCode << ") " << reasonCodeStr);
424  continue;
425  }
426 
427  this->BssType = nw_info->dot11BssType;
428  profileUpdated = true;
429  break;
430  }
431 
432  // free networks memory
433  if (networks != NULL)
434  {
435  WlanFreeMemory(networks);
436  networks = NULL;
437  }
438 
439  if (!profileUpdated)
440  {
441  LOG_ERROR("Failed to find Clarius Wi-Fi network");
442  return PLUS_FAIL;
443  }
444  return PLUS_SUCCESS;
445 }
446 
447 //-------------------------------------------------------------------------------------------------
449 {
450  // check if currently connected
451  if (!this->Connected)
452  {
453  return PLUS_SUCCESS;
454  }
455 
456  // check ClariusWifi was initialized
457  if (this->HClient == NULL)
458  {
459  LOG_ERROR("ClariusWifi must be initialized before calling IsClariusNetworkReady");
460  return PLUS_FAIL;
461  }
462 
463  // disconnect
464  DWORD res = WlanDisconnect(this->HClient, &this->InterfaceGuid, NULL);
465  if (res != ERROR_SUCCESS)
466  {
467  LOG_ERROR("Failed to disconnect from Clarius wifi network with error: " << res);
468  return PLUS_FAIL;
469  }
470 
471  this->Connected = false;
472  return PLUS_SUCCESS;
473 }
474 
475 //-------------------------------------------------------------------------------------------------
476 PlusStatus ClariusWifi::StringToSsid(std::string ssid, PDOT11_SSID pdot11_ssid)
477 {
478  BYTE pb_ssid[DOT11_SSID_MAX_LENGTH + 1] = { 0 };
479 
480  std::wstring w_ssid(ssid.begin(), ssid.end());
481  if (ssid.empty() || pdot11_ssid == NULL)
482  {
483  return PLUS_FAIL;
484  }
485  else
486  {
487  pdot11_ssid->uSSIDLength = WideCharToMultiByte(CP_ACP,
488  0,
489  w_ssid.c_str(),
490  -1,
491  (LPSTR)pb_ssid,
492  sizeof(pb_ssid),
493  NULL,
494  NULL);
495 
496  pdot11_ssid->uSSIDLength--;
497  memcpy(&pdot11_ssid->ucSSID, pb_ssid, pdot11_ssid->uSSIDLength);
498  }
499 
500  return PLUS_SUCCESS;
501 }
const uint32_t * data
Definition: phidget22.h:3971
PlusStatus IsClariusNetworkReady(std::string ssid)
Definition: ClariusWifi.cxx:78
static const float MAX_NETWORK_READY_WAIT_TIME_SEC
Definition: ClariusWifi.cxx:14
if(isValid) trackerLags
igsioStatus PlusStatus
Definition: PlusCommon.h:40
for i
#define PLUS_FAIL
Definition: PlusCommon.h:43
PlusStatus DeInitialize()
Definition: ClariusWifi.cxx:58
PlusStatus UpdateClariusWifiProfile(std::string ssid, std::string password)
PlusStatus ConnectToClariusWifi(std::string ssid, std::string password)
unsigned long DWORD
Definition: ATC3DGm.h:451
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
PlusStatus IsClariusNetworkConnected()
static const float MAX_NETWORK_CONNECTED_WAIT_TIME_SEC
Definition: ClariusWifi.cxx:18
int * state
Definition: phidget22.h:3207
PlusStatus DisconnectFromClariusWifi()
const char int const char * password
Definition: phidget22.h:2552
PlusStatus Initialize()
Definition: ClariusWifi.cxx:37
#define TRUE
Definition: ATC3DGm.h:219
unsigned char BYTE
Definition: ATC3DGm.h:449
for t
Definition: exploreFolders.m:9