Commit Graph
124 Commits
Author SHA1 Message Date
imonlinux 0025fc781f Update mqtt_controller.py
Added MQTT topics for the new alarm duration control:

lva/<device_id>/alarm_duration/set

lva/<device_id>/alarm_duration/state

Published a new Home Assistant number discovery config:

number.<device_id>_alarm_duration (0–3600 seconds, step 5, unit s).

On /alarm_duration/set:

validates and parses the payload as a non-negative integer,

publishes a set_alarm_duration event on the EventBus,

echoes the value back to /alarm_duration/state.

On connect, publishes the current alarm_duration_seconds from preferences to the state topic for retained startup behavior.
2025-11-29 14:38:52 -08:00
imonlinux 5da1dd4bc4 Update models.py
Updated Preferences dataclass with a new field:

alarm_duration_seconds: int = 0

Kept ServerState.save_preferences() unchanged so alarm_duration_seconds is automatically serialized into preferences.json.
2025-11-29 14:38:13 -08:00
imonlinux b43b036198 Update __main__.py
Extended Preferences loading to initialize and backfill a new alarm_duration_seconds field (default 0).

Added a set_alarm_duration event handler to MicMuteHandler which:

validates and normalizes the duration value,

updates state.preferences.alarm_duration_seconds,

persists the updated preferences to disk.

Kept the existing “single writer” pattern (MicMuteHandler) for preferences/state updates.
2025-11-29 14:37:18 -08:00
imonlinux e13cc31e5b Update satellite.py
Fix bug with no stt after wake word detection.
2025-11-24 15:14:15 -08:00
imonlinux baa6f9080f Update satellite.py
Fix wake word change bug
2025-11-22 16:11:16 -08:00
imonlinux f3ae02da0d Update util.py
Revert MAC address detection logic.
2025-11-21 17:17:56 -08:00
imonlinux d2a133191b Update __main__.py
File: linux_voice_assistant/__main__.py

In _init_basics(), the --list-output-devices block is updated so that:

It exits with 0 on success.

It exits with 1 only if an exception occurs.
2025-11-21 17:00:25 -08:00
imonlinux 8d474acdab Update led_controller.py
Wrap the board import in a try/except and introduce a _BOARD_AVAILABLE flag.

If board (or Blinka/platformdetect) is not available or fails, log a clear warning and skip hardware LED initialization.

Keep the event subscriptions intact, but ensure all LED actions become no-ops when _is_ready is False.
2025-11-21 16:59:04 -08:00
imonlinux 93ceffebae Update mpv_player.py
Removed the home-grown backend probing / priority logic (pipewire → pulse → alsa) when no device is explicitly configured.

Kept support for explicitly specifying an audio_output_device in the config/CLI; if provided, it is passed through to mpv.

Added debug logging after mpv initialization to show:

current ao

current audio-device

the full audio-device-list
2025-11-21 11:00:03 -08:00
imonlinux adbb37e731 Update __main__.py
New CLI helpers

    Added support for:

    script/run --list-input-devices
    script/run --list-output-devices

    These code paths:

        Initialize just enough of the audio stack to enumerate devices.

        Print a clean, human-readable list of input/output devices (including PipeWire / PulseAudio virtual devices like Echo-Cancel Source and pipewire/echo-cancel-sink).

        Exit cleanly with status 0 instead of trying to start the full LVA process afterward (fixing the previous CalledProcessError when --list-output-devices was used).

Behavior change

    __main__.py now treats the “list devices” modes as early-exit utility modes, not “run LVA and then also print devices”.

    This makes it practical to use these commands in setup docs and shell scripts.
2025-11-20 20:02:23 -08:00
imonlinux 0151b64810 Update audio_engine.py
Behavioral & logging changes

Improved the wake word processing loop to make the following clearly visible in DEBUG logs:

The current set of active wake word IDs (MWW/OWW).

When the Stop wake word:

is activated by the model,

is accepted (i.e. meets refractory timing + is currently allowed), and

is ignored because it is no longer in active_wake_words.

Ensured the special stop model:

Is only treated as “active” when state.stop_word.is_active is True.

Is flipped back to inactive immediately after satellite.stop() is called, so:

The first “Stop” that passes all checks cancels playback and alarm tones.

Subsequent detections in the same moment appear as “TRIGGERED but IGNORED” (expected and now clearly logged).

Why this matters

When the LVA is playing audio (TTS or timer alarm), you can now:

See exactly when the Stop model fires.

Confirm that playback is being canceled at the right time.

Understand why you might see multiple “Stop wake word ACTIVATED” messages even though the alarm already stopped (model still “hearing” the tail, but logically ignored).

This matches the behavior seen in your logs:

At lower volumes / with AEC, stop is reliably accepted and playback stops immediately.

At high volumes without AEC, the model sees far less “clean” speech, so activations are rare or absent.
2025-11-20 20:01:13 -08:00
imonlinux 0b3c3e7b42 Update satellite.py
Fix ESPHome media_player persistence and entity key stability
2025-11-20 13:04:46 -08:00
imonlinux f34bc90edd Update satellite.py
Registration bug fix
2025-11-19 20:24:42 -08:00
imonlinux 4616645c40 Update __main__.py
Entry point. Clean imports, timestamp logging, integration of AudioEngine.
2025-11-19 18:49:43 -08:00
imonlinux 6eb3f46cbe Create audio_engine.py
Brand new file. Encapsulates audio logic, suppresses warnings, fixes busy wait.
2025-11-19 18:48:44 -08:00
imonlinux 6f5444237c Update satellite.py
Implements non-blocking downloads.
2025-11-19 18:47:37 -08:00
imonlinux cf82a3158d Update models.py
Added threading event for audio loop optimization.
2025-11-19 18:47:01 -08:00
imonlinux e63bda7e76 Update zeroconf.py
Uses the new util to ensure MDNS matches the device ID.
2025-11-19 18:46:05 -08:00
imonlinux 592d5eb0c3 Update util.py
New robust MAC address logic.
2025-11-19 18:45:16 -08:00
imonlinux 360fe06d96 Update satellite.py
Wrong file uploaded
2025-11-18 15:16:19 -08:00
imonlinux efe2b4ff4e Update api_server.py
Wrong file uploaded
2025-11-18 15:15:46 -08:00
imonlinux e3216d3e68 Update __main__.py
Wrong version uploaded.
2025-11-18 15:15:07 -08:00
imonlinux 5eb1489947 Update satellite.py
Uploaded the wrong version of the file.
2025-11-18 11:51:34 -08:00
imonlinux 2808877895 Update models.py
Uploaded wrong version of the file.
2025-11-18 11:51:04 -08:00
imonlinux 2fdef7d6ce Update __main__.py
Wrong version of file uploaded.
2025-11-18 11:48:04 -08:00
imonlinux fd5cd13f72 Update __main__.py
(Major change) main() function completely refactored into helpers. _init_controllers now handles decoupled initialization. _process_audio loop logic was fixed to correctly initialize wake words on startup.

 mic.recorder() loop is now much more robust against OS buffering issue when the microphone is muted and wakewords were detected and processed after unmute.
2025-11-17 22:40:53 -08:00
imonlinux ada83bdfbb Update satellite.py
Re-added the self.state.satellite = self link, which is necessary for the main loop to be reachable from the audio thread.
2025-11-17 21:51:34 -08:00
imonlinux b62d07be7d Update event_bus.py
The EventHandler base class was modified to support the new decoupled __init__ pattern.
2025-11-17 21:50:53 -08:00
imonlinux f39df8a40a Update mqtt_controller.py
__init__ was completely rewritten to be decoupled. It now listens for mic_muted/mic_unmuted events to manage its own state instead of reading from ServerState.
2025-11-17 21:50:08 -08:00
imonlinux 37922351f6 Update led_controller.py
__init__ was completely rewritten to be decoupled. It now receives loop, event_bus, config, and preferences directly and no longer has any reference to ServerState.
2025-11-17 21:49:21 -08:00
imonlinux 64e2657824 Update models.py
ServerState is now a pure data container, no longer holding controller instances. The satellite reference was re-added, as it's required by the audio thread to call satellite.wakeup(). Fixed a TypeError by re-ordering non-default fields.
2025-11-17 21:48:08 -08:00
imonlinux 8c6df9b245 Update __main__.py
(Major change) main() function completely refactored into helpers. _init_controllers now handles decoupled initialization. _process_audio loop logic was fixed to correctly initialize wake words on startup.
2025-11-17 21:46:42 -08:00
imonlinux 52e5fb374e Update models.py
fixed wrong file uploaded
2025-11-17 20:37:46 -08:00
imonlinux 4d8f5c97b7 Update util.py
Removed the unused is_arm function
2025-11-17 20:22:54 -08:00
imonlinux c9be5fc026 Update satellite.py
Added all the logic for downloading external wake words
2025-11-17 20:22:05 -08:00
imonlinux a4fa7b8631 Update __main__.py
Replaced sounddevice with soundcard, removed the audio Queue, added the new download directory to the search path, and added the device listing arguments
2025-11-17 20:21:24 -08:00
imonlinux 005900b2ae Update models.py
Replaced sounddevice with soundcard, removed the audio Queue, added the new download directory to the search path, and added the device listing arguments
2025-11-17 20:19:30 -08:00
imonlinux 324881ca8b Update models.py
Removed audio_queue, added download_dir, and updated AvailableWakeWord to use the new libraries
2025-11-17 20:18:38 -08:00
imonlinux f033595649 Update config.py
Added download_dir and removed old oww_ model paths
2025-11-17 20:17:44 -08:00
imonlinux d2a9057dde Update config.py
Updated for the new soundcard library
2025-11-17 20:17:08 -08:00
imonlinux 82c02e9db9 Delete linux_voice_assistant/openwakeword.py 2025-11-17 20:12:33 -08:00
imonlinux 9bc2830a2d Delete linux_voice_assistant/microwakeword.py 2025-11-17 20:12:18 -08:00
imonlinux 3507074698 Delete linux_voice_assistant/wakeword.py 2025-11-17 20:12:04 -08:00
imonlinux 70e51148bf Update satellite.py
Fixed LED startup state bug.
2025-11-17 18:05:06 -08:00
imonlinux 9d27b016ca Update models.py
Fixed LED startup state bug.
2025-11-17 18:04:34 -08:00
imonlinux 77c2530657 Add config.json
This is the minimum configuration needed to start the LVA. 

{
  "app": {
    "name": "Linux Voice Assistant"
  }
}
2025-11-17 17:42:40 -08:00
imonlinux ebd74c1e80 Update __main__.py
Removed all argparse.add_argument() calls, except for the new --config flag.  The main() function now calls load_config_from_json() at startup.  All internal logic now references the config object (e.g., config.app.name) instead of the old args object.
2025-11-17 17:20:18 -08:00
imonlinux ce5418a27a Add linux_voice_assistant/config.json.example
Here is a complete config.json file showing all available options and explanations.
2025-11-17 17:18:36 -08:00
imonlinux 94e13f2c13 Add linux_voice_assistant/config.py
Adds new dataclasses (AppConfig, AudioConfig, LedConfig, etc.) to define the application's configuration structure. Includes a load_config_from_json() helper to parse the JSON file and provide default values for any omitted sections
2025-11-17 17:13:02 -08:00
imonlinux bd21743c49 Update mpv_player.py
Fix bug with audio backend detection. ALSA was not being detected correctly.
2025-11-17 16:46:15 -08:00