move modules to hass
This commit is contained in:
60
hosts/home-assistant.cloonar.com/modules/deconz/default.nix
Normal file
60
hosts/home-assistant.cloonar.com/modules/deconz/default.nix
Normal file
@@ -0,0 +1,60 @@
|
||||
{ config, lib, pkgs, stdenv, ... }:
|
||||
let
|
||||
deconz-full = pkgs.callPackage ./pkg/default.nix { };
|
||||
deconz = deconz-full.deCONZ;
|
||||
in
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
deconz
|
||||
];
|
||||
|
||||
|
||||
users.users."deconz" = {
|
||||
createHome = true;
|
||||
isSystemUser = true;
|
||||
group = "dialout";
|
||||
home = "/home/deconz";
|
||||
};
|
||||
|
||||
systemd.services.deconz = {
|
||||
enable = true;
|
||||
description = "deconz";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
stopIfChanged = false;
|
||||
serviceConfig = {
|
||||
ExecStart = "${deconz}/bin/deCONZ -platform minimal --http-port=8080 --ws-port=8081 --http-listen=127.0.0.1 --dev=/dev/ttyACM0";
|
||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||
Restart = "always";
|
||||
RestartSec = "10s";
|
||||
# StartLimitInterval = "1min";
|
||||
# StateDirectory = "/var/lib/deconz";
|
||||
User = "deconz";
|
||||
# DeviceAllow = "char-ttyUSB rwm";
|
||||
# DeviceAllow = "char-usb_device rwm";
|
||||
# AmbientCapabilities="CAP_NET_BIND_SERVICE CAP_KILL CAP_SYS_BOOT CAP_SYS_TIME";
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."deconz.cloonar.com" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
acmeRoot = null;
|
||||
extraConfig = ''
|
||||
proxy_buffering off;
|
||||
'';
|
||||
locations."/".extraConfig = ''
|
||||
set $p 8080;
|
||||
if ($http_upgrade = "websocket") {
|
||||
set $p 8081;
|
||||
}
|
||||
proxy_pass http://127.0.0.1:$p;
|
||||
proxy_set_header Host $host;
|
||||
proxy_redirect http:// https://;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
'';
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
{ config, pkgs, stdenv, buildFHSUserEnv, fetchurl, dpkg, qt5, sqlite, hicolor-icon-theme, libcap, libpng, libxcrypt-legacy, ... }:
|
||||
#ith import <nixpkgs> {};
|
||||
let
|
||||
version = "2.21.02";
|
||||
name = "deconz-${version}";
|
||||
in
|
||||
rec {
|
||||
deCONZ-deb = stdenv.mkDerivation {
|
||||
#builder = ./builder.sh;
|
||||
inherit name;
|
||||
dpkg = dpkg;
|
||||
src = fetchurl {
|
||||
url = "https://deconz.dresden-elektronik.de/ubuntu/stable/${name}-qt5.deb";
|
||||
sha256 = "2d5ab8af471ffa82fb0fd0c8a2f0bb09e7c0bd9a03ef887abe49c616c63042f0";
|
||||
};
|
||||
|
||||
dontConfigure = true;
|
||||
dontBuild = true;
|
||||
dontStrip = true;
|
||||
|
||||
buildInputs = [ dpkg sqlite hicolor-icon-theme libcap libpng qt5.qtbase qt5.qtserialport qt5.qtwebsockets qt5.wrapQtAppsHook libxcrypt-legacy ]; # qt5.qtserialport qt5.qtwebsockets ];
|
||||
|
||||
unpackPhase = "dpkg-deb -x $src .";
|
||||
installPhase = ''
|
||||
cp -r usr/* .
|
||||
cp -r ${libxcrypt-legacy}/lib/* share/deCONZ/plugins/
|
||||
cp -r share/deCONZ/plugins/* lib/
|
||||
cp -r . $out
|
||||
'';
|
||||
|
||||
};
|
||||
deCONZ = buildFHSUserEnv {
|
||||
name = "deCONZ";
|
||||
targetPkgs = pkgs: [
|
||||
deCONZ-deb
|
||||
];
|
||||
multiPkgs = pkgs: [
|
||||
dpkg
|
||||
qt5.qtbase
|
||||
qt5.qtserialport
|
||||
qt5.qtwebsockets
|
||||
qt5.wrapQtAppsHook
|
||||
sqlite
|
||||
hicolor-icon-theme
|
||||
libcap
|
||||
libpng
|
||||
];
|
||||
runScript = "deCONZ";
|
||||
};
|
||||
}
|
||||
103
hosts/home-assistant.cloonar.com/modules/home-assistant/ac.nix
Normal file
103
hosts/home-assistant.cloonar.com/modules/home-assistant/ac.nix
Normal file
@@ -0,0 +1,103 @@
|
||||
{
|
||||
services.home-assistant.extraComponents = [
|
||||
"daikin"
|
||||
];
|
||||
|
||||
services.home-assistant.config = {
|
||||
sensor = [
|
||||
{
|
||||
name = "Living Room Window Handle";
|
||||
platform = "enocean";
|
||||
id = [ 129 0 227 53 ];
|
||||
device_class = "windowhandle";
|
||||
}
|
||||
];
|
||||
"automation ac_livingroom" = {
|
||||
alias = "ac_livingroom";
|
||||
hide_entity = true;
|
||||
trigger = {
|
||||
platform = "state";
|
||||
entity_id = "sensor.windowhandle_living_room_window_handle";
|
||||
to = [ "open" "tilt" ];
|
||||
};
|
||||
action = {
|
||||
service = "climate.set_hvac_mode";
|
||||
target = {
|
||||
entity_id = "climate.livingroom_ac";
|
||||
};
|
||||
data = {
|
||||
hvac_mode = "off";
|
||||
};
|
||||
};
|
||||
};
|
||||
"automation ac_eco" = {
|
||||
alias = "ac_eco";
|
||||
hide_entity = true;
|
||||
trigger = {
|
||||
platform = "state";
|
||||
entity_id = [
|
||||
"climate.livingroom_ac"
|
||||
"climate.bedroom_ac"
|
||||
];
|
||||
to = [
|
||||
"heat"
|
||||
"cold"
|
||||
];
|
||||
};
|
||||
action = {
|
||||
service = "climate.set_preset_mode";
|
||||
target = {
|
||||
entity_id = "{{ trigger.entity_id }}";
|
||||
};
|
||||
data = {
|
||||
preset_mode = "eco";
|
||||
};
|
||||
};
|
||||
};
|
||||
"automation bedroom_ac_on" = {
|
||||
alias = "bedroom ac on";
|
||||
hide_entity = true;
|
||||
trigger = {
|
||||
platform = "time";
|
||||
at = "00:30:00";
|
||||
};
|
||||
action = {
|
||||
choose = [
|
||||
{
|
||||
conditions = [ "{{ states('sensor.bedroom_ac_inside_temperature') > 25 and states('sensor.bedroom_ac_outside_temperature') > 22 }}" ];
|
||||
sequence = [
|
||||
{
|
||||
service = "climate.set_hvac_mode";
|
||||
target = {
|
||||
entity_id = "climate.bedroom_ac";
|
||||
};
|
||||
data = {
|
||||
hvac_mode = "cold";
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
"automation bedroom_ac_off" = {
|
||||
alias = "bedroom ac on";
|
||||
hide_entity = true;
|
||||
trigger = {
|
||||
platform = "template";
|
||||
value_template = ''
|
||||
{{ now().timestamp() | timestamp_custom('%H:%M') == (as_timestamp(strptime(states('sensor.bedtime_alarm'), "%H:%M")) - 1800) | timestamp_custom('%H:%M', false) }}
|
||||
'';
|
||||
};
|
||||
action = {
|
||||
service = "climate.set_hvac_mode";
|
||||
target = {
|
||||
entity_id = "climate.bedroom_ac";
|
||||
};
|
||||
data = {
|
||||
hvac_mode = "off";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
services.home-assistant.package = pkgs.home-assistant.override {
|
||||
extraPackages = ps: with ps; [ pyelectroluxconnect ];
|
||||
|
||||
packageOverrides = self: super: {
|
||||
pyelectroluxconnect = super.buildPythonPackage rec {
|
||||
pname = "pyelectroluxconnect";
|
||||
version = "0.3.12";
|
||||
|
||||
src = super.fetchPypi {
|
||||
inherit pname version;
|
||||
sha256 = "sha256-g9UxkWuTIqJe0/CDk3kwU3dSmc+GXlfDMxdzu6CqyY0=";
|
||||
};
|
||||
|
||||
doCheck = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
# services.home-assistant.extraPackages = python3Packages: with python3Packages; [
|
||||
# (callPackage ../../pkgs/pyelectroluxconnect.nix)
|
||||
# ];
|
||||
|
||||
services.home-assistant.config = {
|
||||
electrolux_status = {
|
||||
username = "dominik@superbros.tv";
|
||||
password = "U26tTTYtXdhErWpbRxRRVZy541vFvWyn";
|
||||
region = "emea";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
{
|
||||
services.home-assistant.config = {
|
||||
sensor = [
|
||||
{
|
||||
platform = "template";
|
||||
sensors = {
|
||||
sensors_lowest_battery_level = {
|
||||
friendly_name = "Lowest battery level (Sensors)";
|
||||
entity_id = "sun.sun";
|
||||
device_class = "battery";
|
||||
unit_of_measurement = "%";
|
||||
value_template = ''
|
||||
{% set domains = ['sensor', 'battery'] %}
|
||||
{% set ns = namespace(min_batt=100, entities=[]) %}
|
||||
{%- set exclude_sensors = ['sensor.sensors_lowest_battery_level','sensor.dominiks_iphone_battery_level'] -%}
|
||||
{% for domain in domains %}
|
||||
{% set ns.entities = states[domain] %}
|
||||
{% for sensor in exclude_sensors %}
|
||||
{% set ns.entities = ns.entities | rejectattr('entity_id', 'equalto', sensor) %}
|
||||
{% endfor %}
|
||||
{% set batt_sensors = ns.entities | selectattr('attributes.device_class','equalto','battery') | map(attribute='state') | reject('equalto', 'unknown') | reject('equalto', 'None') | map('int') | reject('equalto', 0) | list %}
|
||||
{% set batt_attrs = ns.entities | selectattr('attributes.battery_level','defined') | map(attribute='attributes.battery_level') | reject('equalto', 'unknown') | reject('equalto', 'None') | map('int') | reject('equalto', 0) | list %}
|
||||
{% set batt_lvls = batt_sensors + batt_attrs %}
|
||||
{% if batt_lvls|length > 0 %}
|
||||
{% set _min = batt_lvls|min %}
|
||||
{% if _min < ns.min_batt %}
|
||||
{% set ns.min_batt = _min %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{ ns.min_batt }}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
binary_sensor = [
|
||||
{
|
||||
platform = "template";
|
||||
sensors = {
|
||||
sensor_low_battery = {
|
||||
value_template = "{{ states('sensor.sensors_lowest_battery_level')|int <= 30 }}";
|
||||
friendly_name = "A sensor has low battery";
|
||||
device_class = "problem";
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
alert = {
|
||||
sensor_low_battery = {
|
||||
name = "Sensor has low battery!";
|
||||
message = ''
|
||||
{%- set domains = ['sensor', 'battery'] -%}
|
||||
{%- set threshold = 30 -%}
|
||||
{%- set exclude_entities = ['sensor.sensors_lowest_battery_level','sensor.dominiks_iphone_battery_level'] -%}
|
||||
Sensors are below 50% battery:
|
||||
{%- for domain in domains -%}
|
||||
{%- for item in states[domain] -%}
|
||||
{%- if item.entity_id not in exclude_entities -%}
|
||||
{%- if item.attributes.battery_level is defined -%}
|
||||
{%- set level = item.attributes.battery_level|int -%}
|
||||
{% if level > 0 and level < threshold %}
|
||||
- {{ item.attributes.friendly_name }} ({{ item.attributes['battery_level']|int}}%)
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- if item.attributes.device_class is defined and item.attributes.device_class == 'battery' -%}
|
||||
{%- set level = item.state|int -%}
|
||||
{% if level > 0 and level <= threshold %}
|
||||
- {{ item.attributes.friendly_name }} ({{ item.state|int }}%)
|
||||
{%- endif -%}
|
||||
{%- endif %}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- endfor -%}
|
||||
'';
|
||||
entity_id = "binary_sensor.sensor_low_battery";
|
||||
state = "on";
|
||||
repeat = [
|
||||
5
|
||||
60
|
||||
360
|
||||
];
|
||||
skip_first = true;
|
||||
can_acknowledge = true;
|
||||
notifiers = [
|
||||
"NotificationGroup"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
{ pkgs, ... }: {
|
||||
imports = [
|
||||
./ac.nix
|
||||
# ./aeg.nix
|
||||
./battery.nix
|
||||
./ecovacs.nix
|
||||
./enocean.nix
|
||||
./ldap.nix
|
||||
./light.nix
|
||||
./locks.nix
|
||||
./multimedia.nix
|
||||
./notify.nix
|
||||
./pc.nix
|
||||
./presence.nix
|
||||
./pushover.nix
|
||||
./roborock.nix
|
||||
./scene-switch.nix
|
||||
./sleep.nix
|
||||
./snapcast.nix
|
||||
];
|
||||
|
||||
services.home-assistant = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
services.home-assistant.extraComponents = [
|
||||
"mobile_app"
|
||||
"shopping_list"
|
||||
"backup"
|
||||
"denonavr"
|
||||
"androidtv"
|
||||
"rainbird"
|
||||
];
|
||||
|
||||
services.home-assistant.config =
|
||||
let
|
||||
hiddenEntities = [
|
||||
"sensor.last_boot"
|
||||
"sensor.date"
|
||||
];
|
||||
in
|
||||
{
|
||||
homeassistant = {
|
||||
name = "Home";
|
||||
latitude = "!secret home_latitude";
|
||||
longitude = "!secret home_longitude";
|
||||
# elevation = "!secret home_elevation";
|
||||
unit_system = "metric";
|
||||
time_zone = "Europe/Vienna";
|
||||
country = "AT";
|
||||
};
|
||||
automation = "!include automations.yaml";
|
||||
frontend = { };
|
||||
http = {
|
||||
use_x_forwarded_for = true;
|
||||
trusted_proxies = [
|
||||
"127.0.0.1"
|
||||
"::1"
|
||||
];
|
||||
};
|
||||
history.exclude = {
|
||||
entities = hiddenEntities;
|
||||
domains = [
|
||||
"automation"
|
||||
"updater"
|
||||
];
|
||||
};
|
||||
"map" = { };
|
||||
enocean = {
|
||||
device = "/dev/serial/by-id/usb-EnOcean_GmbH_EnOcean_USB_300_DC_FT5OI9YG-if00-port0";
|
||||
};
|
||||
# logbook.exclude.entities = "hiddenEntities";
|
||||
logger = {
|
||||
default = "info";
|
||||
};
|
||||
|
||||
#icloud = {
|
||||
# username = "!secret icloud_email";
|
||||
# password = "!secret icloud_password";
|
||||
# with_family = true;
|
||||
#};
|
||||
network = { };
|
||||
zeroconf = { };
|
||||
system_health = { };
|
||||
default_config = { };
|
||||
system_log = { };
|
||||
sensor = [
|
||||
{
|
||||
platform = "template";
|
||||
sensors.bedtime_alarm = {
|
||||
friendly_name = "Bedtime Alarm";
|
||||
value_template = "09:00";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."home-assistant.cloonar.com" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
acmeRoot = null;
|
||||
extraConfig = ''
|
||||
proxy_buffering off;
|
||||
'';
|
||||
locations."/".extraConfig = ''
|
||||
proxy_pass http://127.0.0.1:8123;
|
||||
proxy_set_header Host $host;
|
||||
proxy_redirect http:// https://;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
'';
|
||||
};
|
||||
|
||||
sops.secrets."home-assistant-secrets.yaml" = {
|
||||
owner = "hass";
|
||||
path = "/var/lib/hass/secrets.yaml";
|
||||
restartUnits = [ "home-assistant.service" ];
|
||||
};
|
||||
|
||||
users.users.hass.extraGroups = [ "dialout" ];
|
||||
|
||||
networking.firewall = {
|
||||
allowedUDPPorts = [ 5683 ];
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
services.home-assistant.extraComponents = [
|
||||
"ecovacs"
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
services.home-assistant.config = {
|
||||
"binary_sensor pc_0" = [
|
||||
{
|
||||
platform = "enocean";
|
||||
id = [ 254 235 105 198 ];
|
||||
name = "enocean_switch_pc";
|
||||
}
|
||||
];
|
||||
logger.logs."homeassistant.components.enocean" = "debug";
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
{ pkgs
|
||||
, config
|
||||
, lib
|
||||
, ... }:
|
||||
let
|
||||
ldap-auth-sh = pkgs.stdenv.mkDerivation {
|
||||
name = "ldap-auth-sh";
|
||||
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = "efficiosoft";
|
||||
repo = "ldap-auth-sh";
|
||||
rev = "93b2c00413942908139e37c7432a12bcb705ac87";
|
||||
sha256 = "1pymp6ki353aqkigr89g7hg5x1mny68m31c3inxf1zr26n5s2kz8";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ pkgs.makeWrapper ];
|
||||
installPhase = ''
|
||||
mkdir -p $out/etc
|
||||
cat > $out/etc/home-assistant.cfg << 'EOF'
|
||||
CLIENT="ldapsearch"
|
||||
SERVER="ldaps://ldap.cloonar.com:636"
|
||||
USERDN="cn=home-assistant,ou=system,ou=users,dc=cloonar,dc=com"
|
||||
PW="$(<${config.sops.secrets.home-assistant-ldap.path})"
|
||||
BASEDN="ou=users,dc=cloonar,dc=com"
|
||||
SCOPE="one"
|
||||
FILTER="(&(objectClass=cloonarUser)(memberOf=cn=HomeAssistant,ou=groups,dc=cloonar,dc=com)(mail=$(ldap_dn_escape "$username")))"
|
||||
USERNAME_PATTERN='^[a-z|A-Z|0-9|_|-|.|@]+$'
|
||||
on_auth_success() {
|
||||
# print the meta entries for use in HA
|
||||
if echo "$output" | grep -qE '^(dn|DN):: '; then
|
||||
# ldapsearch base64 encodes non-ascii
|
||||
output=$(echo "$output" | sed -n -e "s/^\(dn\|DN\)\s*::\s*\(.*\)$/\2/p" | base64 -d)
|
||||
else
|
||||
output=$(echo "$output" | sed -n -e "s/^\(dn\|DN\)\s*:\s*\(.*\)$/\2/p")
|
||||
fi
|
||||
name=$(echo "$output" | sed -nr 's/^cn=([^,]+).*/\1/Ip')
|
||||
[ -z "$name" ] || echo "name=$name"
|
||||
}
|
||||
EOF
|
||||
install -D -m755 ldap-auth.sh $out/bin/ldap-auth.sh
|
||||
wrapProgram $out/bin/ldap-auth.sh \
|
||||
--prefix PATH : ${lib.makeBinPath [pkgs.openldap pkgs.coreutils pkgs.gnused pkgs.gnugrep]} \
|
||||
--add-flags "$out/etc/home-assistant.cfg"
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
services.home-assistant.config.homeassistant.auth_providers = [
|
||||
{
|
||||
type = "command_line";
|
||||
command = "${ldap-auth-sh}/bin/ldap-auth.sh";
|
||||
meta = true;
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
sops.secrets.home-assistant-ldap.owner = "hass";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,335 @@
|
||||
{
|
||||
services.home-assistant.extraComponents = [
|
||||
"deconz"
|
||||
"shelly"
|
||||
"sun"
|
||||
];
|
||||
|
||||
services.home-assistant.config = {
|
||||
homeassistant = {
|
||||
customize_domain = {
|
||||
light = {
|
||||
assumed_state = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
"automation light_sunrise" = {
|
||||
alias = "light_sunrise";
|
||||
hide_entity = true;
|
||||
trigger = {
|
||||
platform = "sun";
|
||||
event = "sunrise";
|
||||
};
|
||||
action = {
|
||||
service = "light.turn_on";
|
||||
target = {
|
||||
entity_id = "{{ states.light | selectattr(\"state\",\"eq\",\"on\") | map(attribute=\"entity_id\") | list }}";
|
||||
};
|
||||
data = {
|
||||
brightness_pct = 254;
|
||||
color_temp = 250;
|
||||
};
|
||||
};
|
||||
};
|
||||
"automation light_sunset" = {
|
||||
alias = "light_sunset";
|
||||
hide_entity = true;
|
||||
trigger = {
|
||||
platform = "sun";
|
||||
event = "sunset";
|
||||
};
|
||||
action = {
|
||||
service = "light.turn_on";
|
||||
target = {
|
||||
entity_id = "{{ states.light | selectattr(\"state\",\"eq\",\"on\") | map(attribute=\"entity_id\") | list }}";
|
||||
};
|
||||
data = {
|
||||
brightness_pct = 30;
|
||||
color_temp = 450;
|
||||
};
|
||||
};
|
||||
};
|
||||
"automation light_on" = {
|
||||
alias = "light_on";
|
||||
hide_entity = true;
|
||||
trigger = {
|
||||
platform = "state";
|
||||
entity_id = [
|
||||
"light.bed_room"
|
||||
"light.kitchen"
|
||||
"light.livingroom_lights"
|
||||
"light.hallway_lights"
|
||||
"light.bathroom_light"
|
||||
"light.toilett_lights"
|
||||
"light.storage_lights"
|
||||
];
|
||||
to = "on";
|
||||
};
|
||||
action = [
|
||||
{
|
||||
choose = [
|
||||
{
|
||||
conditions = [ "{{ state_attr('sun.sun', 'elevation') < 5 and trigger.entity_id == 'light.toilett_lights' }}" ];
|
||||
sequence = [
|
||||
{
|
||||
service = "light.turn_on";
|
||||
target = {
|
||||
entity_id = "{{ trigger.entity_id }}";
|
||||
};
|
||||
data = {
|
||||
brightness_pct = 30;
|
||||
color_temp = 450;
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
conditions = [ "{{ state_attr('sun.sun', 'elevation') < 5 and trigger.entity_id == 'light.hallway_lights' }}" ];
|
||||
sequence = [
|
||||
{
|
||||
service = "light.turn_on";
|
||||
target = {
|
||||
entity_id = "{{ trigger.entity_id }}";
|
||||
};
|
||||
data = {
|
||||
brightness_pct = 1;
|
||||
color_temp = 450;
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
conditions = [ "{{ state_attr('sun.sun', 'elevation') < 5 and trigger.entity_id == 'light.bathroom_light' }}" ];
|
||||
sequence = [
|
||||
{
|
||||
service = "light.turn_on";
|
||||
target = {
|
||||
entity_id = "{{ trigger.entity_id }}";
|
||||
};
|
||||
data = {
|
||||
brightness_pct = 30;
|
||||
color_temp = 450;
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
conditions = [ "{{ state_attr('sun.sun', 'elevation') < 5 and trigger.entity_id == 'light.livingroom_lights' }}" ];
|
||||
sequence = [
|
||||
{
|
||||
service = "light.turn_on";
|
||||
target = {
|
||||
entity_id = "{{ trigger.entity_id }}";
|
||||
};
|
||||
data = {
|
||||
brightness_pct = 5;
|
||||
color_temp = 450;
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
conditions = [ "{{ state_attr('sun.sun', 'elevation') < 5 and state_attr(trigger.entity_id, 'is_deconz_group') != None }}" ];
|
||||
sequence = [
|
||||
{
|
||||
service = "light.turn_on";
|
||||
target = {
|
||||
entity_id = "{{ trigger.entity_id }}";
|
||||
};
|
||||
data = {
|
||||
brightness_pct = 30;
|
||||
color_temp = 450;
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
conditions = [ "{{ state_attr('sun.sun', 'elevation') > 4 }}" ];
|
||||
sequence = [
|
||||
{
|
||||
service = "light.turn_on";
|
||||
target = {
|
||||
entity_id = "{{ trigger.entity_id }}";
|
||||
};
|
||||
data = {
|
||||
brightness_pct = 100;
|
||||
color_temp = 250;
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
"automation bathroom light small" = {
|
||||
alias = "bathroom light small";
|
||||
mode = "restart";
|
||||
hide_entity = true;
|
||||
trigger = {
|
||||
platform = "state";
|
||||
entity_id = [
|
||||
"light.bathroom_switch_channel_1"
|
||||
];
|
||||
from = "on";
|
||||
to = "off";
|
||||
};
|
||||
action = [
|
||||
{
|
||||
service = "switch.turn_off";
|
||||
target = {
|
||||
entity_id = "switch.bathroom_small";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
"automation bathroom light" = {
|
||||
alias = "bathroom light";
|
||||
mode = "restart";
|
||||
hide_entity = true;
|
||||
trigger = {
|
||||
platform = "state";
|
||||
entity_id = [
|
||||
"light.bathroom_switch_channel_1"
|
||||
];
|
||||
from = "off";
|
||||
to = "on";
|
||||
};
|
||||
action = [
|
||||
{
|
||||
delay = 3600;
|
||||
}
|
||||
{
|
||||
service = "light.turn_off";
|
||||
target = {
|
||||
entity_id = "light.bathroom_switch_channel_1";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
"automation bed_led" = {
|
||||
alias = "bed_led";
|
||||
mode = "restart";
|
||||
hide_entity = true;
|
||||
trigger = {
|
||||
platform = "state";
|
||||
entity_id = [
|
||||
"light.bedroom_led"
|
||||
];
|
||||
from = "off";
|
||||
to = "on";
|
||||
};
|
||||
action = [
|
||||
{
|
||||
delay = 10800;
|
||||
}
|
||||
{
|
||||
service = "light.turn_off";
|
||||
target = {
|
||||
entity_id = "{{ trigger.entity_id }}";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
"automation hallway_motion" = {
|
||||
alias = "Hallway Motion";
|
||||
hide_entity = true;
|
||||
trigger = {
|
||||
platform = "state";
|
||||
entity_id = "binary_sensor.hallway_motion_motion";
|
||||
};
|
||||
action = {
|
||||
service_template = "light.turn_{{ trigger.to_state.state }}";
|
||||
target = {
|
||||
entity_id = "light.hallway_lights";
|
||||
};
|
||||
};
|
||||
};
|
||||
"automation bed_button_1" = {
|
||||
alias = "bed_button_1";
|
||||
trigger = {
|
||||
platform = "event";
|
||||
event_type = "shelly.click";
|
||||
event_data = {
|
||||
device = "shellybutton1-E8DB84AA196D";
|
||||
};
|
||||
};
|
||||
action = [
|
||||
{
|
||||
choose = [
|
||||
{
|
||||
conditions = [ "{{ trigger.event.data.click_type == \"single\" }}" ];
|
||||
sequence = [
|
||||
{
|
||||
service = "light.toggle";
|
||||
entity_id = "light.bed_reading_1";
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
conditions = [ "{{ trigger.event.data.click_type == \"double\" }}" ];
|
||||
sequence = [
|
||||
{
|
||||
service = "light.toggle";
|
||||
entity_id = "light.bedroom_lights";
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
conditions = [ "{{ trigger.event.data.click_type == \"triple\" }}" ];
|
||||
sequence = [
|
||||
{
|
||||
service = "light.toggle";
|
||||
entity_id = "light.bedroom_bed";
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
"automation bed_button_2" = {
|
||||
alias = "bed_button_2";
|
||||
trigger = {
|
||||
platform = "event";
|
||||
event_type = "shelly.click";
|
||||
event_data = {
|
||||
device = "shellybutton1-E8DB84AA136D";
|
||||
};
|
||||
};
|
||||
action = [
|
||||
{
|
||||
choose = [
|
||||
{
|
||||
conditions = [ "{{ trigger.event.data.click_type == \"single\" }}" ];
|
||||
sequence = [
|
||||
{
|
||||
service = "light.toggle";
|
||||
entity_id = "light.bed_reading_2";
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
conditions = [ "{{ trigger.event.data.click_type == \"double\" }}" ];
|
||||
sequence = [
|
||||
{
|
||||
service = "light.toggle";
|
||||
entity_id = "light.bedroom_lights";
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
conditions = [ "{{ trigger.event.data.click_type == \"triple\" }}" ];
|
||||
sequence = [
|
||||
{
|
||||
service = "light.toggle";
|
||||
entity_id = "light.bedroom_bed";
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
{
|
||||
services.home-assistant.extraComponents = [
|
||||
"nuki"
|
||||
];
|
||||
|
||||
services.home-assistant.config = {
|
||||
"automation house_door" = {
|
||||
alias = "house_door";
|
||||
mode = "restart";
|
||||
hide_entity = true;
|
||||
trigger = {
|
||||
platform = "state";
|
||||
entity_id = [
|
||||
"person.dominik"
|
||||
];
|
||||
from = "not_home";
|
||||
to = "home";
|
||||
};
|
||||
action = [
|
||||
{
|
||||
service = "lock.unlock";
|
||||
target = {
|
||||
entity_id = "lock.house_door";
|
||||
};
|
||||
}
|
||||
{
|
||||
delay = "00:05:00";
|
||||
}
|
||||
{
|
||||
service = "lock.lock";
|
||||
target = {
|
||||
entity_id = "lock.house_door";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
"automation house_door_ring" = {
|
||||
alias = "house_door_ring";
|
||||
trigger = {
|
||||
platform = "event";
|
||||
event_type = "nuki_event";
|
||||
event_data = {
|
||||
type = "ring";
|
||||
};
|
||||
};
|
||||
action = [
|
||||
{
|
||||
choose = [
|
||||
{
|
||||
conditions = [ "{{ state.house_door == \"unlocked\" }}" ];
|
||||
sequence = [
|
||||
{
|
||||
service = "lock.lock";
|
||||
target = {
|
||||
entity_id = "lock.house_door";
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
binary_sensor = [
|
||||
{
|
||||
platform = "template";
|
||||
sensors = {
|
||||
lock_critical_battery = {
|
||||
value_template = ''
|
||||
{% set domains = ['lock'] %}
|
||||
{% set ns = namespace(crit=battery_critical, entities=[]) %}
|
||||
{% for domain in domains %}
|
||||
{% set batt_critical = states[domain] | selectattr('attributes.battery_critical','defined') | map(attribute='attributes.battery_critical') | reject('equalto', 'unknown') | reject('equalto', 'None') | map('int') | reject('equalto', 0) | list %}
|
||||
{% if batt_critical|length > 0 %}
|
||||
{% set ns.battery_critical = true %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{ ns.battery_critical }}
|
||||
'';
|
||||
friendly_name = "A lock has critical battery";
|
||||
device_class = "problem";
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
alert = {
|
||||
battery_critical = {
|
||||
name = "Lock has low battery!";
|
||||
message = ''
|
||||
{%- set domains = ['lock'] -%}
|
||||
Lock battery is critical:
|
||||
{%- for domain in domains -%}
|
||||
{%- for item in states[domain] -%}
|
||||
{%- if item.attributes.battery_critical is defined -%}
|
||||
{% if item.attributes.battery_critical %}
|
||||
- {{ item.attributes.friendly_name }}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- endfor -%}
|
||||
'';
|
||||
entity_id = "binary_sensor.lock_critical_battery";
|
||||
state = "on";
|
||||
repeat = [
|
||||
5
|
||||
60
|
||||
360
|
||||
];
|
||||
skip_first = true;
|
||||
can_acknowledge = true;
|
||||
notifiers = [
|
||||
"NotificationGroup"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
{
|
||||
services.home-assistant.config = {
|
||||
binary_sensor = [
|
||||
{
|
||||
name = "ps5_living";
|
||||
platform = "command_line";
|
||||
command = "python /var/lib/hass/ps5.py -q -b 10.42.96.176";
|
||||
device_class = "connectivity";
|
||||
scan_interval = 5;
|
||||
}
|
||||
{
|
||||
platform = "template";
|
||||
sensors = {
|
||||
multimedia_device_on = {
|
||||
friendly_name = "Any multimedia device on";
|
||||
device_class = "connectivity";
|
||||
value_template = ''
|
||||
{% if is_state('binary_sensor.ps5_living', 'on') or states('media_player.fire_tv_firetv_living_cloonar_com') != 'off' or states('device_tracker.xbox') == 'home' %}
|
||||
on
|
||||
{% else %}
|
||||
off
|
||||
{% endif %}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
# "automation tv scene" = {
|
||||
# alias = "auto tv scene";
|
||||
# hide_entity = true;
|
||||
# trigger = {
|
||||
# platform = "event";
|
||||
# event_type = "button_pressed";
|
||||
# event_data = {
|
||||
# id = [ 254 235 105 198 ];
|
||||
# };
|
||||
# };
|
||||
# action = {
|
||||
# service_template = "switch.turn_on";
|
||||
# data_template = {
|
||||
# entity_id = "switch.computer";
|
||||
# };
|
||||
# };
|
||||
# };
|
||||
# "automation beamer switch" = {
|
||||
# alias = "auto beamer scene";
|
||||
# hide_entity = true;
|
||||
# trigger = {
|
||||
# platform = "state";
|
||||
# entity_id = "sensor.computer_power";
|
||||
# };
|
||||
# condition = {
|
||||
# condition = "and";
|
||||
# conditions = [
|
||||
# {
|
||||
# condition = "numeric_state";
|
||||
# entity_id = "sensor.computer_power";
|
||||
# below = 15;
|
||||
# }
|
||||
# "{{ (as_timestamp(now()) - as_timestamp(states.switch.computer.last_changed)) > 300 }}"
|
||||
# ];
|
||||
# };
|
||||
# action = {
|
||||
# service = "switch.turn_off";
|
||||
# target = {
|
||||
# entity_id = [ "switch.computer" ];
|
||||
# };
|
||||
# };
|
||||
# };
|
||||
"automation xbox on" = {
|
||||
alias = "xbox on";
|
||||
hide_entity = true;
|
||||
trigger = {
|
||||
platform = "state";
|
||||
entity_id = "device-tracker.xbox";
|
||||
to = "home";
|
||||
};
|
||||
action = [
|
||||
{
|
||||
service = "media_player.select_source";
|
||||
target = {
|
||||
entity_id = "media_player.marantz_sr6015";
|
||||
};
|
||||
data = {
|
||||
source = "Xbox";
|
||||
};
|
||||
}
|
||||
{
|
||||
delay = 5;
|
||||
}
|
||||
{
|
||||
service = "denonavr.get_command";
|
||||
target = {
|
||||
entity_id = "media_player.marantz_sr6015";
|
||||
};
|
||||
data = {
|
||||
command = "/goform/formiPhoneAppDirect.xml?PWSTANDBY";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
"automation firetv on" = {
|
||||
alias = "firetv on";
|
||||
hide_entity = true;
|
||||
trigger = {
|
||||
platform = "state";
|
||||
entity_id = "media_player.fire_tv_firetv_living_cloonar_com";
|
||||
from = "off";
|
||||
};
|
||||
action = [
|
||||
{
|
||||
service = "denonavr.get_command";
|
||||
target = {
|
||||
entity_id = "media_player.marantz_sr6015";
|
||||
};
|
||||
data = {
|
||||
command = "/goform/formiPhoneAppDirect.xml?SIMPLAY";
|
||||
};
|
||||
}
|
||||
{
|
||||
delay = 5;
|
||||
}
|
||||
{
|
||||
service = "denonavr.get_command";
|
||||
target = {
|
||||
entity_id = "media_player.marantz_sr6015";
|
||||
};
|
||||
data = {
|
||||
command = "/goform/formiPhoneAppDirect.xml?PWSTANDBY";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
"automation ps5 on" = {
|
||||
alias = "ps5 on";
|
||||
hide_entity = true;
|
||||
trigger = {
|
||||
platform = "state";
|
||||
entity_id = "binary_sensor.ps5_living";
|
||||
to = "on";
|
||||
};
|
||||
action = [
|
||||
{
|
||||
service = "denonavr.get_command";
|
||||
target = {
|
||||
entity_id = "media_player.marantz_sr6015";
|
||||
};
|
||||
data = {
|
||||
command = "/goform/formiPhoneAppDirect.xml?SIBD";
|
||||
};
|
||||
}
|
||||
{
|
||||
delay = 5;
|
||||
}
|
||||
{
|
||||
service = "denonavr.get_command";
|
||||
target = {
|
||||
entity_id = "media_player.marantz_sr6015";
|
||||
};
|
||||
data = {
|
||||
command = "/goform/formiPhoneAppDirect.xml?PWSTANDBY";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
"automation all multimedia off" = {
|
||||
alias = "all multimedia off";
|
||||
trigger = {
|
||||
platform = "state";
|
||||
entity_id = "binary_sensor.multimedia_device_on";
|
||||
to = "off";
|
||||
};
|
||||
action = [
|
||||
{
|
||||
conditions = [ "{{ states('media_player.android_tv_metz_cloonar_com') != 'off'}}" ];
|
||||
sequence = [
|
||||
{
|
||||
service = "androidtv.adb_command";
|
||||
target = {
|
||||
device_id = "a5e50f268f3a2dbd0741fb8e9ff7f931";
|
||||
};
|
||||
data = {
|
||||
command = "POWER";
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
service = "denonavr.get_command";
|
||||
target = {
|
||||
entity_id = "media_player.marantz_sr6015";
|
||||
};
|
||||
data = {
|
||||
command = "/goform/formiPhoneAppDirect.xml?PWSTANDBY";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
"automation all_multimedia_on" = {
|
||||
alias = "all multimedia on";
|
||||
trigger = {
|
||||
platform = "state";
|
||||
entity_id = "binary_sensor.multimedia_device_on";
|
||||
to = "on";
|
||||
};
|
||||
condition = {
|
||||
condition = "or";
|
||||
conditions = [
|
||||
{
|
||||
condition = "state";
|
||||
entity_id = "media_player.android_tv_metz_cloonar_com";
|
||||
state = "off";
|
||||
}
|
||||
{
|
||||
condition = "state";
|
||||
entity_id = "media_player.android_tv_metz_cloonar_com";
|
||||
state = "unavailable";
|
||||
}
|
||||
];
|
||||
};
|
||||
action = [
|
||||
{
|
||||
service = "androidtv.adb_command";
|
||||
target = {
|
||||
device_id = "a5e50f268f3a2dbd0741fb8e9ff7f931";
|
||||
};
|
||||
data = {
|
||||
command = "POWER";
|
||||
};
|
||||
}
|
||||
{
|
||||
delay = 5;
|
||||
}
|
||||
{
|
||||
service = "androidtv.adb_command";
|
||||
target = {
|
||||
device_id = "a5e50f268f3a2dbd0741fb8e9ff7f931";
|
||||
};
|
||||
data = {
|
||||
command = "adb shell am start -a android.intent.action.VIEW -d content://android.media.tv/passthrough/com.mediatek.tvinput%2F.hdmi.HDMIInputService%2FHDMI100004";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
# "automation multimedia input" = {
|
||||
# hide_entity = true;
|
||||
# trigger = {
|
||||
# platform = "state";
|
||||
# entity_id = "sensor.computer_power";
|
||||
# };
|
||||
# condition = {
|
||||
# condition = "and";
|
||||
# conditions = [
|
||||
# {
|
||||
# condition = "numeric_state";
|
||||
# entity_id = "sensor.computer_power";
|
||||
# below = 15;
|
||||
# }
|
||||
# "{{ (as_timestamp(now()) - as_timestamp(states.switch.computer.last_changed)) > 300 }}"
|
||||
# ];
|
||||
# };
|
||||
# action = {
|
||||
# service = "switch.turn_off";
|
||||
# target = {
|
||||
# entity_id = [ "switch.computer" ];
|
||||
# };
|
||||
# };
|
||||
# };
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
{
|
||||
services.home-assistant.extraComponents = [
|
||||
"nuki"
|
||||
];
|
||||
|
||||
services.home-assistant.config = {
|
||||
"automation house_door" = {
|
||||
alias = "house_door";
|
||||
mode = "restart";
|
||||
hide_entity = true;
|
||||
trigger = {
|
||||
platform = "state";
|
||||
entity_id = [
|
||||
"person.dominik"
|
||||
];
|
||||
from = "not_home";
|
||||
to = "home";
|
||||
};
|
||||
action = [
|
||||
{
|
||||
service = "lock.unlock";
|
||||
target = {
|
||||
entity_id = "lock.house_door";
|
||||
};
|
||||
}
|
||||
{
|
||||
delay = "00:05:00";
|
||||
}
|
||||
{
|
||||
service = "lock.lock";
|
||||
target = {
|
||||
entity_id = "lock.house_door";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
"automation house_door_ring" = {
|
||||
alias = "house_door_ring";
|
||||
trigger = {
|
||||
platform = "event";
|
||||
event_type = "nuki_event";
|
||||
event_data = {
|
||||
type = "ring";
|
||||
};
|
||||
};
|
||||
action = [
|
||||
{
|
||||
choose = [
|
||||
{
|
||||
conditions = [ "{{ state.house_door == \"unlocked\" }}" ];
|
||||
sequence = [
|
||||
{
|
||||
service = "lock.lock";
|
||||
target = {
|
||||
entity_id = "lock.house_door";
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
{ ... }: {
|
||||
virtualisation = {
|
||||
podman = {
|
||||
enable = true;
|
||||
|
||||
# Create a `docker` alias for podman, to use it as a drop-in replacement
|
||||
dockerCompat = true;
|
||||
|
||||
# Required for containers under podman-compose to be able to talk to each other.
|
||||
defaultNetwork.settings.dns_enabled = true;
|
||||
# For Nixos version > 22.11
|
||||
#defaultNetwork.settings = {
|
||||
# dns_enabled = true;
|
||||
#};
|
||||
};
|
||||
};
|
||||
|
||||
virtualisation.oci-containers = {
|
||||
backend = "podman";
|
||||
containers.homeassistant = {
|
||||
volumes = [ "home-assistant:/config" ];
|
||||
environment.TZ = "Europe/Vienna";
|
||||
image = "ghcr.io/home-assistant/home-assistant:2023.7.3";
|
||||
extraOptions = [
|
||||
"--network=host"
|
||||
"--device=/dev/serial/by-id/usb-EnOcean_GmbH_EnOcean_USB_300_DC_FT5OI9YG-if00-port0:/dev/serial/by-id/usb-EnOcean_GmbH_EnOcean_USB_300_DC_FT5OI9YG-if00-port0"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."home-assistant.cloonar.com" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
acmeRoot = null;
|
||||
extraConfig = ''
|
||||
proxy_buffering off;
|
||||
'';
|
||||
locations."/".extraConfig = ''
|
||||
proxy_pass http://127.0.0.1:8123;
|
||||
proxy_set_header Host $host;
|
||||
proxy_redirect http:// https://;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
'';
|
||||
};
|
||||
|
||||
networking.firewall = {
|
||||
allowedUDPPorts = [
|
||||
5683 # shelly coiot
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
services.home-assistant.config = {
|
||||
notify = [
|
||||
{
|
||||
name = "NotificationGroup";
|
||||
platform = "group";
|
||||
services = [
|
||||
{
|
||||
service = "pushover_dominik";
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
services.home-assistant.config = {
|
||||
"automation pc_switch" = {
|
||||
alias = "switch pc";
|
||||
hide_entity = true;
|
||||
trigger = {
|
||||
platform = "event";
|
||||
event_type = "button_pressed";
|
||||
event_data = {
|
||||
id = [ 254 235 105 198 ];
|
||||
};
|
||||
};
|
||||
action = {
|
||||
service_template = "switch.turn_on";
|
||||
data_template = {
|
||||
entity_id = "switch.computer";
|
||||
};
|
||||
};
|
||||
};
|
||||
"automation pc power" = {
|
||||
alias = "auto pc power off";
|
||||
hide_entity = true;
|
||||
trigger = {
|
||||
platform = "state";
|
||||
entity_id = "sensor.computer_power";
|
||||
};
|
||||
condition = {
|
||||
condition = "and";
|
||||
conditions = [
|
||||
{
|
||||
condition = "numeric_state";
|
||||
entity_id = "sensor.computer_power";
|
||||
below = 15;
|
||||
}
|
||||
"{{ (as_timestamp(now()) - as_timestamp(states.switch.computer.last_changed)) > 300 }}"
|
||||
];
|
||||
};
|
||||
action = {
|
||||
service = "switch.turn_off";
|
||||
target = {
|
||||
entity_id = [ "switch.computer" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
services.home-assistant.extraComponents = [
|
||||
"mqtt_room"
|
||||
"opnsense"
|
||||
];
|
||||
services.home-assistant.config = {
|
||||
opnsense = {
|
||||
url = "https://fw.cloonar.com/api";
|
||||
api_secret = "!secret opnsense_api_secret";
|
||||
api_key = "!secret opnsense_api_key";
|
||||
};
|
||||
sensor = [
|
||||
{
|
||||
platform = "mqtt_room";
|
||||
name = "Dominiks iPhone BLE";
|
||||
device_id = "roomAssistant:d2a41d13-16bf-41fb-af4b-c520bdc7b68a";
|
||||
# device_id = "0a666fe0ccd0d587414fec9b9946168f";
|
||||
state_topic = "espresense/rooms";
|
||||
away_timeout = 30;
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{ config, ... }:
|
||||
{
|
||||
config.sops.secrets.ps5-mqtt-env.restartUnits = [ "podman-ps5Mqtt.service" ];
|
||||
|
||||
config.virtualisation.oci-containers.containers = {
|
||||
ps5Mqtt = {
|
||||
image = "ghcr.io/funkeyflo/ps5-mqtt/amd64:latest ";
|
||||
# ports = ["127.0.0.1:8645:8645"];
|
||||
volumes = [
|
||||
"/var/lib/ps5-mqtt:/config"
|
||||
];
|
||||
# entrypoint = "/config/run.sh";
|
||||
entrypoint = "/usr/bin/node";
|
||||
cmd = [
|
||||
"app/server/dist/index.js"
|
||||
];
|
||||
# entrypoint = "/bin/bash";
|
||||
# cmd = [
|
||||
# "-c \"echo $MQTT_HOST\""
|
||||
# ];
|
||||
environmentFiles = [
|
||||
config.sops.secrets.ps5-mqtt-env.path
|
||||
];
|
||||
extraOptions = [
|
||||
"--network=host"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
config.networking.firewall = {
|
||||
enable = true;
|
||||
allowedTCPPorts = [ 8645 ];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
services.home-assistant.extraComponents = [
|
||||
"pushover"
|
||||
];
|
||||
|
||||
# services.home-assistant.config = {
|
||||
# notify = [
|
||||
# {
|
||||
# name = "pushover_dominik";
|
||||
# platform = "pushover";
|
||||
# api_key = "!secret pushover_dominik_api_key";
|
||||
# user_key = "!secret pushover_dominik_user_key";
|
||||
# }
|
||||
# ];
|
||||
# };
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
services.home-assistant.extraComponents = [
|
||||
"roborock"
|
||||
];
|
||||
|
||||
services.home-assistant.config = {
|
||||
"automation roborock" = {
|
||||
alias = "roborock";
|
||||
hide_entity = false;
|
||||
trigger = {
|
||||
platform = "state";
|
||||
entity_id = [
|
||||
"person.dominik"
|
||||
];
|
||||
from = "home";
|
||||
to = "not_home";
|
||||
};
|
||||
action = [
|
||||
{
|
||||
service = "vacuum.start";
|
||||
target = {
|
||||
device_id = "136c307ff46cd968d08e9f9d20886755";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
services.home-assistant.config = {
|
||||
"automation scene_switch" = {
|
||||
alias = "switch scene";
|
||||
hide_entity = true;
|
||||
trigger = {
|
||||
platform = "event";
|
||||
event_type = "button_pressed";
|
||||
event_data = {
|
||||
id = [ 254 242 234 134 ];
|
||||
};
|
||||
};
|
||||
action = {
|
||||
service_template = "switch.turn_on";
|
||||
data_template = {
|
||||
entity_id = "switch.computer";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
home-assistant-ldap: ENC[AES256_GCM,data:De7kuRji+flc0juqE3z1MyNo938Y18jhYtxHkvBX1AsmcJO6a37qJ6o9eCVyhcN/uyaS8cySucqKErh3SlCOZw==,iv:DD4Bp7yU0TCQ/Zeildmrt1HSUbuJgQ0L2UUSmMi6Obo=,tag:t1Hz0GiXzodVK64e0Xuf6g==,type:str]
|
||||
home-assistant-secrets.yaml: ENC[AES256_GCM,data:owCBlfPXA66zxGaMwo6mViSZS7f3WPXOTtWiWFR8R/9Cqv7YvIaY7cqYX1OYFfEJyMyq6YLhVV9Zi0/K40VtUmhgR324x/knQbKkZGxv6gwqdIZ/zaZgQIu29xtY4DQnK24/5942HtisSnQnJxgbpchnjJCAQqri2/68LjGh8GoJVhF34Zji0MHBLAxR1y5JApOb5GUpc0ftMu4j6cbU/qxiZbRkzbrjlgAjBFjARYmsaWiilXg5jT2pf0Fz6bOHslcO+b3qePgIb/cJPP9aVYy76QA0oZ03f3Qu0w+IsjBKuXGaWKVBWBDyK1E37Y/Xif8w3H3cPqkAI6qxCPXi7djYfEpOz2M1L+5GTJGJz8fmvYzVJqU+hpZeI/7qJdiQ4/98YfuDU6nTEwWumcsPKsafJzdSeVfFYcE2x1H+QJDfJ3sgWJkfLDOrRxaXIwoXeSBSYAXPxjdomBzcdgKvo8MBH47pDbR4hK+y8+0LnoPafIyh8+FeAFzbn6/9ScWzF/MOyxFnap3edd12k5yWN+Yc4xacye3RR1h/mp1+DQF9xZ1xMTE70nwNdtIsGU0cV8qUvPgknZB/0US2oZ19fdxVuAN2rneEkK/nIGoKVw==,iv:x/F8CnsxROweCosvX1yAMHzwtI34kGauPvWF8yu2Yf8=,tag:WbzjtVhEPgUhL8g07kHjdA==,type:str]
|
||||
ps5-mqtt-env: ENC[AES256_GCM,data:g079HmYjMQ/Dr/vHSuxnLDwyOG3bSmzGtUfQLXJgKFUoC+5dAyUwYu8WRD1hskER2v8yIz2oHx8dQXLuWsmKYRErk6Sybpe0+FOcqOvAXgzv1ow95sjClkrS+rwjHcoHb1nts5lP5bGkY0e4Z6Dfn5AoeQ4pEA1TOzANvPDqDZUBh+L4hUDkDSWg7sAH3pHK0BqZHwiDNrvE9ac8MFHJmrPVEr4dqhRwAip+YMAdGCwp0ofdm2amUL7aHTaCQhjgsAW306C8ksMwuFE+dAvsqJGZ1N5T2nxP9LYVWcc8ZsKV8VklZ/QS6ScBGz4Oi4YpPDvkt+ErY929t0vISjKengnDHhu/+WYaBxeVbre5G29hK+jrnmUHFBa6pjwCSFVJq8mRIn6KorGwltxObyFBxddf+kiAMDbvnqW3E6sZtW+mF+48hTD8ygjSE8D8h7IoyYYTh0nPY4DzkfMR2OXqpz+bh+dpjnh3UQktJ1HXh902A2ljmxUEMGWtcOc2fDTxEMheTqdvg2z7Ek/FIwq/curVbdHIrzeIXDis7LIRk4G8b4mA6nHG4KrzCF00LAV7Ph9Nx1wAgrxvBTq4bqnO2VP44vtDsQ/O+Dr+wZSlP3EL4PsAJznfa7YcvStvV1Nn6FrVY04W,iv:1vttyQqYffChK12Wy5KTZEZ00pESsMefXHbulKsDSqU=,tag:pzgw0jJqICaro2U2FfQEiA==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age16veg3fmvpfm7a89a9fc8dvvsxmsthlm70nfxqspr6t8vnf9wkcwsvdq38d
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBieVNmLy9zK1hXWHdGRHF3
|
||||
WXd5b0pjR0pBaFkvVSt5ZVNyaUlCL0R1c2lnCkRCY1RmZnY1UVFuWURUMElHcFU1
|
||||
WHgrZE5ZY3FQUVp2VkhIcHh3WDV4aUUKLS0tIGFRZFNsKzU4ZDhPQ0NLbmtPSEJB
|
||||
YW8zNjhYWGNRcy9VbEZoaWplakVNWkUK48LBhFusDMZj2momMwRXdU7bLiGvzvqX
|
||||
QwdxorLMP2/GW6x5xpFj1khLCwxYDOys4xGvmE89hYZa++OSYU+Ejw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1ezq2j34qngky22enhnslx6hzh4ekwk8dtmn6c9us0uqxqpn7hgpsspjz58
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwY0pGaUU3alJrYmhQM2Y4
|
||||
TTMrbGsrRThlTUN1R3RCbFZFeVR1KzVDMWg4CnlQTzBzdTNPMTFvTUVYRXFEbUVP
|
||||
YWFvRTJqZjcxZHhtRkJrajNuUWoyYzgKLS0tIEhVcFI4N0E4VEVOZDIxREJ4bkNi
|
||||
UjRhRVpkTHF5a3p2bjhiVDZwMWRWMkEKpsHLWcPGQWpBo4Z8h7XFOP0bCct83BPj
|
||||
d/QDjarzugd6jamWVXKidZwADxfP59Pvo9JmLlFL5isgZ1TL3ZHL+g==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2023-04-26T13:33:07Z"
|
||||
mac: ENC[AES256_GCM,data:i/2+Qr0ihMaDPF22pyo7Qy3SYEr0Fr5dfRJSZ9xMu/5TFSm3GXNhd2KZVXjl6isbPbD22/siuI2MZeSB/iTFcRadtswmGnb6Lgsi8K/LULKvwXHf5t/Py/z59CpXBSgfUQQ6BuodNc25DRpCX8HEhFfd3Ajgyavc8vHVpnwG8eQ=,iv:Xu3WsyIqDbtReP9pBsiEf17pAbdVrY/y6wM2dleguFQ=,tag:gh6m7MUzMx2/lsZ5XExwyw==,type:str]
|
||||
pgp: []
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.7.3
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
services.home-assistant.config.shelly = {
|
||||
FindAndroid = {
|
||||
speech.text = "Send notification";
|
||||
action = {
|
||||
service = "notify.pushover";
|
||||
data = {
|
||||
message = "Phonefinderalert";
|
||||
target = "android";
|
||||
data.sound = "echo";
|
||||
data.priority = 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
{
|
||||
services.home-assistant.config = {
|
||||
"automation wakeup" = {
|
||||
alias = "wakeup";
|
||||
hide_entity = true;
|
||||
trigger = {
|
||||
platform = "template";
|
||||
value_template = ''
|
||||
{{ now().timestamp() | timestamp_custom('%H:%M') == (as_timestamp(strptime(states('sensor.bedtime_alarm'), "%H:%M")) - 1800) | timestamp_custom('%H:%M', false) }}
|
||||
'';
|
||||
};
|
||||
action = {
|
||||
service_template = "switch.turn_on";
|
||||
data_template = {
|
||||
entity_id = "switch.coffee_switch";
|
||||
};
|
||||
};
|
||||
};
|
||||
"automation sleep" = {
|
||||
alias = "sleep";
|
||||
hide_entity = true;
|
||||
trigger = [
|
||||
{
|
||||
platform = "event";
|
||||
event_type = "shelly.click";
|
||||
event_data = {
|
||||
device = "shellybutton1-E8DB84AA196D";
|
||||
};
|
||||
}
|
||||
{
|
||||
platform = "event";
|
||||
event_type = "shelly.click";
|
||||
event_data = {
|
||||
device = "shellybutton1-E8DB84AA136D";
|
||||
};
|
||||
}
|
||||
];
|
||||
action = [
|
||||
{
|
||||
choose = [
|
||||
{
|
||||
conditions = [ "{{ trigger.event.data.click_type == \"long\" }}" ];
|
||||
sequence = [
|
||||
{
|
||||
service = "light.turn_off";
|
||||
entity_id = "all";
|
||||
}
|
||||
{
|
||||
service = "light.turn_on";
|
||||
entity_id = "light.bedroom_bed";
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
{
|
||||
services.home-assistant = {
|
||||
extraComponents = [ "snapcast" ];
|
||||
config = {
|
||||
# "media_player" = {
|
||||
# platform = "snapcast";
|
||||
# host = "snapcast.cloonar.com";
|
||||
# };
|
||||
"automation toilett_music" = {
|
||||
alias = "toilett music";
|
||||
hide_entity = true;
|
||||
trigger = {
|
||||
platform = "state";
|
||||
entity_id = "light.toilett_switch";
|
||||
};
|
||||
action = {
|
||||
choose = [
|
||||
{
|
||||
conditions = [ "{{trigger.to_state.state == 'on'}}" ];
|
||||
sequence = [
|
||||
{
|
||||
service = "media_player.volume_mute";
|
||||
target = {
|
||||
entity_id = "media_player.snapcast_client_e4_5f_01_3c_fb_c3";
|
||||
};
|
||||
data = {
|
||||
is_volume_muted = false;
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
conditions = [ "{{trigger.to_state.state == 'off'}}" ];
|
||||
sequence = [
|
||||
{
|
||||
service = "media_player.volume_mute";
|
||||
target = {
|
||||
entity_id = "media_player.snapcast_client_e4_5f_01_3c_fb_c3";
|
||||
};
|
||||
data = {
|
||||
is_volume_muted = true;
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
"automation piano" = {
|
||||
alias = "piano";
|
||||
hide_entity = true;
|
||||
trigger = {
|
||||
platform = "state";
|
||||
entity_id = "media_player.snapcast_client_e4_5f_01_96_c1_1e";
|
||||
attribute = "is_volume_muted";
|
||||
};
|
||||
action = {
|
||||
service = "switch.turn_on";
|
||||
target = {
|
||||
entity_id = "switch.piano_switch_power";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
59
hosts/home-assistant.cloonar.com/modules/mopidy.nix
Normal file
59
hosts/home-assistant.cloonar.com/modules/mopidy.nix
Normal file
@@ -0,0 +1,59 @@
|
||||
{ pkgs, lib, ... }:
|
||||
let
|
||||
mopidy-autoplay = pkgs.python3Packages.buildPythonApplication rec {
|
||||
pname = "Mopidy-Autoplay";
|
||||
version = "0.2.3";
|
||||
|
||||
src = pkgs.python3Packages.fetchPypi {
|
||||
inherit pname version;
|
||||
sha256 = "sha256-E2Q+Cn2LWSbfoT/gFzUfChwl67Mv17uKmX2woFz/3YM=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [
|
||||
pkgs.mopidy
|
||||
] ++ (with pkgs.python3Packages; [
|
||||
configobj
|
||||
]);
|
||||
|
||||
# no tests implemented
|
||||
doCheck = false;
|
||||
|
||||
meta = with lib; {
|
||||
homepage = "https://codeberg.org/sph/mopidy-autoplay";
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
services.mopidy = {
|
||||
enable = true;
|
||||
extensionPackages = [ pkgs.mopidy-iris pkgs.mopidy-tunein mopidy-autoplay ];
|
||||
configuration = ''
|
||||
[audio]
|
||||
output = audioresample ! audioconvert ! audio/x-raw,rate=48000,channels=2,format=S16LE ! wavenc ! filesink location=/run/snapserver/mopidy
|
||||
|
||||
[file]
|
||||
enabled = false
|
||||
|
||||
[autoplay]
|
||||
enabled = true
|
||||
'';
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."mopidy.cloonar.com" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
acmeRoot = null;
|
||||
extraConfig = ''
|
||||
proxy_buffering off;
|
||||
'';
|
||||
locations."/".extraConfig = ''
|
||||
proxy_pass http://127.0.0.1:6680;
|
||||
proxy_set_header Host $host;
|
||||
proxy_redirect http:// https://;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
'';
|
||||
};
|
||||
}
|
||||
32
hosts/home-assistant.cloonar.com/modules/mosquitto.nix
Normal file
32
hosts/home-assistant.cloonar.com/modules/mosquitto.nix
Normal file
@@ -0,0 +1,32 @@
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
services.mosquitto = {
|
||||
enable = true;
|
||||
|
||||
listeners = [
|
||||
{
|
||||
users."espresense" = {
|
||||
password = "insecure-password";
|
||||
acl = [ "readwrite #" ];
|
||||
};
|
||||
users."home-assistant" = {
|
||||
hashedPassword = "$7$101$7uaagoQWQ3ICJ/wg$5cWZs4ae4DjToe44bOzpDopPv1kRaaVD+zF6BE64yDJH2/MBqXfD6f2/o9M/65ArhV92DAK+txXRYsEcZLl45A==";
|
||||
acl = [ "readwrite #" ];
|
||||
};
|
||||
users."ps5-mqtt" = {
|
||||
password = "insecure-password";
|
||||
acl = [ "readwrite #" ];
|
||||
};
|
||||
users."shairport-mqtt" = {
|
||||
password = "insecure-password";
|
||||
acl = [ "readwrite #" ];
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
networking.firewall = {
|
||||
allowedTCPPorts = [ 1883 ];
|
||||
};
|
||||
}
|
||||
128
hosts/home-assistant.cloonar.com/modules/snapserver.nix
Normal file
128
hosts/home-assistant.cloonar.com/modules/snapserver.nix
Normal file
@@ -0,0 +1,128 @@
|
||||
{ pkgs, config, python3Packages, ... }:
|
||||
let
|
||||
shairport-sync = pkgs.shairport-sync.overrideAttrs (_: {
|
||||
configureFlags = [
|
||||
"--with-alsa" "--with-pipe" "--with-pa" "--with-stdout"
|
||||
"--with-avahi" "--with-ssl=openssl" "--with-soxr"
|
||||
# "--with-mqtt-client"
|
||||
"--without-configfiles"
|
||||
"--sysconfdir=/etc"
|
||||
"--with-metadata"
|
||||
];
|
||||
# buildInputs = [
|
||||
# pkgs.openssl
|
||||
# pkgs.avahi
|
||||
# pkgs.popt
|
||||
# pkgs.libconfig
|
||||
# pkgs.mosquitto
|
||||
# pkgs.alsa-lib
|
||||
# pkgs.libpulseaudio
|
||||
# pkgs.pipewire
|
||||
# pkgs.libjack2
|
||||
# pkgs.soxr
|
||||
# ];
|
||||
});
|
||||
in
|
||||
{
|
||||
environment.etc = {
|
||||
# Creates /etc/nanorc
|
||||
shairport = {
|
||||
text = ''
|
||||
whatever you want to put in the file goes here.
|
||||
metadata =
|
||||
{
|
||||
enabled = "yes"; // set this to yes to get Shairport Sync to solicit metadata from the source and to pass it on via a pipe
|
||||
include_cover_art = "yes"; // set to "yes" to get Shairport Sync to solicit cover art from the source and pass it via the pipe. You must also set "enabled" to "yes".
|
||||
cover_art_cache_directory = "/tmp/shairport-sync/.cache/coverart"; // artwork will be stored in this directory if the dbus or MPRIS interfaces are enabled or if the MQTT client is in use. Set it to "" to prevent caching, which may be useful on some systems
|
||||
pipe_name = "/tmp/shairport-sync-metadata";
|
||||
pipe_timeout = 5000; // wait for this number of milliseconds for a blocked pipe to unblock before giving up
|
||||
};
|
||||
|
||||
|
||||
mqtt =
|
||||
{
|
||||
enabled = "yes"; // set this to yes to enable the mqtt-metadata-service
|
||||
hostname = "127.0.0.1"; // Hostname of the MQTT Broker
|
||||
port = 1883; // Port on the MQTT Broker to connect to
|
||||
username = "espresense"; //set this to a string to your username in order to enable username authentication
|
||||
password = "insecure-password"; //set this to a string you your password in order to enable username & password authentication
|
||||
topic = "shairport"; //MQTT topic where this instance of shairport-sync should publish. If not set, the general.name value is used.
|
||||
// publish_raw = "no"; //whether to publish all available metadata under the codes given in the 'metadata' docs.
|
||||
publish_parsed = "yes"; //whether to publish a small (but useful) subset of metadata under human-understandable topics
|
||||
publish_cover = "yes"; //whether to publish the cover over mqtt in binary form. This may lead to a bit of load on the broker
|
||||
// enable_remote = "no"; //whether to remote control via MQTT. RC is available under `topic`/remote.
|
||||
};
|
||||
'';
|
||||
|
||||
# The UNIX file mode bits
|
||||
mode = "0440";
|
||||
};
|
||||
};
|
||||
|
||||
services.snapserver = {
|
||||
enable = true;
|
||||
codec = "flac";
|
||||
http.docRoot = "${pkgs.snapcast}/share/snapserver/snapweb";
|
||||
streams.mopidy = {
|
||||
type = "pipe";
|
||||
location = "/run/snapserver/mopidy";
|
||||
};
|
||||
streams.airplay = {
|
||||
type = "airplay";
|
||||
location = "${shairport-sync}/bin/shairport-sync";
|
||||
query = {
|
||||
devicename = "Multi Room";
|
||||
port = "5000";
|
||||
params = "--mdns=avahi";
|
||||
};
|
||||
};
|
||||
streams.mixed = {
|
||||
type = "meta";
|
||||
location = "/airplay/mopidy";
|
||||
};
|
||||
};
|
||||
|
||||
services.avahi.enable = true;
|
||||
services.avahi.publish.enable = true;
|
||||
services.avahi.publish.userServices = true;
|
||||
|
||||
# services.shairport-sync = {
|
||||
# enable = true;
|
||||
# arguments = "-v -o=pipe -- pipe:name=/run/snapserver/airplay";
|
||||
# };
|
||||
|
||||
services.nginx.virtualHosts."snapcast.cloonar.com" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
acmeRoot = null;
|
||||
extraConfig = ''
|
||||
proxy_buffering off;
|
||||
'';
|
||||
locations."/".extraConfig = ''
|
||||
proxy_pass http://127.0.0.1:1780;
|
||||
proxy_set_header Host $host;
|
||||
proxy_redirect http:// https://;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
80 # http
|
||||
443 # https
|
||||
1704 # snapcast
|
||||
1705 # snapcast
|
||||
5000 # airplay
|
||||
5353 # airplay
|
||||
];
|
||||
networking.firewall.allowedUDPPorts = [
|
||||
5000 # airplay
|
||||
5353 # airplay
|
||||
];
|
||||
networking.firewall.allowedUDPPortRanges = [
|
||||
{ from = 6001; to = 6011; } # airplay
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user