3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Nature Remo を使ってみてなんとなく分かったこと

Last updated at Posted at 2018-08-19

なんとなく分かった事

  1. [そもそも]トグル形式のボタンとの相性は悪い。(TV on/offなど)
  • [そもそも]リモコンボタンの長押しは再現出来ません。(これは、アプリからのリモコンボタン連打でも再現不可でした)
  • [アプリ]リモコンボタンのディレイ送信は出来ません。(APIでは可能)
  • [API]global APIを叩いて扱う方が用法的には簡単(というか、Local APIはInterfaceが難解なので挫折しました)
    なので、リクエスト送信頻度には気を付ける事(プログラムチックに投げると即、NGくらいます)
  • [API]エアコン以外は、signal idさえ分かれば、簡単にシグナルを送れます。
    エアコンの場合は"aircon_settings"に、”button=power-on" or "power-off"のPOSTパラメータを送れば反応します

構成図

aws.png

ちなみに、ここでは上記でいうディレイ送信の実現についてのみ記載します。(IR機器のみ)

あと端的にいうと、setTimeoutを使った、遅延Request実行をしているだけのコードとなります

その前提で
まずは、すべてのIR機器のニックネームとボタン名のマッピングファイルを用意します(ir.json)。
フォーマットは利便性も兼ねて、以下のようにしています。

ir.json
{
	"電気": {
		"オン": "id",
		"暗く": "id",
		"オフ": "id"
	},
	"オーディオ": {
		"電源": "id",
		"plus": "id"
	},
	"ルンバ君": {
		"clean": "id",
		"やめ": "id"
	}
}

そして、このファイルは以下のコードで自動生成します。(AWS lambda)

generateIR.js
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);
  });

}

次に、どのような順番でそれぞれを呼び出すかを定義します。
上記のマッピングを事前に作ることにより、人にヤサシイ定義ができます。
各シグナルをどの程度の遅延で実行するかを定義してます。

input.json
{
      orders : [
      {
        delay : 3000,
        order : ["電気","オン"]
      },
      {
        delay : 3000,
        order : ["電気","暗く"]
      },
      {
        delay : 3000,
        order : ["電気","オフ"]
      }
    ]
}

そして、このオーダーを以下event.ordersパラメータとしてリクエストします(AWS lambda)

ctrlRemo.js

//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に書き換えて事なきを得た。ってのもあって完成させる気力が失われたからです。
ちなみに、以下がその問題のコードです。参考までに

notworking.js
exports.delayed = function(event, context, callback) {
  var irs = fs.readFileSync("./ir.json","utf8");  <-- ここを readFile(callback version)にすると動作する。。

CROSの難解度やら、ベストプラクティスの移り変わりやらを見てきたのもあって、今後はJSには極力手を出すべきではないなと実感しました。

その後はこちら

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?