diff --git a/README.md b/README.md index cd9d218..fe9fc72 100644 --- a/README.md +++ b/README.md @@ -142,9 +142,17 @@ D7 = GPIO22 ```bash sudo apt update -sudo apt install -y golang git build-essential wiringpi nodejs npm +sudo apt install -y golang git build-essential wiringpi nodejs npm alsa-utils ``` +> `alsa-utils` нужен для монитора уровня звука (использует `arecord`). Проверить, что микрофон виден системе: +> ```bash +> arecord -l +> # **** List of CAPTURE Hardware Devices **** +> # card 3: Device [USB PnP Sound Device], device 0: USB Audio [USB Audio] +> ``` +> Если список пуст — микрофон не подключён или не определился, монитор звука будет отдавать `sound_level: 0`. + ### 2. Клонирование и сборка ```bash @@ -282,7 +290,7 @@ sudo nft add rule inet filter input iifname "wlan0" tcp dport 8080 accept ```bash GET /api/health -# Статус сервера, uptime, статистика +# Статус сервера, uptime, статистика, sound_level (0-100, уровень с микрофона) GET /api/latest # Последние данные и история (10 записей) @@ -350,6 +358,25 @@ GET /api/log/events?limit=100 ls -la /tmp/gpio_pipe ``` +### Если индикатор "🔊 ЗВУК" на dashboard не реагирует на микрофон: + +1. **Проверьте, что arecord установлен и видит микрофон:** + ```bash + which arecord + arecord -l + ``` + +2. **Проверьте лог сервера при запуске** — если микрофон не найден, будет строка: + ``` + Аудио-монитор не запущен (микрофон недоступен?): ... + ``` + +3. **Проверьте права доступа к аудио-устройству** (сервис должен работать от пользователя из группы `audio`): + ```bash + groups + sudo usermod -aG audio + ``` + --- ## Wi-Fi режим Raspberry Pi diff --git a/cmd/server/main.go b/cmd/server/main.go index c706c66..65452ab 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -19,6 +19,7 @@ import ( "time" "gpio-monitor/internal/adapter" + "gpio-monitor/internal/audio" "gpio-monitor/internal/logger" "gpio-monitor/internal/pipe" ) @@ -28,8 +29,9 @@ import ( var webFiles embed.FS type API struct { - buf *adapter.RingBuffer - startTime time.Time + buf *adapter.RingBuffer + startTime time.Time + audioMonitor *audio.Monitor } func writeJSON(w http.ResponseWriter, v any) { @@ -409,6 +411,11 @@ func (a *API) HandleHealth(w http.ResponseWriter, r *http.Request) { now := time.Now() + soundLevel := 0 + if a.audioMonitor != nil { + soundLevel = a.audioMonitor.GetLevel() + } + writeJSON(w, map[string]any{ "status": status, "uptime_sec": time.Since(a.startTime).Seconds(), @@ -418,6 +425,7 @@ func (a *API) HandleHealth(w http.ResponseWriter, r *http.Request) { "latest": latest, "stats": a.buf.Stats(), "server_time": now.Format("02.01.2006 15:04"), + "sound_level": soundLevel, }) } @@ -638,6 +646,13 @@ func main() { // 4. RingBuffer с настройкой размера buf := adapter.NewRingBuffer(*bufferSize) + // 4.5 Монитор уровня звука с микрофона + audioMonitor := audio.NewMonitor() + if err := audioMonitor.Start(); err != nil { + log.Printf("Аудио-монитор не запущен (микрофон недоступен?): %v", err) + } + defer audioMonitor.Stop() + // 5. PipeReader с настройками pipeReader := pipe.NewPipeReader(buf, dataLogger, humanLogger, monitor, eventLogger, config) ctx, cancel := context.WithCancel(context.Background()) @@ -646,8 +661,9 @@ func main() { // ===== API И WEB СЕРВЕР ===== api := &API{ - buf: buf, - startTime: time.Now(), + buf: buf, + startTime: time.Now(), + audioMonitor: audioMonitor, } // ===== API ===== diff --git a/cmd/server/web/js/app.ts b/cmd/server/web/js/app.ts index 5758a50..5b1e671 100644 --- a/cmd/server/web/js/app.ts +++ b/cmd/server/web/js/app.ts @@ -20,6 +20,7 @@ import { setBars, setSignal, setAudioIndicator, + setSoundLevel, DOM, setChannelValue, setChannelCurrentValue, @@ -254,6 +255,8 @@ async function update(): Promise { setServerTime(health.server_time); } + setSoundLevel(health.sound_level ?? 0); + const isOnline = health.pipe_alive && health.has_data; if (isOnline) { @@ -384,6 +387,7 @@ async function update(): Promise { setServerTime("--:--:--"); setBars(0, true); setSignal(0, true); + setSoundLevel(0); resetBufferTracking(); if (lastSignalLevel > 0) { diff --git a/cmd/server/web/js/data.ts b/cmd/server/web/js/data.ts index 149741b..8a21c1e 100644 --- a/cmd/server/web/js/data.ts +++ b/cmd/server/web/js/data.ts @@ -8,6 +8,7 @@ interface HealthResponse { has_data: boolean; latest: number; server_time?: string; + sound_level?: number; stats: { filled: number; bytes_per_sec: number;