1
0
Fork 0

add voice option to home-assistant

This commit is contained in:
ibizaman 2024-04-29 00:11:51 -07:00
parent 2a18c0b28f
commit 710428c5a0
5 changed files with 272 additions and 13 deletions

View file

@ -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": {

View file

@ -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)

View file

@ -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 = {

View file

@ -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
View 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
];
};
};
}