前回で温湿度サーバーは完成したので、今回はクライアントサイドのアプリを作成します。
使用する言語はSwiftにしてiOS用のアプリを作成しました。温湿度サーバーが用意してあれば実際にiPhoneにインストールしても動作します。
ちなみに下記順で見ると、BME280の回路接続方法、温湿度サーバーの作成方法やクライアントアプリの作成方法といった、一通りのことがわかりますので、時間があれば最初からどうぞ。
- 【第1回】Raspberry Piで温湿度センサー(BME280)を動かしてみよう
- 【第2回】プログラムで温湿度センサー(BME280)を操作してみよう!C言語編
- 【第3回】温湿度を計測するサーバーの作成
- 【第4回】温湿度サーバーを複数接続に対応する方法
- 【第5回】温湿度を取得するクライアントアプリの作成(iOS版)← 今ココ
温湿度取得のクライアントアプリ
今回作成したクライアントアプリで重要な部分は下記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の使い方
基本的な流れは下記の通りとなります。サンプルコードもこの順に呼び出しています。
- init()を呼び出してインスタンス生成
- start()を呼び出してコネクション確立
- send()/receive()を呼び出してコネクション先と通信
- 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アドレスがコード内で直書きしていたり、エラー処理がしょぼかったり…まだまだある…。まあ、いろいろありますが、勉強用としては十分でしょう!
次は何を作ろうかな〜。ミニ四駆の速度制御とか面白そう。
コメント