diff --git a/flake.lock b/flake.lock index b66c097..ef59437 100644 --- a/flake.lock +++ b/flake.lock @@ -98,11 +98,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1754725699, - "narHash": "sha256-iAcj9T/Y+3DBy2J0N+yF9XQQQ8IEb5swLFzs23CdP88=", + "lastModified": 1758690382, + "narHash": "sha256-NY3kSorgqE5LMm1LqNwGne3ZLMF2/ILgLpFr1fS4X3o=", "owner": "nixos", "repo": "nixpkgs", - "rev": "85dbfc7aaf52ecb755f87e577ddbe6dbbdbc1054", + "rev": "e643668fd71b949c53f8626614b21ff71a07379d", "type": "github" }, "original": { @@ -114,11 +114,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1754767907, - "narHash": "sha256-8OnUzRQZkqtUol9vuUuQC30hzpMreKptNyET2T9lB6g=", + "lastModified": 1758791193, + "narHash": "sha256-F8WmEwFoHsnix7rt290R0rFXNJiMbClMZyIC/e+HYf0=", "owner": "nixos", "repo": "nixpkgs", - "rev": "c5f08b62ed75415439d48152c2a784e36909b1bc", + "rev": "25e53aa156d47bad5082ff7618f5feb1f5e02d01", "type": "github" }, "original": { diff --git a/nate-work/dotfiles/ghostty/config b/nate-work/dotfiles/ghostty/config index 62d9fad..517f906 100644 --- a/nate-work/dotfiles/ghostty/config +++ b/nate-work/dotfiles/ghostty/config @@ -1,4 +1,4 @@ -theme = "catppuccin-macchiato" +theme = "catppuccin-macchiato.conf" ### # Font config diff --git a/nate-work/dotfiles/ghostty/themes/catppuccin-frappe.conf b/nate-work/dotfiles/ghostty/themes/catppuccin-frappe.conf new file mode 100644 index 0000000..503b7a8 --- /dev/null +++ b/nate-work/dotfiles/ghostty/themes/catppuccin-frappe.conf @@ -0,0 +1,22 @@ +palette = 0=#51576d +palette = 1=#e78284 +palette = 2=#a6d189 +palette = 3=#e5c890 +palette = 4=#8caaee +palette = 5=#f4b8e4 +palette = 6=#81c8be +palette = 7=#a5adce +palette = 8=#626880 +palette = 9=#e78284 +palette = 10=#a6d189 +palette = 11=#e5c890 +palette = 12=#8caaee +palette = 13=#f4b8e4 +palette = 14=#81c8be +palette = 15=#b5bfe2 +background = 303446 +foreground = c6d0f5 +cursor-color = f2d5cf +cursor-text = 232634 +selection-background = 44495d +selection-foreground = c6d0f5 diff --git a/nate-work/dotfiles/ghostty/themes/catppuccin-latte.conf b/nate-work/dotfiles/ghostty/themes/catppuccin-latte.conf new file mode 100644 index 0000000..884910d --- /dev/null +++ b/nate-work/dotfiles/ghostty/themes/catppuccin-latte.conf @@ -0,0 +1,22 @@ +palette = 0=#5c5f77 +palette = 1=#d20f39 +palette = 2=#40a02b +palette = 3=#df8e1d +palette = 4=#1e66f5 +palette = 5=#ea76cb +palette = 6=#179299 +palette = 7=#acb0be +palette = 8=#6c6f85 +palette = 9=#d20f39 +palette = 10=#40a02b +palette = 11=#df8e1d +palette = 12=#1e66f5 +palette = 13=#ea76cb +palette = 14=#179299 +palette = 15=#bcc0cc +background = eff1f5 +foreground = 4c4f69 +cursor-color = dc8a78 +cursor-text = eff1f5 +selection-background = d8dae1 +selection-foreground = 4c4f69 diff --git a/nate-work/dotfiles/ghostty/themes/catppuccin-macchiato.conf b/nate-work/dotfiles/ghostty/themes/catppuccin-macchiato.conf new file mode 100644 index 0000000..b1eb033 --- /dev/null +++ b/nate-work/dotfiles/ghostty/themes/catppuccin-macchiato.conf @@ -0,0 +1,22 @@ +palette = 0=#494d64 +palette = 1=#ed8796 +palette = 2=#a6da95 +palette = 3=#eed49f +palette = 4=#8aadf4 +palette = 5=#f5bde6 +palette = 6=#8bd5ca +palette = 7=#a5adcb +palette = 8=#5b6078 +palette = 9=#ed8796 +palette = 10=#a6da95 +palette = 11=#eed49f +palette = 12=#8aadf4 +palette = 13=#f5bde6 +palette = 14=#8bd5ca +palette = 15=#b8c0e0 +background = 24273a +foreground = cad3f5 +cursor-color = f4dbd6 +cursor-text = 181926 +selection-background = 3a3e53 +selection-foreground = cad3f5 diff --git a/nate-work/dotfiles/ghostty/themes/catppuccin-mocha.conf b/nate-work/dotfiles/ghostty/themes/catppuccin-mocha.conf new file mode 100644 index 0000000..57825be --- /dev/null +++ b/nate-work/dotfiles/ghostty/themes/catppuccin-mocha.conf @@ -0,0 +1,22 @@ +palette = 0=#45475a +palette = 1=#f38ba8 +palette = 2=#a6e3a1 +palette = 3=#f9e2af +palette = 4=#89b4fa +palette = 5=#f5c2e7 +palette = 6=#94e2d5 +palette = 7=#a6adc8 +palette = 8=#585b70 +palette = 9=#f38ba8 +palette = 10=#a6e3a1 +palette = 11=#f9e2af +palette = 12=#89b4fa +palette = 13=#f5c2e7 +palette = 14=#94e2d5 +palette = 15=#bac2de +background = 1e1e2e +foreground = cdd6f4 +cursor-color = f5e0dc +cursor-text = 11111b +selection-background = 353749 +selection-foreground = cdd6f4 diff --git a/nate-work/dotfiles/helix/config.toml b/nate-work/dotfiles/helix/config.toml index 2d6cdc0..73bfcba 100644 --- a/nate-work/dotfiles/helix/config.toml +++ b/nate-work/dotfiles/helix/config.toml @@ -47,6 +47,8 @@ C-n = "select_next_sibling" "@" = ":append-output git config get user.email" [keys.normal.space] +# Git blame for line +B = ":sh git log -n 5 --format='format:%%h (%%an: %%ar) %%s' --no-patch -L%{cursor_line},+1:%{buffer_name}" x = ":write-buffer-close" X = ":write-quit-all" o = ":config-open" diff --git a/nate-work/dotfiles/waybar/config b/nate-work/dotfiles/waybar/config index a538a40..6509e30 100644 --- a/nate-work/dotfiles/waybar/config +++ b/nate-work/dotfiles/waybar/config @@ -36,6 +36,7 @@ "custom/keyboard-layout", "battery", "backlight", + "custom/neewer", "tray", //"custom/weather", "custom/power", @@ -248,6 +249,18 @@ "min-brightness": 1 }, + // Add this configuration block + "custom/neewer": { + "format": "{}", + "return-type": "json", + "exec": "~/nixos/nate-work/dotfiles/waybar/scripts/waybar-neewer.sh status", + "interval": 10, + "on-click-middle": "~/nixos/nate-work/dotfiles/waybar/scripts/waybar-neewer.sh toggle", + "on-click": "~/nixos/nate-work/dotfiles/waybar/scripts/waybar-neewer.sh decrease", + "on-click-right": "~/nixos/nate-work/dotfiles/waybar/scripts/waybar-neewer.sh increase", + "tooltip": true + }, + "custom/storage": { "format": "{icon} {percentage}%", "format-icons": { diff --git a/nate-work/dotfiles/waybar/scripts/neweer_light.py b/nate-work/dotfiles/waybar/scripts/neweer_light.py new file mode 100755 index 0000000..3dca6e7 --- /dev/null +++ b/nate-work/dotfiles/waybar/scripts/neweer_light.py @@ -0,0 +1,231 @@ +#!/usr/bin/env python3 +""" +NEEWER FS230B LED Light Control SDK +Based on reverse-engineered protocol from similar NEEWER models +""" + +import asyncio +import struct +from bleak import BleakClient, BleakScanner +from typing import Optional, List, Tuple +import logging + +# NEEWER BLE Service/Characteristic UUIDs (based on RGB660 PRO reverse engineering) +SERVICE_UUID = "69400001-b5a3-f393-e0a9-e50e-24dc-ca99" +CHARACTERISTIC_UUID = "69400002-b5a3-f393-e0a9-e50e-24dc-ca99" + +class NeewerFS230B: + """Control class for NEEWER FS230B LED Light""" + + def __init__(self, mac_address: str = None): + """ + Initialize the NEEWER light controller + + Args: + mac_address: Bluetooth MAC address of the light. If None, will scan for devices. + """ + self.mac_address = mac_address + self.client = None + self.is_connected = False + self.logger = logging.getLogger(__name__) + + async def scan_for_devices(self, timeout: int = 10) -> List[Tuple[str, str]]: + """ + Scan for NEEWER devices + + Returns: + List of tuples containing (mac_address, device_name) + """ + devices = [] + scanner = BleakScanner() + + self.logger.info(f"Scanning for NEEWER devices for {timeout} seconds...") + discovered_devices = await scanner.discover(timeout=timeout) + + for device in discovered_devices: + # Look for NEEWER devices by name patterns + if device.name and any(keyword in device.name.upper() for keyword in + ["NEEWER", "FS230", "NW"]): + devices.append((device.address, device.name)) + self.logger.info(f"Found NEEWER device: {device.name} ({device.address})") + + return devices + + async def connect(self) -> bool: + """ + Connect to the NEEWER light + + Returns: + True if connected successfully, False otherwise + """ + if not self.mac_address: + devices = await self.scan_for_devices() + if not devices: + self.logger.error("No NEEWER devices found") + return False + self.mac_address = devices[0][0] + self.logger.info(f"Using first found device: {self.mac_address}") + + try: + self.client = BleakClient(self.mac_address) + await self.client.connect() + self.is_connected = True + self.logger.info(f"Connected to NEEWER light at {self.mac_address}") + return True + except Exception as e: + self.logger.error(f"Failed to connect: {e}") + return False + + async def disconnect(self): + """Disconnect from the light""" + if self.client and self.is_connected: + await self.client.disconnect() + self.is_connected = False + self.logger.info("Disconnected from NEEWER light") + + def _calculate_checksum(self, data: List[int]) -> int: + """Calculate checksum for command (sum truncated to last byte)""" + return sum(data) & 0xFF + + async def _send_command(self, command: List[int]) -> bool: + """ + Send a command to the light + + Args: + command: List of integers representing the command bytes + + Returns: + True if command sent successfully + """ + if not self.is_connected or not self.client: + self.logger.error("Not connected to device") + return False + + try: + # Add checksum to command + checksum = self._calculate_checksum(command) + full_command = command + [checksum] + + # Convert to bytes + command_bytes = bytes(full_command) + + self.logger.debug(f"Sending command: {command_bytes.hex()}") + await self.client.write_gatt_char(CHARACTERISTIC_UUID, command_bytes) + return True + except Exception as e: + self.logger.error(f"Failed to send command: {e}") + return False + + async def set_power(self, on: bool) -> bool: + """ + Turn the light on or off + + Args: + on: True to turn on, False to turn off + + Returns: + True if command sent successfully + """ + # Power command format: [0x78, 0x81, 0x01, on_off_byte] + # On = 0x01, Off = 0x02 + command = [0x78, 0x81, 0x01, 0x01 if on else 0x02] + return await self._send_command(command) + + async def set_brightness_and_temperature(self, brightness: int, temperature: int) -> bool: + """ + Set brightness and color temperature + + Args: + brightness: 0-100 (percentage) + temperature: 3200-5600 (Kelvin) for bi-color models + + Returns: + True if command sent successfully + """ + # Validate inputs + brightness = max(0, min(100, brightness)) + temperature = max(3200, min(5600, temperature)) + + # Convert temperature to protocol value (3200K = 0x20, 5600K = 0x38) + temp_value = int(((temperature - 3200) / (5600 - 3200)) * (0x38 - 0x20) + 0x20) + + # CCT command format: [0x78, 0x87, 0x02, brightness, temp_value] + command = [0x78, 0x87, 0x02, brightness, temp_value] + return await self._send_command(command) + + async def set_brightness(self, brightness: int) -> bool: + """ + Set brightness only (maintains current color temperature) + + Args: + brightness: 0-100 (percentage) + + Returns: + True if command sent successfully + """ + # Default to 5600K (daylight) if no temperature specified + return await self.set_brightness_and_temperature(brightness, 5600) + + +# CLI Interface +async def main(): + """Simple CLI for testing the SDK""" + import argparse + + parser = argparse.ArgumentParser(description="Control NEEWER FS230B LED Light") + parser.add_argument("--mac", help="Bluetooth MAC address of the light") + parser.add_argument("--scan", action="store_true", help="Scan for NEEWER devices") + parser.add_argument("--on", action="store_true", help="Turn light on") + parser.add_argument("--off", action="store_true", help="Turn light off") + parser.add_argument("--brightness", type=int, help="Set brightness (0-100)") + parser.add_argument("--temperature", type=int, help="Set color temperature (3200-5600K)") + parser.add_argument("--verbose", "-v", action="store_true", help="Enable verbose logging") + + args = parser.parse_args() + + if args.verbose: + logging.basicConfig(level=logging.DEBUG) + else: + logging.basicConfig(level=logging.INFO) + + light = NeewerFS230B(args.mac) + + if args.scan: + devices = await light.scan_for_devices() + if devices: + print("Found NEEWER devices:") + for mac, name in devices: + print(f" {name}: {mac}") + else: + print("No NEEWER devices found") + return + + # Connect to the light + if not await light.connect(): + print("Failed to connect to light") + return + + try: + # Execute commands + if args.on: + success = await light.set_power(True) + print(f"Turn on: {'Success' if success else 'Failed'}") + + if args.off: + success = await light.set_power(False) + print(f"Turn off: {'Success' if success else 'Failed'}") + + if args.brightness is not None: + if args.temperature: + success = await light.set_brightness_and_temperature(args.brightness, args.temperature) + print(f"Set brightness {args.brightness}% and temperature {args.temperature}K: {'Success' if success else 'Failed'}") + else: + success = await light.set_brightness(args.brightness) + print(f"Set brightness {args.brightness}%: {'Success' if success else 'Failed'}") + + finally: + await light.disconnect() + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/nate-work/dotfiles/waybar/scripts/power-menu.sh b/nate-work/dotfiles/waybar/scripts/power-menu.sh index 02fb20f..39ff617 100755 --- a/nate-work/dotfiles/waybar/scripts/power-menu.sh +++ b/nate-work/dotfiles/waybar/scripts/power-menu.sh @@ -1,12 +1,12 @@ #!/usr/bin/env bash -entries="Logout Suspend Reboot Shutdown" +entries="Lock Suspend Reboot Shutdown" selected=$(printf '%s\n' $entries | wofi --conf=$HOME/.config/wofi/config.power --style=$HOME/.config/wofi/style.widgets.css | awk '{print tolower($1)}') case $selected in - logout) - swaymsg exit;; + lock) + swaylock;; suspend) exec systemctl suspend;; reboot) diff --git a/nate-work/dotfiles/waybar/scripts/waybar-neewer.sh b/nate-work/dotfiles/waybar/scripts/waybar-neewer.sh new file mode 100755 index 0000000..03bf2b5 --- /dev/null +++ b/nate-work/dotfiles/waybar/scripts/waybar-neewer.sh @@ -0,0 +1,99 @@ +#!/usr/bin/env bash + +NEEWER_SDK_PATH="./nate-work/dotfiles/waybar/scripts/neweer_light.py" +NEEWER_MAC="CB:33:40:DF:63:44" +STATE_FILE="$HOME/.cache/neewer_light_state" +BRIGHTNESS_FILE="$HOME/.cache/neewer_brightness" + +# Function to get current brightness from cache +get_brightness() { + if [ -f "$BRIGHTNESS_FILE" ]; then + cat "$BRIGHTNESS_FILE" + else + echo "20" # Default brightness + fi +} + +# Function to save brightness to cache +save_brightness() { + echo "$1" > "$BRIGHTNESS_FILE" +} + +# Function to get current power state +get_power_state() { + if [ -f "$STATE_FILE" ]; then + cat "$STATE_FILE" + else + echo "off" # Default state + fi +} + +# Function to save power state +save_power_state() { + echo "$1" > "$STATE_FILE" +} + +# Function to execute neewer command +execute_neewer() { + local cmd="$1" + if [ -n "$NEEWER_MAC" ]; then + python3 "$NEEWER_SDK_PATH" --mac "$NEEWER_MAC" $cmd + else + python3 "$NEEWER_SDK_PATH" $cmd + fi +} + +# Main function for waybar output +waybar_output() { + local state=$(get_power_state) + local brightness=$(get_brightness) + + if [ "$state" = "on" ]; then + echo "{\"text\":\"󱣝 ${brightness}%\",\"class\":\"on\",\"tooltip\":\"NEEWER Light: ON (${brightness}%)\"}" + else + echo "{\"text\":\"󱣞 OFF\",\"class\":\"off\",\"tooltip\":\"NEEWER Light: OFF\"}" + fi +} + +# Handle different commands +case "$1" in + "toggle") + state=$(get_power_state) + if [ "$state" = "on" ]; then + execute_neewer "--off" && save_power_state "off" + else + execute_neewer "--on" && save_power_state "on" + fi + ;; + "on") + execute_neewer "--on" && save_power_state "on" + ;; + "off") + execute_neewer "--off" && save_power_state "off" + ;; + "brightness") + if [ -n "$2" ]; then + brightness="$2" + execute_neewer "--brightness $brightness" && save_brightness "$brightness" + fi + ;; + "increase") + current=$(get_brightness) + new_brightness=$((current + 10)) + if [ $new_brightness -gt 100 ]; then + new_brightness=100 + fi + execute_neewer "--brightness $new_brightness" && save_brightness "$new_brightness" + ;; + "decrease") + current=$(get_brightness) + new_brightness=$((current - 10)) + if [ $new_brightness -lt 0 ]; then + new_brightness=0 + fi + execute_neewer "--brightness $new_brightness" && save_brightness "$new_brightness" + ;; + "status"|*) + waybar_output + ;; +esac diff --git a/nate-work/modules/home-manager/home.nix b/nate-work/modules/home-manager/home.nix index c169a86..fd2fc93 100644 --- a/nate-work/modules/home-manager/home.nix +++ b/nate-work/modules/home-manager/home.nix @@ -135,6 +135,8 @@ htop neofetch s-tui + openapi-tui + tasktimer # Normies unzip llpp @@ -167,7 +169,8 @@ kdePackages.filelight hugo unstable.llama-cpp - + unstable.davinci-resolve-studio + # # Style # @@ -216,15 +219,15 @@ merge = { conflictStyle="zdiff3"; }; pull = { ff = "only"; }; push = { autoSetupRemote="true"; }; + # Vasion rewrite rule url = { - "git@github.com" = { + "git@github.com:" = { insteadOf = "https://github.com/"; }; }; }; delta = { enable = true; - navigate = true; options = { side-by-side = true; hyperlinks = true; diff --git a/nate-work/modules/hypr/hypr_home.nix b/nate-work/modules/hypr/hypr_home.nix index d45dfe4..bd7773f 100644 --- a/nate-work/modules/hypr/hypr_home.nix +++ b/nate-work/modules/hypr/hypr_home.nix @@ -1,7 +1,7 @@ { inputs, lib, config, pkgs, ... }: -let +# let # unstable = import inputs.nixpkgs-unstable { system = "x86_64-linux"; config.allowUnfree = true; }; -in +# in { options.hyprhome = { enable = lib.mkEnableOption "Enable hyprland home config"; @@ -25,22 +25,24 @@ in [ ###Start dbus ### # Starting it early may help with app launch times - "systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP" "dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP" - # - "swaylock -C ~/.config/swaylock/boot-config" - "swaybg -i ~/.config/hypr/va_background.png" - "waybar" - "nm-applet --indicator" + "systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP" + # Utils "blueman-applet" "hypridle" - "sleep 5 && syncthingtray --wait" "lxqt-policykit-agent" - # May need to kill mako if nwg-panel starts it + "nm-applet --indicator" + "sleep 5 && syncthingtray --wait" # sleep added otherwise it would error... + "swaybg -i ~/.config/hypr/va_background.png" + "swaylock -C ~/.config/swaylock/boot-config" "swaync" - "keepassxc" + "waybar" + # GUI Applications + "firefox --new-tab https://vasion.okta.com --new-tab https://github.com/PrinterLogic --new-tab https://claude.ai" "flatpak run org.signal.Signal" "flatpak run com.slack.Slack" + "ghostty" + "keepassxc" # set gsettings # "dconf write /org/gnome/desktop/interface/cursor-theme \"'catppuccin-macchiato-lavender-cursors'\"" # "dconf write /org/gnome/desktop/interface/cursor-size 24" @@ -63,9 +65,9 @@ in animation = [ "workspaces, 1, 1, easeout" ]; - gestures = { - workspace_swipe = true; - }; + gesture = [ + "3, horizontal, workspace" + ]; general = { gaps_in = 3; gaps_out = 5; diff --git a/nate-work/modules/hypr/hyprland.nix b/nate-work/modules/hypr/hyprland.nix index 9b050d7..e0717cc 100644 --- a/nate-work/modules/hypr/hyprland.nix +++ b/nate-work/modules/hypr/hyprland.nix @@ -128,7 +128,8 @@ in programs.regreet.enable = true; programs.zsh.enable = true; programs.ssh.startAgent = true; - + programs.steam.enable = true; + programs.wshowkeys.enable = true; services.printing = { enable = true; browsing = true; @@ -208,12 +209,12 @@ in settings = { General = { Name = "Nate-Vasion"; - ControlleMode = "dual"; + ControllerMode = "dual"; FastConnectable = "true"; Experimental = "true"; }; Policy = { AutoEnable = "true"; }; - LE = { EnableAdvMonInterleaveScan = "true"; }; + LE = { EnableAdvMonInterleaveScan = 1; }; }; }; # diff --git a/nate/dotfiles/ghostty/config b/nate/dotfiles/ghostty/config index 62d9fad..517f906 100644 --- a/nate/dotfiles/ghostty/config +++ b/nate/dotfiles/ghostty/config @@ -1,4 +1,4 @@ -theme = "catppuccin-macchiato" +theme = "catppuccin-macchiato.conf" ### # Font config