今回は Xamarin.Forms で肌温度値を取得してみます
ソースコードの一式は下記にあります!
細かい実装などはこちらを参照ください
※ 順次改修していく予定なので、この記事の内容が現時点のソースより古い可能性があります
いつものようにまずはデータのいれものを作ります
/// <summary> /// iOS 用肌温度センサーデータ /// </summary> public class NativeBandSkinTemperatureReading : IBandSkinTemperatureReading { /// <summary> /// コンストラクタ /// </summary> /// <param name="data">センサーデータ</param> public NativeBandSkinTemperatureReading(Native.Sensors.BandSensorSkinTemperatureData data) { this.Timestamp = DateTime.Now; this.Temperature = data.Temperature; } /// <summary> /// 検出日時 /// </summary> public DateTimeOffset Timestamp { get; private set; } /// <summary> /// 肌温度 /// </summary> public double Temperature { get; private set; } }
iOS と Android でほぼ同じでかんたんなつくりです
次にセンサー制御クラス
/// <summary> /// iOS 用肌温度センサー /// </summary> public class NativeBandSkinTemperatureSensor : NativeBandSensorBase<IBandSkinTemperatureReading> { /// <summary> /// 肌温度センサー /// </summary> private Native.Sensors.SkinTemperatureSensor sensor = null; /// <summary> /// センサー値変更イベント /// </summary> public override event EventHandler<BandSensorReadingEventArgs<IBandSkinTemperatureReading>> ReadingChanged; /// <summary> /// コンストラクタ /// </summary> /// <param name="manager">Band センサー管理クラス</param> public NativeBandSkinTemperatureSensor(Native.Sensors.IBandSensorManager manager) : base(manager) { this.sensor = Native.Sensors.BandSensorManagerExtensions.CreateSkinTemperatureSensor(manager); this.sensor.ReadingChanged += this.OnReadingChanged; } /// <summary> /// センサー値変更イベントハンドラ /// </summary> /// <param name="sender">イベント発行者</param> /// <param name="e">イベント引数</param> private void OnReadingChanged(object sender, Native.Sensors.BandSensorDataEventArgs<Native.Sensors.BandSensorSkinTemperatureData> e) { if (this.ReadingChanged == null) { return; } this.ReadingChanged.Invoke( this, new BandSensorReadingEventArgs<IBandSkinTemperatureReading>(new NativeBandSkinTemperatureReading(e.SensorReading))); } /// <summary> /// センサー検知を開始する /// </summary> /// <returns>Task</returns> public override Task StartReadingsAsync() { return Task.Run(() => this.sensor.StartReadings()); } /// <summary> /// センサー検知を停止する /// </summary> /// <returns>Task</returns> public override Task StopReadingsAsync() { return Task.Run(() => this.sensor.StopReadings()); } }
こっちが iOS で
/// <summary> /// Android 用肌温度センサー /// </summary> public class NativeBandSkinTemperatureSensor : NativeBandSensorBase<IBandSkinTemperatureReading> { /// <summary> /// 肌温度センサー /// </summary> private Native.Sensors.SkinTemperatureSensor sensor = null; /// <summary> /// センサー値変更イベント /// </summary> public override event EventHandler<BandSensorReadingEventArgs<IBandSkinTemperatureReading>> ReadingChanged; /// <summary> /// コンストラクタ /// </summary> /// <param name="manager">Band センサー管理クラス</param> public NativeBandSkinTemperatureSensor(Native.Sensors.IBandSensorManager manager) : base(manager) { this.sensor = Native.Sensors.BandSensorManagerExtensions.CreateSkinTemperatureSensor(manager); this.sensor.ReadingChanged += this.OnReadingChanged; } /// <summary> /// センサー値変更イベントハンドラ /// </summary> /// <param name="sender">イベント発行者</param> /// <param name="e">イベント引数</param> private void OnReadingChanged(object sender, Native.Sensors.IBandSensorEventEventArgs<Native.Sensors.IBandSkinTemperatureEvent> e) { if (this.ReadingChanged == null) { return; } this.ReadingChanged.Invoke( this, new BandSensorReadingEventArgs<IBandSkinTemperatureReading>(new NativeBandSkinTemperatureReading(e.SensorReading))); } /// <summary> /// センサー検知を開始する /// </summary> /// <returns>Task</returns> public override Task StartReadingsAsync() { return this.sensor.StartReadingsTaskAsync(); } /// <summary> /// センサー検知を停止する /// </summary> /// <returns>Task</returns> public override Task StopReadingsAsync() { return this.sensor.StopReadingsTaskAsync(); } }
こっちが Android ・・・機械的に実装できます
ViewModel も改修
/// <summary> /// センサー情報 ViewModel /// </summary> public class SensorReadingViewModel : BindableBase { ~ 中略 ~ #region SkinTemperatureSensor /// <summary> /// 肌温度 /// </summary> private double skinTempature = 0; /// <summary> /// 肌温度 /// </summary> public double SkinTemperature { get { return this.skinTempature; } set { this.SetProperty<double>(ref this.skinTempature, value); } } #endregion //SkinTemperatureSensor ~ 中略 ~ /// <summary> /// センサー監視切替 /// </summary> /// <param name="detecting">センサー監視フラグ</param> /// <returns>Task</returns> private async Task ChangeDetectSensors(bool detecting) { if (detecting) { // 加速度センサーの検知開始 if (this.client.SensorManager.Accelerometer.IsSupported) { await this.client.SensorManager.Accelerometer.StartReadingsAsync(); this.client.SensorManager.Accelerometer.ReadingChanged += this.OnAccelerometerReadingChanged; } // ジャイロセンサーの検知開始 if (this.client.SensorManager.Gyroscope.IsSupported) { await this.client.SensorManager.Gyroscope.StartReadingsAsync(); this.client.SensorManager.Gyroscope.ReadingChanged += this.OnGyroscopeReadingChanged; } // 心拍数の検知開始 if (this.client.SensorManager.HeartRate.IsSupported) { await this.client.SensorManager.HeartRate.StartReadingsAsync(); this.client.SensorManager.HeartRate.ReadingChanged += this.OnHeartRateReadingChanged; } // 歩数の検知開始 if (this.client.SensorManager.Pedometer.IsSupported) { await this.client.SensorManager.Pedometer.StartReadingsAsync(); this.client.SensorManager.Pedometer.ReadingChanged += this.OnPedometerReadingChanged; } // 移動距離の検知開始 if (this.client.SensorManager.Distance.IsSupported) { await this.client.SensorManager.Distance.StartReadingsAsync(); this.client.SensorManager.Distance.ReadingChanged += this.OnDistanceReadingChanged; } // 肌温度の検知開始 if (this.client.SensorManager.SkinTemperature.IsSupported) { await this.client.SensorManager.SkinTemperature.StartReadingsAsync(); this.client.SensorManager.SkinTemperature.ReadingChanged += this.OnSkinTemperatureReadingChanged; } } else { // 加速度センサーの検知終了 if (this.client.SensorManager.Accelerometer.IsSupported) { await this.client.SensorManager.Accelerometer.StopReadingsAsync(); this.client.SensorManager.Accelerometer.ReadingChanged -= this.OnAccelerometerReadingChanged; this.AccelerationX = 0d; this.AccelerationY = 0d; this.AccelerationZ = 0d; } // ジャイロセンサーの検知終了 if (this.client.SensorManager.Gyroscope.IsSupported) { await this.client.SensorManager.Gyroscope.StopReadingsAsync(); this.client.SensorManager.Gyroscope.ReadingChanged -= this.OnGyroscopeReadingChanged; this.AngularVelocityX = 0d; this.AngularVelocityY = 0d; this.AngularVelocityZ = 0d; this.GyroAccelerationX = 0d; this.GyroAccelerationY = 0d; this.GyroAccelerationZ = 0d; } // 心拍数の検知終了 if (this.client.SensorManager.HeartRate.IsSupported) { await this.client.SensorManager.HeartRate.StopReadingsAsync(); this.client.SensorManager.HeartRate.ReadingChanged -= this.OnHeartRateReadingChanged; this.HeartRate = 0; this.HeartRateQuality = HeartRateQuality.Acquiring; } // 歩数の検知終了 if (this.client.SensorManager.Pedometer.IsSupported) { await this.client.SensorManager.Pedometer.StopReadingsAsync(); this.client.SensorManager.Pedometer.ReadingChanged -= this.OnPedometerReadingChanged; this.TotalSteps = 0L; } // 移動距離の検知終了 if (this.client.SensorManager.Distance.IsSupported) { await this.client.SensorManager.Distance.StopReadingsAsync(); this.client.SensorManager.Distance.ReadingChanged -= this.OnDistanceReadingChanged; this.CurrentMotion = MotionType.Unknown; this.Pace = 0d; this.Speed = 0d; this.TotalDistance = 0L; } // 肌温度の検知終了 if (this.client.SensorManager.SkinTemperature.IsSupported) { await this.client.SensorManager.SkinTemperature.StopReadingsAsync(); this.client.SensorManager.SkinTemperature.ReadingChanged -= this.OnSkinTemperatureReadingChanged; this.SkinTemperature = 0d; } } } ~ 中略 ~ /// <summary> /// 肌温度変更イベントハンドラ /// </summary> /// <param name="sender">イベント発行者</param> /// <param name="e">イベント引数</param> private void OnSkinTemperatureReadingChanged(object sender, BandSensorReadingEventArgs<IBandSkinTemperatureReading> e) { if (e == null) { return; } this.SkinTemperature = e.SensorReading.Temperature; } }
最後に XAML
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:cv="clr-namespace:XamarinBandSample.Converters;assembly=XamarinBandSample" xmlns:t="clr-namespace:XamarinBandSample.Triggers;assembly=XamarinBandSample" xmlns:prismmvvm="clr-namespace:Prism.Mvvm;assembly=XamarinBandSample" prismmvvm:ViewModelLocator.AutoWireViewModel="true" x:Class="XamarinBandSample.Views.TopPage"> ~ 中略 ~ <!-- Sensor Info Pain--> <ScrollView IsVisible="{Binding ShowSensors}" Orientation="Vertical"> <Grid Padding="10" RowSpacing="10" ColumnSpacing="10" BindingContext="{Binding SensorReading}"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="100"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> ~ 中略 ~ <StackLayout Orientation="Horizontal" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="6" Spacing="5"> <Label Text="Skin Temperature:" FontSize="Medium"/> <StackLayout Orientation="Vertical" Padding="10,0,0,0" Spacing="10"> <Label Text="{Binding SkinTemperature, StringFormat='temperature={0}'}" FontSize="Small"/> </StackLayout> </StackLayout> </Grid> </ScrollView> </Grid> </ContentPage>
表示領域を追加してお試し実行
肌温度は体温より少し低め?・・・一応取れているみたいですね