2017年3月8日水曜日

SwiftWebSocket で MODE に WebSocket 接続してみる

概要

前回 Nodejs で MODE に WebSocket 接続をしました
今回は言語とプラットフォーム変更して再挑戦してみました

環境

  • Mac OS X 10.10.5
  • Xcode 7.2.1 (Swift 2.1.1)
  • SwiftWebSocket 2.5.0

いきなりポイントですが、Xcode 7.2 系の場合 SwiftWebSocket は 2.5.0 を使う必要があります
7.3 系の場合は 2.6.0 以上を使って問題ないと思いますがそれ以下だと以下のエラーが発生します
https://github.com/tidwall/SwiftWebSocket/issues/28

SwiftWebSocket のインストール

Cocoapods を使ってインストールします

pod 'SwiftWebSocket', '2.5.0'

を追加して pod install すれば OK です
冒頭でも説明しましたが、今回使用するバージョンは 2.5.0 固定にします

WebScoket クライアントのコーディング

MODE に接続するための WebSocket クライアントを作成します
前回同様サーバ側は MODE になるので、クライアントを実装します

Xcode の場合すべてのコードを掲載するのが厳しいの一部のポイントだけ説明します

まずは MODE に WebSocket 接続するメインとなる関数を生成します

func receiveCommand(){
    var deviceId = "000"
    var deviceAPIKey = "ModeCloud v1.xxxxxxxxxx==.xxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    var messageNum = 0
    let request = NSMutableURLRequest(URL: NSURL(string:"wss://api.tinkermode.com:443/devices/" + deviceId + "/command")!)
    request.addValue(deviceAPIKey, forHTTPHeaderField: "Authorization")
    let ws = WebSocket(request: request)
    let send : ()->() = {
        let msg = "\(++messageNum): \(NSDate().description)"
        print("send: \(msg)")
        ws.send(msg)
    }
    ws.event.open = {
        print("opened")
        send()
    }
    ws.event.close = { code, reason, clean in
        print("close")
    }
    ws.event.error = { error in
        print("error \(error)")
    }
    ws.event.message = { message in
        if let text = message as? String {
            print("recv: \(text)")
            if messageNum == 10 {
                ws.close()
            } else {
                send()
            }
        }
    }
}

deviceIddeviceAPIKey は前回同様 MODE のデバイス一覧から接続したいデバイスを選択してコピペしてください

基本は接続するためのオブジェクトを作成して、それぞれのイベントが発生したときのイベントハンドラを登録するだけです
接続時に deviceAPIKey を使った認証ヘッダ必要なので request.addValue でヘッダを追加しています

  • ws.event.open ・・・ MODE と接続できたときにコールされます
  • ws.event.close ・・・ MODE との接続が切断された場合にコールされます
  • ws.event.message ・・・ MODE からコマンドを受信したときにコールされます
  • ws.event.error ・・・ 何かしらのエラーが発生したときにコールされます

で、あとはこの receiveCommand をコールするだけです
例えば viewDidLoad で呼び出す場合は以下のような感じです

import SwiftWebSocket

class MainViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        receiveCommand()       
    }

}

これで実行するとアプリが起動した直後に MODE に接続しにいきます

ちゃんと接続されたかどうか確認する方法は MODE のデバイス一覧でステータスが「Connected」になっているか確認するか、Xcode のデバッグエリアに ws.event.open 時に出力されるべきログが出力されていることを確認してください

最後に

紹介は以上です
これで前回と含めて

  • サーバ -> Nodejs -> MODE
  • iPhone -> Swift -> MODE

それぞれで Websocket で MODE に接続することができました

今回の場合はアプリがバックグラウンドになっても MODE のステータスは Connected のままでしたが、その状態でコマンドを送信しても実際にコマンドを受信するのはアプリがフォアグランドに戻ったときでした
その点注意してください

あと全然関係ないですが、SwiftWebSocket を使う前に StarScream という別の Swift 製のライブラリを使っていました
理由は全くわからないのですが、これだと上手く接続できませんでした
たぶん自分の使い方が悪かっただけですが、念のためメモしておきます
wss に対応してないのかなと重い ws とかも試してみたのですがダメでした

参考サイト

0 件のコメント:

コメントを投稿