Files

179 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# База прошивок как в SETGUI
Это общий сервис **базы файлов прошивок**: получить список опубликованных
образов, выбрать изделие/версию/транспорт, скачать файл, проверить SHA-256 и
передать его загрузчику. Также можно опубликовать новый образ в эту же базу.
Модуль не зависит от версии самого приложения и от `c/firmware-info`.
## Состав
| Файл | Ответственность |
|---|---|
| [`firmware_database.py`](../../python/setprotocol/firmware_database.py) | Готовый HTTPS-клиент, чтение базы, кэш скачанных образов, публикация в Gitea |
| [`firmware_catalog.py`](../../python/setprotocol/firmware_catalog.py) | Общий формат записей базы, используемый SETGUI |
| [`firmware_publish.py`](../../python/setprotocol/firmware_publish.py) | Метаданные образа, SHA-256, объединение записей каталога |
| [`firmware_db.py`](firmware_db.py) | Самостоятельный консольный запуск без SETGUI |
Требования: Python 3.10+ и стандартная библиотека. Qt, Windows Credential
Manager, установленный SETGUI и библиотеки МК не требуются. Это сервис и CLI;
готовое Qt-окно остаётся в SETGUI, а другой GUI подключает сервис по API ниже.
## Как устроена база
В текущей конфигурации SETGUI файлы находятся в Gitea Releases репозитория
`setcorp/SETRD12-Releases` на `https://git.rd12.ru`. Список файлов лежит в
`firmware.releases` файла `update.json` ветки `main`. Запись содержит изделие,
версию, транспорт, адрес образа, имя файла, SHA-256, описание и необязательный
адрес приложения во Flash. Это файловый каталог; SQL-сервер не нужен.
Новый сервис использует тот же JSON-контракт, поэтому выпуски видны клиентам
SETGUI, поддерживающим указанный транспорт. В текущем SETGUI транспорт `tms`
фильтруется; общий сервис его сохраняет. Публикация не добавляет новый
загрузочный протокол в приложение или МК.
```text
публикация .hex/.bin → Gitea release asset → скачать и проверить SHA-256
обновить firmware.releases
GUI: «Обновить каталог» → выбрать запись → «Скачать и выбрать» → загрузчик МК
```
Для своего сервера задайте `server`, `owner`, `repository`, `branch` и
`manifest_path`. Репозиторий, ветка и JSON-файл должны уже существовать.
Для пустой базы достаточно файла `{"firmware":{"catalogVersion":0,"releases":[]}}`.
Если `update.json` общий с обновлениями приложения, его другие разделы
сохраняются при добавлении прошивки.
## Консоль: проверить, опубликовать, посмотреть, скачать
Из корня `templates` в PowerShell (параметры сервера стоят перед командой):
```powershell
$db = @('--server', 'https://git.rd12.ru', '--owner', 'setcorp', '--repo', 'SETRD12-Releases')
# Без сети: проверить файл и сформировать запись каталога.
python tools/firmware-publish/firmware_db.py @db preflight --file C:/build/device.hex --product MY_DEVICE --version 1.2.3 --version-code 0x010203 --transport can --base-address 0x08003000
# Публикация образа в базу (изменяет сервер).
python tools/firmware-publish/firmware_db.py @db publish --file C:/build/device.hex --product MY_DEVICE --version 1.2.3 --version-code 0x010203 --transport can --base-address 0x08003000
# Получить список записей и скачать конкретную.
python tools/firmware-publish/firmware_db.py @db list --product MY_DEVICE
python tools/firmware-publish/firmware_db.py @db download --product MY_DEVICE --version-code 0x010203 --transport can --cache C:/firmware-cache
```
`MY_DEVICE`, версия, транспорт и адрес — примеры, замените их данными изделия.
SCI8 для TMS публикуйте как `.bin` с `--transport tms`, без `--base-address`.
Инструмент не конвертирует `.axf/.out` и не проверяет пригодность образа для МК.
CLI читает логин и пароль/токен из переменных окружения `FIRMWARE_DB_LOGIN` и
`FIRMWARE_DB_PASSWORD`. Задавайте их средствами своего секрет-хранилища/CI,
а не в файлах проекта и не в аргументах командной строки. Для интерактивного
ввода в PowerShell можно использовать:
```powershell
$fwCredential = Get-Credential -Message 'Gitea: логин и пароль либо токен вместо пароля'
$env:FIRMWARE_DB_LOGIN = $fwCredential.UserName
$env:FIRMWARE_DB_PASSWORD = $fwCredential.GetNetworkCredential().Password
# Выполнить нужные команды; после работы убрать переменные из текущего процесса.
Remove-Item Env:FIRMWARE_DB_LOGIN, Env:FIRMWARE_DB_PASSWORD
```
Публичный каталог можно читать без входа. Публикация через CLI требует обе
переменные. Сервис не извлекает сохранённый пароль SETGUI автоматически.
Команда `publish` явно разрешает запись и не запрашивает дополнительного
подтверждения; `preflight` ничего не загружает. Старый BAT и конфигурации
`firmware-release.cmd` продолжают использовать прежний путь через SETGUI.
## Портирование в другое Python-приложение
Подключите `templates/python` в import path приложения; переносите зависимость
целиком, не одну копию файла. Сеть и кэш реализованы в сервисе, UI и хранение
учётных данных задаёт приложение:
```python
from pathlib import Path
from setprotocol.firmware_database import (
Credentials, FirmwareDatabase, GiteaRepository, GiteaFirmwarePublisher,
)
from setprotocol.firmware_publish import FirmwarePublication
repo = GiteaRepository('https://git.rd12.ru', 'setcorp', 'SETRD12-Releases')
# login и password получает ваше приложение из формы/хранилища.
credentials = Credentials(login, password)
database = FirmwareDatabase(repo.manifest_url, Path('firmware'), credentials=credentials)
# «Обновить каталог»: результат заполнит список в вашем UI.
releases = database.read_catalog(product='MY_DEVICE', transport='can')
# После выбора пользователем строки списка:
selected = releases[selected_index]
path = database.download(selected, progress=lambda percent: print(percent))
# Передайте path, selected.transport и selected.base_address своему загрузчику.
# Публикация нового образа: отдельное действие оператора.
publisher = GiteaFirmwarePublisher(repo, credentials)
publication = FirmwarePublication(
Path('build/device.hex'), 'MY_DEVICE', '1.2.3', 0x010203, 'can', 0x08003000,
'Описание выпуска',
)
preview = publisher.preflight(publication) # можно показать перед выпуском
entry = publisher.publish(publication)
```
Для публичного каталога передайте `credentials=None`. Для чтения каталога,
расположенного вне стандартного Gitea URL, передайте его HTTPS-адрес прямо в
`FirmwareDatabase`; `GiteaRepository` нужен сетевому публикатору.
В Qt выполняйте `read_catalog`, `download`, `publish` в worker/QThread,
передавайте прогресс сигналами в главный поток. По аналогии с SETGUI:
1. Кнопка «Обновить каталог» вызывает `read_catalog`, заполняет combo/table.
2. В строке показываются `product`, `version`, `transport`; в деталях —
`file_name`, `notes`, `base_address`.
3. «Скачать и выбрать» вызывает `download`, возвращает проверенный путь.
4. Сигнал в основное окно передаёт путь и выбранную `FirmwareRelease`;
окно выставляет файл и транспорт на вкладке прошивки.
Скачивание не запускает прошивку устройства автоматически. Для C++/Android
можно использовать CLI как отдельный процесс на ПК или реализовать клиент
этого JSON-контракта на языке платформы; Python-модуль не является C-библиотекой.
## Поведение и ошибки
- Кэш: `<cache>/<sha256>/<fileName>`. Одинаковые имена разных образов не
конфликтуют. Проверенный кэш используется повторно; незавершённые временные
файлы удаляются. Результат появляется только после совпадения SHA-256.
- Только HTTPS. Учётные данные отправляются лишь исходному origin (схема,
хост, порт); на сторонний CDN и при смене origin в redirect не передаются.
Redirect для запросов записи отклоняется.
- Публикация использует asset с SHA-256 в имени: новые байты не заменяют файл,
на который ещё ссылается старый каталог. `fileName` в каталоге остаётся
исходным именем. В этом деталь реализации отличается от старого публикатора
SETGUI, но формат каталога совместим.
- Каталог меняется только после обратного скачивания образа. Запись проверяет
ревизию файла (`sha`). При конфликте операция завершается ошибкой: повторите
выпуск после проверки причины. Загруженный asset может остаться без записи
каталога; повторный запуск использует его и снова проверит скачивание.
- Повтор той же записи не увеличивает `catalogVersion`. Обновление одного
`product + versionCode + transport` заменяет запись. Полный rollback и
автоматическая очистка старых assets не выполняются.
- Текущий upload держит образ в памяти (лимит 128 MiB), чтобы параллельная
пересборка не подменила байты между вычислением хэша и отправкой.
## Проверка
Из `templates`:
```powershell
$env:PYTHONPATH = "$PWD/python"
python -m unittest discover -s python/tests -p test_firmware_database.py -v
python -m unittest discover -s python/tests -p test_firmware_publish.py -v
```
Тесты используют сервер в памяти: каталог → публикация → скачивание, повторный
выпуск, сохранение других разделов, ошибки SHA-256 и конфликты ревизии,
изоляцию авторизации при redirect. Проверка реальной Gitea и загрузка на МК
в эти тесты не входят. Перед производственным подключением проверьте выпуск
в тестовом репозитории вашей Gitea и чтение каталога целевым GUI.