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 //-------------------------------------------------------------------------------------------------
18  : Connected(false)
19  , HClient(NULL)
20  , CurApiVersion(0)
21 {
22 }
23 
24 //-------------------------------------------------------------------------------------------------
26 {
27  // enforce disconnection & de-initialization
29  this->DeInitialize();
30 }
31 
32 //-------------------------------------------------------------------------------------------------
34 {
35  // already initialized, return failure
36  if (this->HClient != NULL)
37  {
38  LOG_ERROR("ClariusWifi already intialized, this initialization call was rejected");
39  return PLUS_FAIL;
40  }
41 
42  DWORD maxClientVersion = 2;
43  DWORD res = WlanOpenHandle(maxClientVersion, NULL, &this->CurApiVersion, &this->HClient);
44  if (res != ERROR_SUCCESS)
45  {
46  LOG_ERROR("Failed to open WLAN API client handle");
47  return PLUS_FAIL;
48  }
49 
50  return PLUS_SUCCESS;
51 }
52 
53 //-------------------------------------------------------------------------------------------------
55 {
56  // already de-initialized, return success
57  if (this->HClient == NULL)
58  {
59  return PLUS_SUCCESS;
60  }
61 
62  DWORD res = WlanCloseHandle(this->HClient, NULL);
63  if (res != ERROR_SUCCESS)
64  {
65  LOG_ERROR("Failed to close WLAN API client handle");
66  return PLUS_FAIL;
67  }
68 
69  this->HClient = NULL;
70  return PLUS_SUCCESS;
71 }
72 
73 //-------------------------------------------------------------------------------------------------
75 {
76  // check ClariusWifi was initialized
77  if (this->HClient == NULL)
78  {
79  LOG_ERROR("ClariusWifi must be initialized before calling IsClariusNetworkReady");
80  return PLUS_FAIL;
81  }
82 
83  PWLAN_INTERFACE_INFO_LIST interfaces = NULL;
84  PWLAN_INTERFACE_INFO if_info = NULL;
85  DWORD res = WlanEnumInterfaces(this->HClient, NULL, &interfaces);
86  if (res != ERROR_SUCCESS)
87  {
88  LOG_ERROR("Failed to enumerate WLAN interfaces");
89  return PLUS_FAIL;
90  }
91 
92  for (int i = 0; i < interfaces->dwNumberOfItems; i++)
93  {
94  if_info = (WLAN_INTERFACE_INFO*)&interfaces->InterfaceInfo[i];
95 
96  PWLAN_RAW_DATA data;
97  res = WlanScan(this->HClient, &if_info->InterfaceGuid, NULL, NULL, NULL);
98  if (res != ERROR_SUCCESS)
99  {
100  LOG_ERROR("Failed to scan for networks");
101  }
102 
103  PWLAN_AVAILABLE_NETWORK_LIST networks = NULL;
104  PWLAN_AVAILABLE_NETWORK nw_info = NULL;
105  res = WlanGetAvailableNetworkList(this->HClient, &if_info->InterfaceGuid,
106  0, NULL, &networks);
107  if (res != ERROR_SUCCESS)
108  {
109  LOG_WARNING("Failed to list available networks for interface: " << if_info->strInterfaceDescription);
110  continue;
111  }
112 
113  for (int j = 0; j < networks->dwNumberOfItems; j++)
114  {
115  nw_info = (WLAN_AVAILABLE_NETWORK*)&networks->Network[j];
116 
117  std::string candidate_ssid = (char*)nw_info->dot11Ssid.ucSSID;
118  if (ssid.compare(candidate_ssid) == 0)
119  {
120  this->InterfaceGuid = if_info->InterfaceGuid;
121  return PLUS_SUCCESS;
122  }
123  }
124 
125  // free networks memory
126  if (networks != NULL)
127  {
128  WlanFreeMemory(networks);
129  networks = NULL;
130  }
131  }
132 
133  // free interfaces memory
134  if (interfaces != NULL)
135  {
136  WlanFreeMemory(interfaces);
137  interfaces = NULL;
138  }
139 
140  return PLUS_FAIL;
141 }
142 
143 //-------------------------------------------------------------------------------------------------
145 {
146  // already connected, return failure
147  if (this->Connected)
148  {
149  LOG_ERROR("ClariusWifi already connected to Clarius network, this connection call was rejected");
150  }
151 
152  // check ClariusWifi was initialized
153  if (this->HClient == NULL)
154  {
155  LOG_ERROR("ClariusWifi must be initialized before calling IsClariusNetworkReady");
156  return PLUS_FAIL;
157  }
158 
159  // wait for Clarius network being ready
160  std::chrono::steady_clock::time_point start_time = std::chrono::steady_clock::now();
161  PlusStatus network_ready = PLUS_FAIL;
162  while (network_ready != PLUS_SUCCESS)
163  {
164  // check we haven't exceeded the maximum wait time for Clarius network
165  // to be ready
166  std::chrono::steady_clock::time_point t = std::chrono::steady_clock::now();
167  std::chrono::duration<double> dur = t - start_time;
168  if (dur.count() > MAX_NETWORK_READY_WAIT_TIME_SEC)
169  {
170  LOG_ERROR("Waiting for Clarius wifi network to be ready timed out.");
171  return PLUS_FAIL;
172  }
173 
174  // pause for 500ms, to avoid overhead of checking wifi availability at high
175  // refresh rate
176  std::this_thread::sleep_for(std::chrono::milliseconds(500));
177 
178  // refresh network_ready state
179  network_ready = this->IsClariusNetworkReady(ssid);
180  }
181 
182  if (this->UpdateClariusWifiProfile(ssid, password) != PLUS_SUCCESS)
183  {
184  LOG_ERROR("Failed to update Clarius wifi profile");
185  return PLUS_FAIL;
186  }
187 
188  // Convert ssid string to DOT11_SSID
189  DOT11_SSID dot11_ssid = { 0 };
190  if (this->StringToSsid(ssid, &dot11_ssid) != PLUS_SUCCESS)
191  {
192  LOG_ERROR("Failed to convert ssid string to DOT11_SSID type");
193  return PLUS_FAIL;
194  }
195 
196  // Connect
197  std::wstring w_ssid = std::wstring(ssid.begin(), ssid.end());
198  WLAN_CONNECTION_PARAMETERS wlan_params;
199  wlan_params.pDot11Ssid = NULL;
200  wlan_params.strProfile = w_ssid.c_str();
201  wlan_params.wlanConnectionMode = wlan_connection_mode_profile;
202  wlan_params.pDesiredBssidList = NULL;
203  wlan_params.dot11BssType = this->BssType;
204  wlan_params.dwFlags = 0;
205 
206  DWORD res = WlanConnect(this->HClient, &this->InterfaceGuid, &wlan_params, NULL);
207  if (res != ERROR_SUCCESS)
208  {
209  LOG_ERROR("Failed to connect to Clarius wifi network: Error code " << res);
210  return PLUS_FAIL;
211  }
212 
213  this->Connected = true;
214  return PLUS_SUCCESS;
215 }
216 
217 //-------------------------------------------------------------------------------------------------
219 {
220  bool profileUpdated = false;
221 
222  PWLAN_AVAILABLE_NETWORK_LIST networks = NULL;
223  PWLAN_AVAILABLE_NETWORK nw_info = NULL;
224  DWORD res = WlanGetAvailableNetworkList(this->HClient, &this->InterfaceGuid,
225  0, NULL, &networks);
226  if (res != ERROR_SUCCESS)
227  {
228  LOG_WARNING("Failed to list available networks");
229  return PLUS_FAIL;
230  }
231 
232  for (int j = 0; j < networks->dwNumberOfItems; j++)
233  {
234  nw_info = (WLAN_AVAILABLE_NETWORK*)&networks->Network[j];
235 
236  std::string candidate_ssid = (char*)nw_info->dot11Ssid.ucSSID;
237  if (ssid.compare(candidate_ssid) != 0)
238  {
239  continue;
240  }
241 
242  std::wstring authenticationAlgorithm;
243  switch (nw_info->dot11DefaultAuthAlgorithm)
244  {
245  case DOT11_AUTH_ALGO_80211_OPEN:
246  authenticationAlgorithm = L"OPEN";
247  break;
248  case DOT11_AUTH_ALGO_80211_SHARED_KEY:
249  authenticationAlgorithm = L"SHARED";
250  break;
251  case DOT11_AUTH_ALGO_WPA:
252  case DOT11_AUTH_ALGO_WPA_PSK:
253  case DOT11_AUTH_ALGO_WPA_NONE:
254  authenticationAlgorithm = L"WPAPSK";
255  break;
256  case DOT11_AUTH_ALGO_RSNA:
257  case DOT11_AUTH_ALGO_RSNA_PSK:
258  authenticationAlgorithm = L"WPA2PSK";
259  break;
260  default:
261  authenticationAlgorithm = L"UNKNOWN";
262  }
263 
264  std::wstring encryptionAlgorithm;
265  std::wstring keyType = L"passPhrase";
266  switch (nw_info->dot11DefaultCipherAlgorithm)
267  {
268  case DOT11_CIPHER_ALGO_NONE:
269  encryptionAlgorithm = L"NONE";
270  break;
271  case DOT11_CIPHER_ALGO_TKIP:
272  encryptionAlgorithm = L"TKIP";
273  break;
274 
275  case DOT11_CIPHER_ALGO_CCMP:
276  encryptionAlgorithm = L"AES";
277  break;
278  default:
279  encryptionAlgorithm = L"WEP";
280  keyType = L"networkKey";
281  }
282 
283  std::wstringstream ss_w_clarius_profile_xml;
284  ss_w_clarius_profile_xml << "<?xml version=\"1.0\" encoding=\"US-ASCII\"?>" << std::endl;
285  ss_w_clarius_profile_xml << "<WLANProfile xmlns=\"http://www.microsoft.com/networking/WLAN/profile/v1\">" << std::endl;
286  ss_w_clarius_profile_xml << " <name>" << std::wstring(ssid.begin(), ssid.end()) << "</name>" << std::endl;
287  ss_w_clarius_profile_xml << " <SSIDConfig>" << std::endl;
288  ss_w_clarius_profile_xml << " <SSID>" << std::endl;
289  ss_w_clarius_profile_xml << " <name>" << std::wstring(ssid.begin(), ssid.end()) << "</name>" << std::endl;
290  ss_w_clarius_profile_xml << " </SSID>" << std::endl;
291  ss_w_clarius_profile_xml << " </SSIDConfig>" << std::endl;
292  ss_w_clarius_profile_xml << " <connectionType>ESS</connectionType>" << std::endl;
293  ss_w_clarius_profile_xml << " <connectionMode>auto</connectionMode>" << std::endl;
294  ss_w_clarius_profile_xml << " <autoSwitch>false</autoSwitch>" << std::endl;
295  ss_w_clarius_profile_xml << " <MSM>" << std::endl;
296  ss_w_clarius_profile_xml << " <security>" << std::endl;
297  ss_w_clarius_profile_xml << " <authEncryption>" << std::endl;
298  ss_w_clarius_profile_xml << " <authentication>" << authenticationAlgorithm << "</authentication>" << std::endl;
299  ss_w_clarius_profile_xml << " <encryption>" << encryptionAlgorithm << "</encryption>" << std::endl;
300  ss_w_clarius_profile_xml << " <useOneX>false</useOneX>" << std::endl;
301  ss_w_clarius_profile_xml << " </authEncryption>" << std::endl;
302  if (nw_info->dot11DefaultCipherAlgorithm != DOT11_CIPHER_ALGO_NONE)
303  {
304  ss_w_clarius_profile_xml << " <sharedKey>" << std::endl;
305  ss_w_clarius_profile_xml << " <keyType>" << keyType << "</keyType>" << std::endl;
306  ss_w_clarius_profile_xml << " <protected>false</protected>" << std::endl;
307  ss_w_clarius_profile_xml << " <keyMaterial>" << std::wstring(password.begin(), password.end()) << "</keyMaterial>" << std::endl;
308  ss_w_clarius_profile_xml << " </sharedKey>" << std::endl;
309  }
310  ss_w_clarius_profile_xml << " </security>" << std::endl;
311  ss_w_clarius_profile_xml << " </MSM>" << std::endl;
312  ss_w_clarius_profile_xml << "</WLANProfile>";
313  std::wstring w_clarius_profile_xml = ss_w_clarius_profile_xml.str();
314  LOG_DEBUG_W(L"WLAN Profile: \n" << ss_w_clarius_profile_xml.str());
315 
316  // Create/update the Wi-Fi profile
317  DWORD reasonCode = 0;
318  res = WlanSetProfile(this->HClient, &this->InterfaceGuid, 0, w_clarius_profile_xml.c_str(), NULL, TRUE, NULL, &reasonCode);
319  if (res != ERROR_SUCCESS)
320  {
321  WCHAR reasonCodeStr[256] = L"\0";
322  WlanReasonCodeToString(reasonCode, 256, reasonCodeStr, NULL);
323  LOG_ERROR("Failed to set Wi-Fi profile: " << nw_info->strProfileName);
324  LOG_ERROR("Error code: " << res);
325  LOG_ERROR_W(L"Reason: (" << reasonCode << ") " << reasonCodeStr);
326  continue;
327  }
328 
329  this->BssType = nw_info->dot11BssType;
330  profileUpdated = true;
331  break;
332  }
333 
334  // free networks memory
335  if (networks != NULL)
336  {
337  WlanFreeMemory(networks);
338  networks = NULL;
339  }
340 
341  if (!profileUpdated)
342  {
343  LOG_ERROR("Failed to find Clarius Wi-Fi network");
344  return PLUS_FAIL;
345  }
346  return PLUS_SUCCESS;
347 }
348 
349 //-------------------------------------------------------------------------------------------------
351 {
352  // check if currently connected
353  if (!this->Connected)
354  {
355  return PLUS_SUCCESS;
356  }
357 
358  // check ClariusWifi was initialized
359  if (this->HClient == NULL)
360  {
361  LOG_ERROR("ClariusWifi must be initialized before calling IsClariusNetworkReady");
362  return PLUS_FAIL;
363  }
364 
365  // disconnect
366  DWORD res = WlanDisconnect(this->HClient, &this->InterfaceGuid, NULL);
367  if (res != ERROR_SUCCESS)
368  {
369  LOG_ERROR("Failed to disconnect from Clarius wifi network with error: " << res);
370  return PLUS_FAIL;
371  }
372 
373  this->Connected = false;
374  return PLUS_SUCCESS;
375 }
376 
377 //-------------------------------------------------------------------------------------------------
378 PlusStatus ClariusWifi::StringToSsid(std::string ssid, PDOT11_SSID pdot11_ssid)
379 {
380  BYTE pb_ssid[DOT11_SSID_MAX_LENGTH + 1] = { 0 };
381 
382  std::wstring w_ssid(ssid.begin(), ssid.end());
383  if (ssid.empty() || pdot11_ssid == NULL)
384  {
385  return PLUS_FAIL;
386  }
387  else
388  {
389  pdot11_ssid->uSSIDLength = WideCharToMultiByte(CP_ACP,
390  0,
391  w_ssid.c_str(),
392  -1,
393  (LPSTR)pb_ssid,
394  sizeof(pb_ssid),
395  NULL,
396  NULL);
397 
398  pdot11_ssid->uSSIDLength--;
399  memcpy(&pdot11_ssid->ucSSID, pb_ssid, pdot11_ssid->uSSIDLength);
400  }
401 
402  return PLUS_SUCCESS;
403 }
const uint32_t * data
Definition: phidget22.h:3971
PlusStatus IsClariusNetworkReady(std::string ssid)
Definition: ClariusWifi.cxx:74
static const float MAX_NETWORK_READY_WAIT_TIME_SEC
Definition: ClariusWifi.cxx:14
igsioStatus PlusStatus
Definition: PlusCommon.h:40
for i
#define PLUS_FAIL
Definition: PlusCommon.h:43
PlusStatus DeInitialize()
Definition: ClariusWifi.cxx:54
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 DisconnectFromClariusWifi()
const char int const char * password
Definition: phidget22.h:2552
PlusStatus Initialize()
Definition: ClariusWifi.cxx:33
#define TRUE
Definition: ATC3DGm.h:219
unsigned char BYTE
Definition: ATC3DGm.h:449
for t
Definition: exploreFolders.m:9