Voice Assistant offline tiếng Việt với Raspberry Pi
Nâng cao✦ Nổi bật1/3/2026

Voice Assistant offline tiếng Việt với Raspberry Pi

Xây dựng trợ lý giọng nói offline hoàn chỉnh bằng Vosk + Raspberry Pi để điều khiển nhà thông minh không cần internet.

Raspberry PiVoskMQTTGPIOPythonVoiceIoT
0 lượt thích0 người đã làm5 giờ5 bước5 linh kiện
← Quay lại dự án
Hướng dẫn chi tiết

Bài 5: Tích hợp MQTT, chạy hệ thống hoàn chỉnh và cài systemd service

Viết mqtt_client.py, tích hợp main.py hoàn chỉnh, test với ESP32 subscriber, cài systemd service để tự khởi động khi boot.

Cập nhật 05/03/2026

mqtt_client.py

import json, time
import paho.mqtt.client as mqtt
from config import MQTT_BROKER, MQTT_PORT, MQTT_TOPIC_PREFIX

_client: mqtt.Client | None = None

def connect() -> None:
    global _client
    _client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, "voice-assistant-rpi")
    _client.on_connect = lambda c,u,f,rc,p: print(f"[MQTT] Kết nối: {rc}")
    _client.connect(MQTT_BROKER, MQTT_PORT, keepalive=60)
    _client.loop_start()

def publish_command(device: str, state: bool) -> None:
    if not _client: return
    topic   = f"{MQTT_TOPIC_PREFIX}/{device}"
    payload = json.dumps({"state":"ON" if state else "OFF",
                           "source":"voice","ts":time.time()})
    _client.publish(topic, payload, qos=1)
    print(f"[MQTT] → {topic}: {payload}")

def disconnect() -> None:
    if _client:
        _client.loop_stop(); _client.disconnect()

main.py — Tích hợp hoàn chỉnh

#!/usr/bin/env python3
import signal, sys
import gpio_controller, mqtt_client
from command_parser import parse_command
from listener import listen
from tts import announce_command_result, announce_error, speak

def handle_command(text: str) -> None:
    cmd = parse_command(text)
    if cmd is None:
        announce_error("không hiểu lệnh này"); return
    state = cmd.action == "on"
    if gpio_controller.set_device(cmd.device, state):
        mqtt_client.publish_command(cmd.device, state)
        announce_command_result(cmd.device, state)
    else:
        announce_error("gặp lỗi phần cứng")

def shutdown(sig, frame):
    speak("Đang tắt hệ thống.")
    mqtt_client.disconnect(); gpio_controller.cleanup(); sys.exit(0)

def main():
    gpio_controller.init(); mqtt_client.connect()
    signal.signal(signal.SIGINT,  shutdown)
    signal.signal(signal.SIGTERM, shutdown)
    speak("Voice Assistant đã sẵn sàng.")
    listen(handle_command)

if __name__ == "__main__":
    main()

ESP32 Subscriber (Arduino)

#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>

WiFiClient wifiClient;
PubSubClient mqtt(wifiClient);
#define RELAY_LIGHT 26

void callback(char* topic, byte* payload, unsigned int length) {
    StaticJsonDocument<128> doc;
    deserializeJson(doc, payload, length);
    bool on = strcmp(doc["state"] | "OFF", "ON") == 0;
    if (String(topic) == "home/voice/light")
        digitalWrite(RELAY_LIGHT, on ? LOW : HIGH);
}

void setup() {
    pinMode(RELAY_LIGHT, OUTPUT); digitalWrite(RELAY_LIGHT, HIGH);
    WiFi.begin("SSID", "PASSWORD");
    while (WiFi.status() != WL_CONNECTED) delay(500);
    mqtt.setServer("192.168.1.100", 1883);
    mqtt.setCallback(callback);
    mqtt.connect("esp32-voice-sub");
    mqtt.subscribe("home/voice/#");
}
void loop() {
    if (!mqtt.connected()) { mqtt.connect("esp32-voice-sub"); mqtt.subscribe("home/voice/#"); }
    mqtt.loop();
}

Cài systemd service

sudo tee /etc/systemd/system/voice-assistant.service << 'EOF'
[Unit]
Description=Voice Assistant offline tieng Viet
After=network.target sound.target

[Service]
Type=simple
User=pi
WorkingDirectory=/home/pi/voice-assistant
ExecStart=/home/pi/voice-assistant/.venv/bin/python main.py
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable voice-assistant
sudo systemctl start voice-assistant
journalctl -u voice-assistant -f

Test toàn bộ hệ thống

# Terminal 1: theo dõi MQTT
mosquitto_sub -h localhost -t "home/voice/#" -v

# Terminal 2: chạy Voice Assistant
cd ~/voice-assistant && source .venv/bin/activate && python main.py
Nói "bật đèn" → Terminal 1 hiển thị: home/voice/light {"state": "ON", "source": "voice"}