# Mila Mila is a small Go library for BVK media-complex content exchange. It implements the HTTP protocol where BVK pushes the currently displayed content state to the media complex: ```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. ## 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 does: - 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` Mila does not: - 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 ## Protocol The media complex acts as an HTTP server. BVK acts as an HTTP client. 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: | 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 | `get-content` response: ```json { "route": "3", "str": "Гостиный двор - Gostiny dvor", "tpl_name": "Гостиный двор" } ``` `updated_at` is stored internally but is not exposed by `/get-content`, because the protocol response should stay strict. ## Usage ```go package main import ( "log" "net/http" "gitea.unprism.ru/KRBL/mila" ) func main() { 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. }), ) srv := &http.Server{ Addr: "0.0.0.0:13280", Handler: handler, } log.Fatal(srv.ListenAndServe()) } ``` ## Configuration Default validation config: ```go cfg := mila.DefaultConfig() ``` Which currently means: ```go mila.Config{ 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. ## Stores Use `MemoryStore` when state does not need to survive process restart: ```go store := mila.NewMemoryStore() ``` Use `FileStore` on a device when the latest BVK state should be persisted: ```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. ## Callback `WithOnSet` lets the host application react to a valid BVK update: ```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 }), ) ``` The callback is intentionally synchronous. Keep it fast; if integration work is heavy, push the state into an internal queue. ## State Model ```json { "route": "3", "str": "Гостиный двор - Gostiny dvor", "tpl_name": "Гостиный двор", "updated_at": "2026-07-12T12:00:00Z" } ``` Go type: ```go type ContentState struct { 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 | Error response: ```json { "error": "route: must be at most 3 characters" } ``` ## 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