2024-09-05 21:33:06 -04:00
|
|
|
{
|
|
|
|
config,
|
|
|
|
lib,
|
|
|
|
pkgs,
|
|
|
|
...
|
|
|
|
}: let
|
|
|
|
inherit
|
|
|
|
(lib)
|
|
|
|
concatMapStringsSep
|
|
|
|
converge
|
|
|
|
elem
|
|
|
|
filterAttrsRecursive
|
|
|
|
getExe
|
|
|
|
mapAttrsToList
|
|
|
|
mkForce
|
|
|
|
mkIf
|
|
|
|
mkOption
|
|
|
|
optionalAttrs
|
|
|
|
optionals
|
|
|
|
optionalString
|
|
|
|
types
|
|
|
|
;
|
|
|
|
|
|
|
|
cfg = config.services.esphome;
|
|
|
|
|
|
|
|
stateDir = "/var/lib/private/esphome";
|
|
|
|
esphomeParams =
|
|
|
|
if cfg.enableUnixSocket
|
|
|
|
then "--socket /run/esphome/esphome.sock"
|
|
|
|
else "--address ${cfg.address} --port ${toString cfg.port}";
|
|
|
|
|
|
|
|
format = pkgs.formats.yaml {};
|
|
|
|
|
|
|
|
# Adapted from https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/home-automation/home-assistant.nix
|
|
|
|
mkESPConf = name: cfg: let
|
|
|
|
filteredConfig = converge (filterAttrsRecursive (_: v: ! elem v [null])) cfg;
|
|
|
|
in {
|
|
|
|
name = "${name}.yaml";
|
|
|
|
file = pkgs.runCommandLocal "${name}.yaml" {} ''
|
2024-09-05 22:42:17 -04:00
|
|
|
cp ${format.generate name filteredConfig} $out
|
2024-09-05 21:33:06 -04:00
|
|
|
sed -i -e "s/'\!\([a-z_]\+\) \(.*\)'/\!\1 \2/;s/^\!\!/\!/;" $out
|
|
|
|
sed -i 's/ {}//g' $out
|
2024-09-10 19:10:02 -04:00
|
|
|
sed -i "s/'\"/\"/g" $out
|
|
|
|
sed -i "s/\"'/\"/g" $out
|
2024-09-05 21:33:06 -04:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
in {
|
|
|
|
options.services.esphome = {
|
|
|
|
firmwareConfigs = mkOption {
|
|
|
|
default = {};
|
|
|
|
type = with types; attrsOf anything;
|
|
|
|
};
|
|
|
|
|
2024-09-05 22:42:17 -04:00
|
|
|
secretsFile = mkOption {
|
|
|
|
default = null;
|
|
|
|
type = types.nullOr types.path;
|
|
|
|
};
|
|
|
|
|
2024-09-05 21:33:06 -04:00
|
|
|
deleteUnmanaged = mkOption {
|
|
|
|
default = true;
|
|
|
|
type = types.bool;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
config = mkIf (cfg.enable) {
|
|
|
|
# FIXME: https://github.com/NixOS/nixpkgs/issues/339557
|
|
|
|
systemd.services.esphome = {
|
|
|
|
environment.PLATFORMIO_CORE_DIR = mkForce "${stateDir}/.platformio";
|
|
|
|
|
|
|
|
serviceConfig =
|
|
|
|
(optionalAttrs (cfg.firmwareConfigs != {}) {
|
|
|
|
ExecStartPre = getExe (pkgs.writeShellApplication {
|
|
|
|
name = "esphome-exec-start-pre";
|
|
|
|
|
|
|
|
runtimeInputs = optionals cfg.deleteUnmanaged [
|
|
|
|
pkgs.findutils
|
|
|
|
];
|
|
|
|
|
|
|
|
text = ''
|
|
|
|
if [[ ! -d ${stateDir} ]]; then
|
|
|
|
mkdir -p ${stateDir}
|
|
|
|
fi
|
|
|
|
|
2024-09-05 22:42:17 -04:00
|
|
|
${optionalString (cfg.secretsFile != null) ''cp -f "$(realpath "${cfg.secretsFile}")" ${stateDir}/secrets.yaml''}
|
|
|
|
|
2024-09-05 21:33:06 -04:00
|
|
|
${optionalString cfg.deleteUnmanaged ''find ${stateDir} -name "*.yaml" ! -name "secrets.yaml" -delete''}
|
|
|
|
|
|
|
|
${concatMapStringsSep
|
|
|
|
"\n"
|
|
|
|
(dev: ''cp -f "$(realpath "${dev.file}")" ${stateDir}/"${dev.name}"'')
|
|
|
|
(mapAttrsToList mkESPConf cfg.firmwareConfigs)}
|
|
|
|
'';
|
|
|
|
});
|
|
|
|
})
|
|
|
|
// {
|
|
|
|
ExecStart = mkForce "${cfg.package}/bin/esphome dashboard ${esphomeParams} ${stateDir}";
|
|
|
|
WorkingDirectory = mkForce stateDir;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|