自分の死活確認を外部から行えるようにしたいと思い、ウェアラブルデバイスをいじり始めました。
いじりはじめたデバイスのひとつが、エプソンの『PULSENSE』。
ただ、PULSENSEのwebサイトの開発者向け情報を見ると「商品化を前提とした法人格を有する組織が守秘義務契約を結んだら情報提供をする」的なことが書いてあり、購買欲は一気にしぼんでしまいました。
が、「Heart Rate Profileに準拠」とも書いてあり、デバイス自体は制御できそうです。
インターネットで検索をしても「つながった」という情報があまり見つからない(Heart Rate Profile準拠のアプリでの接続事例が大半)のですが、イトーヨーカドーのネットショップで普及モデルのPS-100が非常に安く売っていたので、ダメもとで購入してみました。
結論としては、PULSENSEから心拍数データが取得できました。
今回は、Windows上でペアリングを行った状態で、データの取得のみを自前のプログラムで行っています。
プログラムから自動的にペアリングが可能かどうかは今後の検証していく予定です。
まず、必要なものから。
Visual Studioを起動し、適当なプロジェクト(Windowsフォームアプリケーションかコンソールアプリケーションあたりが良いと思います)を作成します。
作成したプロジェクトを閉じて、プロジェクトが格納されている場所にある、拡張子が.vbprojのファイルをテキストエディタで開きます。
開いたらTargetFrameworkVersionタグを検索して、その上あたりに以下の一行を追加します。
<TargetPlatformVersion>8.1</TargetPlatformVersion>
追加したら、Visual Studioでプロジェクトを開きます。
プロジェクトが開いたら、ソリューションエクスプローラで「参照」を右クリックし、メニューの「参照の追加」を選びます。
参照マネージャが開いたら、左側のツリーリストから「Windows 8.1」-「コア」を選択します。
一覧表示された「Windows」をチェックします。
続けて、参照ボタンを押し、アセンブリの参照を追加します。追加するのは以下の2つです。
(アセンブリの場所は環境に合わせて適宜調整してください。厳密には検証していませんが、バージョン番号は4.5.1以降ならば大丈夫そうな感じがします。)
アセンブリの参照を追加をしたら、それぞれチェックを行い、OKボタンを押します。
この時、「”Windows”への参照を追加できませんでした。コンポーネント’Windows’への参照は、プロジェクトに既に存在します。」といったエラーメッセージが表示されることがありますが、無視してしまっても大丈夫なようです。
また、アセンブリ参照が正しく追加されたはずのなのにソリューションエクスプローラを見るとSystem.Runtimeに警告マークが表示されていることがあります。
その時は、再度アセンブリ参照の追加を行うと消えるようです。
ここまででWinRT(Windows Runtime)のAPIを使用できる状態になりました。
あとは下記のソースをモジュールとして追加するなどすれば心拍数データが取得できるようになります。
※注意
PULSENSEからデータ取得ができるか否かを探るのが目的なため、heart rate measurementで定められたデータの解釈を端折っています。この点、ご注意ください。
' This software is distributed under the license of NYSL. ' ( http://www.kmonos.net/nysl/ ) Imports System Imports System.Threading.Tasks Imports Windows.Foundation Imports Windows.Devices.Enumeration Imports Windows.Devices.Bluetooth '''''' PULSENSE(PS-100)から心拍データを取得する ''' Module Module1 Sub Main() HeartRateMonitor() End Sub '''''' PULSENSE(PS-100)の検索から心拍データを取得する準備まで ''' Private Sub HeartRateMonitor() ' Heart Rateのデバイスを検索 Dim devices As DeviceInformationCollection = System.WindowsRuntimeSystemExtensions.AsTask( DeviceInformation.FindAllAsync( GenericAttributeProfile.GattDeviceService.GetDeviceSelectorFromUuid( GenericAttributeProfile.GattServiceUuids.HeartRate))).GetAwaiter().GetResult() ' デバイスが見つからない場合は終了 If devices.Count = 0 Then Console.WriteLine("デバイスなし") Exit Sub End If ' 見つかった最初のデバイスを使用 Dim device = devices(0) ' サービスのインスタンス取得 Dim service As GenericAttributeProfile.GattDeviceService = System.WindowsRuntimeSystemExtensions.AsTask( GenericAttributeProfile.GattDeviceService.FromIdAsync(device.Id)).GetAwaiter().GetResult() ' キャラクタリスティックでHeart Rate Measurementのインスタンスを取得 Dim characteristic As GenericAttributeProfile.GattCharacteristic = service.GetCharacteristics(GenericAttributeProfile.GattCharacteristicUuids.HeartRateMeasurement)(0) ' キャラクタリスティックに対しイベントハンドラ設定 AddHandler characteristic.ValueChanged, AddressOf GattValueChanged ' デバイスに対して通知設定を書き込む System.WindowsRuntimeSystemExtensions.AsTask( characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GenericAttributeProfile.GattClientCharacteristicConfigurationDescriptorValue.Notify)) ' 終了するまでループ While True System.Threading.Thread.Sleep(500) End While End Sub '''''' PULSENSE(PS-100)から取得した心拍データ表示 ''' ''' ''' Private Sub GattValueChanged(sender As GenericAttributeProfile.GattCharacteristic, e As GenericAttributeProfile.GattValueChangedEventArgs) ' デバイスから取得したデータをバイトの配列に展開 Dim bytes() As Byte bytes = New Byte(e.CharacteristicValue.Length - 1) {} Windows.Storage.Streams.DataReader.FromBuffer(e.CharacteristicValue).ReadBytes(bytes) ' 2番目の要素を表示 ' (PS-100では2番目の要素で値が取得できてしまうので正規の処理を端折る) Console.WriteLine(e.Timestamp.ToString & vbTab & bytes(1)) End Sub End Module
C#を使った場合、async/awaitまわりがスマートに記述できると思います。
MSDNなどで用いられているサンプルコードもほとんどC#での記述だったので、今回はVB .NETで書いてみました(^-^;
当初はJavaで実装できないか調査を行ってみたのですが、JavaでBluetoothを扱うための仕様(JSR-82)はBLEに対応していませんでした。
Intelが公開しているTinyBをJNI経由でアクセスできるようラップしたライブラリを使えば、JavaからBLEを扱うこともできそうなのですが、下位層で使用しているBlueZがLinux(とAndroid)にしか対応していないため、Javaでの実装を諦めました。
Please give us your valuable comment