diff --git a/hosts/pianonix/default.nix b/hosts/pianonix/default.nix index d2c4f0e..8db15ea 100644 --- a/hosts/pianonix/default.nix +++ b/hosts/pianonix/default.nix @@ -88,6 +88,9 @@ enable = true; overrideSettings = true; }; + pianoLEDVisualizer = { + enable = true; + }; }; # Enable the Desktop Environment. @@ -196,4 +199,39 @@ # boot.loader.raspberryPi.firmwareConfig = '' # dtparam=audio=on # ''; + + ## Enable SPI + hardware.raspberry-pi."4".apply-overlays-dtmerge.enable = true; + hardware.deviceTree = { + enable = true; + filter = "*-rpi-*.dtb"; + overlays = [ + { + name = "spi"; + dtsoFile = ./spi0-0cd.dtso; + } + ]; + }; + + users.groups.spi = {}; + + # services.udev.extraRules = '' + # SUBSYSTEM=="spidev", KERNEL=="spidev0.0", GROUP="spi", MODE="0660" + # ''; + + ## Use GPIO as non-root + # Create gpio group + users.groups.gpio = {}; + + # Change permissions gpio devices + services.udev.extraRules = '' + SUBSYSTEM=="spidev", KERNEL=="spidev0.0", GROUP="spi", MODE="0660" + + SUBSYSTEM=="bcm2835-gpiomem", KERNEL=="gpiomem", GROUP="gpio",MODE="0660" + SUBSYSTEM=="gpio", KERNEL=="gpiochip*", ACTION=="add", RUN+="${pkgs.bash}/bin/bash -c 'chown root:gpio /sys/class/gpio/export /sys/class/gpio/unexport ; chmod 220 /sys/class/gpio/export /sys/class/gpio/unexport'" + SUBSYSTEM=="gpio", KERNEL=="gpio*", ACTION=="add",RUN+="${pkgs.bash}/bin/bash -c 'chown root:gpio /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value ; chmod 660 /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value'" + ''; + + # Add user to group + users.users.julian.extraGroups = ["gpio"]; } diff --git a/hosts/pianonix/spi0-0cs.dtbo b/hosts/pianonix/spi0-0cs.dtbo new file mode 100644 index 0000000..8b20ab7 Binary files /dev/null and b/hosts/pianonix/spi0-0cs.dtbo differ diff --git a/modules/nixos/default.nix b/modules/nixos/default.nix index db58c58..6fa5fbc 100644 --- a/modules/nixos/default.nix +++ b/modules/nixos/default.nix @@ -2,4 +2,5 @@ # hydra-auto-upgrade = import ./hydra-auto-upgrade.nix; syncthing = import ./syncthing.nix; frajulAutoUpgrade = import ./frajul-auto-upgrade.nix; + pianoLEDVisualizer = import ./piano-led-visualizer.nix; } diff --git a/modules/nixos/piano-led-visualizer.nix b/modules/nixos/piano-led-visualizer.nix new file mode 100644 index 0000000..bb48e64 --- /dev/null +++ b/modules/nixos/piano-led-visualizer.nix @@ -0,0 +1,47 @@ +{ + config, + lib, + pkgs, + ... +}: let + cfg = config.services.piano-led-visualizer; +in { + options.services.piano-led-visualizer = { + enable = lib.mkEnableOption "Enable Piano LED Visualizer"; + + user = lib.mkOption { + type = lib.types.str; + default = "plv"; + description = "User to run the Piano LED Visualizer service."; + }; + + group = lib.mkOption { + type = lib.types.str; + default = "plv"; + description = "Group to run the Piano LED Visualizer service."; + }; + }; + + config = lib.mkIf cfg.enable { + users.users.${cfg.user} = { + isSystemUser = true; + group = cfg.group; + }; + users.groups.${cfg.group} = {}; + + systemd.services.piano-led-visualizer = { + description = "Piano LED Visualizer"; + after = ["network-online.target"]; + wants = ["network-online.target"]; + wantedBy = ["multi-user.target"]; + + serviceConfig = { + ExecStart = "${pkgs.frajul.piano-led-visualizer}/bin/piano-led-visualizer"; + Restart = "always"; + Type = "simple"; + User = cfg.user; + Group = cfg.group; + }; + }; + }; +} diff --git a/pkgs/default.nix b/pkgs/default.nix index 8050149..e3e231d 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -14,4 +14,5 @@ wl-ocr = pkgs.callPackage ./wl-ocr {}; rtklib = pkgs.qt6Packages.callPackage ./rtklib {}; pob2-frajul = pkgs.callPackage ./pob2-frajul {}; + piano-led-visualizer = pkgs.callPackage ./piano-led-visualizer {}; } diff --git a/pkgs/piano-led-visualizer/default.nix b/pkgs/piano-led-visualizer/default.nix new file mode 100644 index 0000000..915a90f --- /dev/null +++ b/pkgs/piano-led-visualizer/default.nix @@ -0,0 +1,60 @@ +{ + lib, + python3, + fetchFromGitHub, + ... +}: let + pythonPackages = python3.pkgs; +in + pythonPackages.buildPythonApplication rec { + pname = "piano-led-visualizer"; + version = "1.6"; + + src = fetchFromGitHub { + owner = "onlaj"; + repo = "Piano-LED-Visualizer"; + rev = "v${version}"; + sha256 = "sha256-SkNNu2pqVG40HBZZYJMCCKiRj1h1QdkteaPR3Ek2P7I="; + }; + + patches = [ + ./fix-log-dir.patch + ]; + + propagatedBuildInputs = with pythonPackages; [ + setuptools + + numpy + pillow + flask + rpi-gpio + webcolors + psutil + mido + rtmidi-python + spidev + waitress + websockets + werkzeug + # rpi_ws281x + ]; + + format = "setuptools"; + + preBuild = '' + cp ${./setup.py} setup.py + sed -i 's/PLACEHOLDER_VERSION/${version}/' setup.py + ''; + + postInstall = '' + mv -v $out/bin/visualizer.py $out/bin/piano-led-visualizer + ''; + + meta = with lib; { + description = "Piano LED Visualizer for Raspberry Pi"; + homepage = "https://github.com/onlaj/Piano-LED-Visualizer"; + license = licenses.gpl3; + maintainers = []; + platforms = platforms.linux; + }; + } diff --git a/pkgs/piano-led-visualizer/fix-log-dir.patch b/pkgs/piano-led-visualizer/fix-log-dir.patch new file mode 100644 index 0000000..e839883 --- /dev/null +++ b/pkgs/piano-led-visualizer/fix-log-dir.patch @@ -0,0 +1,24 @@ +diff --git a/lib/log_setup.py b/lib/log_setup.py +index 34f9156..e164d14 100644 +--- a/lib/log_setup.py ++++ b/lib/log_setup.py +@@ -1,6 +1,7 @@ + import logging + from logging.handlers import RotatingFileHandler + import sys ++import os + + # Create a custom logger + logger = logging.getLogger("my_app") +@@ -10,7 +11,10 @@ logger.setLevel(logging.DEBUG) + + # Create handlers + console_handler = logging.StreamHandler() +-file_handler = RotatingFileHandler('/home/Piano-LED-Visualizer/visualizer.log', maxBytes=500000, backupCount=10) ++ ++log_path = os.path.expanduser('~/Piano-LED-Visualizer/visualizer.log') ++os.makedirs(os.path.dirname(log_path), exist_ok=True) ++file_handler = RotatingFileHandler(log_path, maxBytes=500000, backupCount=10) + + + # Set the level for handlers diff --git a/pkgs/piano-led-visualizer/setup.py b/pkgs/piano-led-visualizer/setup.py new file mode 100644 index 0000000..6783da5 --- /dev/null +++ b/pkgs/piano-led-visualizer/setup.py @@ -0,0 +1,24 @@ +from setuptools import setup, find_packages + +setup( + name="piano_led_visualizer", + version="PLACEHOLDER_VERSION", + py_modules=["visualizer"], + packages=find_packages(), # includes all packages with __init__.py + install_requires=[ + "numpy", + "pillow", + "flask", + "rpi-gpio", + "webcolors", + "psutil", + "mido", + "rtmidi", + "spidev", + "waitress", + "websockets", + "werkzeug", + "rpi_ws281x", + ], + scripts=["visualizer.py"], +)