[SwitchBot] 05 管理アプリMac版の製作 その1 C++, FLTK

[Mac M2 Pro 12CPU, Sonoma 14.5]

SwitchBot管理アプリMac版の製作に着手しました。手順は以下の通りです。

1.Adobe XDでGUIをデザイン。座標とサイズを自作プラグインで抽出
2.ChatGPT用プロンプトを作成しレスポンスを得る
3.手直ししたC++コードをビルド

このコードを土台に肉付けしていきます。

FLTKアプリを作成します
C++コードを考えてください
ウィンドウのサイズは600*400
各ウィジェットの座標は以下の通り
{
  "エアコングラフ": [15, 200, 270, 180],
  "ファン選択": [110, 140, 60, 20],
  "ファン": [10, 141, 53, 18],
  "温度幅表示": [240, 81, 40, 20],
  "温度幅スライダー": [110, 80, 120, 20],
  "温度幅": [10, 81, 54, 18],
  "動作温度表示": [240, 50, 40, 20],
  "動作温度スライダー": [110, 50, 120, 20],
  "動作温度": [10, 51, 72, 18],
  "OFFボタン": [190, 10, 60, 30],
  "AUTOボタン": [110, 10, 60, 30],
  "エアコン": [10, 15, 80, 20],
  "設定温度表示": [240, 110, 40, 20],
  "設定温度スライダー": [110, 110, 120, 20],
  "設定温度": [10, 111, 72, 18]
}

エアコン:Fl_Boxに"エアコン"を表示
AUTOボタン:ラベルが"AUTO"のFl_Button
OFFボタン:ラベルが"OFF"のFl_Button

動作温度:Fl_Boxに"動作温度"を表示
動作温度スライダー:Fl_Sliderを表示 26から28まで0.1きざみ
動作温度表示:Fl_Boxに動作温度スライダーの値を表示。

温度幅:Fl_Boxに"温度幅"を表示
温度幅スライダー:Fl_Sliderを表示 0.1から0.5まで0.1きざみ
温度幅表示:Fl_Boxに温度幅スライダーの値を表示。

設定温度:Fl_Boxに"設定温度"を表示
設定温度スライダー:Fl_Sliderを表示 20から25まで1.0きざみ
設定温度表示:Fl_Boxに設定温度スライダーの値を表示。

ファン:Fl_Boxに"ファン"を表示
ファン選択:ブルダウンで選択 # fan speed includes 1 (auto), 2 (low), 3 (medium), 4 (high);
エアコングラフ:pngファイルを表示

[SwitchBot] 04 エアコンを操作

[Mac M2 Pro 12CPU, Sonoma 14.5]

Pythonでエアコンを操作してみました。

このスクリプトを応用すれば、温湿度計のデータと連携させて0.1度単位でトリガーを設定し、エアコンを操作できるようになります。

純正アプリでは最小で0.5度の温度幅ですが、0.1度まで狭くすることが理屈では可能です。

ただ、SwitchBot APIへのコール回数は1日10000回までになっています。毎秒測定なら1日86400回になるので、10秒に1回程度に減らす必要があります。cronを使えば毎分が最多で1440回です。

import os
import time
import json
import hashlib
import hmac
import base64
import uuid
import requests
import datetime

dir_name = "/SwitchBot/data"

device_id = "XXX"
token = 'XXX'
secret = 'XXX'

# エアコン設定
temperature = 26.5
mode = 2 # modes include 0/1 (auto), 2 (cool), 3 (dry), 4 (fan), 5 (heat);
fanspeed = 1 # fan speed includes 1 (auto), 2 (low), 3 (medium), 4 (high);
power_state = "on" # power state includes on and off

nonce = str(uuid.uuid4())
t = int(round(time.time() * 1000))
string_to_sign = "{}{}{}".format(token, t, nonce)
string_to_sign = bytes(string_to_sign, "utf-8")
secret = bytes(secret, "utf-8")
sign = base64.b64encode(
    hmac.new(secret, msg=string_to_sign, digestmod=hashlib.sha256).digest()
)

HEADERS = {
    "Authorization": token,
    "Content-Type": "application/json",
    "charset": "utf8",
    "t": str(t),
    "sign": str(sign, "utf-8"),
    "nonce": nonce
}

# コマンド内容
command_body = {
    "command": "setAll",
    "parameter": f"{temperature},{mode},{fanspeed},{power_state}",
    "commandType": "command"
}

response = requests.post(
    f"https://api.switch-bot.com/v1.1/devices/{device_id}/commands",
    headers=HEADERS,
    data=json.dumps(command_body)
)

status = response.json()

timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
response_file = f"{dir_name}/AirCon/status_{device_id}_{timestamp}.json"
with open(response_file, "w") as f:
    json.dump(status, f, ensure_ascii=False, indent=4)

print("Success operate Air Conditioner")