Yado_tech

旅館+ITとはなんぞ

お風呂に温度異状があった場合にスマートライトの色を変える。GAS版

tuya Smart Life がIFTTTと連携しなくなるということでびっくりした話。

youtu.be

同時にこういった記事も見つけた。

qiita.com

こちらの記事ではnode.jsからtuya apiにアクセスしていたが、サーバーを用意するのもまだるっこしいので

GASで書いてみた。

必要なもの

  • おんどとりの温度計

データロガー おんどとり | SMART VALVE | T&D Corporation

  • スマートLED(私は2つで3,000円のこちらを購入した)



この辺は先程挙げた記事の中にやり方は書いてあります。

これで以下のようなGASを書いて5分ごとに実行すればOKです。

//TUYA API 設定 環境に応じて書き換えて下さい。
const clientId = "[CLIENTID]";
const clientSecret = "CLIENTSECRET";
const device_id = ["DEVICE_A", "DEVICE_B"];

//おんどとりweb storage API 設定
//環境に応じて書き換えて下さい。
const api_key = "API_KEY";
const login_id = "LOGIN_ID";
const password = "PASSWORD";
//>>>>【重要】最後にtemps関数内の風呂温度の内容を書き換えてください。<<<<<
//

//温度を配列で返す関数
function temps() {
  const ondotori_url = "https://api.webstorage.jp/v1/devices/current";

  const furo_temp = () => {
    var paylord = {
      "api-key": api_key,
      "login-id": login_id,
      "login-pass": password,
    };
    var headers = {
      "X-HTTP-Method-Override": "GET",
      "Content-Type": "application/json",
    };
    var options = {
      method: "post",
      payload: JSON.stringify(paylord),
      headers: headers,
      muteHttpExceptions: true,
    };

    return UrlFetchApp.fetch(ondotori_url, options);
  };
  return JSON.parse(furo_temp());
}

//ここまで関数

//ここから本文
function myfunction() {
  //温度のJSONを取得する
  var tmprs = temps();

  //デバッグ用 女子風呂の温度
  //Logger.log("女子:" + tmprs["devices"][1]["channel"][0].value)

  //↓↓↓男子風呂の温度 環境に応じて切り替えて下さい
  var danshi = tmprs["devices"][2]["channel"][0].value;

  //↓↓↓女子風呂の温度 環境に応じて切り替えて下さい
  var joshi = tmprs["devices"][1]["channel"][0].value;

  if (Math.max(danshi, joshi) > 43) {
    Logger.log(`熱い:男子:${danshi} 女子:${joshi}`);

    setColour(colour.red);
  } else if (Math.min(danshi, joshi) < 40) {
    Logger.log(`冷たい:男子:${danshi} 女子:${joshi}`);

    setColour(colour.blue);
  } else {
    Logger.log(`普通:男子:${danshi} 女子:${joshi}`);
    setColour(colour.green);
  }

  //if (Math.min(danshi,joshi)<38 && Math.max(danshi,joshi)>44){
  //  Logger.log("なんか変")
  //  status = "somethingwrong"
  //}
}
//ここまで本文

//以降はTUYA API用スクリプト
//setColour(colour.red or colour.blue or colour.green)以外はエラーとなります。
//単純に動かないだけ。

var url = "https://openapi.tuyaus.com/v1.0/token?grant_type=1";
var command_url = `https://openapi.tuyaus.com/v1.0/devices/${device_id}/commands`;
var command_urls = device_id.map(
  (key) => `https://openapi.tuyaus.com/v1.0/devices/${key}/commands`
);
var colour = {
  blue: { h: 240, s: 255, v: 255 },
  red: { h: 360, s: 255, v: 255 },
  green: { h: 120, s: 255, v: 100 },
};

function setColour(colors) {
  var timeStamp = getTime().toString();

  var token = retreiveAccessToken(clientId, clientSecret, timeStamp, url);
  var sign = calcSignWithToken(clientId, token, clientSecret, timeStamp);
  var headers = {
    client_id: clientId,
    access_token: token,
    t: timeStamp,
    sign: sign,
    sign_method: "HMAC-SHA256",
    "Content-Type": "application/json",
  };

  var options = {
    method: "POST",
    headers: headers,
    payload: JSON.stringify({
      commands: [
        { code: "switch_led", value: true },
        { code: "colour_data", value: colors },
      ],
    }),
  };
  // Logger.log(`access_token: ${token}`);
  // Logger.log(`sign :${sign}`);
  // Logger.log(`timestamp:${timeStamp}`);
  res = command_urls.map((key) => UrlFetchApp.fetch(key, options));
  Logger.log(res);
}

function retreiveAccessToken(clientId, clientSecret, timeStamp, url) {
  var easy_sign = calcSign(clientId, clientSecret, timeStamp);
  var headers = {
    client_id: clientId,
    sign: easy_sign,
    t: timeStamp,
    sign_method: "HMAC-SHA256",
    // Authorization: `Bearer $clientSecret`,
  };

  var options = {
    method: "GET",
    headers: headers,
    payload: {},
  };

  res = UrlFetchApp.fetch(url, options);
  return JSON.parse(res).result.access_token;
}

function getTime() {
  var now = new Date().getTime();
  return now;
}

function calcSign(clientId, clientSecret, timeStamp) {
  var str = clientId + timeStamp;
  var hash = Utilities.computeHmacSha256Signature(str, clientSecret);
  var signature = hash.reduce(function (str, chr) {
    chr = (chr < 0 ? chr + 256 : chr).toString(16);
    return str + (chr.length == 1 ? "0" : "") + chr;
  }, "");
  return signature.toUpperCase();
}

function calcSignWithToken(clientId, accessToken, clientSecret, timeStamp) {
  var str = clientId + accessToken + timeStamp;
  var hash = Utilities.computeHmacSha256Signature(str, clientSecret);
  var signature = hash.reduce(function (str, chr) {
    chr = (chr < 0 ? chr + 256 : chr).toString(16);
    return str + (chr.length == 1 ? "0" : "") + chr;
  }, "");
  return signature.toUpperCase();
}

ログインにめっちゃ苦労したけどなんとか出来た。よかったよかった。
iot.tuya.comのドキュメントの中にPOSTMANの使い方のなかにSHA256形式で暗号化してログインするというスクリプトが合ったのでそれをGASに合わせて書き換えるのが苦労した。