toio.jsとTwitter APIを合わせて使ってみた
久しぶりの記事投稿。今回はtoioをJavascriptで制御するのとTwitterAPIを合わせて使っていく。
toioとは
toioとはソニーインタラクティブエンタテインメントより発売されているロボットトイである。詳しくは公式サイトを見てほしいが、子供から大人まで楽しめるモノになっている。公式からtoio.jsというNode.js(サーバサイドで動くJavaScript環境)のライブラリが公開されているので今回をそちらを利用していく。
今回やること
toioの最大の特徴は主役であるデバイスのキューブ(下図)の光学センサーを用いて、付属のマットやシールに施されている特殊印刷を読み取り、キューブの絶対座標やIDを取得できる点だ。
今回はその絶対座標や各シールのIDを取得した後、TwitterAPIを介してそれらをTweetするのを目標とする。
なおJavascriptを触るのは初めてなのであしからず。
環境構築
環境構築は以下を行った。今回は手順は省く。
- Node.js及びtoio.jsの環境構築(公式を参照)
- TwitterAPIの導入(参照記事)
なおTwitterのアプリケーション作成方法はアップデート毎に変更されているようだ。3年前に一度Androidアプリ開発で触ったことがあったが、開発者アカウントの作成などは審査などが追加されており少々面倒くさくなっていた。
できたもの
今回はクラフトファイターの技カードのIDを識別してツイートする内容とした。(マットを使った座標が今後考えていく・・・)
以下が機能である。
- キューブはキーボートの矢印キーで走行可能
- プログラム実行中は常にIDを取得し続ける
- スペースキーを押すと現在のIDを利用してツイート文を判定・投稿
スペースキーを押すと何やら詳細情報がたくさん吐き出されてTwitterに投稿される。
投稿が完了するとプログラムは終了するようにした。
toioコンテンツ内の特殊印刷から得られるIDはこちらの技術情報から参照できる。
ソースコード
const twitter = require("twitter");
const fs = require("fs");
const client = new twitter(JSON.parse(fs.readFileSync("secret.json", "utf-8")));
const keypress = require('keypress')
const { NearestScanner } = require('@toio/scanner')
const DURATION = 700 // ms
const SPEED = {
forward: [70, 70],
backward: [-70, -70],
left: [30, 70],
right: [70, 30],
}
const flag = true;
//tweet
function tweet(sentence) {
client.post('statuses/update', { status:sentence }, function (error, tweet, response) {
if (!error) {
console.log(tweet);
process.exit(0);
} else {
console.log('error');
process.exit(1);
}
});
}
//make sentences from data
function make_sentence(value){
if(value === 3670016){
out = 'Typhoon!'
}else{
if(value === 3670054){
out = 'Rush!'
}else{
if(value === 3670018){
out = 'Auto Tackle!'
}else{
if(value === 3670056){
out = 'Random!'
}else{
if(value === 3670020){
out = 'Stab Power Up!'
}else{
if(value === 3670058){
out = 'Slapping Power Up!'
}else{
if(value === 3670022){
out = 'Side Attack!'
}else{
if(value === 3670060){
out ='Easy Mode!'
}
}
}
}
}
}
}
}
}
//exit processing
function exit(){
try{
if(flag){
throw new Error('program end');
}
console.log('not end');
}catch(e){
console.log(e.message);
}
}
//main
async function main() {
// start a scanner to find nearest cube
const cube = await new NearestScanner().start()
// connect to the cube
await cube.connect()
//tweet data initialize
var id = []
//get id data
cube
.on('id:standard-id', data => {id.unshift(data.standardId)})
//.on('id:position-id', data => {id.unshift(data.x,data.y)}) //appendix
//move and tweet
keypress(process.stdin)
process.stdin.on('keypress', (ch, key) => {
// ctrl+c or q -> exit process
if ((key && key.ctrl && key.name === 'c') || (key && key.name === 'q')) {
process.exit()
}
switch (key.name) {
case 'space':
var value = id[0];
console.log('data : ', value)
make_sentence(value)
tweet(out)
break
case'':
break
case 'up':
cube.move(...SPEED.forward, DURATION)
break
case 'down':
cube.move(...SPEED.backward, DURATION)
break
case 'left':
cube.move(...SPEED.left, DURATION)
break
case 'right':
cube.move(...SPEED.right, DURATION)
break
}
})
process.stdin.setRawMode(true)
process.stdin.resume()
}
main()
いかにもJavascript初心者っぽいコーディングだがあしからず・・・
IDを判別して文章を決める大量のif else文をなんとかしたいが、何かいい方法はないだろうか・・・
今後
初挑戦のNode.jsもといJavaScriptだったがtoioの整った環境と使いやすいデバイス、仕様のおかげで1つ作成することができた。
今回は利用するID(toio内の利用物)を絞ったが、次回はマットから取得できるX,Y座標やアングル等を利用して発展させたいと考えている。