Unverified Commit fe460b77 authored by Cabia Rangris's avatar Cabia Rangris Committed by GitHub
Browse files

nixos/klipper: Expose firmware and flasher packages in config (#432658)

parents 21f7946c f72f1eb0
Loading
Loading
Loading
Loading
+88 −63
Original line number Diff line number Diff line
@@ -16,6 +16,68 @@ let
        lib.concatMapStrings (s: "\n  ${lib.generators.mkValueStringDefault { } s}") l;
    mkKeyValue = lib.generators.mkKeyValueDefault { } ":";
  };
  firmwareSubmodule = lib.types.submodule (
    { name, ... }@local:
    let
      mcu = local.name;
      subcfg = local.config;
    in
    {
      options = {
        enable = lib.mkEnableOption ''
          building of firmware for manual flashing
        '';
        enableKlipperFlash = lib.mkEnableOption ''
          flashings scripts for firmware. This will add `klipper-flash-$mcu` scripts to your environment which can be called to flash the firmware.
          Please check the configs at [klipper](https://github.com/Klipper3d/klipper/tree/master/config) whether your board supports flashing via `make flash`
        '';
        serial = lib.mkOption {
          type = lib.types.nullOr lib.types.path;
          description = "Path to serial port this printer is connected to. Derived from `service.klipper.settings` by default.";
          defaultText = lib.literalExpression "config.services.klipper.settings.<name>.serial";
          default =
            if lib.hasAttrByPath [ "${mcu}" "serial" ] cfg.settings then cfg.settings."${mcu}".serial else null;
        };
        configFile = lib.mkOption {
          type = lib.types.path;
          description = "Path to firmware config which is generated using `klipper-genconf`";
        };
        package = lib.mkOption {
          type = lib.types.nullOr lib.types.package;
          readOnly = true;
          description = "Path to the built firmware package.";
        };
        klipperFlashPackage = lib.mkOption {
          type = lib.types.nullOr lib.types.package;
          readOnly = true;
          description = "Path to the built klipper-flash package.";
        };
      };
      config = {
        package =
          if subcfg.enable then
            pkgs.klipper-firmware.override {
              klipper = cfg.package;
              mcu = lib.strings.sanitizeDerivationName mcu;
              firmwareConfig = subcfg.configFile;
            }
          else
            null;

        klipperFlashPackage =
          if subcfg.enable && subcfg.enableKlipperFlash then
            pkgs.klipper-flash.override {
              klipper = cfg.package;
              klipper-firmware = subcfg.package;
              mcu = lib.strings.sanitizeDerivationName mcu;
              flashDevice = subcfg.serial;
              firmwareConfig = subcfg.configFile;
            }
          else
            null;
      };
    }
  );
in
{
  imports = [
@@ -119,30 +181,17 @@ in
      };

      firmwares = lib.mkOption {
        description = "Firmwares klipper should manage";
        description = "Firmwares Klipper should manage";
        default = { };
        type =
          with lib.types;
          attrsOf (submodule {
            options = {
              enable = lib.mkEnableOption ''
                building of firmware for manual flashing
              '';
              enableKlipperFlash = lib.mkEnableOption ''
                flashings scripts for firmware. This will add `klipper-flash-$mcu` scripts to your environment which can be called to flash the firmware.
                Please check the configs at [klipper](https://github.com/Klipper3d/klipper/tree/master/config) whether your board supports flashing via `make flash`
              '';
              serial = lib.mkOption {
                type = lib.types.nullOr path;
                default = null;
                description = "Path to serial port this printer is connected to. Leave `null` to derive it from `service.klipper.settings`.";
              };
              configFile = lib.mkOption {
                type = path;
                description = "Path to firmware config which is generated using `klipper-genconf`";
        type = lib.types.attrsOf firmwareSubmodule;
        example = {
          mcu = {
            enable = true;
            enableKlipperFlash = true;
            serial = "/dev/serial/by-id/usb-Klipper_123ABCDEF";
            configFile = lib.literalExpression "./klipper-firmware.cfg";
          };
        };
          });
      };
    };
  };
@@ -158,16 +207,6 @@ in
        assertion = cfg.user != null -> cfg.group != null;
        message = "Option services.klipper.group is not set when services.klipper.user is specified.";
      }
      {
        assertion =
          cfg.settings != null
          -> lib.foldl (a: b: a && b) true (
            lib.mapAttrsToList (
              mcu: _: mcu != null -> (lib.hasAttrByPath [ "${mcu}" "serial" ] cfg.settings)
            ) cfg.firmwares
          );
        message = "Option services.klipper.settings.$mcu.serial must be set when settings.klipper.firmware.$mcu is specified";
      }
      {
        assertion = (cfg.configFile != null) != (cfg.settings != null);
        message = "You need to either specify services.klipper.settings or services.klipper.configFile.";
@@ -176,7 +215,16 @@ in
        assertion = (cfg.configFile != null) -> (cfg.extraSettings == "");
        message = "You can't use services.klipper.extraSettings with services.klipper.configFile.";
      }
    ];
    ]
    ++ lib.mapAttrsToList (mcu: firmware: {
      assertion = firmware.enable -> firmware.serial != null;
      message = ''
        Unable to determine the serial connection for services.klipper.firmwares."${mcu}". Please set one of the following:

          - services.klipper.firmwares."${mcu}".serial
          - services.klipper.settings."${mcu}".serial
      '';
    }) cfg.firmwares;

    services.klipper = lib.mkIf cfg.octoprintIntegration {
      user = config.services.octoprint.user;
@@ -257,37 +305,14 @@ in
        genconf = pkgs.klipper-genconf.override {
          klipper = cfg.package;
        };
        firmwares = lib.filterAttrs (n: v: v != null) (
          lib.mapAttrs (
            mcu:
            {
              enable,
              enableKlipperFlash,
              configFile,
              serial,
            }:
            if enable then
              pkgs.klipper-firmware.override {
                klipper = cfg.package;
                mcu = lib.strings.sanitizeDerivationName mcu;
                firmwareConfig = configFile;
              }
            else
              null
          ) cfg.firmwares
        firmwares = lib.filter (v: v != null) (
          lib.mapAttrsToList (mcu: firmware: firmware.package) cfg.firmwares
        );
        firmwareFlashers = lib.filter (v: v != null) (
          lib.mapAttrsToList (mcu: firmware: firmware.klipperFlashPackage) cfg.firmwares
        );
        firmwareFlasher = lib.mapAttrsToList (
          mcu: firmware:
          pkgs.klipper-flash.override {
            klipper = cfg.package;
            klipper-firmware = firmware;
            mcu = lib.strings.sanitizeDerivationName mcu;
            flashDevice = default cfg.firmwares."${mcu}".serial cfg.settings."${mcu}".serial;
            firmwareConfig = cfg.firmwares."${mcu}".configFile;
          }
        ) (lib.filterAttrs (mcu: firmware: cfg.firmwares."${mcu}".enableKlipperFlash) firmwares);
      in
      [ genconf ] ++ firmwareFlasher ++ lib.attrValues firmwares;
      [ genconf ] ++ firmwares ++ firmwareFlashers;
  };
  meta.maintainers = [
    lib.maintainers.cab404