nixos/wyoming/satellite: init
This commit is contained in:
parent
eb4113b79c
commit
e0b4ab1a31
|
@ -126,6 +126,8 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
|
||||||
|
|
||||||
- [armagetronad](https://wiki.armagetronad.org), a mid-2000s 3D lightcycle game widely played at iD Tech Camps. You can define multiple servers using `services.armagetronad.<server>.enable`.
|
- [armagetronad](https://wiki.armagetronad.org), a mid-2000s 3D lightcycle game widely played at iD Tech Camps. You can define multiple servers using `services.armagetronad.<server>.enable`.
|
||||||
|
|
||||||
|
- [wyoming-satellite](https://github.com/rhasspy/wyoming-satellite), a voice assistant satellite for Home Assistant using the Wyoming protocol. Available as [services.wyoming.satellite]($opt-services.wyoming.satellite.enable).
|
||||||
|
|
||||||
- [TuxClocker](https://github.com/Lurkki14/tuxclocker), a hardware control and monitoring program. Available as [programs.tuxclocker](#opt-programs.tuxclocker.enable).
|
- [TuxClocker](https://github.com/Lurkki14/tuxclocker), a hardware control and monitoring program. Available as [programs.tuxclocker](#opt-programs.tuxclocker.enable).
|
||||||
|
|
||||||
- [ALVR](https://github.com/alvr-org/alvr), a VR desktop streamer. Available as [programs.alvr](#opt-programs.alvr.enable)
|
- [ALVR](https://github.com/alvr-org/alvr), a VR desktop streamer. Available as [programs.alvr](#opt-programs.alvr.enable)
|
||||||
|
|
|
@ -588,6 +588,7 @@
|
||||||
./services/home-automation/govee2mqtt.nix
|
./services/home-automation/govee2mqtt.nix
|
||||||
./services/home-automation/home-assistant.nix
|
./services/home-automation/home-assistant.nix
|
||||||
./services/home-automation/matter-server.nix
|
./services/home-automation/matter-server.nix
|
||||||
|
./services/home-automation/wyoming/satellite.nix
|
||||||
./services/home-automation/zigbee2mqtt.nix
|
./services/home-automation/zigbee2mqtt.nix
|
||||||
./services/home-automation/zwave-js.nix
|
./services/home-automation/zwave-js.nix
|
||||||
./services/logging/SystemdJournal2Gelf.nix
|
./services/logging/SystemdJournal2Gelf.nix
|
||||||
|
|
244
nixos/modules/services/home-automation/wyoming/satellite.nix
Normal file
244
nixos/modules/services/home-automation/wyoming/satellite.nix
Normal file
|
@ -0,0 +1,244 @@
|
||||||
|
{ config
|
||||||
|
, lib
|
||||||
|
, pkgs
|
||||||
|
, ...
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.wyoming.satellite;
|
||||||
|
|
||||||
|
inherit (lib)
|
||||||
|
elem
|
||||||
|
escapeShellArgs
|
||||||
|
getExe
|
||||||
|
literalExpression
|
||||||
|
mkOption
|
||||||
|
mkEnableOption
|
||||||
|
mkIf
|
||||||
|
mkPackageOption
|
||||||
|
optional
|
||||||
|
optionals
|
||||||
|
types
|
||||||
|
;
|
||||||
|
|
||||||
|
finalPackage = cfg.package.overridePythonAttrs (oldAttrs: {
|
||||||
|
propagatedBuildInputs = oldAttrs.propagatedBuildInputs
|
||||||
|
# for audio enhancements like auto-gain, noise suppression
|
||||||
|
++ cfg.package.optional-dependencies.webrtc
|
||||||
|
# vad is currently optional, because it is broken on aarch64-linux
|
||||||
|
++ optionals cfg.vad.enable cfg.package.optional-dependencies.silerovad;
|
||||||
|
});
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
meta.buildDocsInSandbox = false;
|
||||||
|
|
||||||
|
options.services.wyoming.satellite = with types; {
|
||||||
|
enable = mkEnableOption "Wyoming Satellite";
|
||||||
|
|
||||||
|
package = mkPackageOption pkgs "wyoming-satellite" { };
|
||||||
|
|
||||||
|
user = mkOption {
|
||||||
|
type = str;
|
||||||
|
example = "alice";
|
||||||
|
description = ''
|
||||||
|
User to run wyoming-satellite under.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
group = mkOption {
|
||||||
|
type = str;
|
||||||
|
default = "users";
|
||||||
|
description = ''
|
||||||
|
Group to run wyoming-satellite under.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
uri = mkOption {
|
||||||
|
type = str;
|
||||||
|
default = "tcp://0.0.0.0:10700";
|
||||||
|
description = ''
|
||||||
|
URI where wyoming-satellite will bind its socket.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
name = mkOption {
|
||||||
|
type = str;
|
||||||
|
default = config.networking.hostName;
|
||||||
|
defaultText = literalExpression ''
|
||||||
|
config.networking.hostName
|
||||||
|
'';
|
||||||
|
description = ''
|
||||||
|
Name of the satellite.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
area = mkOption {
|
||||||
|
type = nullOr str;
|
||||||
|
default = null;
|
||||||
|
example = "Kitchen";
|
||||||
|
description = ''
|
||||||
|
Area to the satellite.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
microphone = {
|
||||||
|
command = mkOption {
|
||||||
|
type = str;
|
||||||
|
default = "arecord -r 16000 -c 1 -f S16_LE -t raw";
|
||||||
|
description = ''
|
||||||
|
Program to run for audio input.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
autoGain = mkOption {
|
||||||
|
type = ints.between 0 31;
|
||||||
|
default = 5;
|
||||||
|
example = 15;
|
||||||
|
description = ''
|
||||||
|
Automatic gain control in dbFS, with 31 being the loudest value. Set to 0 to disable.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
noiseSuppression = mkOption {
|
||||||
|
type = ints.between 0 4;
|
||||||
|
default = 2;
|
||||||
|
example = 3;
|
||||||
|
description = ''
|
||||||
|
Noise suppression level with 4 being the maximum suppression,
|
||||||
|
which may cause audio distortion. Set to 0 to disable.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
sound = {
|
||||||
|
command = mkOption {
|
||||||
|
type = nullOr str;
|
||||||
|
default = "aplay -r 22050 -c 1 -f S16_LE -t raw";
|
||||||
|
description = ''
|
||||||
|
Program to run for sound output.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
sounds = {
|
||||||
|
awake = mkOption {
|
||||||
|
type = nullOr path;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Path to audio file in WAV format to play when wake word is detected.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
done = mkOption {
|
||||||
|
type = nullOr path;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Path to audio file in WAV format to play when voice command recording has ended.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
vad = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = true;
|
||||||
|
description = ''
|
||||||
|
Whether to enable voice activity detection.
|
||||||
|
|
||||||
|
Enabling will result in only streaming audio, when speech gets
|
||||||
|
detected.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
extraArgs = mkOption {
|
||||||
|
type = listOf str;
|
||||||
|
default = [ ];
|
||||||
|
description = ''
|
||||||
|
Extra arguments to pass to the executable.
|
||||||
|
|
||||||
|
Check `wyoming-satellite --help` for possible options.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
systemd.services."wyoming-satellite" = {
|
||||||
|
description = "Wyoming Satellite";
|
||||||
|
after = [
|
||||||
|
"network-online.target"
|
||||||
|
"sound.target"
|
||||||
|
];
|
||||||
|
wants = [
|
||||||
|
"network-online.target"
|
||||||
|
"sound.target"
|
||||||
|
];
|
||||||
|
wantedBy = [
|
||||||
|
"multi-user.target"
|
||||||
|
];
|
||||||
|
path = with pkgs; [
|
||||||
|
alsa-utils
|
||||||
|
];
|
||||||
|
script = let
|
||||||
|
optionalParam = param: argument: optionals (!elem argument [ null 0 false ]) [
|
||||||
|
param argument
|
||||||
|
];
|
||||||
|
in ''
|
||||||
|
export XDG_RUNTIME_DIR=/run/user/$UID
|
||||||
|
${escapeShellArgs ([
|
||||||
|
(getExe finalPackage)
|
||||||
|
"--uri" cfg.uri
|
||||||
|
"--name" cfg.name
|
||||||
|
"--mic-command" cfg.microphone.command
|
||||||
|
]
|
||||||
|
++ optionalParam "--mic-auto-gain" cfg.microphone.autoGain
|
||||||
|
++ optionalParam "--mic-noise-suppression" cfg.microphone.noiseSuppression
|
||||||
|
++ optionalParam "--area" cfg.area
|
||||||
|
++ optionalParam "--snd-command" cfg.sound.command
|
||||||
|
++ optionalParam "--awake-wav" cfg.sounds.awake
|
||||||
|
++ optionalParam "--done-wav" cfg.sounds.done
|
||||||
|
++ optional cfg.vad.enable "--vad"
|
||||||
|
++ cfg.extraArgs)}
|
||||||
|
'';
|
||||||
|
serviceConfig = {
|
||||||
|
User = cfg.user;
|
||||||
|
Group = cfg.group;
|
||||||
|
# https://github.com/rhasspy/hassio-addons/blob/master/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/assist_microphone/run
|
||||||
|
CapabilityBoundingSet = "";
|
||||||
|
DeviceAllow = "";
|
||||||
|
DevicePolicy = "closed";
|
||||||
|
LockPersonality = true;
|
||||||
|
MemoryDenyWriteExecute = false; # onnxruntime/capi/onnxruntime_pybind11_state.so: cannot enable executable stack as shared object requires: Operation not permitted
|
||||||
|
PrivateDevices = true;
|
||||||
|
PrivateUsers = true;
|
||||||
|
ProtectHome = false; # Would deny access to local pulse/pipewire server
|
||||||
|
ProtectHostname = true;
|
||||||
|
ProtectKernelLogs = true;
|
||||||
|
ProtectKernelModules = true;
|
||||||
|
ProtectKernelTunables = true;
|
||||||
|
ProtectControlGroups = true;
|
||||||
|
ProtectProc = "invisible";
|
||||||
|
ProcSubset = "all"; # Error in cpuinfo: failed to parse processor information from /proc/cpuinfo
|
||||||
|
Restart = "always";
|
||||||
|
RestrictAddressFamilies = [
|
||||||
|
"AF_INET"
|
||||||
|
"AF_INET6"
|
||||||
|
"AF_UNIX"
|
||||||
|
"AF_NETLINK"
|
||||||
|
];
|
||||||
|
RestrictNamespaces = true;
|
||||||
|
RestrictRealtime = true;
|
||||||
|
SupplementaryGroups = [
|
||||||
|
"audio"
|
||||||
|
];
|
||||||
|
SystemCallArchitectures = "native";
|
||||||
|
SystemCallFilter = [
|
||||||
|
"@system-service"
|
||||||
|
"~@privileged"
|
||||||
|
];
|
||||||
|
UMask = "0077";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user