SwiftでJINS MEMEアプリ開発

# JINS MEME

https://jins-meme.com/ja/

![JINS MEME](https://meme-consumer-static.jins-meme.com/img/eyewear-apps/eyewear_img01.jpg?version=201510261130)

いわゆるライフログ系のウェアラブルデバイスをメガネにしたもの。リストバンドタイプのものが多いよね。
メガネなので、加速度や傾きを頭部で測れるという面白さがある。
あと眼電位を測れて、眼の動きやまばたきを検出できる（ESモデルのみ）。

2015/11/05に発売。発売時からiOS用SDKが配布されており、計測データを使ったアプリ開発が可能。
Android向けSDKも年明けに出るとか。

# 概要

というわけで、早速iOSアプリ作るよ。

## 環境

- Xcode 7.1 (El Capitan)
- iPhone 6
- iOS 9.1
- JINS MEME ES
- JINS MEME SDK 1.0.5

# 手順

## Project作成

ウィザードに従って、こんな感じで。

- Single View Application
- Language: Swift
- Devices: iPhone

## SDK導入

https://developers.jins.com/ja/sdks/ios/

上記ページからSDKをダウンロード

開発用とApple申請用の2種類のフレームワークがあるので、開発用を使う。
`framework/universal/MEMELib.framework` を、作成したプロジェクトのディレクトリにコピー。
更に、コピーした上記ファイル（実体はディレクトリ）を、Xcodeの `Embedded Binaries` にドラッグ＆ドロップ。

<img width="1418" alt="スクリーンショット 2015-11-08 22.02.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/51567/22d82a95-24cd-c7f1-ac56-61c2c16b2894.png">

## Bluetooth権限設定

Capabilities > Background ModesをONにし、 `Use Bluetooth LE accessory` にチェック。

<img width="1418" alt="スクリーンショット 2015-11-08 21.19.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/51567/e551c81d-f1f7-05aa-0ef0-9b44ec9b0336.png">

## Bridging Headerファイル作成

プロジェクトに新規headerファイルを作成し、以下のimport文を記述。

```objc
#import <MEMELib/MEMELib.h>
```

さらに、Build Settings > Swift Compiler - Code Generationに、Bridging Headerファイルパスを指定。

<img width="1418" alt="スクリーンショット 2015-11-08 21.24.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/51567/7e28f761-702e-ca7f-077b-e21cd4b2a7f7.png">

## アプリケーション認証コード発行

https://developers.jins.com/ja/apps/create/

上記ページからアプリケーション登録する。
登録すると、アプリ一覧ページに表示される。

https://developers.jins.com/ja/apps/

「詳細・編集」ボタンを押すと、アプリケーション認証コードを確認できる。

## コード記述

### アプリケーション認証

`AppDelegate.swift` に以下を記述。

```swift:AppDelegate.swift
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    MEMELib.setAppClientId("<発行されたアプリID>", clientSecret: "<発行されたアプリSecret>")
    return true
}
```

以後、 `MEMELib.sharedInstance()` に対して各種処理をコールしていくが、1回目の `sharedInstance()` 取得の前にこのアプリ認証情報設定が必要。

### JINS MEMEに接続して、データを取得

ここでは、エラー処理とか、あらゆるパターンを考慮したライフサイクル管理とか一切省略。動かすことに専念する。

`ViewController.swift` を以下のような感じに。

```swift:ViewController.swift
import UIKit

class ViewController: UIViewController, MEMELibDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        MEMELib.sharedInstance().delegate = self
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    func memeAppAuthorized(status: MEMEStatus) {
        MEMELib.sharedInstance().startScanningPeripherals()
    }
    
    func memePeripheralFound(peripheral: CBPeripheral!, withDeviceAddress address: String!) {
        MEMELib.sharedInstance().connectPeripheral(peripheral)
    }
    
    func memePeripheralConnected(peripheral: CBPeripheral!) {
        let status = MEMELib.sharedInstance().startDataReport()
        print(status)
    }
    
    func memeRealTimeModeDataReceived(data: MEMERealTimeData!) {
        print(data.description)
    }
}
```

- `MEMELibDelegate` をimplement
- `MEMELib` インスタンスの `delegate` プロパティに自身を代入し、各種イベントが通知されるように
- 1回目の `sharedInstance()` コール時にアプリ認証が走り、成功したら `memeAppAuthorized` が呼ばれる
    - `startScanningPeripherals()` をコールし、BT接続済みのJINS MEMEを探す
    - このコードは一応、事前に公式アプリでBT接続しておく前提
- JINS MEMEが見つかったら `memePeripheralFound` が呼ばれる
    - `connectPeripheral(peripheral)` をコールし、アプリ - JINS MEME間接続を試みる
- アプリとJINS MEMEが接続されたら、 `memePeripheralConnected` が呼ばれる
    - `startDataReport()` をコールすると、定期的にデータが取得され・・・るはず
    - なんだけど、 **データ取得開始しませんｗ**
    - このコードみたく、 `startDataReport()` の戻りをチェックすると、確かに失敗コードが返る
    - あと、以下の様なエラーが出る

```
JinsQiita[5749:2461884] MEME Model Type Check: error = [(null)], errorDescription = [(null)]
```

`startDataReport()` がもし成功していたら、データが `memeRealTimeModeDataReceived` に流れてくるはず。


# というわけで、動かない

フォーラム見てみたら、同じエラー出てる人いた。

https://developers.jins.com/ja/forums/sdk/topic/8519/

ので、ちょいと様子見。
動いた人いたら教えてくださいｍｍ


# 2015-11-09 追記

動いた！

フォーラムから引用

> JINSMEMEからのデータ送信中は、
> データモードの変更を許可しない仕様としております。
> 弊社Officialアプリは、スタンダードモードを利用しており、
> このモードでデータ送信中の場合に当現象が発生致します。
> 弊社Officialアプリを起動しない状態にて、
> JINSMEMEに接続し、ご利用いただけますでしょうか。

公式アプリは「スタンダードモード」で動いてるが、独自アプリは「リアルタイムモード」になる。
で、両モードを同時には動かせないということらしい。

うまく公式アプリ側を止めてやるとちゃんと動くとのことだが、この記事のコードだと1つ問題がある。

- `startScanningPeripherals()` を実行するときには、公式アプリで繋がっていないといけない。

本記事のコードは `startScanningPeripherals()` から `startDataReport()` までノンストップで実行するようになっているので、その間に公式アプリを止めるタイミングがないということになる。

`connectPeripheral()` のコールは無条件で走らせずに、タップなどのユーザイベントをフックする形にすれば回避できるが、今のコードのままで動作させる手順もあったので、記載しておく。

1. 公式アプリ側の設定画面で一度JINS MEMEを切断
2. 設定画面で再接続
3. その後、公式アプリは、ホームやライブビューに遷移せず、そのまま閉じる
4. 自作アプリを起動

この手順だと、公式アプリの「スタンダードモード」が起動しないのだと思われる。