pepe,porani: setup media center
This commit is contained in:
parent
219bfc4786
commit
b358052c42
20 changed files with 148 additions and 1305 deletions
|
@ -5,22 +5,16 @@
|
||||||
<system/server>
|
<system/server>
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
|
|
||||||
#./syncthing.nix
|
./home-assistant.nix
|
||||||
|
./kodi.nix
|
||||||
|
./syncthing.nix
|
||||||
./tinc.nix
|
./tinc.nix
|
||||||
./wifi-access-point.nix
|
./wifi-access-point.nix
|
||||||
./home-assistant.nix
|
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
system.custom.wifi = {
|
|
||||||
enable = true;
|
|
||||||
interfaces = [ "wlp3s0" ];
|
|
||||||
configurationFile = <secrets/wpa_supplicant>;
|
|
||||||
};
|
|
||||||
|
|
||||||
networking.hostName = "pepe";
|
networking.hostName = "pepe";
|
||||||
|
services.printing.enable = false;
|
||||||
services.printing.enable = true;
|
|
||||||
|
|
||||||
# fonts
|
# fonts
|
||||||
# -----
|
# -----
|
||||||
|
@ -28,14 +22,20 @@
|
||||||
programs.custom.xterm.fontSize = 12;
|
programs.custom.xterm.fontSize = 12;
|
||||||
system.custom.fonts.dpi = 100;
|
system.custom.fonts.dpi = 100;
|
||||||
|
|
||||||
virtualisation = {
|
# networking
|
||||||
docker.enable = false;
|
# ----------
|
||||||
|
system.custom.wifi = {
|
||||||
virtualbox = {
|
enable = true;
|
||||||
host.enable = false;
|
interfaces = [ "wlp3s0" ];
|
||||||
guest.x11 = false;
|
configurationFile = <secrets/wpa_supplicant>;
|
||||||
guest.enable = false;
|
|
||||||
};
|
};
|
||||||
|
# nix-shell -p speedtest_cli --run speedtest
|
||||||
|
configuration.fireqos = {
|
||||||
|
enable = true;
|
||||||
|
interface = "wlp3s0";
|
||||||
|
input = 30000;
|
||||||
|
output = 5000;
|
||||||
|
balance = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,30 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = [ <nixpkgs/nixos/modules/installer/scan/not-detected.nix> ];
|
imports = [
|
||||||
|
<nixpkgs/nixos/modules/installer/scan/not-detected.nix>
|
||||||
|
|
||||||
|
(let mediaUUID = "29ebe5ba-7599-4dd3-99a3-37b9bf8e4d61";
|
||||||
|
in {
|
||||||
|
fileSystems."/media" = {
|
||||||
|
device = "/dev/disk/by-uuid/${mediaUUID}";
|
||||||
|
fsType = "ext4";
|
||||||
|
options = [
|
||||||
|
"nofail"
|
||||||
|
"noauto"
|
||||||
|
#"x-systemd.device-timeout=1ms"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
systemd.mounts = [{
|
||||||
|
enable = true;
|
||||||
|
options = "nofail,noauto";
|
||||||
|
type = "ext4";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
what = "/dev/disk/by-uuid/${mediaUUID}";
|
||||||
|
where = "/media";
|
||||||
|
}];
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
boot.initrd.availableKernelModules =
|
boot.initrd.availableKernelModules =
|
||||||
[ "ehci_pci" "ahci" "usb_storage" "sd_mod" "sdhci_pci" ];
|
[ "ehci_pci" "ahci" "usb_storage" "sd_mod" "sdhci_pci" ];
|
||||||
|
@ -29,14 +52,6 @@
|
||||||
fsType = "tmpfs";
|
fsType = "tmpfs";
|
||||||
};
|
};
|
||||||
|
|
||||||
fileSystems."/browsers/" = {
|
|
||||||
#device = "/dev/ram2";
|
|
||||||
#fsType = "tmpfs";
|
|
||||||
options = [ "noatime" "nodiratime" "discard" ];
|
|
||||||
device = "/dev/secure_vg/browser";
|
|
||||||
fsType = "ext4";
|
|
||||||
};
|
|
||||||
|
|
||||||
nix.maxJobs = lib.mkDefault 4;
|
nix.maxJobs = lib.mkDefault 4;
|
||||||
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
|
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ in {
|
||||||
./home-assistant/mqtt.nix
|
./home-assistant/mqtt.nix
|
||||||
#./home-assistant/dayOfWeek.nix
|
#./home-assistant/dayOfWeek.nix
|
||||||
#./home-assistant/timer.nix
|
#./home-assistant/timer.nix
|
||||||
#./home-assistant/kodi.nix
|
./home-assistant/kodi.nix
|
||||||
#./home-assistant/zigbee2mqtt.nix
|
#./home-assistant/zigbee2mqtt.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
38
configs/pepe/kodi.nix
Normal file
38
configs/pepe/kodi.nix
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
{ config, lib, pkgs, ... }: {
|
||||||
|
|
||||||
|
services.xserver = {
|
||||||
|
enable = true;
|
||||||
|
autorun = false;
|
||||||
|
desktopManager = {
|
||||||
|
kodi.enable = true;
|
||||||
|
default = "kodi";
|
||||||
|
xterm.enable = false;
|
||||||
|
};
|
||||||
|
displayManager = {
|
||||||
|
sddm = {
|
||||||
|
enable = true;
|
||||||
|
autoLogin = {
|
||||||
|
enable = true;
|
||||||
|
relogin = true;
|
||||||
|
user = config.users.users.kodi.name;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
users = {
|
||||||
|
# mutableUsers = true;
|
||||||
|
users.kodi = {
|
||||||
|
isNormalUser = true;
|
||||||
|
name = "kodi";
|
||||||
|
uid = 1338;
|
||||||
|
initialPassword = lib.fileContents <secrets/kodi/password>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# allow everybody in the net to access the wifi
|
||||||
|
networking.firewall = {
|
||||||
|
allowedTCPPorts = [ 8080 ];
|
||||||
|
allowedUDPPorts = [ 8080 ];
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,4 +0,0 @@
|
||||||
{ config, ... }:
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,11 +1,21 @@
|
||||||
{ config, pkgs, lib, ... }: {
|
{ config, pkgs, lib, ... }: {
|
||||||
|
|
||||||
|
users.groups."syncthing".members = [ "mpd" "syncthing" "kodi" ];
|
||||||
|
|
||||||
|
custom.samba-share = {
|
||||||
|
enable = true;
|
||||||
|
folders = {
|
||||||
|
movies = config.test.services.syncthing.declarative.folders.movies.path;
|
||||||
|
music =
|
||||||
|
config.test.services.syncthing.declarative.folders.music-library.path;
|
||||||
|
samples = config.test.services.syncthing.declarative.folders.samples.path;
|
||||||
|
series = config.test.services.syncthing.declarative.folders.series.path;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
test.services.syncthing = {
|
test.services.syncthing = {
|
||||||
enable = true;
|
enable = true;
|
||||||
openDefaultPorts = false;
|
openDefaultPorts = true;
|
||||||
user = "palo";
|
|
||||||
dataDir = "/home/palo/.syncthing";
|
|
||||||
configDir = "/home/palo/.syncthing";
|
|
||||||
declarative = {
|
declarative = {
|
||||||
cert = toString <secrets/syncthing/cert.pem>;
|
cert = toString <secrets/syncthing/cert.pem>;
|
||||||
key = toString <secrets/syncthing/key.pem>;
|
key = toString <secrets/syncthing/key.pem>;
|
||||||
|
@ -15,47 +25,70 @@
|
||||||
|
|
||||||
# on encrypted drive
|
# on encrypted drive
|
||||||
# ------------------
|
# ------------------
|
||||||
desktop = {
|
|
||||||
enable = true;
|
|
||||||
path = "/home/palo/desktop";
|
|
||||||
};
|
|
||||||
finance = {
|
|
||||||
enable = true;
|
|
||||||
path = "/home/palo/finance";
|
|
||||||
};
|
|
||||||
|
|
||||||
# no need to be encrypted
|
# no need to be encrypted
|
||||||
# -----------------------
|
# -----------------------
|
||||||
book = {
|
books = {
|
||||||
enable = true;
|
enable = true;
|
||||||
path = "/home/palo/books";
|
path = "/media/syncthing/books";
|
||||||
|
rescanInterval = 8 * 3600;
|
||||||
};
|
};
|
||||||
kruck-pepe = {
|
movies = {
|
||||||
enable = true;
|
enable = true;
|
||||||
path = "/home/palo/pepe-kruck";
|
path = "/media/syncthing/movies";
|
||||||
|
rescanInterval = 8 * 3600;
|
||||||
};
|
};
|
||||||
music-library = {
|
music-library = {
|
||||||
enable = true;
|
enable = true;
|
||||||
path = "/home/palo/music-library";
|
path = "/media/syncthing/music-library";
|
||||||
|
rescanInterval = 8 * 3600;
|
||||||
};
|
};
|
||||||
music-projects = {
|
music-library-free = {
|
||||||
enable = true;
|
enable = true;
|
||||||
path = "/home/palo/music-projects";
|
path = "/media/syncthing/music-library-free";
|
||||||
|
rescanInterval = 8 * 3600;
|
||||||
};
|
};
|
||||||
porani-pepe = {
|
porn = {
|
||||||
enable = true;
|
enable = true;
|
||||||
path = "/home/palo/pepe-porani";
|
path = "/media/syncthing/porn";
|
||||||
|
rescanInterval = 8 * 3600;
|
||||||
};
|
};
|
||||||
schasch-pepe = {
|
samples = {
|
||||||
enable = true;
|
enable = true;
|
||||||
path = "/home/palo/pepe-schasch";
|
path = "/media/syncthing/samples";
|
||||||
|
rescanInterval = 8 * 3600;
|
||||||
};
|
};
|
||||||
workout-pepe = {
|
series = {
|
||||||
enable = true;
|
enable = true;
|
||||||
path = "/home/palo/pepe-workout";
|
path = "/media/syncthing/series";
|
||||||
|
rescanInterval = 8 * 3600;
|
||||||
|
};
|
||||||
|
smartphone-folder = {
|
||||||
|
enable = true;
|
||||||
|
path = "/media/syncthing/smartphone-folder";
|
||||||
|
rescanInterval = 8 * 3600;
|
||||||
|
};
|
||||||
|
video-material = {
|
||||||
|
enable = true;
|
||||||
|
path = "/media/syncthing/video-material";
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
systemd.services."permown._media_syncthing" = {
|
||||||
|
bindsTo = [ "media.mount" ];
|
||||||
|
after = [ "media.mount" ];
|
||||||
|
};
|
||||||
|
system.permown."/media/syncthing" = {
|
||||||
|
owner = "syncthing";
|
||||||
|
group = "syncthing";
|
||||||
|
umask = "0007";
|
||||||
|
};
|
||||||
|
systemd.services."syncthing" = {
|
||||||
|
bindsTo = [ "media.mount" ];
|
||||||
|
after = [ "media.mount" ];
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{ lib, pkgs, ... }:
|
{ lib, pkgs, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
wifi = "wlp0s26u1u2";
|
wifi = "wlp0s29u1u1";
|
||||||
ipAddress = "10.23.45.1";
|
ipAddress = "10.23.45.1";
|
||||||
prefixLength = 24;
|
prefixLength = 24;
|
||||||
servedAddressRange = "10.23.45.2,10.23.45.150,12h";
|
servedAddressRange = "10.23.45.2,10.23.45.150,12h";
|
||||||
|
|
|
@ -6,11 +6,7 @@
|
||||||
|
|
||||||
./tinc.nix
|
./tinc.nix
|
||||||
./syncthing.nix
|
./syncthing.nix
|
||||||
#./packages.nix
|
|
||||||
#./home-assistant.nix
|
|
||||||
#./wifi-access-point.nix
|
|
||||||
./kodi.nix
|
./kodi.nix
|
||||||
#./mpd.nix
|
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -1,217 +0,0 @@
|
||||||
{ pkgs, config, lib, ... }:
|
|
||||||
let unstablePkgs = import <nixpkgs-unstable> { };
|
|
||||||
in {
|
|
||||||
|
|
||||||
imports = [
|
|
||||||
./home-assistant/chaospott.nix
|
|
||||||
./home-assistant/holiday.nix
|
|
||||||
./home-assistant/mpd.nix
|
|
||||||
./home-assistant/sonoff.nix
|
|
||||||
./home-assistant/mqtt.nix
|
|
||||||
./home-assistant/dayOfWeek.nix
|
|
||||||
./home-assistant/timer.nix
|
|
||||||
./home-assistant/kodi.nix
|
|
||||||
./home-assistant/zigbee2mqtt.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
services.homeAssistantConfig = {
|
|
||||||
|
|
||||||
# turn on to edit GUI
|
|
||||||
# lovelace = {};
|
|
||||||
|
|
||||||
homeassistant = {
|
|
||||||
latitude = 51.444847;
|
|
||||||
longitude = 6.967006;
|
|
||||||
elevation = 116;
|
|
||||||
|
|
||||||
auth_providers = [{
|
|
||||||
type = "trusted_networks";
|
|
||||||
trusted_networks =
|
|
||||||
[ config.module.cluster.services.tinc."private".networkSubnet ];
|
|
||||||
}];
|
|
||||||
};
|
|
||||||
|
|
||||||
prometheus.namespace = "hass";
|
|
||||||
|
|
||||||
automation = [
|
|
||||||
|
|
||||||
# todo when ich weis ich bin zuhause
|
|
||||||
#{
|
|
||||||
# alias = "Licht and wenn Dunkel";
|
|
||||||
# trigger = {
|
|
||||||
# platform = "state";
|
|
||||||
# entity_id = [ "binary_sensor.night" ];
|
|
||||||
# from = "off";
|
|
||||||
# to = "on";
|
|
||||||
# };
|
|
||||||
# action = [
|
|
||||||
# {
|
|
||||||
# service = "switch.turn_on";
|
|
||||||
# entity_id = "group.kitchen";
|
|
||||||
# }
|
|
||||||
# {
|
|
||||||
# service = "switch.turn_on";
|
|
||||||
# entity_id = "group.living_room";
|
|
||||||
# }
|
|
||||||
# ];
|
|
||||||
#}
|
|
||||||
|
|
||||||
#{
|
|
||||||
# alias = "Küchen Sensor An";
|
|
||||||
# trigger = {
|
|
||||||
# platform = "state";
|
|
||||||
# entity_id = [ "binary_sensor.motion_1" ];
|
|
||||||
# to = "on";
|
|
||||||
# };
|
|
||||||
# action = {
|
|
||||||
# service = "switch.turn_on";
|
|
||||||
# entity_id = "group.kitchen";
|
|
||||||
# };
|
|
||||||
#}
|
|
||||||
|
|
||||||
#{
|
|
||||||
# alias = "Küchen Sensor aus";
|
|
||||||
# trigger = {
|
|
||||||
# platform = "state";
|
|
||||||
# entity_id = [ "binary_sensor.motion_1" ];
|
|
||||||
# to = "off";
|
|
||||||
# for = "00:00:25";
|
|
||||||
# };
|
|
||||||
# action = {
|
|
||||||
# service = "switch.turn_off";
|
|
||||||
# entity_id = "group.kitchen";
|
|
||||||
# };
|
|
||||||
#}
|
|
||||||
];
|
|
||||||
|
|
||||||
group = {
|
|
||||||
bed_room = {
|
|
||||||
name = "Schlafzimmer";
|
|
||||||
view = false;
|
|
||||||
};
|
|
||||||
tv = {
|
|
||||||
name = "TV";
|
|
||||||
view = false;
|
|
||||||
};
|
|
||||||
living_room = {
|
|
||||||
name = "Wohnzimmer";
|
|
||||||
view = false;
|
|
||||||
};
|
|
||||||
kitchen = {
|
|
||||||
name = "Küche";
|
|
||||||
view = false;
|
|
||||||
};
|
|
||||||
today = {
|
|
||||||
control = "hidden";
|
|
||||||
name = "Today";
|
|
||||||
view = false;
|
|
||||||
entities = [ "sensor.weather_temperature" "sun.sun" ];
|
|
||||||
};
|
|
||||||
all_lights = {
|
|
||||||
name = "All Lights";
|
|
||||||
view = false;
|
|
||||||
};
|
|
||||||
unknown = {
|
|
||||||
control = "hidden";
|
|
||||||
name = "Not Used";
|
|
||||||
view = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
view_rooms = {
|
|
||||||
name = "Räume";
|
|
||||||
view = true;
|
|
||||||
entities = [
|
|
||||||
"group.all_lights"
|
|
||||||
"group.bed_room"
|
|
||||||
"group.living_room"
|
|
||||||
"group.kitchen"
|
|
||||||
"group.tv"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
view_overview = {
|
|
||||||
name = "Übersicht";
|
|
||||||
view = true;
|
|
||||||
entities = [ "group.today" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
sun = { };
|
|
||||||
|
|
||||||
script.turn_all_off.sequence = [ ];
|
|
||||||
|
|
||||||
script.turn_all_on.sequence = [ ];
|
|
||||||
|
|
||||||
sensor = [
|
|
||||||
# Weather prediction
|
|
||||||
{
|
|
||||||
platform = "zamg";
|
|
||||||
name = "Weather";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
# todo: add holidays package to home-assiatnt
|
|
||||||
binary_sensor = [
|
|
||||||
{
|
|
||||||
name = "before_workday";
|
|
||||||
platform = "workday";
|
|
||||||
country = "DE";
|
|
||||||
province = "NW";
|
|
||||||
workdays = [ "mon" "tue" "wed" "thu" "fri" ];
|
|
||||||
days_offset = 1;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "workday";
|
|
||||||
platform = "workday";
|
|
||||||
country = "DE";
|
|
||||||
province = "NW";
|
|
||||||
workdays = [ "mon" "tue" "wed" "thu" "fri" ];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
services.home-assistant = {
|
|
||||||
enable = true;
|
|
||||||
package = unstablePkgs.home-assistant.override {
|
|
||||||
python3 = unstablePkgs.python36;
|
|
||||||
extraPackages = python: [
|
|
||||||
# todo : check which is still needed
|
|
||||||
python.netdisco
|
|
||||||
python.xmltodict
|
|
||||||
python.mpd2
|
|
||||||
|
|
||||||
# for mqtt
|
|
||||||
python.hbmqtt
|
|
||||||
python.paho-mqtt
|
|
||||||
|
|
||||||
# needed for platform workday
|
|
||||||
(python.buildPythonPackage rec {
|
|
||||||
|
|
||||||
pname = "holidays";
|
|
||||||
version = "0.9.10";
|
|
||||||
|
|
||||||
src = python.fetchPypi {
|
|
||||||
inherit pname version;
|
|
||||||
sha256 =
|
|
||||||
"9f06d143eb708e8732230260636938f2f57114e94defd8fa2082408e0d422d6f";
|
|
||||||
};
|
|
||||||
|
|
||||||
doCheck = false;
|
|
||||||
buildInputs = [ pkgs.dateutils ];
|
|
||||||
propagatedBuildInputs = [ python."python-dateutil" python."six" ];
|
|
||||||
meta = with pkgs.stdenv.lib; {
|
|
||||||
homepage = "https://github.com/dr-prodigy/python-holidays";
|
|
||||||
license = licenses.mit;
|
|
||||||
description = "Generate and work with holidays in Python";
|
|
||||||
maintainers = with maintainers; [ mrVanDalo ];
|
|
||||||
};
|
|
||||||
|
|
||||||
})
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,82 +0,0 @@
|
||||||
{ config, pkgs, ... }:
|
|
||||||
let
|
|
||||||
|
|
||||||
name = "chaospott";
|
|
||||||
folderPath = config.services.home-assistant.configDir;
|
|
||||||
filePath = "${folderPath}/${name}.json";
|
|
||||||
|
|
||||||
in {
|
|
||||||
services.homeAssistantConfig = {
|
|
||||||
|
|
||||||
sensor = [
|
|
||||||
{
|
|
||||||
platform = "file";
|
|
||||||
name = "${name}_aerie";
|
|
||||||
file_path = filePath;
|
|
||||||
value_template = "{{ value_json.aerie }}";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "file";
|
|
||||||
name = "${name}_cellar";
|
|
||||||
file_path = filePath;
|
|
||||||
value_template = "{{ value_json.cellar }}";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
homeassistant = {
|
|
||||||
whitelist_external_dirs = [ folderPath ];
|
|
||||||
customize = {
|
|
||||||
"sensor.${name}_aerie" = {
|
|
||||||
icon = "mdi:store";
|
|
||||||
entity_picture = "https://chaospott.de/images/logo.png";
|
|
||||||
friendly_name = "ChaosPott Oben";
|
|
||||||
};
|
|
||||||
"sensor.${name}_cellar" = {
|
|
||||||
icon = "mdi:store";
|
|
||||||
entity_picture = "https://chaospott.de/images/logo.png";
|
|
||||||
friendly_name = "ChaosPott Unten";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
group = {
|
|
||||||
"${name}" = {
|
|
||||||
name = "ChaosPott (Essen)";
|
|
||||||
control = "hidden";
|
|
||||||
entities = [ "sensor.${name}_aerie" "sensor.${name}_cellar" ];
|
|
||||||
};
|
|
||||||
view_overview.entities = [ "group.${name}" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services."${name}" = {
|
|
||||||
enable = true;
|
|
||||||
before = [ "home-assistant.service" ];
|
|
||||||
wantedBy = [ "home-assistant.service" ];
|
|
||||||
serviceConfig = {
|
|
||||||
User = "hass";
|
|
||||||
Type = "oneshot";
|
|
||||||
};
|
|
||||||
description = "set ${name} for homeassistant";
|
|
||||||
script = # sh
|
|
||||||
''
|
|
||||||
${pkgs.curl}/bin/curl -Ls https://status.chaospott.de/api \
|
|
||||||
| ${pkgs.jq}/bin/jq --compact-output \
|
|
||||||
'.sensors.door_locked |
|
|
||||||
[.[] | { "\(.location)" : (if .value then "closed" else "open" end) }] |
|
|
||||||
reduce .[] as $item ({}; . + $item) ' \
|
|
||||||
>> ${filePath}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.timers."${name}" = {
|
|
||||||
enable = true;
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
timerConfig = {
|
|
||||||
OnCalendar = "hourly";
|
|
||||||
Persistent = "true";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
{ config, ... }:
|
|
||||||
let
|
|
||||||
|
|
||||||
folderPath = config.services.home-assistant.configDir;
|
|
||||||
filePath = "${folderPath}/dayOfWeek.json";
|
|
||||||
|
|
||||||
in {
|
|
||||||
services.homeAssistantConfig = {
|
|
||||||
|
|
||||||
sensor = [{
|
|
||||||
platform = "file";
|
|
||||||
name = "day_of_week";
|
|
||||||
file_path = filePath;
|
|
||||||
value_template = "{{ value_json.dayOfWeek }}";
|
|
||||||
}];
|
|
||||||
|
|
||||||
homeassistant = {
|
|
||||||
whitelist_external_dirs = [ folderPath ];
|
|
||||||
customize."sensor.day_of_week" = {
|
|
||||||
icon = "mdi:calendar-today";
|
|
||||||
friendly_name = "Wochen Tag";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
group = { overview.entities = [ "sensor.day_of_week" ]; };
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.dayOfWeek = {
|
|
||||||
enable = true;
|
|
||||||
before = [ "home-assistant.service" ];
|
|
||||||
wantedBy = [ "home-assistant.service" ];
|
|
||||||
serviceConfig = {
|
|
||||||
User = "hass";
|
|
||||||
Type = "oneshot";
|
|
||||||
};
|
|
||||||
description = "set day of wek for homeassistant";
|
|
||||||
script = # sh
|
|
||||||
''
|
|
||||||
date +'{"dayOfWeek":"%A"}' >> ${filePath}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
systemd.timers.dayOfWeek = {
|
|
||||||
enable = true;
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
timerConfig = {
|
|
||||||
OnCalendar = "00:01:00";
|
|
||||||
Persistent = "true";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,92 +0,0 @@
|
||||||
{ config, pkgs, ... }:
|
|
||||||
let
|
|
||||||
|
|
||||||
state = "NW"; # NRW
|
|
||||||
# state = "BE"; # Berlin
|
|
||||||
|
|
||||||
name = "holiday";
|
|
||||||
folderPath = config.services.home-assistant.configDir;
|
|
||||||
filePath = "${folderPath}/${name}.json";
|
|
||||||
|
|
||||||
in {
|
|
||||||
services.homeAssistantConfig = {
|
|
||||||
|
|
||||||
# todo : use the python tool
|
|
||||||
sensor = [
|
|
||||||
{
|
|
||||||
platform = "file";
|
|
||||||
name = "${name}_date";
|
|
||||||
file_path = filePath;
|
|
||||||
value_template = "{{ value_json.date }}";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "file";
|
|
||||||
name = "${name}_name";
|
|
||||||
file_path = filePath;
|
|
||||||
value_template = "{{ value_json.name }}";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
homeassistant = {
|
|
||||||
whitelist_external_dirs = [ folderPath ];
|
|
||||||
customize = {
|
|
||||||
"sensor.${name}_date" = {
|
|
||||||
icon = "mdi:calendar";
|
|
||||||
friendly_name = "Nächster Feiertag";
|
|
||||||
};
|
|
||||||
"sensor.${name}_name" = {
|
|
||||||
icon = "mdi:calendar";
|
|
||||||
friendly_name = "Nächster Feiertag";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
group = {
|
|
||||||
|
|
||||||
holidays = {
|
|
||||||
name = "Feiertage";
|
|
||||||
view = false;
|
|
||||||
control = "hidden";
|
|
||||||
entities = [ "sensor.${name}_date" "sensor.${name}_name" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
view_overview.entities = [ "group.holidays" ];
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services."${name}" = {
|
|
||||||
enable = true;
|
|
||||||
before = [ "home-assistant.service" ];
|
|
||||||
wantedBy = [ "home-assistant.service" ];
|
|
||||||
serviceConfig = {
|
|
||||||
User = "hass";
|
|
||||||
Type = "oneshot";
|
|
||||||
};
|
|
||||||
description = "set ${name} for homeassistant";
|
|
||||||
script = # sh
|
|
||||||
''
|
|
||||||
${pkgs.curl}/bin/curl \
|
|
||||||
-Ls "https://feiertage-api.de/api/?jahr=$( date +%Y )&nur_land=${state}" \
|
|
||||||
| ${pkgs.jq}/bin/jq --compact-output '
|
|
||||||
map_values( .datum ) |
|
|
||||||
to_entries |
|
|
||||||
map( { date: .value, name : .key } ) |
|
|
||||||
sort_by( .date ) |
|
|
||||||
map(select ( .date >= "'`date +%Y-%m-%d`'" )) |
|
|
||||||
.[0]' \
|
|
||||||
>> ${filePath}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.timers."${name}" = {
|
|
||||||
enable = true;
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
timerConfig = {
|
|
||||||
OnCalendar = "daily";
|
|
||||||
Persistent = "true";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,81 +0,0 @@
|
||||||
{ pkgs, config, lib, ... }: {
|
|
||||||
|
|
||||||
services.homeAssistantConfig = {
|
|
||||||
|
|
||||||
group.view_overview.entities = [ "media_player.kodi" ];
|
|
||||||
|
|
||||||
media_player = [{
|
|
||||||
platform = "kodi";
|
|
||||||
host = "127.0.0.1";
|
|
||||||
turn_on_action.service = "script.watch_tv";
|
|
||||||
turn_off_action.service = "script.stop_watch_tv";
|
|
||||||
}];
|
|
||||||
|
|
||||||
shell_command = {
|
|
||||||
start_display =
|
|
||||||
"sudo ${pkgs.systemd}/bin/systemctl start display-manager";
|
|
||||||
stop_display = "sudo ${pkgs.systemd}/bin/systemctl stop display-manager";
|
|
||||||
};
|
|
||||||
|
|
||||||
script = {
|
|
||||||
|
|
||||||
turn_all_off.sequence = [
|
|
||||||
# todo : use the shell_command here
|
|
||||||
{
|
|
||||||
alias = "turn off tv";
|
|
||||||
service = "switch.turn_off";
|
|
||||||
data.entity_id = "group.tv";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
alias = "stop kodi";
|
|
||||||
service = "shell_command.stop_display";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
test_display.sequence = [
|
|
||||||
{ service = "shell_command.start_display"; }
|
|
||||||
{ delay.seconds = 20; }
|
|
||||||
{ service = "shell_command.stop_display"; }
|
|
||||||
];
|
|
||||||
|
|
||||||
watch_tv = {
|
|
||||||
alias = "Watch TV";
|
|
||||||
sequence = [
|
|
||||||
{
|
|
||||||
alias = "turn on tv";
|
|
||||||
service = "switch.turn_on";
|
|
||||||
data.entity_id = "group.tv";
|
|
||||||
}
|
|
||||||
{ delay.minutes = 1; }
|
|
||||||
{
|
|
||||||
alias = "start kodi";
|
|
||||||
service = "shell_command.start_display";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
stop_watch_tv = {
|
|
||||||
alias = "Stop TV";
|
|
||||||
sequence = [
|
|
||||||
{
|
|
||||||
alias = "turn off tv";
|
|
||||||
service = "switch.turn_off";
|
|
||||||
data.entity_id = "group.tv";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
alias = "stop kodi";
|
|
||||||
service = "shell_command.stop_display";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
group.tv.entities = [ "script.watch_tv" "script.stop_watch_tv" ];
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
security.sudo.extraConfig = ''
|
|
||||||
hass ALL= (root) NOPASSWD: ${pkgs.systemd}/bin/systemctl start display-manager
|
|
||||||
hass ALL= (root) NOPASSWD: ${pkgs.systemd}/bin/systemctl stop display-manager
|
|
||||||
'';
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
{ lib, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
services.homeAssistantConfig = {
|
|
||||||
|
|
||||||
group.view_overview.entities = [ "media_player.mpd" ];
|
|
||||||
|
|
||||||
media_player = [{
|
|
||||||
platform = "mpd";
|
|
||||||
host = "localhost";
|
|
||||||
}];
|
|
||||||
|
|
||||||
script.turn_all_off.sequence = [{
|
|
||||||
alias = "turn mpd off";
|
|
||||||
service = "media_player.turn_off";
|
|
||||||
data.entity_id = "media_player.mpd";
|
|
||||||
}];
|
|
||||||
|
|
||||||
script.turn_all_on.sequence = [
|
|
||||||
{
|
|
||||||
alias = "turn mpd on";
|
|
||||||
service = "media_player.turn_on";
|
|
||||||
data.entity_id = "media_player.mpd";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
alias = "Adjust volume";
|
|
||||||
service = "media_player.volume_set";
|
|
||||||
data = {
|
|
||||||
entity_id = "media_player.mpd";
|
|
||||||
volume_level = "0.90";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
{
|
|
||||||
services.homeAssistantConfig.mqtt = {
|
|
||||||
# discovery = false;
|
|
||||||
|
|
||||||
# for mosquitto
|
|
||||||
broker = "127.0.0.1";
|
|
||||||
username = fileContents <secrets/home-assistant/mqtt-user>;
|
|
||||||
password = fileContents <secrets/home-assistant/mqtt-password>;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
services.mosquitto = {
|
|
||||||
enable = true;
|
|
||||||
host = "0.0.0.0";
|
|
||||||
users = {
|
|
||||||
homeassistant = {
|
|
||||||
password = lib.fileContents <secrets/mosquitto/password>;
|
|
||||||
acl = [ "topic readwrite #" ];
|
|
||||||
};
|
|
||||||
zigbee = {
|
|
||||||
password = lib.fileContents <secrets/zigbee/password>;
|
|
||||||
acl = [ "topic readwrite #" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,120 +0,0 @@
|
||||||
{ pkgs, config, lib, ... }:
|
|
||||||
|
|
||||||
let unstablePkgs = import <nixpkgs-unstable> { };
|
|
||||||
in {
|
|
||||||
|
|
||||||
services.homeAssistantConfig = let
|
|
||||||
|
|
||||||
sonoffSwitches = {
|
|
||||||
"pal01" = {
|
|
||||||
label = "Bett";
|
|
||||||
icon = "mdi:lightbulb-on";
|
|
||||||
};
|
|
||||||
"pal02" = {
|
|
||||||
label = "Lampe";
|
|
||||||
icon = "mdi:lightbulb-on";
|
|
||||||
};
|
|
||||||
"pal03" = {
|
|
||||||
label = "Couche";
|
|
||||||
icon = "mdi:lightbulb-on";
|
|
||||||
};
|
|
||||||
"pal06" = {
|
|
||||||
label = "Küche";
|
|
||||||
icon = "mdi:lightbulb-on";
|
|
||||||
};
|
|
||||||
"pal05" = {
|
|
||||||
label = "TV";
|
|
||||||
icon = "mdi:television";
|
|
||||||
};
|
|
||||||
|
|
||||||
"pal04" = {
|
|
||||||
label = "Nummer 4";
|
|
||||||
icon = "mdi:power-plug-off";
|
|
||||||
};
|
|
||||||
"pal07" = {
|
|
||||||
label = "Nummer 7";
|
|
||||||
icon = "mdi:power-plug-off";
|
|
||||||
};
|
|
||||||
"pal08" = {
|
|
||||||
label = "Nummer 8";
|
|
||||||
icon = "mdi:power-plug-off";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
toSwitch = name: "switch.${name}";
|
|
||||||
|
|
||||||
in {
|
|
||||||
|
|
||||||
homeassistant = {
|
|
||||||
customize = lib.mapAttrs' (entity: value: {
|
|
||||||
name = toSwitch entity;
|
|
||||||
value = {
|
|
||||||
friendly_name = value.label;
|
|
||||||
icon = value.icon;
|
|
||||||
};
|
|
||||||
}) sonoffSwitches;
|
|
||||||
};
|
|
||||||
|
|
||||||
script.turn_all_off.sequence = [
|
|
||||||
{
|
|
||||||
alias = "turn off sonoff";
|
|
||||||
service = "switch.turn_off";
|
|
||||||
data.entity_id = "group.all_lights";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
alias = "turn off sonoff";
|
|
||||||
service = "switch.turn_off";
|
|
||||||
data.entity_id = "group.tv";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
script.turn_all_on.sequence = [{
|
|
||||||
alias = "turn on all lights";
|
|
||||||
service = "switch.turn_on";
|
|
||||||
data.entity_id = "group.all_lights";
|
|
||||||
}];
|
|
||||||
|
|
||||||
group = {
|
|
||||||
bed_room = { entities = builtins.map toSwitch [ "pal01" ]; };
|
|
||||||
living_room = { entities = builtins.map toSwitch [ "pal03" "pal02" ]; };
|
|
||||||
tv = { entities = builtins.map toSwitch [ "pal05" ]; };
|
|
||||||
kitchen = { entities = builtins.map toSwitch [ "pal06" ]; };
|
|
||||||
unknown = {
|
|
||||||
entities = builtins.map toSwitch [ "pal04" "pal07" "pal08" ];
|
|
||||||
};
|
|
||||||
all_lights = {
|
|
||||||
entities = builtins.map toSwitch [ "pal01" "pal02" "pal03" "pal06" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
switch = let
|
|
||||||
sonoffConfigurations = builtins.map (name: {
|
|
||||||
name = name;
|
|
||||||
platform = "mqtt";
|
|
||||||
command_topic = "cmnd/${lib.toUpper name}/POWER";
|
|
||||||
state_topic = "stat/${lib.toUpper name}/POWER";
|
|
||||||
payload_on = "ON";
|
|
||||||
payload_off = "OFF";
|
|
||||||
state_on = "ON";
|
|
||||||
state_off = "OFF";
|
|
||||||
}) (builtins.attrNames sonoffSwitches);
|
|
||||||
in sonoffConfigurations;
|
|
||||||
|
|
||||||
# discover state on init
|
|
||||||
automation = [{
|
|
||||||
alias = "Sonoff initial Power state";
|
|
||||||
trigger = {
|
|
||||||
platform = "homeassistant";
|
|
||||||
event = "start";
|
|
||||||
};
|
|
||||||
action = builtins.map (name: {
|
|
||||||
service = "mqtt.publish";
|
|
||||||
data = {
|
|
||||||
topic = "cmnd/${lib.toUpper name}/power";
|
|
||||||
payload = "";
|
|
||||||
};
|
|
||||||
}) (builtins.attrNames sonoffSwitches);
|
|
||||||
}];
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,244 +0,0 @@
|
||||||
{ config, ... }: {
|
|
||||||
|
|
||||||
imports = [ ./mpd.nix ];
|
|
||||||
|
|
||||||
services.homeAssistantConfig = {
|
|
||||||
|
|
||||||
sensor = [{
|
|
||||||
platform = "time_date";
|
|
||||||
display_options = [ "time" "date" ];
|
|
||||||
}];
|
|
||||||
|
|
||||||
input_datetime = {
|
|
||||||
wakeup = {
|
|
||||||
name = "Arbeitswecker";
|
|
||||||
has_time = true;
|
|
||||||
has_date = false;
|
|
||||||
icon = "mdi:alarm";
|
|
||||||
};
|
|
||||||
leave = {
|
|
||||||
name = "Turn off Time";
|
|
||||||
has_time = true;
|
|
||||||
has_date = false;
|
|
||||||
icon = "mdi:alarm";
|
|
||||||
};
|
|
||||||
return = {
|
|
||||||
name = "Return home";
|
|
||||||
has_time = true;
|
|
||||||
has_date = false;
|
|
||||||
icon = "mdi:alarm";
|
|
||||||
};
|
|
||||||
sleep = {
|
|
||||||
name = "Turn off Time";
|
|
||||||
has_time = true;
|
|
||||||
has_date = false;
|
|
||||||
icon = "mdi:alarm";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
input_boolean = {
|
|
||||||
wakeup = {
|
|
||||||
name = "enable";
|
|
||||||
icon = "mdi:toggle-switch";
|
|
||||||
};
|
|
||||||
leave = {
|
|
||||||
name = "enable";
|
|
||||||
icon = "mdi:toggle-switch";
|
|
||||||
};
|
|
||||||
return = {
|
|
||||||
name = "enable";
|
|
||||||
icon = "mdi:toggle-switch";
|
|
||||||
};
|
|
||||||
sleep = {
|
|
||||||
name = "enable";
|
|
||||||
icon = "mdi:toggle-switch";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
input_select = {
|
|
||||||
wakeup = {
|
|
||||||
name = "Playlist";
|
|
||||||
icon = "mdi:library-music";
|
|
||||||
options = [ "wakeup" "wakeup1" "wakeup2" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
binary_sensor = [
|
|
||||||
{
|
|
||||||
platform = "tod";
|
|
||||||
name = "night";
|
|
||||||
after = "sunset";
|
|
||||||
before = "sunrise";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "tod";
|
|
||||||
name = "daytime";
|
|
||||||
after = "sunrise";
|
|
||||||
before = "sunset";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
group = {
|
|
||||||
|
|
||||||
timer_wakeup = {
|
|
||||||
view = false;
|
|
||||||
name = "Arbeits Aufwachen";
|
|
||||||
control = "hidden";
|
|
||||||
entities = [
|
|
||||||
"input_boolean.wakeup"
|
|
||||||
"input_datetime.wakeup"
|
|
||||||
"input_select.wakeup"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
timer_leave = {
|
|
||||||
view = false;
|
|
||||||
name = "Leave Time";
|
|
||||||
control = "hidden";
|
|
||||||
entities = [ "input_boolean.leave" "input_datetime.leave" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
timer_return = {
|
|
||||||
view = false;
|
|
||||||
name = "Nach Hause kommen";
|
|
||||||
control = "hidden";
|
|
||||||
entities = [ "input_boolean.return" "input_datetime.return" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
timer_sleep = {
|
|
||||||
view = false;
|
|
||||||
name = "Einschlafen";
|
|
||||||
control = "hidden";
|
|
||||||
entities = [ "input_boolean.sleep" "input_datetime.sleep" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
timers.entities = [
|
|
||||||
"group.timer_wakeup"
|
|
||||||
"group.timer_leave"
|
|
||||||
"group.timer_return"
|
|
||||||
"group.timer_sleep"
|
|
||||||
"binary_sensor.night"
|
|
||||||
"binary_sensor.daytime"
|
|
||||||
];
|
|
||||||
|
|
||||||
today.entities = [ "sensor.date" "sensor.time" ];
|
|
||||||
|
|
||||||
view_overview.entities = [
|
|
||||||
"group.timer_wakeup"
|
|
||||||
"group.timer_leave"
|
|
||||||
"group.timer_return"
|
|
||||||
"group.timer_sleep"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
automation = [
|
|
||||||
{
|
|
||||||
alias = "Wecker Arbeiten";
|
|
||||||
trigger = {
|
|
||||||
platform = "template";
|
|
||||||
value_template =
|
|
||||||
"{{ states('sensor.time') == (states.input_datetime.wakeup.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}";
|
|
||||||
};
|
|
||||||
condition = {
|
|
||||||
condition = "and";
|
|
||||||
conditions = [
|
|
||||||
{
|
|
||||||
condition = "state";
|
|
||||||
entity_id = "input_boolean.wakeup";
|
|
||||||
state = "on";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
condition = "state";
|
|
||||||
entity_id = "binary_sensor.workday";
|
|
||||||
state = "on";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
action = [
|
|
||||||
{
|
|
||||||
alias = "Play wakeup list";
|
|
||||||
service = "media_player.play_media";
|
|
||||||
data_template = {
|
|
||||||
entity_id = "media_player.mpd";
|
|
||||||
media_content_type = "playlist";
|
|
||||||
media_content_id = "{{ states('input_select.wakeup') }}";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
alias = "turn all on";
|
|
||||||
service = "script.turn_on";
|
|
||||||
entity_id = "script.turn_all_on";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
alias = "Leave Turn all off Timer";
|
|
||||||
trigger = {
|
|
||||||
platform = "template";
|
|
||||||
value_template =
|
|
||||||
"{{ states('sensor.time') == (states.input_datetime.leave.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}";
|
|
||||||
};
|
|
||||||
condition = {
|
|
||||||
condition = "and";
|
|
||||||
conditions = [{
|
|
||||||
condition = "state";
|
|
||||||
entity_id = "input_boolean.leave";
|
|
||||||
state = "on";
|
|
||||||
}];
|
|
||||||
};
|
|
||||||
action = [{
|
|
||||||
alias = "turn all off";
|
|
||||||
service = "script.turn_on";
|
|
||||||
entity_id = "script.turn_all_off";
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
alias = "Return to Home";
|
|
||||||
trigger = {
|
|
||||||
platform = "template";
|
|
||||||
value_template =
|
|
||||||
"{{ states('sensor.time') == (states.input_datetime.return.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}";
|
|
||||||
};
|
|
||||||
condition = {
|
|
||||||
condition = "and";
|
|
||||||
conditions = [{
|
|
||||||
condition = "state";
|
|
||||||
entity_id = "input_boolean.return";
|
|
||||||
state = "on";
|
|
||||||
}];
|
|
||||||
};
|
|
||||||
action = [{
|
|
||||||
alias = "turn all on";
|
|
||||||
service = "script.turn_on";
|
|
||||||
entity_id = "script.turn_all_on";
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
alias = "Sleep Turn all off Timer";
|
|
||||||
trigger = {
|
|
||||||
platform = "template";
|
|
||||||
value_template =
|
|
||||||
"{{ states('sensor.time') == (states.input_datetime.sleep.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}";
|
|
||||||
};
|
|
||||||
condition = {
|
|
||||||
condition = "and";
|
|
||||||
conditions = [{
|
|
||||||
condition = "state";
|
|
||||||
entity_id = "input_boolean.sleep";
|
|
||||||
state = "on";
|
|
||||||
}];
|
|
||||||
};
|
|
||||||
action = [{
|
|
||||||
alias = "turn all off";
|
|
||||||
service = "script.turn_on";
|
|
||||||
entity_id = "script.turn_all_off";
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,279 +0,0 @@
|
||||||
{ pkgs, lib, config, ... }:
|
|
||||||
let
|
|
||||||
|
|
||||||
# allow new devices to join
|
|
||||||
enablePairing = true;
|
|
||||||
|
|
||||||
device = "/dev/ttyACM0";
|
|
||||||
dataFolder = "/srv/zigbee/data";
|
|
||||||
|
|
||||||
sensors = {
|
|
||||||
buttons = {
|
|
||||||
"button_1".id = "0x00158d0002b04f65";
|
|
||||||
"button_2".id = "0x00158d0002b04f09";
|
|
||||||
"button_3".id = "0x00158d0002b00e04";
|
|
||||||
};
|
|
||||||
temperature = {
|
|
||||||
"temperature_sensor_1".id = "0x00158d0002d79220";
|
|
||||||
"temperature_sensor_2".id = "0x00158d0002d7913d";
|
|
||||||
};
|
|
||||||
motion = { "motion_sensor_1".id = "0x00158d0002fbd451"; };
|
|
||||||
};
|
|
||||||
|
|
||||||
# todo : rename with allSensors
|
|
||||||
allSensors = with sensors; buttons // temperature // motion;
|
|
||||||
|
|
||||||
zigBee2MqttConfig = {
|
|
||||||
|
|
||||||
# Home Assistant integration (MQTT discovery)
|
|
||||||
homeassistant = false;
|
|
||||||
# homeassistant = true;
|
|
||||||
|
|
||||||
# allow new devices to join
|
|
||||||
permit_join = enablePairing;
|
|
||||||
|
|
||||||
# MQTT settings
|
|
||||||
mqtt = {
|
|
||||||
# MQTT base topic for zigbee2mqtt MQTT messages
|
|
||||||
base_topic = "zigbee2mqtt";
|
|
||||||
# MQTT server URL
|
|
||||||
server = "mqtt://127.0.0.1:1883";
|
|
||||||
# MQTT server authentication, uncomment if required:
|
|
||||||
user = "zigbee";
|
|
||||||
password = lib.fileContents <secrets/zigbee/password>;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Serial settings
|
|
||||||
serial = {
|
|
||||||
port = "/dev/ttyACM0";
|
|
||||||
# Optional: disable LED of CC2531 USB sniffer
|
|
||||||
disable_led = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
devices = lib.mapAttrs' (name:
|
|
||||||
{ id, ... }: {
|
|
||||||
name = id;
|
|
||||||
value = {
|
|
||||||
retain = false;
|
|
||||||
friendly_name = name;
|
|
||||||
};
|
|
||||||
}) allSensors;
|
|
||||||
};
|
|
||||||
|
|
||||||
configurationYaml =
|
|
||||||
pkgs.writeText "configuration.yml" (builtins.toJSON zigBee2MqttConfig);
|
|
||||||
in {
|
|
||||||
imports = [ ./mqtt.nix ];
|
|
||||||
|
|
||||||
services.homeAssistantConfig = {
|
|
||||||
|
|
||||||
# group.unknown.entities = [ "sensor.button_1" ];
|
|
||||||
|
|
||||||
sensor = let
|
|
||||||
buttons = with lib;
|
|
||||||
mapAttrsToList (name:
|
|
||||||
{ ... }: {
|
|
||||||
platform = "mqtt";
|
|
||||||
name = name;
|
|
||||||
icon = "mdi:toggle-switch";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
value_template = "{{ value_json.click }}";
|
|
||||||
}) sensors.buttons;
|
|
||||||
|
|
||||||
temperature = with lib;
|
|
||||||
mapAttrsToList (name:
|
|
||||||
{ ... }: [
|
|
||||||
{
|
|
||||||
platform = "mqtt";
|
|
||||||
name = name;
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
unit_of_measurement = "°C";
|
|
||||||
device_class = "temperature";
|
|
||||||
value_template = "{{ value_json.temperature }}";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "mqtt";
|
|
||||||
name = "humidity_${name}";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
unit_of_measurement = "%";
|
|
||||||
device_class = "humidity";
|
|
||||||
value_template = "{{ value_json.humidity }}";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "mqtt";
|
|
||||||
name = "pressure_${name}";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
unit_of_measurement = "hPa";
|
|
||||||
device_class = "pressure";
|
|
||||||
value_template = "{{ value_json.pressure }}";
|
|
||||||
}
|
|
||||||
]) sensors.temperature;
|
|
||||||
|
|
||||||
informations = lib.mapAttrsToList (name:
|
|
||||||
{ ... }: [
|
|
||||||
{
|
|
||||||
platform = "mqtt";
|
|
||||||
name = "battery_${name}";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
unit_of_measurement = "%";
|
|
||||||
device_class = "battery";
|
|
||||||
value_template = "{{ value_json.battery }}";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "link_${name}";
|
|
||||||
platform = "mqtt";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
unit_of_measurement = "-";
|
|
||||||
value_template = "{{ value_json.linkquality }}";
|
|
||||||
}
|
|
||||||
]) allSensors;
|
|
||||||
|
|
||||||
in lib.flatten (buttons ++ temperature ++ informations);
|
|
||||||
|
|
||||||
binary_sensor = let
|
|
||||||
|
|
||||||
motion = lib.mapAttrsToList (name:
|
|
||||||
{ ... }: {
|
|
||||||
name = name;
|
|
||||||
platform = "mqtt";
|
|
||||||
device_class = "motion";
|
|
||||||
#icon = "mdi:motion-sensor";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
payload_on = true;
|
|
||||||
payload_off = false;
|
|
||||||
value_template = "{{ value_json.occupancy }}";
|
|
||||||
}) sensors.motion;
|
|
||||||
in lib.flatten (motion);
|
|
||||||
|
|
||||||
group = let
|
|
||||||
|
|
||||||
information = name: [ "sensor.battery_${name}" "sensor.link_${name}" ];
|
|
||||||
|
|
||||||
sensor = lib.mapAttrs' (name:
|
|
||||||
{ ... }: {
|
|
||||||
name = name;
|
|
||||||
value = {
|
|
||||||
control = "hidden";
|
|
||||||
entities = [ "sensor.${name}" ] ++ (information name);
|
|
||||||
};
|
|
||||||
}) (sensors.buttons);
|
|
||||||
|
|
||||||
sensorTemperature = lib.mapAttrs' (name:
|
|
||||||
{ ... }: {
|
|
||||||
name = name;
|
|
||||||
value = {
|
|
||||||
control = "hidden";
|
|
||||||
entities = [
|
|
||||||
"sensor.${name}"
|
|
||||||
"sensor.humidity_${name}"
|
|
||||||
"sensor.pressure_${name}"
|
|
||||||
] ++ (information name);
|
|
||||||
};
|
|
||||||
}) (sensors.temperature);
|
|
||||||
|
|
||||||
binarySensor = lib.mapAttrs' (name:
|
|
||||||
{ ... }: {
|
|
||||||
name = name;
|
|
||||||
value = {
|
|
||||||
control = "hidden";
|
|
||||||
entities = [ "binary_sensor.${name}" ] ++ (information name);
|
|
||||||
};
|
|
||||||
}) (sensors.motion);
|
|
||||||
|
|
||||||
views = {
|
|
||||||
view_sensors = {
|
|
||||||
name = "Sensoren";
|
|
||||||
control = "hidden";
|
|
||||||
view = true;
|
|
||||||
entities =
|
|
||||||
lib.mapAttrsToList (name: { ... }: "group.${name}") allSensors;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
in views // sensor // binarySensor // sensorTemperature;
|
|
||||||
|
|
||||||
automation = let
|
|
||||||
lights = map (button: {
|
|
||||||
alias = "Toggle all lights, on click";
|
|
||||||
trigger = {
|
|
||||||
platform = "mqtt";
|
|
||||||
topic = "zigbee2mqtt/${button}";
|
|
||||||
};
|
|
||||||
condition = {
|
|
||||||
condition = "template";
|
|
||||||
value_template = ''{{ "single" == trigger.payload_json.click }}'';
|
|
||||||
};
|
|
||||||
action = {
|
|
||||||
service = "switch.toggle";
|
|
||||||
entity_id = "group.all_lights";
|
|
||||||
};
|
|
||||||
}) [ "button_1" "button_2" "button_3" ];
|
|
||||||
mpd = map (button: {
|
|
||||||
alias = "Toggle mpd, on double click";
|
|
||||||
trigger = {
|
|
||||||
platform = "mqtt";
|
|
||||||
topic = "zigbee2mqtt/${button}";
|
|
||||||
};
|
|
||||||
condition = {
|
|
||||||
condition = "template";
|
|
||||||
value_template = ''{{ "double" == trigger.payload_json.click }}'';
|
|
||||||
};
|
|
||||||
action = {
|
|
||||||
service = "media_player.toggle";
|
|
||||||
# todo use a group here
|
|
||||||
entity_id = "media_player.mpd";
|
|
||||||
};
|
|
||||||
}) [ "button_1" "button_2" "button_3" ];
|
|
||||||
in lights ++ mpd;
|
|
||||||
|
|
||||||
# click = double => music an aus
|
|
||||||
|
|
||||||
# click = hold => film an aus
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
virtualisation.docker.enable = true;
|
|
||||||
|
|
||||||
# todo : einen eigenen container bauen mit dockerTool : https://nixos.wiki/wiki/Docker
|
|
||||||
|
|
||||||
systemd.services."zigbee2mqtt" = {
|
|
||||||
enable = true;
|
|
||||||
description =
|
|
||||||
"Allows you to use your Zigbee devices without the vendors bridge/gateway.";
|
|
||||||
after = [ "docker.service" ];
|
|
||||||
requires = [ "docker.service" ];
|
|
||||||
# todo : udev rule erstellen, die diesen service erst startet, dieses wanted by ist labil
|
|
||||||
wantedBy = [ "home-assistant.service" ];
|
|
||||||
|
|
||||||
preStart = ''
|
|
||||||
if [ -f ${dataFolder}/configuration.yaml ]
|
|
||||||
then
|
|
||||||
rm ${dataFolder}/configuration.yaml
|
|
||||||
fi
|
|
||||||
mkdir -p ${dataFolder}
|
|
||||||
cat ${configurationYaml} | ${pkgs.yq}/bin/yq --yaml-output '.' > ${dataFolder}/configuration.yaml
|
|
||||||
'';
|
|
||||||
|
|
||||||
restartTriggers = [ configurationYaml ];
|
|
||||||
|
|
||||||
script = ''
|
|
||||||
# delete old instance to ensure update
|
|
||||||
${pkgs.docker}/bin/docker stop zigbee2mqtt || true && ${pkgs.docker}/bin/docker rm -f zigbee2mqtt || true
|
|
||||||
# start instance
|
|
||||||
${pkgs.docker}/bin/docker run \
|
|
||||||
--network="host" \
|
|
||||||
--name zigbee2mqtt \
|
|
||||||
-v ${dataFolder}:/app/data \
|
|
||||||
--device=${device} \
|
|
||||||
koenkk/zigbee2mqtt
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -245,6 +245,7 @@
|
||||||
}) (map (name: { inherit name; }) [
|
}) (map (name: { inherit name; }) [
|
||||||
"workhorse"
|
"workhorse"
|
||||||
"porani"
|
"porani"
|
||||||
|
"pepe"
|
||||||
"sputnik"
|
"sputnik"
|
||||||
]
|
]
|
||||||
#(lib.attrNames config.module.cluster.services.tinc."private".hosts)
|
#(lib.attrNames config.module.cluster.services.tinc."private".hosts)
|
||||||
|
|
|
@ -94,12 +94,12 @@ with lib; {
|
||||||
enable = lib.mkDefault false;
|
enable = lib.mkDefault false;
|
||||||
id = "vatmy-c2qf4";
|
id = "vatmy-c2qf4";
|
||||||
watch = false;
|
watch = false;
|
||||||
devices = [ "workhorse" "porani" ];
|
devices = [ "workhorse" "pepe" "porani" ];
|
||||||
};
|
};
|
||||||
porn = {
|
porn = {
|
||||||
enable = lib.mkDefault false;
|
enable = lib.mkDefault false;
|
||||||
watch = false;
|
watch = false;
|
||||||
devices = [ "workhorse" ];
|
devices = [ "workhorse" "pepe" ];
|
||||||
};
|
};
|
||||||
music-library = {
|
music-library = {
|
||||||
enable = lib.mkDefault false;
|
enable = lib.mkDefault false;
|
||||||
|
@ -111,7 +111,7 @@ with lib; {
|
||||||
enable = lib.mkDefault false;
|
enable = lib.mkDefault false;
|
||||||
id = "mu9mn-zgvsw";
|
id = "mu9mn-zgvsw";
|
||||||
watch = false;
|
watch = false;
|
||||||
devices = [ "workout" "workhorse" "mors" ];
|
devices = [ "workout" "workhorse" "pepe" "mors" ];
|
||||||
};
|
};
|
||||||
music-projects = {
|
music-projects = {
|
||||||
enable = lib.mkDefault false;
|
enable = lib.mkDefault false;
|
||||||
|
@ -122,25 +122,25 @@ with lib; {
|
||||||
smartphone-folder = {
|
smartphone-folder = {
|
||||||
enable = lib.mkDefault false;
|
enable = lib.mkDefault false;
|
||||||
watch = false;
|
watch = false;
|
||||||
devices = [ "workout" "workhorse" "sterni" "smartphone" ];
|
devices = [ "workout" "workhorse" "sterni" "smartphone" "pepe" ];
|
||||||
};
|
};
|
||||||
samples = {
|
samples = {
|
||||||
enable = lib.mkDefault false;
|
enable = lib.mkDefault false;
|
||||||
id = "pcgkj-tjucd";
|
id = "pcgkj-tjucd";
|
||||||
watch = false;
|
watch = false;
|
||||||
devices = [ "workout" "workhorse" "sterni" ];
|
devices = [ "workout" "workhorse" "sterni" "pepe" ];
|
||||||
};
|
};
|
||||||
series = {
|
series = {
|
||||||
enable = lib.mkDefault false;
|
enable = lib.mkDefault false;
|
||||||
id = "all-series";
|
id = "all-series";
|
||||||
watch = false;
|
watch = false;
|
||||||
devices = [ "workhorse" "porani" ];
|
devices = [ "workhorse" "porani" "pepe" ];
|
||||||
};
|
};
|
||||||
video-material = {
|
video-material = {
|
||||||
enable = lib.mkDefault false;
|
enable = lib.mkDefault false;
|
||||||
id = "wgkun-fec5h";
|
id = "wgkun-fec5h";
|
||||||
watch = false;
|
watch = false;
|
||||||
devices = [ "workout" "workhorse" ];
|
devices = [ "workout" "workhorse" "pepe" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
windows-sync = {
|
windows-sync = {
|
||||||
|
@ -149,11 +149,6 @@ with lib; {
|
||||||
watch = false;
|
watch = false;
|
||||||
devices = [ "bumba" "workout" ];
|
devices = [ "bumba" "workout" ];
|
||||||
};
|
};
|
||||||
workout-pepe = {
|
|
||||||
enable = lib.mkDefault false;
|
|
||||||
devices = [ "pepe" "workout" ];
|
|
||||||
watch = false;
|
|
||||||
};
|
|
||||||
workhorse-sterni = {
|
workhorse-sterni = {
|
||||||
enable = lib.mkDefault false;
|
enable = lib.mkDefault false;
|
||||||
devices = [ "workhorse" "sterni" ];
|
devices = [ "workhorse" "sterni" ];
|
||||||
|
|
Loading…
Reference in a new issue