[IOT]Windows 10 IoT Core Build 14376 已支援 RPi3 內建 Bluetooth 了哦!

環境: Windows 10 IoT Core Build 14376 (10.0.14376.0), VS2015

Raspberry Pi3 有內建的 Bluetooth ,但之前使用的 IoT Core 卻還不 Support。

要用 Bluetooth 還要再外接 Bluetooth ,但 Build 14376 已支援了哦!

以下筆者建立一個 iBeacon 的 headless App 來演示一下,

下載及安裝請參考「Windows 10 IoT Core 的 remote debugging PIN」。

預設 Bluetooth 是沒有啟用的,所以要在 裝置設定=>藍牙 那裡啟用它,如下,

再來程式就可以透過 BluetoothLEAdvertisementPublisher 來模擬 iBeacon ,

1.設定 藍牙 權限,在 Package.appxmanifest 的 Capabilities 中,要勾選 Bluetooth,如下,

2.新增一個存放 beacon 資料的json檔(beaconData.json)(因為可能要部到不同的Pi上面,所以可以上傳設定檔)

{
  "manufacturerId": "0215",
  "uuid": "e4c8a4fc-f68b-470d-959f-29382af72ce7",
  "major": "000C",
  "minor": "0003",
  "txPower": "c5"
}

3.設定 beaconData.json 的屬性,在檔案屬性視窗中,Build Action請用Content,如下,

4.在 StartupTask.cs 中加入啟動 iBeacon 的模擬,會先檢查 ApplicationData.Current.LocalFolder ,不存再檔案時,再檢查 Windows.ApplicationModel.Package.Current.InstalledLocation 目錄,如下,

namespace iBeacon
{
    public sealed class StartupTask : IBackgroundTask
    {
        public async void Run(IBackgroundTaskInstance taskInstance)
        {
            // Create the deferral by requesting it from the task instance.
            BackgroundTaskDeferral deferral = taskInstance.GetDeferral();
            try
            {
                //先讀取 beaconData 設定的 Beacon 資訊
                var beaconData = await GetBeaconData();
                // 開始廣播 iBeacon 的廣告訊息
                PublishiBeacon(beaconData);
            }catch(Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }

            // Once the asynchronous method(s) are done, close the deferral.
            // 不要 Call Complete 就不會停止
            //deferral.Complete();
        }

        /// <summary>
        /// 取得 beacon 的資訊
        /// </summary>
        /// <returns></returns>
        private async Task<byte[]> GetBeaconData()
        {
            string fileContent = await ReadBeaconDataFromFile();
            dynamic beacon = JsonConvert.DeserializeObject(fileContent);
            StringBuilder beaconData = new StringBuilder();
            beaconData.Append((string)beacon.manufacturerId);
            beaconData.Append(((string)beacon.uuid).Replace("-",string.Empty));
            beaconData.Append((string)beacon.major);
            beaconData.Append((string)beacon.minor);
            beaconData.Append((string)beacon.txPower);
            string beaconDataStr = beaconData.ToString();
            var result = Enumerable.Range(0, beaconDataStr.Length)
                .Where(x => x % 2 == 0)
                .Select(x => Convert.ToByte(beaconDataStr.Substring(x, 2), 16))
                .ToArray();

            return result;
        }

        /// <summary>
        /// 讀取 beaconData.json 的內容
        /// </summary>
        /// <returns></returns>
        private async Task<string> ReadBeaconDataFromFile()
        {
            var fileName = @"beaconData.json";
            StorageFolder folder;
            StorageFile file;
            try
            {
                //先在 LocalFolder 裡找
                folder = ApplicationData.Current.LocalFolder;
                file = await folder.GetFileAsync(fileName);
            }
            catch (Exception ex)
            {

                //找不到檔案,所以取預設的地方
                folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
                file = await folder.GetFileAsync(fileName);
                Debug.WriteLine(ex.ToString());
            }
            var fileContent = await FileIO.ReadTextAsync(file);
            return fileContent;
        }

        BluetoothLEAdvertisementPublisher _blePublisher;
        private void PublishiBeacon(byte[] dataArray)
        {
            var manufactureData = new BluetoothLEManufacturerData();
            //0x004C	Apple, Inc.
            manufactureData.CompanyId = 0x004c;
            //using System.Runtime.InteropServices.WindowsRuntime;
            manufactureData.Data = dataArray.AsBuffer();
            _blePublisher = new BluetoothLEAdvertisementPublisher();
            _blePublisher.Advertisement.ManufacturerData.Add(manufactureData);
            //開始發佈
            _blePublisher.Start();
        }
    }
}

 

再來就是將程式部到 RPi3 上執行, App執行起來可以用 Android 的手機來掃到模擬出來的Beacon,

而資料就是我們預設的 beaconData.json 的內容,如下,

再來我們先將App停掉,然後修改 beaconData.json 內容如下,

{
  "manufacturerId": "0215",
  "uuid": "e4c8a4fc-f68b-470d-959f-29382af72ce7",
  "major": "000D",
  "minor": "0004",
  "txPower": "c5"
}

然後透過 App File Explorer 上傳到 App 的 LocalState 目錄之中,如下,

再啟動 App,再掃一次就會發現,它會使用新的 beacon 設定(Major:13, Minor:4),如下,

完整程式在 rainmakerho/iBeaconHeadless

註:目前 Build 14393 也出來了哦! 修正一些問題,所以可以直接下載 Build 14393 哦!

 

參考資料

Windows 10 IoT Core 的 remote debugging PIN

儲存及擷取設定和其他 app 資料

Windows 10 IoT Core Command Line Utils

rainmakerho/iBeaconHeadless

Release Notes for Windows 10 IoT Core

Hi, 

亂馬客Blog已移到了 「亂馬客​ : Re:從零開始的軟體開發生活

請大家繼續支持 ^_^