フューチャーホームコントローラーを支える技術 テンプレートとしてのjson


フューチャーホームコントローラーの技術解説を書いてます。
フューチャーホームコントローラーは、声でしゃべるだけで様々な家電を操作できる未来的ガジェットです。(写真の手前にあるのは名刺のです。)

ここから注文することができます。
http://rti-giken.jp/



フューチャーホームコントローラー自体は、httpdの部分からC++11でガリガリ書いています。
そして、フューチャーホームコントローラーの設定画面はwebページです。
なので、C++でHTMLを生成することになります。


簡単なHTMLテンプレートだったら、そこそこ簡単に作ることができますが、
もう少し複雑なデータ構造になると、そうも行きません。

フューチャーホームコントローラーの画面もjquery mobile をベースに作っているので、基本的にajaxで通信します。
そのため、C++側は、jsonでデータを送り、
ajaxで値を埋め込んで画面を描画しています。
そして、ブラウザからは、POST / GETで結果をもらうという構造になっています。

var g_Remocon = %REMOCON%;

↓文字列置換でjsonで渡す

var g_Remocon = {"hogehoge": "123" , "b": "456" ... };

//javascriptでフォームに埋め込む
$("#hogehoge").val(g_Remocon["hogehoge"]);


現時点で、
javascript + html で、とか6000行ぐらいありまして、
それを司るC++のルーチンも 4000行ぐらいあります。
UIはとても手間がかかるものところです。

その代償

もちろん、こーゆーことをすると速度が低下します。
FHCの設定画面にスマホで入れなくしているのはこのためです。

私が持っている古いiphone(3GS)で設定画面を開くと、
うごくことはうごきますが、とても動作がもっさりしてしまいます。
PCで開くととても快適なのですが、、
jQuery Mobile も重いとかゆうのがありますが、困ったところです。

これではリモコンの勝てない

FHCは、音声で家電を操作できるガジェットですから、スマホやPCで家電を操作する機能はオプション機能です。
ですが、それらに対して妥協はしたくないところです。
スマホで家電を操作しようと思った時にも、快適な操作できないといけません。

FHCのライバルは、普通のリモコンです。
普通のリモコンよりも不便なものを作ってしまって、利用する意味がありません。

スマホを使って家電を操作する時点で、
リモコンに対してどうしても操作速度という点では負けてしまいます。

リモコン
リモコンを探す -> 手に取る -> 機材に向け -> ボタンをおす

スマホ
スマホを探す -> 手に取る -> ロック解除 -> アプリを立ち上げ -> ボタンをおす

スマホは、ロック画面にパスがかかっていたり、
アプリを立ち上げるのにホーム画面をスワイプしたり、目的のボタンを探すのにも何回かクリックしなきゃいけなかったりと、いろいろい手間隙がかかります。

もし、両者が手元にあったとしたら、スマホよりリモコンの方が早いです。
専用機と汎用機の近いというところでしょうか。

FHCは音声認識がありますから、何も考えずに、「コンピュータ、電気つけて!」といえばいいだけなので、
リモコンにも勝てる動作速度であると考えています。
(もちろん、騒がしかったりマイクが遠かったりで認識が失敗しまくれば話は変わりますが・・・)

話を戻しましょう。
スマホは、リモコンよりも動作ステップが多いので、
スマホのアプリぐらいは快適に動作しないといけません。

AJAXだともっさり、だから、非AJAXで作るお

前に説明したとおり、AJAXで作ると、 javascriptでフォームへのはめ込みができるので作るのが楽です。
その代わり、どうしてもjavascriptでDOMを操作したりシないといけないので動作がもっさりしてしまいます。
昔のスマホとかだと、処理速度が遅いのでこの差は顕著です。

なので、FHCでは、リモコン操作画面、ログイン画面の読み込みからAJAXを排除しました。
C++上に作った自前テンプレートによりHTMLで生成しています。
もちろん、圧縮やキャッシュやらは効かせてあるので、帯域もそれほど食べません。
古いiphone(3GS)で、ブラウザのリロードボタンからで1秒で描画がすべて完了することを目標としています。
ブラウザが起動していない状態からだと、ブラウザ起動時間があるので、もう少し時間がかかってしまいますが、、、

//自前テンプレートエンジンで置換を行う例。
	<ul id="remocon_remoconmenu_ul">
%REMOCON_LOOP_START%
		<li class="item itemshow">
				<div class="mainicon"><img src="%ICON%" width="120" height="120" /></div>
				<div class="type">%TYPE%</div>
				<div class="status_label" style="color:%STATUSCOLOR%;">状態:<span class="status">%STATUS%</span></div>
				
				//skip
		</li>
%REMOCON_LOOP_END%
	</ul>

表示の部分ですから、 IF と LOOP と文字置き換えがあればなんとかなるので、
こーゆー簡単なテンプレート構文でも特に困りませんでした。
これでAJAXで書き換えるよりも早く表示されます。

速さでこれ以上を目指すとしたら、HTML5のcache manifestを使えばもっと早くなるとは思います。
ただ、FHCの場合、機材のステータスを表示しないといけないので、両立は難しいところです。
画面だけ先読みして、機材の並び順やステータスを後読みしたところで、読み込みが終わるまではユーザは事実上操作できないですから、どれほど意味があるか謎です。

または、HTML5をすべて捨てて、ネイティヴアプリにすることになるかと思います。
こうなれば、もっと爆速で動作しますが、開発が忙しくなってしまうところです。

まぁ、
今時、iphone 3GSなんて使っているのは私ぐらいなので、新しいiphoneとかだとすごくさくさく動くとは思いますけどね・・・

AJAXで作ると楽。だけど遅い。早くしたければHTMLで生成する。

まとめると、
AJAXを使って、C++からはjsonを生成し、
jsonjavascriptでDOMに当てはめて行くと、開発は楽です。
ですが、ユーザ体験は劣化します。
設定項目が多い設定画面等に向いていると思います。

HTMLテンプレートとかでPHPとかみたいにHTMLを生成すれば、
速度は早いですが、C++で作るといろいろとめんどいです。

支えなかったLUA

実は、当初は、LUAをHTMLに埋め込んで PHPみたいに使う予定でした。
そのために、 とかみたいなものを実は作りました
この仕組はちゃんと動きますが、実際にこれで作ってみると、かなーり作りづらいものがありました。

<html>
<body>
<?lua for(i=1,99){ 
	local key=""..i.."";
	if( not out["records"][key]){ break; }
	local value = out["records"][key];
?>
	<div class="img" id="img-1">
		<div><a href="javascript:void(0)" onclick="mediaplay(<?= key ?>)">
			<img width="255" height="255"  src='data:image/jpeg;base64,<?= value["image"] ?>'><br />
			<div class="msg" ><span class="select_mark"><?= key ?></span><?= value["title"] ?></div>
		</a></div>
	</div>
<?lua } ?>
</body>
<html>

LUAでのテーブル(連想配列)の生成と、その利用がとてもめんどく、
げっそりとするものでした。
また、C++ / LUA / javascript / html などがソースコードに乱立してしまいとても悲しいものがありました。

そのため、この機能を廃止して、
C++ から AJAXjson配列で渡して、javascriptで画面を生成するという案になりました。

スマホでのajaxがもー少し早くなれば

スマホでのajaxが、PCぐらいに早ければ ajaxベースで開発するのは十分にありだと思いました。
ただ、速度が求められる部分だと、まだ少し早いのかなとも思います。
ただ、スマホも急激に進化していますので、それほど問題にならなくなる日も来るとおもいます。