651 lines
19 KiB
Nix
651 lines
19 KiB
Nix
{
|
|
config,
|
|
lib,
|
|
pkgs,
|
|
namespace,
|
|
...
|
|
}:
|
|
with lib;
|
|
let
|
|
cfg = config.${namespace}.services.home-assistant;
|
|
in
|
|
{
|
|
# disabledModules = [
|
|
# "services/home-automation/home-assistant.nix"
|
|
# ];
|
|
|
|
# imports = [
|
|
# "${inputs.nixpkgs-unstable}/nixos/modules/services/home-automation/home-assistant.nix"
|
|
# ];
|
|
|
|
config = mkIf cfg.enable {
|
|
|
|
services.home-assistant = {
|
|
enable = true;
|
|
package = pkgs.home-assistant;
|
|
openFirewall = true;
|
|
configDir = "/var/lib/homeassistant";
|
|
configWritable = true; # todo
|
|
# All components
|
|
# extraComponents = config.services.home-assistant.package.availableComponents;
|
|
extraComponents = [
|
|
"accuweather"
|
|
"adguard"
|
|
"air_quality"
|
|
"apcupsd"
|
|
"apple_tv"
|
|
"analytics"
|
|
"assist_pipeline"
|
|
"assist_satellite"
|
|
"backup"
|
|
"bluetooth"
|
|
"bluetooth_adapters"
|
|
"bluetooth_le_tracker"
|
|
"brother"
|
|
"browser"
|
|
"button"
|
|
"caldav"
|
|
"calendar"
|
|
"camera"
|
|
"cast"
|
|
"climate"
|
|
"cloud"
|
|
"cloudflare"
|
|
"co2signal"
|
|
"coinbase"
|
|
"color_extractor"
|
|
"config"
|
|
"configurator"
|
|
"conversation"
|
|
"counter"
|
|
"cpuspeed"
|
|
"date"
|
|
"datetime"
|
|
"deluge"
|
|
"device_automation"
|
|
"device_sun_light_trigger"
|
|
"device_tracker"
|
|
"dhcp"
|
|
"diagnostics"
|
|
"discord"
|
|
"dlna_dmr"
|
|
"dlna_dms"
|
|
"downloader"
|
|
"ecobee"
|
|
"energy"
|
|
"epic_games_store"
|
|
"esphome"
|
|
"event"
|
|
"fan"
|
|
"fastdotcom"
|
|
"ffmpeg"
|
|
"ffmpeg_motion"
|
|
"ffmpeg_noise"
|
|
"file"
|
|
"file_upload"
|
|
"filesize"
|
|
"filter"
|
|
"folder"
|
|
"fully_kiosk"
|
|
"generic"
|
|
"generic_thermostat"
|
|
# "geo_json_events"
|
|
# "geo_location"
|
|
# "geo_rss_events"
|
|
"github"
|
|
"gitlab_ci"
|
|
"glances"
|
|
"google"
|
|
"google_cloud"
|
|
"google_drive"
|
|
"google_mail"
|
|
"google_maps"
|
|
"google_photos"
|
|
"google_translate"
|
|
"govee_ble"
|
|
"gpsd"
|
|
"gpslogger"
|
|
"hardware"
|
|
"hddtemp"
|
|
"hdmi_cec"
|
|
"history"
|
|
"history_stats"
|
|
"holiday"
|
|
"homeassistant"
|
|
"homeassistant_alerts"
|
|
"homeassistant_sky_connect"
|
|
"homekit"
|
|
"homekit_controller"
|
|
"http"
|
|
"humidifier"
|
|
"ibeacon"
|
|
"image"
|
|
"image_processing"
|
|
"image_upload"
|
|
"immich"
|
|
"input_boolean"
|
|
"input_button"
|
|
"input_datetime"
|
|
"input_number"
|
|
"input_select"
|
|
"input_text"
|
|
"ios"
|
|
"ipp"
|
|
"isal"
|
|
"jellyfin"
|
|
"lidarr"
|
|
"light"
|
|
"litterrobot"
|
|
"local_calendar"
|
|
"local_file"
|
|
"local_ip"
|
|
"local_todo"
|
|
"logbook"
|
|
"logentries"
|
|
"logger"
|
|
"lovelace"
|
|
"manual_mqtt"
|
|
"matter"
|
|
"met"
|
|
"microsoft"
|
|
"min_max"
|
|
"mobile_app"
|
|
"mqtt"
|
|
"music_assistant"
|
|
"ntfy"
|
|
"nut"
|
|
"nextcloud"
|
|
"notify"
|
|
"nws"
|
|
"ollama"
|
|
"onedrive"
|
|
"onkyo"
|
|
"openhardwaremonitor"
|
|
"opensky"
|
|
"openweathermap"
|
|
"open_router"
|
|
"paperless_ngx"
|
|
"persistent_notification"
|
|
"pinecil"
|
|
"ping"
|
|
"piper"
|
|
"playstation_network"
|
|
"radarr"
|
|
"radio_browser"
|
|
"raspberry_pi"
|
|
"recorder"
|
|
"reddit"
|
|
"remote"
|
|
"remote_calendar"
|
|
"remote_rpi_gpio"
|
|
"roborock" # currently broken
|
|
"samsungtv"
|
|
"schedule"
|
|
"script"
|
|
"search"
|
|
"season"
|
|
"select"
|
|
"sense"
|
|
"sensor"
|
|
"shopping_list"
|
|
"simplefin"
|
|
"smartthings"
|
|
"sonarr"
|
|
"speedtestdotnet"
|
|
"sql"
|
|
"ssdp"
|
|
"statistics"
|
|
"stream"
|
|
"subaru"
|
|
"sun"
|
|
"switch"
|
|
"system_health"
|
|
"system_log"
|
|
"systemmonitor"
|
|
"tailscale"
|
|
"tasmota"
|
|
"tcp"
|
|
"template"
|
|
"text"
|
|
"thread"
|
|
"time"
|
|
"time_date"
|
|
"timer"
|
|
"torque"
|
|
"tplink"
|
|
"tuya"
|
|
"upnp"
|
|
"uptime"
|
|
"usb"
|
|
"vacuum"
|
|
"vlc"
|
|
"vesync"
|
|
"wake_on_lan"
|
|
"waze_travel_time"
|
|
"weather"
|
|
"weatherkit"
|
|
"webdav"
|
|
"webhook"
|
|
"whisper"
|
|
"whois"
|
|
"workday"
|
|
"wyoming"
|
|
"youtube"
|
|
"zeroconf"
|
|
"zha"
|
|
"zone"
|
|
];
|
|
|
|
customComponents =
|
|
with pkgs.home-assistant-custom-components;
|
|
[
|
|
# nixpkgs
|
|
auth_oidc
|
|
better_thermostat
|
|
localtuya
|
|
luxer_one
|
|
prometheus_sensor
|
|
roborock_custom_map
|
|
smartir
|
|
versatile_thermostat
|
|
]
|
|
++ (with pkgs.${namespace}; [
|
|
ha-anycubic
|
|
ha-bambulab
|
|
ha-bedjet
|
|
ha-gehome
|
|
# ha-govee
|
|
ha-icloud3
|
|
ha-local-llm
|
|
ha-mail-and-packages
|
|
ha-nanokvm
|
|
ha-openhasp
|
|
ha-overseerr
|
|
ha-petlibro
|
|
ha-wyzeapi
|
|
]);
|
|
|
|
customLovelaceModules = with pkgs.home-assistant-custom-lovelace-modules; [
|
|
atomic-calendar-revive
|
|
bubble-card
|
|
button-card
|
|
hourly-weather
|
|
mini-graph-card
|
|
mini-media-player
|
|
multiple-entity-row
|
|
mushroom
|
|
vacuum-card
|
|
weather-chart-card
|
|
zigbee2mqtt-networkmap
|
|
];
|
|
# use postgresql instead of sqlite
|
|
extraPackages =
|
|
ps:
|
|
with ps;
|
|
[
|
|
dateparser
|
|
psycopg2
|
|
]
|
|
++ (with pkgs.${namespace}; [
|
|
gehomesdk
|
|
magicattr
|
|
pyoverseerr
|
|
python-nanokvm
|
|
python-roborock
|
|
wyzeapy
|
|
]);
|
|
|
|
config = {
|
|
# Includes dependencies for a basic setup
|
|
# https://www.home-assistant.io/integrations/default_config/
|
|
default_config = { };
|
|
|
|
cloud = false;
|
|
|
|
frontend = {
|
|
themes = "!include_dir_merge_named themes";
|
|
};
|
|
|
|
"automation manual" = "!include_dir_merge_list /etc/hass";
|
|
"automation ui" = "!include automations.yaml";
|
|
"scene ui" = "!include scenes.yaml";
|
|
"script ui" = "!include scripts.yaml";
|
|
|
|
http = {
|
|
use_x_forwarded_for = true;
|
|
trusted_proxies = [
|
|
"172.30.33.0/24"
|
|
"10.0.1.4"
|
|
"10.0.1.3"
|
|
"10.0.1.18"
|
|
"10.0.1.0/24"
|
|
];
|
|
};
|
|
|
|
recorder = {
|
|
# db_url = "postgresql://@/hass"; # local DB
|
|
db_url = "postgresql://homeassistant@10.0.1.3/homeassistant";
|
|
purge_keep_days = 180;
|
|
};
|
|
|
|
auth_header = {
|
|
debug = false;
|
|
username_header = "X-authentik-username";
|
|
};
|
|
|
|
# https://www.home-assistant.io/integrations/ota_updater/
|
|
zha.zigpy_config.ota.z2m_remote_index = "https://raw.githubusercontent.com/Koenkk/zigbee-OTA/master/index.json";
|
|
|
|
openhasp = {
|
|
plate = {
|
|
# nodes = [
|
|
# "plate"
|
|
# ];
|
|
# pages_jsonl = [
|
|
# "pages.jsonl"
|
|
# "page1.jsonl"
|
|
# "page2.jsonl"
|
|
# ];
|
|
objects = [
|
|
|
|
# -----------------------------------------------------------------------
|
|
# PAGE 1 LIGHTS
|
|
# -----------------------------------------------------------------------
|
|
|
|
# -- Living Room Lights ---
|
|
{
|
|
obj = "p1b11"; # Toggle button
|
|
properties = {
|
|
val = '''{{ 1 if is_state("light.living_room_lights", "on") else 0 }}'';
|
|
text = '''{{ "\uE6E8" if is_state("light.living_room_lights", "on") else "\uE335" | e }}'';
|
|
text_color = '''{{ "#FFD700" if is_state("light.living_room_lights", "on") else "#666666" }}'';
|
|
};
|
|
event = {
|
|
down = {
|
|
action = "homeassistant.toggle";
|
|
target = {
|
|
entity_id = "light.living_room_lights";
|
|
};
|
|
};
|
|
};
|
|
}
|
|
{
|
|
obj = "p1b12"; # Brightness slider
|
|
properties = {
|
|
val = ''
|
|
{{ state_attr('light.living_room_lights', 'brightness') | int(default=0)
|
|
if state_attr('light.living_room_lights', 'brightness') != None else 0 }}'';
|
|
click = '''{{ 'false' if is_state('light.living_room_lights', 'off') else 'true' }}'';
|
|
};
|
|
event = {
|
|
changed = {
|
|
action = "light.turn_on";
|
|
data = {
|
|
brightness = "{{ val }}";
|
|
};
|
|
target = {
|
|
entity_id = "light.living_room_lights";
|
|
};
|
|
};
|
|
up = {
|
|
action = "light.turn_on";
|
|
data = {
|
|
brightness = "{{ val }}";
|
|
};
|
|
target = {
|
|
entity_id = "light.living_room_lights";
|
|
};
|
|
};
|
|
};
|
|
}
|
|
# -- Bedroom Lights ---
|
|
{
|
|
obj = "p1b21"; # Toggle button
|
|
properties = {
|
|
val = ''{{ 1 if is_state("light.bedroom_lights", "on") else 0 }}'';
|
|
text = ''{{ "\uE6E8" if is_state("light.bedroom_lights", "on") else "\uE335" | e }}'';
|
|
text_color = ''{{ "#FFD700" if is_state("light.bedroom_lights", "on") else "#666666" }}'';
|
|
};
|
|
event = {
|
|
down = {
|
|
action = "homeassistant.toggle";
|
|
target = {
|
|
entity_id = "light.bedroom_lights";
|
|
};
|
|
};
|
|
};
|
|
}
|
|
{
|
|
obj = "p1b22"; # Brightness slider
|
|
properties = {
|
|
val = ''
|
|
{{ state_attr('light.bedroom_lights', 'brightness') | int(default=0)
|
|
if state_attr('light.bedroom_lights', 'brightness') != None else 0 }}'';
|
|
click = ''{{ 'false' if is_state('light.bedroom_lights', 'off') else 'true' }}'';
|
|
};
|
|
event = {
|
|
changed = {
|
|
action = "light.turn_on";
|
|
data = {
|
|
brightness= "{{ val }}";
|
|
};
|
|
target = {
|
|
entity_id = "light.bedroom_lights";
|
|
};
|
|
};
|
|
up = {
|
|
action = "light.turn_on";
|
|
data = {
|
|
brightness = "{{ val }}";
|
|
};
|
|
target = {
|
|
entity_id = "light.bedroom_lights";
|
|
};
|
|
};
|
|
};
|
|
}
|
|
# -- Front Closet Lights ---
|
|
{
|
|
obj = "p1b31"; # Toggle button
|
|
properties = {
|
|
val = ''{{ 1 if is_state("light.front_closet_lights", "on") else 0 }}'';
|
|
text = ''{{ "\uE6E8" if is_state("light.front_closet_lights", "on") else "\uE335" | e }}'';
|
|
text_color = ''{{ "#FFD700" if is_state("light.front_closet_lights", "on") else "#666666" }}'';
|
|
};
|
|
event = {
|
|
down = {
|
|
action = "homeassistant.toggle";
|
|
target = {
|
|
entity_id = "light.front_closet_lights";
|
|
};
|
|
};
|
|
};
|
|
}
|
|
|
|
# -----------------------------------------------------------------------
|
|
# PAGE 2 FANS
|
|
# -----------------------------------------------------------------------
|
|
|
|
# -- Bedroom Fan (preset mode = auto/low/medium/high) ---
|
|
{
|
|
obj = "p2b11"; # Toggle button
|
|
properties = {
|
|
val = ''{{ 1 if is_state("fan.bedroom_fan", "on") else 0 }}'';
|
|
text = ''{{ "\uE210" if is_state("fan.bedroom_fan", "on") else "\uE210" | e }}'';
|
|
text_color = ''{{ "#4FC3F7" if is_state("fan.bedroom_fan", "on") else "#666666" }}'';
|
|
};
|
|
event = {
|
|
down = {
|
|
action = "fan.toggle";
|
|
target = {
|
|
entity_id = "fan.bedroom_fan";
|
|
};
|
|
};
|
|
};
|
|
}
|
|
{
|
|
obj = "p2b13"; # Preset mode dropdown (auto/low/medium/high)
|
|
properties = {
|
|
val = ''
|
|
{% set modes = ['auto', 'low', 'medium', 'high'] %}
|
|
{% set current = state_attr('fan.bedroom_fan', 'preset_mode') %}
|
|
{{ modes.index(current) if current in modes else 0 }}'';
|
|
click = ''{{ 'false' if is_state('fan.bedroom_fan', 'off') else 'true' }}'';
|
|
};
|
|
event = {
|
|
changed = {
|
|
action = "fan.set_preset_mode";
|
|
data = {
|
|
preset_mode= "{{ text }}";
|
|
};
|
|
target = {
|
|
entity_id = "fan.bedroom_fan";
|
|
};
|
|
};
|
|
};
|
|
}
|
|
|
|
# -- Bedroom Air Purifier ---
|
|
{
|
|
obj = "p2b21"; # Toggle button
|
|
properties = {
|
|
val = ''{{ 1 if is_state("fan.bedroom_air_purifier", "on") else 0 }}'';
|
|
text = ''{{ "\uE210" | e }}'';
|
|
text_color = ''{{ "#4FC3F7" if is_state("fan.bedroom_air_purifier", "on") else "#666666" }}'';
|
|
};
|
|
event = {
|
|
down = {
|
|
action = "fan.toggle";
|
|
target = {
|
|
entity_id = "fan.bedroom_air_purifier";
|
|
};
|
|
};
|
|
};
|
|
}
|
|
{
|
|
obj = "p2b22"; # Speed slider (0-100%)
|
|
properties = {
|
|
val = ''
|
|
{{ state_attr('fan.bedroom_air_purifier', 'percentage') | int(default=0)
|
|
if state_attr('fan.bedroom_air_purifier', 'percentage') != None else 0 }}'';
|
|
click = ''{{ 'false' if is_state('fan.bedroom_air_purifier', 'off') else 'true' }}'';
|
|
};
|
|
event = {
|
|
changed = {
|
|
action = "fan.set_percentage";
|
|
data = {
|
|
percentage = "{{ val }}";
|
|
};
|
|
target = {
|
|
entity_id = "fan.bedroom_air_purifier";
|
|
};
|
|
};
|
|
up = {
|
|
action = "fan.set_percentage";
|
|
data = {
|
|
percentage = "{{ val }}";
|
|
};
|
|
target = {
|
|
entity_id = "fan.bedroom_air_purifier";
|
|
};
|
|
};
|
|
};
|
|
}
|
|
|
|
# -- Living Room Air Purifier ---
|
|
{
|
|
obj = "p2b31"; # Toggle button
|
|
properties = {
|
|
val = ''{{ 1 if is_state("fan.living_room_air_purifier", "on") else 0 }}'';
|
|
text = ''{{ "\uE210" | e }}'';
|
|
text_color = ''{{ "#4FC3F7" if is_state("fan.living_room_air_purifier", "on") else "#666666" }}'';
|
|
};
|
|
event = {
|
|
down = {
|
|
action = "fan.toggle";
|
|
target = {
|
|
entity_id = "fan.living_room_air_purifier";
|
|
};
|
|
};
|
|
};
|
|
}
|
|
{
|
|
obj = "p2b32"; # Speed slider (0-100%)
|
|
properties = {
|
|
val = ''
|
|
{{ state_attr('fan.living_room_air_purifier', 'percentage') | int(default=0)
|
|
if state_attr('fan.living_room_air_purifier', 'percentage') != None else 0 }}'';
|
|
click = ''{{ 'false' if is_state('fan.living_room_air_purifier', 'off') else 'true' }}'';
|
|
};
|
|
event = {
|
|
changed = {
|
|
action = "fan.set_percentage";
|
|
data = {
|
|
percentage = "{{ val }}";
|
|
};
|
|
target = {
|
|
entity_id = "fan.living_room_air_purifier";
|
|
};
|
|
};
|
|
up = {
|
|
action = "fan.set_percentage";
|
|
data = {
|
|
percentage = "{{ val }}";
|
|
};
|
|
target = {
|
|
entity_id = "fan.living_room_air_purifier";
|
|
};
|
|
};
|
|
};
|
|
}
|
|
];
|
|
};
|
|
};
|
|
conversation = {
|
|
intents = {
|
|
GetStatus = [
|
|
"What's the status of {entity}"
|
|
"Is {entity} {state}"
|
|
"How is the {entity}"
|
|
"What is the {sensor_type} in {location}"
|
|
];
|
|
ControlDevice = [
|
|
"Turn {state} {entity}"
|
|
"Set {entity} to {value}"
|
|
"Adjust {entity} to {value}"
|
|
"Make {entity} {value}"
|
|
"{state} {entity}"
|
|
];
|
|
ActivateScene = [
|
|
"Activate {scene}"
|
|
"Set scene to {scene}"
|
|
"I'm {activity}"
|
|
"We're {activity}"
|
|
"Time for {activity}"
|
|
];
|
|
RunAutomation = [
|
|
"Run {automation}"
|
|
"Start {automation}"
|
|
"Trigger {automation}"
|
|
"Execute {automation}"
|
|
];
|
|
HomeQuery = [
|
|
"When did {entity} last change"
|
|
"How long has {entity} been {state}"
|
|
"Which {domain} are {state}"
|
|
"Where is {person}"
|
|
];
|
|
SystemCommand = [
|
|
"Restart Home Assistant"
|
|
"Reload {component}"
|
|
"What version are you running"
|
|
"Are there any errors"
|
|
"System status"
|
|
];
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
}
|