Nature Remo Cloud APIを使って自宅の温度変化を可視化してみる

今年はおそろしく暑いですね。寝るときもエアコンが必須です。
ただ、寝てる最中にエアコンが冷やしすぎてしまったりして体に悪いので、設定温度を微調整したいなと思いました。
せっかく自宅には複数台Remo mini 2が置いてあるので、まずは寝ている最中の記録を取ることで適正な設定値を検討するのに役立ててみようと思いました。

これはなに

Nature Remo Cloud APIから室温を取得してGoogleSpreadSheetに記録するスクリプトです。

手順

トークンの取得

トークンをこちらから取得します。
取得したトークンを控えます。
このトークンは外部に漏れないように気をつけて管理してください。
悪用されると自宅の家電を色々操作されたりします。

プロジェクトの作成

$ npm init -y

モジュールの追加

開発自体はローカルで行いつつGitでバージョン管理もしたかったのでclaspを導入します。
併せてVSCodeで補完などができると便利なのでtypes/google-apps-scriptも導入しておきます。
ちなみにTypeScriptよくわかってません、なんとなくで書いてます、ご容赦ください。

$ npm install @google/clasp   

added 245 packages, and audited 246 packages in 14s

61 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
$ npm install @types/google-apps-script

added 1 package, and audited 247 packages in 2s

61 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

Googleアカウントの認証

ログイン用のコマンドを実行します。
めちゃくちゃ長いURLがプロンプトに発行されるのでブラウザでアクセスし、認証させるアカウントを選んで先に進みます。
権限の認可の画面に移るので許可をして先に進みます。
認証コードが発行されるので元のコマンドのプロンプトに入力すれば認証が完了します。

$ npx clasp login --no-localhost
Warning: You seem to already be logged in *globally*. You have a ~/.clasprc.json
Logging in globally…
🔑 Authorize clasp by visiting this url:
 https://accounts.google.com/o/oauth2/v2/auth?hogehogehogehoge

Enter the code from that page here:

なお、認証した結果はホームディレクトリに.clasprc.jsonとして保存されます。このファイルも大切なので外部に漏れないようにしましょう。

GASプロジェクトの作成

claspを使用してプロジェクトを作成します。
コマンドを実行するとスクリプトを紐付けるサービスを聞かれます。今回はスプレッドシートを利用するのでsheetsを選択します。
この段階で空のスプレッドシートがGoogleドライブに、空のプロジェクトがApps Scriptに作成されています。

$ npx clasp create
? Create which script? sheets
Created new Google Sheet: https://drive.google.com/open?id=xxxx
Created new Google Sheets Add-on script: https://script.google.com/d/xxx/edit

タイムゾーンの設定

このままだとプロジェクトの設定が日本時刻になっていないのでタイムゾーンの設定を変更します。
appsscript.jsonで管理されているので変更します。

{
  "timeZone": "Asia/Tokyo",
  "dependencies": {},
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8"
}

natureのトークンをスクリプトプロパティに登録

スクリプト内にトークンをベタ書きするのはセキュリティの観点で良くないのでGASのスクリプトプロパティを利用します。
GASのプロジェクトの設定からスクリプトプロパティを登録します。
プロパティ名はNatureTokenとして、値には最初に取得したトークンを入れます。
これでこれから作成するコードから値を参照することができます。

コード

以下のコードをmain.tsとして保存します。
データを書き込むシート名はdataとなっています。スプレッドシートがまっさらでも必要なものは実行すれば自分で作ってくれるようになっています。

const dataSheetName = "data"

function get_token() {
    //nature token
    var token = PropertiesService.getScriptProperties().getProperty('NatureToken')
    return token
}

function natureApiGetRequest(api: string): [] {
    const url: string = 'https://api.nature.global' + api
    const token = get_token()
    let params = {
        'method': 'get',
        'accept': 'application/json',
        'headers': {
            'Authorization': 'Bearer ' + token
        }
    }

    let response = UrlFetchApp.fetch(url, params).getContentText()
    return JSON.parse(response)
}

function isSheetExists(sheetName: string): boolean {
    let ss = SpreadsheetApp.getActiveSpreadsheet();
    let allSheets = ss.getSheets()

    for (let i = 0; i < allSheets.length; i++) {
        let val = (allSheets[i].getName())
        if (val === sheetName) {
            return true
        }
    }
    return false
}

function addSheet() {
    let ss = SpreadsheetApp.getActiveSpreadsheet();
    let rc = isSheetExists(dataSheetName)
    if (rc === false) {
        ss.insertSheet(dataSheetName)
    }
}

function outputData2Sheet(data: [], execdate) {
    let ss = SpreadsheetApp.getActiveSpreadsheet()
    let sheet = ss.getSheetByName(dataSheetName)
    let titles = []

    console.log(execdate)
    console.log(data)
    sheet.getRange("A1").setValue("日時")
    let lc = sheet.getLastColumn()
    let addrow = sheet.getLastRow() + 1

    if (lc > 1) {
        let titles = sheet.getRange(1, 2, 1, lc - 1).getValues()[0]
        console.log(titles)
    }

    for (let i = 0; i < data.length; i++) {
        let title = data[i].name
        let teval = data[i].newest_events.te.val
        let timestr = Utilities.formatDate(execdate, 'JST', 'yyyy-MM-dd HH:mm:ss')

        let colnum = i + 2

        //書き込む列を決める
        if (titles.length > 1) {
            let num = titles.indexOf(title)
            if (num >= 0) {
                let colnum = num + 2
            } else {
                let colnum = lc + 1
                lc++
            }
        }

        //タイトル行の生成
        sheet.getRange(1, colnum).setValue(title)
        sheet.getRange(addrow, 1).setValue(timestr)
        sheet.getRange(addrow, colnum).setValue(teval)
    }
}

function main() {
    const api = '/1/devices'

    //APIからデータを取得
    let response = natureApiGetRequest(api)
    //データ取得した日時を取得
    let execdate = new Date()

    //必要ならスプレッドシートにシートを作成
    addSheet()

    //シートにデータを書き込み
    outputData2Sheet(response, execdate)
}

デプロイ

ファイルをプロジェクトにアップロードします。

$ npx clasp push 

実行

GASのプロジェクト画面からmain関数を実行します。
途中でGoogleから権限を求められるので許可しましょう。
スプレッドシートを確認すると、日時と各remoの名前を見出しとし、それぞれの下にデータ取得日時と室温が記録されます。
あとはプロジェクトを定期的に実行するように設定すれば自動でデータが追加されてきます。
よしなにグラフ化するなどして、快適に過ごせるように空調の設定を見直すなどしましょう。

コメント

タイトルとURLをコピーしました