スマートホームガイド
Matter、AI家電、音声アシスタントを活用した次世代スマートホームの構築と技術を解説する
スマートホームガイド
Matter、AI家電、音声アシスタントを活用した次世代スマートホームの構築と技術を解説する
この章で学ぶこと
- スマートホームプロトコル — Matter、Thread、Zigbee、Wi-Fi の違いと選び方
- AI家電の進化 — 音声アシスタント、AIカメラ、予測制御の技術基盤
- 実践的構築 — Home Assistant を中心としたスマートホームシステムの設計と自動化
前提知識
このガイドを読む前に、以下の知識があると理解が深まります:
- 基本的なプログラミングの知識
- 関連する基礎概念の理解
- ロボティクスガイド の内容を理解していること
1. スマートホームの全体像
スマートホームのレイヤー構造
+-----------------------------------------------------------+
| スマートホーム アーキテクチャ |
+-----------------------------------------------------------+
| |
| +----------------------------------------------------+ |
| | アプリケーション層 | |
| | Apple Home / Google Home / Alexa / Home Assistant | |
| | 自動化ルール、シーン、音声制御 | |
| +----------------------------------------------------+ |
| | |
| +----------------------------------------------------+ |
| | プロトコル層 | |
| | Matter / HomeKit / Google Home API / Alexa Skills | |
| +----------------------------------------------------+ |
| | |
| +----------------------------------------------------+ |
| | 通信層 | |
| | Thread / Wi-Fi / Zigbee / Z-Wave / Bluetooth LE | |
| +----------------------------------------------------+ |
| | |
| +----------------------------------------------------+ |
| | デバイス層 | |
| | 照明 / サーモスタット / カメラ / ドアロック / センサー | |
| +----------------------------------------------------+ |
+-----------------------------------------------------------+
Matter の登場による統一
【Matter 以前】 【Matter 以後】
+--------+ +--------+ +------+ +----------------------------+
| HomeKit| | Google | | Alexa| | Matter |
| only | | only | | only | | (Apple + Google + Amazon |
+--------+ +--------+ +------+ | + Samsung + ...) |
| | | +----------------------------+
v v v |
一部の 一部の 一部の ほぼ全ての対応デバイスが
デバイス デバイス デバイス 全プラットフォームで動作
スマートホームの市場動向と進化
スマートホーム市場は2025年時点で約1,500億ドル規模に達し、年間成長率20%以上で拡大を続けている。この成長を牽引するのは3つの要因である。
- Matter規格の普及: 2022年に最初のバージョンがリリースされて以来、対応デバイスが急速に増加。2025年末時点で1,000以上の認定デバイスが市場に出ている。
- エッジAIの進化: NPU搭載デバイスの低価格化により、クラウドに依存しないローカルAI処理が可能になった。
- エネルギー価格の上昇: 電力コスト削減のため、AIによるエネルギー最適化への需要が増加。
【スマートホーム進化の4段階】
Stage 1: リモコン代替期(2014-2018)
├── スマホから家電を操作するだけ
├── Wi-Fi接続の単体デバイス(Philips Hue、TP-Link)
└── 音声アシスタント初期(Echo第1世代: 2014年)
Stage 2: 自動化期(2018-2022)
├── IF-THEN ルールによる自動化(IFTTT、Alexa Routines)
├── シーン管理(「おやすみ」で全照明OFF + ドアロック)
└── 各エコシステムの囲い込み競争
Stage 3: AI統合期(2022-2025)
├── Matter による相互運用性の実現
├── LLM ベースの自然言語制御
├── 行動予測による先回り自動化
└── ローカルAI処理(NPU、Coral)
Stage 4: アンビエントAI期(2025-)
├── 環境が自動的に居住者に適応
├── マルチモーダルセンシング(映像+音声+環境)
├── デジタルツインによるシミュレーション最適化
└── ヘルスケア統合(睡眠、ストレス、活動量)
2. 通信プロトコル比較
プロトコル比較表
| プロトコル | 周波数帯 | 通信距離 | 消費電力 | 速度 | メッシュ | 主な用途 |
|---|---|---|---|---|---|---|
| Wi-Fi | 2.4/5/6 GHz | 30-50m | 高 | 高速 | 非対応 | カメラ、ディスプレイ |
| Thread | 2.4 GHz | 10-30m | 非常に低 | 中速 | 対応 | センサー、照明 |
| Zigbee | 2.4 GHz | 10-20m | 非常に低 | 低速 | 対応 | センサー、スイッチ |
| Z-Wave | 900 MHz | 30-100m | 低 | 低速 | 対応 | ドアロック、センサー |
| Bluetooth LE | 2.4 GHz | 10-30m | 非常に低 | 低速 | 対応(Mesh) | 近距離小型デバイス |
| Matter | 上記の上位層 | プロトコル依存 | プロトコル依存 | - | Thread経由 | 統一規格 |
Thread ネットワーク構造
+-----------------------------------------------------------+
| Thread メッシュネットワーク |
+-----------------------------------------------------------+
| |
| +------+ +------+ +------+ |
| |Border|--- Wi-Fi --|Router|--- Wi-Fi --|Border| |
| |Router| | | |Router| |
| +--+---+ +--+---+ +--+---+ |
| | | | |
| Thread Thread Thread |
| mesh mesh mesh |
| | | | |
| +--+---+ +------+ +--+---+ +------+ +--+---+ |
| | 照明 |--| 温度 |--| 照明 |--|ドアロック|--| 温度 | |
| | | |センサー| | | | | |センサー| |
| +------+ +------+ +------+ +------+ +------+ |
| |
| Border Router: Thread ←→ Wi-Fi/Ethernet のブリッジ |
| (Apple TV, Google Nest Hub, HomePod mini が対応) |
+-----------------------------------------------------------+
Thread プロトコルの詳細技術
Thread は IEEE 802.15.4 上に構築された IPv6 ベースのメッシュネットワーキングプロトコルである。従来の Zigbee と同じ物理層を使用するが、ネットワーク層以上が大きく異なる。
【Thread プロトコルスタック】
+-------------------------------------------+
| Application Layer (Matter / CoAP) |
+-------------------------------------------+
| UDP / TCP |
+-------------------------------------------+
| IPv6 (6LoWPAN 圧縮) |
+-------------------------------------------+
| Mesh Link Establishment (MLE) |
| ルーティング: RLOC16 ベース |
+-------------------------------------------+
| IEEE 802.15.4 MAC |
| AES-CCM-128 暗号化 |
+-------------------------------------------+
| IEEE 802.15.4 PHY |
| 2.4 GHz, 250 kbps |
+-------------------------------------------+
Thread ネットワークのノードには以下の役割がある。
| ノードタイプ | 役割 | 常時稼働 | 中継能力 |
|---|---|---|---|
| Leader | ネットワーク管理、パーティション統合 | はい | はい |
| Router | パケット中継、子ノード管理 | はい | はい |
| REED (Router-Eligible End Device) | 必要時にRouterに昇格 | はい | 昇格後 |
| End Device (SED/MED) | 末端デバイス、中継なし | MED:はい / SED:間欠 | なし |
| Border Router | Thread ←→ Wi-Fi/Ethernet ブリッジ | はい | はい |
# OpenThread を使った Thread ネットワーク情報取得例
import openthread
def analyze_thread_network(interface="wpan0"):
"""Thread ネットワークの状態を分析"""
ot = openthread.OpenThread(interface)
# ネットワーク情報
network_info = {
"network_name": ot.get_network_name(),
"channel": ot.get_channel(),
"panid": hex(ot.get_panid()),
"extended_panid": ot.get_extended_panid().hex(),
"mesh_local_prefix": str(ot.get_mesh_local_prefix()),
}
# ノード情報
node_info = {
"role": ot.get_role(), # leader, router, child, detached
"rloc16": hex(ot.get_rloc16()),
"router_id": ot.get_router_id(),
"partition_id": ot.get_partition_id(),
}
# 隣接ノード一覧
neighbors = ot.get_neighbor_table()
for neighbor in neighbors:
print(f" Neighbor RLOC16: {hex(neighbor.rloc16)}")
print(f" Role: {'Router' if neighbor.is_router else 'Child'}")
print(f" Link Quality: {neighbor.link_quality_in}/3")
print(f" Age: {neighbor.age}s")
print(f" RSSI: {neighbor.average_rssi} dBm")
# ルーティングテーブル
router_table = ot.get_router_table()
print(f"\nRouter Table ({len(router_table)} entries):")
for router in router_table:
print(f" Router ID {router.router_id}: "
f"RLOC16={hex(router.rloc16)}, "
f"Next Hop={router.next_hop}, "
f"Path Cost={router.path_cost}")
return network_info, node_infoZigbee と Thread の移行戦略
既存の Zigbee デバイスを所有するユーザーにとって、Thread への移行は重要な検討事項である。
【Zigbee → Thread 移行パス】
パターン A: Bridge 経由(推奨)
+-------------------+ +------------------+ +--------+
| Zigbee デバイス群 | --> | Zigbee-Matter | --> | Matter |
| (Hue, IKEA等) | | Bridge | | 統合 |
+-------------------+ | (Hue Bridge v2) | +--------+
+------------------+
パターン B: 段階的置換
Phase 1: 新規購入は Thread/Matter 対応のみ
Phase 2: 故障・寿命時に Thread デバイスへ交換
Phase 3: 3-5年で完全移行
パターン C: 併用(コスト重視)
+-------------------+ +------------------+
| Zigbee デバイス | --> | Zigbee2MQTT | --> Home Assistant
+-------------------+ +------------------+ ↑
+-------------------+ +------------------+ |
| Thread デバイス | --> | Thread Border | -------+
+-------------------+ | Router |
+------------------+
3. Matter プロトコル
Matterの技術構造
+-----------------------------------------------------------+
| Matter プロトコル |
+-----------------------------------------------------------+
| |
| +----------------------------------------------------+ |
| | Application Layer | |
| | デバイスタイプ定義(照明、サーモスタット、ドアロック) | |
| | クラスタ(On/Off, Level Control, Color Control) | |
| +----------------------------------------------------+ |
| |
| +----------------------------------------------------+ |
| | Interaction Model | |
| | Read / Write / Subscribe / Invoke | |
| +----------------------------------------------------+ |
| |
| +----------------------------------------------------+ |
| | Security Layer | |
| | CASE (Certificate Authenticated Session) | |
| | PASE (Passcode Authenticated Session) | |
| +----------------------------------------------------+ |
| |
| +----------------------------------------------------+ |
| | Transport Layer | |
| | IPv6 over Wi-Fi / Thread / Ethernet | |
| +----------------------------------------------------+ |
+-----------------------------------------------------------+
Matter のデバイスタイプとクラスタ
Matter はデバイスの機能を「クラスタ」という単位で標準化している。各デバイスタイプは必須クラスタとオプショナルクラスタの組み合わせで定義される。
| デバイスタイプ | Device Type ID | 必須クラスタ | オプショナルクラスタ |
|---|---|---|---|
| On/Off Light | 0x0100 | On/Off, Level Control | Color Control, Scenes |
| Dimmable Light | 0x0101 | On/Off, Level Control | Color Control |
| Color Temperature Light | 0x010C | On/Off, Level, Color Control | Scenes |
| Thermostat | 0x0301 | Thermostat, Fan Control | Humidity Measurement |
| Door Lock | 0x000A | Door Lock | Alarms, Time Sync |
| Window Covering | 0x0202 | Window Covering | Scenes |
| Occupancy Sensor | 0x0107 | Occupancy Sensing | Illuminance |
| Temperature Sensor | 0x0302 | Temperature Measurement | - |
| Humidity Sensor | 0x0307 | Relative Humidity | - |
| Contact Sensor | 0x0015 | Boolean State | - |
Matter のコミッショニング(ペアリング)プロセス
【Matter デバイスのコミッショニングフロー】
1. QRコードスキャン / NFC タッチ| スマートフォン | --> | デバイスQRコード |
|---|---|---|
| (Commissioner) | (Commissionee) |
2. PASE(パスコード認証セッション確立)
Commissioner ←──── SPAKE2+ ────→ Commissionee
※ QRコードからセットアップペイロードを抽出
※ Discriminator + Passcode で認証
3. 証明書チェーン検証
Commissionee → DAC (Device Attestation Certificate)
→ PAI (Product Attestation Intermediate)
→ PAA (Product Attestation Authority)
※ DCL (Distributed Compliance Ledger) で検証
4. NOC(Network Operating Certificate)発行
Commissioner → Root CA → NOC → Commissionee
※ Fabric ID + Node ID を付与
5. ACL(Access Control List)設定
Adminが他のコントローラにもアクセス権を付与可能
※ Multi-Admin: 最大5つのFabricに同時参加可能
6. CASE セッション確立(運用時)
Controller ←── Sigma1/Sigma2/Sigma3 ──→ Device
※ NOC ベースの相互認証
※ AES-CCM-128 暗号化通信
コード例1: Matter デバイスの制御(概念コード)
# Matter デバイスの制御例(Python chip-tool ライクなAPI)
from matter_sdk import MatterController, clusters
async def control_smart_home():
controller = MatterController()
# デバイスの検出とペアリング
devices = await controller.discover()
print(f"検出されたデバイス: {len(devices)}台")
for device in devices:
print(f" - {device.name} (Type: {device.device_type})")
# 照明の制御
light = controller.get_device("living_room_light")
# On/Off クラスタ
await light.clusters.on_off.on()
# Level Control クラスタ(明るさ)
await light.clusters.level_control.move_to_level(
level=128, # 0-254 (50%)
transition_time=10, # 1秒 (10 = 1s)
)
# Color Control クラスタ(色温度)
await light.clusters.color_control.move_to_color_temperature(
color_temperature_mireds=370, # 2700K (暖白色)
transition_time=20,
)
# サーモスタットの制御
thermostat = controller.get_device("thermostat")
await thermostat.clusters.thermostat.set_setpoint(
mode="heating",
temperature=22.0, # 摂氏
)
# ドアロックの制御
lock = controller.get_device("front_door")
await lock.clusters.door_lock.lock()
status = await lock.clusters.door_lock.get_lock_state()
print(f"ドアの状態: {status}") # "locked"コード例: Matter デバイス開発(ESP32 + ESP-Matter)
// ESP32 で Matter 対応照明デバイスを開発する例
// ESP-IDF + ESP-Matter SDK
#include <esp_matter.h>
#include <esp_matter_attribute.h>
#include <esp_matter_endpoint.h>
#include <app/server/Server.h>
using namespace esp_matter;
using namespace chip::app::Clusters;
// GPIO 設定
#define LED_GPIO GPIO_NUM_2
// Attribute コールバック
static esp_err_t app_attribute_update_cb(
attribute::callback_type_t type,
uint16_t endpoint_id,
uint32_t cluster_id,
uint32_t attribute_id,
esp_matter_attr_val_t *val,
void *priv_data)
{
if (type == attribute::PRE_UPDATE) {
// On/Off クラスタの処理
if (cluster_id == OnOff::Id) {
if (attribute_id == OnOff::Attributes::OnOff::Id) {
gpio_set_level(LED_GPIO, val->val.b ? 1 : 0);
ESP_LOGI("APP", "LED %s", val->val.b ? "ON" : "OFF");
}
}
// Level Control クラスタの処理
if (cluster_id == LevelControl::Id) {
if (attribute_id == LevelControl::Attributes::CurrentLevel::Id) {
uint8_t level = val->val.u8;
// PWM で明るさ制御(0-254 → 0-255 duty)
ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, level);
ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
ESP_LOGI("APP", "Brightness: %d/254", level);
}
}
}
return ESP_OK;
}
extern "C" void app_main()
{
// GPIO 初期化
gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << LED_GPIO),
.mode = GPIO_MODE_OUTPUT,
};
gpio_config(&io_conf);
// Matter ノード作成
node::config_t node_config;
node_t *node = node::create(&node_config, app_attribute_update_cb, NULL);
// Dimmable Light エンドポイント追加
endpoint::dimmable_light::config_t light_config;
light_config.on_off.on_off = false;
light_config.level_control.current_level = 128;
endpoint_t *endpoint = endpoint::dimmable_light::create(
node, &light_config, ENDPOINT_FLAG_NONE, NULL
);
// Matter スタート
esp_matter::start(NULL);
ESP_LOGI("APP", "Matter Dimmable Light Started");
ESP_LOGI("APP", "QR Code URL: https://project-chip.github.io/...");
}コード例2: Home Assistant の自動化設定
# Home Assistant の automation.yaml
# AI的な条件判断を含む自動化ルール
# 自動化1: 日没時に照明を自動点灯
- alias: "日没時の照明自動化"
trigger:
- platform: sun
event: sunset
offset: "-00:30:00" # 日没30分前
condition:
- condition: state
entity_id: binary_sensor.occupancy_living_room
state: "on" # 在宅時のみ
action:
- service: light.turn_on
target:
entity_id: light.living_room
data:
brightness_pct: 70
color_temp_kelvin: 3000
transition: 30 # 30秒かけてフェードイン
# 自動化2: 外出検知で省エネモード
- alias: "全員外出で省エネモード"
trigger:
- platform: state
entity_id: group.family
to: "not_home"
for: "00:10:00" # 10分間不在
action:
- service: climate.set_temperature
target:
entity_id: climate.main_thermostat
data:
temperature: 18 # 暖房を下げる
- service: light.turn_off
target:
entity_id: all
- service: switch.turn_off
target:
entity_id: switch.entertainment_system
# 自動化3: AIカメラ連携(人物検出)
- alias: "不審者検知アラート"
trigger:
- platform: state
entity_id: image_processing.front_camera_person_detection
to: "detected"
condition:
- condition: state
entity_id: group.family
state: "not_home"
action:
- service: notify.mobile_app
data:
title: "セキュリティ警告"
message: "玄関カメラで人物を検出しました"
data:
image: "/api/camera_proxy/camera.front_door"
- service: light.turn_on
target:
entity_id: light.porch
data:
brightness_pct: 100コード例: Home Assistant カスタムコンポーネント開発
"""Home Assistant カスタムインテグレーション: スマート環境センサー"""
# custom_components/smart_environment/sensor.py
import logging
from datetime import timedelta
from homeassistant.components.sensor import (
SensorEntity,
SensorDeviceClass,
SensorStateClass,
)
from homeassistant.const import UnitOfTemperature, PERCENTAGE
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity,
DataUpdateCoordinator,
)
_LOGGER = logging.getLogger(__name__)
SCAN_INTERVAL = timedelta(seconds=30)
class SmartEnvironmentCoordinator(DataUpdateCoordinator):
"""環境データを統合管理するコーディネーター"""
def __init__(self, hass, sensors_config):
super().__init__(
hass,
_LOGGER,
name="Smart Environment",
update_interval=SCAN_INTERVAL,
)
self._sensors = sensors_config
self._history = []
async def _async_update_data(self):
"""センサーデータを収集・分析"""
data = {}
# 各センサーからデータ収集
for sensor_id in self._sensors:
state = self.hass.states.get(sensor_id)
if state and state.state not in ("unknown", "unavailable"):
data[sensor_id] = float(state.state)
# 快適度スコアを計算
if "sensor.temperature" in data and "sensor.humidity" in data:
temp = data["sensor.temperature"]
humidity = data["sensor.humidity"]
data["comfort_score"] = self._calculate_comfort(temp, humidity)
# 換気推奨判定
if "sensor.co2" in data:
co2 = data["sensor.co2"]
data["ventilation_needed"] = co2 > 1000
# 履歴保存(トレンド分析用)
self._history.append(data)
if len(self._history) > 120: # 1時間分
self._history.pop(0)
# トレンド分析
data["temperature_trend"] = self._analyze_trend("sensor.temperature")
return data
def _calculate_comfort(self, temp, humidity):
"""PMV簡易モデルによる快適度計算(0-100)"""
# 不快指数ベースの簡易計算
discomfort = 0.81 * temp + 0.01 * humidity * (
0.99 * temp - 14.3
) + 46.3
# 70-75が快適ゾーン
if 70 <= discomfort <= 75:
return 100
elif discomfort < 70:
return max(0, 100 - (70 - discomfort) * 10)
else:
return max(0, 100 - (discomfort - 75) * 10)
def _analyze_trend(self, sensor_id):
"""直近30分のトレンドを分析"""
values = [
h.get(sensor_id) for h in self._history[-60:]
if h.get(sensor_id) is not None
]
if len(values) < 10:
return "stable"
slope = (values[-1] - values[0]) / len(values)
if slope > 0.05:
return "rising"
elif slope < -0.05:
return "falling"
return "stable"
class ComfortScoreSensor(CoordinatorEntity, SensorEntity):
"""快適度スコアセンサー"""
_attr_name = "快適度スコア"
_attr_native_unit_of_measurement = PERCENTAGE
_attr_state_class = SensorStateClass.MEASUREMENT
_attr_icon = "mdi:emoticon-happy-outline"
def __init__(self, coordinator):
super().__init__(coordinator)
self._attr_unique_id = "smart_env_comfort_score"
@property
def native_value(self):
if self.coordinator.data:
return self.coordinator.data.get("comfort_score")
return None
@property
def extra_state_attributes(self):
"""追加属性"""
data = self.coordinator.data or {}
return {
"temperature_trend": data.get("temperature_trend", "unknown"),
"ventilation_needed": data.get("ventilation_needed", False),
}Home Assistant ダッシュボード(Lovelace UI)設計
# Home Assistant Lovelace Dashboard 設計例
# ui-lovelace.yaml
title: スマートホーム
views:
- title: ホーム
path: home
icon: mdi:home
cards:
# 在宅状態カード
- type: entities
title: 家族の在宅状況
entities:
- entity: person.taro
secondary_info: last-changed
- entity: person.hanako
secondary_info: last-changed
- entity: binary_sensor.anyone_home
name: 在宅者あり
# 環境モニター
- type: custom:mini-graph-card
title: 室内環境
entities:
- entity: sensor.living_room_temperature
name: 温度
color: "#e74c3c"
- entity: sensor.living_room_humidity
name: 湿度
color: "#3498db"
y_axis: secondary
hours_to_show: 24
points_per_hour: 4
show:
labels: true
average: true
extrema: true
# 照明コントロール
- type: custom:light-entity-card
entity: light.living_room
shorten_cards: true
consolidate_entities: true
child_card: true
hide_header: false
effects_list: true
# エネルギー使用量
- type: energy-distribution
title: エネルギー分配
link_dashboard: true
# カメラフィード
- type: picture-glance
title: 玄関カメラ
camera_image: camera.front_door
entities:
- binary_sensor.front_door_motion
- binary_sensor.front_door_person
camera_view: live
- title: 自動化
path: automations
icon: mdi:robot
cards:
# 自動化の一覧と状態
- type: custom:auto-entities
card:
type: entities
title: アクティブな自動化
filter:
include:
- domain: automation
state: "on"
exclude:
- entity_id: automation.system_*
sort:
method: last_triggered
reverse: true
# 自動化のトリガー履歴
- type: logbook
title: 直近の自動化実行
hours_to_show: 24
entities:
- automation.sunset_lights
- automation.away_mode
- automation.security_alert4. 音声アシスタントとAI
音声アシスタント比較表
| 項目 | Amazon Alexa | Google Assistant | Apple Siri | Home Assistant Voice |
|---|---|---|---|---|
| デバイス | Echo シリーズ | Nest シリーズ | HomePod, iPhone | 自作/ESP32 |
| スマートホーム統合 | 非常に広い | 広い | HomeKit中心 | 最も広い(DIY) |
| AI能力 | Alexa LLM | Gemini統合 | Apple Intelligence | ローカルLLM対応 |
| プライバシー | クラウド処理 | クラウド処理 | オンデバイス重視 | 完全ローカル可 |
| Skills/Actions | 10万+ | 数万 | Siri Shortcuts | Home Assistantの全機能 |
| 日本語対応 | 対応 | 対応 | 対応 | コミュニティ対応 |
| 価格帯 | 3,000-30,000円 | 5,000-30,000円 | 15,000-50,000円 | 自作コスト |
音声認識パイプライン
+-----------------------------------------------------------+
| 音声アシスタント処理フロー |
+-----------------------------------------------------------+
| |
| 「アレクサ、リビングの照明を暖色に」 |
| | |
| v |
| +--------------------+ |
| | ウェイクワード検出 | ← デバイス上で常時動作(NPU) |
| | "アレクサ" を検知 | |
| +--------------------+ |
| | |
| v |
| +--------------------+ |
| | 音声認識 (ASR) | ← クラウド or オンデバイス |
| | 音声 → テキスト | Whisper, Google ASR |
| +--------------------+ |
| | |
| v |
| +--------------------+ |
| | 自然言語理解 (NLU) | ← LLM ベースが主流に |
| | Intent: 照明制御 | 意図と実体の抽出 |
| | Entity: リビング | |
| | Entity: 暖色 | |
| +--------------------+ |
| | |
| v |
| +--------------------+ |
| | スキル/アクション | ← デバイスAPI呼び出し |
| | light.set_color() | |
| +--------------------+ |
| | |
| v |
| +--------------------+ |
| | 音声合成 (TTS) | ← 確認応答を生成 |
| | 「リビングの照明を | |
| | 暖色にしました」 | |
| +--------------------+ |
+-----------------------------------------------------------+
ローカル音声アシスタント構築(Wyoming Protocol)
Home Assistant のローカル音声処理は Wyoming プロトコルを使用して、各音声処理コンポーネントをマイクロサービスとして接続する。
【ローカル音声アシスタント アーキテクチャ】
+-------------------+
| マイク入力 | ESP32-S3-BOX / USB マイク
+--------+----------+
|
v
+--------+----------+
| ウェイクワード検出 | openWakeWord / Porcupine
| "OK ナブ" | ← ESP32上で動作(低遅延)
+--------+----------+
|
v (Wyoming Protocol)
+--------+----------+
| 音声認識 (STT) | faster-whisper / Whisper.cpp
| 音声 → テキスト | ← ローカルGPU or CPU
| モデル: large-v3 | ← 日本語対応
+--------+----------+
|
v
+--------+----------+
| インテント処理 | Home Assistant Conversation Agent
| LLM or ルールベース | ← Ollama (llama3) / ルールベース
+--------+----------+
|
v
+--------+----------+
| 音声合成 (TTS) | Piper TTS
| テキスト → 音声 | ← ローカル、低遅延
| 声質: ja_JP-takumi | ← 日本語音声モデル
+--------+----------+
|
v
+--------+----------+
| スピーカー出力 | ESP32-S3-BOX / 外部スピーカー
+-------------------+
# Home Assistant の Wyoming 音声パイプライン設定
# docker-compose.yml
version: '3.8'
services:
# Whisper STT サーバー
whisper:
image: rhasspy/wyoming-whisper:latest
ports:
- "10300:10300"
volumes:
- whisper-data:/data
command: >
--model large-v3
--language ja
--device cuda # GPU使用(CPU: --device cpu)
--beam-size 5
--compute-type float16
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
# Piper TTS サーバー
piper:
image: rhasspy/wyoming-piper:latest
ports:
- "10200:10200"
volumes:
- piper-data:/data
command: >
--voice ja_JP-takumi-medium
--speaker 0
--length-scale 1.0
--noise-scale 0.667
--noise-w 0.8
# openWakeWord サーバー
openwakeword:
image: rhasspy/wyoming-openwakeword:latest
ports:
- "10400:10400"
command: >
--preload-model ok_nabu
--threshold 0.5
--trigger-level 1
volumes:
whisper-data:
piper-data:ESP32-S3 ベースの音声サテライト構築
# ESPHome 設定: ESP32-S3-BOX を音声サテライト化
# esphome/voice-satellite.yaml
esphome:
name: voice-satellite-living
friendly_name: "リビング音声アシスタント"
esp32:
board: esp32-s3-box
framework:
type: esp-idf
# Wi-Fi設定
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# マイクロフォン(I2S入力)
i2s_audio:
- id: i2s_input
i2s_lrclk_pin: GPIO41
i2s_bclk_pin: GPIO42
- id: i2s_output
i2s_lrclk_pin: GPIO46
i2s_bclk_pin: GPIO17
microphone:
- platform: i2s_audio
id: mic
i2s_audio_id: i2s_input
adc_type: external
i2s_din_pin: GPIO2
pdm: false
channel: left
bits_per_sample: 32bit
sample_rate: 16000
# スピーカー(I2S出力)
speaker:
- platform: i2s_audio
id: spk
i2s_audio_id: i2s_output
dac_type: external
i2s_dout_pin: GPIO15
mode: stereo
# 音声アシスタント
voice_assistant:
id: va
microphone: mic
speaker: spk
noise_suppression_level: 2
auto_gain: 31dBFS
volume_multiplier: 2.0
use_wake_word: true
on_wake_word_detected:
- light.turn_on:
id: led_ring
effect: "listening"
on_stt_end:
- light.turn_on:
id: led_ring
effect: "thinking"
on_tts_start:
- light.turn_on:
id: led_ring
effect: "speaking"
on_end:
- light.turn_off:
id: led_ring
- wait_until:
not:
voice_assistant.is_running:
- delay: 500ms
- voice_assistant.start_continuous:
# LED リング(状態表示)
light:
- platform: esp32_rmt_led_strip
id: led_ring
pin: GPIO39
num_leds: 12
chipset: SK6812
rgb_order: GRB
effects:
- addressable_rainbow:
name: "listening"
speed: 30
- pulse:
name: "thinking"
min_brightness: 30%
max_brightness: 100%
- addressable_scan:
name: "speaking"
move_interval: 50ms
# 物理ボタン(ミュート)
binary_sensor:
- platform: gpio
pin:
number: GPIO0
inverted: true
name: "ミュートボタン"
on_press:
- voice_assistant.stop:
- light.turn_on:
id: led_ring
red: 100%
green: 0%
blue: 0%5. AI 家電の技術
コード例3: エネルギー最適化AI
import numpy as np
from sklearn.ensemble import GradientBoostingRegressor
class SmartThermostatAI:
"""
AIによるサーモスタットの予測制御
ユーザーの行動パターンと外気温から最適な温度を予測
"""
def __init__(self):
self.comfort_model = GradientBoostingRegressor()
self.occupancy_model = GradientBoostingRegressor()
def train(self, history_data):
"""過去の行動データから学習"""
features = self._extract_features(history_data)
# 特徴量: 時刻, 曜日, 外気温, 湿度, 過去の設定温度
# ターゲット: ユーザーが設定した温度
self.comfort_model.fit(
features, history_data['target_temperature']
)
self.occupancy_model.fit(
features, history_data['is_occupied']
)
def predict_schedule(self, forecast_weather, day_of_week):
"""24時間の温度スケジュールを予測"""
schedule = []
for hour in range(24):
features = np.array([[
hour,
day_of_week,
forecast_weather[hour]['temperature'],
forecast_weather[hour]['humidity'],
]])
predicted_temp = self.comfort_model.predict(features)[0]
occupancy_prob = self.occupancy_model.predict(features)[0]
# 不在予測時は省エネ温度に
if occupancy_prob < 0.3:
target_temp = predicted_temp - 3 # 3度下げる
else:
target_temp = predicted_temp
schedule.append({
'hour': hour,
'target': round(target_temp, 1),
'occupancy': round(occupancy_prob, 2),
})
return schedule
def estimate_energy_savings(self, schedule, baseline=22.0):
"""省エネ効果を推定"""
# 温度1度下げると約7%の省エネ
savings = sum(
max(0, baseline - s['target']) * 0.07
for s in schedule
) / 24
return f"推定省エネ率: {savings*100:.1f}%"コード例: 高度なエネルギー管理システム(HEMS)
"""家庭用エネルギー管理システム (HEMS) の実装"""
import asyncio
from datetime import datetime, timedelta
from dataclasses import dataclass
from typing import Optional
@dataclass
class EnergyDevice:
"""エネルギーデバイスの抽象化"""
name: str
entity_id: str
power_watts: float
priority: int # 1=最高, 5=最低
shiftable: bool # 稼働時間をずらせるか
min_runtime_minutes: int = 0
max_power_watts: Optional[float] = None
class HEMSController:
"""
HEMS(Home Energy Management System)コントローラー
太陽光発電、蓄電池、電力料金を考慮して
家電の稼働スケジュールを最適化する
"""
def __init__(self, hass, config):
self.hass = hass
self.config = config
self.devices: list[EnergyDevice] = []
self.solar_forecast = []
self.price_schedule = []
self.battery_soc = 0.0 # State of Charge (%)
async def update_solar_forecast(self):
"""太陽光発電予測を更新(Solcast API)"""
import aiohttp
async with aiohttp.ClientSession() as session:
url = "https://api.solcast.com.au/rooftop_sites"
params = {
"resource_id": self.config["solcast_resource_id"],
"api_key": self.config["solcast_api_key"],
}
async with session.get(
f"{url}/{params['resource_id']}/forecasts",
params={"api_key": params["api_key"]}
) as resp:
data = await resp.json()
self.solar_forecast = [
{
"time": entry["period_end"],
"power_kw": entry["pv_estimate"],
"power_kw_10": entry["pv_estimate10"], # 10%ile
"power_kw_90": entry["pv_estimate90"], # 90%ile
}
for entry in data["forecasts"][:48] # 24時間分
]
def get_electricity_price(self, hour: int) -> float:
"""時間帯別電力料金を取得(円/kWh)"""
# オクトパスエナジー等の動的料金プラン想定
price_table = {
range(0, 6): 18.0, # 深夜料金
range(6, 8): 28.0, # 朝方
range(8, 10): 32.0, # 午前
range(10, 17): 35.0, # 日中ピーク
range(17, 21): 38.0, # 夕方ピーク
range(21, 24): 25.0, # 夜間
}
for time_range, price in price_table.items():
if hour in time_range:
return price
return 30.0
async def optimize_schedule(self):
"""デバイス稼働スケジュールを最適化"""
schedule = {}
current_hour = datetime.now().hour
for device in sorted(self.devices, key=lambda d: d.priority):
if not device.shiftable:
# シフト不可デバイスはそのまま
schedule[device.entity_id] = "always_on"
continue
# 最安時間帯を探索
best_hour = current_hour
best_cost = float('inf')
runtime_hours = max(1, device.min_runtime_minutes // 60)
for start_hour in range(24):
total_cost = 0
for h in range(runtime_hours):
hour = (start_hour + h) % 24
price = self.get_electricity_price(hour)
# 太陽光発電がある時間帯はコストを下げる
solar_offset = self._get_solar_power(hour)
net_price = price * max(
0, 1 - solar_offset / device.power_watts
)
total_cost += net_price * (device.power_watts / 1000)
if total_cost < best_cost:
best_cost = total_cost
best_hour = start_hour
schedule[device.entity_id] = {
"start_hour": best_hour,
"duration_hours": runtime_hours,
"estimated_cost_yen": round(best_cost, 1),
}
return schedule
def _get_solar_power(self, hour: int) -> float:
"""指定時刻の太陽光発電量(W)を取得"""
for forecast in self.solar_forecast:
forecast_hour = datetime.fromisoformat(
forecast["time"]
).hour
if forecast_hour == hour:
return forecast["power_kw"] * 1000
return 0
async def battery_strategy(self):
"""蓄電池の充放電戦略を決定"""
strategies = []
for hour in range(24):
price = self.get_electricity_price(hour)
solar = self._get_solar_power(hour)
if solar > 2000 and self.battery_soc < 80:
# 太陽光余剰で充電
strategies.append({
"hour": hour, "action": "charge",
"reason": "太陽光余剰", "power_w": min(solar - 1500, 3000)
})
elif price >= 35 and self.battery_soc > 30:
# 高料金時に放電
strategies.append({
"hour": hour, "action": "discharge",
"reason": "ピーク料金回避", "power_w": 2000
})
elif price <= 20 and self.battery_soc < 50:
# 深夜料金で充電
strategies.append({
"hour": hour, "action": "charge",
"reason": "深夜料金充電", "power_w": 3000
})
else:
strategies.append({
"hour": hour, "action": "standby",
"reason": "待機", "power_w": 0
})
return strategies
def daily_report(self, schedule, battery_plan):
"""日次エネルギーレポート生成"""
total_cost = sum(
s.get("estimated_cost_yen", 0)
for s in schedule.values()
if isinstance(s, dict)
)
solar_total = sum(
self._get_solar_power(h) / 1000 for h in range(24)
)
charge_hours = sum(
1 for s in battery_plan if s["action"] == "charge"
)
discharge_hours = sum(
1 for s in battery_plan if s["action"] == "discharge"
)
return {
"date": datetime.now().strftime("%Y-%m-%d"),
"estimated_cost_yen": round(total_cost, 0),
"solar_generation_kwh": round(solar_total, 1),
"battery_charge_hours": charge_hours,
"battery_discharge_hours": discharge_hours,
"self_consumption_rate": round(
solar_total / max(1, solar_total + total_cost / 30) * 100, 1
),
}コード例4: AIカメラの人物検出
# ローカルAIカメラ(Frigate NVR + Home Assistant連携)
# frigate.yml 設定例
# Frigate NVR の設定
mqtt:
host: 192.168.1.100
detectors:
coral:
type: edgetpu
device: usb # Google Coral USB Accelerator
cameras:
front_door:
ffmpeg:
inputs:
- path: rtsp://192.168.1.50:554/stream
roles:
- detect
- record
detect:
width: 1280
height: 720
fps: 5
objects:
track:
- person
- car
- dog
filters:
person:
min_area: 5000
max_area: 100000
threshold: 0.7
zones:
front_yard:
coordinates: 0,300,640,300,640,720,0,720
record:
enabled: true
retain:
days: 7
events:
retain:
default: 30 # イベント映像は30日保持
snapshots:
enabled: true
retain:
default: 30Frigate NVR の高度な設定と最適化
# frigate.yml - 高度な設定
# 複数カメラ + カスタムモデル + 通知設定
# グローバル設定
mqtt:
host: 192.168.1.100
port: 1883
user: frigate
password: "{FRIGATE_MQTT_PASSWORD}"
topic_prefix: frigate
database:
path: /media/frigate/frigate.db
# 検出器設定(複数対応)
detectors:
coral_usb:
type: edgetpu
device: usb:0
# 2つ目のCoral(高負荷環境)
coral_pcie:
type: edgetpu
device: pci:0
# モデル設定
model:
path: /config/model_cache/yolov8n_320.tflite
input_tensor: nhwc
input_pixel_format: rgb
width: 320
height: 320
labelmap_path: /config/labelmap.txt
# 録画設定
record:
enabled: true
retain:
days: 7
mode: motion # motion/all
events:
retain:
default: 30
mode: active_objects
pre_capture: 5 # イベント前5秒
post_capture: 10 # イベント後10秒
# スナップショット設定
snapshots:
enabled: true
timestamp: true
bounding_box: true
crop: true
quality: 85
retain:
default: 30
# 複数カメラ設定
cameras:
# 玄関カメラ
front_door:
ffmpeg:
inputs:
- path: rtsp://192.168.1.50:554/h264
roles: [detect]
- path: rtsp://192.168.1.50:554/h265_main
roles: [record]
output_args:
record: -f segment -segment_time 60 -segment_format mp4 -reset_timestamps 1 -strftime 1 -c:v copy -c:a aac
detect:
width: 1280
height: 720
fps: 5
enabled: true
motion:
threshold: 25
contour_area: 30
delta_alpha: 0.2
frame_alpha: 0.2
improve_contrast: true
objects:
track: [person, car, dog, cat, package]
filters:
person:
min_area: 5000
min_score: 0.6
threshold: 0.75
car:
min_area: 10000
min_score: 0.5
package:
min_area: 2000
min_score: 0.5
zones:
porch:
coordinates: 100,400,500,400,500,720,100,720
objects: [person, package]
driveway:
coordinates: 500,300,1280,300,1280,720,500,720
objects: [person, car]
review:
alerts:
required_zones: [porch]
labels: [person]
detections:
labels: [car, dog, cat]
# 裏庭カメラ
backyard:
ffmpeg:
inputs:
- path: rtsp://192.168.1.51:554/stream
roles: [detect, record]
detect:
width: 1920
height: 1080
fps: 5
objects:
track: [person, dog, cat]
filters:
person:
min_area: 3000
threshold: 0.7
motion:
mask:
# 木の揺れを除外
- 0,0,200,0,200,300,0,300
# 室内カメラ(ペットモニター)
living_room:
ffmpeg:
inputs:
- path: rtsp://192.168.1.52:554/stream
roles: [detect]
detect:
width: 640
height: 480
fps: 3 # 室内は低FPSで十分
objects:
track: [dog, cat]
filters:
dog:
min_area: 2000
record:
enabled: false # プライバシー考慮で録画なし
snapshots:
enabled: true
# 通知設定(Home Assistant連携)
# automation.yaml 側で設定コード例5: Home Assistant でのローカルLLM統合
# Home Assistant の configuration.yaml
# ローカル LLM (Ollama) との統合
# Ollama 音声アシスタント統合
conversation:
intents:
# カスタムインテント定義
# Extended OpenAI Conversation (カスタムコンポーネント)
# ローカルの Ollama にリクエスト
openai_conversation:
api_key: "sk-not-needed"
base_url: "http://192.168.1.100:11434/v1"
model: "llama3.1"
prompt: |
あなたはスマートホームアシスタントです。
以下のデバイスを制御できます:
- light.living_room: リビング照明
- light.bedroom: 寝室照明
- climate.thermostat: エアコン
- lock.front_door: 玄関ドアロック
- cover.curtain_living: リビングカーテン
ユーザーの要望に対して、適切なサービスコールを生成してください。
応答は日本語で行ってください。LLM ベースのスマートホーム制御(Function Calling)
"""LLM Function Calling によるスマートホーム制御"""
import json
from openai import OpenAI
# ローカル Ollama に接続
client = OpenAI(
base_url="http://192.168.1.100:11434/v1",
api_key="not-needed",
)
# Home Assistant のサービスを関数として定義
tools = [
{
"type": "function",
"function": {
"name": "control_light",
"description": "照明を制御する(点灯/消灯/明るさ/色温度の変更)",
"parameters": {
"type": "object",
"properties": {
"entity_id": {
"type": "string",
"description": "照明のエンティティID",
"enum": [
"light.living_room",
"light.bedroom",
"light.kitchen",
"light.bathroom",
],
},
"action": {
"type": "string",
"enum": ["turn_on", "turn_off", "toggle"],
},
"brightness_pct": {
"type": "integer",
"description": "明るさ(0-100%)",
"minimum": 0,
"maximum": 100,
},
"color_temp_kelvin": {
"type": "integer",
"description": "色温度(2000-6500K)",
"minimum": 2000,
"maximum": 6500,
},
},
"required": ["entity_id", "action"],
},
},
},
{
"type": "function",
"function": {
"name": "control_climate",
"description": "エアコン/暖房を制御する",
"parameters": {
"type": "object",
"properties": {
"entity_id": {
"type": "string",
"enum": ["climate.living_room", "climate.bedroom"],
},
"action": {
"type": "string",
"enum": ["set_temperature", "turn_off", "set_mode"],
},
"temperature": {
"type": "number",
"description": "目標温度(摂氏)",
},
"hvac_mode": {
"type": "string",
"enum": ["heat", "cool", "auto", "off"],
},
},
"required": ["entity_id", "action"],
},
},
},
{
"type": "function",
"function": {
"name": "get_sensor_value",
"description": "センサーの値を取得する",
"parameters": {
"type": "object",
"properties": {
"entity_id": {
"type": "string",
"description": "センサーのエンティティID",
"enum": [
"sensor.temperature_living_room",
"sensor.humidity_living_room",
"sensor.co2_living_room",
"sensor.power_consumption",
],
},
},
"required": ["entity_id"],
},
},
},
{
"type": "function",
"function": {
"name": "activate_scene",
"description": "シーン(プリセット)を実行する",
"parameters": {
"type": "object",
"properties": {
"scene_name": {
"type": "string",
"enum": [
"scene.movie_time",
"scene.good_morning",
"scene.good_night",
"scene.away_mode",
"scene.party",
],
},
},
"required": ["scene_name"],
},
},
},
]
def process_user_command(user_input: str):
"""ユーザーの自然言語コマンドを処理"""
messages = [
{
"role": "system",
"content": (
"あなたはスマートホームアシスタントです。"
"ユーザーの要望を理解し、適切な関数を呼び出してください。"
"曖昧な要望は確認してください。"
),
},
{"role": "user", "content": user_input},
]
response = client.chat.completions.create(
model="llama3.1:8b",
messages=messages,
tools=tools,
tool_choice="auto",
)
message = response.choices[0].message
if message.tool_calls:
results = []
for tool_call in message.tool_calls:
func_name = tool_call.function.name
func_args = json.loads(tool_call.function.arguments)
# Home Assistant API を呼び出し
result = execute_ha_service(func_name, func_args)
results.append({
"function": func_name,
"args": func_args,
"result": result,
})
return results
else:
return {"response": message.content}
def execute_ha_service(func_name: str, args: dict) -> str:
"""Home Assistant のサービスを実行"""
import requests
ha_url = "http://192.168.1.100:8123"
ha_token = "YOUR_LONG_LIVED_TOKEN"
headers = {
"Authorization": f"Bearer {ha_token}",
"Content-Type": "application/json",
}
if func_name == "control_light":
service = f"light/{args['action']}"
data = {"entity_id": args["entity_id"]}
if "brightness_pct" in args:
data["brightness_pct"] = args["brightness_pct"]
if "color_temp_kelvin" in args:
data["color_temp_kelvin"] = args["color_temp_kelvin"]
elif func_name == "control_climate":
if args["action"] == "set_temperature":
service = "climate/set_temperature"
data = {
"entity_id": args["entity_id"],
"temperature": args.get("temperature", 22),
}
elif args["action"] == "set_mode":
service = "climate/set_hvac_mode"
data = {
"entity_id": args["entity_id"],
"hvac_mode": args.get("hvac_mode", "auto"),
}
else:
service = "climate/turn_off"
data = {"entity_id": args["entity_id"]}
elif func_name == "get_sensor_value":
resp = requests.get(
f"{ha_url}/api/states/{args['entity_id']}",
headers=headers,
)
state = resp.json()
return f"{state['attributes'].get('friendly_name')}: {state['state']} {state['attributes'].get('unit_of_measurement', '')}"
elif func_name == "activate_scene":
service = "scene/turn_on"
data = {"entity_id": args["scene_name"]}
else:
return f"Unknown function: {func_name}"
resp = requests.post(
f"{ha_url}/api/services/{service}",
headers=headers,
json=data,
)
return f"OK (status: {resp.status_code})"
# 使用例
if __name__ == "__main__":
commands = [
"リビングの照明を暖かい色で50%にして",
"今の室温を教えて",
"映画モードにして",
"寝室のエアコンを25度に設定して",
"外出モードをオンにして",
]
for cmd in commands:
print(f"\nユーザー: {cmd}")
result = process_user_command(cmd)
print(f"結果: {json.dumps(result, ensure_ascii=False, indent=2)}")6. セキュリティとプライバシー
スマートホームセキュリティの層
+-----------------------------------------------------------+
| スマートホーム セキュリティ層 |
+-----------------------------------------------------------+
| |
| Layer 4: アプリケーションセキュリティ |
| +-- 二要素認証 (2FA) |
| +-- アクセスログの監視 |
| +-- ゲストアクセスの期限管理 |
| |
| Layer 3: プロトコルセキュリティ |
| +-- Matter: CASE (証明書認証) |
| +-- HomeKit: Ed25519 暗号化 |
| +-- TLS 1.3 通信暗号化 |
| |
| Layer 2: ネットワークセキュリティ |
| +-- IoT専用VLAN分離 |
| +-- ファイアウォールルール |
| +-- DNS over HTTPS (DoH) |
| |
| Layer 1: デバイスセキュリティ |
| +-- ファームウェア自動更新 |
| +-- セキュアブート |
| +-- デフォルトパスワードの変更 |
+-----------------------------------------------------------+
IoT VLAN 分離の具体的設定
# UniFi / pfSense でのIoT VLAN設定例
【ネットワーク設計】| VLAN 1 (Default): 管理用ネットワーク |
|---|
| 192.168.1.0/24 |
| デバイス: PC, スマホ, NAS |
| → フルアクセス |
| VLAN 10: IoTデバイス |
| 192.168.10.0/24 |
| デバイス: 照明, センサー, スマートプラグ |
| → インターネット制限、VLAN1へアクセス不可 |
| VLAN 20: カメラ専用 |
| 192.168.20.0/24 |
| デバイス: IPカメラ, NVR |
| → インターネットアクセス完全禁止 |
| → NVR (192.168.1.x) のみアクセス可 |
| VLAN 30: ゲスト用 |
| 192.168.30.0/24 |
| デバイス: ゲストのスマホ |
| → インターネットのみ、LAN内アクセス不可 |
# pfSense ファイアウォールルール(概念)
# /etc/pf.conf
# IoT VLAN → メインLAN: ブロック
block in on $iot_vlan from 192.168.10.0/24 to 192.168.1.0/24
# IoT VLAN → Home Assistant のみ許可
pass in on $iot_vlan from 192.168.10.0/24 to 192.168.1.100 port 8123
# IoT VLAN → MQTT Broker のみ許可
pass in on $iot_vlan from 192.168.10.0/24 to 192.168.1.100 port 1883
# IoT VLAN → DNS のみ許可(Pi-hole/AdGuard)
pass in on $iot_vlan from 192.168.10.0/24 to 192.168.1.53 port 53
# カメラ VLAN → 完全隔離
block in on $camera_vlan from 192.168.20.0/24 to any
pass in on $camera_vlan from 192.168.20.0/24 to 192.168.1.100 # NVRのみ
# ゲスト VLAN → インターネットのみ
block in on $guest_vlan from 192.168.30.0/24 to 192.168.0.0/16
pass in on $guest_vlan from 192.168.30.0/24 to anyDNS フィルタリングによるIoTセキュリティ
# AdGuard Home 設定 - IoTデバイス用フィルタリング
# /opt/adguardhome/conf/AdGuardHome.yaml (抜粋)
dns:
bind_hosts:
- 192.168.1.53
port: 53
upstream_dns:
- https://dns.cloudflare.com/dns-query # DoH
- https://dns.google/dns-query
filtering:
# IoTデバイスのテレメトリをブロック
rewrites:
# 中華IoTデバイスの電話帰り通信をブロック
- domain: "*.tuya.com"
answer: "0.0.0.0"
- domain: "*.tuyaus.com"
answer: "0.0.0.0"
# カメラのクラウドアップロードをブロック
- domain: "*.xiongmaitech.com"
answer: "0.0.0.0"
# スマートTVの追跡をブロック
- domain: "*.samsungacr.com"
answer: "0.0.0.0"
- domain: "*.lgtvsdp.com"
answer: "0.0.0.0"
clients:
# IoTデバイスグループ
runtime_sources:
- name: "IoT Devices"
ids:
- "192.168.10.0/24"
tags:
- "device_iot"
use_global_blocked_services: false
blocked_services:
- facebook
- tiktok
filtering_enabled: true
parental_enabled: false
safesearch_enabled: false7. アンチパターン
アンチパターン1: 全デバイスをWi-Fiに接続
NG: 照明、センサー、カメラ全てをWi-Fiで接続
→ Wi-Fiルーターの接続上限超過(通常30-50台)
→ 遅延増大、ネットワーク不安定化
OK: プロトコルを適材適所で使い分け
Wi-Fi: カメラ(高帯域が必要)、スマートディスプレイ
Thread: 照明、温度センサー、ドアセンサー(低消費電力メッシュ)
Zigbee: 既存のIKEAやPhilips Hueデバイス
Bluetooth: ビーコン、近距離一時接続
アンチパターン2: クラウド依存の過信
NG: 全ての自動化をクラウドサービスに依存
→ インターネット切断時に全てが停止
→ サービス終了で全デバイスがブリック化
OK: ローカルファースト設計
1. Home Assistant などローカルハブを中核に
2. 照明・ドアロックなど基本制御はローカルで完結
3. クラウドは付加価値(リモートアクセス、AI機能)のみ
4. Matter/Thread 対応デバイスを優先(ローカル通信可)
アンチパターン3: セキュリティ無視のデバイス導入
NG: 安価な中華IoTデバイスを無対策で導入
→ デフォルトパスワード(admin/admin)のまま運用
→ クラウドサーバーへの常時通信(データ漏洩リスク)
→ ファームウェア更新なし(既知の脆弱性放置)
→ フラットなネットワーク上に全デバイスが同居
OK: 段階的なセキュリティ対策
1. VLAN分離: IoTデバイスを専用ネットワークに隔離
2. DNSフィルタリング: 不要な外部通信をブロック
3. ファームウェア: 自動更新が可能なデバイスを選択
4. 認証: 全デバイスのパスワードを変更、可能なら2FA
5. 監査: ネットワーク監視で異常な通信を検出
アンチパターン4: 過度な自動化による混乱
NG: 条件が複雑すぎる自動化ルールを大量に作成
→ ルール同士が競合(照明をONにする自動化とOFFにする自動化が同時発火)
→ デバッグ困難(なぜ照明が点いたのかわからない)
→ 家族が手動で操作できなくなる
OK: 自動化の設計原則
1. シンプルに: 1つの自動化に条件は3つ以下
2. 優先度管理: 手動操作 > 自動化(手動操作後は一定時間自動化を抑制)
3. フィードバック: 自動化実行時に通知(LED、音、アプリ通知)
4. キルスイッチ: 全自動化を一括停止できるスイッチを用意
5. 段階的導入: 1つずつ追加して動作確認
6. ドキュメント: 自動化の意図と条件をコメントに記述
アンチパターン5: バックアップ戦略の欠如
NG: Home Assistant の設定をバックアップしていない
→ SDカード故障で全設定が消失
→ 数十時間かけた自動化ルールが一瞬でゼロに
→ デバイスの再ペアリングが必要
OK: 多層バックアップ戦略
1. 自動スナップショット: 毎日深夜にHA自動バックアップ
2. 外部保存: Google Drive / NAS にバックアップを同期
3. Git管理: YAML設定ファイルをGitリポジトリで管理
4. SSD化: Raspberry PiのSDカードをSSD/NVMeに換装
5. HA OS: 専用OS使用でスナップショット復元が容易
設定例(Home Assistant バックアップ自動化):
# Home Assistant バックアップ自動化
- alias: "毎日自動バックアップ"
trigger:
- platform: time
at: "03:00:00"
action:
- service: backup.create
data:
name: "auto_backup_{{ now().strftime('%Y%m%d') }}"
# Google Drive にアップロード(Google Drive Backup アドオン)
- delay: "00:05:00"
- service: hassio.addon_stdin
data:
addon: cebe7a76_hassio_google_drive_backup
input:
command: "backup"8. スマートホーム構築実践ガイド
予算別構成例
【ミニマル構成】予算: 2-3万円
├── Raspberry Pi 5 (4GB): 12,000円
├── Zigbee USBドングル (SONOFF ZBDongle-E): 2,500円
├── スマート照明 x3 (IKEA TRADFRI): 6,000円
├── 温度・湿度センサー x2 (Aqara): 4,000円
└── スマートプラグ x2 (TP-Link): 3,000円
【スタンダード構成】予算: 5-8万円
├── Home Assistant Green: 15,000円
├── Thread Border Router (Apple TV 4K): 22,000円
├── Matter対応照明 x5 (Nanoleaf/Eve): 15,000円
├── スマートロック (SwitchBot Lock Pro): 12,000円
├── 温度・湿度・CO2センサー (Aqara): 8,000円
├── スマートカーテン (SwitchBot): 8,000円
└── スマートプラグ x3: 5,000円
【フル構成】予算: 15-25万円
├── Home Assistant Yellow (PoE): 25,000円
├── UniFi Dream Machine SE: 50,000円
├── Thread/Matter照明システム: 30,000円
├── Frigate NVR + Coral USB: 15,000円
├── IPカメラ x3 (Reolink PoE): 30,000円
├── ESP32-S3-BOX x2 (音声サテライト): 8,000円
├── スマートロック + キーパッド: 20,000円
├── 各種センサー群: 15,000円
├── スマートカーテン x3: 24,000円
└── UPS (停電対策): 15,000円
段階的導入ロードマップ
【Phase 1: 基盤構築(1-2週間)】
Day 1-2: ハードウェア設置
└── Home Assistant インストール、ネットワーク設定
Day 3-5: 基本デバイス接続
└── 照明、プラグ、センサーのペアリング
Day 6-7: 基本自動化
└── 日没照明、外出モード、温度アラート
Day 8-14: 安定性確認
└── 1週間運用して問題を洗い出し
【Phase 2: 拡張(3-4週目)】
Week 3: セキュリティ強化
└── VLAN分離、DNSフィルタリング、バックアップ設定
Week 4: AI機能追加
└── Frigate NVR、音声アシスタント(Wyoming)
【Phase 3: 最適化(2ヶ月目以降)】
Month 2: 高度な自動化
└── 行動パターン学習、エネルギー最適化
Month 3+: 継続改善
└── 新デバイス追加、自動化の調整
FAQ
Q1. Matter 対応デバイスと非対応デバイス、どちらを買うべき?
今後の購入は原則 Matter 対応を推奨。Matter 対応デバイスはApple Home、Google Home、Amazon Alexa全てで動作し、ベンダーロックインを避けられる。ただし Zigbee の既存エコシステム(IKEA TRADFRI、Philips Hue)は Bridge経由で Matter に対応するため、既存デバイスの買い替えは不要。
Q2. Home Assistant の導入コストと難易度は?
Raspberry Pi 4/5(1-2万円)にインストールすれば最低限で始められる。専用ハードウェアの Home Assistant Green(約15,000円)やHome Assistant Yellow もある。初期設定はGUIで行え、基本的な自動化はYAML不要。高度なカスタマイズにはYAMLとPythonの知識が必要。
Q3. 音声アシスタントのプライバシーは大丈夫か?
Amazon Alexa と Google Assistant はデフォルトで音声をクラウドに送信する。プライバシーが重要なら、1) 録音データの自動削除を設定、2) Apple Siri(オンデバイス処理重視)を使う、3) Home Assistant のローカル音声処理(Wyoming protocol + Whisper + Piper)でクラウドを完全排除する。
Q4. Thread と Zigbee はどちらを選ぶべきか?
新規購入なら Thread を推奨する。Thread は IPv6 ネイティブであり、Matter の推奨トランスポート層として位置づけられている。ただし現時点では Zigbee のデバイス種類が圧倒的に多い。既存の Zigbee デバイスがあるなら Zigbee2MQTT で Home Assistant に統合しつつ、新規購入は Thread/Matter 対応を選ぶ「併用戦略」が現実的。Thread Border Router は Apple TV 4K、HomePod mini、Google Nest Hub (2nd gen) が対応しており、いずれかを所有していれば追加コストなしで Thread ネットワークを構築できる。
Q5. スマートホームのデバイスが100台を超えるとどうなる?
デバイス数が増えると以下の問題が発生しやすい。(1) Wi-Fi のみの構成では帯域不足でレスポンスが悪化する。Thread/Zigbee メッシュで負荷を分散すること。(2) Home Assistant の自動化が複雑化し、起動時間が長くなる。YAML を分割し、パッケージ構成(packages ディレクトリ)で管理する。(3) ダッシュボードが煩雑になる。部屋別・機能別のビューを作成し、custom:auto-entities カードで動的にフィルタリングする。(4) mDNS/DNS-SD のブロードキャストが増えるため、ネットワーク機器の処理能力に注意する。エンタープライズグレードのルーター(UniFi Dream Machine 等)を推奨する。
Q6. 停電時にスマートホームはどうなる?
UPS(無停電電源装置)を Home Assistant サーバーとネットワーク機器に接続することで、停電後も数十分から数時間の稼働が可能。スマートロックは電池駆動のため停電の影響を受けない。照明やエアコンは物理的に停止するが、復電後に自動的に前の状態に復帰するよう自動化を設定できる。蓄電池(テスラ Powerwall 等)があれば、太陽光発電と組み合わせて完全な停電対策が可能。Home Assistant の NUT(Network UPS Tools)統合で UPS の状態を監視し、バッテリー残量が低下したら安全にシャットダウンする自動化も推奨する。
まとめ
| 概念 | 要点 |
|---|---|
| Matter | Apple/Google/Amazon統一のスマートホーム規格 |
| Thread | 低消費電力メッシュネットワーク(Matter推奨通信層) |
| Home Assistant | オープンソースのローカルスマートホームハブ |
| 音声アシスタント | Alexa/Google/Siri + ローカルLLMの選択肢 |
| Frigate NVR | ローカルAIカメラ(Coral対応) |
| ローカルファースト | インターネット不要で基本機能が動作する設計 |
| VLAN分離 | IoTデバイスをメインネットワークから隔離 |
| エネルギー最適化AI | 行動予測による自動温度制御 |
| HEMS | 太陽光+蓄電池+動的料金の統合エネルギー管理 |
| Wyoming Protocol | ローカル音声処理のためのマイクロサービス接続規格 |
次に読むべきガイド
- 02-emerging/03-future-hardware.md — 未来のハードウェア:量子コンピュータ、ニューロモルフィック
- 02-emerging/01-robotics.md — ロボティクス:Boston Dynamics、Figure
- 01-computing/02-edge-ai.md — エッジAI:NPU、Coral、Jetson
参考文献
- CSA — Matter 仕様 https://csa-iot.org/all-solutions/matter/
- Home Assistant 公式ドキュメント https://www.home-assistant.io/docs/
- Thread Group 公式 https://www.threadgroup.org/
- Frigate NVR https://docs.frigate.video/
- ESPHome 音声アシスタント https://esphome.io/components/voice_assistant.html
- Wyoming Protocol https://github.com/rhasspy/wyoming
- Matter SDK (connectedhomeip) https://github.com/project-chip/connectedhomeip
- OpenThread https://openthread.io/