mirror of
https://github.com/Theaninova/TheaninovOS.git
synced 2026-07-25 01:54:48 +00:00
feat: airgradient
This commit is contained in:
@@ -60,8 +60,6 @@
|
|||||||
udev.packages = with pkgs; [
|
udev.packages = with pkgs; [
|
||||||
usb-sniffer
|
usb-sniffer
|
||||||
];
|
];
|
||||||
|
|
||||||
hardware.openrgb.enable = true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
hardware = {
|
hardware = {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
window#waybar {
|
window#waybar {
|
||||||
background: none;
|
background: none;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
window#waybar > box.horizontal {
|
window#waybar > box.horizontal {
|
||||||
@@ -15,7 +16,6 @@ window#waybar > box.horizontal {
|
|||||||
|
|
||||||
#clock {
|
#clock {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 16px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#privacy-item {
|
#privacy-item {
|
||||||
|
|||||||
@@ -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}))
|
||||||
@@ -16,17 +16,26 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
home-manager.users.${username}.programs.waybar = {
|
home-manager.users.${username} = {
|
||||||
|
home.packages = [ (pkgs.callPackage ./waybar-ha { }) ];
|
||||||
|
programs.waybar = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
settings =
|
||||||
|
let
|
||||||
|
waybar-ha = pkgs.callPackage ./waybar-ha { };
|
||||||
|
in
|
||||||
|
{
|
||||||
mainBar = {
|
mainBar = {
|
||||||
layer = "top";
|
layer = "top";
|
||||||
|
|
||||||
height = 24;
|
height = 36;
|
||||||
reload_style_on_change = true;
|
reload_style_on_change = true;
|
||||||
exclusive = true;
|
exclusive = true;
|
||||||
|
|
||||||
modules-left = (
|
modules-left = [
|
||||||
|
"custom/ha"
|
||||||
|
]
|
||||||
|
++ (
|
||||||
if cfg.mobile then
|
if cfg.mobile then
|
||||||
[
|
[
|
||||||
"battery"
|
"battery"
|
||||||
@@ -41,6 +50,7 @@ in
|
|||||||
"privacy"
|
"privacy"
|
||||||
"gamemode"
|
"gamemode"
|
||||||
"tray"
|
"tray"
|
||||||
|
|
||||||
"pulseaudio"
|
"pulseaudio"
|
||||||
]
|
]
|
||||||
++ (
|
++ (
|
||||||
@@ -130,6 +140,13 @@ in
|
|||||||
"tooltip-format" = "{capacity}%";
|
"tooltip-format" = "{capacity}%";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
"custom/ha" = {
|
||||||
|
exec = pkgs.lib.getExe waybar-ha;
|
||||||
|
return-type = "json";
|
||||||
|
interval = 30;
|
||||||
|
format = "{}";
|
||||||
|
};
|
||||||
|
|
||||||
"custom/theme" = {
|
"custom/theme" = {
|
||||||
return-type = "json";
|
return-type = "json";
|
||||||
exec-on-event = true;
|
exec-on-event = true;
|
||||||
@@ -156,4 +173,5 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user