add voice option to home-assistant
This commit is contained in:
parent
2a18c0b28f
commit
710428c5a0
5 changed files with 272 additions and 13 deletions
|
@ -35,11 +35,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1714076141,
|
||||
"narHash": "sha256-Drmja/f5MRHZCskS6mvzFqxEaZMeciScCTFxWVLqWEY=",
|
||||
"lastModified": 1714253743,
|
||||
"narHash": "sha256-mdTQw2XlariysyScCv2tTE45QSU9v/ezLcHJ22f0Nxc=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "7bb2ccd8cdc44c91edba16c48d2c8f331fb3d856",
|
||||
"rev": "58a1abdbae3217ca6b702f03d3b35125d88a2994",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
@ -111,6 +111,7 @@
|
|||
// (vm_test "audiobookshelf" ./test/vm/audiobookshelf.nix)
|
||||
// (vm_test "authelia" ./test/vm/authelia.nix)
|
||||
// (vm_test "grocy" ./test/vm/grocy.nix)
|
||||
// (vm_test "home-assistant" ./test/vm/home-assistant.nix)
|
||||
// (vm_test "jellyfin" ./test/vm/jellyfin.nix)
|
||||
// (vm_test "ldap" ./test/vm/ldap.nix)
|
||||
// (vm_test "lib" ./test/vm/lib.nix)
|
||||
|
|
|
@ -29,12 +29,11 @@ rec {
|
|||
mkdir -p $(dirname ${templatePath})
|
||||
ln -fs ${file} ${templatePath}
|
||||
rm -f ${resultPath}
|
||||
if [ -z "${sedPatterns}" ]; then
|
||||
'' + (if sedPatterns == "" then ''
|
||||
cat ${templatePath} > ${resultPath}
|
||||
else
|
||||
'' else ''
|
||||
${pkgs.gnused}/bin/sed ${sedPatterns} ${templatePath} > ${resultPath}
|
||||
fi
|
||||
'';
|
||||
'');
|
||||
|
||||
secretFileType = lib.types.submodule {
|
||||
options = {
|
||||
|
|
|
@ -136,6 +136,42 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
voice = lib.mkOption {
|
||||
description = "Options related to voice service.";
|
||||
default = {};
|
||||
type = lib.types.submodule {
|
||||
options = {
|
||||
speech-to-text = lib.mkOption {
|
||||
description = ''
|
||||
Wyoming piper servers.
|
||||
|
||||
https://search.nixos.org/options?channel=23.11&from=0&size=50&sort=relevance&type=packages&query=services.wyoming.piper.servers
|
||||
'';
|
||||
type = lib.types.attrsOf lib.types.anything;
|
||||
default = {};
|
||||
};
|
||||
text-to-speech = lib.mkOption {
|
||||
description = ''
|
||||
Wyoming faster-whisper servers.
|
||||
|
||||
https://search.nixos.org/options?channel=23.11&from=0&size=50&sort=relevance&type=packages&query=services.wyoming.faster-whisper.servers
|
||||
'';
|
||||
type = lib.types.attrsOf lib.types.anything;
|
||||
default = {};
|
||||
};
|
||||
wakeword = lib.mkOption {
|
||||
description = ''
|
||||
Wyoming open wakework servers.
|
||||
|
||||
https://search.nixos.org/options?channel=23.11&from=0&size=50&sort=relevance&type=packages&query=services.wyoming.openwakeword
|
||||
'';
|
||||
type = lib.types.anything;
|
||||
default = { enable = false; };
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
backupCfg = lib.mkOption {
|
||||
type = lib.types.anything;
|
||||
description = "Backup configuration for home-assistant";
|
||||
|
@ -258,6 +294,10 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
services.wyoming.piper.servers = cfg.voice.text-to-speech;
|
||||
services.wyoming.faster-whisper.servers = cfg.voice.speech-to-text;
|
||||
services.wyoming.openwakeword = cfg.voice.wakeword;
|
||||
|
||||
services.nginx.virtualHosts."${fqdn}" = {
|
||||
http2 = true;
|
||||
|
||||
|
@ -274,7 +314,7 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
systemd.services.home-assistant.preStart = lib.mkIf cfg.ldap.enable (
|
||||
systemd.services.home-assistant.preStart = lib.mkIf cfg.enable (
|
||||
let
|
||||
onboarding = pkgs.writeText "onboarding" ''
|
||||
{
|
||||
|
@ -289,16 +329,16 @@ in
|
|||
}
|
||||
}
|
||||
'';
|
||||
storage = "${config.services.home-assistant.configDir}";
|
||||
file = "${storage}/.storage/onboarding";
|
||||
configDir = "${config.services.home-assistant.configDir}";
|
||||
file = "${configDir}/.storage/onboarding";
|
||||
in
|
||||
''
|
||||
if ! -f ${file}; then
|
||||
mkdir -p ${storage} && cp ${onboarding} ${file}
|
||||
if ! [ -f ${file} ]; then
|
||||
mkdir -p ${configDir}/.storage && cp ${onboarding} ${file}
|
||||
fi
|
||||
'' + shblib.replaceSecrets {
|
||||
userConfig = cfg.config;
|
||||
resultPath = "${config.services.home-assistant.configDir}/secrets.yaml";
|
||||
resultPath = "${configDir}/secrets.yaml";
|
||||
generator = name: value: lib.generators.toYAML {} value;
|
||||
});
|
||||
|
||||
|
|
219
test/vm/home-assistant.nix
Normal file
219
test/vm/home-assistant.nix
Normal file
|
@ -0,0 +1,219 @@
|
|||
{ pkgs, lib, ... }:
|
||||
let
|
||||
pkgs' = pkgs;
|
||||
|
||||
commonTestScript = { nodes, extraPorts ? [], ... }:
|
||||
let
|
||||
hasSSL = !(isNull nodes.server.shb.home-assistant.ssl);
|
||||
fqdn = if hasSSL then "https://ha.example.com" else "http://ha.example.com";
|
||||
in
|
||||
''
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
|
||||
start_all()
|
||||
server.wait_for_unit("home-assistant.service")
|
||||
server.wait_for_open_port(${toString nodes.server.services.home-assistant.config.http.server_port})
|
||||
''
|
||||
+ lib.concatMapStringsSep "\n" (port: ''
|
||||
server.wait_for_open_port(${toString port})
|
||||
'') extraPorts
|
||||
+ ''
|
||||
|
||||
if ${if hasSSL then "True" else "False"}:
|
||||
server.copy_from_vm("/etc/ssl/certs/ca-certificates.crt")
|
||||
client.succeed("rm -r /etc/ssl/certs")
|
||||
client.copy_from_host(str(pathlib.Path(os.environ.get("out", os.getcwd())) / "ca-certificates.crt"), "/etc/ssl/certs/ca-certificates.crt")
|
||||
|
||||
def curl(target, format, endpoint, succeed=True):
|
||||
return json.loads(target.succeed(
|
||||
"curl --fail-with-body --silent --show-error --output /dev/null --location"
|
||||
+ " --connect-to ha.example.com:443:server:443"
|
||||
+ " --connect-to ha.example.com:80:server:80"
|
||||
+ f" --write-out '{format}'"
|
||||
+ " " + endpoint
|
||||
))
|
||||
|
||||
print(server.succeed("cat /var/lib/hass/configuration.yaml"))
|
||||
print(server.succeed("systemctl cat home-assistant"))
|
||||
print(server.succeed("cat ''$(systemctl cat home-assistant | grep ExecStartPre | cut -d= -f2)"))
|
||||
print(server.succeed("cat /var/lib/hass/secrets.yaml.template"))
|
||||
print(server.succeed("cat /var/lib/hass/secrets.yaml"))
|
||||
|
||||
with subtest("access"):
|
||||
response = curl(client, """{"code":%{response_code}}""", "${fqdn}")
|
||||
|
||||
if response['code'] != 200:
|
||||
raise Exception(f"Code is {response['code']}")
|
||||
'';
|
||||
|
||||
modules = {
|
||||
base = {
|
||||
imports = [
|
||||
(pkgs'.path + "/nixos/modules/profiles/headless.nix")
|
||||
(pkgs'.path + "/nixos/modules/profiles/qemu-guest.nix")
|
||||
../../modules/blocks/nginx.nix
|
||||
../../modules/services/home-assistant.nix
|
||||
];
|
||||
|
||||
# Nginx port.
|
||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||
# VM needs a bit more memory than default.
|
||||
# virtualisation.memorySize = 4096;
|
||||
};
|
||||
|
||||
basic = {
|
||||
imports = [
|
||||
{
|
||||
options = {
|
||||
shb.backup = lib.mkOption { type = lib.types.anything; };
|
||||
shb.authelia = lib.mkOption { type = lib.types.anything; };
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
shb.home-assistant = {
|
||||
enable = true;
|
||||
domain = "example.com";
|
||||
subdomain = "ha";
|
||||
|
||||
config = {
|
||||
name = "SHB Test";
|
||||
country = "BE"; # https://en.wikipedia.org/wiki/ISO_3166-1
|
||||
latitude = "0";
|
||||
longitude = "0";
|
||||
time_zone.source = pkgs.writeText "timeZoneSecret" "UTC"; # https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
||||
unit_system = "metric";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ldap = { config, ... }: {
|
||||
imports = [
|
||||
../../modules/blocks/ldap.nix
|
||||
];
|
||||
|
||||
shb.ldap = {
|
||||
enable = true;
|
||||
domain = "example.com";
|
||||
subdomain = "ldap";
|
||||
ldapPort = 3890;
|
||||
webUIListenPort = 17170;
|
||||
dcdomain = "dc=example,dc=com";
|
||||
ldapUserPasswordFile = pkgs.writeText "ldapUserPassword" "ldapUserPassword";
|
||||
jwtSecretFile = pkgs.writeText "jwtSecret" "jwtSecret";
|
||||
};
|
||||
|
||||
shb.home-assistant = {
|
||||
ldap = {
|
||||
enable = true;
|
||||
host = "127.0.0.1";
|
||||
port = config.shb.ldap.ldapPort;
|
||||
userGroup = "homeassistant_user";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
voice = {
|
||||
shb.home-assistant.voice.text-to-speech = {
|
||||
"fr" = {
|
||||
enable = true;
|
||||
voice = "fr-siwis-medium";
|
||||
uri = "tcp://0.0.0.0:10200";
|
||||
speaker = 0;
|
||||
};
|
||||
"en" = {
|
||||
enable = true;
|
||||
voice = "en_GB-alba-medium";
|
||||
uri = "tcp://0.0.0.0:10201";
|
||||
speaker = 0;
|
||||
};
|
||||
};
|
||||
shb.home-assistant.voice.speech-to-text = {
|
||||
"tiny-fr" = {
|
||||
enable = true;
|
||||
model = "base-int8";
|
||||
language = "fr";
|
||||
uri = "tcp://0.0.0.0:10300";
|
||||
device = "cpu";
|
||||
};
|
||||
"tiny-en" = {
|
||||
enable = true;
|
||||
model = "base-int8";
|
||||
language = "en";
|
||||
uri = "tcp://0.0.0.0:10301";
|
||||
device = "cpu";
|
||||
};
|
||||
};
|
||||
shb.home-assistant.voice.wakeword = {
|
||||
enable = true;
|
||||
uri = "tcp://127.0.0.1:10400";
|
||||
preloadModels = [
|
||||
"alexa"
|
||||
"hey_jarvis"
|
||||
"hey_mycroft"
|
||||
"hey_rhasspy"
|
||||
"ok_nabu"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
basic = pkgs.testers.runNixOSTest {
|
||||
name = "home-assistant-basic";
|
||||
|
||||
nodes.server = { config, pkgs, ... }: {
|
||||
imports = [
|
||||
modules.base
|
||||
modules.basic
|
||||
];
|
||||
};
|
||||
|
||||
nodes.client = {};
|
||||
|
||||
testScript = commonTestScript;
|
||||
};
|
||||
|
||||
ldap = pkgs.testers.runNixOSTest {
|
||||
name = "home-assistant-ldap";
|
||||
|
||||
nodes.server = { config, pkgs, ... }: {
|
||||
imports = [
|
||||
modules.base
|
||||
modules.basic
|
||||
modules.ldap
|
||||
];
|
||||
};
|
||||
|
||||
nodes.client = {};
|
||||
|
||||
testScript = commonTestScript;
|
||||
};
|
||||
|
||||
voice = pkgs.testers.runNixOSTest {
|
||||
name = "home-assistant-basic";
|
||||
|
||||
nodes.server = { config, pkgs, ... }: {
|
||||
imports = [
|
||||
modules.base
|
||||
modules.basic
|
||||
modules.voice
|
||||
];
|
||||
};
|
||||
|
||||
nodes.client = {};
|
||||
|
||||
testScript = { nodes, ... }: commonTestScript {
|
||||
inherit nodes;
|
||||
extraPorts = [
|
||||
10200
|
||||
10201
|
||||
# 10300
|
||||
# 10301
|
||||
10400
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue