iPod touchとサーバ(hubot)間の通信をsocket.ioで行うように実装しました。これにより、直接双方向でボットとiPhoneアプリ間でメッセージのやり取りができるようになります。
まずhubotはボットがメッセージに応答したり、自律的に何らかのアクションを実行するためのプログラム(hubot scripts)と、チャット等の外部サービス間とデータをやり取りするためのプログラム(hubot adapters)が必要です。今回はこのアダプター部分を実装してみました。下記がそのソースです。割とシンプルに書けますね。ちなみに、コメント中のMBEDというのは、iPhoneアプリのことを指しています(前回を参照)。このアプリとのメッセージのやり取りを、Socket.ioを使って行っています。やり取りするデータは適当です。
{Robot, Adapter, TextMessage, Response} = require 'hubot'
{EventEmitter} = require 'events'
class MbedAdapter extends Adapter
run: ->
options = {}
bot = new MbedStreaming options, @robot
bot.on 'message', (userId, userData, message) =>
user = @robot.brain.userForId userId, userData
@receive new TextMessage user, message
# ここでサービスに接続し、継続的にメッセージを待ち受けるハンドラを作成
bot.listen()
@bot = bot
@emit 'connected'
send: (envelope, strings...) =>
@bot.send str for str in strings
reply: (envelope, strings...) ->
exports.use = (robot) ->
new MbedAdapter robot
class MbedStreaming extends EventEmitter
constructor: (options, @robot) ->
send: (message) ->
# ここでMBEDにメッセージを送信する
@io?.sockets.emit 'message', message
listen: ->
self = @
http = require 'http'
io = require 'socket.io'
htserver = http.createServer (req,res) ->
res.write 'Test'
res.end()
io = io.listen htserver
htserver.listen 7799
io.sockets.on 'connection', (socket) ->
#接続された時の処理
socket.on 'message', (data) ->
# MBEDからのメッセージを取得する
# data = JSON.parse data
usr_id = data.uid
usr_data =
name:data.uname
room:data.room
self.emit 'message', 100, usr_data, data.text
@io = io
今回初めてCoffeeScriptでコードを書いたのですが、確かにコードが書きやすくなりました。あと、ベースはJavascriptなので、特に新しい概念を覚える必要がなくて学習コストも少なそうです。ちょっとだけハマったのはインデントですかね。基本、スペースだけでインデントしてますが、たまにタブが混じったりするとエラーになって、何が原因かわからなくなることがありました(見た目は全く問題ないわけですから)。
次はiPhoneアプリの方です。Socket.ioでデータをやり取りするため、Socket.IO-Client-Swiftというライブラリを使いました。ユーザーIDとかは適当です。
import UIKit
import SocketIOClientSwift
class ViewController: UIViewController {
let SocketURL = NSURL(string:"http://192.168.1.7:7799")
var socket: SocketIOClient!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
socket = SocketIOClient(socketURL: SocketURL!, options:[.Log(true), .ForcePolling(true)])
socket.on("connect") { data, ack in
print("socket connected!!")
let msg : Dictionary<String, String> = [ "uid":"123", "uname":"nanasi", "room":"myhouse", "text":"mbedbot HELLO"]
self.socket.emit("message", msg)
}
socket.on("disconnect") { data, ack in
print("socket disconnected!!")
}
socket.on("message") { data, emitter in
if let message = data as? [String] {
print(message[0])
}
}
socket.connect()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}