Nature Remoの情報を基にLINEに通知を送るGAS(Google Apps Script)の作成

Nature Remoにて家電の消し忘れとかがあった場合に、
LINEに通知するようなGAS(Google Apps Script)を作成してみました。

コートは下記になります。
※今回は例として、平日の午前9時にエアコンの電源がオンになっていたら
　LINEに通知するようなプログラムとなります。(祝日にも対応しています)

:::note info
Nature Remo、LINEともにアクセスするためのトークンが必要となります。
取得の方法はここでは割愛しますので、各自で取得してください。
※LINEはLINE Messaging APIを使っています。
※元々はLINE Notifyで作成していたのですが、サービス終了するとのことで、LINE Messaging APIで作成しなおしました
:::

:::note info
1台のNature Remoと紐づかれているエアコンが複数ある場合はtypeではかぶってしまうため、
typeの代わりにnicknameを使うなどの修正が必要になります。
:::

```javascript


function getNatureRemoData() {
  let access_token = ''//←Nature Remoのトークンを入れる
  let url = "https://api.nature.global/1/appliances";
  let headers = {
    "Content-Type" : "application/json;",
    'Authorization': 'Bearer ' + access_token,
  };

  let options = {
    "method" : "get",
    "headers" : headers,
  };

  let data = JSON.parse(UrlFetchApp.fetch(url, options));
  let ac=-1;
  for (var i = 0; i < data.length; i++) {
    if(data[i]["type"]=="AC") ac=i; 
  }
  return data[ac]["settings"]["button"];

}

//送信するメッセージ定義する関数を作成します。
function createMessage() {
  //メッセージを定義する
  message = "エアコンがついています。";
  return push(message);
}


//実際にメッセージを送信する関数を作成します。
function push(text) {

// LINE Developersに書いてあるChannel Access Token
var access_token = "Channel Access Token"
// 自分のユーザーIDを指定します。LINE Developersの「Your user ID」の部分です。
var to = "ユーザーID"

  var url = "https://api.line.me/v2/bot/message/push";
  var headers = {
    "Content-Type" : "application/json; charset=UTF-8",
    'Authorization': 'Bearer ' + access_token,
  };
  
  //toのところにメッセージを送信したいユーザーのIDを指定します。(toは最初の方で自分のIDを指定したので、linebotから自分に送信されることになります。)
  //textの部分は、送信されるメッセージが入ります。createMessageという関数で定義したメッセージがここに入ります。
  var postData = {
    "to" : to,
    "messages" : [
      {
        'type':'text',
        'text':text,
      }
    ]
  };
 
  var options = {
    "method" : "post",
    "headers" : headers,
    "payload" : JSON.stringify(postData)
  };
 
  return UrlFetchApp.fetch(url, options);
}


function createTrigger() {
  var allTriggers = ScriptApp.getProjectTriggers();
  var existingTrigger = null;

  // すでに存在するmyFunctionトリガーを探す
  for (var i = 0; i < allTriggers.length; i++) {
    if (allTriggers[i].getHandlerFunction() === 'createTrigger') {
      existingTrigger = allTriggers[i];
      break;
    }
  }

  // すでに存在するトリガーがあれば削除
  if (existingTrigger !== null) {
    ScriptApp.deleteTrigger(existingTrigger);
  }
  if(getNatureRemoData()!="power-off"){
    createMessage();
  }
  // 新しいトリガーを作成
  var triggerDay = new Date();
  var wday=1;
  if(triggerDay.getDay()==5) wday=3;
  if(triggerDay.getDay()==6) wday=2;
 
  while(true){
    triggerDay.setDate(triggerDay.getDate() + wday);
    var url = "http://api.national-holidays.jp/" + Utilities.formatDate(triggerDay, "JST", "yyyy/MM/dd");
    
    var data=JSON.parse(UrlFetchApp.fetch(url,{muteHttpExceptions: true}));
    if(data["error"] == "not_found"){
      break;
    }
    wday=1;
  }
  
  triggerDay.setHours(7);
  triggerDay.setMinutes(40);
  triggerDay.setSeconds(0);

  ScriptApp.newTrigger('createTrigger')
    .timeBased()
    .at(triggerDay)
    .create();

  // トリガー設定日時を記録
  var scriptProperties = PropertiesService.getScriptProperties();
  scriptProperties.setProperty('TriggerSetAt', triggerDay.toString());
}

```

参考にしたリンク以外の個所についての説明を行います。

```javascript
  let data = JSON.parse(UrlFetchApp.fetch(url, options));
  let ac=-1;
  for (var i = 0; i < data.length; i++) {
    if(data[i]["type"]=="AC") ac=i; 
  }
  return data[ac]["settings"]["button"];
```

Nature RemoのAPIで取得したJSON形式のデーターを見たところ、
各家電のタイプが[番号]["type"]に記載されていて、
エアコンはACでした。
番号の個所はおそらく登録順かと思われますので、
別のNature Remoでも対応できるようにfor文でエアコンの番号を検査しています。
調べたところ、エアコンのオンオフは[番号]["settings"]["button"]に記載されていて、
オフの場合は"power-off"と記載、オンの場合は空欄でした。
これにてオンオフの判定を行っています。


```javascript
  // 新しいトリガーを作成
  var triggerDay = new Date();
  var wday=1;
  if(triggerDay.getDay()==5) wday=3;
  if(triggerDay.getDay()==6) wday=2;
 
  while(true){
    triggerDay.setDate(triggerDay.getDate() + wday);
    var url = "http://api.national-holidays.jp/" + Utilities.formatDate(triggerDay, "JST", "yyyy/MM/dd");
    
    var data=JSON.parse(UrlFetchApp.fetch(url,{muteHttpExceptions: true}));
    if(data["error"] == "not_found" && triggerDay.getDay()!=0 && triggerDay.getDay()!=6){
      break;
    }
    wday=1;
  }
  
  triggerDay.setHours(7);
  triggerDay.setMinutes(40);
  triggerDay.setSeconds(0);
```

トリガーを作成する際に、土日は飛ばして作成する場合、
現在の曜日をgetDayで調べて、金曜だったら3日後、土曜だったら2日後
の日付になるように設定し、それ以外1日後となるようにし、
祝日APIを利用して、設定した日付が祝日だった場合は
祝日でないかつ土日でない日付まで日付をずらします。

## Nature RemoのJSON形式のデーターの見方
上記プログラムの場合、
getNatureRemoData関数内、
data変数宣言直後にブレイクポイントを配置し、
getNatureRemoDataをデバッグすることで、
data変数内に格納されたデーターを見ることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/855481/2a16ee59-014c-3f2e-f1a2-8715f190a0fe.png)

## 最後に

上記コードを応用すれば、エアコンだけでなく様々な家電についてLINEに通知を送信することが可能となります。
スマートロックと連携して鍵の閉め忘れがあったら通知とか。
自分の環境に合ったものを作成してみてはいかがでしょうか。



# 参考リンク

Nature RemoのAPIからの情報取得は下記を参考にしました。

https://qiita.com/t-chi/items/01b9a9b98fbccef880c3

LINEへの通知は下記を参考にしました。

https://qiita.com/n_oshiumi/items/a1a02e03093825f41e01


トリガーの作成は下記を参考にしました。

https://qiita.com/kakakaori830/items/c06674252513b8d1c42e