消費電力でキングスライムの色が変わる!楽しい電力ビジュアライズ

Raspberry Pi

電気代が気になるけど、わざわざアプリやGrafanaを開いて確認するのは面倒…そんな悩みを解決するために「見るだけ」で電力使用量がわかるシステムを作りました。
ドラゴンクエストのスライムをモチーフにしたカラーリングで、消費電力に応じてLED電球の色がリアルタイムに変化します。数字を一切見なくても、電球をちらっと見るだけで今の電力状況が把握できるユニークなスマートホーム機能です。

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

我が家ではNature Remo E liteでスマートメーターに接続し、家全体の消費電力をInfluxDB+Grafanaで可視化しています。しかし、Grafanaのグラフを確認するにはPCかスマホを開かなければならず、日常生活の中でリアルタイムに電力を意識するのは難しい状況でした。
家族全員が「今の電力使用量」を自然に意識できる仕組みを作りたいと思い、部屋の棚に置いたLED電球の色でひと目でわかるようにしました。せっかく作るなら楽しくしようと、大好きなドラゴンクエストのスライムのカラーリングをテーマにしました。

数字を見なくても、電球の色だけで電力の使いすぎを家族みんなに気づいてほしい!

実現したいこと

  • 家の瞬間消費電力をリアルタイムでLED電球の色で表現する
  • 消費電力の増加に応じて電球の色が変わる(ドラクエのスライムカラーをモチーフ)
    • 300W未満:白(メタルキング)
    • 300〜500W:青(キングスライム)
    • 500〜1000W:緑(スライムベホマズン)
    • 1000〜1500W:黄色
    • 1500〜2000W:オレンジ
    • 2000〜2500W:紫
    • 2500W以上:赤
    • 3000W超:赤+最大輝度(警告モード)
  • 部屋が暗くなったら電球も自動でOFFになる(無駄な発光を防ぐ)
  • 電力量が危険ゾーン(3000W超)に達したら電球を最大輝度にして視覚的に警告する

この記事でわかること

  • Nature Remo E liteのAPIを使って瞬間消費電力を取得する方法
  • SwitchBot カラー電球をAPIで色・輝度制御する方法
  • InfluxDBに記録したデータをPythonから取得・活用する方法
  • SwitchBot コンタクトセンサーの照度情報と連動して電球を自動ON/OFFする方法
  • systemdサービスとして常駐実行する設定方法

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

ハードウェア
  • ミニPC または Raspberry Pi(Ubuntu/Linux)
  • Nature Remo E lite(スマートメーターとのBルーター接続済みのもの)
  • SwitchBot カラー電球
  • SwitchBot Hub 2 または Hub Mini(カラー電球の遠隔制御に必要)
  • SwitchBot コンタクトセンサー(部屋の照度検知用・オプション)
ソフトウェア/サービス
  • Python 3.x
    • requests
    • influxdb-client
  • InfluxDB v2(電力データの蓄積に使用)
  • Nature Remo API(クラウドAPI・無料プラン利用可)
  • SwitchBot API v1.1

完成イメージ

棚の上に置いたキングスライムのフィギュアの横に、SwitchBotカラー電球を設置しています。電力使用量によって電球の色がリアルタイムに変化します。
家族がリビングにいると自然と目に入る場所に置いているため、「あ、今電気使いすぎてるな」と直感的に気づけるようになりました。特に赤くなった時のインパクトは大きく、子供も「スライムが赤くなってる!」と電力の使いすぎに気づいてくれます。

消費電力電球の色ドラクエモチーフRGB値
〜299Wメタルキング255:255:255
300〜499Wキングスライム0:118:255
500〜999Wスライムベホマズン36:255:0
1000〜1499W黄色255:174:0
1500〜1999Wオレンジ255:57:17
2000〜2499W255:0:255
2500〜2999W255:0:0
3000W以上赤+最大輝度⚠ 警告モード255:0:0(輝度100%)

システムの仕組み

本システムは2つのプログラムが連携して動作します。

  1. 電力記録プログラム(home_energy_status_record.py):crontabで1分ごとに実行され、Nature Remo E liteのクラウドAPIから瞬間消費電力などのスマートメーター情報を取得してInfluxDBに記録する
  2. スライムライト制御プログラム(slime_light_control.py):systemdサービスとして常駐し、15秒ごとにInfluxDBから最新の消費電力を取得してLED電球の色を制御する

データの流れは以下のとおりです。

スマートメーター
    ↓ (ECHONET Lite / Bルーター接続)
Nature Remo E lite
    ↓ (Nature Remo クラウドAPI)
[電力記録プログラム] ← crontab 1分ごとに実行
    ↓ (InfluxDB v2 に書き込み)
InfluxDB
    ↑ (15秒ごとに最新値を取得)
[スライムライト制御プログラム] ← systemd サービスとして常駐
    ↓ (SwitchBot API v1.1)
SwitchBot Hub
    ↓
SwitchBot カラー電球 → 色が変わる!

スライムライト制御プログラムが直接Nature Remo APIを呼ばずにInfluxDB経由にしているのは、Nature Remo APIに1時間あたりのAPIコール数制限があるためです。電力記録プログラムが代表して1分ごとにAPIを呼び出しInfluxDBに記録。スライムライト制御プログラムはそこからデータを取得することで、APIの呼び出し回数を最小限に抑えています。

実装のポイント

前回と同じ色のときはAPIを叩かない

SwitchBot APIにも呼び出し回数の制限があります。15秒ごとのループの中で、前回と色が変わっていない場合はAPIを呼ばないようにし、必要最小限のAPI呼び出しに抑えています。

API呼び出しを最小化
色が変わった時だけSwitchBot APIを叩くことで、利用制限に引っかかることなく安定して動作します。1日のAPI呼び出し回数を大幅に削減できます。

照度センサー連動で自動ON/OFF

SwitchBotコンタクトセンサーで部屋の明るさを検知し、部屋が暗くなったら電球も自動でOFFにします。深夜など部屋の照明をすべて消した後も電球だけ光り続けるという不自然な状況を防いでいます。

自然な連動動作
部屋の照明と連動してON/OFFするため、「電球が無駄に光り続ける」という状況が発生しません。コンタクトセンサーがない場合は、この部分のロジックを省略してもシステムは動作します。

3000W超えの「警告演出」

消費電力が3000Wを超えた場合は、赤色に加えて電球の輝度を最大(100%)にする演出を追加しています。通常時の輝度は1%に抑えているため、急に真っ赤に明るくなることで「電力超過警告」として強い視覚的インパクトを生み出しています。

「色+輝度」の二段階演出
3000Wを超えた瞬間に電球が最大輝度の赤になるため、家族全員がすぐに気づきます。エアコン・電子レンジ・IH調理器を同時に使った時などに発動します。

事前準備

Nature Remo API アクセストークンの取得

Nature Remoのアカウントページにアクセスし、「新しいトークンを発行する」からアクセストークンを取得します。取得したトークンは後述のsettings.jsonに設定します。

SwitchBot API トークン・シークレットの取得

SwitchBotアプリの「プロフィール」→「設定」→「アプリバージョン」を10回タップするとデベロッパーモードが有効になります。そこからトークンとクライアントシークレットを取得します。

SwitchBot カラー電球・センサーのデバイスIDの取得

SwitchBot APIのデバイス一覧取得エンドポイントを叩いて、カラー電球とコンタクトセンサーのデバイスIDを確認しておきます。取得したIDはsettings.jsonに設定します。

InfluxDB v2 のセットアップ確認

InfluxDB v2がすでに稼働していることが前提です。電力記録プログラムが remo_e というmeasurementに measured_instantaneous(瞬間消費電力・W)を定期記録していることを確認してください。

実装方法

設定ファイル(settings.json)

{
    "switchbot": {
        "api": "<your-switchbot-token>",
        "secret": "<your-switchbot-secret>",
        "api_url_v11": "https://api.switch-bot.com/v1.1/",
        "device_id": {
            "slime_light_bulb": "<カラー電球のデバイスID>",
            "living_aircon_sensor": "<照度検知用コンタクトセンサーのデバイスID>"
        }
    },
    "remo": {
        "api": "<your-nature-remo-token>",
        "api_url_appliances": "https://api.nature.global/1/appliances",
        "remo_e_no": 0
    }
}

remo_e_no はNature Remo APIのappliances一覧の中でRemo E liteが何番目に返ってくるかを示すインデックスです。0から始まります。環境によって異なるため、一度APIを叩いて確認してください。

電力記録プログラム(home_energy_status_record.py)

Nature Remo E liteのAPIからスマートメーター情報を取得してInfluxDBに記録するプログラムです。このプログラムはcrontabで1分ごとに実行します。

# -*- coding: utf-8 -*-
import sys
import os
import requests
import datetime
from influxdb_client import InfluxDBClient, Point, WritePrecision
from influxdb_client.client.write_api import SYNCHRONOUS

# InfluxDB 接続設定
INFLUXDB_URL    = "http://localhost:8086"
INFLUXDB_TOKEN  = "<your-influxdb-token>"
INFLUXDB_ORG    = "<your-org>"
INFLUXDB_BUCKET = "houseinfo"

# Nature Remo API 設定
REMO_API_TOKEN        = "<your-nature-remo-token>"
REMO_API_URL          = "https://api.nature.global/1/appliances"
REMO_E_INDEX          = 0  # Remo E lite が appliances の何番目か

def fetch_smart_meter_data():
    """Nature Remo E lite API からスマートメーター情報を取得する"""
    headers = {
        'Authorization': 'Bearer ' + REMO_API_TOKEN,
        'accept': 'application/json'
    }
    appliances = requests.get(REMO_API_URL, headers=headers).json()
    props = appliances[REMO_E_INDEX]['smart_meter']['echonetlite_properties']
    return {item['name']: item['val'] for item in props}

def write_to_influxdb(data):
    """取得した電力データを InfluxDB に書き込む"""
    client = InfluxDBClient(url=INFLUXDB_URL, token=INFLUXDB_TOKEN, org=INFLUXDB_ORG)
    write_api = client.write_api(write_options=SYNCHRONOUS)

    point = (
        Point("remo_e")
        .tag("deviceType", "Remo E lite")
        .field("measured_instantaneous",
               int(data['measured_instantaneous']))
        .field("normal_direction_cumulative_electric_energy",
               int(data['normal_direction_cumulative_electric_energy']))
        .time(datetime.datetime.utcnow(), WritePrecision.SECONDS)
    )
    write_api.write(bucket=INFLUXDB_BUCKET, org=INFLUXDB_ORG, record=point)
    client.close()

if __name__ == '__main__':
    try:
        data = fetch_smart_meter_data()
        write_to_influxdb(data)
        print("電力データの記録が完了しました: " + str(data['measured_instantaneous']) + "W")
    except Exception as e:
        print("エラー: " + str(e))
        sys.exit(1)

このプログラムをcrontabに登録して1分ごとに実行するように設定します。

# crontabを編集
crontab -e

# 以下を追記(1分ごとに実行)
* * * * * /usr/bin/python3 /home/<username>/projects/smarthome/core/record/energy/home_energy_status_record.py >> /home/<username>/projects/smarthome/logs/crontab/home_energy_status.log 2>&1

スライムライト制御プログラム(slime_light_control.py)

メインとなるスライムライト制御プログラムです。systemdサービスとして常駐させ、15秒ごとにInfluxDBの電力データを取得してSwitchBotカラー電球の色を制御します。

# -*- coding: utf-8 -*-
import sys
import os
import time
import json
import requests
import hashlib
import hmac
import base64
import uuid
import datetime
from influxdb_client import InfluxDBClient
from influxdb_client.client.query_api import QueryApi

# ---- InfluxDB 接続設定 ----
INFLUXDB_URL    = "http://localhost:8086"
INFLUXDB_TOKEN  = "<your-influxdb-token>"
INFLUXDB_ORG    = "<your-org>"
INFLUXDB_BUCKET = "houseinfo"

# ---- SwitchBot API 設定 ----
SWITCHBOT_TOKEN           = "<your-switchbot-token>"
SWITCHBOT_SECRET          = "<your-switchbot-secret>"
SWITCHBOT_API_URL         = "https://api.switch-bot.com/v1.1/"
SLIME_BULB_DEVICE_ID      = "<カラー電球のデバイスID>"
LIVING_SENSOR_DEVICE_ID   = "<照度センサーのデバイスID>"  # コンタクトセンサー

# ---- スライムのカラー定義(ドラクエモチーフ) ----
SLIME_COLOR = {
    'white':  '255:255:255',  # メタルキング    (~300W未満)
    'blue':   '0:118:255',    # キングスライム  (~500W未満)
    'green':  '36:255:0',     # スライムベホマズン (~1000W未満)
    'yellow': '255:174:0',    # (~1500W未満)
    'orange': '255:57:17',    # (~2000W未満)
    'purple': '255:0:255',    # (~2500W未満)
    'red':    '255:0:0'        # (2500W以上)
}

def get_switchbot_header():
    """SwitchBot API v1.1 用の認証ヘッダーを生成する"""
    nonce  = str(uuid.uuid4())
    t      = int(round(time.time() * 1000))
    string = '{}{}{}'.format(SWITCHBOT_TOKEN, t, nonce)
    sign   = base64.b64encode(
        hmac.new(SWITCHBOT_SECRET.encode('utf-8'),
                 msg=string.encode('utf-8'),
                 digestmod=hashlib.sha256).digest()
    )
    return {
        'Authorization': SWITCHBOT_TOKEN,
        'sign':          str(sign, 'utf-8'),
        't':             str(t),
        'nonce':         nonce,
        'Content-Type':  'application/json; charset: utf8'
    }

def switchbot_command(device_id, command, parameter='default'):
    """SwitchBot デバイスにコマンドを送信する"""
    url  = SWITCHBOT_API_URL + 'devices/' + device_id + '/commands'
    body = {'command': command, 'parameter': parameter, 'commandType': 'command'}
    requests.post(url, headers=get_switchbot_header(), json=body)

def get_latest_power_w():
    """InfluxDB から最新の瞬間消費電力(W)を取得する"""
    client    = InfluxDBClient(url=INFLUXDB_URL, token=INFLUXDB_TOKEN, org=INFLUXDB_ORG)
    query_api = client.query_api()
    query = '''
        from(bucket: "houseinfo")
          |> range(start: -5m)
          |> filter(fn: (r) => r._measurement == "remo_e")
          |> filter(fn: (r) => r._field == "measured_instantaneous")
          |> last()
    '''
    tables = query_api.query(query, org=INFLUXDB_ORG)
    client.close()
    for table in tables:
        for record in table.records:
            return int(record.get_value())
    return 0

def get_latest_brightness():
    """InfluxDB から照度センサーの最新状態を取得する"""
    client    = InfluxDBClient(url=INFLUXDB_URL, token=INFLUXDB_TOKEN, org=INFLUXDB_ORG)
    query_api = client.query_api()
    query = '''
        from(bucket: "houseinfo")
          |> range(start: -5m)
          |> filter(fn: (r) => r._measurement == "contact_sensor")
          |> filter(fn: (r) => r._field == "brightness")
          |> filter(fn: (r) => r.deviceId == "''' + LIVING_SENSOR_DEVICE_ID + '''")
          |> last()
    '''
    tables = query_api.query(query, org=INFLUXDB_ORG)
    client.close()
    for table in tables:
        for record in table.records:
            return record.get_value()
    return 'unknown'

def get_slime_color(watts):
    """消費電力(W)に応じてスライムの色(RGB文字列)を返す"""
    if watts < 300:
        return SLIME_COLOR['white']
    elif watts < 500:
        return SLIME_COLOR['blue']
    elif watts < 1000:
        return SLIME_COLOR['green']
    elif watts < 1500:
        return SLIME_COLOR['yellow']
    elif watts < 2000:
        return SLIME_COLOR['orange']
    elif watts < 2500:
        return SLIME_COLOR['purple']
    else:
        return SLIME_COLOR['red']

def main():
    color_before         = None
    is_over_3000w_before = None
    brightness_before    = None
    is_lighting          = None

    print("スライムライト制御を開始します。")

    while True:
        try:
            # InfluxDB から最新データを取得
            watts      = get_latest_power_w()
            brightness = get_latest_brightness()

            print(datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S')
                  + " | 消費電力: " + str(watts) + "W | 照度: " + str(brightness))

            # ---- 照度の変化に応じて電球を自動 ON/OFF ----
            if brightness != brightness_before:
                if brightness == 'bright':
                    switchbot_command(SLIME_BULB_DEVICE_ID, 'turnOn')
                    is_lighting = True
                    print("電球を点灯しました。")
                else:
                    switchbot_command(SLIME_BULB_DEVICE_ID, 'turnOff')
                    is_lighting = False
                    print("電球を消灯しました。")

            # ---- 消費電力に応じてスライムの色を決定 ----
            is_over_3000w = (watts >= 3000)
            color = get_slime_color(watts)

            # 電球が点灯中かつ前回と状態が変わった場合のみ API を叩く
            color_changed    = (color != color_before)
            warning_changed  = (is_over_3000w != is_over_3000w_before)

            if is_lighting and (color_changed or warning_changed):
                # 電球の色を変更
                switchbot_command(SLIME_BULB_DEVICE_ID, 'setColor', color)
                print("電球色を変更しました: " + color + " (" + str(watts) + "W)")

                # 3000W 超えの場合は輝度を最大にして警告演出
                if warning_changed and is_over_3000w_before is not None:
                    if is_over_3000w:
                        switchbot_command(SLIME_BULB_DEVICE_ID, 'setBrightness', '100')
                        print("警告!3000W超え → 輝度を最大にしました。")
                    else:
                        switchbot_command(SLIME_BULB_DEVICE_ID, 'setBrightness', '1')
                        print("3000W以下に戻りました → 輝度を最小にしました。")

            # 状態を保存(次回比較用)
            color_before         = color
            is_over_3000w_before = is_over_3000w
            brightness_before    = brightness

        except Exception as e:
            print("エラー: " + str(e))

        time.sleep(15)

if __name__ == '__main__':
    main()

systemd サービスファイルの作成

スライムライト制御プログラムをOS起動時から自動で常駐実行するために、systemdサービスとして登録します。

[Unit]
Description=Smarthome Slime Light Control
After=network.target influxdb.service

[Service]
Type=simple
User=<username>
ExecStart=/usr/bin/python3 /home/<username>/projects/smarthome/core/display/energy_saving/slime_light_control.py
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

サービスファイルを作成したら、以下のコマンドで登録・起動します。

# サービスを登録して自動起動を有効化
sudo systemctl daemon-reload
sudo systemctl enable smh-slime-light-control.service

# サービスを起動
sudo systemctl start smh-slime-light-control.service

# 起動状態を確認
sudo systemctl status smh-slime-light-control.service

コードの解説

1. スライムカラーの定義

電球の色はSwitchBot APIの setColor コマンドに R:G:B 形式の文字列を渡すことで指定します。ドラゴンクエストのスライムシリーズのカラーリングを参考に色を選びました。

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'
}

2. 消費電力→色の変換ロジック

消費電力の閾値は家庭によって異なります。我が家では待機電力が約150〜200W程度のため、300Wを最初の境界としています。各家庭の電力使用パターンに合わせて閾値を調整してください。

def get_slime_color(watts):
    if watts < 300:   return SLIME_COLOR['white']   # 待機電力レベル
    elif watts < 500:  return SLIME_COLOR['blue']    # 通常使用
    elif watts < 1000: return SLIME_COLOR['green']   # やや多め
    elif watts < 1500: return SLIME_COLOR['yellow']  # エアコン1台程度
    elif watts < 2000: return SLIME_COLOR['orange']  # エアコン+α
    elif watts < 2500: return SLIME_COLOR['purple']  # 使いすぎ注意
    else:              return SLIME_COLOR['red']      # 危険域

3. 差分チェックによるAPI呼び出し最小化

前回の色・輝度状態を変数に保持しておき、変化があった場合のみSwitchBot APIを呼び出します。これにより、SwitchBot APIのレート制限(1日10,000リクエスト)を大幅に下回る消費量に抑えられます。

# 前回と変化がない場合は API を呼ばない
color_changed   = (color != color_before)
warning_changed = (is_over_3000w != is_over_3000w_before)

if is_lighting and (color_changed or warning_changed):
    switchbot_command(SLIME_BULB_DEVICE_ID, 'setColor', color)

4. SwitchBot API v1.1 の認証ヘッダー生成

SwitchBot API v1.1 ではトークンとシークレットを使ったHMAC-SHA256署名による認証が必要です。リクエストのたびにタイムスタンプとnonceを含む署名を生成します。

def get_switchbot_header():
    nonce  = str(uuid.uuid4())
    t      = int(round(time.time() * 1000))
    string = '{}{}{}'.format(SWITCHBOT_TOKEN, t, nonce)
    sign   = base64.b64encode(
        hmac.new(SWITCHBOT_SECRET.encode('utf-8'),
                 msg=string.encode('utf-8'),
                 digestmod=hashlib.sha256).digest()
    )
    return {
        'Authorization': SWITCHBOT_TOKEN,
        'sign': str(sign, 'utf-8'),
        't': str(t),
        'nonce': nonce,
    }

SwitchBot API v1.0 では Authorization ヘッダーにトークンをそのまま渡すだけでしたが、v1.1 からはHMAC-SHA256による署名が必須になりました。古い記事のコードをそのまま使うと認証エラーになるので注意してください。

動作確認

まずプログラムを直接実行して、コンソールに状態が出力されることを確認します。

python3 /home/<username>/projects/smarthome/core/display/energy_saving/slime_light_control.py

正常に動作している場合、以下のようなログが15秒ごとに出力されます。

スライムライト制御を開始します。
2026/05/23 10:00:00 | 消費電力: 430W | 照度: bright
電球を点灯しました。
電球色を変更しました: 0:118:255 (430W)
2026/05/23 10:00:15 | 消費電力: 435W | 照度: bright
2026/05/23 10:00:30 | 消費電力: 1250W | 照度: bright
電球色を変更しました: 255:174:0 (1250W)

動作が確認できたら、systemdサービスとして登録して常駐起動に切り替えます。ミニPCやRaspberry Piを再起動しても自動的に起動します。

動作確認のコツ
電子レンジ(約1400W)や電気ケトル(約1200W)を使って意図的に電力を増やしてみると、電球の色が変わる様子を簡単に確認できます。

まとめ

消費電力でLED電球の色が変わる「スライム電力計」の実装方法を紹介しました。

  • Nature Remo E liteでスマートメーターの瞬間消費電力を取得
  • InfluxDBを中継してAPIコール数を節約しながらリアルタイム性を維持
  • SwitchBotカラー電球をドラクエのスライムカラーで7段階に色分け
  • 照度センサー連動で自動ON/OFF、3000W超えで警告演出

この仕組みを導入してから、家族が「スライムの色」を意識するようになり、電力の使いすぎに気づいて自然と節電行動をとるようになりました。特に子供が「スライムが赤い!消そう!」と自発的に電気を消してくれるようになったのが一番の成果です。
数字やグラフではなく「色」で伝えるというアプローチは、ITリテラシーに関わらず家族全員に刺さる直感的なインターフェースだと感じています。ぜひ皆さんの家でも試してみてください。

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