heater fiddeling around with stuff

This commit is contained in:
Ingolf Wagner 2021-03-20 13:28:40 +01:00
parent 9a9f5f58b1
commit cf61334f5e
Signed by: palo
GPG key ID: 76BF5F1928B9618B
9 changed files with 171 additions and 49 deletions

View file

@ -6,7 +6,7 @@ in {
#./home-assistant/mpd.nix
#./home-assistant/timer.nix
./home-assistant/light-control.nix
./home-assistant/heater-control.nix
./home-assistant/iot-control.nix
./home-assistant/chaospott.nix
./home-assistant/kodi.nix
./home-assistant/mqtt.nix

View file

@ -6,6 +6,7 @@ let unstable = import <nixpkgs-unstable> { };
in {
imports = [
./mqtt.nix
./zigbee2mqtt/service.nix
./zigbee2mqtt/buttons.nix
./zigbee2mqtt/configurationHelper.nix
./zigbee2mqtt/doors.nix
@ -18,7 +19,7 @@ in {
./zigbee2mqtt/temperatur.nix
];
services.zigbee2mqtt = {
custom.services.zigbee2mqtt = {
enable = true;
#package = pkgs.own_zigbee2mqtt;
#package = unstable.zigbee2mqtt;
@ -77,9 +78,9 @@ in {
};
};
systemd.services.zigbee2mqtt.environment = {
ZIGBEE2MQTT_DATA = "/var/lib/zigbee2mqtt";
};
#systemd.services.zigbee2mqtt.environment = {
# ZIGBEE2MQTT_DATA = "/var/lib/zigbee2mqtt";
#};
services.nginx = {
enable = true;
@ -89,7 +90,7 @@ in {
serverAliases = [ "zigbee.pepe.private" ];
locations."/" = {
proxyPass = "http://localhost:${
toString config.services.zigbee2mqtt.config.frontend.port
toString config.custom.services.zigbee2mqtt.config.frontend.port
}";
proxyWebsockets = true;
};

View file

@ -3,10 +3,10 @@ let
# https://www.zigbee2mqtt.io/devices/E1757.html
allDevices = {
"fyrtur1" = { id = "0x680ae2fffe64fa40"; }; # office
"fyrtur2" = { id = "0x680ae2fffe6e9f41"; }; # bed room
"fyrtur3" = { id = "0x680ae2fffe8f6411"; }; # (retoure)
"fyrtur4" = { id = "0x680ae2fffe91d234"; }; # office (close to kitchen)
"office_fyrtur_1" = { id = "0x680ae2fffe64fa40"; };
"office_fyrtur_2" = { id = "0x680ae2fffe91d234"; };
"bedroom_fyrtur_1" = { id = "0x680ae2fffe6e9f41"; };
"broken_fyrtur_1" = { id = "0x680ae2fffe8f6411"; };
};
# -t "zigbee2mqtt/fyrtur1/set" -m '{"position":100}'

View file

@ -3,10 +3,10 @@ let
# https://www.zigbee2mqtt.io/devices/SPZB0001.html
allDevices = {
"heater1" = { id = "0x00158d00032f5ee4"; }; # office
"heater2" = { id = "0x00158d00032f5f9f"; }; # office (kitchen)
"heater3" = { id = "0x00158d00032f6d1e"; }; # bed room
"heater4" = { id = "0x00158d00032f604d"; }; # abstell raum
"office_heater_1" = { id = "0x00158d00032f5ee4"; }; # office
"office_heater_2" = { id = "0x00158d00032f5f9f"; }; # office (kitchen)
"bedroom_heater_1" = { id = "0x00158d00032f6d1e"; }; # bed room
"storage_heater_1" = { id = "0x00158d00032f604d"; }; # abstell raum
};
# -t "zigbee2mqtt/heater3/set" -m '{"system_mode":"auto","current_heating_setpoint":23}'
@ -27,9 +27,9 @@ in {
"battery_low"
"eurotronic_host_flags"
"eurotronic_system_mode"
"occupied_heating_setpoint"
#"occupied_heating_setpoint"
#"pi_heating_demand"
"unoccupied_heating_setpoint"
#"unoccupied_heating_setpoint"
];
};
}) allDevices;

View file

@ -0,0 +1,118 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.custom.services.zigbee2mqtt;
configJSON = pkgs.writeText "configuration.json" (builtins.toJSON
(recursiveUpdate cfg.config config.services.zigbee2mqtt.config));
configFile =
pkgs.runCommand "configuration.yaml" { preferLocalBuild = true; } ''
${pkgs.remarshal}/bin/json2yaml -i ${configJSON} -o $out
'';
# the default config contains all required settings,
# so the service starts up without crashing.
defaultConfig = {
homeassistant = false;
permit_join = false;
mqtt = {
base_topic = "zigbee2mqtt";
server = "mqtt://localhost:1883";
};
serial.port = "/dev/ttyACM0";
# put device configuration into separate file because configuration.yaml
# is copied from the store on startup
devices = "devices.yaml";
};
in {
options.custom.services.zigbee2mqtt = {
enable = mkEnableOption "enable zigbee2mqtt service";
package = mkOption {
description = "ignored";
default = pkgs.zigbee2mqtt.override { dataDir = cfg.dataDir; };
defaultText = "pkgs.zigbee2mqtt";
type = types.package;
};
dataDir = mkOption {
description = "Zigbee2mqtt data directory";
default = "/var/lib/zigbee2mqtt";
type = types.path;
};
config = mkOption {
default = { };
type = with types; nullOr attrs;
example = literalExample ''
{
homeassistant = config.services.home-assistant.enable;
permit_join = true;
serial = {
port = "/dev/ttyACM1";
};
}
'';
description = ''
Your <filename>configuration.yaml</filename> as a Nix attribute set.
'';
};
};
config = mkIf (cfg.enable) {
virtualisation.oci-containers.containers.zigbee2mqtt = {
image = "koenkk/zigbee2mqtt:1.18.1";
volumes = [
"${cfg.dataDir}:/app/data"
#"/run/udev:/run/udev:ro"
];
extraOptions = [
"--device=${cfg.config.serial.port}" # /dev/ttyUSB0
"--network=host"
#"--privileged=true"
];
environment = { TZ = "Europe/Amsterdam"; };
#ports = [ "127.0.0.1:${toString frontPort}:80" ];
};
# create config before staring container
systemd.services.docker-zigbee2mqtt = {
preStart = ''
cp --no-preserve=mode ${configFile} "${cfg.dataDir}/configuration.yaml"
'';
};
#systemd.services.zigbee2mqtt = {
# description = "Zigbee2mqtt Service";
# wantedBy = [ "multi-user.target" ];
# after = [ "network.target" ];
# environment.ZIGBEE2MQTT_DATA = cfg.dataDir;
# serviceConfig = {
# ExecStart = "${cfg.package}/bin/zigbee2mqtt";
# User = "zigbee2mqtt";
# WorkingDirectory = cfg.dataDir;
# Restart = "on-failure";
# ProtectSystem = "strict";
# ReadWritePaths = cfg.dataDir;
# PrivateTmp = true;
# RemoveIPC = true;
# };
# preStart = ''
# cp --no-preserve=mode ${configFile} "${cfg.dataDir}/configuration.yaml"
# '';
#};
#users.users.zigbee2mqtt = {
# home = cfg.dataDir;
# createHome = true;
# group = "zigbee2mqtt";
# extraGroups = [ "dialout" ];
# uid = config.ids.uids.zigbee2mqtt;
#};
#users.groups.zigbee2mqtt.gid = config.ids.gids.zigbee2mqtt;
};
}

View file

@ -25,7 +25,6 @@ in {
gwenview
skanlite
#(tor-browser-bundle-bin.overrideAttrs (old: {
# #version = "10.0.13";
# src = pkgs.fetchurl {

View file

@ -17,9 +17,8 @@ class Position(Enum):
class Fyrtur:
def __init__(self, topic, set_topic, top, bottom):
def __init__(self, topic, top, bottom):
self.topic = topic
self.set_topic = set_topic
self.top = top
self.bottom = bottom
self.current_position = 100
@ -31,9 +30,9 @@ class Fyrtur:
def needs_publish(self):
return self.wanted_position != self.current_position
def payload(self):
def topic_and_payload_for_set(self):
payload = {"position": self.wanted_position}
return json.dumps(payload)
return ("%s/set" % self.topic), json.dumps(payload)
class FyrturWatcher:
@ -61,14 +60,15 @@ class FyrturWatcher:
def publish(self, client):
for fyrtur in self.fyrturs.values():
if fyrtur.needs_publish():
client.publish(fyrtur.set_topic, fyrtur.payload())
topic, payload = fyrtur.topic_and_payload_for_set()
client.publish(topic, payload)
time.sleep(2)
watcher = FyrturWatcher({
"office1": Fyrtur(topic="zigbee2mqtt/fyrtur1", set_topic="zigbee2mqtt/fyrtur1/set", top=100, bottom=16),
"office2": Fyrtur(topic="zigbee2mqtt/fyrtur4", set_topic="zigbee2mqtt/fyrtur4/set", top=100, bottom=22),
"bedroom": Fyrtur(topic="zigbee2mqtt/fyrtur2", set_topic="zigbee2mqtt/fyrtur2/set", top=100, bottom=16),
"office1": Fyrtur(topic="zigbee2mqtt/office_fyrtur_1", top=100, bottom=16),
"office2": Fyrtur(topic="zigbee2mqtt/office_fyrtur_2", top=100, bottom=22),
"bedroom": Fyrtur(topic="zigbee2mqtt/bedroom_fyrtur_1", top=100, bottom=16),
})
@ -83,7 +83,6 @@ def on_connect(client, _userdata, _flags, rc):
client.subscribe("control/lights/set")
for topic in watcher.get_topics():
client.subscribe(topic)
# watcher.pull_values(client)
# The callback for when a PUBLISH message is received from the server.
@ -110,7 +109,7 @@ def update_scene(client):
watcher.update("office1", Position.DOWN)
watcher.update("office2", Position.DOWN)
watcher.update("bedroom", Position.DOWN)
elif scene in ["default", "up-bright", "up-dark"]:
elif scene in ["default", "up-bright", "up-dark" "outside"]:
watcher.update("office1", Position.UP)
watcher.update("office2", Position.UP)
watcher.update("bedroom", Position.UP)

View file

@ -6,23 +6,12 @@ from typing import Dict
class Heater:
def __init__(self, topic, set_topic):
def __init__(self, topic):
self.not_initialized_yet = True
self.wanted_temperature = 15
self.actual_temperature = 15
self.set_topic = set_topic
self.wanted_temperature = 10
self.actual_temperature = 10
self.topic = topic
def payload(self):
payload = {
"system_mode": "auto",
"current_heating_setpoint": self.wanted_temperature,
#"occupied_heating_setpoint": self.wanted_temperature,
#"unoccupied_heating_setpoint": self.wanted_temperature,
"eurotronic_host_flags": {"window_open": True}
}
return json.dumps(payload)
def needs_publish(self):
if self.not_initialized_yet:
return True
@ -40,10 +29,25 @@ class Heater:
def topic_and_payload_for_query(self):
payload = {
"current_heating_setpoint": ""
"current_heating_setpoint": "",
"occupied_heating_setpoint": "",
"unoccupied_heating_setpoint": "",
"local_temperature": "",
#"pi_heating_demand": "",
#"system_mode": "",
}
return ("%s/get" % self.topic), json.dumps(payload)
def topic_and_payload_for_set(self):
payload = {
"system_mode": "auto",
#"current_heating_setpoint": str(self.wanted_temperature),
"occupied_heating_setpoint": str(self.wanted_temperature),
"unoccupied_heating_setpoint": str(self.wanted_temperature),
"eurotronic_host_flags": {"window_open": True}
}
return ("%s/set" % self.topic), json.dumps(payload)
class Watcher:
@ -53,7 +57,8 @@ class Watcher:
def publish(self, client):
for heater in self.heater.values():
if heater.needs_publish():
client.publish(heater.set_topic, heater.payload())
topic, payload = heater.topic_and_payload_for_set()
client.publish(topic, payload)
time.sleep(2)
def update(self, name, temperature):
@ -78,9 +83,9 @@ class Watcher:
scene = "default"
watcher = Watcher({
"office1": Heater(topic="zigbee2mqtt/heater1", set_topic="zigbee2mqtt/heater1/set"),
"office2": Heater(topic="zigbee2mqtt/heater2", set_topic="zigbee2mqtt/heater2/set"),
"bedroom": Heater(topic="zigbee2mqtt/heater3", set_topic="zigbee2mqtt/heater3/set"),
"office1": Heater(topic="zigbee2mqtt/office_heater_1"),
"office2": Heater(topic="zigbee2mqtt/office_heater_2"),
"bedroom": Heater(topic="zigbee2mqtt/bedroom_heater_1"),
})
@ -109,7 +114,6 @@ def on_message(client, _userdata, msg):
else:
print("got %s" % topic)
watcher.update_actual_heating_point_for_topic(topic, payload)
# watcher.publish(client)
def parse_message(msg):
@ -122,7 +126,7 @@ def update_scene(client):
if scene in ["night", "outside"]:
watcher.update("office1", 10)
watcher.update("office2", 10)
watcher.update("bedroom", 13)
watcher.update("bedroom", 10)
elif scene in ["default", "up-bright", "up-dark", "half", "down"]:
watcher.update("office1", 26)
watcher.update("office2", 26)
@ -130,7 +134,7 @@ def update_scene(client):
else:
watcher.update("office1", 10)
watcher.update("office2", 10)
watcher.update("bedroom", 13)
watcher.update("bedroom", 10)
watcher.publish(client)
@ -138,6 +142,7 @@ def update_scene(client):
def loop_thread(client):
while True:
watcher.publish(client)
watcher.pull_values(client)
time.sleep(120)