凹みTips

C++、JavaScript、Unity、ガジェット等の Tips について雑多に書いています。

Vim × Future Home Controller で家電を操作する unite source 作った

Vim Advent Calendar 96 日目の記事になります。

はじめに

先日、声で家電を操作できるガジェット Future Home Controller(FHC)を購入しました。

私も声で家電を操作したり室温からエアコン温度を自動調節したりするインフラを作っていたのですが、FHC は更に高機能な面もあり、イイトコどりのハイブリッドにするため飛びついてしまいました。さてさて、そんな FHC の大きな機能の一つとして Web API のサポートが挙げられます。

非常に多くの Web API が用意されていますが、今回はこの中から、登録されている音声認識ワード一覧を取得する recog/list と、音声認識ワードの文字列で各機能を呼び出しできる recog/firebystringwebapi-vim を利用して叩くことで、Unite.vim から 家電を操作できる unite source を作りました。Vim は暮らしの一部となりました!

デモ


片手ふさがってるので連打してますが、通常は絞り込みで使ってます。

インストール

NeoBundle を使用していれば、以下のように書けます。

通常版
NeoBundle 'mattn/webapi-vim'
NeoBundle 'hecomi/unite-fhc'
遅延ロード版
NeoBundleLazy 'hecomi/unite-fhc', {
\	'depends'  : ['mattn/webapi-vim'],
\	'autoload' : {
\		'unite_sources' : 'fhc',
\	},
\ }
設定
" FHC の IP
let g:fhc_ip     = '192.168.0.11'
" FHC の Web API key
let g:fhc_apikey = 'webapi_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

コード

今回はじめて plugin を書いてみたのですが、webapi-vim の至れり尽せり感がすごいので、特に詰まるところもなく他の言語と同じように処理を書くことが出来ました。

scriptencoding utf-8

let g:fhc = {}

function! g:fhc.get_json(kind, opt)
	let l:opt = ''
	for key in keys(a:opt)
		let l:opt .= '&'.key.'='.a:opt[key]
	endfor
	let l:fhc_url = 'http://'.g:fhc_ip.'/api/'.a:kind.'?webapi_apikey='.g:fhc_apikey.l:opt
	let l:res     = webapi#http#get(l:fhc_url)
	if l:res.content == ''
		return {'result': 'error', 'code': 'xxx', 'message': 'network error'}
	endif
	let l:json    = webapi#json#decode(l:res.content)
	return l:json
endfunction

function! g:fhc.check_err(json)
	if a:json.result != 'ok'
		echo a:json.code . ': ' . a:json.message
		return -1
	endif
	return 0
endfunction

function! g:fhc.get_list()
	let l:json = self.get_json('recong/list', {})
	if self.check_err(l:json) != 0
		return []
	endif
	return l:json.list
endfunction

function! g:fhc.firebystring(str)
	let l:json = self.get_json('recong/firebystring', {'str': a:str})
	if !self.check_err(l:json) != 0
		return
	endif
endfunction

let s:source = {
\	'name'        : 'fhc',
\	'description' : 'exec future home controller commands',
\ }
call unite#define_source(s:source)

function! s:source.gather_candidates(args, context)
	let l:command = 'call g:fhc.firebystring("%s")'
	return map(
	\ g:fhc.get_list(),
	\ '{
	\	"word"            : v:val,
	\	"source"          : "fhc",
	\	"kind"            : "command",
	\	"action__command" : printf(l:command, v:val),
	\ }')
endfunction

function! unite#sources#fhc#define()
	return s:source
endfunction

基本的には、

let l:res = webapi#http#get(l:fhc_url)

で、対象の URL から json を引っ張ってきて、

let l:json = webapi#json#decode(l:res.content)

で、json を辞書型にデコードしてくれて、

l:json.list

にアクセスすれば、機能一覧の配列がもらえるので、そのまま unite source に使用しているだけです。楽ちんですね。

おわりに

他の方にも使って頂きたいですが、Vim ユーザと FHC ユーザの積集合 = 1人(= 自分)疑惑ある...。
明日はおしょーさん(id:osyo-manga)です!果たして100日行くのか…。