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";
+ };
};
};
};