なんとなく分かった事
- [そもそも]トグル形式のボタンとの相性は悪い。(TV on/offなど)
- [そもそも]リモコンボタンの長押しは再現出来ません。(これは、アプリからのリモコンボタン連打でも再現不可でした)
- [アプリ]リモコンボタンのディレイ送信は出来ません。(APIでは可能)
- [API]global APIを叩いて扱う方が用法的には簡単(というか、Local APIはInterfaceが難解なので挫折しました)
なので、リクエスト送信頻度には気を付ける事(プログラムチックに投げると即、NGくらいます) - [API]エアコン以外は、signal idさえ分かれば、簡単にシグナルを送れます。
エアコンの場合は"aircon_settings"に、”button=power-on" or "power-off"のPOSTパラメータを送れば反応します
構成図
ちなみに、ここでは上記でいうディレイ送信の実現についてのみ記載します。(IR機器のみ)
あと端的にいうと、setTimeoutを使った、遅延Request実行をしているだけのコードとなります
その前提で
まずは、すべてのIR機器のニックネームとボタン名のマッピングファイルを用意します(ir.json)。
フォーマットは利便性も兼ねて、以下のようにしています。
{
"電気": {
"オン": "id",
"暗く": "id",
"オフ": "id"
},
"オーディオ": {
"電源": "id",
"plus": "id"
},
"ルンバ君": {
"clean": "id",
"やめ": "id"
}
}
そして、このファイルは以下のコードで自動生成します。(AWS lambda)
exports.generateIRList = function(event, context, callback) {
this.get({ url : "https://api.nature.global/1/appliances"},{},(err,res)=>{
var contents = res.filter((e)=>{return e.type === "IR"}).reduce((prev,c)=>{
prev[c.nickname] = c.signals.reduce((p,c)=>{p[c.name]=c.id;return p;},{});
return prev;
},{});
var dt = JSON.stringify(contents,null,"\t");
console.log(dt);
fs.writeFile(`./ir.json`, dt, 'utf8');
callback(null,dt);
});
}
次に、どのような順番でそれぞれを呼び出すかを定義します。
上記のマッピングを事前に作ることにより、人にヤサシイ定義ができます。
各シグナルをどの程度の遅延で実行するかを定義してます。
{
orders : [
{
delay : 3000,
order : ["電気","オン"]
},
{
delay : 3000,
order : ["電気","暗く"]
},
{
delay : 3000,
order : ["電気","オフ"]
}
]
}
そして、このオーダーを以下event.ordersパラメータとしてリクエストします(AWS lambda)
//lambda layer
exports.delayed = function(event, context, callback) {
var irs = fs.readFileSync("./ir.json","utf8");
irs = JSON.parse(irs);
console.log(irs);
var promises = [];
event.orders.forEach((e,idx)=>{
var id = irs[e.order[0]][e.order[1]]; //ここで実際に誰(nickname)に対して、何のシグナル(id)を送るかをir.jsonより決定
var orderObj = urlfactroy("IR",id);
console.log(e.delay);
console.log(orderObj);
setTimeout((i)=>{
promises.push(postImpl(orderObj.url));
if(event.orders.length == (i+1)){
Promise.all(promises).then((res)=>{ //すべてのリクエスト追加が終わってからpromise.allで待つ
console.log("sending ok");
callback(null,res); //完了
});
}
},e.delay*(idx+1),idx); //遅延起動時間 bug有り
});
};
}
## 実行
3秒毎に、電気をオン、電気を暗く、電気をオフ。を実行してくれます。
なんの役にもたたないですが、自分のコードで家電が動く感動は、かなりあります。
これでようやく、電源オンに時間がかかるIR機の操作(我が家のオーディオ)は、操作可能になりそうです。
終わりに
Global API呼び出しに関しては、他の記事がたくさんあるので省略しました。
それも含めてみたければ、こちらをどうぞ
ちなみに、エラーハンドリングは皆無です。
というのも理由は分かりませんが、readFileSyncがalways empty stringを返すバグに直面して
1時間程格闘したのち、fs.readFileに書き換えて事なきを得た。ってのもあって完成させる気力が失われたからです。
ちなみに、以下がその問題のコードです。参考までに
exports.delayed = function(event, context, callback) {
var irs = fs.readFileSync("./ir.json","utf8"); <-- ここを readFile(callback version)にすると動作する。。
CROSの難解度やら、ベストプラクティスの移り変わりやらを見てきたのもあって、今後はJSには極力手を出すべきではないなと実感しました。