├── README.md
├── zha-backto-zigbee2mqtt.md
├── homeassistant-google-home-ip-ranges.md
├── homeassistant-proxmoxve-updates-notification.md
├── homeassistant-ebusd-statenumber-translation.md
├── homeassistant-diskspace-notification.md
├── proxmox-nixos-lxc.md
├── proxmox-security-groups.md
├── homeassistant-proxmox-host-ssh.md
├── homeassistant-ebusd-read-values.md
├── frigate-lxc.md
├── openwrt-802.11k.md
├── zabbix-mqtt.md
├── zabbix-debian-updating.md
├── proxmox-lxc-nixos-desktop.md
├── ryzenadj-on-proxmox.md
├── homeassistant-ebusd-sensor-names.md
├── frigate-docker-lxc.md
├── MR60BHA2.md
├── provision-lxc-desktop-from-homeassistant.md
└── ebus-hass.md
/README.md:
--------------------------------------------------------------------------------
1 | # proxmox-tips
2 | Some self-hosting tips (Proxmox, HomeAssistant, etc)
3 |
4 | In this repository i described some parts of my home-lab setup.
5 |
--------------------------------------------------------------------------------
/zha-backto-zigbee2mqtt.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 | For a few years i've been using Zigbee2MQTT which did work fine. But during some refactoring of my homeserver i wanted to switch to ZHA as it's integrated in Home Assistant.
3 | Unfortunatly devices are becomming unavailable and seem to be dropping of the network. So now i'll be switching back to Zigbee2MQTT.
4 |
5 | # Zigbee2MQTT
6 |
7 | 1. I added a new Home Assistant addon repository: https://github.com/zigbee2mqtt/hassio-zigbee2mqtt
8 | 2. I installed the Zigbee2MQTT addon
9 | 3. Copied the serial port ZHA is using: `/dev/serial/by-id/usb-Silicon_Labs_CP2102N_USB_to_UART_Bridge_Controller_46541a0ee993eb1198edb15b3d98b6d1-if00-port0` and `/dev/ttyUSB1`
10 | 4. Disabled the ZHA-integration
11 | 5. In the field "serial" i put in: `port: /dev/serial/by-id/usb-Silicon_Labs_CP2102N_USB_to_UART_Bridge_Controller_46541a0ee993eb1198edb15b3d98b6d1-if00-port0`
12 | 6. I started the addon
13 | 7. I then removed the ZHA-integration
14 |
--------------------------------------------------------------------------------
/homeassistant-google-home-ip-ranges.md:
--------------------------------------------------------------------------------
1 | I use my Google Home devices to control my smart-home via Home Assistant. This uses the Google Assistant integration in Home Assistant.
2 |
3 | For this to work i need to allow the following IP-ranges through my firewall to my Home Assistant instance.
4 |
5 | This are the IP-ranges:
6 | * 66.102.0.0/20
7 | * 66.249.80.0/20
8 | * 74.125.0.0/16
9 | * 108.177.0.0/17
10 | * 192.178.0.0/15
11 |
12 | I also had to add an IP-address from my ISP (Tmobile/Odido), but this might be from a mobile phone:
13 | * 89.205.130.202
14 |
15 | This are some of the IP-adresses i actually saw incomming traffic from:
16 | * 66.102.9.73
17 | * 66.102.9.74
18 | * 66.249.81.133
19 | * 66.249.93.14
20 | * 66.249.93.2
21 | * 74.125.208.72
22 | * 74.125.208.73
23 | * 74.125.208.74
24 | * 74.125.211.7
25 | * 108.177.64.4
26 | * 108.177.64.5
27 | * 108.177.64.6
28 | * 108.177.76.2
29 | * 192.178.13.200
30 |
31 |
32 |
33 | Resources:
34 | * https://community.home-assistant.io/t/expose-home-assistant-for-google-ips-only-ipv4-only/184646
35 | * https://md5calc.com/google/ip
36 | * https://www.gstatic.com/ipranges/goog.json
37 |
--------------------------------------------------------------------------------
/homeassistant-proxmoxve-updates-notification.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 | Via HACS i installed the [ProxmoxVE-integration](https://github.com/dougiteixeira/proxmoxve) to be able to monitor my Proxmox-installation. I would like to see a persistent-notification in Home Assistant when an update is available for ProxmoxVE.
3 |
4 |
5 | # Automations
6 |
7 | This is the automation to create a persistant notification when updates are available for ProxmoxVE:
8 | ```
9 | alias: ProxmoxVE updates notificatie
10 | description: ""
11 | trigger:
12 | - platform: numeric_state
13 | entity_id:
14 | - sensor.node_pve_total_updates
15 | above: 0
16 | - platform: homeassistant
17 | event: start
18 | condition:
19 | - condition: numeric_state
20 | entity_id: sensor.node_pve_total_updates
21 | above: 0
22 | action:
23 | - service: persistent_notification.create
24 | data:
25 | message: >-
26 | {{ states("sensor.node_pve_total_updates") }} updates beschikbaar voor
27 | ProxmoxVE
28 | notification_id: proxmoxve_updates
29 | ```
30 | I added "Home Assistant start" as a trigger as otherwise the notification will disappear after a restart of Home Assistant.
31 |
32 | And an automation to close the notification when no updates are available:
33 | ```
34 | alias: ProxmoxVE updates notificatie sluiten
35 | trigger:
36 | - platform: numeric_state
37 | entity_id:
38 | - sensor.node_pve_total_updates
39 | below: 1
40 | action:
41 | - service: persistent_notification.dismiss
42 | data:
43 | notification_id: proxmoxve_updates
44 | ```
45 |
--------------------------------------------------------------------------------
/homeassistant-ebusd-statenumber-translation.md:
--------------------------------------------------------------------------------
1 | Page 44/45: https://www.vaillant.nl/downloads/handleidingen-na-10-december-2014/installatiehandleiding-ecotec-plus-0020116691-05-272298.pdf
2 |
3 | My Vaillant EcoTec CV publishes it's "statenumber" on the ebus. By translating the numbers into a textual description, the functioning of the CV is much more clear.
4 |
5 | Home Assistant "Template helper sensor" to translate "ebusd bai statenumber" into a description:
6 | ```text
7 | {{
8 | {
9 | '0':'Verwarming geen warmtevraag',
10 | '1':'CV-bedrijf ventilatorstart',
11 | '2':'CV-bedrijf pompvoorloop',
12 | '3':'CV-bedrijf ontsteking',
13 | '4':'CV-bedrijf brander aan',
14 | '5':'CV-bedrijf pomp-/ventilatornaloop',
15 | '6':'CV-bedrijf ventilatornaloop',
16 | '7':'CV-bedrijf pompnaloop',
17 | '8':'CV-bedrijf restwachttijd',
18 | '9':'Meetprogramma',
19 | '10':'Warmwatervraag door stromingssensor',
20 | '11':'Warmwaterbedrijf ventilatorstart',
21 | '13':'Warmwaterbedrijf ontsteking',
22 | '14':'Warmwaterbedrijf brander aan',
23 | '15':'Warmwaterbedrijf pomp-/ventilatornaloop',
24 | '16':'Warmwaterbedrijf ventilatornaloop',
25 | '17':'Warmwaterbedrijf pompnaloop',
26 | '30':'Kamerthermostaat (RT) blokkeert CV vraag',
27 | '31':'Zomermodus actief of geen warmtevraag door eBus-thermostaat',
28 | '32':'Wachttijd wegens afwijking ventilatortoerental',
29 | '34':'Vorstbeveiligingsfunctie actief',
30 | '76':'Installatiedruk te gering. Water bijvullen'
31 | }.get(states('sensor.ebusd_bai_statenumber') | default('') )
32 | }}
33 | ```
34 |
35 | The above states can also be viewed using the "live monitor" functionality on the display of the CV.
36 |
37 | In Home Assistant i see this in the logbook:
38 | 
39 |
--------------------------------------------------------------------------------
/homeassistant-diskspace-notification.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 | I just got an error in Homeassistant about the file-system being readonly. This was caused by Homeassistant running out-of-disk-space in the VM as the disk was only 32gb. I would've liked to have received a notification for this. To resolve the error itself i increased the sized of the disk via Proxmox.
3 |
4 | # Data-disk
5 | I also chose to take this opportunity to add a second disk to the Home Assistant VM and to make this the data-disk for Home Assistant.
6 | 1. Via Proxmox i added a 40gb on SCSI:1 with writetrough-caching, enabled discard, enabled backup. It's important to choose the size to match or be larger than the current disk on which Home Assistant is installed or an errormessage will be displayed in Home Assistant.
7 | 2. Rebooted the Home Assistant VM to get Home Assistant to learn about the newly added disk
8 | 3. Navigate in Home Assistant to "Settings" > "Storage"
9 | 4. I chose "Move data-disk" and selected the only available option "drive-scsi1"
10 | 5. In the Proxmox console of the Home Assistant VM i watched the log for the operation to complete
11 |
12 | # Sensors
13 | I would expect that Homeassistant or "Home Assistant Supervisor" to provide information about diskspace, but apparently not.
14 | But the "systemmonitor" integration does provide this information. With this Yaml the diskspace information will become available:
15 | ```
16 | sensor:
17 | - platform: systemmonitor
18 | resources:
19 | - type: processor_use
20 | - type: disk_use_percent
21 | arg: /
22 | - type: disk_use_percent
23 | arg: /config
24 | - type: disk_use
25 | arg: /
26 | - type: disk_free
27 | arg: /
28 | ```
29 | After reload/reboot Home Assistant i got the following sensors:
30 | * `sensor.processor_use`
31 | * `sensor.disk_use_percent`
32 | * `sensor.disk_use_percent_config`
33 | * `sensor.disk_use`
34 | * `sensor.disk_free`
35 |
36 |
37 | # Automation
38 | With the following automation i will receive a notification on my iPhone when more than 90% is used:
39 | ```
40 | alias: Home Assistant controleer vrije diskruimte
41 | description: ""
42 | trigger:
43 | - platform: numeric_state
44 | entity_id:
45 | - sensor.disk_use_percent
46 | above: 90
47 | - platform: numeric_state
48 | entity_id:
49 | - sensor.disk_use_percent_config
50 | above: 90
51 | action:
52 | - service: notify.mobile_app_iphone_van_sander
53 | data:
54 | message: Weinig vrije diskruimte voor Home Assisant
55 | mode: single
56 | ```
57 |
--------------------------------------------------------------------------------
/proxmox-nixos-lxc.md:
--------------------------------------------------------------------------------
1 | # Create NixOS environments as Proxmox LXC containers
2 | Created on: 18-12-2024, NixOS release 24.11, Proxmox v8.3.1
3 |
4 | ## Get a NixOS container template from hydra.nixos.org
5 |
6 | 1. Open in browser: [https://hydra.nixos.org/project/nixos](https://hydra.nixos.org/project/nixos)
7 | 2. Select the release: [at this time: `nixos:release-24.11`](https://hydra.nixos.org/jobset/nixos/release-24.11)
8 | 3. Navigate to the tab: `Jobs` [nixos:release-24.11 Jobs](https://hydra.nixos.org/jobset/nixos/release-24.11#tabs-jobs)
9 | 4. On the Jobs-tab use the search-bar to search for: `nixos.proxmoxLXC.x86_64-linux`
10 | 5. Click a green checkmark which sits behind the correct CPU-arch
11 | 6. Copy the download link of `nixos-system-x86_64-linux.tar.xz`
12 | 7. In the Proxmox Web UI, navigate to the "Storage" and choose `CT Template`
13 | 8. Click the button `Download from URL` and paste the download link ([at this time](https://hydra.nixos.org/build/282070945/download/1/nixos-system-x86_64-linux.tar.xz))
14 |
15 | ## Create a NixOS environment as a Proxmox LXC container
16 | * The exact parameters for `cmode`, `unprivileged`, `ostype`, and `features` is needed for getting this container running.
17 | * The container will get an IP via DHCP
18 | * The root user in the container is passwordless
19 | * SSH is enabled, also for the root user
20 |
21 | Run on your Proxmox host:
22 | ```
23 | pct create 300 local-btrfs:vztmpl/nixos-system-x86_64-linux.tar.xz --tags nixos --cmode console \
24 | -ostype nixos --arch amd64 -net0 name=eth0,bridge=vmbr0,hwaddr=BC:24:11:8B:6C:00,ip=dhcp,type=veth \
25 | -storage local-btrfs --hostname qbittorrent --swap 0 --memory 2048 --unprivileged 0 --features nesting=1
26 |
27 | pct resize 300 rootfs +2G
28 | pct start 300
29 | pct enter 300
30 | ```
31 | In the shell of CT 300:
32 | 1. Run: `source /etc/set-environment`
33 | 2. Clear the root password: `passwd --delete root`
34 | 3. Start editting: `nano /etc/nixos/configuration.nix`
35 | 4. Add the following minimal configuration to allow for remote deployment via SSH
36 | ```
37 | { config, modulesPath, pkgs, lib, ... }:
38 | {
39 | imports = [ (modulesPath + "/virtualisation/proxmox-lxc.nix") ];
40 | nix.settings = { sandbox = false; };
41 | security.pam.services.sshd.allowNullPassword = true;
42 | services.openssh = {
43 | enable = true;
44 | openFirewall = true;
45 | settings = {
46 | PermitRootLogin = "yes";
47 | PasswordAuthentication = true;
48 | PermitEmptyPasswords = "yes";
49 | };
50 | };
51 | system.stateVersion = "24.11";
52 | }
53 | ```
54 | 4. Run the following commands
55 | ```
56 | nix-channel --update
57 | nixos-rebuild switch --upgrade
58 | ```
59 |
60 | I myself use this container as the target to deploy a flake target onto, by:
61 | ```
62 | nixos-rebuild switch --flake .#qbittorrent --target-host root@192.168.1.119
63 | ```
64 |
65 |
66 |
--------------------------------------------------------------------------------
/proxmox-security-groups.md:
--------------------------------------------------------------------------------
1 | If you have multiple virtual appliances in Proxmox with Zabbix-clients, then it's possible to create a "Security Group" to configure a set of firewall rules.
2 |
3 | Zabbix-server communicates with it's Zabbix client instances using TCP 10050.
4 | It's also possible to have an "active" Zabbix client instance which will communicate using TCP 10051 to the Zabbix-server.
5 |
6 | # Create alias for Zabbix-server IP#
7 | 1. Navigate in Proxmox WebUI to the Proxmox Cluster node.
8 | 2. Expand the menu "Firewall"
9 | 3. Navigate to "Alias"
10 | 4. Click "Create" to create an alias
11 | 5. Give:
12 | name: `Zabbix-server`
13 | IP/CIDR: `192.168.178.10`
14 | Comment: `Zabbix server`
15 |
16 | # Create Security Group "Zabbix-client"
17 | 1. Navigate in Proxmox WebUI to the Proxmox Cluster node.
18 | 2. Expand the menu "Firewall"
19 | 3. Navigate to "Security Group"
20 | 4. Click "Create" to create a group
21 | 5. Give name: `zabbix-client`
22 | 6. Confirm with the "OK" button
23 | 7. Select the group "zabbix-client"
24 | 8. On the right-side choose for "Add"
25 | 9. Configure:
26 | Direction: `In`
27 | Action: `Accept`
28 | Protocol: `TCP`
29 | Dest.Port: `10050`
30 | Source: alias `zabbix-server`
31 | Comment: `Allow inbound Zabbix agent traffic`
32 | Log level: `nolog`
33 | 10. Choose again on the right side for "Add"
34 | 11. Configure:
35 | Direction: `Out`
36 | Action: `Accept`
37 | Protocol: `TCP`
38 | Dest.Port: `10051`
39 | Destination: alias `zabbix-server`
40 | Comment: `Allow outbound Zabbix agent (active) traffic`
41 | Log level: `nolog`
42 |
43 | # Insert Security Group "Zabbix-client" to "OPNsense"
44 | 1. Navigate in Proxmox to your "OPNsense" container
45 | 2. Navigate to the Firewall-menu
46 | 3. Click the "Insert: security group" button
47 | 4. Select:
48 | Security Group: `zabbix-client`
49 | Enabled: `checked`
50 | 5. Confirm with the "OK" button
51 |
52 | # Create Security Group for "Zabbix-ping"
53 | I also configured Zabbix-server to ping my network devices. I want to allow this ping-checks.
54 | So i created a "Security Group" named `zabbix-ping`.
55 | With a rule:
56 | Direction: `In`
57 | Action: `Accept`
58 | Protocol: `icmp`
59 | ICMP-type: `echo-request`
60 | Source: `zabbix-server`
61 | Comment: `Allow inbound Zabbix ping`
62 | Log level: `nolog`
63 | I added this security group to all my LXCs/VMs.
64 |
65 | # Create Security Group for "Mail-delivery"
66 | I also create a Security Group to allow mail-delivery (smtp, tcp/25) to my mail-server.
67 |
68 | I create an alias for my mail-server:
69 | * Name: `Mail-server`
70 | * IP/CIDR: `192.168.178.97`
71 | * Comment: `Mail server`
72 |
73 | So i created a "Security Group" named `mail-delivery`.
74 | With a rule:
75 | Direction: `Out`
76 | Action: `Accept`
77 | Protocol: `tcp`
78 | Dest Port: `80`
79 | Destination: alias `mail-server`
80 | Comment: `Allow mail delivery`
81 | Log level: `nolog`
82 | I added this security group to all my LXCs/VMs which make use of mail-delivery (Zabbix, PVE-node).
83 |
84 |
85 | # Create Security Group for "drop-inbound-mdns"
86 |
87 | | | | Protocol | Destination |
88 | |------|------|--------------|-------------|
89 | | IN | DROP |
90 |
--------------------------------------------------------------------------------
/homeassistant-proxmox-host-ssh.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 | I wanted to use Homeassistant to execute scripts on my Proxmox host. In the past i did this through setting up SSH-connection by logging in as the root.
3 | I searched for an alternative solution which would work without SSH. I though something like a rest-api for triggering scripts would exist. And indeed those solutions did exist, but no common-used-solution that everybody is using.
4 | This common-used-solution seem to be "SSH". So eventually i chose to use SSH.
5 |
6 | # Creating the "Homeassistant" user on the Proxmox host
7 | 1. Open a Shell on Proxmox via the Web-gui
8 | 2. Create the user “homeassistant” with: `useradd --shell /usr/bash --create-home homeassistant`
9 |
10 | # Enable the "Homeassistant" user in Proxmox
11 | 1. Navigate in the Proxmox GUI to the "Server View" > “Datacenter”
12 | 2. Navigate to “Permissions” > “Users”
13 | 3. Click “Add”
14 | 4. Give "Username": `homeassistant`
15 | 5. Ensure "Realm": `Linux PAM standard authentication`
16 | 6. Ensure "Enabled": `Checked`
17 | 7. Click the button to create the user
18 | 8. Select the user `homeassistant`
19 | 9. Choose the button "Password"
20 | 10. Enter a password
21 |
22 | # Generate keypair and provide to remote host
23 | 1. Open "Homeassistant"
24 | 2. Install the "SSH-addon"
25 | 3. Configure the "SSH-addon" to accept a password by providing a password
26 | 4. Configure the "SSH-addon" to work on port: 22
27 | 5. Start the SSH-addon
28 | 6. Choose the the button "OPEN WEB-UI"
29 | 7. In the console crreate directory: `mkdir -p /config/key/`
30 | 8. Generate keypair: `ssh-keygen -t rsa -b 4096 -f /config/key/id_rsa`
31 | 9. Copy the public key to the Proxmox-host: `ssh-copy-id -i /config/key/id_rsa.pub homeassistant@192.168.178.2` (192.168.178.2 is the IP# of my Proxmox-host)
32 | 10. Accept the fingerprint of the remote host (SSH addon)
33 | 11. Enter the password of the user “homeassistant” you created on the Proxmox-host
34 |
35 | # (Optional) Allow Homeassistant to run ryzenadj
36 | In the shell of the Proxmox-host as the root user:
37 | 1. Create a usegroup which can run "ryzenadj": `groupadd ryzenadj`
38 | 2. Make the user "homeassistant" member of the usergroup: `usermod -aG ryzenadj homeassistant`
39 | 3. Create a sudoers-file to allow for running "ryzenadj" with "sudo" without requiring a password: `nano /etc/sudoers.d/ryzenadj`
40 | 4. Put in this file:
41 | ```
42 | ## Members of the ryzenadj group may gain some privileges
43 | %ryzenadj ALL=(ALL) NOPASSWD: /usr/local/bin/ryzenadj
44 | ```
45 | I installed the [remote command line integration](https://github.com/koying/ha-remote-command-line) via HACS.
46 | In homeassistant add this yaml:
47 | ```
48 | remote_command_line:
49 | tdp_low:
50 | ssh_user: homeassistant
51 | ssh_host: 192.168.178.2 < IP# of my Proxmox host
52 | ssh_key: /config/key/id_rsa
53 | command_timeout: 10
54 | command: "sudo ./ryzenadj --stapm-limit=1000 --fast-limit=1000 --slow-limit=1000 --tctl-temp=90 --power-saving > /dev/null"
55 |
56 | tdp_high:
57 | ssh_user: homeassistant
58 | ssh_host: 192.168.178.2
59 | ssh_key: /config/key/id_rsa < IP# of my Proxmox host
60 | command_timeout: 10
61 | command: "sudo ./ryzenadj --stapm-limit=45000 --fast-limit=45000 --slow-limit=45000 --tctl-temp=90 --max-performance > /dev/null"
62 | ```
63 |
64 |
--------------------------------------------------------------------------------
/homeassistant-ebusd-read-values.md:
--------------------------------------------------------------------------------
1 | The following script will send an "ebusd/list"- and some "get"-commands via MQTT. This to populate Home Assistant entities as early as possible with values.
2 | This script also registers high-priority updating for some values.
3 |
4 | ```
5 | alias: Alle ebusd entiteiten voorzien van de ontvangen waarden of null
6 | description: ""
7 | sequence:
8 | - service: mqtt.publish
9 | data:
10 | topic: ebusd/list
11 | payload: " "
12 | alias: Publiceer "ebusd/list" commando voor ophalen alle bekende waarden
13 | - delay:
14 | seconds: 5
15 | - variables:
16 | topics:
17 | - 350/DisplayedHc1RoomTempDesired
18 | - 350/DisplayedRoomTemp
19 | - 350/HwcOPMode
20 | - 350/Hc1DayTemp
21 | - 350/Hc1HolidayRoomTemp
22 | - 350/Hc1NightTemp
23 | - bai/PrEnergySumHc1
24 | - bai/PrEnergySumHwc1
25 | - bai/PartloadHcKW
26 | alias: Definieer lijst van topics waarvan de waarde opgevraagd dient te worden
27 | - alias: Publiceer "get" commando's voor ophalen van waarden van topics
28 | repeat:
29 | count: "{{ topics | count }}"
30 | sequence:
31 | - variables:
32 | topic: ebusd/{{ topics[repeat.index - 1] }}/get
33 | - service: mqtt.publish
34 | data:
35 | topic: "{{topic}}"
36 | - variables:
37 | topics:
38 | - bai/Flame
39 | - bai/CirPump
40 | - bai/HwcWaterflow
41 | - bai/PrEnergySumHc1
42 | - bai/PrEnergySumHwc1
43 | - bai/Statenumber
44 | - bai/HwcDemand
45 | - bai/RemainingBoilerblocktime
46 | - bai/ReturnTemp
47 | - bai/PumpPowerDesired
48 | alias: >-
49 | Definieer lijst van topics waarvan de waarde regelmatig bijgewerkt dient
50 | te worden
51 | - alias: >-
52 | Publiceer "get?1" commando's voor het regelmatig bijwerken van de waarden
53 | van topics
54 | repeat:
55 | count: "{{ topics | count }}"
56 | sequence:
57 | - variables:
58 | topic: ebusd/{{ topics[repeat.index - 1] }}/get
59 | - service: mqtt.publish
60 | data:
61 | topic: "{{topic}}"
62 | payload: "?1"
63 | ```
64 |
65 | I combine the script above with the two following automations:
66 | ```
67 | alias: Alle ebusd waarden opvragen bij starten Home Assistant
68 | description: ""
69 | trigger:
70 | - platform: homeassistant
71 | event: start
72 | action:
73 | - delay:
74 | hours: 0
75 | minutes: 1
76 | seconds: 0
77 | milliseconds: 0
78 | - service: script.turn_on
79 | metadata: {}
80 | data: {}
81 | target:
82 | entity_id: script.opvragen_ebusd_waarden
83 | ```
84 |
85 | ```
86 | alias: Alle ebusd waarden opvragen na opstarten ebusd/mqtt
87 | description: ""
88 | trigger:
89 | - platform: state
90 | entity_id:
91 | - sensor.ebusd_scan
92 | to: "\"finished\""
93 | condition: []
94 | action:
95 | - delay:
96 | hours: 0
97 | minutes: 1
98 | seconds: 0
99 | milliseconds: 0
100 | - service: script.turn_on
101 | metadata: {}
102 | data: {}
103 | target:
104 | entity_id: script.opvragen_ebusd_waarden
105 | mode: single
106 | ```
107 |
108 |
109 | Because of the above script i can see an accurate representation of my boiler:
110 | 
111 |
112 | 
113 |
114 |
115 | 
116 |
--------------------------------------------------------------------------------
/frigate-lxc.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 | I've tried many different apps to monitor my security camera, but i keep on comming back to Frigate and it's free.
3 | * I found the UI of Shinobi counter-intuitive. Also the live-stream was very much delayed. I chose to switch to Frigate again when the Testflight-period expired of the Shinobi-iOS app.
4 |
5 | # Create container
6 | 1. I used the TTeck Docker script to create the container with:
7 | `bash -c "$(wget -qLO - https://github.com/tteck/Proxmox/raw/main/ct/docker.sh)"`
8 | 2. During the script i chose "Debian 12", hostname "frigate", disable ipv6
9 | 3. I also chose to make the container "Privileged". This as i intend to give the container access to my GPU.
10 | 4. I also had to choose the option "enabled fuse OverlayFS". This as my Proxmox host is using ZFS.
11 | 5. I choose NOT to install "Portainer" or the "Portainer agent"
12 | 6. I chose to install "Docker Compose"
13 |
14 | # Bind mounts
15 | 1. Stop the created container
16 | 2. Make a directory for storage on the proxmox host via the Proxmox shell: `mkdir /root/frigate`
17 | 2. Also in the Proxmox shell configure the mount for storage on the container: `pct set 211 -mp0 /root/frigate,mp=/cctv_clips`
18 | 3. Add an mount to passthrough the GPU: `nano /etc/pve/lxc/211.conf`
19 | 4. Add the following line: `lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file 0, 0`. I also had to add the environment variable "LIBVA_DRIVER_NAME" in the docker-compose.yaml file. This to allow my AMD Ryzen 4800H CPU to hardware accelerate video processing.
20 | 5. I chose to remove mounting of USB-devices from the LXC configuration file. This as i will not use that.
21 | 6. Choose to start the container with: `pct start 211`
22 |
23 |
24 | # Install Frigate
25 | 1. Via the Proxmox Web-UI open the console of the created container
26 | 2. In the console, run: `cd /opt`
27 | 3. Create a docker compose file: `nano docker-compose.yaml` and put this in this file
28 | ```
29 | version: '3.9'
30 |
31 | services:
32 |
33 | frigate:
34 | container_name: frigate
35 | privileged: true
36 | restart: unless-stopped
37 | image: ghcr.io/blakeblackshear/frigate:stable
38 | shm_size: "128mb"
39 | devices:
40 | - /dev/dri/renderD128
41 | volumes:
42 | - /etc/localtime:/etc/localtime:ro
43 | - /opt/frigate/config:/config:ro
44 | - /cctv_clips:/media/frigate
45 | - type: tmpfs
46 | target: /tmp/cache
47 | tmpfs:
48 | size: 1000000000
49 | ports:
50 | - "5000:5000"
51 | - "1935:1935" # RTMP feeds
52 | environment:
53 | FRIGATE_RTSP_PASSWORD: "myPassword"
54 | LIBVA_DRIVER_NAME: "radeonsi"
55 | ```
56 |
57 | # Continue
58 | 1. Run: `mkdir -p /opt/frigate/config`
59 | 1. Run: `cd /opt`
60 | 2. Run: `docker compose pull`
61 | 3. Run: `nano /opt/frigate/config/config.yml`
62 | 4. Put this in the file:
63 |
64 | ```
65 | mqtt:
66 | enabled: false
67 | ffmpeg:
68 | hwaccel_args: preset-vaapi
69 | detectors:
70 | coral:
71 | type: edgetpu
72 | device: usb
73 | #Global Object Settings
74 | objects:
75 | track:
76 | - person
77 | filters:
78 | person:
79 | min_area: 5000
80 | max_area: 100000
81 | cameras:
82 | FrontCam:
83 | ffmpeg:
84 | inputs:
85 | # High Resolution Stream
86 | - path: rtsp://192.168.22.1:7447/P6C9GcVoZ8mRmYor
87 | roles:
88 | - record
89 | # Low Resolution Stream
90 | - path: rtsp://192.168.22.1:7447/s0Wju46GtlXua3J4
91 | roles:
92 | - detect
93 | detect:
94 | width: 480
95 | height: 360
96 | fps: 24
97 | ```
98 |
99 | 1. Run: `docker compose pull -d`
100 |
101 |
102 |
103 | Based on:
104 | * https://www.homeautomationguy.io/blog/running-frigate-on-proxmox
105 | * https://github.com/blakeblackshear/frigate/discussions/1111
106 |
107 |
108 | Todo:
109 | I suspect this also needs to be added to the 211.conf file:
110 | ```
111 | lxc.cgroup2.devices.allow: c 226:128 rwm
112 | ```
113 |
--------------------------------------------------------------------------------
/openwrt-802.11k.md:
--------------------------------------------------------------------------------
1 | For a while i've used Usteer and Dawn to enable devices to switch between Access-Points. Modern devices would roam using 802.11k and 802.11r and legacy devices would be kicked upon bad-connections.
2 |
3 | I was doing experimentation with `ubus` and noticed the ability to call `rrm_nr_list` to retrieve the list of WiFi-networks to be available for roaming. I think a static list of networks would be sufficient.
4 | I have 4 access-points in my house with the same SSID for 2g and 5g bands. So devices should already be able to roam automatically. But wihout 802.11r a new handshake would probably need to be made.
5 |
6 | I have configured the radio's to align with the names of the bands: `2g` and `5g` instead of (phy0-ap0, phy1-ap0).
7 |
8 | Check if 802.11k and 802.11v is enabled on your access-points, by running:
9 | ```
10 | ubus call hostapd.5g get_status
11 | ubus call hostapd.2g get_status
12 | ```
13 |
14 | You can enable with:
15 | ```
16 | ubus call hostapd.5g bss_mgmt_enable '{ "neighbor_report": true, "beacon_report": true, "link_measurements": true, "bss_transition": true }'
17 | ```
18 |
19 | ```
20 | {
21 | "status": "ENABLED",
22 | "bssid": "90:9f:22:0d:97:bf",
23 | "ssid": "WiFiForMe",
24 | "freq": 5320,
25 | "channel": 64,
26 | "op_class": 128,
27 | "beacon_interval": 100,
28 | "bss_color": 8,
29 | "phy": "phy1",
30 | "rrm": {
31 | "neighbor_report_tx": 13
32 | },
33 | "wnm": {
34 | "bss_transition_query_rx": 0,
35 | "bss_transition_request_tx": 0,
36 | "bss_transition_response_rx": 0
37 | },
38 | "airtime": {
39 | "time": 6528591,
40 | "time_busy": 454027,
41 | "utilization": 18
42 | },
43 | "dfs": {
44 | "cac_seconds": 0,
45 | "cac_active": false,
46 | "cac_seconds_left": 0
47 | }
48 | }
49 |
50 | ```
51 |
52 |
53 | For all your access-points you need to retrieve some info of the interfaces by running:
54 | ```
55 | ubus call hostapd.5g rrm_nr_get_own
56 | ubus call hostapd.2g rrm_nr_get_own
57 | ```
58 |
59 |
60 |
61 | Using the info i retrieved from my Access-Points i created the following script:
62 | ```/root/rrm.sh
63 | ssid="WiFiForMe"
64 | ap_beneden=[\"f8:0d:a9:3a:19:ba\",\"$ssid\",\"f80da93a19baef5900008088090603028a00\"],[\"f8:0d:a9:3a:19:b9\",\"$ssid\",\"f80da93a19b9ef4900005101070603000100\"]
65 | ap_keuken=[\"90:9f:22:0d:97:bf\",\"$ssid\",\"909f220d97bfef5900008040090603023a00\"],[\"90:9f:22:0d:97:be\",\"$ssid\",\"909f220d97beef4900005103070603000300\"]
66 | ap_washok=[\"d4:1a:d1:18:87:01\",\"$ssid\",\"d41ad1188701ef5900008040090603023a00\"],[\"d4:1a:d1:18:87:00\",\"$ssid\",\"d41ad1188700ef4900005106070603000600\"]
67 | ap_zolder=[\"f8:0d:a9:3a:01:01\",\"$ssid\",\"f80da93a0101ef5900008040090603023a00\"],[\"f8:0d:a9:3a:00:00\",\"$ssid\",\"f80da93a0000ef490000510d070603000d00\"]
68 |
69 | # Remove current Access-Point from $list. This to not advertise itself.
70 | list=[$ap_beneden,$ap_zolder,$ap_washok,$ap_keuken]
71 |
72 | ubus call hostapd.5g rrm_nr_set '{"list": '$list' }'
73 | ubus call hostapd.2g rrm_nr_set '{"list": '$list' }'
74 | ```
75 | The script will register 5g and 2g of each Access-Point and assigns them both bands.
76 |
77 | Check using:
78 | ```
79 | ubus call hostapd.5g rrm_nr_list
80 | ubus call hostapd.2g rrm_nr_list
81 | ```
82 |
83 | ```
84 | more /var/run/hostapd-ph0.conf
85 | ```
86 |
87 | In Startup: `sleep 10 && /root/rrm.sh &`
88 |
89 |
90 | https://github.com/simonyiszk/openwrt-rrm-nr-distributor
91 |
92 |
93 | ```
94 | root@AP-Keuken:~# hostapd_cli -i 5g show_neighbor
95 | d4:1a:d1:18:87:00 ssid=57694669466f724d65 nr=d41ad1188700ef4900005106070603000600
96 | d4:1a:d1:18:87:01 ssid=57694669466f724d65 nr=d41ad1188701ef5900008040090603023a00
97 | f8:0d:a9:3a:00:00 ssid=57694669466f724d65 nr=f80da93a0000ef490000510d070603000d00
98 | f8:0d:a9:3a:01:01 ssid=57694669466f724d65 nr=f80da93a0101ef5900008040090603023a00
99 | f8:0d:a9:3a:19:b9 ssid=57694669466f724d65 nr=f80da93a19b9ef4900005101070603000100
100 | f8:0d:a9:3a:19:ba ssid=57694669466f724d65 nr=f80da93a19baef5900008088090603028a00
101 | 90:9f:22:0d:97:bf ssid=57694669466f724d65 nr=909f220d97bfef5900008040090603023a00 stat
102 | ```
103 |
--------------------------------------------------------------------------------
/zabbix-mqtt.md:
--------------------------------------------------------------------------------
1 | # Monitoring MQTT with Zabbix
2 |
3 | ## MQTT-plugin
4 | The Zabbix-agent2 version has support for MQTT using the [MQTT-plugin](https://www.zabbix.com/documentation/current/en/manual/appendix/config/zabbix_agent2_plugins/mqtt_plugin).
5 | I've decided that i wanted to use the agent within my Zabbix-LXC-container would be the best instance to have it monitor MQTT.
6 |
7 | ### Install Zabbix-agent2 in Zabbix-LXC-container
8 | My Zabbix-LXC-container was setup with the older Zabbix-agent (v1) which does not support the MQTT-plugin. This meant that i had to switch from the currently installed agent (v1) and to install the new agent (v2).
9 |
10 | I disabled the service of the current intstalled agent (v1):
11 | ```
12 | systemctl stop zabbix-agent
13 | systemctl disable zabbix-agent
14 | ```
15 |
16 | I installed and enabled the new agent (v2):
17 | ```
18 | apt install -y zabbix-agent2
19 | systemctl enable zabbix-agent2
20 | ```
21 |
22 | I renamed the example provisioned `mqtt.conf` file:
23 | ```
24 | mv /etc/zabbix/zabbix_agent2.d/plugins/mqtt.conf /etc/zabbix/zabbix_agent2.d/plugins/mqtt.conf.org
25 | ```
26 |
27 | I created a new `mqtt.conf` file:
28 | ```
29 | nano /etc/zabbix/zabbix_agent2.d/plugins/mqtt.conf
30 | ```
31 | And put this in the file:
32 | ```
33 | Plugins.MQTT.Sessions.hassaddon.Url=tcp://192.168.178.9:1883
34 | Plugins.MQTT.Sessions.hassaddon.Topic=$SYS/broker/clients/active
35 | Plugins.MQTT.Sessions.hassaddon.User=mosquitto
36 | Plugins.MQTT.Sessions.hassaddon.Password=Passw0rd!
37 | ```
38 | I'm not actually sure about the value of the topic.
39 |
40 | I restarted the agent (v2) service:
41 | ```
42 | systemctl restart zabbix-agent2
43 | systemctl status zabbix-agent2
44 | ```
45 |
46 | If everything went well, uninstall the old agent (v1):
47 | ```
48 | apt purge zabbix-agent
49 | apt autoremove
50 | ```
51 |
52 | ## Create the item "Broker clients active"
53 | These steps describe how to create an item which pulls data from your MQTT-broker into Zabbix via the agent:
54 | 1. In Zabbix i navigated to "Data collection" > "Hosts"
55 | 2. For the entry of my Zabbix server i chose for the link `Items`
56 | 3. In the top-right-corner i chose for the "Create item" button.
57 | 4. I enter the following values for the fields:
58 | * Name: `Broker clients active`
59 | * Type: `Zabbix agent (active)`
60 | * Key: `mqtt.get["hassaddon","$SYS/broker/clients/active"]`
61 | * Type of information: `Numeric (unsigned)`
62 | * Enabled: `checked`
63 | 5. I checked the checkbox in front of the newly item and clicked the buttons "Enable" and "Execute now" at the bottom of the screen.
64 |
65 | ## Create the trigger "Mosquitto: Active clients has changed"
66 | These steps describe how to create a trigger which will raise a problem if the item-value changes:
67 | 1. In Zabbix i navigated to "Data collection" > "Hosts"
68 | 2. For the entry of my Zabbix server i chose for the link `Triggers`
69 | 3. In the top-right-corner i chose for the "Create trigger" button.
70 | 4. I enter the following values for the fields:
71 | * Name: `Mosquitto: Active clients has changed`
72 | * Event name: `Mosquitto: Active clients has changed`
73 | * Operational data: `From {ITEM.LASTVALUE1} to {ITEM.LASTVALUE2}`
74 | * Severity: `Warning`
75 | * Expression: `last(/Zabbix server/mqtt.get["hassaddon","$SYS/broker/clients/active"],#1)<>last(/Zabbix server/mqtt.get["hassaddon","$SYS/broker/clients/active"],#2)`
76 | * OK event generation: `None`
77 | * Allow manual close: `checked`
78 | * Enabled: `checked`
79 |
80 |
81 |
82 | ## Other items
83 | I also create items for the following MQTT topics..
84 |
85 | ### Item: EbusD ebus running
86 | * Name: `EbusD ebus running`
87 | * Type: `Zabbix agent (active)`
88 | * Key: `mqtt.get["hassaddon","ebusd/global/running"]`
89 | * Type of information: `Text`
90 | * Enabled: `checked`
91 |
92 | ### Item: EBusD Ebus signal
93 | * Name: `EbusD ebus running`
94 | * Type: `Zabbix agent (active)`
95 | * Key: `mqtt.get["hassaddon","ebusd/global/signal"]`
96 | * Type of information: `Text`
97 | * Enabled: `checked`
98 |
99 | ### Item: EbusD update check
100 | * Name: `EbusD update check`
101 | * Type: `Zabbix agent (active)`
102 | * Key: `mqtt.get["hassaddon","ebusd/global/updatecheck"]`
103 | * Type of information: `Text`
104 | * Enabled: `checked`
105 |
106 | ### Item: Frigate available
107 | * Name: `Frigate available`
108 | * Type: `Zabbix agent (active)`
109 | * Key: `mqtt.get["hassaddon","frigate/available"]`
110 | * Type of information: `Text`
111 | * Enabled: `checked`
112 |
113 | ## Other triggers
114 |
115 | ### Trigger: Frigate available
116 | * Name: `Frigate available`
117 | * Event name: `Frigate available: not online`
118 | * Severity: `High`
119 | * Expression: `last(/Zabbix server/mqtt.get["hassaddon","frigate/available"])<>"online"`
120 | * OK event generation: `Expression`
121 | * Allow manual close: `UN-checked`
122 | * Description: `Frigate is not available`
123 | * Enabled: `checked`
124 |
125 |
--------------------------------------------------------------------------------
/zabbix-debian-updating.md:
--------------------------------------------------------------------------------
1 | # Check for Debian updates on machine
2 |
3 | ## Configure on Debian machine
4 |
5 | Open a terminal on the Debian machines you want to check for updates on.
6 |
7 | Install the required packages:
8 | ```
9 | apt-get install unattended-upgrades apt-listchanges
10 | ```
11 |
12 | Now create there a configuration file:
13 | ```
14 | nano /etc/zabbix/zabbix_agent2.d/90-debian-updates.conf
15 | ```
16 | Give that file the following content:
17 | ```
18 | UserParameter=debian_updates.package,apt-get upgrade -s | grep -c ^Inst
19 | UserParameter=debian_updates.security,apt-get upgrade -s | grep ^Inst | grep -c security
20 | ```
21 | Restart the service:
22 | ```
23 | systemctl restart zabbix-agent2
24 | ```
25 |
26 | ## Import template in Zabbix
27 | Create a file on your desktop with the follow contents:
28 | ```
29 |
30 |
31 | 6.0
32 | 2023-02-20T08:27:01Z
33 |
34 |
35 | 846977d1dfed4968bc5f8bdb363285bc
36 | Templates/Operating systems
37 |
38 |
39 |
40 |
41 | 98df8075f43e4f8da8c96c04df1e400f
42 | debian_updates
43 | Debian Updates
44 | Configured to check if unattended-upgrade keeps working correctly.
45 |
46 | **Requirements**
47 | 1. Activate unattended upgrades (preferable with security only) and reboot at e.g. 02:30AM
48 | 2. Extend your Zabbix Agent 2 configuration (e.g. /etc/zabbix/zabbix_agent2.d/90-updatenotifier.conf):
49 | UserParameter=debian_updates.package,apt-get upgrade -s | grep -c ^Inst
50 | UserParameter=debian_updates.security,apt-get upgrade -s | grep ^Inst | grep -c security
51 | 3. packages is used for all updates and will alert after 160days
52 | 4. security updates are checked and will alert after 14days
53 |
54 |
55 | Templates/Operating systems
56 |
57 |
58 |
59 | -
60 | f406fdf857d24e8aaf14e4899efba664
61 | Debian Updates - Packages
62 | debian_updates.package
63 | 4h
64 | 180d
65 | Retrieves the number of currently needed updates (all).
66 |
67 |
68 | Application
69 | Debian Updates
70 |
71 |
72 |
73 |
74 | 205b3ab218734affb4a0217cd1d555db
75 | last(/debian_updates/debian_updates.package,#1:now-160d)>=0
76 | Debian - Package Update available
77 | INFO
78 | Your Debian apt system reports pending updates (all).
79 | YES
80 |
81 |
82 |
83 | -
84 | 80665a2458eb478688f05660846c89f5
85 | Debian Updates - Security
86 | debian_updates.security
87 | 4h
88 | Retrieves the number of currently needed apt security updates.
89 |
90 |
91 | Application
92 | Debian Updates
93 |
94 |
95 |
96 |
97 | 45e1cee36d9244ab94004697c068d9d6
98 | last(/debian_updates/debian_updates.security,#1:now-14d)>=0
99 | Debian - Security update available
100 | AVERAGE
101 | Your Debian apt system reports pending security updates.
102 | YES
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 | ```
111 |
112 | Open web WebUI of your Zabbix instance and navigate to "Data collection" > "Templates".
113 | Click the "Import" button at the top-right. Select the file you created on your desktop.
114 | Now assign the template to the hosts which you want to check for available updates.
115 |
116 | # Script "Apt full-upgrade"
117 | * Name: `Apt full-upgrade`
118 | * Scope: `Manual host action`
119 | * Type: `Script`
120 | * Execute on: `Zabbix agent`
121 | * Commands: `apt update && apt full-upgrade`
122 | * Host group: `Selected` `Linux servers`
123 | * User group: `Zabbix administrators`
124 | * Required host permissions: `Write`
125 | * Enable confirmation: `checked`
126 | * Confirmation text: `Are you sure you want to do a full-upgrade?`
127 |
128 | # Allow running commands on Linux server
129 | Allow running commands on a machine:
130 | 1. Edit configuration file: `nano /etc/zabbix/zabbix_agent2.conf`
131 | 2. Add at the bottom of the file: `AllowKey=system.run[*]`
132 |
133 | # Run zabbix-agent2 as root
134 | Open SSH terminal on a machine you want to run commands on:
135 | ```
136 | ssh root@192.168.178.xxx
137 | ```
138 | We are gonna edit the configuration of the zabbix-agent2 service:
139 | ```
140 | systemctl edit zabbix-agent2
141 | ```
142 | Add at the specified line:
143 | ```
144 | [Service]
145 | User=root
146 | Group=root
147 | ```
148 |
149 | Restart service:
150 | ```
151 | systemctl daemon-reload
152 | systemctl restart zabbix-agent2
153 | ```
154 |
--------------------------------------------------------------------------------
/proxmox-lxc-nixos-desktop.md:
--------------------------------------------------------------------------------
1 | # NixOS KDE/Plasma desktop in a LXC-container on Proxmox
2 | My preference is to re-use as much as possible of my tech-stuff. More tech-stuff means more effort to keep things working.
3 | This preference resulted in me running a small mini pc for my smart-home, but also using that pc for desktop usage.
4 | Currently i'm running a [Minisforum](https://www.minisforum.com/) um4800xt mini-pc.
5 | This mini-pc is running Proxmox as it's host-os. In VMs/LXCs i'm running: Frigate, Home assistant, OPNsense, Immich and more...
6 |
7 | Instead of having a seperate machine to run as a desktop-computer, i'm running full Linux Desktop environments also on this mini-pc. The desktops having full GPU access and have HDMI output for video and audio.
8 | It's kind-of mind-boggling what kind of magic is behind enabling this ability.
9 |
10 | For a long while i've creating my desktop environment based on Debian, but recently felt comfortable to try it using NixOS. I'm happy to share my knowledge/experience how to achieve this.
11 |
12 | ## How?
13 | It all boils down to running a LXC-container with these properties:
14 | * Devices should be available for the Proxmox-host (thus device-drivers should be installed)
15 | * An Privileged LXC-container with extra low-level privileges
16 | * Passing through the device-files of the host to the LXC-container.
17 |
18 | ## Know issues
19 | * Sometimes the screen blacks-out for a while when i move my mouse. Currently i don't why this happens. I've noticed that this happens when i move my mouse on the login-screen (SDDM-greeter), but also when i move my mouse when making a snapshot with Spectacle.
20 | * In the log (`journalctl -ef`) quite some errors are logged because of some services not being available.
21 |
22 | ## Privileges
23 | For running a full desktop, the following configuration is needed:
24 | ```
25 | lxc.apparmor.profile: unconfined
26 | lxc.cap.drop:
27 | lxc.cap.drop: sys_time sys_module sys_rawio
28 | lxc.cgroup2.devices.allow: a
29 | lxc.mount.auto: cgroup:rw
30 | lxc.mount.auto: sys:rw
31 | ```
32 |
33 | ## Device-files
34 |
35 | ### Display passthrough
36 | It all starts with passing through the device-files of the display to the LXC-container. These device-files are in [/dev/dri/](https://en.wikipedia.org/wiki/Direct_Rendering_Infrastructure) of your Proxmox-host.
37 | To "see" these device-files, you can connect with the Console/Shell of your Proxmox-host and run: `ls /dev/dri -lai`, which should display something like this:
38 | ```
39 | 949 drwxr-xr-x 3 root root 100 Jun 1 00:14 .
40 | 1 drwxr-xr-x 19 root root 4740 Jun 11 08:57 ..
41 | 961 drw-rw---- 2 root root 80 Jun 11 08:57 by-path
42 | 951 crw-rw----+ 1 root video 226, 1 Jun 11 08:57 card1
43 | 950 crw-rw-rw-+ 1 root 303 226, 128 Jun 11 08:57 renderD128
44 | ```
45 | The device-files "card1" and "renderD128" are related and for the single display-device my mini-pc has. If you have more display-devices, you should see more "card*" and "renderD*" entries.
46 | The name "card1" is somewhat weird, previously i had the name "card0" here. I don't know why that changed on my machine.
47 | It's important to take notice of the major device-number" `226`. As i only have one device, i've chosen to passthrough the whole `/dev/dri/`-folder.
48 | The passthrough is done using this LXC-configuration snippet:
49 | ```
50 | lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir
51 | lxc.cgroup2.devices.allow: c 226:* rwm
52 | ```
53 | When you got your LXC-container up and running, doing a `ls /dev/dri -lai` in your LXC container should display something like this:
54 | ```
55 | 949 drwxr-xr-x 3 root root 100 1 jun 00:14 .
56 | 1 drwxr-xr-x 13 root root 800 11 jun 08:57 ..
57 | 961 drw-rw---- 2 root root 80 11 jun 08:57 by-path
58 | 951 crw-rw----+ 1 root 44 226, 1 11 jun 08:57 card1
59 | 950 crw-rw-rw-+ 1 root render 226, 128 11 jun 08:57 renderD128
60 | ```
61 | As you can see the output is almost the same as the output we got on the Proxmox-host itself.
62 | The only difference is that in the LXC-container the groupid "44" is displayed instead of the groupname "video", but this is not important or an issue.
63 |
64 | ## Sound passthrough
65 | The passthrough of the sound-devices is the same procedure as the "Display passthrough".
66 | On the Console/Shell of your Proxmox-host run: `ls /dev/dri -lai`, which should display something like this:
67 | ```
68 | 580 drwxr-xr-x 3 root root 300 Jun 1 00:14 .
69 | 1 drwxr-xr-x 19 root root 4740 Jun 11 08:57 ..
70 | 921 drwxr-xr-x 2 root root 80 Jun 11 08:57 by-path
71 | 919 crw-rw----+ 1 root audio 116, 7 Jun 11 08:57 controlC0
72 | 930 crw-rw----+ 1 root audio 116, 11 Jun 11 08:57 controlC1
73 | 909 crw-rw----+ 1 root audio 116, 6 Jun 11 08:57 hwC0D0
74 | 927 crw-rw----+ 1 root audio 116, 10 Jun 11 08:57 hwC1D0
75 | 905 crw-rw----+ 1 root audio 116, 2 Jun 11 08:57 pcmC0D3p
76 | 906 crw-rw----+ 1 root audio 116, 3 Jun 11 08:57 pcmC0D7p
77 | 907 crw-rw----+ 1 root audio 116, 4 Jun 11 08:57 pcmC0D8p
78 | 908 crw-rw----+ 1 root audio 116, 5 Jun 11 08:57 pcmC0D9p
79 | 926 crw-rw----+ 1 root audio 116, 9 Jun 11 08:57 pcmC1D0c
80 | 925 crw-rw----+ 1 root audio 116, 8 Jun 11 08:57 pcmC1D0p
81 | 582 crw-rw----+ 1 root audio 116, 1 Jun 11 08:57 seq
82 | 581 crw-rw----+ 1 root audio 116, 33 Jun 11 08:57 timer
83 | ```
84 | The passthrough is done using this LXC-configuration snippet:
85 | ```
86 | lxc.mount.entry: /dev/snd dev/snd none bind,optional,create=dir
87 | lxc.cgroup.devices.allow: c 116:* rwm
88 | ```
89 |
90 |
91 |
92 | Passthrough input devices (keyboard, mouse):
93 | ```
94 | lxc.mount.entry: /dev/input dev/input none bind,optional,create=dir
95 | lxc.cgroup2.devices.allow: c 13:* rwm
96 | ```
97 |
98 | Passthrough TTY:
99 | ```
100 | lxc.tty.max: 6
101 |
102 | lxc.cgroup2.devices.allow: c 4:* rwm
103 |
104 | lxc.mount.entry: /dev/tty0 dev/tty0 none bind,create=file 0 0
105 |
106 | lxc.mount.entry: /dev/tty7 dev/tty7 none bind,optional,create=file
107 |
108 | lxc.mount.entry: /dev/tty8 dev/tty8 none bind,create=file 0 0
109 | ```
110 |
111 | Passthough framebuffer:
112 | ```
113 | lxc.mount.entry: /dev/fb0 dev/fb0 none bind,optional,create=file
114 | lxc.cgroup2.devices.allow: c 29:0 rwm
115 | ```
116 |
117 | Passthrough fuse:
118 | ```
119 | lxc.mount.entry: /dev/fuse dev/fuse none bind,create=file,optional
120 | lxc.cgroup2.devices.allow: c 10:229 rwm
121 | ```
122 |
--------------------------------------------------------------------------------
/ryzenadj-on-proxmox.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 | I recently bought a [MinisForum UM450XT](https://store.minisforum.de/products/minisforum-venus-series-um560) to be used as my homeserver. The version i bought has got a Ryzen 7 4800H as the cpu.
3 | This CPU is very powerfull but will use up-to 45watt of power. As this machine is 24/7/365 running, making it run as efficiently as possible makes sense. When nobody is at home or during the night the system can be throttled without anybody noticing. After i installed everything i measured around 19watt when running idle (with a few VMs and LXCs). Not too bad, but i wanted to see if i could reduce it anyway.
4 |
5 | # CPU Scaling Governor
6 | I started out with using the [Proxmox VE CPU Scaling Governor script from TTeck](https://tteck.github.io/Proxmox/) to select the Powersave-profile. This did work, but kept the system running idle at 15watt.
7 |
8 | # BIOS setting
9 | In the BIOS i noticed an option with which the CPU TDP can be selected. The system came configured with a TDP of 45watt. I selected a TDP of 15watt which resulted in a lowering the idle usage to around 8watts. Selecting this TDP of course seriously capped the power/speed of the CPU.
10 |
11 | # Powertop
12 | I did try to run `powertop` a few times, but don´t seem to understand how to actually use it. I'll look into it at a later time.
13 |
14 | # RyzenAdj
15 | I came across [RyzenAdj](https://github.com/FlyGoat/RyzenAdj) which allowed for doing the same as the BIOS setting, but then on-the-fly.
16 |
17 | I had to compile the application on my Proxmox host. The instructions were very clear. My preference would be not to install any additional packages on my Proxmox host. Thus i created a script to allow me to For which i used this script:
18 | ```
19 | apt install build-essential cmake libpci-dev git
20 | git clone https://github.com/FlyGoat/RyzenAdj.git
21 | cd RyzenAdj
22 | git fetch --prune
23 | git pull
24 | rm -r win32
25 | rm -rf build
26 | mkdir build && cd build
27 | cmake -DCMAKE_BUILD_TYPE=Release ..
28 | make
29 | if [ -d ~/.local/bin ]; then ln -s $PWD/ryzenadj ~/.local/bin/ryzenadj && echo "symlinked to ~/.local/bin/ryzenadj"; fi
30 | if [ -d ~/.bin ]; then ln -s $PWD/ryzenadj ~/.bin/ryzenadj && echo "symlinked to ~/.bin/ryzenadj"; fi
31 | if [ -d /usr/local/bin ]; then ln -s $PWD/ryzenadj /usr/local/bin/ryzenadj && echo "symlinked to /usr/local/bin/ryzenadj"; fi
32 | ```
33 |
34 | Running this command would make the system run at a very low power usage CPU TDP of 1watt:
35 | ```
36 | ./ryzenadj --stapm-limit=1000 --fast-limit=1000 --slow-limit=1000 --tctl-temp=90 --info --power-saving
37 | ```
38 |
39 | Running this command would make the system run at higher power usage with a CPU TDP of 45watt:
40 | ```
41 | ./ryzenadj --stapm-limit=45000 --fast-limit=45000 --slow-limit=45000 --tctl-temp=90 --info --max-performance
42 | ```
43 |
44 |
45 | # Benchmarking
46 | For comparing the various scenario's i used the built-in benchmark functionality of 7zip. Which i installed with:
47 | ```
48 | apt install -y 7zip
49 | ```
50 |
51 | To run a benchmark i used the following command on the Proxmox host via the Shell:
52 | ```
53 | 7zz b
54 | ```
55 |
56 | The first result i got was:
57 | ```
58 | root@pve:~# 7zz b
59 |
60 | 7-Zip (z) 22.01 (x64) : Copyright (c) 1999-2022 Igor Pavlov : 2022-07-15
61 | 64-bit locale=en_US.UTF-8 Threads:16
62 |
63 | Compiler: 12.2.0 GCC 12.2.0
64 | Linux : 6.5.11-4-pve : #1 SMP PREEMPT_DYNAMIC PMX 6.5.11-4 (2023-11-20T10:19Z) : x86_64
65 | PageSize:4KB THP:madvise hwcap:2 hwcap2:2
66 | AMD Ryzen 7 4800H with Radeon Graphics (860F01)
67 |
68 | 1T CPU Freq (MHz): 386 388 391 392 391 389 391
69 | 8T CPU Freq (MHz): 788% 383 787% 383
70 |
71 | RAM size: 15415 MB, # CPU hardware threads: 16
72 | RAM usage: 3559 MB, # Benchmark threads: 16
73 |
74 | Compressing | Decompressing
75 | Dict Speed Usage R/U Rating | Speed Usage R/U Rating
76 | KiB/s % MIPS MIPS | KiB/s % MIPS MIPS
77 |
78 | 22: 6310 1103 557 6139 | 54633 1272 366 4659
79 | 23: 5922 1104 546 6035 | 51009 1203 367 4413
80 | 24: 5686 1085 563 6114 | 51079 1220 367 4482
81 | 25: 5496 1077 582 6275 | 49455 1202 366 4400
82 | ---------------------------------- | ------------------------------
83 | Avr: 5854 1092 562 6141 | 51544 1224 367 4488
84 | Tot: 1158 464 5315
85 | ````
86 |
87 | ```
88 | root@pve:~# ryzenadj/RyzenAdj/build/ryzenadj --info
89 | CPU Family: Renoir
90 | SMU BIOS Interface Version: 18
91 | Version: v0.14.0
92 | PM Table Version: 370005
93 | | Name | Value | Parameter |
94 | |---------------------|-----------|--------------------|
95 | | STAPM LIMIT | 1.000 | stapm-limit |
96 | | STAPM VALUE | 4.230 | |
97 | | PPT LIMIT FAST | 1.000 | fast-limit |
98 | | PPT VALUE FAST | 4.239 | |
99 | | PPT LIMIT SLOW | 1.000 | slow-limit |
100 | | PPT VALUE SLOW | 3.923 | |
101 | | StapmTimeConst | 275.000 | stapm-time |
102 | | SlowPPTTimeConst | 5.000 | slow-time |
103 | | PPT LIMIT APU | 54.000 | apu-slow-limit |
104 | | PPT VALUE APU | 3.923 | |
105 | | TDC LIMIT VDD | 58.000 | vrm-current |
106 | | TDC VALUE VDD | 0.780 | |
107 | | TDC LIMIT SOC | 15.000 | vrmsoc-current |
108 | | TDC VALUE SOC | 1.292 | |
109 | | EDC LIMIT VDD | 96.000 | vrmmax-current |
110 | | EDC VALUE VDD | 7.501 | |
111 | | EDC LIMIT SOC | 20.000 | vrmsocmax-current |
112 | | EDC VALUE SOC | 0.000 | |
113 | | THM LIMIT CORE | 90.000 | tctl-temp |
114 | | THM VALUE CORE | 29.657 | |
115 | | STT LIMIT APU | 0.000 | apu-skin-temp |
116 | | STT VALUE APU | 0.000 | |
117 | | STT LIMIT dGPU | 0.000 | dgpu-skin-temp |
118 | | STT VALUE dGPU | 0.000 | |
119 | | CCLK Boost SETPOINT | 95.000 | power-saving / |
120 | | CCLK BUSY VALUE | 99.615 | max-performance |
121 | ```
122 |
123 | Retrieving the Scaling Governor with:
124 | ```
125 | cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
126 | ```
127 |
128 | # Benchmark results
129 | | Scaling governor | Idle watt | Benchmarking | stapm-limit | fast-limit | slow-limit | threads | 8T MHZ | AVG Compressing MIPS | AVG Decompressing MIPS |
130 | |------------------|-----------|--------------|--------------|-------------|------------|---------|--------|----------------------|------------------------|
131 | | ondemand | 9.3w | 10.5w | 45.000 | 45.000 | 100 | 16 | 379 | 6.056 | 4.401 |
132 | | ondemand | 8.7w | 11.0w | 1.000 | 1.000 | 1.000 | 16 | 380 | 6.001 | 4.380 |
133 | | ondemand | 15.4w | 30.4w | 45.000 | 45.000 | 4.000 | 16 | 378 | 42.954 | 39.411 |
134 | | ondemand | 15.6w | 30.4w | 45.000 | 45.000 | 15.000 | 16 | 3.793 | 42.954 | 39.411 |
135 | | ondemand | 11.6w | 71.1w | 45.000 | 45.000 | 45.000 | 16 | 3.017 | 47.122 | 53.957 |
136 | | powersave | 11.6w | 18.1w | 45.000 | 45.000 | 45.000 | 16 | 1.381 | 23.744 | 18.329 |
137 | | performance | 13.1w | 73.4w | 45.000 | 45.000 | 45.000 | 16 | 4.207 | 49.404 | 55.004 |
138 |
139 | With these results i'm not sure what the best settings are.
140 | A "slow-limit" below 4000 doesn't have any impact.
141 | I´m unable to notice any difference with the "stapm-limit" and "fast-limit" parameters.
142 | In the table of "Supported Models" my "Renoir" CPU-model is stated that "stapm-limit" does not do anything.
143 |
--------------------------------------------------------------------------------
/homeassistant-ebusd-sensor-names.md:
--------------------------------------------------------------------------------
1 | When using EBusD via MQTT, i got a lot of cryptic-named entities in Home Assistant.
2 | In the following table i provided more descriptive entity names for the Diagnose-fields.
3 |
4 |
5 | | D-code | Default sensor Entity id | Given entity name | Icon | Remark |
6 | |--------|------------------------------|------------------|----------------|-------|
7 | |D.000| ebusd_bai_partloadhckw_power | CV-deellast (D.000) | | |
8 | |D.001| ebusd_bai_wppostruntime_minutes0 | Nalooptijd interne pomp voor CV-bedrijf (D.001) | | |
9 | |D.002| ebusd_bai_blocktimehcmax_minutes0 | Maximum branderwachttijd verwarming (D.002) | | |
10 | |D.003| ebusd_bai_hwctemp_temp | Warmwater temperatuur gemeten (D.003) | | |
11 | |D.004| ebusd_bai_storagetemp_temp | Meetwaarde van de warmwatersensor (D.004) | | |
12 | |D.005| ebusd_bai_flowtempdesired_temp | Gewenste aanvoertemperatuur (D.005) | | |
13 | |D.006| ebusd_bai_hwctempdesired_temp | Gewenste waarde warmwatertemperatuur (D.006) | | |
14 | |D.007| ebusd_bai_storagetempdesired_temp | Gewenste waarde warmestarttemperatuur (D.007) | | |
15 | |D.008| # niets | | |
16 | |D.009| ebusd_bai_extflowtempdesiredmin_temp | Gewenste waarde van externe eBUS thermostaat (D.009) | | |
17 | |D.010| ebusd_bai_wp_onoff | Status interne pomp (D.010) | | |
18 | |D.011| ebusd_bai_extwp_onoff | Status externe CV-pomp (D.011) | mdi:pump | |
19 | |D.012| ebusd_bai_storageloadpump_percent0 | Status boilerlaadpomp (D.012) | | |
20 | |D.013| ebusd_bai_cirpump_onoff | Status warmwater - circulatiepomp (D.013) | | |
21 | |D.013| ebusd_bai_statuscirpump | Status warmwater - circulatiepomp (D.013) | | |
22 | |D.014| ebusd_bai_pumppowerdesired | Pomp kracht ingesteld (D.014) | | |
23 | |D.015| ebusd_bai_pumppower | Pomp kracht werkelijke waarde (D.015) | | |
24 | |D.016| DCRoomthermostat | Kamerthermostaat 24V DC (D.016) | | |
25 | |D.017| ebusd_bai_returnregulation_onoff | Retour temperatuurregeling verwarming (D.017) | | |
26 | |D.018| ebusd_bai_hcpumpmode | Instelling van de pompmodus (D.018) | mdi:pump | |
27 | |D.019| ebusd_bai_secondpumpmode | Modus van de 2-traps pomp (D.019) | | |
28 | |D.020| ebusd_bai_hwctempmax_temp | Max. instelwaarde voor gewenste boilerwaarde (D.020) | | |
29 | |D.021|
30 | |D.022| ebusd_bai_hwcdemand_yesno | Vraag warm water (D.022) | mdi:hand-water | |
31 | |D.023| ebusd_bai_heatingswitch_onoff | Verwarming geactiveerd (D.023) | | |
32 | |D.024|
33 | |D.025| ebusd_bai_storagereleaseclock_yesno | Warmwaterbereiding vrijgegeven door eBus-thermostaat (D.025) | | |
34 | |D.026| | Aansturing hulprelais | | |
35 | |D.027| ebusd_bai_accessoriesone | Omschakeling relais 1 (D.027) | | Decode error |
36 | |D.028| ebusd_bai_accessoriestwo | Omschakeling relais 2 (D.028) | | Decode error |
37 | |D.029|
38 | |D.030|
39 | |D.031|
40 | |D.032|
41 | |D.033| ebusd_bai_targetfanspeed | Gewenste waarde ventilatortoerental (D.033) | mdi:fan | |
42 | |D.034| ebusd_bai_fanspeed | Actuele waarde ventilatortoerental (D.034) | | |
43 | |D.035| ebusd_bai_positionvalveset | Stand van de driewegklep (D.035) | mdi:valve-open | |
44 | |D.036| ebusd_bai_hwcwaterflow_uin100 | Warmwaterdebiet (D.036) | | |
45 | |D.037|
46 | |D.038|
47 | |D.039| | Zonne-inlooptemperatuur (D.039) | | |
48 | |D.040| ebusd_bai_flowtemp_temp | Aanvoertemperatuur (D.040) | | |
49 | |D.041| ebusd_bai_returntemp_temp | Retourtemperatuur (D.041) | | |
50 | |D.042|
51 | |D.043|
52 | |D.044| ebusd_bai_ionisationvoltagelevel | Gedigitaliseerde ionisatiewaarde (D.044) | | |
53 | |D.045|
54 | |D.046| | Soort pomp 0 (D.046) | | |
55 | |D.047| ebusd_bai_outdoorstempsensor_temp | Buitentemperatuur (D.047) | | |
56 | |D.048|
57 | |D.049|
58 | |D.050| ebusd_bai_fanspeedoffsetmin | Offset voor minimaal toerental (D.050) | | |
59 | |D.051| ebusd_bai_fanspeedoffsetmax | Offset voor maximaal toerental (D.051) | | |
60 | |D.052|
61 | |D.053|
62 | |D.054|
63 | |D.055|
64 | |D.056|
65 | |D.057|
66 | |D.058| ebusd_bai_solpostheat | Activering naverwarming via zonneenergie voor combiproduct (D.058) | | |
67 | |D.059|
68 | |D.060| ebusd_bai_deactivationstemplimiter | Aantal uitschakelingen door temperatuurbegrenzer (D.060) | | |
69 | |D.061| ebusd_bai_deactivationsifc | Aantal storingen branderautomaat (D.061) | | |
70 | |D.062|
71 | |D.063|
72 | |D.064| ebusd_bai_averageignitiontime | Gemiddelde ontstekingstijd (D.064) | mdi:fire | |
73 | |D.065| ebusd_bai_maxignitiontime | Maximale ontstekingstijd (D.065) | | |
74 | |D.066|
75 | |D.067| ebusd_bai_remainingboilerblocktime_minutes0 | Resterende branderwachttijd (D.067) | | |
76 | |D.068| ebusd_bai_counterstartattempts1_temp0 | Mislukte ontstekingen bij 1e poging (D.068) | | |
77 | |D.069| ebusd_bai_counterstartattempts2_temp0 | Mislukte ontstekingen bij 2e poging (D.069) | | |
78 | |D.070| ebusd_bai_valvemode | Instellen stand driewegklep (D.070) | | |
79 | |D.071| ebusd_bai_flowsethcmax_temp | Gewenste waarde max. aanvoertemperatuur verwarming (D.071) | | |
80 | |D.072| ebusd_bai_hwcpostruntime | Nalooptijd interne pomp na boilerlading (D.072) | | |
81 | |D.073| ebusd_bai_warmstartoffset_temp | Gewenste warme start offset (D.073) | | |
82 | |D.074| ebusd_bai_apclegioprotection | Legionellabeveiligingsfunctie actoSTOR (D.074) | | Geen actoSTOR aanwzg |
83 | |D.075| ebusd_bai_storageloadtimemax_minutes0 | Max. laadtijd voor warmwaterboiler zonder eigen regeling (D.075) | | |
84 | |D.076| | Toestelidentificatie (D.076) | | |
85 | |D.077| ebusd_bai_partloadhwckw_power | Begrenzing van het boilerlaadvermogen in kW (D.077) | | Decode error |
86 | | | ebusd_bai_modulationtempdesired | Modulatie temperatuur gevraagd | | ebusd_bai_partloadhwckw_power = % van partloadhcKW |
87 | |D.078| ebusd_bai_flowsethwcmax_temp | Begrenzing van de boilerlaadtemperatuur in °C (D.078) | | |
88 | |D.079|
89 | |D.080| ebusd_bai_hchours_hoursum2 | Bedrijfsuren verwarming (D.080) | | |
90 | |D.081| ebusd_bai_hwchours_hoursum2 | Bedrijfsuren warmwaterbereiding (D.081) | | |
91 | |D.082| ebusd_bai_hcstarts | Aantal branderstarts in CV-bedrijf (D.082) | | |
92 | |D.083| ebusd_bai_hwcstarts | Aantal branderstarts in warmwaterbedrijf (D.083) | | |
93 | |D.084| ebusd_bai_hourstillservice_hoursum2 | Onderhoudsindicatie: aantal uren tot de volgende onderhoudsbeurt (D.084) | | |
94 | |D.085|
95 | |D.086|
96 | |D.087|
97 | |D.088| ebusd_bai_specialadj | Inschakelvertraging voor warmwatertapherkenning via vleugelwiel (D.088) | | # werkt niet |
98 | |D.089|
99 | |D.090| ebusd_bai_ebusheatcontrol_yesno | Status digitale thermostaat (D.090) | | |
100 | |D.091| thermostaat_statusdcf_dcfstate | Status DCF bij aangesloten buitentemperatuurvoeler (D.091) | | |
101 | |D.092| ebusd_bai_apccomstatus | actoSTOR moduleherkenning (D.092) | | |
102 | |D.093| ebusd_bai_dsnoffset | Instelling toestelidentificatie (D.093) | | |
103 | |D.094| | Foutcode historie verwijderen (D.094) | | |
104 | |D.095| | Softwareversie PeBUS-componenten Printplaat (D.095) | | |
105 | |D.096| | Fabrieksinstelling Reset (D.096) | | |
106 | |D.097| ebusd_bai_password | Activering installateurniveau Code (D.097) | | werkt niet |
107 | |D.098| | Waarde van de codeerweerstanden (D.098) |
108 |
109 |
110 | | Other | Name | Icon |
111 | |---------------|-----|------|
112 | | sensor.ebusd_bai_flame | CV brander | mdi:fire |
113 | | sensor.ebusd_bai_gasvalveasicfeedback | CV gas-klep terugkoppeling | |
114 | | sensor.ebusd_bai_gasvalve3uc | CV gas-klep activeer 3 signaal | mdi:ray-start |
115 | | sensor.ebusd_bai_gasvalve | CV gas-klep actief | mdi:valve |
116 | | binary_sensor.ebusd_bai_fluegasvalve_onoff | CV rookgasklep actief | mdi:valve |
117 | | sensor.ebusd_bai_status01_pumpstate | CV pomp actief | mdi:pump |
118 | | sensor.ebusd_bai_templimiter | | |
119 | | sensor.ebusd_bai_statenumber | | |
120 | | sensor.ebusd_bai_status | | |
121 | | sensor.ebusd_bai_pumphours_hoursum2 | CV uren pomp actief | mdi:pump |
122 | | sensor.ebusd_bai_setmode_disablehc | CV verwarming uitgeschakeld | mdi:radiator-off |
123 | | sensor.ebusd_bai_status02_hwcmode | Warm-water circuit geactiveerd | mdi:hand-water |
124 | | sensor.ebusd_bai_blocktimehcmax_minutes0 | CV maximale wachttijd | mdi:timer-sand |
125 | | binary_sensor.ebusd_bai_externalfaultmessage_onoff | CV extern fout bericht | |
126 | | sensor.ebusd_bai_hwcwaterflowmax_uin100 | Warm-water circuit maximale doorstroming | |
127 | | sensor.ebusd_bai_remainingboilerblocktime_minutes0 | Resterende CV wachttijd | |
128 | | sensor.ebusd_bai_targetfanspeedoutput | CV gerealiseerde ventilator doel snelheid | mdi:fan |
129 | | sensor.ebusd_bai_waterpressure_press | Verwarming waterdruk | |
130 |
131 |
132 | 
133 |
--------------------------------------------------------------------------------
/frigate-docker-lxc.md:
--------------------------------------------------------------------------------
1 | With these notes it is possible to take the official Frigate (Docker) container and convert it into a fully working Proxmox LXC container. Thus running it without Docker as virtualization layer. The LXC container should not suffer from the issues which are known for having a ZFS filesystem and nested Docker.
2 |
3 | It's actually working :-S
4 | 
5 |
6 | # Initialization
7 | We will using the init-system which is part of the Frigate Docker container. This init-system (`s6-overlay`) manages the several parallel processes for Frigate. Normally in LXC-containers `systemd` is used, but for this container this is not neccesary.
8 | Be aware that the init-system will stop the LXC-container when an error occurs or the configuration is changed.
9 |
10 | # Process
11 |
12 | ## Creating the template
13 |
14 | Create raw LXC container from Docker container image. Run this on your Proxmox host:
15 | ```
16 | apt install skopeo umoci jq
17 | lxc-create frigate -t oci -- --url docker://ghcr.io/blakeblackshear/frigate:stable
18 | ```
19 | 
20 | You will now have a LXC container running which is not managed by Proxmox. The commando `lxc-ls` should now show a container named "frigate" next to the Proxmox managed containers.
21 | The filesystem of the running Frigate container is here: `/var/lib/lxc/frigate/rootfs`
22 |
23 | Change to the rootfs directory of the Frigate LXC container:
24 | ```
25 | cd /var/lib/lxc/frigate/rootfs/
26 | ```
27 | Create the Frigate media and config folders:
28 | ```
29 | mkdir -p media/frigate
30 | mkdir -p config
31 | ```
32 |
33 | Edit the init file with: `nano init`. We will be adding some statements to provide DHCP on eth0 in the container. Also we will create a ramdisk for the cache.Add the parts between `# Begin` and `# End` to the file:
34 | ```
35 | #!/bin/sh -e
36 |
37 | # Begin
38 | /sbin/ip link set dev eth0 up
39 | /sbin/ip link set dev lo up
40 | dhclient
41 |
42 | export S6_LOGGING_SCRIPT="T 1 n0 s10000000 T"
43 | export S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0
44 | #export CCACHE_DIR=/root/.ccache
45 | #export CCACHE_MAXSIZE=2G
46 |
47 | mkdir -p /tmp/cache
48 | chmod 777 /tmp/cache
49 | mount -t tmpfs -o size=1024m tmpcache /tmp/cache
50 |
51 | rm -rf /dev/shm
52 | mkdir -p /dev/shm/logs/frigate/
53 | chmod -R 777 /dev/shm/
54 | mount -t tmpfs -o size=1024m devshm /dev/shm
55 | # End
56 |
57 | # This is the first program launched at container start.
58 | # We don't know where our binaries are and we cannot guarantee
59 | # that the default PATH can access them.
60 | # So this script needs to be entirely self-contained until it has
61 | # at least /command, /usr/bin and /bin in its PATH.
62 | ...
63 | ```
64 |
65 | Also add this part between `# Begin` and `# End` to the init file:
66 | ```
67 | addpath /bin
68 | addpath /usr/bin
69 | addpath /command
70 |
71 | # Begin
72 | addpath /usr/lib/btbn-ffmpeg/bin
73 | addpath /usr/local/go2rtc/bin
74 | addpath /usr/local/nginx/sbin
75 | # End
76 |
77 | export PATH
78 | ...
79 | ```
80 | Save and close Nano with CTRL-O, , CTRL-X
81 |
82 | For running this LXC container within Proxmox some packages need to be installed in the container rootsfs.
83 | ```
84 | /usr/sbin/chroot /var/lib/lxc/frigate/rootfs/ apt update
85 | /usr/sbin/chroot /var/lib/lxc/frigate/rootfs/ apt install init isc-dhcp-client -y
86 | ```
87 | The package `init` might not be needed anymore.
88 |
89 | Lookup in which folder the Proxmox templates are situated by running `cat /etc/pve/storage.cfg`. On my system the output is:
90 | ```
91 | dir: local
92 | disable
93 | path /var/lib/vz
94 | content vztmpl,backup,iso
95 |
96 | btrfs: local-btrfs
97 | path /var/lib/pve/local-btrfs
98 | content rootdir,vztmpl,images,backup,iso
99 | ```
100 | In my system the storage named `local` is disabled and the one named `local-btrfs` is used. So i'll be using the path `/var/lib/pve/local-btrfs` in the next command. You might to use path `/var/lib/vz`. If i run `ls /var/lib/pve/local-btrfs` i should see previously downloaded CT templates.
101 |
102 | Create the template file by creating an archive from the rootfs filesystem. This command might take a few minutes:
103 | ```
104 | ctstorage="/var/lib/pve/local-btrfs"
105 | tar --exclude=dev --exclude=sys --exclude=proc -czf $ctstorage/template/cache/frigate_template.tar.gz ./
106 | ```
107 | After creating the Proxmox-LXC-template, you can remove the unmanaged LXC frigate container:
108 | ```
109 | cd /
110 | lxc-destroy frigate
111 | ```
112 |
113 | ## Creating the Frigate container in Proxmox
114 |
115 | We can create now create a Promox managed Frigate LXC container. This can be done by using the Proxmox Web UI, but also via the command-line:
116 | ```
117 | ctid="998"
118 | ctstorage="local-btrfs"
119 | storage="local-btrfs"
120 | pct create $ctid /var/lib/pve/$ctstorage/template/cache/frigate_template.tar.gz \
121 | -hostname frigate-test -memory 2048 --cores 2 \
122 | -net0 name=eth0,hwaddr=52:4A:5E:26:58:D8,bridge=vmbr0 \
123 | -storage $storage -password Passw0rd! \
124 | --unprivileged 0 --features nesting=1 --cmode console
125 | ```
126 | 
127 |
128 | For updating the Frigate container in the future, it's smart to keep data stored outside of the Frigate container. The following command is what i use:
129 | ```
130 | configpath="/root/frigate"
131 | mediapath="/zpool-storage/media/Frigate"
132 | ctid="998"
133 | mkdir -p $configpath
134 | mkdir -p $mediapath
135 | chmod -R 777 $mediapath
136 | chmod -R 777 $configpath
137 | pct set $ctid -mp0 $configpath,mp=/config/
138 | pct set $ctid -mp1 $mediapath,mp=/media/frigate
139 | ```
140 |
141 | In the media folder we bound to the container, we will download a sample video file:
142 | ```
143 | mediapath="/zpool-storage/media/Frigate"
144 | cd $mediapath
145 | wget -q https://github.com/intel-iot-devkit/sample-videos/raw/master/person-bicycle-car-detection.mp4
146 | ```
147 |
148 | Here we will be creating an initial configuration file in the folder i've just bound to the container:
149 | ```
150 | configpath="/root/frigate"
151 | cat >$configpath/config.yml <<'EOL'
152 | detectors:
153 | detector_name:
154 | type: cpu
155 |
156 | mqtt:
157 | enabled: False
158 |
159 | go2rtc:
160 | webrtc:
161 | candidates:
162 | - stun:8555
163 |
164 | cameras:
165 | dummy_camera:
166 | ffmpeg:
167 | inputs:
168 | - path: /media/frigate/person-bicycle-car-detection.mp4
169 | input_args: -re -stream_loop -1 -fflags +genpts
170 | roles:
171 | - detect
172 |
173 | motion:
174 | threshold: 30
175 | lightning_threshold: 0.8
176 | contour_area: 10
177 | frame_alpha: 0.01
178 | frame_height: 50
179 | improve_contrast: False
180 | mqtt_off_delay: 30
181 |
182 | record:
183 | enabled: False
184 |
185 | objects:
186 | track:
187 | - person
188 | - car
189 | - bicycle
190 | EOL
191 | ```
192 |
193 | Edit the lxc config file with:
194 | ```
195 | ctid="998"
196 | nano /etc/pve/lxc/$ctid.conf
197 | ```
198 |
199 | Add in this file:
200 | ```
201 | lxc.init.cmd: /init
202 | lxc.log.level: 3
203 | lxc.console.logfile: /var/log/frigate.log
204 | ```
205 |
206 |
207 | ## Starting the container
208 |
209 | Start Proxmox LXC container:
210 | ```
211 | ctid="998"
212 | pct start $ctid
213 | pct status $ctid
214 | ```
215 |
216 | In Proxmox you should the logging output of Frigate rolling by on the console of the container.
217 |
218 | You now probably need to get the IP-address of the container. You can do this:
219 | ```
220 | ctid="998"
221 | pct enter $ctid
222 | ip a
223 | ...
224 | exit
225 | ```
226 | The container should've received an IP-address via DHCP from your router.
227 |
228 | You should be able to access Frigate with the IP-address on port 5000, for example: `http://192.168.178.156:5000/`
229 |
230 | # Notes
231 | * On the proxmox host a log file is created at: `tail -f /var/log/frigate.log`
232 | * Log files in the container are created at: `cd /dev/shm/logs`
233 | * Frigate S6-overlay files are at: `/etc/s6-overlay/s6-rc.d`
234 |
235 | Resources:
236 | * https://www.buzzwrd.me/index.php/2021/03/10/creating-lxc-containers-from-docker-and-oci-images/
237 | * https://github.com/pimox/pimox7/issues/160
238 | * https://forum.proxmox.com/threads/permission-denied-failed-to-exec-sbin-init.118710/
239 | * https://forum.proxmox.com/threads/cant-start-lxc.108036/
240 | * https://forum.proxmox.com/threads/how-to-migrate-a-regular-lxc-container-to-a-proxmox-lxc-container.24138/
241 | * https://serverfault.com/questions/731400/how-to-migrate-a-regular-lxc-container-to-a-proxmox-lxc-container
242 | * https://gist.github.com/midoriiro/58b6d16d1578e030e7078917a5872290
243 | * https://github.com/just-containers/s6-overlay
244 | * https://unix.stackexchange.com/questions/119100/cannot-connect-to-any-localhost-connections
245 |
246 | # Hardware acceleration
247 | I'm able to get Hardware-acceleration on my AMD Ryzen 4800h system with the notes below. I have multiple LXC containers which share the Hardware-acceleration of my GPU. This is only possible with LXC containers, not with VMs.
248 | ```
249 | lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file
250 | lxc.cgroup2.devices.allow: c 226:128 rwm
251 | ```
252 | Add in the Frigate configuration file:
253 | ```
254 | environment_vars:
255 | LIBVA_DRIVER_NAME=radeonsi
256 |
257 | ffmpeg:
258 | hwaccel_args: preset-vaapi
259 | ```
260 | # Notes
261 | * After modifying the config via the web-ui. Saving will stop the LXC container. And should manually be started.
262 |
--------------------------------------------------------------------------------
/MR60BHA2.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | So i just received from Seeedstudio the [MR60BHA2](https://www.seeedstudio.com/MR60BHA2-60GHz-mmWave-Sensor-Breathing-and-Heartbeat-Module-p-5945.html) mmwave sensor for Breathing and Heartbeat detection.
4 | It comes with pre-flashed with an ESPHome based firmware.
5 |
6 | # Fork of original repository
7 | I created [my own fork](https://github.com/grumpymeow/MR60BHA2_ESPHome_external_components) of the [original repository](https://github.com/limengdu/MR60BHA2_ESPHome_external_components).
8 | This to resolve a few issues.
9 |
10 | ## Hard to upload firmware
11 | At often times it was quite hard to upload a new firmware to the device over-the-air. Quite often no connection could be made from ESPHome to the device. Partly this is caused by the poor wireless connection the device had.
12 | I had to resort to using ESPTool and flash over-the-wire. I eventually added a `yield()` to `loop` function to give ensure the CPU would give more time to other processes. This resolved all timeout issues.
13 | ```
14 | // main loop
15 | void MR60BHA2Component::loop() {
16 | uint8_t byte;
17 |
18 | // Is there data on the serial port
19 | while (this->available()) {
20 | this->read_byte(&byte);
21 | this->rx_message_.push_back(byte);
22 | if (!this->validate_message_()) {
23 | this->rx_message_.clear();
24 | }
25 | }
26 | yield(); <= added this
27 | }
28 | ```
29 |
30 | ## More frame types
31 | At this time 3 time of frame types with data can be processed by the code, but the device itself transmits two additional frame types. In code I added these event-types. Although i didn't bother to implement the decoding as i saw no interesting information.
32 | One of the frame-types transmitted the text `no targets!!!`.
33 | ```
34 | static const uint16_t UNKNOWN_TYPE_BUFFER = 0x0A13; <== Added this
35 | static const uint16_t UNKNOWN2_TYPE_BUFFER = 0x0100; <== Added this
36 | static const uint16_t BREATH_RATE_TYPE_BUFFER = 0x0A14;
37 | static const uint16_t HEART_RATE_TYPE_BUFFER = 0x0A15;
38 | static const uint16_t DISTANCE_TYPE_BUFFER = 0x0A16;
39 | ```
40 | and
41 | ```
42 | void MR60BHA2Component::process_frame_(uint16_t frame_id, uint16_t frame_type, const uint8_t *data, size_t length) {
43 | switch (frame_type) {
44 | case BREATH_RATE_TYPE_BUFFER:
45 | ...
46 | break;
47 | case HEART_RATE_TYPE_BUFFER:
48 | ...
49 | break;
50 | case DISTANCE_TYPE_BUFFER:
51 | ...
52 | break;
53 | case UNKNOWN_TYPE_BUFFER:
54 | break;
55 | case UNKNOWN2_TYPE_BUFFER:
56 | break;
57 | default:
58 | break;
59 | }
60 | }
61 | ```
62 |
63 | # No distance data
64 | In the current version of the repository there is an error in the decoding of distance.
65 | ```
66 | case DISTANCE_TYPE_BUFFER:
67 | if (data[0] != 0) { <== changed
68 | if (this->distance_sensor_ != nullptr && length >= 8) {
69 | uint32_t current_distance_int = encode_uint32(data[7], data[6], data[5], data[4]);
70 | float distance_float;
71 | memcpy(&distance_float, ¤t_distance_int, sizeof(float));
72 | this->distance_sensor_->publish_state(distance_float);
73 | }
74 | }
75 | ```
76 |
77 |
78 | # YAML-definition
79 |
80 | I currently am using this Yaml-definition. In this definition i added template-sensors for heartrate and breathingrate which expose the minimum, maximum and average values.
81 | For all the sensors i'd added the `timeout`-filter to make the sensor `unavailable` in Home Assistant when nothing is detected for a while.
82 | I also added the `clamp` filter to get rid of noise values.
83 | ```
84 | substitutions:
85 | name: "slaapsensor"
86 | friendly_name: "Slaapsensor"
87 | timeout: 120s
88 | hrf_name: "Hartslagfrequentie"
89 | brf_name: "Ademfrequentie"
90 |
91 | esphome:
92 | name: "${name}"
93 | friendly_name: "${friendly_name}"
94 | # project:
95 | # name: "seeedstudio.mr60bha2_kit"
96 | # version: "2.0"
97 | platformio_options:
98 | board_upload.maximum_size: 4194304
99 | min_version: "2024.3.2"
100 |
101 | esp32:
102 | board: esp32-c6-devkitc-1
103 | variant: esp32c6
104 | flash_size: 4MB
105 | framework:
106 | type: esp-idf
107 | sdkconfig_options:
108 | CONFIG_ESPTOOLPY_FLASHSIZE_4MB: y
109 |
110 | # Enable logging
111 | logger:
112 | hardware_uart: USB_SERIAL_JTAG
113 | #level: VERY_VERBOSE
114 | level: DEBUG
115 |
116 | api:
117 | reboot_timeout: 0s
118 |
119 | ota:
120 | - platform: esphome
121 |
122 | wifi:
123 | ssid: !secret wifi_ssid
124 | password: !secret wifi_password
125 | fast_connect: false
126 | enable_btm: true
127 | enable_rrm: true
128 | power_save_mode: none
129 | reboot_timeout: 120min
130 | ap:
131 | ssid: "Slaapsensor hotspot"
132 | password: !secret wifi_password
133 | ap_timeout: 5min
134 |
135 | light:
136 | - platform: esp32_rmt_led_strip
137 | id: led_ring
138 | name: "Led"
139 | pin: GPIO1
140 | num_leds: 1
141 | rmt_channel: 0
142 | rgb_order: GRB
143 | chipset: ws2812
144 |
145 | i2c:
146 | sda: GPIO22
147 | scl: GPIO23
148 | scan: true
149 | # frequency: 200kHz
150 | id: bus_a
151 |
152 | uart:
153 | id: uart_bus
154 | baud_rate: 115200
155 | rx_pin: 17
156 | tx_pin: 16
157 | parity: NONE
158 | stop_bits: 1
159 |
160 | seeed_mr60bha2:
161 | id: my_seeed_mr60bha2
162 |
163 | sensor:
164 | - platform: bh1750
165 | name: "Omgevingslicht"
166 | address: 0x23
167 | update_interval: 60s
168 | filters:
169 | - timeout: ${timeout}
170 | - platform: seeed_mr60bha2
171 | breath_rate:
172 | id: brf_raw
173 | name: "${brf_name} ruw"
174 | unit_of_measurement: bpm
175 | internal: false
176 | accuracy_decimals: 2
177 | filters:
178 | - clamp:
179 | min_value: 1
180 | max_value: 40
181 | ignore_out_of_range: true
182 | - timeout: ${timeout}
183 | on_value:
184 | then:
185 | - component.update: brf_avg
186 | - component.update: brf_min
187 | - component.update: brf_max
188 | heart_rate:
189 | id: hrf_raw
190 | name: "${hrf_name} ruw"
191 | unit_of_measurement: bpm
192 | internal: false
193 | accuracy_decimals: 2
194 | filters:
195 | - clamp:
196 | min_value: 40
197 | max_value: 130
198 | ignore_out_of_range: true
199 | - timeout: ${timeout}
200 | on_value:
201 | then:
202 | - component.update: hrf_avg
203 | - component.update: hrf_min
204 | - component.update: hrf_max
205 | distance:
206 | name: "Afstand"
207 | accuracy_decimals: 2
208 | filters:
209 | - exponential_moving_average:
210 | alpha: 0.1
211 | send_every: 1
212 | - timeout: ${timeout}
213 |
214 | # Hartslagfrequentie
215 | - platform: template
216 | id: hrf_avg
217 | name: "${hrf_name}"
218 | accuracy_decimals: 2
219 | unit_of_measurement: bpm
220 | lambda: return id(hrf_raw).state;
221 | filters:
222 | - exponential_moving_average:
223 | alpha: 0.1
224 | send_every: 1
225 | - timeout: ${timeout}
226 | - platform: template
227 | id: hrf_min
228 | name: "${hrf_name} min"
229 | accuracy_decimals: 2
230 | unit_of_measurement: bpm
231 | lambda: return id(hrf_raw).state;
232 | filters:
233 | - min:
234 | window_size: 5
235 | send_every: 1
236 | - timeout: ${timeout}
237 | - platform: template
238 | id: hrf_max
239 | name: "${hrf_name} max"
240 | accuracy_decimals: 2
241 | unit_of_measurement: bpm
242 | lambda: return id(hrf_raw).state;
243 | filters:
244 | - max:
245 | window_size: 5
246 | send_every: 1
247 | - timeout: ${timeout}
248 |
249 | # Ademfrequentie
250 | - platform: template
251 | id: brf_avg
252 | name: "${brf_name}"
253 | accuracy_decimals: 2
254 | unit_of_measurement: bpm
255 | lambda: return id(brf_raw).state;
256 | filters:
257 | - exponential_moving_average:
258 | alpha: 0.1
259 | send_every: 1
260 | - timeout: ${timeout}
261 | - platform: template
262 | id: brf_min
263 | name: "${brf_name} min"
264 | accuracy_decimals: 2
265 | unit_of_measurement: bpm
266 | lambda: return id(brf_raw).state;
267 | filters:
268 | - min:
269 | window_size: 5
270 | send_every: 1
271 | - timeout: ${timeout}
272 | - platform: template
273 | id: brf_max
274 | name: "${brf_name} max"
275 | accuracy_decimals: 2
276 | unit_of_measurement: bpm
277 | lambda: return id(brf_raw).state;
278 | filters:
279 | - max:
280 | window_size: 5
281 | send_every: 1
282 | - timeout: ${timeout}
283 |
284 |
285 | external_components:
286 | - source:
287 | type: git
288 | url: https://github.com/grumpymeow/MR60BHA2_ESPHome_external_components
289 | ref: main
290 | components: [ seeed_mr60bha2 ]
291 | refresh: 0s
292 | ```
293 |
294 | # Results
295 |
296 | ## 18-12-2024
297 |
298 | ### Distance detected object
299 | The result of the measured distance looks accurate. It detected some tossing and turning of me during my sleep.
300 | 
301 |
302 | ### Light sensor
303 | The result of the measured light looks accurate. At 6:45 a bedside lamp is turned on. From 8:40 and later it's daylight.
304 | 
305 |
306 |
307 | ### Breathing rate
308 | This is a graph of the raw sensor data. The variation is quite big and hopefully inaccuracy. This as otherwise i might have a severe case of slaap apnea.
309 | 
310 |
311 | I also do some filtering on the sensor data which results in this chart:
312 | 
313 |
314 | I also expose the min and max of the sensor data.
315 | 
316 |
317 |
318 | ### Heart rate
319 | This is the chart of the raw and filtered sensor data. The brownish-line is of the raw data. Blue is of the filtered data.
320 | 
321 |
322 | This is the chart of the min and max sensor data.
323 | 
324 |
325 | ### Conclusion
326 | My conclusion at this time is that i need to increase the average over a longer period. As the variation makes it impossible to visually see anything usefull.
327 |
328 | Current filter settings:
329 | ```
330 | - exponential_moving_average:
331 | alpha: 0.1
332 | send_every: 1 (default=15, i might have used a weird value here)
333 | send_first_at: 1 <=default
334 |
335 | - max/min:
336 | window_size: 5
337 | send_every: 1
338 | ```
339 |
340 | My new filter settings i'm gonna try:
341 | ```
342 | - quantile:
343 | window_size: 7 (default=7)
344 | send_every: 4
345 | send_first_at: 3
346 | quantile: .9
347 |
348 | - max/min:
349 | window_size: 20
350 | send_first_at: 1
351 | send_every: 1
352 | ```
353 | I also chose to increase the timeout from `timeout: 120s` to `timeout: 600s` to get rid of some small gaps in the data.
354 |
355 | There seem to be a [few patterns](https://ouraring.com/blog/sleeping-heart-rate/) which can be seen during sleeping.
356 | It would be fun to eventually see these patterns arise.
357 |
358 | Looking at the data i already suspect that there might not be enough of data to really get usefull insights.
359 | Maybe just like on the Oura-ring page, only three-point-patterns like hammock, slope, hill, etc. We will see.
360 |
361 | I noticed the device crashes on a regular basis which is recognizable by the short lighting of the led. This distorts the filters. So probably better to implement the filters in Home Assistant instead of on the device.
362 |
363 | ## 29-12-2024
364 | Doing the filtering in Home Assistant gives much better results.
365 |
366 | Initially i had configured a moving-average filter with a maximum of 50samples and/or 30minutes. This still gave too much jittery to visually interpret.
367 | The following screenshot is my breathing-frequency for the last 6 nights. The last night i had changed the moving-average filter to 250samples and/or 2hours.
368 | 
369 | And this is the screenshot of my heart-rate for the last 6 nights.
370 | 
371 |
372 | This is the chart of my breathing-rate of the last night:
373 | 
374 | And the same chart with the raw sensor values in blue overlayed:
375 | 
376 |
377 | ### Conclusion
378 | I think better results might be retrieved by reducing the number of ourliers which should allow for reducing the strength moving average filter.
379 |
--------------------------------------------------------------------------------
/provision-lxc-desktop-from-homeassistant.md:
--------------------------------------------------------------------------------
1 | In conformance to `when you have a hammer, everything is a nail` i have a command in Home Assistant which provisions a fresh desktop environment.
2 | Triggering the [`create_desktop` command](https://github.com/koying/ha-remote-command-line) will create:
3 | * An unprivileged/unconfined LXC container
4 | * Debian v12 LXC is upgraded to v13
5 | * Mounted GPU-devices, USB, sound and low-level devices
6 | * Plasma-desktop with Chromium and other apps i regularly use
7 |
8 | I have this running on my Minisforum UM480xt machine with directly connected monitor. When i start the container, the Proxmox console will automatically switch to the screen of the container. It runs (near?) native using my Proxmox connected monitor:
9 |
10 |
11 | The only thing i notice that i'm running inside an LXC container is that things like Snap and Flatpak have issues.
12 |
13 | ```
14 | remote_command_line:
15 | create_desktop:
16 | ssh_user: root
17 | ssh_host: hub.lan
18 | ssh_key: /config/key/id_ed25519
19 | command_timeout: 900
20 | command: |
21 | ctid="800"
22 | ctname="desktop"
23 | user="sander"
24 | password="Passw0rd!"
25 | template="/var/lib/pve/local-btrfs/template/cache/debian-12-standard_12.7-1_amd64.tar.zst"
26 |
27 | logger "Create container $ctid"
28 | pct create $ctid $template \
29 | --storage "local-btrfs" \
30 | --rootfs volume=local-btrfs:16 \
31 | --start false \
32 | --timezone host \
33 | --unprivileged 0 \
34 | --cores 4 \
35 | --features nesting=1,fuse=1,force_rw_sys=1,mount=sysfs\;cgroup \
36 | --tty=6 \
37 | --hostname $ctname \
38 | --memory 4096 \
39 | --password $password \
40 | --onboot 0 \
41 | --arch amd64 \
42 | --ostype debian \
43 | --force 1 \
44 | --description "Big Beautiful Desktop" \
45 | --hookscript local:snippets/chvt-desktop.pl \
46 | --unique=1 \
47 | --net0 name=eth0,bridge=vmbr0,hwaddr=66:66:66:66:66:66,ip=dhcp,type=veth
48 |
49 | logger "Configuring container $ctid"
50 | cat <> /etc/pve/lxc/$ctid.conf
51 | lxc.apparmor.profile: unconfined
52 | lxc.cap.drop:
53 | lxc.cap.drop: sys_time sys_module sys_rawio
54 | lxc.cgroup2.devices.allow: a
55 |
56 | lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir
57 | lxc.cgroup2.devices.allow: c 226:* rwm
58 |
59 | lxc.mount.entry: /dev/tty7 dev/tty7 none bind,optional,create=file
60 | lxc.cgroup2.devices.allow: c 4:7 rwm
61 |
62 | lxc.mount.entry: /dev/tty8 dev/tty8 none bind,create=file 0 0
63 | lxc.cgroup2.devices.allow: c 4:8 rwm
64 |
65 | lxc.mount.entry: /dev/tty0 dev/tty0 none bind,create=file 0 0
66 | lxc.cgroup2.devices.allow: c 4:0 rwm
67 |
68 | lxc.mount.entry: /dev/input dev/input none bind,optional,create=dir
69 | lxc.cgroup2.devices.allow: c 13:* rwm
70 |
71 | lxc.mount.entry: /dev/snd dev/snd none bind,optional,create=dir
72 | lxc.cgroup.devices.allow = c 116:* rwm
73 |
74 | lxc.mount.entry: /dev/fb0 dev/fb0 none bind,optional,create=file
75 | lxc.cgroup2.devices.allow: c 29:0 rwm
76 |
77 | lxc.mount.entry: /dev/fuse dev/fuse none bind,create=file,optional
78 | lxc.cgroup2.devices.allow: c 10:229 rwm
79 |
80 | lxc.mount.auto: cgroup:rw
81 | lxc.mount.auto: sys:rw
82 | lxc.tty.max: 6
83 | EOF
84 |
85 | pct snapshot $ctid "Post-configuration"
86 |
87 | logger "Starting container"
88 | pct start $ctid
89 |
90 | logger "Waiting for network connectivity"
91 | sleep 10
92 |
93 | logger "Provisioning SSH public keys"
94 | pct exec $ctid -- sh -c "echo \"....\" >> /root/.ssh/authorized_keys"
95 | pct exec $ctid -- sh -c "echo \"...\" >> /root/.ssh/authorized_keys"
96 |
97 | pct exec $ctid -- sh -c "apt update"
98 |
99 | logger "Install essential tools"
100 | pct exec $ctid -- sh -c "apt install -y sudo curl apt-transport-https nano"
101 |
102 | logger "Configure container timezone"
103 | pct exec $ctid -- sh -c "
104 | apt install -y locales;
105 | locale-gen en_US.UTF-8;
106 | locale-gen nl_NL.UTF-8;
107 | localedef -i nl_NL -f UTF-8 nl_NL.UTF-8
108 | "
109 |
110 | logger "Configuring keyboard"
111 | pct exec $ctid -- sh -c "tee /etc/default/keyboard < /etc/polkit-1/rules.d/49-nm-network-control.rules"
155 |
156 | logger "Installing applications"
157 | pct exec $ctid -- su - $user -c "sudo apt -y install chromium"
158 | pct exec $ctid -- su - $user -c "sudo apt -y install radeontop"
159 | pct exec $ctid -- su - $user -c "sudo apt -y install gimp"
160 | pct exec $ctid -- su - $user -c "sudo apt -y install kcharselect"
161 | pct exec $ctid -- su - $user -c "sudo apt -y install filelight"
162 | pct exec $ctid -- su - $user -c "sudo apt -y install okular"
163 | pct exec $ctid -- su - $user -c "sudo apt -y install skanpage"
164 | pct exec $ctid -- su - $user -c "sudo apt -y install thunderbird thunderbird-l10n-nl"
165 | pct exec $ctid -- su - $user -c "sudo apt -y install vlc"
166 | pct exec $ctid -- su - $user -c "sudo apt -y install kdenlive"
167 | pct exec $ctid -- su - $user -c "sudo apt -y install libreoffice-calc"
168 | pct exec $ctid -- su - $user -c "sudo apt -y install ksystemlog"
169 | pct exec $ctid -- su - $user -c "sudo apt -y install kwave"
170 | pct exec $ctid -- su - $user -c "sudo apt -y install webext-plasma-browser-integration"
171 | pct exec $ctid -- su - $user -c "sudo apt -y install golang"
172 | pct exec $ctid -- su - $user -c "sudo apt -y install flatpak"
173 |
174 | logger "Installing dutch spelling"
175 | pct exec $ctid -- su - $user -c "sudo apt -y install aspell-nl hunspell-nl"
176 | pct exec $ctid -- su - $user -c "kwriteconfig5 --file KDE/Sonnet.conf --group General --key defaultLanguage nl_NL"
177 |
178 | logger "Set user language"
179 | pct exec $ctid -- su - $user -c "
180 | kwriteconfig5 --file plasma-localerc --group Formats --key LANG nl_NL.UTF-8;
181 | kwriteconfig5 --file plasma-localerc --group Translations --key LANGUAGE nl
182 | "
183 |
184 | logger "Set keyboard layout"
185 | pct exec $ctid -- su - $user -c "
186 | kwriteconfig5 --file kxkbrc --group Layout --key LayoutList nl;
187 | kwriteconfig5 --file kxkbrc --group Layout --key Model pc105;
188 | kwriteconfig5 --file kxkbrc --group Layout --key Use true;
189 | kwriteconfig5 --file kxkbrc --group Layout --key VariantList us
190 | "
191 |
192 | logger "Configuring daily automatic updating"
193 | pct exec $ctid -- su - $user -c "kwriteconfig5 --file PlasmaDiscoverUpdates --group Global --key UseUnattendedUpdates true"
194 |
195 | logger "Configuring Screen timeout"
196 | pct exec $ctid -- su - $user -c "kwriteconfig5 --file ~/.config/kscreenlockerrc --group Daemon --key Timeout 300"
197 |
198 | logger "Installing Tailscale"
199 | pct exec $ctid -- su - $user -c "
200 | curl -fsSL https://pkgs.tailscale.com/stable/debian/bookworm.noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null;
201 | curl -fsSL https://pkgs.tailscale.com/stable/debian/bookworm.tailscale-keyring.list | sudo tee /etc/apt/sources.list.d/tailscale.list;
202 | sudo apt-get update;
203 | sudo apt-get install -y tailscale
204 | "
205 | logger "Install TriliumNext desktop v0.98.0"
206 | pct exec $ctid -- su - $user -c "
207 | wget https://github.com/TriliumNext/Trilium/releases/download/v0.98.0/TriliumNotes-v0.98.0-linux-x64.deb;
208 | sudo dpkg -i TriliumNotes-v0.98.0-linux-x64.deb;
209 | rm TriliumNotes-v0.98.0-linux-x64.deb
210 | "
211 |
212 | logger "Install Bitwarden desktop"
213 | pct exec $ctid -- su - $user -c "
214 | wget \"https://bitwarden.com/download/?app=desktop&platform=linux&variant=deb\" -O bitwarden.deb;
215 | sudo dpkg -i bitwarden.deb;
216 | rm bitwarden.deb
217 | "
218 |
219 | logger "Installing VSCode"
220 | pct exec $ctid -- su - $user -c "
221 | echo \"code code/add-microsoft-repo boolean true\" | sudo debconf-set-selections;
222 | sudo apt-get install wget gpg;
223 | wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg;
224 | sudo install -D -o root -g root -m 644 microsoft.gpg /usr/share/keyrings/microsoft.gpg;
225 | rm -f microsoft.gpg
226 | "
227 | pct exec $ctid -- sh -c "tee /etc/apt/sources.list.d/vscode.sources <-
85 | Definieer lijst van topics waarvan de waarde direct opgevraagd dient te
86 | worden
87 | - alias: Publiceer "get" commando's voor direct ophalen van waarden van topics
88 | repeat:
89 | count: "{{ topics | count }}"
90 | sequence:
91 | - variables:
92 | topic: ebusd/{{ topics[repeat.index - 1] }}/get
93 | - data:
94 | topic: "{{topic}}"
95 | action: mqtt.publish
96 | - variables:
97 | topics:
98 | - bai/Flame
99 | - bai/HwcWaterflow
100 | - bai/Statenumber
101 | - bai/HwcDemand
102 | - bai/PumpPower
103 | alias: >-
104 | Definieer lijst van topics waarvan de waarde zeer regelmatig bijgewerkt
105 | dient te worden
106 | - alias: >-
107 | Publiceer "get?1" commando's voor het zeer regelmatig bijwerken van de
108 | waarden van topics
109 | repeat:
110 | count: "{{ topics | count }}"
111 | sequence:
112 | - variables:
113 | topic: ebusd/{{ topics[repeat.index - 1] }}/get
114 | - data:
115 | topic: "{{topic}}"
116 | payload: "?1"
117 | action: mqtt.publish
118 | - variables:
119 | topics:
120 | - bai/CirPump
121 | - bai/PrEnergySumHc1
122 | - bai/PrEnergySumHwc1
123 | - bai/PrEnergyCountHwc1
124 | - bai/PrEnergyCountHc1
125 | - bai/RemainingBoilerblocktime
126 | - bai/ReturnTemp
127 | - bai/PumpPowerDesired
128 | alias: >-
129 | Definieer lijst van topics waarvan de waarde minder regelmatig bijgewerkt
130 | dient te worden
131 | - alias: >-
132 | Publiceer "get?2" commando's voor het minder regelmatig bijwerken van de
133 | waarden van topics
134 | repeat:
135 | count: "{{ topics | count }}"
136 | sequence:
137 | - variables:
138 | topic: ebusd/{{ topics[repeat.index - 1] }}/get
139 | - data:
140 | topic: "{{topic}}"
141 | payload: "?2"
142 | action: mqtt.publish
143 | ```
144 |
145 | ## Feature: High-low-temperature schedule
146 | I am using a "2 presets" configuration with a high-temperature and low-temperature preset.
147 |
148 | I am using a setup which is using a [Schedule helper](https://www.home-assistant.io/integrations/schedule/) to switch the heating-presets (high or low) at which times.
149 |
150 | I am also using a [Boolean helper](https://www.home-assistant.io/integrations/input_boolean/) to temporarely pause the heating, for instance when doors are opened or nobody is at home.
151 |
152 |
153 | 
154 |
155 | ### Helpers
156 | * `input_boolean.verwarming_schema_gestuurd`: This is a switch to enable/disable the controlling of the heating via the schema.
157 | * `schedule.verwarming`: This is a schedule helper in which a week-schedule can be configured to define when the "high"-heating-preset is desired.
158 | * `input_number.woonkamer_verwarming_hoog_temperatuur`: This is the temperature which is desired to be used for the "high"-preset.
159 | * `input_number.woonkamer_verwarming_laag_temperatuur`: This is the temperature which is desired to be used for the "low"-preset
160 |
161 | ### Dashboard card
162 | ```
163 | type: entities
164 | title: Verwarmingsschema
165 | state_color: false
166 | entities:
167 | - entity: input_boolean.verwarming_schema_gestuurd
168 | secondary_info: last-changed
169 | - type: simple-entity
170 | name: Schema tijdelijk onderbroken
171 | entity: input_boolean.verwarming_schema_gestuurd_tijdelijk_gedeactiveerd
172 | secondary_info: last-changed
173 | state_color: true
174 | tap_action:
175 | action: more-info
176 | hold_action:
177 | action: none
178 | double_tap_action: none
179 | - type: conditional
180 | conditions:
181 | - condition: state
182 | entity: schedule.verwarming
183 | state: "on"
184 | row:
185 | type: attribute
186 | name: Huidige aansturing
187 | icon: mdi:radiator
188 | format: time
189 | entity: schedule.verwarming
190 | attribute: next_event
191 | prefix: hoog tot
192 | - type: conditional
193 | conditions:
194 | - condition: state
195 | entity: schedule.verwarming
196 | state: "off"
197 | row:
198 | type: attribute
199 | name: Verwarming schema
200 | icon: mdi:radiator-disabled
201 | format: time
202 | entity: schedule.verwarming
203 | attribute: next_event
204 | prefix: laag tot
205 | - type: weblink
206 | name: Schema helper
207 | url: /config/helpers
208 | icon: mdi:home-assistant
209 | new_tab: false
210 | - type: divider
211 | - type: custom:multiple-entity-row
212 | name: Woonkamer temperatuur
213 | entity: climate.woonkamer_verwarming
214 | entities:
215 | - entity: sensor.huidige_temperatuur_woonkamer
216 | name: Huidig
217 | - entity: input_number.woonkamer_verwarming_hoog_temperatuur
218 | name: Hoog
219 | - entity: input_number.woonkamer_verwarming_laag_temperatuur
220 | name: Laag
221 | show_header_toggle: false
222 | ```
223 |
224 | ### "Woonkamer verwarming hoog op basis van schema"
225 | This automation ensures the "high"-preset to be enabled.
226 | ```
227 | alias: Woonkamer verwarming hoog op basis van schema
228 | triggers:
229 | - trigger: state
230 | entity_id:
231 | - schedule.verwarming
232 | from: "off"
233 | to: "on"
234 | - trigger: state
235 | entity_id:
236 | - input_boolean.verwarming_schema_gestuurd
237 | from: "off"
238 | to: "on"
239 | - trigger: state
240 | entity_id:
241 | - input_boolean.verwarming_schema_gestuurd_tijdelijk_gedeactiveerd
242 | from: "on"
243 | to: "off"
244 | conditions:
245 | - condition: state
246 | entity_id: schedule.verwarming
247 | state: "on"
248 | - condition: state
249 | entity_id: input_boolean.verwarming_schema_gestuurd
250 | state: "on"
251 | - condition: state
252 | entity_id: input_boolean.verwarming_schema_gestuurd_tijdelijk_gedeactiveerd
253 | state: "off"
254 | actions:
255 | - target:
256 | entity_id:
257 | - climate.woonkamer_verwarming
258 | data:
259 | temperature: "{{ states(\"input_number.woonkamer_verwarming_hoog_temperatuur\") }}"
260 | alias: Stel temperatuur in op hoog
261 | action: climate.set_temperature
262 | mode: single
263 | ```
264 |
265 | ### "Woonkamer verwarming laag op basis van schema"
266 | This automation ensures the "low"-preset to be activated.
267 | ```
268 | alias: Woonkamer verwarming laag op basis van schema
269 | triggers:
270 | - entity_id:
271 | - schedule.verwarming
272 | trigger: state
273 | from: "on"
274 | to: "off"
275 | - trigger: state
276 | entity_id:
277 | - input_boolean.verwarming_schema_gestuurd_tijdelijk_gedeactiveerd
278 | from: "on"
279 | to: "off"
280 | conditions:
281 | - condition: state
282 | entity_id: schedule.verwarming
283 | state: "off"
284 | - condition: state
285 | entity_id: input_boolean.verwarming_schema_gestuurd
286 | state: "on"
287 | - condition: state
288 | entity_id: input_boolean.verwarming_schema_gestuurd_tijdelijk_gedeactiveerd
289 | state: "off"
290 | actions:
291 | - alias: Stel temperatuur in op laag
292 | target:
293 | entity_id:
294 | - climate.woonkamer_verwarming
295 | data:
296 | temperature: "{{ states(\"input_number.woonkamer_verwarming_laag_temperatuur\") }}"
297 | hvac_mode: heat
298 | action: climate.set_temperature
299 | mode: single
300 | ```
301 |
302 | ## Feature: Polling and updating
303 | This automation keeps the script running. The script should run continuously. I use this automation and a script to prevent Home Assistant from continuously registering the start of automations and scripts.
304 |
305 | ### "automation.poll_warm_water_script_starten"
306 | ```
307 | alias: Scripts "eBUS polling" actief houden
308 | triggers:
309 | - trigger: homeassistant
310 | event: start
311 | - trigger: state
312 | entity_id:
313 | - script.poll_warm_water_waarden
314 | to: "off"
315 | - trigger: state
316 | entity_id:
317 | - script.poll_low_prio_ebus_registers
318 | to: "off"
319 | actions:
320 | - action: script.turn_on
321 | target:
322 | entity_id:
323 | - script.poll_warm_water_waarden
324 | - script.poll_low_prio_ebus_registers
325 | mode: single
326 | ```
327 |
328 | ### "script.poll_warm_water_waarden"
329 | This script polls values which are used to temporarily increase the polling frequency of certain other values.
330 | ```
331 | sequence:
332 | - repeat:
333 | while:
334 | - condition: template
335 | value_template: "{{true}}"
336 | sequence:
337 | - action: mqtt.publish
338 | data:
339 | topic: ebusd/bai/HwcDemand/get
340 | payload: "?1"
341 | alias: Poll "warm-water-vraag"
342 | - delay:
343 | seconds: 5
344 | - alias: Poll "flame"
345 | action: mqtt.publish
346 | data:
347 | topic: ebusd/bai/Flame/get
348 | payload: "?1"
349 | - delay:
350 | seconds: 5
351 | - alias: Poll "Statenumber"
352 | action: mqtt.publish
353 | data:
354 | topic: ebusd/bai/Statenumber/get
355 | payload: "?1"
356 | - delay:
357 | seconds: 5
358 | alias: Poll high-prio ebus waarden
359 | icon: mdi:target
360 | ```
361 |
362 | ### "script.poll_low_prio_ebus_registers"
363 | This script runs in a loop and will poll certain values on a lower frequency.
364 | ```
365 | sequence:
366 | - repeat:
367 | while:
368 | - condition: template
369 | value_template: "{{true}}"
370 | sequence:
371 | - action: mqtt.publish
372 | data:
373 | topic: ebusd/bai/PrEnergySumHwc1/get
374 | payload: "?1"
375 | alias: Poll "PrEnergySumHwc1"
376 | - action: mqtt.publish
377 | data:
378 | topic: ebusd/bai/PrEnergyCountHwc1/get
379 | payload: "?1"
380 | alias: Poll "PrEnergyCountHwc1"
381 | - action: mqtt.publish
382 | data:
383 | topic: ebusd/bai/HwcStarts/get
384 | payload: "?1"
385 | alias: Poll "HwcStarts"
386 | - action: mqtt.publish
387 | data:
388 | topic: ebusd/bai/HwcTemp/get
389 | payload: "?1"
390 | alias: Poll "HwcTemp"
391 | - action: mqtt.publish
392 | data:
393 | topic: ebusd/bai/HwcHours/get
394 | payload: "?1"
395 | alias: Poll "HwcHours"
396 | - delay:
397 | seconds: 60
398 | - action: mqtt.publish
399 | data:
400 | topic: ebusd/bai/CirPump/get
401 | payload: "?1"
402 | alias: Poll "CirPump"
403 | - action: mqtt.publish
404 | data:
405 | topic: ebusd/bai/PrEnergySumHc1/get
406 | payload: "?1"
407 | alias: Poll "PrEnergySumHc1"
408 | - action: mqtt.publish
409 | data:
410 | topic: ebusd/bai/PrEnergyCountHc1/get
411 | payload: "?1"
412 | alias: Poll "PrEnergyCountHc1"
413 | - action: mqtt.publish
414 | data:
415 | topic: ebusd/bai/ReturnTemp/get
416 | payload: "?1"
417 | alias: Poll "ReturnTemp"
418 | - alias: Poll "DisplayedRoomTemp"
419 | action: mqtt.publish
420 | data:
421 | topic: ebusd/350/DisplayedRoomTemp/get
422 | payload: "?1"
423 | - delay:
424 | seconds: 60
425 | alias: Poll low-prio ebus registers
426 | description: ""
427 | icon: mdi:target-variant
428 | ```
429 |
430 | ### "automation.tijdens_cv_brander_frequenter_waarden_ophalen"
431 | ```
432 | alias: Tijdens "CV Brander" frequenter waarden ophalen
433 | description: ""
434 | triggers:
435 | - trigger: state
436 | entity_id:
437 | - sensor.ebusd_bai_flame
438 | to: "on"
439 | from: "off"
440 | actions:
441 | - repeat:
442 | while:
443 | - condition: state
444 | entity_id: sensor.ebusd_bai_flame
445 | state: "on"
446 | sequence:
447 | - action: mqtt.publish
448 | metadata: {}
449 | data:
450 | topic: ebusd/bai/PrEnergySumHc1/get
451 | payload: "?1"
452 | alias: Poll "PrEnergySumHc1"
453 | - action: mqtt.publish
454 | metadata: {}
455 | data:
456 | topic: ebusd/bai/PrEnergyCountHc1/get
457 | payload: "?1"
458 | alias: Poll "PrEnergyCountHc1"
459 | - action: mqtt.publish
460 | metadata: {}
461 | data:
462 | topic: ebusd/bai/Flame/get
463 | payload: "?1"
464 | alias: Poll "flame"
465 | - delay:
466 | hours: 0
467 | minutes: 0
468 | seconds: 5
469 | milliseconds: 0
470 | mode: single
471 | ```
472 |
473 |
474 | ## Feature: Seperate sensors for gas usage for heating-circuit and hot-water-circuit
475 | Using a P1 meter i'm able to track the usage of gas. But using PrEnergy* of my Vaillant Boiler, i'm even able to track for which goal gas used.
476 |
477 |
478 |
479 | ### "automation.reset_prenergy_waarden_om_middernacht"
480 | This automation will start a script at midnight which resets the prenergy* fields.
481 | ```
482 | alias: Reset PrEnergy* waarden om middernacht
483 | triggers:
484 | - trigger: time_pattern
485 | hours: "0"
486 | minutes: "0"
487 | seconds: "0"
488 | actions:
489 | - action: script.turn_on
490 | target:
491 | entity_id: script.reset_prenergy_waarden
492 | mode: single
493 | ```
494 |
495 | ### "script.reset_prenergy_waarden"
496 | This script resets the PrEnergy* fields.
497 | ```
498 | sequence:
499 | - alias: Reset ebusd/bai/PrEnergyCountHwc1
500 | data:
501 | topic: ebusd/bai/PrEnergyCountHwc1/set
502 | payload: "0"
503 | action: mqtt.publish
504 | enabled: true
505 | - alias: Reset ebusd/bai/PrEnergyCountHc1
506 | data:
507 | topic: ebusd/bai/PrEnergyCountHc1/set
508 | payload: " 0"
509 | action: mqtt.publish
510 | enabled: true
511 | - alias: Reset ebusd/bai/PrEnergySumHc1
512 | data:
513 | topic: ebusd/bai/PrEnergySumHc1/set
514 | payload: " 0"
515 | action: mqtt.publish
516 | enabled: true
517 | - alias: Reset ebusd/bai/PrEnergySumHwc1
518 | data:
519 | topic: ebusd/bai/PrEnergySumHwc1/set
520 | payload: " 0"
521 | action: mqtt.publish
522 | enabled: true
523 | alias: Reset PrEnergy* waarden
524 | ```
525 |
526 |
527 | ### Template Helper: "sensor.gasverbruik_voor_warm_water"
528 | This helper will calculate the m3 of gas used for hot-water-circuit.
529 | ```
530 | {{ (states("sensor.ebusd_bai_prenergysumhwc1") |float) * 0.000002010000000 }}
531 | ```
532 |
533 | ### Template Helper: "sensor.gasverbruik_vandaag_voor_verwarming"
534 | This helper will calculate the m3 of gas used for heating-circuit.
535 | ```
536 | {{ (states("sensor.ebusd_bai_prenergysumhc1") |float) * 0.00000203370665409 }}
537 | ```
538 |
--------------------------------------------------------------------------------