Skip to content

Legacy profile and migration

The media server keeps old ecosystem clients working during the move to API v1 through an explicit, time-boxed legacy profile. It is never a set of ad-hoc aliases in the native API.

Item Rule
Enable [legacy] enabled = true — default on in 1.x, removed in API v2
socket.io default namespace / on the main listener (/socket.io/) — asyncapi/socketio-legacy.yaml
Port 3000 the old default of razvivalka / churyavzrosliy; extra listener only with [legacy] listen_3000 = true
Plain WS /ws/commands (flutter_freedome 1.0.0 command frames), /ws (Manager v4 init / status_update)
REST /api/command, /api/system/*, /api/vendor/*, /api/dome/{info,status}, Manager v4 / backend v3 /api/*, /dome/{id}/*
OSC aliases of osc/legacy.yaml (NestJS v3, media server 2.0)
Auth pairing token in socket.io auth.token or ?token=; otherwise the anonymous guest policy (guest scopes)
Translation each legacy message → exactly one native operation (same scopes); the table is the set of compat/legacy/**/*.fixture.json (mapsTo)
Values legacy 0..100 volume / brightness ÷ 100 at the boundary (native 0..1); events rendered back × 100; legacy dome ids → venue default
Unknown unknown command type → command_response {success:false, error:"legacy-unsupported: <type>"} (plain WS: the same object as a frame; REST: 501 problem legacy-unsupported) — never silently ignored
Metric every legacy hit increments freedome_mediaserver_legacy_requests_total{client,message} (docs/metrics.md) and is logged once per client per day; Manager warns while it grows

Tests: make fixtures (schema, operationIds, channel messages, runner self-test) and, against a server with the profile enabled, make fixtures-replay SERVER=http://<host>:8080 [TOKEN=…].

Client What it uses Native replacement Migration
flutter_freedome 3.0 (libs/flutter_freedome) socket.io command → command_response, system_event; POST /api/command; REST /api/system/*, /api/vendor/*; simulated discovery WS / socket.io /v1 call, events; getSystem, getLogs, /metrics, gateways ops; mDNS + getInfo rebuilt as facade over freedome_client
flutter_freedome 1.0.0 (pub.dev; churyavzrosliy) plain WS /ws/commands (FreeDomeCommand JSON, no answer awaited), socket.io dome-state / integration-event (S→C), heartbeat (C→S), GET /api/dome/{info,status} call + events, getInfo, getPlayer+getVenue+getOutput, publishAppPayload, registerClient + clients/{c}/commands churyavzrosliy moves to freedome_client
react-native-freedome 0.1 port scan 8080 / 8081 / 3000 / 5000 / 9000 + GET /api/dome/info; GET /api/dome/status; socket.io command with ack, heartbeat, dome-state, integration-event mDNS + GET /api/v1/info; socket.io /v1 call with ack rebuilt as @freedome/client facade
razvivalka socket.io dome-state, integration-event (both ways), clear-integration, numeric brightness / volume (0..100) / rotation publishAppPayload, clearAppPayloads, patchOutput, events apps/{app} / venues/default/output app migrated to the SDK
Manager v4 /api/{status,play,pause,stop,brightness,volume,rotation,calibration,projection-mode,media*,playlists*,streaming*,logs}; WS init / disconnect → status_update / projection_update / error REST v1 + WS hello / events Manager is rewritten on the SDK; the profile serves only old installed builds
Manager backend v3 (deleted NestJS / Express) /api/*, /dome/{id}/* (DomeControlDto actions), /api/audio-calibration/*, /api/ambisonic/*; socket getState / setState / sendOsc → state / oscSent / error; OSC /play /stop /pause /volume /brightness /rotation /position /lighting /calibrate per-action ops, calibration jobs audio-*, setSourcePosition, sendOsc; consciousness/*, therapy/*, lubomir/* → legacy-unsupported backend retired
Media server 2.0 /status, /api/v1/dome/:id/*, /api/v1/osc/send, /api/v1/content*, /api/v1/engine/*, /ws /health + getInfo, getVenue, sendOsc, assets, getEngine never used by clients → no REST aliases (404); its OSC aliases are in osc/legacy.yaml, /freedome/render/single dropped (A1)
Manager dome360 / webmanager360 :3080/api/v2/Player/* of a 360dome system outbound driver of the 360dome gateway not a legacy-profile matter (fixtures in compat/dome360/, P5)
Sphere stubs (freedome_api_stubs.dart) no wire protocol (stubs) getInfo + WS, getVenue/listEngines, startCalibrationJob{audio-room | visual-camera}, listAudioDevices+listDisplays, uploads + putShow / startImport, preview via play Sphere uses the SDK

The published flutter_freedome 1.0.0 (pub.dev, 2025-09-19, the version churyavzrosliy pins with ^1.0.0) was inspected read-only (archive in the session scratchpad, nothing copied). Findings:

  • FreeDomeClient does not exist in 1.0.0 (nor FreeDomeDevice / FreeDomeBiometric). The public classes are FlutterFreeDome, FreeDomeConnectionService, FreeDomeContentService, FreeDomeGuestService, FreeDomeCalibrationService, FreeDomeSystemService, FreeDomeAuthService, widgets and models. churyavzrosliy’s lib/services/freedome_service.dart therefore does not compile against the package it pins; the methods integrateApp, sendDeviceCapabilities, sendSensorData, sendEvent, subscribeToEvents never had a published wire format.
  • What 1.0.0 really puts on the wire: commands = FreeDomeCommand JSON {type, data, targetSystemId, sessionId, priority, timestamp} sent over plain WebSocket ws://host:port/ws/commands without waiting for an answer (connection_service.dart:323-357, 395); socket.io listeners dome-state and integration-event (S→C, :410, :419); socket.io heartbeat {timestamp} (C→S, :545); REST GET /api/dome/info (discovery, :183) and GET /api/dome/status (:476). Command types used: play_content, pause_playback, resume_playback, stop_playback, set_volume, set_brightness, set_projection_type, set_installation_type, set_compute_backend, set_ndi_enabled, set_active_vendor, run_diagnostics, system_reboot, update_firmware, clear_logs, restore_configuration (as 3.0) plus calibrate_projector, align_projectors, start_calibration, stop_calibration, calibrate_microphone, test_audio_channel, activate_audio_profile, set_projector_brightness, set_projector_contrast, set_volume_settings (the last group → legacy-unsupported in v1 except where a fixture maps it).
  • Device commands reach churyavzrosliy inside dome-state.freedomeCommands[] with types vibrate, biometric_auth, camera_capture, sensor_data (app code freedome_service.dart:128-150).

Updated row: churyavzrosliy — plain WS /ws/commands command frames → per-type native op (as flutter_freedome 3.0); GET /api/dome/info → getInfo; GET /api/dome/status → getPlayer + getVenue + getOutput (legacy shape); heartbeat → ignored; app content → integration-event (C→S) → publishAppPayload(app); device commands ← clients/{c}/commands rendered as dome-state.freedomeCommands[] (the profile registers the legacy socket as a client with the app’s capabilities). Fixtures: compat/legacy/flutter_freedome-1.0/.

FreeDomeClient methods used by churyavzrosliy → native

Section titled “FreeDomeClient methods used by churyavzrosliy → native”
Method (app code) 1.0.0 wire Native operation
FreeDomeClient(serverUrl, appName, onConnected, onDisconnected, onDomeStateChanged, onIntegrationEvent) + connect() / disconnect() — (class absent) socket.io /v1 connect (welcome) or legacy /; registerClient
integrateApp(appName, data) — publishAppPayload(app) (legacy: integration-event)
setDomeBrightness(int) / setDomeVolume(int) — (1.0.0: set_brightness / set_volume command) patchOutput {brightness | volume} (÷ 100)
setDomeRotation(double) — patchOutput {rotation}
getDomeStatus() — (1.0.0: GET /api/dome/status) getPlayer + getVenue + getOutput
sendCommand(command, data, appName) — (1.0.0: /ws/commands frame) WS / socket.io call {op}; legacy: per-type mapping
subscribeToEvents(events, appName) / unsubscribeFromEvents — subscribe / unsubscribe (topics)
sendDeviceCapabilities(map) — registerClient {capabilities}
sendSensorData(map) — postClientTelemetry
sendEvent('biometric-auth-success' | 'camera-capture', data) — publishAppPayload {kind: state}
incoming vibrate, biometric_auth, camera_capture, sensor_data dome-state.freedomeCommands[] events client.command on clients/{c}/commands (vibrate, biometric, capture, sensors)

Every method is mapped; none is unsupported. Because no build of churyavzrosliy can have shipped with this API, the recommended path is the SDK migration rather than relying on the profile.