Windows10のPCをBLEのGATTサーバーとして機能させるようなWPFアプリケーションを開発しています。
GATTサーバーとして機能させるために、以下のようにmicrosoft.windows.sdk.contractsをNuGetより取得し、GattServiceProviderを使用しています。
(Guidの値は伏せています)
private static GattServiceProvider serviceProvider = null;
private static GattLocalCharacteristicResult localCharacteristicResult = null;
private async void StartGattServiceProviderAdvertisingParameters()
{
var gattServiceProviderResult = await GattServiceProvider.CreateAsync(new Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"));
if (gattServiceProviderResult.Error != BluetoothError.Success)
{
MessageBox.Show("GATT Serviceの起動に失敗");
Console.WriteLine("GATT Serviceの起動に失敗(Bluetooth LE対応デバイスがない?)");
return false;
}
serviceProvider = gattServiceProviderResult.ServiceProvider;
GattLocalCharacteristicParameters cReadWriteParam = new GattLocalCharacteristicParameters
{
CharacteristicProperties = GattCharacteristicProperties.Read | GattCharacteristicProperties.Write | GattCharacteristicProperties.Notify, //読み込み & 書き込み & 通知購読可能
ReadProtectionLevel = GattProtectionLevel.Plain, //誰でも読み込み可能
WriteProtectionLevel = GattProtectionLevel.Plain, //誰でも書き込み可能
UserDescription = "cReadWrite" //ユーザーに見える説明(BLEツールを使って読むことができる)
};
//定義した情報をもとに、指定のUUIDでサービスに登録する
localCharacteristicResult = await serviceProvider.Service.CreateCharacteristicAsync(new Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"), cReadWriteParam);
//読込が発生したときのコールバック定義
localCharacteristicResult.Characteristic.ReadRequested += Characteristic_ReadRequested;
//書き込みが発生したときのコールバック定義 localCharacteristicResult.Characteristic.WriteRequested += Characteristic_WriteRequested;
//購読者の増減が発生したときのコールバック定義 localCharacteristicResult.Characteristic.SubscribedClientsChanged += Characteristic_SubscribedClientsChanged;
GattServiceProviderAdvertisingParameters serviceProviderAdvertisingParameters = new GattServiceProviderAdvertisingParameters
{
IsConnectable = true, //接続可能
IsDiscoverable = true //検出可能
};
serviceProvider.StartAdvertising(_serviceProviderAdvertisingParameters);
return true;
}
ここからが本題ですが、アプリの中でPCから発信するアドバタイズパケットのLocal Nameを途中で変更したく、
以下のように、Microsoft.Win32.RegistryKeyを使用して、PCのBluetoothデバイス名を変更(設定)しています。
public static void ChangePCBluetoothDeviceName()
{
//Windows Management Instrumentation (WMI) を使ってプラグ アンド プレイ デバイスを取得
ManagementObjectSearcher searchSerial = new ManagementObjectSearcher("SELECT * FROM Win32_PnPEntity WHERE Service='BTHUSB'");
foreach (ManagementObject obj in searchSerial.Get())
{
//string name = obj["Name"] as string; // デバイスマネージャーに表示されている機器名
string classGuid = obj["ClassGuid"] as string; // デバイスのGUID
string devicePass = obj["DeviceID"] as string; // デバイスインスタンスパス
string service = obj["Service"] as string; // デバイスのサービス
if (classGuid != null && devicePass != null)
{
// デバイスインスタンスパスからUSB Bluetoothの デバイスを抽出
// {e0cbf06c-cd8b-4647-bb8a-263b43f0f974}がその固定値
// StringComparison:文字列比較の際の動作を指定するための列挙型で、InvariantCultureで、特定の言語および国・地域に依存しないカルチャを指定する
if (String.Equals(classGuid, "{e0cbf06c-cd8b-4647-bb8a-263b43f0f974}", StringComparison.InvariantCulture))
{
// デバイスインスタンスパスからデバイスIDを2段階で抜き出す
string[] tokens = devicePass.Split('\\');
//BTHUSBで自身のBluetoothデバイス(インテルワイヤレスBluetoothなど)を指定
if (service == "BTHUSB" && tokens[0] == "USB")
{
string path = @"SYSTEM\CurrentControlSet\Enum\";
foreach (string token in tokens)
{
path += token + @"\";
}
path += "Device Parameters";
//レジストリからデバイス名(Local Name)を取得する。
//registryKeyがnullだとpathに合致したレジストリがない、ということ
registryKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(path, true);
//LocalNameの設定がある
if (registryKey != null)
{
}
else
{
registryKey = Microsoft.Win32.Registry.LocalMachine.CreateSubKey(path, true);
}
byte[] ascii = Encoding.ASCII.GetBytes(newName);
registryKey.SetValue("Local Name", ascii2);
registryKey.Flush();
registryKey.Close();
return;
}
}
}
}
}
しかし、設定をし直した後にアドバタイズを再開すると、
アドバタイジングパケットのLocal Nameに変更後の値が反映されたりされなかったりと動作が安定しません。
PCのBluetoothデバイス名を変更後、PCのBluetoothのオンオフを切り替えすることも試しています。
・アドバタイジングパケット(GattServiceProvider)のLocal Nameに変更が反映されたりされなかったりするのはなぜか
・そもそも、GattServiceProviderはどこの値を使用しているのか
・アプリケーション内でLocal Nameを確実に変更できる方法はあるのか
という点をご教授頂きたいです。
よろしくお願いいたします。