13 #include <winrt/base.h> 14 #include <winrt/windows.devices.bluetooth.h> 15 #include <winrt/windows.devices.bluetooth.genericattributeprofile.h> 16 #include <winrt/windows.devices.enumeration.h> 17 #include <winrt/windows.foundation.h> 18 #include <winrt/windows.foundation.collections.h> 19 #include <winrt/windows.storage.h> 20 #include <winrt/windows.storage.streams.h> 23 using namespace winrt;
24 using namespace Windows::Devices::Bluetooth;
25 using namespace Windows::Devices::Bluetooth::GenericAttributeProfile;
26 using namespace Windows::Devices::Enumeration;
27 using namespace Windows::Foundation;
28 using namespace Windows::Foundation::Collections;
29 using namespace Windows::Storage;
30 using namespace Windows::Storage::Streams;
43 #pragma comment(lib, "windowsapp") 47 { 0x8c853b6a, 0x2297, 0x44c1, { 0x82, 0x77, 0x73, 0x62, 0x7c, 0x8d, 0x2a, 0xbc } };
51 { 0x8c853b6a, 0x2297, 0x44c1, { 0x82, 0x77, 0x73, 0x62, 0x7c, 0x8d, 0x2a, 0xbd } };
55 { 0x8c853b6a, 0x2297, 0x44c1, { 0x82, 0x77, 0x73, 0x62, 0x7c, 0x8d, 0x2a, 0xbe } };
59 { 0xf9eb3fae, 0x947a, 0x4e5b, { 0xab, 0x7c, 0xc7, 0x99, 0xe9, 0x1e, 0xd7, 0x80 } };
63 { 0xf9eb3fae, 0x947a, 0x4e5b, { 0xab, 0x7c, 0xc7, 0x99, 0xe9, 0x1e, 0xd7, 0x81 } };
67 { 0xf9eb3fae, 0x947a, 0x4e5b, { 0xab, 0x7c, 0xc7, 0x99, 0xe9, 0x1e, 0xd7, 0x82 } };
80 template <
typename TAsyncOp>
83 std::promise<void> wait_prom;
84 std::future<void> wait_future = wait_prom.get_future();
86 auto busy_wait = [&](TAsyncOp op)
88 while (op.Status() == AsyncStatus::Started);
91 wait_prom.set_value();
96 if (wait_future.wait_for(std::chrono::seconds(
BLE_OP_TIMEOUT_SEC)) != std::future_status::ready)
99 if (op.Status() == AsyncStatus::Canceled)
101 LOG_ERROR(
"Awaiting asynchronous operation which terminated with status AsyncStatus::Canceled");
103 else if (op.Status() == AsyncStatus::Started)
105 LOG_ERROR(
"Awaiting asynchronous operation which timed out with status AsyncStatus::Started");
107 else if (op.Status() == AsyncStatus::Error)
109 LOG_ERROR(
"Error occurred while awaiting asynchronous operation. Error code was: " << op.ErrorCode());
113 LOG_ERROR(
"Unexpected error occurred causing timeout while awaiting completion of C++/WinRT asynchronous operation");
126 std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
127 return converter.from_bytes(str);
133 std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
134 return converter.to_bytes(wstr);
140 std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
141 return converter.to_bytes(hstr.c_str());
148 std::stringstream str;
149 str << std::uppercase << std::hex;
150 str << std::setw(8) << std::setfill(
'0') << uuid.Data1 <<
"-";
151 str << std::setw(4) << std::setfill(
'0') << uuid.Data2 <<
"-";
152 str << std::setw(4) << std::setfill(
'0') << uuid.Data3 <<
"-";
153 str << std::setw(2) << std::setfill('0') << static_cast<short>(uuid.Data4[0])
154 << std::setw(2) << std::setfill(
'0') << static_cast<short>(uuid.Data4[1])
156 << std::setw(2) << std::setfill(
'0') << static_cast<short>(uuid.Data4[2])
157 << std::setw(2) << std::setfill(
'0') << static_cast<short>(uuid.Data4[3])
158 << std::setw(2) << std::setfill(
'0') << static_cast<short>(uuid.Data4[4])
159 << std::setw(2) << std::setfill(
'0') << static_cast<short>(uuid.Data4[5])
160 << std::setw(2) << std::setfill(
'0') << static_cast<short>(uuid.Data4[6])
161 << std::setw(2) << std::setfill(
'0') << static_cast<short>(uuid.Data4[7]);
162 str << std::nouppercase;
169 class ClariusBLEPrivate
175 virtual ~ClariusBLEPrivate() =
default;
178 void DeviceAdded(DeviceWatcher sender, DeviceInformation deviceInfo);
184 void DeviceUpdated(DeviceWatcher sender, DeviceInformationUpdate devInfoUpdate);
187 void PowerStateChanged(GattCharacteristic sender, GattValueChangedEventArgs args);
190 void WifiStateChanged(GattCharacteristic sender, GattValueChangedEventArgs args);
206 std::string GattCommunicationStatusToString(GattCommunicationStatus status);
209 void ProcessWifiInfo(std::string info);
217 std::wstring ProbeId;
220 std::vector<std::string> FoundProbeIds;
223 std::string LastError;
226 DeviceInformation DeviceInfo{
nullptr };
227 std::promise<void> DeviceInfoPromise;
228 BluetoothLEDevice Device{
nullptr };
231 GattDeviceService PowerService{
nullptr };
232 GattDeviceService WifiService{
nullptr };
235 GattCharacteristic PowerPublishedChar{
nullptr };
236 GattCharacteristic PowerRequestChar{
nullptr };
237 GattCharacteristic WifiPublishedChar{
nullptr };
238 GattCharacteristic WifiRequestChar{
nullptr };
241 std::atomic<bool> PowerState;
244 std::promise<void> WifiInfoPromise;
245 std::atomic<bool> WifiInfoSet;
250 PlusStatus RetrieveService(
const guid& serviceUuid, GattDeviceService& service);
253 bool RetrieveCharacteristic(
254 const GattDeviceService& service,
256 GattCharacteristic& characteristic
260 std::vector<std::string> TokenizeString(std::string str,
const char delimiter);
263 std::mutex WifiInfoMutex;
270 ClariusBLEPrivate::ClariusBLEPrivate(
ClariusBLE* ext)
278 void ClariusBLEPrivate::DeviceAdded(
279 DeviceWatcher sender,
280 DeviceInformation info)
284 std::wstring name{ info.Name().c_str() };
285 if (name == this->ProbeId)
287 this->DeviceInfo = info;
288 this->DeviceInfoPromise.set_value();
290 else if (name.find(L
"CUS") != std::wstring::npos)
297 void ClariusBLEPrivate::DeviceUpdated(
298 winrt::Windows::Devices::Enumeration::DeviceWatcher sender,
299 winrt::Windows::Devices::Enumeration::DeviceInformationUpdate devInfoUpdate)
306 void ClariusBLEPrivate::PowerStateChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
308 DataReader reader = DataReader::FromBuffer(args.CharacteristicValue());
309 uint8_t powered = reader.ReadByte();
310 this->PowerState = bool(powered);
314 void ClariusBLEPrivate::WifiStateChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
316 DataReader reader = DataReader::FromBuffer(args.CharacteristicValue());
317 winrt::hstring wifiHString = reader.ReadString(reader.UnconsumedBufferLength());
319 this->ProcessWifiInfo(wifiStr);
322 this->WifiInfoPromise.set_value();
326 PlusStatus ClariusBLEPrivate::SetupPowerService()
346 if (!this->PowerPublishedChar)
348 this->LastError =
"Could not find PowerPublished characteristic";
352 if (!this->PowerRequestChar)
354 this->LastError =
"Could not find PowerRequest characteristic";
359 this->PowerPublishedChar.WriteClientCharacteristicConfigurationDescriptorAsync(
360 GattClientCharacteristicConfigurationDescriptorValue::Notify);
361 this->PowerPublishedChar.ValueChanged({
this, &ClariusBLEPrivate::PowerStateChanged });
367 PlusStatus ClariusBLEPrivate::SetupWifiService()
387 if (!this->WifiPublishedChar)
389 this->LastError =
"Could not find WifiPublished characteristic";
393 if (!this->WifiRequestChar)
395 this->LastError =
"Could not find WifiRequest characteristic";
401 this->WifiPublishedChar.WriteClientCharacteristicConfigurationDescriptorAsync(
402 GattClientCharacteristicConfigurationDescriptorValue::Notify);
403 this->WifiPublishedChar.ValueChanged({
this, &ClariusBLEPrivate::WifiStateChanged });
409 PlusStatus ClariusBLEPrivate::InitializeState()
412 IAsyncOperation<GattReadResult> powerOp =
413 this->PowerPublishedChar.ReadValueAsync(BluetoothCacheMode::Uncached);
418 GattReadResult powerResult = powerOp.GetResults();
420 if (powerResult.Status() != GattCommunicationStatus::Success)
422 std::stringstream msg;
423 msg <<
"Failed to initialize power state in InitializeState with non-successful " 424 "GATT communication. Status was: " 425 << this->GattCommunicationStatusToString(powerResult.Status());
426 this->LastError = msg.str();
430 DataReader powerReader = DataReader::FromBuffer(powerResult.Value());
431 this->PowerState = bool(powerReader.ReadByte());
433 if (!this->PowerState)
441 IAsyncOperation<GattReadResult> wifiOp =
442 this->WifiPublishedChar.ReadValueAsync(BluetoothCacheMode::Uncached);
448 GattReadResult wifiResult = wifiOp.GetResults();
450 if (wifiResult.Status() != GattCommunicationStatus::Success)
452 std::stringstream msg;
453 msg <<
"Failed to initialize wifi state in InitializeState with non-successful " 454 "GATT communication. Status was: " << this->GattCommunicationStatusToString(wifiResult.Status());
455 this->LastError = msg.str();
459 DataReader wifiReader = DataReader::FromBuffer(wifiResult.Value());
460 winrt::hstring wifiHString = wifiReader.ReadString(wifiReader.UnconsumedBufferLength());
462 this->ProcessWifiInfo(wifiStr);
470 std::unique_lock<std::mutex> wifiInfoLock(this->WifiInfoMutex);
471 return this->WifiInfo;
475 std::string ClariusBLEPrivate::GattCommunicationStatusToString(GattCommunicationStatus status)
479 case GattCommunicationStatus::AccessDenied:
480 return "AccessDenied";
481 case GattCommunicationStatus::ProtocolError:
482 return "ProtocolError";
483 case GattCommunicationStatus::Success:
485 case GattCommunicationStatus::Unreachable:
486 return "Unreachable";
488 return "Unknown GattCommunicationStatus";
493 PlusStatus ClariusBLEPrivate::RetrieveService(
const guid& serviceUuid, GattDeviceService& service)
495 IAsyncOperation<GattDeviceServicesResult> getServicesOp =
496 this->Device.GetGattServicesForUuidAsync(serviceUuid, BluetoothCacheMode::Uncached);
502 GattDeviceServicesResult servicesResult = getServicesOp.GetResults();
505 if (servicesResult.Status() != GattCommunicationStatus::Success)
507 std::stringstream msg;
508 msg <<
"ClariusBLEPrivate::RetrieveService failed for UUID " <<
uuid_to_string(serviceUuid)
509 <<
" with non-successful GATT communication. Status was: " 510 << this->GattCommunicationStatusToString(servicesResult.Status());
511 this->LastError = msg.str();
516 if (!servicesResult.Services().Size())
518 std::stringstream msg;
519 msg <<
"ClariusBLEPrivate::RetrieveService failed for UUID " <<
uuid_to_string(serviceUuid)
520 <<
". No services with this UUID were found.";
521 this->LastError = msg.str();
525 service = *servicesResult.Services().First();
528 std::stringstream msg;
529 msg <<
"ClariusBLEPrivate::RetrieveService could not find service " <<
uuid_to_string(serviceUuid);
530 this->LastError = msg.str();
537 bool ClariusBLEPrivate::RetrieveCharacteristic(
538 const GattDeviceService& service,
540 GattCharacteristic& characteristic)
542 IAsyncOperation<GattCharacteristicsResult> getCharsOp =
543 service.GetCharacteristicsForUuidAsync(charUuid, BluetoothCacheMode::Uncached);
549 GattCharacteristicsResult charsResult = getCharsOp.GetResults();
552 if (charsResult.Status() != GattCommunicationStatus::Success)
554 std::stringstream msg;
555 msg <<
"ClariusBLEPrivate::RetrieveCharacteristic failed for UUID " <<
uuid_to_string(charUuid)
556 <<
" with non-successful GATT communication. Status was: " 557 << this->GattCommunicationStatusToString(charsResult.Status());
558 this->LastError = msg.str();
563 if (!charsResult.Characteristics().Size())
565 std::stringstream msg;
566 msg <<
"ClariusBLEPrivate::RetrieveCharacteristic failed for UUID " <<
uuid_to_string(charUuid)
567 <<
". No characteristics with this UUID were found.";
568 this->LastError = msg.str();
572 characteristic = *charsResult.Characteristics().First();
577 void ClariusBLEPrivate::ProcessWifiInfo(std::string info)
579 std::unique_lock<std::mutex> wifiInfoLock(this->WifiInfoMutex);
580 std::vector<std::string> infoList = this->TokenizeString(info,
'\n');
582 if (infoList.size() == 1)
585 if (infoList.at(0).find(
"state") == std::string::npos)
587 throw std::runtime_error(
"Format of ClariusWifiInfo string has changed. Please report " 588 "this info the the PLUS developers");
592 newInfo.
Ready =
false;
593 this->WifiInfo = newInfo;
596 else if (infoList.size() != 10)
598 throw std::runtime_error(
"Format of ClariusWifiInfo string has changed. Please report " 599 "this info the the PLUS developers");
605 std::string stateStr = infoList.at(0);
606 newInfo.
Ready = (stateStr.find(
"connected") != std::string::npos);
609 std::string availStr = infoList.at(7);
610 std::string availTag =
"avail: ";
611 availStr = availStr.replace(0, availTag.length(),
"");
612 if (availStr ==
"available")
616 else if (availStr ==
"listen")
626 std::string apStr = infoList.at(1);
627 if (apStr.find(
"true") != std::string::npos)
637 std::string ssidStr = infoList.at(2);
638 std::string ssidTag =
"ssid: ";
639 newInfo.
SSID = ssidStr.replace(0, ssidTag.length(),
"");
642 std::string pwStr = infoList.at(3);
643 std::string pwTag =
"pw: ";
644 newInfo.
Password = pwStr.replace(0, pwTag.length(),
"");
647 std::string ipv4Str = infoList.at(4);
648 std::string ipv4Tag =
"ip4: ";
649 newInfo.
IPv4 = ipv4Str.replace(0, ipv4Tag.length(),
"");
652 std::string macStr = infoList.at(9);
653 std::string macTag =
"mac: ";
654 newInfo.
MacAddress = macStr.replace(0, macTag.length(),
"");
657 std::string ctlStr = infoList.at(5);
658 std::string ctlTag =
"ctl: ";
659 std::string ctlStrInt = ctlStr.replace(0, ctlTag.length(),
"");
663 std::string castStr = infoList.at(6);
664 std::string castTag =
"cast: ";
665 std::string castStrInt = castStr.replace(0, castTag.length(),
"");
666 newInfo.
CastPort = std::stoi(castStrInt);
669 std::string channelStr = infoList.at(8);
670 std::string channelTag =
"channel: ";
671 std::string channelStrInt = channelStr.replace(0, channelTag.length(),
"");
672 newInfo.
Channel = std::stoi(channelStrInt);
675 this->WifiInfo = newInfo;
676 this->WifiInfoSet =
true;
680 std::vector<std::string> ClariusBLEPrivate::TokenizeString(std::string str,
const char delimiter)
682 std::stringstream ss(str);
683 std::vector<std::string> tokens;
686 while (getline(ss, tmp, delimiter))
688 tokens.push_back(tmp);
698 : _impl(std::make_unique<ClariusBLEPrivate>(this))
712 std::string fullBleName =
"CUS-" + serialNum;
715 DeviceWatcher deviceWatcher{
nullptr };
716 winrt::hstring aqsFilter{ BluetoothLEDevice::GetDeviceSelectorFromPairingState(
true) };
717 deviceWatcher = DeviceInformation::CreateWatcher(
720 DeviceInformationKind::AssociationEndpoint
722 deviceWatcher.Added({ _impl.get(), &ClariusBLEPrivate::DeviceAdded });
723 deviceWatcher.Updated({ _impl.get(), &ClariusBLEPrivate::DeviceUpdated });
725 std::future<void> deviceInfoFuture = _impl->DeviceInfoPromise.get_future();
726 deviceWatcher.Start();
728 if (deviceInfoFuture.wait_for(std::chrono::milliseconds(1000)) == std::future_status::ready)
730 deviceWatcher.Stop();
734 deviceWatcher.Stop();
741 return _impl->FoundProbeIds;
747 return (_impl->Device && _impl->Device.ConnectionStatus() == BluetoothConnectionStatus::Connected);
753 if (!_impl->DeviceInfo)
755 _impl->LastError =
"Attempted to call ClariusBLE::Connect with unset m_deviceInfo, " 756 "ensure ClariusBLE::FindBySerial is called successfully before calling Connect";
759 if (_impl->Device && _impl->Device.ConnectionStatus() == BluetoothConnectionStatus::Connected)
761 _impl->LastError =
"Connect called but probe is already connected";
766 int maxConnectionAttempts = 15;
770 int connectionAttemptCount = 0;
771 int retryDelayMs = 1000;
772 while (connectionAttemptCount < maxConnectionAttempts && !success)
774 if (connectionAttemptCount > 0)
776 LOG_DEBUG(
"Attempt #" << connectionAttemptCount <<
" failed. Last error: \"" << this->
GetLastError() <<
"\"");
778 std::this_thread::sleep_for(std::chrono::milliseconds(retryDelayMs));
781 ++connectionAttemptCount;
782 LOG_DEBUG(
"Trying to connect: Attempt #" << connectionAttemptCount);
784 IAsyncOperation<BluetoothLEDevice> deviceOp = BluetoothLEDevice::FromIdAsync(_impl->DeviceInfo.Id());
787 _impl->LastError =
"Failed to connect to device.";
790 _impl->Device = deviceOp.GetResults();
791 if (_impl->Device ==
nullptr)
793 _impl->LastError =
"Failed to connect to device.";
814 LOG_DEBUG(
"Device connected: Attempt #" << connectionAttemptCount);
823 if (_impl->PowerService)
825 _impl->PowerService.Close();
827 if (_impl->WifiService)
829 _impl->WifiService.Close();
833 _impl->Device.Close();
836 _impl->PowerPublishedChar =
nullptr;
837 _impl->PowerRequestChar =
nullptr;
838 _impl->WifiPublishedChar =
nullptr;
839 _impl->WifiRequestChar =
nullptr;
841 _impl->PowerService =
nullptr;
842 _impl->WifiService =
nullptr;
844 _impl->Device =
nullptr;
860 _impl->DeviceInfo =
nullptr;
868 return _impl->PowerState;
876 _impl->LastError =
"RequestProbeOn called but no probe is connected";
881 writer.WriteByte(0x01);
882 IBuffer buf = writer.DetachBuffer();
884 IAsyncOperation<GattWriteResult> writeOp =
885 _impl->PowerRequestChar.WriteValueWithResultAsync(buf, GattWriteOption::WriteWithResponse);
891 GattWriteResult writeResult = writeOp.GetResults();
893 if (writeResult.Status() != GattCommunicationStatus::Success)
895 std::stringstream msg;
896 msg <<
"ClariusBLE::ProbeOn failed with non-successful GATT communication. Status was: " 897 << _impl->GattCommunicationStatusToString(writeResult.Status());
898 _impl->LastError = msg.str();
910 _impl->LastError =
"RequestProbeOff called but no probe is connected";
915 writer.WriteByte(0x00);
916 IBuffer buf = writer.DetachBuffer();
918 if (_impl->PowerRequestChar)
920 IAsyncOperation<GattWriteResult> writeOp =
921 _impl->PowerRequestChar.WriteValueWithResultAsync(buf, GattWriteOption::WriteWithResponse);
927 GattWriteResult writeResult = writeOp.GetResults();
929 if (writeResult.Status() != GattCommunicationStatus::Success)
931 std::stringstream msg;
932 msg <<
"ClariusBLE::ProbeOff failed with non-successful GATT communication. Status was: " 933 << _impl->GattCommunicationStatusToString(writeResult.Status());
934 _impl->LastError = msg.str();
940 LOG_ERROR(
"Unable to send probe off signal. Power request characteristic not availiable.");
950 if (_impl->WifiInfoSet)
959 if (_impl->WifiInfoSet)
965 std::future<void> wifiInfoFuture = _impl->WifiInfoPromise.get_future();
967 if (wifiInfoFuture.wait_for(std::chrono::seconds(
POWER_ON_TIMEOUT_SEC)) == std::future_status::ready)
976 if (!_impl->WifiInfoSet)
978 std::stringstream msg;
980 <<
" to boot up and provide Wifi info, please try again" << std::endl;
981 _impl->LastError = msg.str();
991 IAsyncOperation<GattReadResult> wifiOp =
992 _impl->WifiPublishedChar.ReadValueAsync(BluetoothCacheMode::Uncached);
995 GattReadResult wifiResult = wifiOp.GetResults();
996 DataReader wifiReader = DataReader::FromBuffer(wifiResult.Value());
997 winrt::hstring wifiHString = wifiReader.ReadString(wifiReader.UnconsumedBufferLength());
999 _impl->ProcessWifiInfo(wifiStr);
1010 _impl->LastError =
"ConfigureWifiAP called but no probe is connected";
1014 std::stringstream ss;
1016 ss <<
"channel: auto\n";
1020 IBuffer buf = writer.DetachBuffer();
1022 IAsyncOperation<GattWriteResult> writeOp =
1023 _impl->WifiRequestChar.WriteValueWithResultAsync(buf, GattWriteOption::WriteWithResponse);
1029 GattWriteResult writeResult = writeOp.GetResults();
1031 if (writeResult.Status() != GattCommunicationStatus::Success)
1033 std::stringstream msg;
1034 msg <<
"ClariusBLE::ConfigureWifiAP failed with non-successful GATT communication. Status was: " 1035 << _impl->GattCommunicationStatusToString(writeResult.Status());
1036 _impl->LastError = msg.str();
1048 _impl->LastError =
"ConfigureWifiLAN called but no probe is connected";
1054 _impl->LastError =
"ClariusBLE::ConfigureWifiLAN called with ssid parameter of invalid length (0)";
1059 _impl->LastError =
"ClariusBLE::ConfigureWifiLAN called with password parameter of invalid length (0)";
1063 std::stringstream ss;
1064 ss <<
"ap: false\n";
1065 ss <<
"ssid: " << ssid <<
"\n";
1070 IBuffer buf = writer.DetachBuffer();
1072 IAsyncOperation<GattWriteResult> writeOp =
1073 _impl->PowerRequestChar.WriteValueWithResultAsync(buf, GattWriteOption::WriteWithResponse);
1079 GattWriteResult writeResult = writeOp.GetResults();
1081 if (writeResult.Status() != GattCommunicationStatus::Success)
1083 std::stringstream msg;
1084 msg <<
"ClariusBLE::ConfigureWifiLAN failed with non-successful GATT communication. Status was: " 1085 << _impl->GattCommunicationStatusToString(writeResult.Status());
1086 _impl->LastError = msg.str();
1096 if (!_impl->WifiInfoSet)
1098 _impl->LastError =
"Clarius wifi info not set yet...";
1108 return _impl->LastError;
static const winrt::guid WIFI_SERVICE_UUID
PlusStatus FindBySerial(std::string serialNum)
std::string to_narrow_string(std::wstring wstr)
PlusStatus CloseConnection()
std::string uuid_to_string(const winrt::guid &uuid)
PlusStatus ConfigureWifiAP()
std::pair< PlusStatus, ClariusWifiInfo > GetWifiInfo()
PlusStatus await_async(TAsyncOp op)
static const winrt::guid POWER_SERVICE_UUID
PlusStatus RequestProbeOn()
const char int const char * password
ClariusAvailability Available
bool AwaitWifiInfoReady()
static const winrt::guid WIFI_REQUEST_CHAR_UUID
static const uint64_t POWER_ON_TIMEOUT_SEC
std::string GetLastError()
PlusStatus ReadWifiInfo()
static const uint64_t BLE_OP_TIMEOUT_SEC
static const winrt::guid WIFI_PUBLISHED_CHAR_UUID
static const winrt::guid POWER_PUBLISHED_CHAR_UUID
PlusStatus ConfigureWifiLAN(std::string ssid, std::string password)
PlusStatus RequestProbeOff()
static const winrt::guid POWER_REQUEST_CHAR_UUID
std::wstring to_wide_string(std::string str)
std::vector< std::string > RetrieveFoundProbeIds()