From 6a5b8390695068823f80131be4801297d963880e Mon Sep 17 00:00:00 2001 From: Michal Sojka Date: Tue, 29 Mar 2022 23:54:42 +0200 Subject: [PATCH] usbrelay: init at 0.9 --- nixos/modules/module-list.nix | 1 + nixos/modules/services/hardware/usbrelayd.nix | 44 +++++++++++++ pkgs/os-specific/linux/usbrelay/daemon.nix | 36 +++++++++++ pkgs/os-specific/linux/usbrelay/default.nix | 29 +++++++++ pkgs/os-specific/linux/usbrelay/python.nix | 12 ++++ pkgs/os-specific/linux/usbrelay/test.nix | 63 +++++++++++++++++++ pkgs/top-level/all-packages.nix | 3 + pkgs/top-level/python-packages.nix | 2 + 8 files changed, 190 insertions(+) create mode 100644 nixos/modules/services/hardware/usbrelayd.nix create mode 100644 pkgs/os-specific/linux/usbrelay/daemon.nix create mode 100644 pkgs/os-specific/linux/usbrelay/default.nix create mode 100644 pkgs/os-specific/linux/usbrelay/python.nix create mode 100644 pkgs/os-specific/linux/usbrelay/test.nix diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 71c84fbe6b4b..4dfeaa4ecdc9 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -457,6 +457,7 @@ ./services/hardware/udisks2.nix ./services/hardware/upower.nix ./services/hardware/usbmuxd.nix + ./services/hardware/usbrelayd.nix ./services/hardware/thermald.nix ./services/hardware/undervolt.nix ./services/hardware/vdr.nix diff --git a/nixos/modules/services/hardware/usbrelayd.nix b/nixos/modules/services/hardware/usbrelayd.nix new file mode 100644 index 000000000000..c0322e89e6b1 --- /dev/null +++ b/nixos/modules/services/hardware/usbrelayd.nix @@ -0,0 +1,44 @@ +{ config, lib, pkgs, ... }: +with lib; +let + cfg = config.services.usbrelayd; +in +{ + options.services.usbrelayd = with types; { + enable = mkEnableOption "USB Relay MQTT daemon"; + + broker = mkOption { + type = str; + description = "Hostname or IP address of your MQTT Broker."; + default = "127.0.0.1"; + example = [ + "mqtt" + "192.168.1.1" + ]; + }; + + clientName = mkOption { + type = str; + description = "Name, your client connects as."; + default = "MyUSBRelay"; + }; + }; + + config = mkIf cfg.enable { + + # TODO: Rename to .conf in upcomming release + environment.etc."usbrelayd.ini".text = '' + [MQTT] + BROKER = ${cfg.broker} + CLIENTNAME = ${cfg.clientName} + ''; + + services.udev.packages = [ pkgs.usbrelayd ]; + systemd.packages = [ pkgs.usbrelayd ]; + users.users.usbrelay = { + isSystemUser = true; + group = "usbrelay"; + }; + users.groups.usbrelay = { }; + }; +} diff --git a/pkgs/os-specific/linux/usbrelay/daemon.nix b/pkgs/os-specific/linux/usbrelay/daemon.nix new file mode 100644 index 000000000000..5f8d23e5201d --- /dev/null +++ b/pkgs/os-specific/linux/usbrelay/daemon.nix @@ -0,0 +1,36 @@ +{ stdenv, usbrelay, python3 }: +let + python = python3.withPackages (ps: with ps; [ usbrelay-py paho-mqtt ]); +in +# This is a separate derivation, not just an additional output of +# usbrelay, because otherwise, we have a cyclic dependency between +# usbrelay (default.nix) and the python module (python.nix). +stdenv.mkDerivation rec { + pname = "usbrelayd"; + + inherit (usbrelay) src version; + + postPatch = '' + substituteInPlace 'usbrelayd.service' \ + --replace '/usr/bin/python3' "${python}/bin/python3" \ + --replace '/usr/sbin/usbrelayd' "$out/bin/usbrelayd" + ''; + + buildInputs = [ python ]; + + dontBuild = true; + + installPhase = '' + runHook preInstall; + install -m 644 -D usbrelayd $out/bin/usbrelayd + install -m 644 -D usbrelayd.service $out/lib/systemd/system/usbrelayd.service + install -m 644 -D 50-usbrelay.rules $out/lib/udev/rules.d/50-usbrelay.rules + runHook postInstall + ''; + # TODO for later releases: install -D usbrelayd.conf $out/etc/usbrelayd.conf # include this as an example + + meta = { + description = "USB Relay MQTT service"; + inherit (usbrelay.meta) homepage license maintainers platforms; + }; +} diff --git a/pkgs/os-specific/linux/usbrelay/default.nix b/pkgs/os-specific/linux/usbrelay/default.nix new file mode 100644 index 000000000000..ebbb1dd79228 --- /dev/null +++ b/pkgs/os-specific/linux/usbrelay/default.nix @@ -0,0 +1,29 @@ +{ stdenv, lib, fetchFromGitHub, hidapi }: +stdenv.mkDerivation rec { + pname = "usbrelay"; + version = "0.9"; + + src = fetchFromGitHub { + owner = "darrylb123"; + repo = "usbrelay"; + rev = version; + sha256 = "sha256-bxME4r5W5bZKxMZ/Svi1EenqHKVWIjU6iiKaM8U6lmA="; + }; + + buildInputs = [ + hidapi + ]; + + makeFlags = [ + "DIR_VERSION=${version}" + "PREFIX=${placeholder "out"}" + ]; + + meta = with lib; { + description = "Tool to control USB HID relays"; + homepage = "https://github.com/darrylb123/usbrelay"; + license = licenses.gpl2Plus; + maintainers = with maintainers; [ wentasah ]; + platforms = platforms.linux; + }; +} diff --git a/pkgs/os-specific/linux/usbrelay/python.nix b/pkgs/os-specific/linux/usbrelay/python.nix new file mode 100644 index 000000000000..02d5ac284eda --- /dev/null +++ b/pkgs/os-specific/linux/usbrelay/python.nix @@ -0,0 +1,12 @@ +{ buildPythonPackage, usbrelay }: + +buildPythonPackage rec { + pname = "usbrelay_py"; + inherit (usbrelay) version src; + + buildInputs = [ usbrelay ]; + + pythonImportsCheck = [ "usbrelay_py" ]; + + inherit (usbrelay) meta; +} diff --git a/pkgs/os-specific/linux/usbrelay/test.nix b/pkgs/os-specific/linux/usbrelay/test.nix new file mode 100644 index 000000000000..dc5847558a69 --- /dev/null +++ b/pkgs/os-specific/linux/usbrelay/test.nix @@ -0,0 +1,63 @@ +# NixOS test for usbrelayd +# +# It is not stored in nixos/tests directory, because it requires the +# USB relay connected to the host computer and as such, it cannot be +# run automatically. +# +# Run this test as: +# +# nix-build test.nix -A driverInteractive && ./result/bin/nixos-test-driver --no-interactive +# +# The interactive driver is required because the default +# (non-interactive) driver uses qemu without support for passing USB +# devices to the guest (see +# https://discourse.nixos.org/t/hardware-dependent-nixos-tests/18564 +# for discussion of other alternatives). + +import ../../../../nixos/tests/make-test-python.nix ({ pkgs, ... }: { + name = "usbrelayd"; + + nodes.machine = { + virtualisation.qemu.options = [ + "-device qemu-xhci" + "-device usb-host,vendorid=0x16c0,productid=0x05df" + ]; + services.usbrelayd.enable = true; + systemd.services.usbrelayd = { + after = [ "mosquitto.service" ]; + }; + services.mosquitto = { + enable = true; + listeners = [{ + acl = [ "pattern readwrite #" ]; + omitPasswordAuth = true; + settings.allow_anonymous = true; + }]; + }; + environment.systemPackages = [ + pkgs.usbrelay + pkgs.mosquitto + ]; + documentation.nixos.enable = false; # building nixos manual takes long time + }; + + testScript = '' + if os.waitstatus_to_exitcode(os.system("lsusb -d 16c0:05df")) != 0: + print("No USB relay detected, skipping test") + import sys + sys.exit(2) + machine.start() + # usbrelayd is started by udev when an relay is detected + machine.wait_for_unit("usbrelayd.service") + + stdout = machine.succeed("usbrelay") + relay_id = stdout.split(sep="_")[0] + assert relay_id != "" + import time + time.sleep(1) + machine.succeed(f"mosquitto_pub -h localhost -t cmnd/{relay_id}/1 -m ON") + time.sleep(1) + machine.succeed(f"mosquitto_pub -h localhost -t cmnd/{relay_id}/1 -m OFF") + print("Did you see the relay switching on and off?") + ''; +}) diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index c5312c987727..f3d401ff99bc 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -23515,6 +23515,9 @@ with pkgs; libgcrypt = null; }; + usbrelay = callPackage ../os-specific/linux/usbrelay { }; + usbrelayd = callPackage ../os-specific/linux/usbrelay/daemon.nix { }; + usbtop = callPackage ../os-specific/linux/usbtop { }; usbutils = callPackage ../os-specific/linux/usbutils { }; diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix index dfeb7f84f6aa..2732fb588dc7 100644 --- a/pkgs/top-level/python-packages.nix +++ b/pkgs/top-level/python-packages.nix @@ -10420,6 +10420,8 @@ in { urwid-readline = callPackage ../development/python-modules/urwid-readline { }; + usbrelay-py = callPackage ../os-specific/linux/usbrelay/python.nix { }; + usbtmc = callPackage ../development/python-modules/usbtmc { }; us = callPackage ../development/python-modules/us { };