1. 概要
SwitchBotWin は、SwitchBot API v1.1 を利用してスマートホームデバイスをWindows PCから一元管理・操作するためのWPFデスクトップアプリケーションである。
項目 内容 フレームワーク WPF(.NET 8.0) 言語 C# 12 アーキテクチャ MVVM(Model-View-ViewModel) バージョン 1.0.0 対象OS Windows 10 / 11 外部依存 System.Security.Cryptography.ProtectedData 8.0.0
2. アプリケーション構成
2.1 ディレクトリ構成
SwitchBotWin/
├── Models/ # データモデル
│ └── Enums/ # 列挙型定義
├── ViewModels/ # ビューモデル(MVVM)
├── Views/ # XAML画面・パネル
├── Services/ # ビジネスロジック・API通信
├── Converters/ # WPFバインディング用値変換
├── Helpers/ # ユーティリティクラス
├── Themes/ # ダーク/ライトテーマ定義
└── Assets/ # 効果音ファイル等
2.2 アーキテクチャ図
graph TD
subgraph View
MW["MainWindow"]
DP["DashboardPanel"]
ACP["AirConditionerPanel"]
TVP["TvPanel"]
LP["LightPanel"]
FP["FanPanel"]
GRP["GenericRemotePanel"]
PDP["PhysicalDevicePanel"]
MEP["MacroEditorPanel"]
SD["SettingsDialog"]
AD["AboutDialog"]
STD["StatsDialog"]
end
subgraph ViewModel
MVM["MainViewModel"]
ACVM["AirConditionerViewModel"]
TVVM["TvViewModel"]
LVM["LightViewModel"]
FVM["FanViewModel"]
GRVM["GenericRemoteViewModel"]
PDVM["PhysicalDeviceViewModel"]
MEVM["MacroEditorViewModel"]
SVM["SettingsViewModel"]
SCVM["SensorCardViewModel"]
end
subgraph Service
API["SwitchBotApiClient"]
DM["DeviceManager"]
MM["MacroManager"]
SM["SettingsManager"]
TM["ThemeManager"]
WM["WindowStateManager"]
SS["SoundService"]
ASM["AcStatusManager"]
end
subgraph External
SBAPI["SwitchBot API v1.1"]
end
MW --> MVM
MVM --> DM
MVM --> MM
MVM --> SM
MVM --> API
API --> SBAPI
DM --> API
MM --> API
3. 認証・セキュリティ
3.1 API認証
SwitchBot API v1.1 のHMAC認証方式を使用する。
項目 内容 認証方式 HMAC-SHA256 署名 必要情報 Open Token、Secret Key ヘッダー Authorization(Token)、sign(HMAC署名)、t(タイムスタンプ)、nonce(UUID)
3.2 認証情報の保存
項目 内容 暗号化方式 Windows DPAPI(DataProtectionScope.CurrentUser) 保存形式 Base64エンコードされた暗号文をJSON形式で保存 保存先 %APPDATA%/SwitchBotWin/settings.json書き込み方式 アトミック書き込み(一時ファイル → リネーム)
3.3 接続テスト
設定ダイアログにて、入力したToken/Secretで一時的なAPIクライアントを生成し、デバイス一覧APIを呼び出すことで接続確認を行う。テスト成功後にのみ保存ボタンが有効化される。
4. デバイス管理
4.1 対応デバイス分類
4.1.1 赤外線リモコンデバイス(InfraredRemoteDevice)
SwitchBot Hub経由で制御される赤外線リモコン仮想デバイス。
リモコン種別 API値 専用ViewModel 操作 エアコン Air ConditionerAirConditionerViewModel電源ON/OFF、温度設定(16〜30℃)、モード切替、風量調整、一括送信 テレビ TVTvViewModel電源ON/OFF、CH切替、音量、ミュート、チャンネル番号直接入力(1〜12) 照明 LightLightViewModel電源ON/OFF、明るさUP/DOWN、色温度UP/DOWN 扇風機 FanFanViewModel電源ON/OFF、風量3段階、スイング、タイマー DVD DVDGenericRemoteViewModel電源ON/OFF + メディアプレーヤーコマンド セットトップボックス Set Top BoxGenericRemoteViewModel同上 ストリーマー StreamerGenericRemoteViewModel同上 スピーカー SpeakerGenericRemoteViewModel電源ON/OFF + 音量/ミュート プロジェクター ProjectorGenericRemoteViewModel電源ON/OFF カメラ CameraGenericRemoteViewModel電源ON/OFF 空気清浄機 Air PurifierGenericRemoteViewModel電源ON/OFF 給湯器 Water HeaterGenericRemoteViewModel電源ON/OFF その他 OthersGenericRemoteViewModel電源ON/OFF
4.1.2 物理デバイス(SwitchBotDevice)
SwitchBotの物理製品。制御デバイスとデータデバイスに分類される。
制御デバイス:
Bot(スイッチ操作)
Curtain / Curtain 3(カーテン開閉)
Smart Lock / Smart Lock Pro(施錠/解錠)
Plug / Plug Mini(JP/US)(電源プラグ制御)
Robot Vacuum Cleaner S1 / S1 Plus / S10(掃除機)
Hub 2 / Hub 3(ハブ+センサー)
データデバイス(センサー):
Meter / MeterPlus / WoIOSensor(温湿度計)
MeterPro / MeterPro(CO2)(温湿度+CO2計)
Hub 2 / Hub 3(温湿度+照度センサー)
Motion Sensor(人感センサー)
Contact Sensor(開閉センサー)
4.2 デバイスキャッシュ
項目 内容 保存先 %APPDATA%/SwitchBotWin/device_cache.json保存内容 物理デバイスリスト、IRリモコンリスト、最終更新日時、デバイス表示順序、カテゴリ表示順序 更新タイミング API取得成功時、デバイス状態変更時(エアコン設定送信等) マージ戦略 API更新時に既存キャッシュの最終状態(LastState)を新データにマージ
4.3 デバイス表示順序
ユーザーがドラッグ&ドロップで並び替えた順序はカテゴリごとに保存される。
カテゴリキー 内容 remotesIRリモコンデバイス sensorsセンサーデバイス physical制御デバイス macrosマクロ systemシステム情報
5. エアコン制御
5.1 操作仕様
操作 コマンド パラメータ 電源ON turnOndefault電源OFF turnOffdefault一括設定 setAll温度,モード,風量,電源 (例: 26,2,1,on)
5.2 運転モード(AcMode)
enum値 モード名 備考 1 自動 デフォルト 2 冷房 – 3 除湿 – 4 送風 温度設定無効 5 暖房 –
5.3 風量(FanSpeed)
5.4 温度範囲
最小: 16℃
最大: 30℃
デフォルト: 26℃
Math.Clamp で範囲制限
5.5 エアコン状態管理
最後に送信したエアコンの設定(温度、モード、風量、電源)を以下の2箇所で永続化する。
デバイスキャッシュ : DeviceManager.UpdateLastState() で device_cache.json 内の LastState を更新
ステータステキスト : AcStatusManager で ac_status.txt に表示用テキストを保存
6. マクロ機能
6.1 概要
複数のデバイスコマンドを順次実行する自動化機能。条件分岐(センサー値判定)と待機ステップをサポートする。
6.2 マクロモデル(Macro)
プロパティ 型 説明 IdstringGUID(一意識別子) Namestring表示名(デフォルト:「新しいマクロ」) Iconstringアイコン絵文字(デフォルト: ⚡) Descriptionstring説明文 StepsList<MacroStep>ステップリスト IsEnabledbool有効/無効フラグ CreatedAt / UpdatedAtDateTime作成/更新日時(UTC)
6.3 マクロステップ種別(MacroStepType)
種別 説明 CommandデバイスにAPIコマンドを送信 Delay指定時間(ミリ秒)待機 Conditionセンサー値を条件判定し、不成立時にスキップまたは中断
6.4 条件分岐(MacroCondition)
プロパティ 説明 DeviceId判定対象のセンサーデバイスID Property判定対象プロパティ(temperature、humidity、moveDetected、openState等) Operator比較演算子(==、!=、>、<、>=、<=) Value比較値 Action条件不成立時の動作(Skip: 次のConditionまでスキップ / Abort: マクロ中断)
6.5 マクロ実行フロー
flowchart TD
Start["マクロ実行開始"] --> Validate["バリデーション:参照デバイスの存在確認"]
Validate -->|NG| Error["エラーメッセージ返却"]
Validate -->|OK| Loop["ステップ順次実行ループ"]
Loop --> Type{"ステップ種別"}
Type -->|Command| Send["APIにコマンド送信"]
Send --> Sound["効果音再生"]
Sound --> Next["次のステップへ"]
Type -->|Delay| Wait["指定時間待機"]
Wait --> Next
Type -->|Condition| Eval["センサー値取得&条件判定"]
Eval -->|成立| Next
Eval -->|不成立 + Skip| SkipToNext["次のConditionまでスキップ"]
Eval -->|不成立 + Abort| Abort["マクロ中断"]
Next -->|残りあり| Loop
Next -->|全完了| Done["完了"]
6.6 マクロ保存
項目 内容 保存先 %APPDATA%/SwitchBotWin/macros.json形式 MacroStore(macros プロパティに全マクロを格納)保存タイミング 作成/更新/削除時に自動保存(デバウンス付き) 排他制御 SemaphoreSlim によるロック
6.7 仮想マクロ実行
保存されていない編集中のマクロデータを使用して直接実行する機能。マクロエディタのテスト実行で使用される。
7. センサー監視
7.1 対応センサー情報
デバイス種別 取得可能データ Meter / MeterPlus / WoIOSensor 温度、湿度、バッテリー MeterPro 温度、湿度、バッテリー MeterPro(CO2) 温度、湿度、CO2濃度、バッテリー Hub 2 / Hub 3 温度、湿度、照度レベル Motion Sensor 動体検知状態、明るさ、バッテリー Contact Sensor 開閉状態、明るさ、バッテリー
7.2 自動更新
項目 内容 更新間隔 10分(DispatcherTimer) 初回取得 アプリ起動時にAPIから全センサーのステータスを取得 手動更新 更新ボタン押下時に全デバイス+センサーを再取得
7.3 ダッシュボード表示
SensorCardViewModel としてカード形式で表示
温度・湿度・明るさ・CO2・バッテリーを絵文字付きテキストで表示
SensorDisplayHelper でセンサー値のフォーマット・日本語変換を行う
8. ダッシュボード
8.1 構成
ダッシュボードはデバイス未選択時に表示されるホーム画面で、以下のセクションから成る。
セクション 内容 リモコン 登録済みIRリモコンデバイスのカード一覧 センサー センサーカード(温湿度・CO2・バッテリー等) デバイス 物理デバイス(Bot、カーテン、ロック、プラグ等) マクロ マクロカード(ホバー時に実行/編集ボタン表示) システム 最終更新時刻、API残量、エアコン直近送信状態
8.2 カテゴリ順序管理
各セクションの表示順序はドラッグ&ドロップで変更可能
編集モード(IsEditMode)のON/OFFで切り替え
順序は device_cache.json 内の categoryOrder に保存
8.3 各セクションの折りたたみ
左ペインとダッシュボードそれぞれで独立した展開/折りたたみ状態を保持する。
9. UI仕様
9.1 メイン画面構成
ライトモード
ダークモード
9.2 フィルター機能
左ペインのフィルターは接続中デバイスに基づいて動的に構築される。
フィルター 表示対象 全て 全デバイス表示 エアコン IRリモコン(Air Conditioner) テレビ IRリモコン(TV) 照明 IRリモコン(Light) 扇風機 IRリモコン(Fan) DVD / セットトップボックス / ストリーマー / スピーカー 各IRリモコン種別 その他 主要種別以外のIRリモコン 温湿度計 Meter系センサー 人感センサー Motion/Contactセンサー ボット / カーテン / ロック / プラグ / ハブ 各物理デバイス マクロ マクロのみ
9.3 テーマ
項目 内容 テーマ検出 Windowsレジストリ(AppsUseLightTheme)からOS設定を読み取り 切り替え方式 ResourceDictionary の動的差し替えリアルタイム追従 SystemEvents.UserPreferenceChanged でOS変更を監視タイトルバー DWM API(DwmSetWindowAttribute)でダークモード対応 テーマファイル DarkTheme.xaml / LightTheme.xaml
9.4 ウィンドウ状態の保存・復元
保存項目 デフォルト値 位置(Left, Top) 100, 100 サイズ(Width, Height) 1000 × 650 最大化状態 false 左ペイン幅 260px 選択フィルター 「全て」 選択デバイスID null 各セクション展開状態 全てtrue
保存先: %APPDATA%/SwitchBotWin/windowstate.json
9.5 効果音
項目 内容 ファイル Assets/pi.wav再生タイミング コマンド送信成功時 再生方式 SoundPlayer.Play()(非同期、UIノンブロッキング)キャッシュ SoundPlayerインスタンスを初回生成後に再利用
9.6 ドラッグ&ドロップ
ダッシュボード : カテゴリセクションの並び替え
左ペイン : カテゴリ内デバイスの並び替え
DragScrollBehavior: ドラッグスクロールのUX改善(ドラッグ閾値、編集モード連携)
10. API通信
10.1 エンドポイント
操作 メソッド エンドポイント デバイス一覧取得 GET /v1.1/devicesコマンド送信 POST /v1.1/devices/{deviceId}/commandsステータス取得 GET /v1.1/devices/{deviceId}/status
10.2 リトライ機構
項目 内容 最大リトライ回数 3回 バックオフ方式 エクスポネンシャルバックオフ リトライ対象 HttpRequestException、TaskCanceledException、HTTPステータス 429/500/502/503/504
10.3 レート制限管理
項目 内容 日次上限 10,000回 ヘッダー読み取り X-RateLimit-Remaining、X-RateLimit-Limitローカルカウンター API成功時にインクリメント、日付変更でリセット 永続化ファイル %APPDATA%/SwitchBotWin/api_call_count.json警告色 残り ≤ 100: 赤、残り ≤ 500: 黄
11. データ永続化
11.1 保存ファイル一覧
全ファイルは %APPDATA%/SwitchBotWin/ 配下に保存される。
ファイル名 内容 管理クラス settings.jsonDPAPI暗号化済みAPI認証情報 SettingsManagerdevice_cache.jsonデバイス一覧・表示順序・最終状態 DeviceManagermacros.jsonマクロ定義 MacroManagerwindowstate.jsonウィンドウ位置・サイズ・展開状態 WindowStateManagerapi_call_count.jsonAPI呼び出しカウンター SwitchBotApiClientac_status.txtエアコン直近送信ステータス AcStatusManager
11.2 書き込み方式
ファイル破損防止のため、アトミック書き込み(一時ファイル作成 → File.Move でリネーム)を採用。
12. ダイアログ
12.1 設定ダイアログ(SettingsDialog)
SwitchBot APIの認証情報(Token/Secret)を設定する。
操作 説明 接続テスト 入力したToken/Secretでデバイス一覧APIを呼び出しテスト 保存 テスト成功後にDPAPI暗号化して保存
12.2 バージョン情報ダイアログ(AboutDialog)
アプリケーションのバージョン情報を表示する。
12.3 詳細統計ダイアログ(StatsDialog)
API使用状況、デバイス統計、センサー情報などの詳細データを閲覧できる。
13. コンバーター一覧
コンバーター 機能 BoolToVisibilityConverterbool → Visibility 変換InverseBoolConverterbool の反転InverseBoolToVisibilityConverterbool 反転 → VisibilityEnumToBoolConverterenum 値と bool の相互変換EqualityConverter値の等価比較 → bool NullToFalseConverternull → false 変換RemoteTypeToIconConverterリモコン種別 → アイコン文字列 StringEqualityMultiConverter複数文字列の等価比較
14. エラーハンドリング
14.1 API通信エラー
SwitchBotApiException: API固有エラー(HTTPステータスコード付き)
HTTPステータス別のエラーメッセージ生成
ステータスバーにエラーメッセージを表示
14.2 ファイルI/Oエラー
全てのファイル操作は try-catch でラップし、失敗時はデフォルト値を返す/無視する設計。アプリケーションのクラッシュを防止する。
14.3 マクロ実行時バリデーション
参照デバイスの存在確認(削除されたデバイスを検知)
キャンセルトークン対応(実行中のキャンセル可能)
ステップ単位のエラーハンドリング
15. テスト
15.1 テスト構成
テストプロジェクトは Tests/ ディレクトリに配置され、[InternalsVisibleTo("Tests")] により内部メンバーへのアクセスが許可されている。
16. 起動・終了フロー
16.1 起動フロー
flowchart TD
A["アプリケーション起動"] --> B["設定ファイル読み込み"]
B -->|設定なし| C["設定ダイアログ表示"]
B -->|設定あり| D["APIクライアント初期化"]
C -->|保存成功| D
D --> E["テーマ初期化(OS設定読み取り)"]
E --> F["キャッシュから同期復元(InitializeFromCache)"]
F --> G["ウィンドウ状態復元"]
G --> H["メインウィンドウ表示"]
H --> I["非同期初期化(InitializeAsync)"]
I --> J["APIからデバイス一覧取得"]
J --> K["センサーステータス取得"]
K --> L["定期更新タイマー開始(10分)"]
16.2 終了フロー
ウィンドウ状態の保存(位置・サイズ・選択状態・展開状態)
APIコールカウンターの保存
テーマ監視の停止
タイマーの停止
リソースの解放(IDisposable)