From fa70c98160da50fe5c7b90ea0b6e2a81d913bd95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thea=20Sch=C3=B6bl?= Date: Tue, 28 Apr 2026 15:38:47 +0200 Subject: [PATCH] feat: airgradient --- hosts/MONSTER/default.nix | 2 - modules/home-manager/theme/waybar.css | 2 +- modules/nixos/shell/waybar-ha/default.nix | 17 + modules/nixos/shell/waybar-ha/pyproject.toml | 10 + .../shell/waybar-ha/waybar_ha/__init__.py | 0 .../nixos/shell/waybar-ha/waybar_ha/main.py | 111 +++++++ modules/nixos/shell/waybar.nix | 290 ++++++++++-------- 7 files changed, 293 insertions(+), 139 deletions(-) create mode 100644 modules/nixos/shell/waybar-ha/default.nix create mode 100644 modules/nixos/shell/waybar-ha/pyproject.toml create mode 100644 modules/nixos/shell/waybar-ha/waybar_ha/__init__.py create mode 100644 modules/nixos/shell/waybar-ha/waybar_ha/main.py diff --git a/hosts/MONSTER/default.nix b/hosts/MONSTER/default.nix index 73df97c..713d38b 100644 --- a/hosts/MONSTER/default.nix +++ b/hosts/MONSTER/default.nix @@ -60,8 +60,6 @@ udev.packages = with pkgs; [ usb-sniffer ]; - - hardware.openrgb.enable = true; }; hardware = { diff --git a/modules/home-manager/theme/waybar.css b/modules/home-manager/theme/waybar.css index e5c7b6c..dc9f891 100644 --- a/modules/home-manager/theme/waybar.css +++ b/modules/home-manager/theme/waybar.css @@ -1,6 +1,7 @@ window#waybar { background: none; border-bottom: none; + font-size: 20px; } window#waybar > box.horizontal { @@ -15,7 +16,6 @@ window#waybar > box.horizontal { #clock { font-weight: bold; - font-size: 16px; } #privacy-item { diff --git a/modules/nixos/shell/waybar-ha/default.nix b/modules/nixos/shell/waybar-ha/default.nix new file mode 100644 index 0000000..42e6ada --- /dev/null +++ b/modules/nixos/shell/waybar-ha/default.nix @@ -0,0 +1,17 @@ +{ python3Packages }: +with python3Packages; +buildPythonPackage rec { + pname = "waybar-ha"; + version = "0.0.1"; + format = "pyproject"; + src = ./.; + buildInputs = [ + setuptools + ]; + propagatedBuildInputs = [ + requests + keyring + ]; + + meta.mainProgram = pname; +} diff --git a/modules/nixos/shell/waybar-ha/pyproject.toml b/modules/nixos/shell/waybar-ha/pyproject.toml new file mode 100644 index 0000000..a670edc --- /dev/null +++ b/modules/nixos/shell/waybar-ha/pyproject.toml @@ -0,0 +1,10 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +[project] +name = "waybar-ha" +version = "0.0.1" + +[project.scripts] +waybar-ha = "waybar_ha.main:main" diff --git a/modules/nixos/shell/waybar-ha/waybar_ha/__init__.py b/modules/nixos/shell/waybar-ha/waybar_ha/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/modules/nixos/shell/waybar-ha/waybar_ha/main.py b/modules/nixos/shell/waybar-ha/waybar_ha/main.py new file mode 100644 index 0000000..e60f280 --- /dev/null +++ b/modules/nixos/shell/waybar-ha/waybar_ha/main.py @@ -0,0 +1,111 @@ +import json +from requests import get +import keyring +import colorsys +import math + + +group = "waybar-ha" + +HA_URL = keyring.get_password(group, "HA_URL") +HA_TOKEN = keyring.get_password(group, "HA_TOKEN") +if not HA_URL: + keyring.set_password(group, "HA_URL", "YOUR_URL") +if not HA_TOKEN: + keyring.set_password(group, "HA_TOKEN", "YOUR_TOKEN") + +hsv_s = 0.42 +hsv_v = 0.96 + +numbers_filled = ["󰰖", "󰲠", "󰲢", "󰲤", "󰲦", "󰲨", "󰲪", "󰲬", "󰲮", "󰲰", "󰄯", "󰰙", "󰰐"] +numbers_outline = ["󰰗", "󰲡", "󰲣", "󰲥", "󰲧", "󰲩", "󰲫", "󰲭", "󰲯", "󰲱", "󰄰", "󰰚", "󰰑"] +dots = 8 + + +SENSORS = [ + ( + "sensor.i_9psl_carbon_dioxide", + [ + (0, 1, 117), + (600, 2, 100), + (800, 3, 65), + (1000, 4, 41), + (1250, 5, 27), + (1500, 6, 12), + (1750, 7, 0), + (1751, 7, 360), + (2000, 8, 329), + (3000, 8, 290), + ], + ), +] + + +def lerp(a: float, b: float, t: float) -> float: + return (1 - t) * a + t * b + + +def main() -> None: + states = get( + f"{HA_URL}/api/states", + headers={ + "Authorization": f"Bearer {HA_TOKEN}", + "Content-Type": "application/json", + }, + ).json() + + text = "" + states_idx = {s["entity_id"]: s for s in states} + for sensor, thresholds in SENSORS: + if sensor not in states_idx: + continue + state = states_idx[sensor] + state_icon = 1 + state_color = "" + sensor_value = int(state["state"]) + + if thresholds is not None: + try: + for i, (threshold, icon, hue) in reversed(list(enumerate(thresholds))): + if sensor_value >= threshold: + if sensor_value != threshold and i < len(thresholds) - 1: + next_threshold, _, next_hue = SENSORS[0][1][i + 1] + hue = lerp( + hue, + next_hue, + (sensor_value - threshold) + / (next_threshold - threshold), + ) + + state_icon = icon + state_color = "#{:02x}{:02x}{:02x}".format( + *( + int(c * 255) + for c in colorsys.hsv_to_rgb(hue / 360, hsv_s, hsv_v) + ) + ) + break + except ValueError: + pass + + suffix = [] # [11, 11, 12] + digits: list[int] = list(map(lambda x: int(x), list(f"{sensor_value}"))) + s = "".join( + map( + lambda t: ( + numbers_outline[t[1]] + if dots - t[0] > state_icon + else numbers_filled[t[1]] + ), + enumerate( + [ + *map(lambda _: 10, range(dots - len(digits) - len(suffix))), + *digits, + *suffix, + ] + ), + ) + ) + text += f'{s}' + + print(json.dumps({"text": text})) diff --git a/modules/nixos/shell/waybar.nix b/modules/nixos/shell/waybar.nix index 4bca9d3..54bebf9 100644 --- a/modules/nixos/shell/waybar.nix +++ b/modules/nixos/shell/waybar.nix @@ -16,143 +16,161 @@ in }; config = lib.mkIf cfg.enable { - home-manager.users.${username}.programs.waybar = { - enable = true; - settings = { - mainBar = { - layer = "top"; - - height = 24; - reload_style_on_change = true; - exclusive = true; - - modules-left = ( - if cfg.mobile then - [ - "battery" - ] - else - [ ] - ); - modules-center = [ - "clock" - ]; - modules-right = [ - "privacy" - "gamemode" - "tray" - "pulseaudio" - ] - ++ ( - if cfg.mobile then - [ "backlight" ] - else - [ - "custom/brightness" - ] - ) - ++ [ - # "custom/theme" - # "network" - ]; - - "pulseaudio" = { - format = "{icon} {volume}%"; - format-icons = { - "alsa_output.usb-Turtle_Beach_Turtle_Beach_Stealth_700_G2_MAX-01.iec958-stereo" = "󰋋"; - "alsa_output.pci-0000_0a_00.4.analog-stereo" = "󰓃"; - "alsa_output.pci-0000_08_00.1.hdmi-stereo-extra4" = "󰽟"; - "alsa_output.usb-Blue_Microphones_Yeti_Stereo_Microphone_797_2018_11_12_79383-00.analog-stereo" = - "󰍬"; - "default" = "󰕾"; - }; - on-click = "pavucontrol --tab=3"; - }; - - "backlight" = { - "format" = "{icon}"; - "format-icons" = [ - "󰃚" - "󰃛" - "󰃜" - "󰃝" - "󰃞" - "󰃟" - "󰃠" - ]; - "tooltip-format" = "{percent}%"; - }; - - "hyprland/workspaces" = { - format = "{windows}"; - window-rewrite = { - "class" = "󰈹"; - "class" = ""; - "class" = ""; - "class" = ""; - "class" = "󰹛"; - "class" = ""; - "class" = ""; - }; - window-rewrite-default = ""; - }; - - "network" = { - "format-icons" = [ - "󰤯" - "󰤟" - "󰤢" - "󰤥" - "󰤨" - ]; - "format" = "󰛳"; - "format-wifi" = "{icon}"; - "format-ethernet" = "󰈀"; - "format-disconnected" = if cfg.mobile then "󰤭" else "󰲛"; - }; - - "battery" = { - "format-icons" = [ - "󰂎" - "󰁺" - "󰁻" - "󰁼" - "󰁽" - "󰁾" - "󰁿" - "󰂀" - "󰂁" - "󰂂" - "󰁹" - ]; - "format" = "{icon}"; - "format-time" = "{H}:{m}"; - "tooltip-format" = "{capacity}%"; - }; - - "custom/theme" = { - return-type = "json"; - exec-on-event = true; - exec = pkgs.writeShellScript "waybar-theme" '' - if [ $(theme mode) = "dark" ]; then - echo '{"text": "", "tooltip": "Switch to light theme"}' - elif [ $(theme mode) = "auto" ]; then - echo '{"text": "󰖛", "tooltip": "Switch to dark theme"}' - else - echo '{"text": "", "tooltip": "Switch to dark theme"}' - fi - ''; - exec-if = "sleep 1"; - interval = "once"; - on-click = "theme toggle"; - on-click-right = "theme auto"; - on-click-middle = "theme wallpaper"; - }; - }; - }; - systemd = { + home-manager.users.${username} = { + home.packages = [ (pkgs.callPackage ./waybar-ha { }) ]; + programs.waybar = { enable = true; - target = "graphical-session.target"; + settings = + let + waybar-ha = pkgs.callPackage ./waybar-ha { }; + in + { + mainBar = { + layer = "top"; + + height = 36; + reload_style_on_change = true; + exclusive = true; + + modules-left = [ + "custom/ha" + ] + ++ ( + if cfg.mobile then + [ + "battery" + ] + else + [ ] + ); + modules-center = [ + "clock" + ]; + modules-right = [ + "privacy" + "gamemode" + "tray" + + "pulseaudio" + ] + ++ ( + if cfg.mobile then + [ "backlight" ] + else + [ + "custom/brightness" + ] + ) + ++ [ + # "custom/theme" + # "network" + ]; + + "pulseaudio" = { + format = "{icon} {volume}%"; + format-icons = { + "alsa_output.usb-Turtle_Beach_Turtle_Beach_Stealth_700_G2_MAX-01.iec958-stereo" = "󰋋"; + "alsa_output.pci-0000_0a_00.4.analog-stereo" = "󰓃"; + "alsa_output.pci-0000_08_00.1.hdmi-stereo-extra4" = "󰽟"; + "alsa_output.usb-Blue_Microphones_Yeti_Stereo_Microphone_797_2018_11_12_79383-00.analog-stereo" = + "󰍬"; + "default" = "󰕾"; + }; + on-click = "pavucontrol --tab=3"; + }; + + "backlight" = { + "format" = "{icon}"; + "format-icons" = [ + "󰃚" + "󰃛" + "󰃜" + "󰃝" + "󰃞" + "󰃟" + "󰃠" + ]; + "tooltip-format" = "{percent}%"; + }; + + "hyprland/workspaces" = { + format = "{windows}"; + window-rewrite = { + "class" = "󰈹"; + "class" = ""; + "class" = ""; + "class" = ""; + "class" = "󰹛"; + "class" = ""; + "class" = ""; + }; + window-rewrite-default = ""; + }; + + "network" = { + "format-icons" = [ + "󰤯" + "󰤟" + "󰤢" + "󰤥" + "󰤨" + ]; + "format" = "󰛳"; + "format-wifi" = "{icon}"; + "format-ethernet" = "󰈀"; + "format-disconnected" = if cfg.mobile then "󰤭" else "󰲛"; + }; + + "battery" = { + "format-icons" = [ + "󰂎" + "󰁺" + "󰁻" + "󰁼" + "󰁽" + "󰁾" + "󰁿" + "󰂀" + "󰂁" + "󰂂" + "󰁹" + ]; + "format" = "{icon}"; + "format-time" = "{H}:{m}"; + "tooltip-format" = "{capacity}%"; + }; + + "custom/ha" = { + exec = pkgs.lib.getExe waybar-ha; + return-type = "json"; + interval = 30; + format = "{}"; + }; + + "custom/theme" = { + return-type = "json"; + exec-on-event = true; + exec = pkgs.writeShellScript "waybar-theme" '' + if [ $(theme mode) = "dark" ]; then + echo '{"text": "", "tooltip": "Switch to light theme"}' + elif [ $(theme mode) = "auto" ]; then + echo '{"text": "󰖛", "tooltip": "Switch to dark theme"}' + else + echo '{"text": "", "tooltip": "Switch to dark theme"}' + fi + ''; + exec-if = "sleep 1"; + interval = "once"; + on-click = "theme toggle"; + on-click-right = "theme auto"; + on-click-middle = "theme wallpaper"; + }; + }; + }; + systemd = { + enable = true; + target = "graphical-session.target"; + }; }; }; };