0

Jawbone Up24の(enter|exit)_sleep_modeイベントが復活した

Up24のボタン長押しでsleepモードと通常モードを切り替えた時に送られてくるexit_sleep_modeとenter_sleep_modeイベントが復活した。

6月ごろからイベントがwebhookでpushされて来なくなってたんだけど、昨日になって復活してるのに気づいた。

俺APIからのイベントをhubotで受けとってこういう風に通知がだせる。起きたらhue電球つけるとか寝たら消すとかも簡単にできると思う。




config =
url: 'https://ore-api.herokuapp.com'
slack:
room: "#ore"

module.exports = (robot) ->

socket = require('socket.io-client').connect config.url

socket.on 'exit_sleep_mode', (event) ->
robot.send config.slack, "@#{event.screen_name} が眠りから覚めました"


socket.on 'enter_sleep_mode', (event) ->
robot.send config.slack, "@#{event.screen_name} が眠りにつきました"

0

Jawbone Up24の運動ログをHubot経由でSlackに流す

前:Web+DB Press vol.82にJawbone Up24について書いた

先月末に発売されたWeb+DB Press vol.82で、コードが長すぎてページが足りなくて入りきらなかったネタ


研究室でにわかにjawbone up24が流行り始めていて、slackの#newsというチャットルームに「起きた(5時間寝た、3回二度寝した)」とかログが流れてくる。

そこに「何歩歩いた」あるいは「活発に活動中」というログも流すようにした。


これは記事の中に書いた俺APIというJawbone APIのプロキシを使ってる。Bluetooth LEで自動同期できるup24がちょっと歩く毎にガンガンwebhookでpushしてくるのを俺APIが受信して、さらにそこからsocket.ioでhubotに再配信してくれる。
JawboneのAPIはOAuth2で認証しないと使えないんだけど、もっと細かくてどうでもいい事に気軽に使いたかったのでAPIプロキシを立てた。あと俺が起きてるか寝てるかなんて認証かける必要なく公開されてていいと思った。ので作った。


hubot-ore-api.coffee

ちょっと長いけど、こういうhubot scriptを書いておけばチャットに運動の通知が流せる。(実際使ってるやつから抜粋してきた)
歩いた時は〜〜歩歩いたってslackに流れるし、歩かずにデスクワークしている時もpush来るので「活発に活動中」とかslackに通知するようにしている。

俺APIでoauth2認証しておけば色々なところからjawboneのイベントが使えるようになるので便利だと思う。

hubot-ore-api.coffee
debug = require('debug')('hubot-ore-api')

config =
url: 'https://ore-api.herokuapp.com'
slack:
room: "#news"

module.exports = (robot) ->

socket = require('socket.io-client').connect config.url

## jawboneから動いたイベントがpushされてくる
socket.on 'move', (event) ->
debug "move - #{JSON.stringify event}"
if event.action is 'updation'
notify_move event

last_notify_at = {}
## 動いた事を通知する
notify_move = (event) ->
if Date.now() - (last_notify_at[event.screen_name] or 0) < 1000*60*60 # 1時間毎に間引く
debug "throttled #{event.screen_name}'s notify_move"
return
last_notify_at[event.screen_name] = Date.now()
get_activity "moves", event.screen_name, event.event_xid, (err, move) ->
if err or move.details?.steps < 1
debug 'no steps data in event'
return
current_steps = move.details.steps
last_steps = robot.brain.get("steps_#{event.screen_name}") or 0
robot.brain.set("steps_#{event.screen_name}", current_steps)
if last_steps > current_steps
last_steps = 0
new_steps = current_steps - last_steps
if new_steps > 0
txt = "@#{event.screen_name} が#{new_steps}歩運動しました (本日合計#{current_steps}歩 #{move.details.km}km)"
else
txt = "@#{event.screen_name} が活発に活動しています"
robot.send config.slack, txt

## ore-api.herokuappにあるJawbone APIプロキシを使う
get_activity = (type, screen_name, xid, callback = ->) ->
robot.http("#{config.url}/#{screen_name}/#{type}.json?xid=#{xid}").get() (err, res, body) ->
if err
callback err
return
try
data = JSON.parse body
catch err
callback err
return
debug data
callback null, data.data
return

0

Web+DB Press vol.82にJawbone Up24について書いた

8/23発売のvol.82 Amazonで予約できるようになってた

WEB+DB PRESS Vol.82
WEB+DB PRESS Vol.82
posted with amazlet at 14.08.20
山口 徹 Jxck 佐々木 大輔 横路 隆 加来 純一 山本 伶 大平 武志 米川 健一 坂本 登史文 若原 祥正 和久田 龍 平栗 遵宜 伊藤 直也 佐藤 太一 高橋 俊幸 海野 弘成 五嶋 壮晃 佐藤 歩 吉村 総一郎 橋本 翔 舘野 祐一 中島 聡 渡邊 恵太 はまちや2 竹原 河合 宜文
技術評論社
売り上げランキング: 330


前の号から「Hack the Real World」という、オープンなAPIがあるガジェットで何か面白い・便利な物作ろうという連載をやってる。

今回はJawbone Up24という腕輪型のアクティビティロガーについて書いた。
Up24は睡眠や運動のログを記録して、BLEでスマホと同期し、さらにjawbone.comからそれを取得できるAPIがある。
webhook APIもあって、運動したり起床したりすると瞬時にデータをサーバーpushしてくれたりもしてすごい。似たようなロガーは色々あるけど一番APIが良かったのでUp24にした。


記事では基本的なAPIの解説と、起きたらMacからラジオ体操.mp3を流すとか、チャットで俺の状態が見れるようにするとかの例を作った。
Hubot使ったりした。(同じ号にHubotの解説記事もあるらしい)

アクティビティロガーがpushでデータ送ってくれると(ほぼ)完全にインタフェースの操作なしで起きたらエアコン付けるとか、寝てない奴にコードレビュー回さないとかできるわけで、システムを使うとか考えなくてよくなるからユビキタスコンピューティングっぽくて良いと思う。



ちょっと面倒だったのは、テザリング環境で原稿書いているとwebhookが受けられないのと、実際に寝たり起きたりしてデータ取る必要があって夜寝る前にプログラム動かしておいて朝確かめるとか、6月末にjawbone APIのバージョン上がったとか、色々あった。
まあ記事読めばそういう苦労はいらないと思います。


なお記事に出てくる「俺API」という、jawbone APIへのプロキシ的なwebアプリはクライアント(Hubot等)との接続にsocket.ioを使っているけど、別にwebhookでも構わないです。
家のMacで俺APIからのデータ受信してラジオ体操流すとかを作る時に、socket.ioの方がルータ超えとか便利だったのでそうした。

0

Jawbone Up24のpubsub APIを受信する

Jawbone Up24を買った。Apple Storeで売ってた。
前のUpと比べてbluetoothで同期できるので楽というのもあるが、webhookによるサーバープッシュAPIの方が気になってて買った。

UP for Developers: Pub Sub


通知

oauthで認証してもらったユーザーが寝たり・起きたり・活動したりすると、約10秒後に自作のwebアプリにjsonでwebhookが通知される。
jawbone up—(bluetooth)—>スマホ—(HTTP)—>jawboneのサーバー—(HTTP webhook)—>自作webアプリ
と通知がリレーされていくわけです。

最近色々とまともなAPIのあるガジェットは増えてるけど、出力側ばっかりで、入力というかトリガー側(センサー)になるやつはあまり無い。


ソースコード

前に作ったJawbone UpのAPIで睡眠時間などを取得するを少し改造した。

https://github.com/shokai/jawbone-up-api-study


設定

アプリケーションの設定にpubsubのURLを書くだけで通知が来るようになる。


プログラム

post ‘/pubsub’を追加した。あとAPIのscopeを色々追加した。move_readが無いと運動した時に空の通知が来てしまっていたので。

https://github.com/shokai/jawbone-up-api-study/tree/master/auth
def app_root
"#{env['rack.url_scheme']}://#{env['HTTP_HOST']}#{env['SCRIPT_NAME']}"
end

def oauth_client
@client ||= OAuth2::Client.new(CLIENT_ID, APP_SECRET,
:site => 'https://jawbone.com',
:authorize_url => '/auth/oauth2/auth',
:token_url => '/auth/oauth2/token')
end

get '/' do
unless session[:oauth_token]
@mes = %Q{<p><a href="/login">login</a></p>}
else
@mes = %Q{<p><a href="/logout">logout</a></p>
<p>your token : #{session[:oauth_token]}</p>}
end
end

get '/login' do
scope = "basic_read extended_read mood_read move_read sleep_read generic_event_read"
redirect oauth_client.auth_code.authorize_url(:scope => scope,
:redirect_uri => "#{app_root}/auth")
end

get '/auth' do
code = params["code"]
halt 400, 'code missing' unless code
begin
session[:oauth_token] = oauth_client.auth_code.get_token(code).token
puts "TOKEN : "+session[:oauth_token]
rescue => e
STDERR.puts e.message
end
redirect "/"
end

get '/logout' do
session.delete :oauth_token
redirect "/"
end

post '/pubsub' do
request.body.rewind
puts request.body.read
"ok"
end


こういうのがpushされてくる
{"events": [{"action": "enter_sleep_mode", "timestamp": 1396797071, "user_xid": "gvT5W2FhlrHsB3r9Wq_unA"}], "notification_timestamp": 1396797074}
{"events": [{"action": "exit_sleep_mode", "timestamp": 1396797115, "user_xid": "gvT5W2FhlrHsB3r9Wq_unA"}], "notification_timestamp": 1396797117}
{"events": [{"action": "creation", "timestamp": 1396797240, "user_xid": "gvT5W2FhlrHsB3r9Wq_unA", "type": "move", "event_xid": "mD99tHyRBx4xNT7HoSCUmA"}], "notification_timestamp": 1396798341}

1

Jawbone UpのAPIで睡眠時間などを取得する

oauth2で認証してからjawbone gemを使う。

ここに置いてある
https://github.com/shokai/jawbone-up-api-study


腕輪型アクティビティロガーのAPI

腕輪型アクティビティロガーではJawbone Up、FitBit、FuelBandの3つが有名だと思う。どれもAPIがある。

JawboneがOAuth2、FitBitがOAuthで認証して詳細なデータが取得できて、APIもいろいろあって遊べる。作ったアプリを他人に使ってもらいやすい。
Nike FuelBandは野良開発者は自分のバンドしかデータが取れず、しかも詳細な数値はナイキのパートナーしか取得できないようだ。遊べない。

Jawbone Up24(Bluetooth LEでiPhone/Androidと同期するやつ)はwebhookのURLが登録できて、OAuth2で読み取り権限をくれたユーザーのデータがガンガン自分のwebアプリにサーバー間プッシュされるらしいので興味深い。例えば睡眠に入った、起きた、等のタイミングでpushされるらしい。普通のUpでも同期したタイミングでpushされてくるかなと思って試したけど、webhookされなかった。Up24がほしい。

俺が普通のJawbone Upを買ったのは3つのAPIドキュメントを比較してみて、Jawboneが一番面白そうだなと思ったからなんだけど、当時AndroidではUp24とbluetooth接続できなかったので普通のUpを買ったという次第。Up24ほしい。


まずアプリを登録する

https://jawbone.com/up/developer/

とりあえずローカルホストでアプリを作るのでcallbackをうけるためにlocalhost:5000で登録する。

Client IdとApp Secretをメモしておく。


認証する


これをSinatraで実装する
UP for Developers: Authentication

config.ru

require 'sinatra'
require 'oauth2'

CLIENT_ID="your-client-id"
APP_SECRET="your-app-secret"

require_relative 'main'

enable :sessions
set :session_secret, (ENV["SESSION_SECRET"] || "zanmai-kazusuke-kazudon-marutaka")

run Sinatra::Application

main.rb

def oauth_client
@client ||= OAuth2::Client.new(CLIENT_ID, APP_SECRET,
:site => 'https://jawbone.com',
:authorize_url => '/auth/oauth2/auth',
:token_url => '/auth/oauth2/token')
end

get '/' do
unless session[:oauth_token]
@mes = %Q{<p><a href="/login">login</a></p>}
else
@mes = %Q{<p><a href="/logout">logout</a></p>
<p>your token : #{session[:oauth_token]}</p>}
end
end

get '/login' do
scope = "extended_read sleep_read mood_read"
redirect oauth_client.auth_code.authorize_url(:scope => scope,
:redirect_uri => "http://localhost:5000/auth")
end

get '/auth' do
code = params["code"]
halt 400, 'code missing' unless code
begin
session[:oauth_token] = oauth_client.auth_code.get_token(code).token
rescue => e
STDERR.puts e.message
end
redirect "/"
end

get '/logout' do
session.delete :oauth_token
redirect "/"
end

起動

% bundle exec rackup config.ru -p 5000


loginするとjawboneのサイトに飛んでoauthで認証しlocalhost:5000に戻ってくる。


APIで睡眠データを取得する

/users/@me/sleeps
 を読む。

これが
UP for Developers: Endpoints

ラップされてjawbone gemになる

["move", "body_event", "workout", "sleep", "meal", "cardiac_event", "generic_event", "mood"]
が使える。


require 'jawbone'
require 'awesome_print'

OAUTH_TOKEN = "your-oauth-token"

client = Jawbone::Client.new OAUTH_TOKEN

ap client.user
ap client.sleeps
睡眠時間などを取得する


何時から何時まで寝たか(asleep_timeとawake_time)、深い眠り(deep)と浅い眠り(light)の長さ、ただ横になっているだけで寝ていない時間(awake)、二度寝を何回したか(awakenings)などがわかる。
単位は全て秒とunixtime。