nixos-configs/devices/homie/modules/home-assistant/firmware.nix
matt1432 100e93bbdd
All checks were successful
Discord / discord commits (push) Has been skipped
feat(hass): add bluetooth speaker control
2024-09-10 01:21:08 -04:00

431 lines
12 KiB
Nix

{config, ...}: {
services.esphome = {
secretsFile = config.sops.secrets.esphome.path;
firmwareConfigs = {
"esp1" = {
# Device specific settings
api.encryption.key = "!secret api_key";
ota = [
{
platform = "esphome";
password = "!secret ota_pass";
}
];
wifi = {
ssid = "!secret wifi_ssid";
password = "!secret wifi_password";
manual_ip = {
static_ip = "192.168.0.92";
gateway = "192.168.0.1";
subnet = "255.255.255.0";
};
ap = {
ssid = "Esp1 Fallback Hotspot";
password = "!secret ap_fallback";
};
};
# Hardware Declaration
esphome = {
friendly_name = "M5Stack Atom Echo";
min_version = "2024.6.0";
name = "m5stack-atom-echo";
name_add_mac_suffix = true;
};
esp32 = {
board = "m5stack-atom";
framework.type = "esp-idf";
};
esp_adf = {};
button = [
{
id = "button_safe_mode";
name = "Safe Mode Boot";
platform = "safe_mode";
}
{
id = "factory_reset_btn";
name = "Factory reset";
platform = "factory_reset";
}
];
microphone = [
{
adc_type = "external";
i2s_din_pin = "GPIO23";
id = "echo_microphone";
pdm = true;
platform = "i2s_audio";
}
];
speaker = [
{
dac_type = "external";
i2s_dout_pin = "GPIO22";
id = "echo_speaker";
mode = "mono";
platform = "i2s_audio";
}
];
i2s_audio = [
{
id = "i2s_audio_bus";
i2s_bclk_pin = "GPIO19";
i2s_lrclk_pin = "GPIO33";
}
];
light = [
{
id = "led";
name = "None";
entity_category = "config";
chipset = "SK6812";
pin = "GPIO27";
platform = "esp32_rmt_led_strip";
default_transition_length = "0s";
disabled_by_default = false;
num_leds = 1;
rgb_order = "grb";
rmt_channel = 0;
effects = [
{
pulse = {
name = "Slow Pulse";
max_brightness = "100%";
min_brightness = "50%";
transition_length = "250ms";
update_interval = "250ms";
};
}
{
pulse = {
name = "Fast Pulse";
max_brightness = "100%";
min_brightness = "50%";
transition_length = "100ms";
update_interval = "100ms";
};
}
];
}
];
# Home-assistant buttons
switch = [
{
id = "use_wake_word";
name = "Use wake word";
entity_category = "config";
optimistic = true;
platform = "template";
restore_mode = "RESTORE_DEFAULT_ON";
on_turn_on = [
{lambda = "id(va).set_use_wake_word(true);";}
{
"if" = {
condition.not = ["voice_assistant.is_running"];
"then" = ["voice_assistant.start_continuous"];
};
}
{"script.execute" = "reset_led";}
];
on_turn_off = [
"voice_assistant.stop"
{lambda = "id(va).set_use_wake_word(false);";}
{"script.execute" = "reset_led";}
];
}
{
id = "use_listen_light";
name = "Use listen light";
entity_category = "config";
optimistic = true;
platform = "template";
restore_mode = "RESTORE_DEFAULT_ON";
on_turn_on = [{"script.execute" = "reset_led";}];
on_turn_off = [{"script.execute" = "reset_led";}];
}
{
id = "timer_ringing";
internal = true;
optimistic = true;
platform = "template";
restore_mode = "ALWAYS_OFF";
on_turn_on = [
{delay = "15min";}
{"switch.turn_off" = "timer_ringing";}
];
}
];
binary_sensor = [
{
id = "echo_button";
name = "Button";
entity_category = "diagnostic";
disabled_by_default = false;
platform = "gpio";
pin = {
inverted = true;
number = "GPIO39";
};
on_multi_click = [
{
timing = ["ON for at least 50ms" "OFF for at least 50ms"];
"then" = [
{
"if" = {
condition = {"switch.is_on" = "timer_ringing";};
"then" = [{"switch.turn_off" = "timer_ringing";}];
"else" = [
{
"if" = {
condition = {"switch.is_off" = "use_wake_word";};
"then" = [
{
"if" = {
condition = "voice_assistant.is_running";
"then" = [
{"voice_assistant.stop" = {};}
{"script.execute" = "reset_led";}
];
"else" = [{"voice_assistant.start" = {};}];
};
}
];
"else" = [
"voice_assistant.stop"
{delay = "1s";}
{"script.execute" = "reset_led";}
{"script.wait" = "reset_led";}
{"voice_assistant.start_continuous" = {};}
];
};
}
];
};
}
];
}
{
timing = ["ON for at least 10s"];
"then" = [{"button.press" = "factory_reset_btn";}];
}
];
}
];
# Misc
logger = {};
external_components = [
{
source = "github://pr#5230";
components = ["esp_adf"];
refresh = "0s";
}
{
source = "github://jesserockz/esphome-components";
components = ["file"];
refresh = "0s";
}
];
file = [
{
file = "https://github.com/esphome/firmware/raw/main/voice-assistant/sounds/timer_finished.wav";
id = "timer_finished_wave_file";
}
];
# Configs
script = [
{
id = "reset_led";
"then" = [
{
"if" = {
condition = [
{"switch.is_on" = "use_wake_word";}
{"switch.is_on" = "use_listen_light";}
];
"then" = [
{
"light.turn_on" = {
id = "led";
brightness = "60%";
effect = "none";
red = "100%";
green = "89%";
blue = "71%";
};
}
];
"else" = [{"light.turn_off" = "led";}];
};
}
];
}
];
voice_assistant = {
id = "va";
speaker = "echo_speaker";
microphone = "echo_microphone";
auto_gain = "31dBFS";
noise_suppression_level = 2;
vad_threshold = 3;
volume_multiplier = 2;
on_client_connected = [
{
"if" = {
condition = {"switch.is_on" = "use_wake_word";};
"then" = [
{"voice_assistant.start_continuous" = {};}
{"script.execute" = "reset_led";}
];
};
}
];
on_client_disconnected = [
{
"if" = {
condition = {"switch.is_on" = "use_wake_word";};
"then" = [
{"voice_assistant.stop" = {};}
{"light.turn_off" = "led";}
];
};
}
];
on_end = [
{delay = "100ms";}
{wait_until.not."speaker.is_playing" = {};}
{"script.execute" = "reset_led";}
];
on_error = [
{
"light.turn_on" = {
id = "led";
brightness = "100%";
effect = "none";
red = "100%";
green = "0%";
blue = "0%";
};
}
{delay = "1s";}
{"script.execute" = "reset_led";}
];
on_listening = [
{
"light.turn_on" = {
id = "led";
effect = "Slow Pulse";
green = "0%";
red = "0%";
blue = "100%";
};
}
];
on_stt_vad_end = [
{
"light.turn_on" = {
id = "led";
effect = "Fast Pulse";
red = "0%";
green = "0%";
blue = "100%";
};
}
];
on_timer_finished = [
{"voice_assistant.stop" = {};}
{"switch.turn_on" = "timer_ringing";}
{wait_until.not."microphone.is_capturing" = {};}
{
"light.turn_on" = {
id = "led";
brightness = "100%";
effect = "Fast Pulse";
red = "0%";
green = "100%";
blue = "0%";
};
}
{
while = {
condition = {"switch.is_on" = "timer_ringing";};
"then" = [
{lambda = "id(echo_speaker).play(id(timer_finished_wave_file), sizeof(id(timer_finished_wave_file)));";}
{delay = "1s";}
];
};
}
{wait_until.not."speaker.is_playing" = {};}
{"light.turn_off" = "led";}
{"switch.turn_off" = "timer_ringing";}
{
"if" = {
condition = {"switch.is_on" = "use_wake_word";};
"then" = [
{"voice_assistant.start_continuous" = {};}
{"script.execute" = "reset_led";}
];
};
}
];
on_tts_start = [
{
"light.turn_on" = {
id = "led";
brightness = "100%";
effect = "none";
red = "0%";
green = "0%";
blue = "100%";
};
}
];
};
};
};
};
}