掃除ロボットを不在時に稼働する

SwitchBot K10+という型落ちのお掃除ロボットを買った。

朝起床前に稼働するようにスケジュールしたところ、朝起きると一度掃除機をかけた状態になっているので大変気分がいい。

せっかく自動で掃除してくれるのに1日に1回しか動かさないのでは少しもったいない気がするので、家に誰もいないときは自動で掃除するようにしたい。

調べてみると公式のSwitchBotアプリでは自分が家を離れたらGPSで検知してデバイスを動かすことはできるけど、複数人が家を離れるというシナリオには対応していないようだった。


SwitchBotはAPIを公開してるので、なんらかの方法で家に誰もいないことがわかれば、APIから掃除ロボットを稼働できそうだと思った。

家族全員分のiPhoneがルーターに接続されているかをarp-scanで確認し、全てのiPhoneが接続されていない場合、SwitchBotのAPIをコールして掃除ロボットを稼働させるスクリプトを定期実行することにした。それが一番簡単そうなので。

iPhoneはMACアドレスをランダムに変えるそうなので、固定する必要あり。

iPhoneの設定 > Wi-Fi > 接続しているルーターのiアイコンをタップ > プライベートWiFiアドレスをオフ。


サーバーは電気代が安いこと、すでに持っていて買う必要がないということから、Raspberry Pi2を使うことにした。約10年前に買ってから、特に利用用途が見つからずにしまい込んでいた。当時5000円くらいで買えたように記憶している。


Raspberry Piの設定

久しぶりに電源を入れるとOSが起動しなかったのでOSのインストールから。他のディストリビューション同様、Raspberry Pi Imagerというものがあり、OSのダウンロードからSDへ書き込みまでやってくれる。

Raspberry Pi Imagerは公式サイトからもダウンロードできるが、Fedoraのターミナルからインストールできるようだったのでそちらを利用した。

書き込みが終わったらSDカード、HDMIケーブル、キーボード、マウスをRaspberry Piに接続してしばらく待つ。リージョン、ユーザーネーム、パスワード、デフォルトブラウザなどの初期設定を聞かれるので言われるがままに進める。その他にはIPアドレスの固定、FireWall設定、SSH有効化、SSH接続用のキーの生成をしておく。


スクリプトの準備

次に掃除ロボットのdevice IDを取得する。Raspberry PiにjqをインストールしてSwithcBotのAPIをcurl。

TOKENはSwitchBotアプリ > プロフィール > 設定 > 基本データ > 開発者向けオプションで取得する。開発者向けオプションはアプリバージョンを連続でタップする。SwitchBot公式ブログと実際のアプリの画面に少し差異あり。

curl -s \
-H "Authorization: SWITCHBOT_TOKEN" \
-H "Content-Type: application/json" \
https://api.switch-bot.com/v1.1/devices | jq .

デバイスリストがjsonで返ってくるので掃除ロボットのdevice idをメモする。


次にスクリプトを書く。Raspberry Pi2ではPythonよりもシェルスクリプトの方が軽快に動くような気がしたものの、自分はシェルスクリプトがまともに書けないのでChatGPTに書いてもらった。

最終的にこのファイルを5分ごとに実行することになるんだけど、以下のような場合にはスタートさせなくていいかなと思った。

  1. 既に運転中の場合
  2. 掃除が終わった後、ステータスが在宅→外出に変わっていない場合


そのため、

deviceのstatusをチェックしてcleaning以外の場合のみスタートさせる。

last_state.txtという別ファイルに在宅状態を記録し、HOMEからAWAYに変わった場合だけスタートさせる。

また、iPhoneがarp-scanに反応しない場合があり誤作動するので、arp-scanで3回連続MACアドレスが見つからない場合だけスタートさせるようにした。

掃除モードも指定できるけど、今回は指定しなかった。


vacuum.sh

#!/bin/bash

HOUR=$(date +%H)
if [ "$HOUR" -lt 9 ] || [ "$HOUR" -ge 17 ]; then
echo "⏸️ 実行時間外 ($HOUR 時)"
exit 0
fi

# === 設定 ===
TOKEN="SWITCHBOT_TOKEN"
DEVICE_ID="DEVICE_ID" # K10+ の deviceId
MAC_LIST=("aa:bb:cc:dd:ee:ff" "gg:hh:ii:jj:kk:ll") # 家族スマホのMACアドレス
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
STATE_FILE="$SCRIPT_DIR/last_state.txt"

# === 関数 ===
is_home() {
local tries=3
for mac in "${MAC_LIST[@]}"; do
local found=false
for i in $(seq 1 $tries); do
if sudo arp-scan --localnet 2>/dev/null | grep -iq "$mac"; then
echo "✅ $mac detected (try $i/$tries)"
found=true
break
else
echo "⚠️ $mac not found (try $i/$tries)"
sleep 1
fi
done
if [ "$found" = true ]; then
return 0 # 誰か見つかった → HOME
fi
done
return 1 # 全員いなかった → AWAY
}

get_status() {
curl -s \
-H "Authorization: $TOKEN" \
-H "Content-Type: application/json" \
"https://api.switch-bot.com/v1.1/devices/$DEVICE_ID/status" \
| jq -r '.body.workingStatus'
}

start_vacuum() {
curl -s -X POST "https://api.switch-bot.com/v1.1/devices/$DEVICE_ID/commands" \
-H "Authorization: $TOKEN" \
-H "Content-Type: application/json" \
-d '{"command":"start","parameter":"default","commandType":"command"}'
}

# === 今の状態を判定 ===
if is_home; then
current="HOME"
echo "🏠 家に誰かいる"
else
current="AWAY"
echo "🚶 全員外出中"
fi

# === 前回の状態を読み込み ===
last="UNKNOWN"
[ -f "$STATE_FILE" ] && last=$(cat "$STATE_FILE")

# === 状態変化をチェック ===
if [ "$last" = "HOME" ] && [ "$current" = "AWAY" ]; then
echo "🚀 状態変化: HOME → AWAY"
status=$(get_status)
echo "📡 掃除機ステータス: $status"

if [ "$status" != "cleaning" ]; then
echo "✅ 掃除開始!"
start_vacuum
else
echo "⏸️ すでに掃除中なのでスキップ"
fi
else
echo "ℹ️ 状態変化なし ($last → $current)"
fi

# === 今回の状態を保存 ===
echo "$current" > "$STATE_FILE"

エラー処理していない。


arp-scanでルーターに接続しているデバイスをスキャンするのでインストールが必要。

sudo apt install arp-scan


vacuum.shに実行権限をつける。

chmod +x vacuum.sh

この時点でiPhoneのWiFIをON・OFFして、手元でvacuum.shを走らせるとiPhoneがWiFiに接続されていない場合だけ掃除ロボットを運転開始させることができた。


arp-scapにsu権限が必要なので、パスワードをバイパス出来るよう設定する。

sudo visudo

以下を書き足す。

USERNAME ALL=(ALL) NOPASSWD: /usr/bin/arp-scan


5分間隔でvacuum.shを実行するスケジューラーを設定する。

systemdのサービスを作る。

sudo nano /etc/systemd/system/vacuum.service

vacuum.service

[Unit]
Description=SwitchBot Vacuum Trigger Script

[Service]
Type=oneshot
ExecStart=/home/USERNAME/scripts/vacuum.sh
User=USERNAME
WorkingDirectory=/home/USERNAME/scripts


systemd timerを作る。

sudo nano /etc/systemd/system/vacuum.timer

vacuum.timer

[Unit]
Description=Run vacuum.sh every 5 minutes

[Timer]
OnCalendar=*:0/5
Unit=vacuum.service
Persistent=true

[Install]
WantedBy=timers.target

ここで9時から17時の間、5分間隔で実行としたかった。色々試したけどうまくいかず。

結局5分間隔という部分だけここに書き、9時から17時の間の部分はvacuum.shの冒頭で処理することにした。


systemd設定を反映。

sudo systemctl daemon-reload
sudo systemctl enable --now vacuum.timer

これで5分に1度vacuum.shが走る。


ログはjournalctlで見るとのこと。

journalctl -u vacuum.service -n 50


しばらく様子見。


Raspberry Pi OS: https://www.raspberrypi.com/software/

SwitchBot API: https://github.com/OpenWonderLabs/SwitchBotAPI

SwitchBotのTOKEN取得: https://support.switch-bot.com/hc/ja/articles/12822710195351-%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%81%AE%E5%8F%96%E5%BE%97%E6%96%B9%E6%B3%95