Quantcast
Channel: かずきのBlog@hatena
Viewing all articles
Browse latest Browse all 1387

WPFからUWPのAPIを使ってBLEの操作をしよう

$
0
0

さて、UWPのAPIを使えるということで先日アドバタイズパケットの受信をやりました。

blog.okazuki.jp

今度はBLEの通信をしてみたいと思います。

参考ページは以下。

blog.fenrir-inc.com

そして、今回使うセンサーはSensorTagのv1です。

www.tij.co.jp

Windows Runtime用ソースコードがあるので、参考にさせてもらいます。

sensortag.codeplex.com

作ってみよう

WPFのプロジェクトを作ってUwpDesktopパッケージをNuGetからインストールします。SensorTagで使うUUIDを定義します。

namespace BleSample
{
    publicclass SensorTagUuid
    {
        // https://sensortag.codeplex.com/SourceControl/latest#SensorTagLibrary/SensorTagLibrary/Source/SensorTagUuid.cspublicconststring UuidIrtService = "f000aa00-0451-4000-b000-000000000000";
        publicconststring UuidIrtData = "f000aa01-0451-4000-b000-000000000000";
        publicconststring UuidIrtConf = "f000aa02-0451-4000-b000-000000000000";
    }
}

画面に初期化用ボタンと値を読み込み始めるボタンとデータ表示用TextBlockを置きます。

<Window x:Class="BleSample.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:BleSample"mc:Ignorable="d"Title="MainWindow"Height="350"Width="525"><StackPanel><Button Content="Connect"Click="ButtonConnect_Click" /><Button Content="Read value"Click="ButtonReadValue_Click" /><TextBlock x:Name="TextBlockTemp" /></StackPanel></Window>

そして、コードビハインドにUWPのAPIを使ってさくっとコードを書きましょう。

using System;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Windows;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Devices.Enumeration;
using Windows.Storage.Streams;

namespace BleSample
{
    /// <summary>/// MainWindow.xaml の相互作用ロジック/// </summary>publicpartialclass MainWindow : Window
    {
        private GattDeviceService GattDeviceService { get; set; }

        private GattCharacteristic GattCharacteristic { get; set; }

        public MainWindow()
        {
            InitializeComponent();
        }

        private async void ButtonConnect_Click(object sender, RoutedEventArgs e)
        {
            // SensorTagを取得
            var selector = GattDeviceService.GetDeviceSelectorFromUuid(new Guid(SensorTagUuid.UuidIrtService));
            var devices = await DeviceInformation.FindAllAsync(selector);
            var deviceInformation = devices.FirstOrDefault();
            if (deviceInformation == null)
            {
                MessageBox.Show("not found");
                return;
            }

            this.GattDeviceService = await GattDeviceService.FromIdAsync(deviceInformation.Id);
            MessageBox.Show($"found {deviceInformation.Id}");

            // センサーの有効化?
            var configCharacteristic = this.GattDeviceService.GetCharacteristics(new Guid(SensorTagUuid.UuidIrtConf)).First();
            var status = await configCharacteristic.WriteValueAsync(newbyte[] { 1 }.AsBuffer());
            if (status == GattCommunicationStatus.Unreachable)
            {
                MessageBox.Show("Initialize failed");
                return;
            }
        }

        private async void ButtonReadValue_Click(object sender, RoutedEventArgs e)
        {
            if (this.GattDeviceService == null)
            {
                MessageBox.Show("Please click connect button");
                return;
            }

            // 値を読み始めるif (this.GattCharacteristic == null)
            {
                this.GattCharacteristic = this.GattDeviceService.GetCharacteristics(new Guid(SensorTagUuid.UuidIrtData)).First();
                this.GattCharacteristic.ValueChanged += this.GattCharacteristic_ValueChanged;

                var status = await this.GattCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify);
                if (status == GattCommunicationStatus.Unreachable)
                {
                    MessageBox.Show("Failed");
                }
            }
        }

        private async void GattCharacteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
        {
            // 値を読んで表示する
            await this.Dispatcher.InvokeAsync(() =>
            {
                var data = newbyte[args.CharacteristicValue.Length];
                DataReader.FromBuffer(args.CharacteristicValue).ReadBytes(data);
                var temp = BitConverter.ToUInt16(data, 2) / 128.0;
                this.TextBlockTemp.Text = $"{temp}℃";
            });
        }
    }
}

基本的にGattなにがし系のクラスを使う感じですね。あとはIBufferとbyte[]の相互変換あたりがポイントでしょうか。あとはSensorTagのコードを参考に真似させてもらいました。

実行してボタンをぽちぽちっと押すと温度が表示されます。

f:id:okazuki:20160722225923p:plain

ソースコード

ソースコード全体はGitHubに上げておきます。

github.com


Viewing all articles
Browse latest Browse all 1387

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>