Commit Graph
276 Commits
Author SHA1 Message Date
imonlinux e0bb8e7793 Update .gitignore 2025-11-17 20:13:31 -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 bf39055441 Delete wakewords/openWakeWord/melspectrogram.tflite 2025-11-17 20:11:42 -08:00
imonlinux 3587d8329f Delete wakewords/openWakeWord/embedding_model.tflite 2025-11-17 20:11:30 -08:00
imonlinux d07e1be653 Delete lib directory 2025-11-17 20:11:04 -08:00
imonlinux 28c4ade611 Update README.md
Refactor: Sync with Upstream Architectural Changes (Nov 2025)
Type: Refactor / Feat

Description
This PR ports several major architectural changes and new features from the upstream OHF-Voice/linux-voice-assistant repository. Because our codebase has been significantly refactored (config file, state machine), these changes were ported manually to integrate them cleanly with our new architecture.

This brings our fork up-to-date with the upstream's core logic and dependencies, ensuring we benefit from future bug fixes in those externalized libraries.

Key Changes
Audio Library Replaced: Replaced the sounddevice library with soundcard.

New Audio Capture Loop: The entire audio processing pipeline in __main__.py has been rewritten. It no longer uses a Queue and a sounddevice callback. Instead, the process_audio thread now runs a blocking mic.recorder() loop from the soundcard library, which is the new architecture adopted by the upstream project.

External Wake Word Libraries: All local wake word code (microwakeword.py, openwakeword.py, wakeword.py) and the lib/ directory have been deleted. They are replaced by new pip dependencies: pymicro-wakeword and pyopen-wakeword.

New Feature: External Wake Words: Ported the feature to allow Home Assistant to provide custom, external wake words. The LVA will now download models sent from HA to a new local/ directory.

New Feature: List Devices: Ported the --list-input-devices and --list-output-devices CLI helpers from upstream.

Dependency Updates: > * Bumped aioesphomeapi to 42.7.0 and updated api_server.py to use AuthenticationRequest (from ConnectRequest). > * Constrained zeroconf to <1. > * Updated dev dependencies (black, flake8, etc.)

Cleanup: Updated .gitignore to include the new /local/ download directory and mypy.ini for the new libraries.
2025-11-17 20:09:57 -08:00
imonlinux 90f37df4e8 Merge pull request #34 from imonlinux/centralized-configuration-file
Refactor: Centralize Configuration into config.json
Type: Refactor Issue: Closes #XYZ (if you have one)

Description
This pull request completes a major refactoring goal by moving all (20+) command-line arguments into a single, centralized config.json file.

The application is now launched with a single -c or --config flag pointing to this new file, dramatically simplifying startup scripts and configuration management.

Changes
NEW: 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.

MODIFIED: linux_voice_assistant/__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 18:40:01 -08:00
imonlinux 8e4480716a Update linux-voice-assistant-2mic-install.md
Updated the tutorial to reflect the change to config.json instead of command line arguements.
2025-11-17 18:38:01 -08:00
imonlinux 531e6500d0 Update README.md 2025-11-17 18:09:34 -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 b209c1300e Update and rename user-linux-voice-assistant.service to linux-voice-assistant.service
Changes the user mode service file to the single command needed to start LVA. All other configuration arguments are in the linux_voice_assistant/config.json file.
2025-11-17 18:03:09 -08:00
imonlinux e073be7978 Delete service/user-pw-linux-voice-assistant.service
No longer needed.
2025-11-17 17:44:16 -08:00
imonlinux 75d02225b0 Delete service/user-pa-linux-voice-assistant.service
No longer needed.
2025-11-17 17:43:47 -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 bd24e543b9 Update README.md
Updated README.md to align with the recent modifications and to close out some of the ToDo's.
2025-11-17 17:38:56 -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
imonlinux 474ddfbaa4 Merge pull request #33 from imonlinux/normalize-satellite-state-machine
Normalize satellite state machine
2025-11-17 15:31:06 -08:00
imonlinux 208e7baec6 Merge pull request #32 from imonlinux/fix-mqtt-race-condition
Update mqtt_controller.py
2025-11-17 15:29:59 -08:00
imonlinux 899130c0d5 Merge pull request #31 from imonlinux/fix_mpv_race_condition
Fix mpv race condition
2025-11-17 15:28:46 -08:00
imonlinux 2ab4ae7b22 Merge pull request #30 from imonlinux/consolidate-dependencies
Consolidate dependencies
2025-11-17 15:26:37 -08:00
imonlinux 4d153d41cd Delete requirements.txt 2025-11-17 15:23:09 -08:00
imonlinux ab4bc2d027 Update pyproject.toml
Goal: You currently have dependencies listed in both pyproject.toml and requirements.txt. These files are redundant and also conflicting (they list different things). This can cause confusion and versioning problems.

The Fix: We will make pyproject.toml the single source of truth by merging all dependencies into it and then deleting the old requirements.txt file.

I merged the two unique libraries from requirements.txt (gpiozero and spidev) into the dependencies list.
2025-11-17 15:22:14 -08:00
imonlinux a1c1336ba2 Update led_controller.py
Update led_controller.py to subscribe to the new, normalized state events being published by satellite.py
2025-11-17 15:09:36 -08:00
imonlinux f1137232e0 Update satellite.py
This is the major change. All the _is_speaking, _run_finished, etc. flags are gone, replaced by a single self._state variable and a _set_state method. The logic is now much cleaner.
2025-11-17 15:08:10 -08:00
imonlinux 0f1ceefc5c Update models.py
Goal: satellite.py currently uses a set of boolean flags (_is_streaming_audio, _tts_played, _run_finished, _is_speaking) to figure out what it's doing. This is hard to read and easy to break. Replaced this with a clean, formal state machine (using an Enum). This makes the logic explicit and much easier to manage.

added the SatelliteState Enum at the top and removed the media_player_entity from ServerState as it's better managed by the satellite itself
2025-11-17 15:05:35 -08:00
imonlinux 2cdabdad30 Update mqtt_controller.py
Goal: We'll apply the exact same pattern to the MqttController. The paho-mqtt library runs its _on_message callback in a separate thread. We'll stop it from modifying state directly and instead schedule a new function to run on the main asyncio loop.

Here is the complete file. The key changes are:

The _on_message function is now tiny. It just gets the topic/payload and uses self.state.loop.call_soon_threadsafe to schedule a new function.

A new function _handle_message_on_loop contains all the logic that used to be in _on_message. This new function will run safely on the main asyncio loop, eliminating the race condition.
2025-11-17 14:44:41 -08:00
imonlinux 64c46fce2d Update mpv_player.py
added loop: asyncio.AbstractEventLoop to __init__ and used self.loop.call_threadsafe in _run_done_callback
2025-11-17 14:42:06 -08:00
imonlinux 943a8a0d5c Update __main__.py
Fix MpvMediaPlayer Race Condition
Goal: The mpv library runs in its own thread. When a track finishes, its callback (_on_idle_active) runs in that thread and tries to modify the satellite's state, creating a race condition. We will fix this by "marshaling" that callback onto the main asyncio loop.

added loop=loop to the MpvMediaPlayer constructors
2025-11-17 14:40:42 -08:00
imonlinux 61bf13ca98 Update api_server.py 2025-11-11 20:33:59 -08:00
imonlinux 111f99983e Update pyproject.toml 2025-11-11 19:57:35 -08:00
imonlinux a74bf2ca1d Update api_server.py 2025-11-11 19:56:29 -08:00
imonlinux 676591a75d Update pyproject.toml
Add RPi.GPIO library
2025-11-04 13:34:27 -08:00
imonlinux 4cbfc760f3 Update README.md 2025-10-17 09:34:49 -07:00
imonlinux 8b30c3cecb Add info for working external SPI LEDs 2025-10-15 22:26:33 -07:00
imonlinux c4f632a48f Merge pull request #28 from imonlinux/neopixel_spi
Feature - Add WS2812B (NeoPixel) LED Support
2025-10-15 20:36:22 -07:00
imonlinux 8bef7e0f7a Add Support for NEOPixel via SPI 2025-10-15 20:34:12 -07:00
imonlinux d427d138e6 Add Support for NEOPixel via SPI 2025-10-15 20:33:24 -07:00
imonlinux 85f4d9150b Add Support for NEOPixel via SPI 2025-10-15 20:32:48 -07:00
imonlinux 9547a8eea6 Add Support for NEOPixel via SPI 2025-10-15 20:31:38 -07:00
imonlinux ce4486896a Regression Bug for LED Event
Continued conversation listening was showing Idle effect instead of Listening.
2025-10-15 09:31:26 -07:00
imonlinux 2dc8e146af Merge pull request #26 from imonlinux/Add_Support_PA_PW
Add support for PipeWire, PulseAudio, and Alsa
2025-10-14 18:37:22 -07:00
imonlinux 31ea2762a3 Add support for PipeWire, PulseAudio, and Alsa
Selects the best available audio output backend for mpv.
    
The selection follows a clear priority:
    1. A fully qualified device string (e.g., 'alsa/plughw:...') is used directly.
    2. A simple device name tries PipeWire, then PulseAudio, then ALSA.
    3. No device specified (or 'default') tries the default for PipeWire, PulseAudio, and ALSA in order.
2025-10-14 18:35:30 -07:00
imonlinux d98ed168a4 Simplify mpv_player.py Backend dection logic code cleanup 2025-10-14 15:45:26 -07:00
imonlinux 8cd9ffc0d5 Fix issue where Stop was not detected during playback 2025-10-14 15:44:22 -07:00