mirror of
https://github.com/Theaninova/TheaninovOS.git
synced 2026-07-25 10:04:44 +00:00
feat: airgradient
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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'<span color="{state_color}">{s}</span>'
|
||||
|
||||
print(json.dumps({"text": text}))
|
||||
+154
-136
@@ -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<firefox>" = "";
|
||||
"class<thunderbird>" = "";
|
||||
"class<neovide>" = "";
|
||||
"class<kitty>" = "";
|
||||
"class<OrcaSlicer>" = "";
|
||||
"class<blender>" = "";
|
||||
"class<steam>" = "";
|
||||
};
|
||||
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<firefox>" = "";
|
||||
"class<thunderbird>" = "";
|
||||
"class<neovide>" = "";
|
||||
"class<kitty>" = "";
|
||||
"class<OrcaSlicer>" = "";
|
||||
"class<blender>" = "";
|
||||
"class<steam>" = "";
|
||||
};
|
||||
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";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user