diff --git a/README.md b/README.md index a60e787..ec5ed22 100644 --- a/README.md +++ b/README.md @@ -1,77 +1,79 @@ # Mila -Mila is a small Go library for BVK media-complex content exchange. +Mila — небольшая Go-библиотека для обмена данными между БВК и +медиакомплексом. -It implements the HTTP protocol where BVK pushes the currently displayed -content state to the media complex: +Библиотека реализует HTTP-протокол, в котором БВК отправляет в медиакомплекс +текущее состояние отображаемого контента: ```text GET /set-content?route=&str=&tpl_name= GET /get-content ``` -The library intentionally does not know anything about snapshots, route -progress, geolocation, frontend state, or media playback rules. It only parses, -validates, stores, logs, and returns BVK content state. +Mila намеренно не знает ничего про снапшоты, геопозицию, прогресс маршрута, +фронтенд, правила воспроизведения медиа и структуру контента White Nights. Она +только принимает, валидирует, сохраняет, логирует и возвращает состояние, +полученное от БВК. -## Install +## Установка ```bash go get gitea.unprism.ru/KRBL/mila ``` -## Scope +## Зона Ответственности -Mila is a protocol library. It should be embedded into an application service, -for example `wn-content`, and exposed on the address required by the transport -integration. +Mila — библиотека протокола. Ее нужно встраивать в прикладной сервис, например +в `wn-content`, и открывать на адресе, который требуется транспортной +интеграцией. -Mila does: +Mila делает: -- parse `GET /set-content` -- parse `GET /get-content` -- validate `route`, `str`, and `tpl_name` -- URL-decode query parameters through Go's standard HTTP parser -- store the latest state in memory or in a JSON file -- return protocol-compatible JSON -- log each HTTP request with method, path, status, remote address, and duration -- call an optional callback after successful `set-content` +- разбирает `GET /set-content`; +- разбирает `GET /get-content`; +- валидирует `route`, `str` и `tpl_name`; +- декодирует URL-параметры стандартным HTTP-парсером Go; +- хранит последнее состояние в памяти или JSON-файле; +- возвращает JSON, совместимый с протоколом; +- логирует каждый HTTP-запрос: метод, путь, статус, удаленный адрес и время; +- вызывает опциональный callback после успешного `set-content`. -Mila does not: +Mila не делает: -- calculate route progress -- work with geolocation or NMEA -- map `tpl_name` to real media playlists -- read or write snapshots -- communicate with frontend directly -- decide how content should be rendered +- не считает прогресс маршрута; +- не работает с геопозицией или NMEA; +- не сопоставляет `tpl_name` с реальными плейлистами; +- не читает и не пишет снапшоты; +- не общается с фронтендом напрямую; +- не решает, как именно должен отображаться контент. -## Protocol +## Протокол -The media complex acts as an HTTP server. BVK acts as an HTTP client. +Медиакомплекс выступает HTTP-сервером. БВК выступает HTTP-клиентом. -Default address from the PDF: +Адрес по документу: ```text 172.16.16.2:13280 ``` -Endpoints: +Ручки: ```text GET /set-content?route=&str=&tpl_name= GET /get-content ``` -`set-content` accepts URL-encoded query parameters: +`set-content` принимает URL-encoded query-параметры: -| Parameter | Required | Meaning | +| Параметр | Обязательный | Описание | | --- | --- | --- | -| `route` | yes | route number, default limit is 1-3 characters | -| `str` | no | ticker/running text, default limit is 200 characters | -| `tpl_name` | yes | media content template name, default limit is 200 characters | +| `route` | да | номер маршрута, по умолчанию 1-3 символа | +| `str` | нет | текст бегущей строки, по умолчанию до 200 символов | +| `tpl_name` | да | название шаблона медиаконтента, по умолчанию до 200 символов | -`get-content` response: +Ответ `get-content`: ```json { @@ -81,96 +83,101 @@ GET /get-content } ``` -`updated_at` is stored internally but is not exposed by `/get-content`, because -the protocol response should stay strict. +Поле `updated_at` хранится внутри состояния, но не отдается через +`/get-content`, потому что ответ должен оставаться строгим относительно +протокола. -## Usage +## Использование ```go package main import ( - "log" - "net/http" + "log" + "net/http" - "gitea.unprism.ru/KRBL/mila" + "gitea.unprism.ru/KRBL/mila" ) func main() { -store := mila.NewFileStore("/srv/persistence/client_logs/bvk_content.json") + store := mila.NewFileStore("/srv/persistence/client_logs/bvk_content.json") -handler := mila.NewHandler(mila.DefaultConfig(), store, - mila.WithOnSet(func(state mila.ContentState) { - // Application-specific integration goes here. - }), -) + handler := mila.NewHandler(mila.DefaultConfig(), store, + mila.WithOnSet(func(state mila.ContentState) { + // Здесь прикладная интеграция: + // - передать route/str/tpl_name в состояние приложения; + // - сопоставить state.Template с локальным шаблоном; + // - записать дополнительные логи. + }), + ) -srv := &http.Server{ - Addr: "0.0.0.0:13280", - Handler: handler, -} + srv := &http.Server{ + Addr: "0.0.0.0:13280", + Handler: handler, + } -log.Fatal(srv.ListenAndServe()) + log.Fatal(srv.ListenAndServe()) } ``` -## Configuration +## Конфигурация -Default validation config: +Конфигурация валидации по умолчанию: ```go cfg := mila.DefaultConfig() ``` -Which currently means: +Сейчас это: ```go mila.Config{ - MaxRouteLen: 3, - MaxTextLen: 200, - MaxTemplateLen: 200, + MaxRouteLen: 3, + MaxTextLen: 200, + MaxTemplateLen: 200, } ``` -The text/template limits should be confirmed with the integrator. The provided -PDF has an ambiguous text layer for those values. +Лимиты для `str` и `tpl_name` нужно подтвердить у интегратора. В переданном PDF +текстовый слой неоднозначно распознает исходное значение. -## Stores +## Хранилища -Use `MemoryStore` when state does not need to survive process restart: +`MemoryStore` подходит, когда состояние не должно переживать рестарт процесса: ```go store := mila.NewMemoryStore() ``` -Use `FileStore` on a device when the latest BVK state should be persisted: +`FileStore` подходит для устройства, если последнее состояние от БВК нужно +сохранять на диске: ```go store := mila.NewFileStore("/srv/persistence/client_logs/bvk_content.json") ``` -`FileStore` writes atomically through a temporary file and keeps an in-memory -copy after the first successful read or write. +`FileStore` пишет состояние атомарно через временный файл и держит копию в +памяти после первого успешного чтения или записи. ## Callback -`WithOnSet` lets the host application react to a valid BVK update: +`WithOnSet` позволяет приложению отреагировать на валидное обновление от БВК: ```go handler := mila.NewHandler(mila.DefaultConfig(), store, - mila.WithOnSet(func(state mila.ContentState) { - // Example host-side decisions: - // - publish route and ticker to frontend state - // - map state.Template to a local playlist/template - // - write application-specific logs - }), + mila.WithOnSet(func(state mila.ContentState) { + // Возможные действия на стороне приложения: + // - опубликовать номер маршрута и бегущую строку; + // - сопоставить state.Template с локальным плейлистом; + // - записать прикладные логи. + }), ) ``` -The callback is intentionally synchronous. Keep it fast; if integration work is -heavy, push the state into an internal queue. +Callback выполняется синхронно. Его нужно держать быстрым. Если интеграционная +логика тяжелая, лучше положить состояние во внутреннюю очередь. -## State Model +## Модель Состояния ```json { @@ -181,29 +188,29 @@ heavy, push the state into an internal queue. } ``` -Go type: +Go-тип: ```go type ContentState struct { - Route string `json:"route"` - Text string `json:"str"` - Template string `json:"tpl_name"` - UpdatedAt time.Time `json:"updated_at,omitempty"` + Route string `json:"route"` + Text string `json:"str"` + Template string `json:"tpl_name"` + UpdatedAt time.Time `json:"updated_at,omitempty"` } ``` -## Status Codes +## Коды Ответов -| Code | When | +| Код | Когда возвращается | | ---: | --- | -| 200 | valid `set-content` or ready `get-content` | -| 400 | invalid request parameters | -| 404 | unknown path | -| 405 | method is not `GET` | -| 500 | store/internal error | -| 503 | `get-content` before first state, canceled/deadline context, unavailable dependency | +| 200 | валидный `set-content` или готовый `get-content` | +| 400 | невалидные параметры запроса | +| 404 | неизвестный путь | +| 405 | метод не `GET` | +| 500 | ошибка хранилища или внутренняя ошибка | +| 503 | `get-content` до первого состояния, отмененный контекст, недоступная зависимость | -Error response: +Формат ошибки: ```json { @@ -211,17 +218,17 @@ Error response: } ``` -## Testing +## Тестирование ```bash go test ./... ``` -Current tests cover: +Текущие тесты покрывают: -- successful `set-content` + `get-content` -- `get-content` before state is ready -- invalid route validation -- UTF-8 text/template validation -- file store persistence -- missing file store state +- успешный `set-content` + `get-content`; +- `get-content` до готовности состояния; +- невалидный `route`; +- UTF-8 и лимиты для текста/шаблона; +- сохранение и чтение через `FileStore`; +- отсутствие файла состояния в `FileStore`. diff --git a/protocol.md b/protocol.md index f652245..2a443bc 100644 --- a/protocol.md +++ b/protocol.md @@ -1,45 +1,46 @@ -# BVK Exchange Protocol +# Протокол Обмена С БВК -Based on `Протокол_обмена_медиакомплекса_и_БВК.pdf`. +Документ основан на файле +`Протокол_обмена_медиакомплекса_и_БВК.pdf`. -## Role +## Роли -- BVK is the HTTP client. -- Media complex is the HTTP server. -- Default address from the document: `172.16.16.2:13280`. +- БВК — HTTP-клиент. +- Медиакомплекс — HTTP-сервер. +- Адрес по документу: `172.16.16.2:13280`. -## Set Content +## Установка Контента ```text GET /set-content?route=&str=&tpl_name= ``` -Parameters are URL-encoded. +Параметры передаются в query string и должны быть URL-encoded. -| Parameter | Meaning | +| Параметр | Описание | | --- | --- | -| `route` | Route number, 1 to 3 characters | -| `str` | Ticker/running text | -| `tpl_name` | Media content template name | +| `route` | номер маршрута, от 1 до 3 символов | +| `str` | текст бегущей строки | +| `tpl_name` | название шаблона медиаконтента | -Current library defaults: +Текущие значения по умолчанию в библиотеке: -| Field | Default limit | +| Поле | Лимит по умолчанию | | --- | ---: | -| `route` | 3 characters | -| `str` | 200 characters | -| `tpl_name` | 200 characters | +| `route` | 3 символа | +| `str` | 200 символов | +| `tpl_name` | 200 символов | -The exact text/template limits must be confirmed with the integrator because the -PDF text layer is ambiguous for the original value. +Точные лимиты для `str` и `tpl_name` нужно подтвердить у интегратора, потому что +текстовый слой PDF неоднозначно распознает исходное значение. -## Get Content +## Запрос Контента ```text GET /get-content ``` -Response: +Ответ: ```json { @@ -49,15 +50,37 @@ Response: } ``` -Mila keeps `updated_at` internally, but the HTTP response is strict and exposes -only the fields defined by the protocol. +Mila хранит `updated_at` внутри состояния, но HTTP-ответ оставляет строгим и +отдает только поля, описанные в протоколе. -## Status Codes +## Коды Ответов -| Code | Meaning | +| Код | Значение | | ---: | --- | | 200 | OK | -| 400 | Bad request / validation error | -| 404 | Path not found | -| 500 | Internal server error | -| 503 | State is not ready or dependency unavailable | +| 400 | ошибка в запросе или валидации | +| 404 | путь не найден | +| 405 | метод не поддерживается | +| 500 | внутренняя ошибка сервера | +| 503 | состояние еще не готово или зависимость недоступна | + +## Важное Ограничение + +Протокол БВК передает только: + +- номер маршрута; +- текст бегущей строки; +- название шаблона медиаконтента. + +Он не передает: + +- координаты; +- направление движения; +- текущий сегмент маршрута; +- процент прохождения маршрута; +- ближайшую остановку; +- ближайшие достопримечательности. + +Поэтому Mila не должна использоваться как источник геопозиции или route +progress. Эти данные должны приходить из отдельного источника: NMEA, API, +симулятора или другого механизма геолокации.