【Raspberry Pi】温湿度を取得するクライアントアプリの作成方法

前回で温湿度サーバーは完成したので、今回はクライアントサイドのアプリを作成します。

使用する言語はSwiftにしてiOS用のアプリを作成しました。温湿度サーバーが用意してあれば実際にiPhoneにインストールしても動作します。

ちなみに下記順で見ると、BME280の回路接続方法、温湿度サーバーの作成方法やクライアントアプリの作成方法といった、一通りのことがわかりますので、時間があれば最初からどうぞ。

目次

温湿度取得のクライアントアプリ

今回作成したクライアントアプリで重要な部分は下記2つなります。

クライアントアプリで重要な部分
  • Network Framework(ネットワークフレームワーク)
    サーバーにアクセスするため使用。簡単にTCP通信などを確立できる。
  • Timer(タイマー)
    定期的にサーバーアクセスするために使用。

コード全部を解説すると冗長になるため、この2つの使い方を重点的に解説を行います。(というよりこの2つ以外はswiftの基本的な部分なので、それはまた別の機会に)

ちなみに作成したコードは下記のリポジトリに格納しています。

このリポジトリ内の"example/client/iOS/TempHum"が作成したXcodeプロジェクトなので、ダウンロードして使ってみると分かりやすいかもしれません。

アプリの動作

コードの解説の前にとりあえず今回作成したものがどんな感じに動くか紹介します。動画はシミュレータで動かしていますが、実機で動くことも確認しました。

5秒ごとにサーバーにアクセスして、温湿度、気圧情報を取得しています。見た目はシンプルですが、デザインは後々どうにでもなるので、とりあえず動くものを。

では、今回のコードの主要機能2つの内容と使い方を紹介します。

Network Framework(ネットワークフレームワーク)

Swiftを使ってTCP通信をする方法が結構たくさんあるんですが、今回はわかりやすいNetwork Frameworkを使いました。

Network Frameword 使用したAPI一覧

今回使用したNetwork FrameworkのAPIはこちらになります。

Network FrameworkはNWConnectionというクラスを通して使うので、NWConnectionにあるメソッドを使ってTCP通信を行います。

NWConnection.init()

NWConnectionの初期化処理

引数

host:IPアドレス
port:ポート番号
using:プロトコル(TCPやUDPなど)

戻り値

NWConnection:NWConnectionのインスタンス

処理内容

引数のIPアドレス、ポート番号、プロトコルを使って、NWConnectionにインスタンス生成を行います。以後のAPIはこのインスタンスを通して呼び出します。

NWConnection.start()

コネクションを開始

引数

queue:接続イベントを伝えるためのキュー

戻り値

なし

処理内容

init()で設定した情報にしたがって、コネクションを開始します。

NWConnection.send()

コネクション先にデータ送信

引数

content:送信データ
completion:送信完了時のクロージャ

戻り値

なし

処理内容

引数のデータを送信開始します。
送信が完了したら、completionに設定したクロージャが処理されます。

NWConnection.receive()

コネクション先からデータ受信

引数

minimumIncompleteLength:最小受信長
maximumLength:最大受信長
completion:受信完了時のクロージャ

戻り値

なし

処理内容

コネクション先からのデータを受信開始します。
受信が完了したら、completionに設定したクロージャが処理されます。

NWConnection.cancel()

コネクションを切断

引数

なし

戻り値

なし

処理内容

コネクションを切断します。

Network Framework APIの使い方

基本的な流れは下記の通りとなります。サンプルコードもこの順に呼び出しています。

基本的な流れ
  1. init()を呼び出してインスタンス生成
  2. start()を呼び出してコネクション確立
  3. send()/receive()を呼び出してコネクション先と通信
  4. cancel()を呼び出してコネクション切断

たったこれだけで簡単に通信することができます。

なお、start()やsend()/receive()は非同期のメソッドになります。そのため、順次実行したいのであればサンプルコードのようにセマフォを使って同期処理にしましょう。(早くasync/await来ないかな)

Timer(タイマー)

アプリ側から定期的に温湿度サーバーへアクセスするために、Timerを使います。この機能も簡単に使えます。

Timer 使用したAPI一覧

Timer.scheduledTimer()

Timerの初期設定および起動

引数

timeInterval:起動間隔
target:selectorを持っているオブジェクト
selector:実行するメソッド
userInfo:メソッドに渡す情報
repeats:繰り返し実行するかどうか

戻り値

Timer:Timerのインスタンス

処理内容

引数の情報を使ってインスタンスを生成。また、同時にタイマーを起動します。

Timer.fire()

初期設定したメソッドを呼び出す

引数

なし

戻り値

なし

処理内容

インスタンス生成時にセットしたメソッドを即時呼び出します。

Timer 使い方

こちらはコードを実際に見てみましょう。

    init(host: String, port: String) {
        let addr = ["host":host, "port":port]
        addTimer =  Timer.scheduledTimer(timeInterval:5.0,
                                         target:self,
                                         selector:#selector(interval_get),
                                         userInfo:addr,
                                         repeats:true)
        addTimer.fire()
    }

このように"timeInterval"に"5.0"をセット、"selector"に"interval_get"をセットすると、5秒毎に"interval_get()"という関数が呼び出されるようになります。めちゃくちゃ簡単。

また、起動直後に一度すぐに取得して欲しいので、"fire()"を使うことで"interval_get()"をすぐに呼び出すようにしています。(これを呼ばないと5秒後に初回の取得が始まる)

まとめ

以上でサーバーの作成とクライアントの作成が一通り完成しました。まだまだ荒削りな部分がたくさんありますが、一応実用的なものになりましたね。

荒削りな部分としては、netcatで動作確認するためにデータが文字列になっていたり、クライアントアプリのデザインがしょぼかったり、IPアドレスがコード内で直書きしていたり、エラー処理がしょぼかったり…まだまだある…。まあ、いろいろありますが、勉強用としては十分でしょう!

次は何を作ろうかな〜。ミニ四駆の速度制御とか面白そう。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次