Files
nix-config/modules/nixos/homeassistant/services/homeassistant/default.nix
mjallen18 0beecf9cce hasp?
2026-03-05 14:33:30 -06:00

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"
];
};
};
};
};
};
}