ホットカーペットのつけっぱなしをゼロに!SwitchBot電球で電源状態を光で可視化する方法

Raspberry Pi

皆さんのご家庭でも、子どもがホットカーペットをつけたままにしてしまうことはありませんか?
ホットカーペットは外から見ると電源が入っているかどうかがわかりにくく、気づいたら何時間もつけっぱなしだった…ということも。
本記事では、SwitchBotのスマートプラグとカラー電球を使って、ホットカーペットの使用状況をリアルタイムに光で可視化するシステムの実装方法を解説します。消費電力に応じて電球の色が変わるので、遠くから見ても一目でホットカーペットの状態がわかります。

なぜこの機能を作ったのか?

我が家では子どもたちがホットカーペットを勝手につけることがよくあります。問題は「つけっぱなし」が非常に多いこと。ホットカーペットは消費電力が大きく、つけっぱなしにすると電気代にダイレクトに響いてきます。
また、ホットカーペットは電源ランプが小さかったり本体が絨毯の下に隠れていたりして、側から見ると電源が入っているかどうかがまったくわかりません。
そこで、ホットカーペットの電源状態と消費電力を、リビングに置いたスマート電球の点灯・色で可視化することにしました。電球が光っていればホットカーペットが動いている、消えていれば停止中、という直感的な仕組みです。

ホットカーペットのつけっぱなしを「見える化」して、電気代を節約したい!

実現したいこと

  • ホットカーペットの電源ON/OFFをスマート電球の点灯/消灯で表示する
  • 消費電力の大きさに応じてスマート電球の色を変える
    • 弱〜中 (300W未満):黄色
    • 中〜強 (300〜400W):オレンジ
    • 強 (400W以上):赤
  • 5秒ごとにリアルタイムで状態を更新する
  • 電球の色が変わった場合のみSwitchBot APIを呼び出す (無駄なAPI呼び出しを減らす)

この記事でわかること

  • SwitchBotスマートプラグの消費電力データをInfluxDBから取得する方法
  • SwitchBot APIを使ってカラー電球のON/OFFや色を制御する方法
  • 消費電力の変化を検知して電球の点灯・消灯・色変更を行うロジックの実装方法
  • 前回の状態と比較して不要なAPI呼び出しを省く方法

必要な準備と用意するもの

ハードウェア
  • Raspberry Pi(例:Raspberry Pi 4 / 5)
  • SwitchBot スマートプラグミニ(ホットカーペットに接続して消費電力を計測)
  • SwitchBot カラー電球(ホットカーペットの状態を色で表示)
ソフトウェア/サービス
  • Python 3
  • InfluxDB v2(SwitchBotプラグの電力データを蓄積するデータベース)
  • SwitchBot API v1.1(カラー電球の制御)
  • 自作ライブラリ
    • influx.v2(InfluxDBクライアント)
    • switchbot(SwitchBot APIラッパー)
    • smarthomelog(ログ出力)

完成イメージ

ホットカーペットをつけると、近くに置いたスマート電球が点灯します。消費電力に応じて電球の色が変わるので、弱運転・強運転の状態もひと目でわかります。ホットカーペットを消すと電球も自動で消灯します。

スマート電球をホットカーペットの近く(例:テレビボードの上のスタンドライトなど)に設置すると、遠くからでも「あ、ホットカーペットついてる」と気づけてとても便利です。

システムの仕組み

システム全体の流れは下記の通りです。

  1. SwitchBotスマートプラグがホットカーペットの消費電力を定期的に計測し、データをInfluxDBに蓄積する
  2. Raspberry Pi上のPythonプログラムが5秒ごとにInfluxDBから最新の消費電力を取得する
  3. 前回の状態と比較して変化があれば、SwitchBot APIでカラー電球を制御する
    • 消費電力が0W → 電球をOFF
    • 消費電力が0Wより大きい → 電球をONにして消費電力に応じた色に変更

「前回と今回が両方0W」または「前回も今回も0W超」の場合は電球の操作をスキップすることで、SwitchBot APIへの無駄なリクエストを減らしています。

実装のポイント

電球ON/OFFの判定ロジック

ポイントは「前回の消費電力」と「今回の消費電力」を比較して、状態が変わったときだけ電球を操作することです。毎回API呼び出しをすると無駄なリクエストが増えるうえ、レート制限に引っかかる可能性もあります。

API呼び出しを最小化
前回と今回の消費電力の両方が0、または両方が0超の場合は電球操作をスキップ。ON→OFFまたはOFF→ONの変化が起きたときだけAPIを呼び出す設計にすることで、SwitchBot APIへのリクエスト数を大幅に削減できます。

消費電力に応じた電球の色設定

電球の色は消費電力の閾値で3段階に分けています。ホットカーペットの一般的な消費電力を考慮して以下の色にしています。

  • 黄色 (255:174:0):300W未満(弱〜中運転)
  • オレンジ (255:57:17):300W〜400W未満(中〜強運転)
  • 赤 (255:0:0):400W以上(強運転・最大)

色の閾値はホットカーペットの機種によって異なります。実際に使用するホットカーペットの消費電力仕様を確認してから値を調整してください。

電球の色変更は点灯中のみ実施

電球が消灯している状態で色変更APIを呼び出しても意味がないため、is_lightingフラグを使って点灯中のときだけ色変更コマンドを送信するようにしています。また色が変わった場合のみコマンドを送信することで、不要なAPI呼び出しを避けています。

事前準備

SwitchBotスマートプラグの設置

SwitchBotスマートプラグミニをホットカーペットのコンセントに挿し込みます。SwitchBotアプリでプラグを登録し、デバイスIDを控えておきます。
スマートプラグの電力データをInfluxDBに記録する仕組みは別記事を参照してください。

SwitchBotカラー電球の設置

SwitchBotカラー電球をリビングのスタンドライトなどに取り付け、SwitchBotアプリで登録します。デバイスIDを控えておきます。

SwitchBot APIトークンの取得

SwitchBotアプリの「プロフィール」→「設定」→「アプリバージョン」を10回タップするとAPIトークンを取得できます。取得したトークンを設定ファイルに記載します。

設定ファイルの準備

下記のようにsettings.jsonにSwitchBotの情報を設定します。

{
    "switchbot": {
        "api": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "api_url": "https://api.switch-bot.com/v1.1/",
        "device_id": {
            "floor_heating_plug": "xxxxxxxxxxxx",
            "floor_heating_bulb": "xxxxxxxxxxxx",
            "living_aircon_sensor": "xxxxxxxxxxxx"
        }
    }
}

APIトークンやデバイスIDは外部に公開しないよう十分注意してください。GitHubなどにアップロードする際は設定ファイルを.gitignoreに追加してください。

実装方法

プログラム全体は以下の通りです。5秒ごとにInfluxDBから最新の消費電力を取得し、状態が変化した場合にSwitchBot APIでカラー電球を制御します。

# -*- coding: utf-8 -*-
__group__ = '省エネ'
__description__ = 'ホットカーペット使用状況の可視化'
# ------ 全Pythonプログラム共通の宣言 ----------------------------
from pathlib import Path
import sys
# プロジェクトのルートフォルダを取得
PROJECT_ROOT = Path(__file__).resolve()
while PROJECT_ROOT.name != "smarthome":
    if PROJECT_ROOT.parent == PROJECT_ROOT:
        raise RuntimeError("smarthome project root not found")
    PROJECT_ROOT = PROJECT_ROOT.parent
# Bootstrapをimportするためだけにプロジェクトルートをパスに追加
sys.path.insert(0, str(PROJECT_ROOT))
# BootstrapでPathの設定と設定ファイルの取得
from libs.bootstrap import Bootstrap
bootstrap = Bootstrap(__file__)
settings = bootstrap.settings
# ------------------------------------------------------------
import time
from influx.v2 import client as influxclient
from influx.v2 import writer as influxwriter
import switchbot
import smarthomelog

try:
    # スライムに設定する色を定義 (RGB形式)
    slime_color = {
        'white':  '255:255:255',
        'blue':   '0:118:255',
        'green':  '36:255:0',
        'yellow': '255:174:0',
        'orange': '255:57:17',
        'purple': '255:0:255',
        'red':    '255:0:0'
    }

    # InfluxDBクライアントとライターを初期化
    influx_client = influxclient
    influx = influxwriter.Writer()
    success_log = smarthomelog.Log(__file__, smarthomelog.LogType.SUCCESS)
    app_err_log = smarthomelog.Log(__file__, smarthomelog.LogType.APPLICATION_ERROR)

    influx.insert_execution_log(__file__, 'Start Floor Heater Lighting!')

    # SwitchBotインスタンスを取得
    switchbot_instance = switchbot.Switchbot()

    # SwitchBot APIコマンド定義
    json_data_turnOn = {
        'command': 'turnOn',
        'parameter': 'default',
        'commandType': 'command'
    }
    json_data_turnOff = {
        'command': 'turnOff',
        'parameter': 'default',
        'commandType': 'command'
    }

    # 前回の状態を保持する変数
    color_before = None
    waight_before = 0
    is_lighting = None

    while True:

        # InfluxDBから最新の消費電力(W)を取得
        res = influx_client.query_dict_by_influxql(
            'plug',
            {'weight'},
            {'deviceId': settings['switchbot']['device_id']['floor_heating_plug']},
            query_mode=influxclient.QueryMode.LAST
        )
        # InfluxDBからリビングのエアコン送風口の照度を取得
        res_lav = influx_client.query_dict_by_influxql(
            'contact_sensor',
            {'brightness'},
            {'deviceId': settings['switchbot']['device_id']['living_aircon_sensor']},
            query_mode=influxclient.QueryMode.LAST
        )

        # 取得した消費電力と照度を変数に格納
        latestWeight = res[0].get('weight') if res else 0
        brightness = res_lav[0].get('brightness') if res_lav else 'unknown'

        # ログ出力
        if color_before is not None:
            influx.insert_execution_log(__file__,
                '現在の消費電力(W): ' + str(latestWeight) +
                '    現在の電球色: ' + color_before +
                '    リビングの明るさ: ' + brightness)

        # 電球のON/OFF制御
        # 前回も今回も0W、または前回も今回も0W超の場合は操作しない
        if (latestWeight == waight_before and latestWeight == 0) or (latestWeight > 0 and waight_before > 0):
            print('電球の点灯や消灯の操作はなし。')
        elif latestWeight > 0:
            # ホットカーペットがONになった → 電球を点ける
            response = switchbot_instance.execute_command(
                settings['switchbot']['device_id']['floor_heating_bulb'],
                json_data_turnOn
            )
            influx.insert_execution_log(__file__, '電気を点けました。')
            is_lighting = True
        else:
            # ホットカーペットがOFFになった → 電球を消す
            response = switchbot_instance.execute_command(
                settings['switchbot']['device_id']['floor_heating_bulb'],
                json_data_turnOff
            )
            influx.insert_execution_log(__file__, '電気を消しました。')
            is_lighting = False

        # 消費電力に応じて電球の色を決定
        if latestWeight < 300:
            color = slime_color['yellow']   # 弱〜中運転
        elif latestWeight < 400:
            color = slime_color['orange']   # 中〜強運転
        else:
            color = slime_color['red']      # 強運転・最大

        # 電球の色変更 (点灯中かつ色が変わった場合のみ)
        if is_lighting and color != color_before:
            json_data_setColor = {
                'command': 'setColor',
                'parameter': color,
                'commandType': 'command'
            }
            response = switchbot_instance.execute_command(
                settings['switchbot']['device_id']['floor_heating_bulb'],
                json_data_setColor
            )
            influx.insert_execution_log(__file__, '電球色が変更されました。 (変更後の電球色: ' + color + ')')

        # 今回の状態を保存
        color_before = color
        waight_before = latestWeight

        success_log.write('処理が正常に終了しました。', __file__)
        time.sleep(5)

except Exception as e:
    log = smarthomelog.Log(__file__, smarthomelog.LogType.SYSTEM_ERROR)
    log.write_error(sys.exc_info())

プログラム中で influx.v2switchbotsmarthomelogbootstrap はこのスマートホームプロジェクト内の自作ライブラリです。それぞれ別記事を参照して準備するか、該当箇所をご自身の環境に合わせて書き換えてください。

コードの解説

電球ON/OFF制御のロジック (状態変化の検知)

下記の条件分岐が電球制御の核心部分です。

if (latestWeight == waight_before and latestWeight == 0) or (latestWeight > 0 and waight_before > 0):
    print('電球の点灯や消灯の操作はなし。')
elif latestWeight > 0:
    # 電球をON
else:
    # 電球をOFF

ポイントは「前回と今回で状態が変わったときだけ電球を操作する」という設計です。毎回APIを呼び出すと、SwitchBotのAPIレート制限に引っかかるリスクがあるほか、電球が不必要にチラつく原因にもなります。

消費電力に応じた色の決定

電球の色はRGB形式の文字列 ("R:G:B") でSwitchBot APIに渡します。消費電力の閾値を変えることで、ご自身のホットカーペットの仕様に合わせて調整できます。

if latestWeight < 300:
    color = slime_color['yellow']   # 弱〜中運転
elif latestWeight < 400:
    color = slime_color['orange']   # 中〜強運転
else:
    color = slime_color['red']      # 強運転・最大

ホットカーペットの消費電力は機種によってかなり異なります。例えば2畳用で弱100W・強200W程度の機種もあれば、3畳用で弱200W・強400W超の機種もあります。スマートプラグのアプリで実際の消費電力を確認してから閾値を設定しましょう。

色変更は点灯中かつ色が変わったときだけ

if is_lighting and color != color_before:

is_lighting フラグで電球が点灯中かどうかを管理し、さらに前回の色 (color_before) と今回の色が違う場合だけ色変更コマンドを送信します。消費電力が同じ範囲内に留まっている間は余計なAPI呼び出しをしません。

動作確認

プログラムを手動で実行して動作を確認します。

python floor_heater_light.py

下記の手順で動作を確認してください。

  1. ホットカーペットをOFFの状態でプログラムを起動 → カラー電球が消灯していることを確認
  2. ホットカーペットを弱または中に設定 → カラー電球が黄色で点灯することを確認
  3. ホットカーペットをに設定 → カラー電球がオレンジまたは赤に変わることを確認
  4. ホットカーペットをOFFに戻す → カラー電球が消灯することを確認

動作確認ができたら、systemdを使ってRaspberry Pi起動時に自動実行されるよう設定しておくと便利です。

まとめ

本記事では、SwitchBotスマートプラグとカラー電球を組み合わせて、ホットカーペットの使用状況を光で可視化するシステムの実装方法を解説しました。

  • ホットカーペットのON/OFFを電球の点灯/消灯で視覚化
  • 消費電力に応じて電球を黄・オレンジ・赤の3色で表示
  • 状態変化を検知したときだけAPIを呼び出す効率的な設計

「ホットカーペットってついてる?」という確認の手間がなくなり、子どもたちのつけっぱなしもすぐ気づけるようになりました。同じ仕組みはホットカーペット以外にも、電気ストーブや加湿器など「外から電源状態がわかりにくい家電」全般に応用できます。ぜひ試してみてください!

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