What's JINS MEME
こちらをご参考ください。
http://qiita.com/mito_log/items/020a87996ed2b9d793e6
Motivation
JINS MEMEを使って何か作るにもデータの傾向を見たり分析してからでないとなぁ。ということでxx秒ごとにgoogle spread sheetに投げてデータを見てみます。今回も前回に引き続きRxSwiftで頑張っております。
github
Spreadsheet
Screenshots
How it works
ios側では、データを一旦配列に貯めておいて、一定時間毎にcsvでデータをpostで送信しています。
google spreadsheet側では、google app scriptのContent Serviceという機能を使い、簡単なRestfulAPI(POSTのみ)を用意しています。そこで、csvをパースして、シートに転記しています。
google apps scriptを使ったAPIについては、過去に書いた記事を見つつ作れるかと思います。注意すべきは、
- スプレッドシート名を固有のものにすること
- アプリの実行権限を得ること
- ウェブアプリケーションとして導入のオプション
くらいかと思います。
Recap
Too much memory use while data retrieval and sending
今回もRxSwiftを使ってみたのですが、dispose関連のタイミングやら手法がまだカバーできていないせいか、データ取得時に大量にメモリを食ってしまっています。一応leaksでみてみるとリークは無いとの判定でしたが、工夫したいところです。
takeUntil
今回、スタート/ストップボタンを押すと、「データの取得開始、タイマーの起動」をしています。つまり、
スタート:subscribeの開始
ストップ: dispose
としたかったのですが、disposeをどうやるべきか...紆余曲折を経てtakeUntilを使う手法にたどり着きました。
画像: RxSwiftのPlaygroundより
一番上をrealtimeDataを取得するシーケンス(MEMELibAccess.sharedInstance.rx_realtimeDataReceived
)、そのすぐ下を、データストップシーケンス(stopSequence
)とすると、stopSequenceに何かしら次のアイテムをセットした時点で一番上のシーケンスは完了扱いとなり、disposeされます。
コード上でいくと、
MEMELibAccess.sharedInstance.rx_realtimeDataReceived
.takeUntil(self.stopSequence)
.subscribeNext { [unowned self] realtimeData in
というふうにせっとしておいて、その後に、stopSequence.on(.Next(true))
とかしてあげればOKです。
詳しくは、GettingStartedのDisposingの箇所を見るといいかと思います。
bi-directional binding
RxSwiftで双方向データバインディングをみながらやってみました。
とても柔軟だなとおもったのは、例えばモデルがdoubleでビューがstringでもバインドできます。
self.intervalTextField.rx_text.subscribeNext { [unowned self] intervalStr in
if intervalStr.utf16.count > 0 {
self.vm.interval.value = atof(intervalStr)
}
}.addDisposableTo(self.disposeBag)
self.vm.interval
.subscribeOn(MainScheduler.sharedInstance)
.map { interval in
return String(interval)
}
.bindTo(self.intervalTextField.rx_text)
.addDisposableTo(self.disposeBag)
mapを噛ませて、stringを返すようにすればバインドできました。
Scheduler
今回のように通信が絡んだりタイマーが絡むと、UIスレッドを意識しないといけません。RxSwiftでもスケジューラーという概念でスレッドを管理できるようになっているので、スケジューラーは要チェックです。
1点気になったのが、ドキュメントでは、.subscribeOn(MainScheduler.sharedInstance)
すればメインスレッドでsubscribeできるよみたいに書いてあったのですが、一部効かない場所があったので、dispatch_async(dispatch_get_main_queue()) {}
で対応しました。
20Hz
いきなりJINS MEMEのことになりますが(ていうかほぼRxSwiftの勉強になっていますね...)、JINS MEMEのrealtimeモードでは、通信速度がBluetooth通信周期にのっとって約20Hzとなっています。
参照: https://developers.jins.com/ja/
ということは、1秒間に約20サンプルのデータがiPhoneには送られていることになり、10秒だと約200のサンプルになります。
google spreadsheetの最大セル数は、200万セルということなので、逆算すると、
2000000セル / 16(1行分のセル数) / 20サンプル = 6250秒(約104分)
は貯められることになりますが、用途としては、突発的な動作や短いスパンでの変化を分析したいときに使えるかなと思いました。
ということで、引き続きデータを見ながらどんなことができそうかを探っていきます。