2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【IoT】ESP8266で温湿度取得してスマホでモニタリング 第2回

Last updated at Posted at 2017-09-14

#はじめに
【IoT】ESP8266で温湿度取得してスマホでモニタリング 第1回に引き続き、第2回はAndroidアプリ側を制作したので投稿します。
グラフはネットで調べたところ、MPAndroidChartが広く使われている(?)ようだったので使ってみました。

#Xamarin.Android
開発環境は、前回に引き続きVisual Studio Community 2017を使っています。
Xamarin.Androidインストール手順
公式サンプルソース

#MPAndroidChartライブラリ
Xamarinで使えるMPAndroidChartはこちらからソースをダウンロードできます。
ダウンロードはここからgithub
ダウンロード後、ソースをビルドすると各種DLLが生成させるようです。
(私の環境では普通にビルド通りましたけどどうなんでしょうか)
今回は、\packages\MPAndroidChart.3.0.0\lib\MPAndroidChart.dllを使いました。
Xamarin版のサンプルソースがJava版と比較して圧倒的に少ないのが難点ですね。

#MQTTライブラリ
MQTTはC#で使えるライブラリを適当にチョイスしました。
ダウンロードはここからgithub
ダウンロード後、M2Mqtt.dllを使いました。
すぐ使えるアプリケーションもセットになっているので、使い易いかと思います。

#作製したアプリの各画面
##メイン画面
Screenshot_20170914-230707_compressed.jpg

##設定画面
Screenshot_20170914-230630_compressed.jpg Screenshot_20170914-230641_compressed.jpg Screenshot_20170914-230656_compressed.jpg

#開発で行き詰った事
##NumberPickerはマイナスが表示できない問題
温度・湿度のスケールを設定するダイアログで、当初はNumberPickerで作っていたましたが、いざ作ってみるとマイナスが表示されないことに気づきました。仕方ないので、普通にListViewで選択する方向で作ってみましたが、なんかダサいですね。
後々調べてみると、NumberPickerをカスタムして使う投稿もあったみたいですね。
NumberPickerをカスタムして使う

##ポップアップをクローズしたときに親画面に値を返せない問題
AlertDialogクラスにはクローズ時のイベントOnDismissが用意されていますが、さすがに親に値を返すイベントまではないようです。
仕方ないので、クローズしたときに呼び出されるコールバック関数を用意しました。

ListDialogFragment.cs
    public class DialogEventArgs : EventArgs
    {
        public string ReturnValue { get; set; }
    }

    /// <summary>
    /// リストダイアログ表示クラス
    /// </summary>
    public class ListDialogFragment : DialogFragment
    {
        public event EventHandler<DialogEventArgs> DialogClosed;
        public delegate void DialogEventHandloer(object sender, DialogEventArgs e);

        //処理内容省略...

        /// <summary>
        /// ダイアログクローズ時のイベント
        /// </summary>
        /// <param name="dialog"></param>
        public override void OnDismiss(IDialogInterface dialog)
        {
            base.OnDismiss(dialog);

            // 呼び出した親に値を返す
            if (DialogClosed != null)
            {
                DialogClosed(this, new DialogEventArgs { ReturnValue = _selectedValue });
            }
        }
    }

ダイアログを呼び出す親画面でDialogClosedにコールバック関数を設定してあげると、ダイアログをクローズしたときにコールバック関数が呼び出されます。尚、値はDialogEventArgs eのReturnValueプロパティにセットされています。

SettingActivity.cs
        protected override void OnCreate(Bundle savedInstanceState)
        {
            //処理内容省略...

            // 室温最小値ボタンのクリックイベント
            btnTempMin.Click += (_, __) =>
            {
                dialogKey = TempMinKey;
                // ダイアログ表示
                ListDialogFragment dlg = new ListDialogFragment(
                                                this,
                                                "室温(最小)を選択してください",
                                                Resource.Array.TempAxisItems,
                                                Resource.Array.TempAxisValues);
                dlg.DialogClosed += OnDialogClosed;     // 選択時のコールバック関数
                dlg.Show(this.FragmentManager, typeof(ListDialogFragment).Name);
            };
            //処理内容省略...
        }

        /// <summary>
        /// ダイヤログ選択時のコールバック関数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void OnDialogClosed(object sender, DialogEventArgs e)
        {
            //処理内容省略...
        }

##MPAndroidChartのX軸のラベルをカスタムする方法
MPAndroidChartのX軸のラベルはデフォルトでは、0,1,2…のようにインデックスで表示されます。
カスタムラベルする方法は、Javaでは結構サンプルソースがあるのですが、Xamarin.Androidでは中々見つからないので苦労しました。
結局のところ、IAxisValueFormatterを継承したクラスを作らないといけないようです。
以下のソースでは、IAxisValueFormatterを継承したXLabelFormatterクラスを用意し、GetFormattedValueでラベルを作成します。
”if (int.TryParse(value.ToString("0.#"), out val) == true)”をしているのは、整数チェックをしています。というのは、引数のfloat valueには少数で値が入ってくることがあるようです。(なぜかは不明)
また、”if (labelList.Count > val && val >= 0)”は、グラフに表示するデータ件数が0件でもグラフの枠だけ表示し、ラベルは何も表示したくないので、このような処理を入れています。
XLabelFormatterでは、addLabelでX軸に表示したいラベルをlabelListにaddし、GetFormattedValueでX軸のインデックスに対応したラベルをlabelListから取得しています。

MainActivity.cs
    public class MainActivity : Activity
    {
        //処理内容省略...
        XLabelFormatter xformatter = new XLabelFormatter();
        private void setData(string xlabel, string temp, string humi)
        {
            // X軸の設定
            XAxis xAxis = mChart.XAxis;
            xAxis.SetLabelCount(tempDataset.EntryCount, true);
            xformatter.addLabel(xlabel);
            xAxis.ValueFormatter = xformatter;
            //処理内容省略...
        }

        //処理内容省略...
    }

    public class XLabelFormatter : Java.Lang.Object, IAxisValueFormatter
    {
        private static List<string> labelList = new List<string>();

        public int DecimalDigits => 0;

        public void addLabel(string item)
        {
            labelList.Add(item);
        }

        public string GetFormattedValue(float value, AxisBase axis)
        {
            int val = 0;
            string ret = "";
            if (int.TryParse(value.ToString("0.#"), out val) == true)
                if (labelList.Count > val && val >= 0)
                    ret = labelList[val];
            return ret;
        }
    }

#おわりに
今回はArduinoもXamarinもAndroidも初めてづくしで調べなたら開発したので、かなり時間かかってしまった印象です。
Arduinoではセンサー系を試してみたので、次はモータ系を試してみたいですね。
構想としては、Arduino+ROS+ドローン+PS4コントローラとかやってみたいなぁ・・・
と考えているので、進捗が出ましたらまた投稿したいと思います。

#関連記事
【IoT】ESP8266で温湿度取得してスマホでモニタリング 第1回

#ソース
準備中...少々お待ちください。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?