Editions and push-to-talk voice buttons

- Editions (buttons / full): edition.json decides whether the sensor
  collector and voice service are installed and run; bt-update sync-system
  re-enables the collector when an edition with sensors appears.
- Voice button type: hold to record, release to send to the demo server's
  /api/voice; the recognized category lights up, holding again clears it.
  buttontask-voice daemon (voice/) records via PulseAudio, panel settings
  for server URL and key with a connectivity check in the web UI.
- Packaging: full edition bundle, device-install and adb bundle updates.
- Stop bt-update from re-disabling PulseAudio on every sync.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-12 12:54:26 +00:00
co-authored by Claude Opus 5.5
parent 7db69d1397
commit 2e554a56b1
40 changed files with 2562 additions and 103 deletions
+33 -17
View File
@@ -1,6 +1,11 @@
# make-adb-bundle.ps1 — собирает offline-бандл (Windows-хост, без WSL).
#
# powershell -ExecutionPolicy Bypass -File make-adb-bundle.ps1 -Version 2.0
# powershell ... make-adb-bundle.ps1 -Version 2.0 -Edition full # + BLE-датчики, голос
#
# -Edition (docs/editions.md): buttons (по умолчанию) — без collector/ и voice/
# (и без их юнитов); full — со всем. Редакция пишется в бандл (файл EDITION) и при установке
# в /opt/buttontask/config/edition.json; OTA её не меняет.
#
# По умолчанию берёт софт из .\software (бинарник ButtonTask + webconfig\),
# пакеты из .\debs. Все shell-скрипты/юниты нормализуются в LF (CRLF-фикс).
@@ -9,7 +14,8 @@ param(
[Parameter(Mandatory = $true)][string]$Version,
[string]$BinPath,
[string]$DebsDir,
[string]$MasterPassword
[string]$MasterPassword,
[ValidateSet('buttons', 'full')][string]$Edition = 'buttons'
)
$ErrorActionPreference = 'Stop'
$Here = Split-Path -Parent $MyInvocation.MyCommand.Path
@@ -39,8 +45,10 @@ if (-not (Get-Command tar.exe -ErrorAction SilentlyContinue)) {
Die "не найден tar.exe (есть в Windows 10 1803+)"
}
# юниты systemd — все *.service из webconfig
$svc = @(Get-ChildItem $web -Filter '*.service' -File)
# юниты systemd — все *.service из webconfig (в buttons — без модулей)
$moduleUnits = @('buttontask-collector.service', 'buttontask-voice.service')
$svc = @(Get-ChildItem $web -Filter '*.service' -File |
Where-Object { $Edition -ne 'buttons' -or $moduleUnits -notcontains $_.Name })
if ($svc.Count -eq 0) { Die "в webconfig нет ни одного *.service" }
# хелперы (должны совпадать с device-install.sh)
@@ -67,20 +75,26 @@ Copy-Item $BinPath (Join-Path $stage 'app\ButtonTask')
Log "копирую webconfig"
Copy-Item $web (Join-Path $stage 'webconfig') -Recurse
# BLE collector (repo root or software/collector)
$collectorCandidates = @(
(Join-Path $SoftwareDir 'collector'),
(Join-Path (Split-Path -Parent $Here) 'collector')
)
$collectorSrc = $collectorCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
if ($collectorSrc) {
Log "копирую collector: $collectorSrc"
Copy-Item $collectorSrc (Join-Path $stage 'collector') -Recurse
# Drop caches / tests optional keep tests
Get-ChildItem (Join-Path $stage 'collector') -Recurse -Directory -Filter '__pycache__' -ErrorAction SilentlyContinue |
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
} else {
Warn "collector/ не найден — BLE-сервис не попадёт в бандл"
# Необязательные модули (repo root или software\<модуль>): BLE collector, голос
foreach ($mod in 'collector', 'voice') {
$modCandidates = @(
(Join-Path $SoftwareDir $mod),
(Join-Path (Split-Path -Parent $Here) $mod)
)
$modSrc = $modCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
if ($Edition -eq 'buttons') {
Log "редакция buttons — $mod в бандл не кладу"
Remove-Item (Join-Path $stage "webconfig\buttontask-$mod.service") -Force -ErrorAction SilentlyContinue
} elseif ($modSrc) {
Log "копирую ${mod}: $modSrc"
Copy-Item $modSrc (Join-Path $stage $mod) -Recurse
foreach ($junk in '__pycache__', 'tests') {
Get-ChildItem (Join-Path $stage $mod) -Recurse -Directory -Filter $junk -ErrorAction SilentlyContinue |
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
}
} else {
Warn "$mod/ не найден — модуль не попадёт в бандл"
}
}
Log "копирую хелперы и sudoers"
@@ -175,6 +189,8 @@ else { Warn "каталог debs пуст ($DebsDir) — сначала прог
Log "кладу device-install.sh и VERSION"
Copy-Item (Join-Path $Here 'device-install.sh') (Join-Path $stage 'device-install.sh')
Write-Bytes (Join-Path $stage 'VERSION') ($Version + "`n")
Write-Bytes (Join-Path $stage 'EDITION') ($Edition + "`n")
Log "редакция: $Edition"
Log "нормализую переводы строк в LF (CRLF-фикс)"
$fix = @()