Repository navigation
Releases: zero-labsco/flutter_rtc_link
Release list
Release v0.4.0
Added / 新增
- Added separate public entry points
flutter_rtc_link_device.dart(provisioning, OTA, logs, diagnostics, generic BLE) andflutter_rtc_link_robot.dart(teleoperation, BLE control link), so an app that only needs media no longer compiles those modules, and addedtool/check_module_boundaries.dartto enforce the module directions in CI.- 新增独立公开入口
flutter_rtc_link_device.dart(配网、OTA、日志、诊断、通用 BLE)与flutter_rtc_link_robot.dart(遥控、BLE 控制链路),只需要媒体能力的应用不再编译这些模块,并新增tool/check_module_boundaries.dart在 CI 中强制校验模块依赖方向。
- 新增独立公开入口
- Added
RobotEvent, a sealed hierarchy inrobot/robot_events.dartthat takes over the telemetry, pause / resume, stale-drop and watchdog events previously hanging offDeviceEvent.- 新增
RobotEvent(位于robot/robot_events.dart的密封层级),接管此前挂在DeviceEvent下的遥测、暂停 / 恢复、过期丢弃与看门狗事件。
- 新增
- Added
NfcTagBackendandWifiNetworkConnector: injectable adapters so the NFC and Wi-Fi stacks are supplied by the app instead of being forced on every consumer of the plugin.- 新增
NfcTagBackend与WifiNetworkConnector可注入适配器,使 NFC 与 Wi-Fi 技术栈由应用提供,而不强加给插件的每个使用者。
- 新增
Changed / 优化
- Changed the public barrel
flutter_rtc_link.dartto export the media core only: device and robot symbols must now be imported fromflutter_rtc_link_device.dart/flutter_rtc_link_robot.dart(breaking, no compatibility shim).- 公开 barrel
flutter_rtc_link.dart现只导出媒体核心:设备与机器人符号需改从flutter_rtc_link_device.dart/flutter_rtc_link_robot.dart导入(破坏性变更,无兼容垫片)。
- 公开 barrel
- Changed
core/into a dependency-free shared kernel:DeviceEventmoved todevice/device_events.dart,MqttCredentialstocore/rtc_credentials.dartandBleDevicetoble/ble_device.dart, socoreandresilienceno longer depend ondevice,robot,bleorplatforms.- 将
core/改为零依赖共享内核:DeviceEvent迁至device/device_events.dart、MqttCredentials迁至core/rtc_credentials.dart、BleDevice迁至ble/ble_device.dart,core与resilience自此不再依赖device、robot、ble或platforms。
- 将
- Changed
RobotController.eventsto emitStream<RobotEvent>instead ofStream<DeviceEvent>;DeviceEventkeeps only provisioning, OTA, log and diagnostics events.RobotController.events改为发出Stream<RobotEvent>而非Stream<DeviceEvent>;DeviceEvent只保留配网、OTA、日志与诊断事件。
- Changed
NfcProvisioningChannelImplto require anNfcTagBackend, and renamedWifiIotSoftApChanneltoSoftApProvisioningChannelImplwith a requiredWifiNetworkConnector; the demo app wires both withnfc_managerandwifi_iot.NfcProvisioningChannelImpl现在要求传入NfcTagBackend;WifiIotSoftApChannel更名为SoftApProvisioningChannelImpl并要求传入WifiNetworkConnector;示例应用用nfc_manager与wifi_iot完成接线。
- Dropped the unused
nordic_dfudependency and removedndef_record,nfc_managerandwifi_iotfrom the published package, cutting four native plugin integrations (and their merged Android permissions) from every install.- 移除未使用的
nordic_dfu依赖,并从发布包中删除ndef_record、nfc_manager与wifi_iot,每次安装少引入四个原生插件(及其合并进来的 Android 权限)。
- 移除未使用的
Release v0.3.1
Added / 新增
- Added
LiveKitSubscriber.publication: exposes the wrappedRemoteTrackPublicationso callers can read the real track kind.- 新增
LiveKitSubscriber.publication:暴露被封装的RemoteTrackPublication,便于调用方读取真实轨道类型。
- 新增
- Added
DeviceProvisioning.readNfcCredential(): reads a credential tag and returns the credentials without provisioning anything, so the "tap a tag to learn the Wi-Fi password" flow no longer has to misuseprovisionViaNfc().- 新增
DeviceProvisioning.readNfcCredential():只读取凭据标签并返回凭据、不做任何配网,使"碰一碰拿到 Wi-Fi 密码"的流程不必再误用provisionViaNfc()。
- 新增
- Added
ProvisionDevice.dppUri: carries the Wi-Fi Easy Connect bootstrap URI (DPP:…) scanned from the device QR code, which is what DPP actually needs.- 新增
ProvisionDevice.dppUri:承载从设备二维码扫到的 Wi-Fi Easy Connect 引导 URI(DPP:…),这才是 DPP 真正需要的内容。
- 新增
Changed / 优化
provisionViaNfc({ProvisionDevice? device})now delivers the tag credentials to that device over BLE / SoftAP / SmartConfig, so NFC can actually provision instead of just reading. The extra parameter is optional, so existing calls keep compiling.provisionViaNfc({ProvisionDevice? device})现在会把标签凭据经 BLE / SoftAP / SmartConfig 下发给该设备,NFC 由此能真正完成配网而不只是读取。该参数为可选,既有调用无需改动。
Fixed / 修复
-
Fixed
provisionViaNfc()reportingsuccessafter merely reading a tag: nothing was ever sent to a device (and the credentials were dropped), so the status now fails with an explicit message unless aProvisionDeviceis supplied.- 修复
provisionViaNfc()仅读到标签就上报success的问题:凭据从未下发给任何设备(且被丢弃),现在未传入ProvisionDevice时会以明确信息失败。
- 修复
-
Fixed DPP being handed
device.id(a BLE address or SoftAP SSID) as the QR content:provisionViaDpp()now requires aDPP:bootstrap URI and rejects anything else asprotocolMismatchwith a readable message, instead of failing opaquely inside the system configurator.- 修复把
device.id(BLE 地址或 SoftAP SSID)当作 DPP 二维码内容的问题:provisionViaDpp()现在要求DPP:引导 URI,其余一律按protocolMismatch并给出可读信息拒绝,而不是在系统配置器里不明原因地失败。
- 修复把
-
Fixed
protocomm's AES-CTR dropping the intra-block remainder, so every message after a non-16-byte payload was garbled; the counter now follows one continuous keystream.- 修复
protocomm的 AES-CTR 丢弃块内余数,导致非 16 字节整数倍载荷之后的所有消息错位;计数器现遵循一条连续 keystream。
- 修复
-
Fixed
protocomm'ssetup1failing open, so a device omittingSessionResp1skipped Proof-of-Possession authentication; it now raises.- 修复
protocomm的 setup1 失败开放,省略SessionResp1的设备会跳过所有权证明鉴权;现在改为抛错。
- 修复
-
Fixed
PbReader/PbWriter: bounds checks, malformed-field tolerance and a negative varint guard.- 修复
PbReader/PbWriter:补充边界检查、畸形字段容错与负数 varint 防护。
- 修复
-
Fixed OTA: verify the server's resume start offset, reuse a single
http.Client, and release the BLE link on failure (try/finally).- 修复 OTA:校验服务端续传起始偏移、复用单个
http.Client,并在失败时(try/finally)释放 BLE 连接。
- 修复 OTA:校验服务端续传起始偏移、复用单个
-
Fixed the log collector: verify the MQTT connection (batches were silently dropped), disconnect stale clients, guard concurrent flushes and tolerate corrupt cache lines.
- 修复日志采集器:校验 MQTT 连接(此前批次被静默丢弃)、释放旧 client、防并发 flush 并容忍损坏的缓存行。
-
Fixed provisioning: poll for a terminal Wi-Fi state instead of reading it once, and release the scan subscription when scanning throws.
- 修复配网:轮询终态 Wi-Fi 状态而非只读一次,并在扫描抛错时释放扫描订阅。
-
Fixed BLE:
BleTeleopChannel.dispose()now stops the transport (a failed connect left the auto-reconnect timer running), and the link clears stale characteristic handles on reconnect, resets its retry budget, guards concurrent connects and closes its controllers.- 修复 BLE:
BleTeleopChannel.dispose()现在停止传输层(连接失败后自动重连定时器仍在运行),链路在重连时清除陈旧特征句柄、重置重试预算、防并发连接并关闭控制器。
- 修复 BLE:
-
Fixed
DualTeleopChannelcrashing whendisconnect()runs beforeconnect(); it can be reconnected afterwards.- 修复
DualTeleopChannel在connect()之前调用disconnect()会崩溃的问题;之后可重新连接。
- 修复
-
Fixed MQTT teleop: guard concurrent connects, release the previous client and subscription, verify the connection state and tolerate non-JSON telemetry.
- 修复 MQTT 遥操作:防并发连接、释放旧 client 与订阅、校验连接状态并容忍非 JSON 遥测。
-
Fixed resilience: dispose the previous session on reconnect (it was only left), serialise attaches, re-check
disposedafter awaits, rate-limit recovery actions, re-enable video after reconnect, only stop the robot on a background pause, require a session inconfirmResume()and clear orphan resume tickets.- 修复韧性层:重连时释放前一个会话(此前仅 leave)、串行化 attach、await 后复检 disposed、恢复动作限流、重连后重新开启视频、仅在后台暂停时停车、
confirmResume()要求会话存在并清除孤儿恢复票据。
- 修复韧性层:重连时释放前一个会话(此前仅 leave)、串行化 attach、await 后复检 disposed、恢复动作限流、重连后重新开启视频、仅在后台暂停时停车、
-
Fixed WHIP/WHEP: drain responses, close the HTTP client, resolve relative
Locationheaders, buffer trickle ICE candidates until the resource exists, guard concurrent peer-connection creation and clean up on failure.- 修复 WHIP/WHEP:排空响应、关闭 HTTP 客户端、解析相对
Location头、缓存 trickle ICE 候选直到资源就绪、防并发建连并在失败时清理。
- 修复 WHIP/WHEP:排空响应、关闭 HTTP 客户端、解析相对
-
Fixed
simulcast: everycasenow breaks — falling through made all layers end up atfull ~/ 4.- 修复 simulcast:每个 case 现在都 break——直通会让所有层最终变成
full ~/ 4。
- 修复 simulcast:每个 case 现在都 break——直通会让所有层最终变成
-
Fixed emits after
dispose()throwing "Cannot add event after closing": they are now ignored.- 修复
dispose()之后的 emit 抛 "Cannot add event after closing" 的问题:现在改为忽略。
- 修复
-
Fixed LAN discovery: stop a discovery cancelled before it started, and surface errors instead of losing them.
- 修复 LAN 发现:停止启动前被取消的 discovery,并上报错误而非将其丢失。
-
Fixed the scanners: drop the previous scan's replayed results and handle stream errors.
- 修复扫描器:丢弃上一次扫描的回放结果并处理流错误。
-
Fixed
stream_relay.stop()catching onlyRtcException: it now catches every error so cleanup always finishes, and releases the Egress HTTP client.- 修复
stream_relay.stop()只捕获RtcException的问题:现在捕获所有异常以保证清理完成,并释放 Egress HTTP 客户端。
- 修复
-
Fixed LiveKit:
dispose()is now idempotent on both the engine and the session, joining a disposed engine is rejected, andunsubscribe()reports the real track kind instead of always claiming video.- 修复 LiveKit:引擎与会话的
dispose()现在幂等、已释放的引擎拒绝入会、unsubscribe()上报真实轨道类型而非一律声称视频。
- 修复 LiveKit:引擎与会话的
-
Fixed
NetworkPath.isSameLinkAs(): a metered flip now counts as a different link, so a hotspot that starts charging triggers a policy re-evaluation.- 修复
NetworkPath.isSameLinkAs():计费状态翻转现在算作另一条链路,开始计费的热点会触发策略重算。
- 修复
-
Fixed
VideoGridControlleraccumulating stale clarity overrides: overrides of removed streams are now pruned, so long-running rooms no longer leak entries.- 修复
VideoGridController累积失效清晰度覆盖的问题:已移除流的覆盖会被清理,长时间运行的房间不再泄漏条目。
- 修复
-
Fixed
switchCamera()leaving a stale "camera active" status when the capture fails: the old device is already released, so the camera is now reported as off.- 修复采集失败时
switchCamera()留下"摄像头已开启"失效状态的问题:旧采集设备已释放,现如实上报为已关闭。
- 修复采集失败时
-
Fixed
switchToVariantStream(): it now registers the replacement before dropping the old subscriber (never hands out a disposed object) and releases the new server resource when the session is disposed mid-switch.- 修复
switchToVariantStream():先登记替代者再丢弃旧订阅器(绝不交出已销毁对象),并在切换期间会话被释放时清理新建的服务端资源。
- 修复
-
Fixed
RoleTransfer.handover()leaving two anchors publishing at once: when revoking the previous anchor fails, the first grant is rolled back.- 修复
RoleTransfer.handover()可能留下两个牵头同时推流的问题:收回原牵头失败时回滚第一次授权。
- 修复
-
Fixed LiveKit leaking a
Roomon every reconnect: the session now callsroom.dispose()afterdisconnect(), so long-running sessions no longer accumulate rooms (a source of connection/handle leaks during 7×24 operation).- 修复 LiveKit 每次重连泄漏
Room的问题:会话在disconnect()之后现在调用room.dispose(),长时间运行的会话不再累积 Room(7×24 运行期间连接 / 句柄泄漏的来源之一)。
- 修复 LiveKit 每次重连泄漏
-
Fixed
LiveKitPublisherleaks and false "active" status:dispose()now releases theValueNotifier(UI listeners no longer leak), andstartCamera/startMic/startScreenShareno longer report the track as active when the room is not connected or permission is denied (they now report it off).- 修复
LiveKitPublisher的泄漏与"已开启"假状态:dispose()现在释放ValueNotifier(UI 监听者不再泄漏);房间未连或权限被拒时,startCamera/startMic/startScreenShare不再谎报轨道已开启(现如实上报为关闭)。
- 修复
-
Fixed
Diagnosticsleaking a socket on a failed TLS handshake and aborting on one bad log line: the probe now destroys the underlying socket infinally, and crash-log parsing guards the type and skips corrupt lines instead of throwing.- 修复
Diagnostics在 TLS 握手失败时泄漏 socket、且一条坏日志就中止整个诊断的问题:探测现在在finally销毁底层 socket,崩溃日志解析增加类型防护并跳过损坏行而非抛异常。
- 修复
-
Fixed
AppLifecycleGatetearing the link down after the app returned to the foreground: lifecycle transitions are now serialised, so a rapid background→foreground toggle ends in the foreground.- 修复
AppLifecycleGate在应用回到前台后错误拆除链路的问题:生命周期切换现已串行化,快速的"后台→前台"切换最终落在前台。
- 修复
-
Fixed
ControlLinkRoutermislabeling a multi-path selection asonlyOption: when several reachable paths tie on RTT it now reportslowestRttinstead of falsely claiming there was only one path.- 修复
ControlLinkRouter把多路径选择误标为onlyOption的问题:多条可达路径 RTT 恰好相等时,现改为上报lowestRtt,而非谎称只有一条路径。
- 修复
Release v0.3.0
Added / 新增
- Persistent BLE GATT teleop control channel. / 基于 BLE GATT 的持久控制通道。
BleTeleopChannel implements TeleopChanneldrops straight intoRobotController/DualTeleopChannel— the watchdog, epoch gating and keepalive are unchanged; only the transport changes. /BleTeleopChannel implements TeleopChannel,可直接接入RobotController/DualTeleopChannel——看门狗、epoch 门控与保活逻辑不变,仅传输换了。FlutterBluePlusBleLinkresolves the GATT service + command/telemetry characteristics, negotiates a larger MTU (256), subscribes to telemetry notifications, and auto-reconnects on a drop (capped, exponential backoff). /FlutterBluePlusBleLink解析 GATT 服务与指令 / 遥测特征、协商更大 MTU(256)、订阅遥测通知,并在断线后自动重连(有上限、指数退避)。BleTeleopDiscovererscans for the teleop GATT service;BleDevicekeeps the public API free offlutter_blue_plustypes. Command/telemetry reuse the JSON envelopes of the other channels. /BleTeleopDiscoverer扫描遥测 GATT 服务;BleDevice让公开 API 不暴露flutter_blue_plus类型。指令 / 遥测复用其它通道的 JSON 封包。- Example
ble_control_demo_pageand website docs (ble_control.md,zh/) with the GATT contract. / 示例ble_control_demo_page与文档站(ble_control.md、中文版)含 GATT 契约。
- Protocol-agnostic BLE for any device (speaker, sensor, peripheral — not just robots). / 面向任意设备(音响、传感器、外设——不限于机器人)的、与协议无关的通用 BLE。
BleScannerdiscovers nearby devices with no service filter (or narrowed toserviceUuids), returning the sameBleDevicethe teleop path uses. /BleScanner无需服务过滤即可发现附近设备(也可按serviceUuids收敛),返回与遥测路径相同的BleDevice。BleGattClientconnects to aBleDevice, discovers services, and exposes rawread/write/subscribeplus aconnectionStatestream — no teleop / ESP contract assumed. /BleGattClient连接BleDevice、发现服务,并暴露原始的read/write/subscribe与连接状态流——不做任何遥测 / ESP 契约假设。BleScannerandBleGattClientare exported from the package root and built onflutter_blue_plus, keeping exactly one Bluetooth library in the dependency tree. /BleScanner与BleGattClient均从包根导出,基于flutter_blue_plus,使依赖树中恰好只有一个蓝牙库。- Example
ble_control_demo_pageadds a Teleop / All devices toggle: "All devices" connects viaBleGattClientand shows the GATT services / characteristics (tap a readable characteristic to read it). / 示例ble_control_demo_page新增 Teleop / All devices 切换:"All devices" 经BleGattClient连接并展示 GATT 服务 / 特征(点击可读取的特征即可读取值)。
Release v0.2.0
Added / 新增
- 4K (2160p) publish support. / 4K(2160p)发布支持。
- New
ClarityLevel.p2160(height 2160, label2160p, suggested full-layer cap 8000 kbps). / 新增ClarityLevel.p2160(高度 2160,标签2160p,满层建议码率上限 8000 kbps)。 - LiveKit
capturePresetFor/simulcastLayersFornow mapp2160toVideoParametersPresets.h2160_169(capture 3840×2160 with 180p/540p/1080p/2160p simulcast layers). / LiveKit 的capturePresetFor/simulcastLayersFor现在将p2160映射到h2160_169(采集 3840×2160,simulcast 层为 180p/540p/1080p/2160p)。 - WHIP/WHEP publishers derive the 16:9 capture width from the clarity height, so
p2160automatically requests 3840×2160. / WHIP/WHEP 推流器按清晰度高度推导 16:9 采集宽度,p2160自动请求 3840×2160。 - Clarity selector UI in
RtcControlBarand the examplertc_demo_pagenow offer2160p. /RtcControlBar与示例rtc_demo_page的清晰度选择器现已提供2160p。 fromHeightmaps 1080p < height ≤ 2160 top2160, anddegradeClarityladder starts atp2160. /fromHeight将 1080p < 高度 ≤ 2160 映射为p2160,degradeClarity阶梯顶端为p2160。
- New
Fixed / 修复
- Negative bitrate after ICE restart / network handover:
RtcStatsSamplercompared the new peer connection's byte counter (which resets to ~0) against the previous cumulative baseline, producing a bogus negativebitrateKbpsfor one sample. The sampler now treats a counter reset as zero bitrate, andWhipWhepPublisher.restartIceresets both the video and audio samplers.RtcStatsSampleralso accepts an injectable clock for deterministic tests.- ICE 重启 / 网络切换后的负码率:
RtcStatsSampler会把新 peer connection 的字节计数器(归零)与之前累计的基线比较,导致某一帧bitrateKbps出现虚假负值。现改为将计数器重置视为零码率,且WhipWhepPublisher.restartIce会同时重置视频与音频采样器。RtcStatsSampler现支持注入可测时钟。
- ICE 重启 / 网络切换后的负码率:
Release v0.1.3
Added / 新增
LocalPublisher.cameraStream(flutter_webrtcMediaStream?): exposes the camera media stream so consumers can render a local preview with a fullMediaStream(binding only a track id does not render on Android).WhipWhepPublisherpopulates it from the active capture stream;LiveKitPublisherreturnsnull(LiveKit previews its own tracks vialk.VideoTrackRenderer, not a flutter_webrtc stream).LocalPublisher.cameraStream(flutter_webrtc的MediaStream?):暴露摄像头媒体流,便于消费者用完整MediaStream渲染本地预览(只绑 track id 在 Android 上不会出画)。WhipWhepPublisher从当前采集流填充该值;LiveKitPublisher返回null(LiveKit 经自身的lk.VideoTrackRenderer渲染预览,不依赖 flutter_webrtc 的 stream)。
Changed / 变更
- Raised the
permission_handlerconstraint from^11.0.0to^12.0.0. 12.0.0 only requires AndroidcompileSdk 35(itspermission_handler_androidsubmodule is 13.0.0), which is still ≤ the default Flutter template's 36, so the AGP 9.1.0 / compileSdk 36 build is unaffected and the earlier "API ≤ 36" rationale still holds. The plugin's own usage ofpermission_handler(thePermissionenum,request(),status,openAppSettings()) is unchanged.- 将
permission_handler约束由^11.0.0提升到^12.0.0。12.0.0 仅需 AndroidcompileSdk 35(底层permission_handler_android子模块为 13.0.0),仍 ≤ 默认 Flutter 模板的 36,因此 AGP 9.1.0 / compileSdk 36 构建不受影响,先前"API ≤ 36"的考量依旧成立;插件对其 Dart API(Permission枚举、request()、status、openAppSettings())的用法无变更。
- 将
Release v0.1.2
Fixed / 修复
- Example app device-page action row overflow on narrow screens: the SCAN BLE / DPP / NFC buttons were laid out in a fixed three-up
Rowthat overflowed; they now wrap so they flow to the next line when space is tight.- 示例应用设备页操作行在窄屏溢出:SCAN BLE / DPP / NFC 原本排成固定三列
Row会溢出;现已改为自动换行。
- 示例应用设备页操作行在窄屏溢出:SCAN BLE / DPP / NFC 原本排成固定三列
- Lowered the
permission_handlerconstraint to^11.0.0so its Android submodule stays at API ≤ 36, keeping the default Flutter template (AGP 9.1.0 / compileSdk 36) buildable without forcing an AGP / Gradle upgrade.- 将
permission_handler约束降到^11.0.0,使其 Android 子模块停留在 API ≤ 36,从而默认 Flutter 模板(AGP 9.1.0 / compileSdk 36)无需升级 AGP / Gradle 即可构建。
- 将
Release v0.1.1
Fixed / 修复
- Joystick crash on first release:
_animationwas declaredlate finalbut reassigned in_release(), throwingLateInitializationError. It is now a reassignablelatefield.- 摇杆首次松手崩溃:
_animation被声明为late final却在_release()中二次赋值,抛LateInitializationError;现改为可重新赋值的late字段。
- 摇杆首次松手崩溃:
- LiveKit multi-stream subscription revocation: subscribing a second stream overwrote the track-subscription allowlist and revoked the first. Wanted track SIDs are now accumulated per participant and re-granted together.
- LiveKit 多路订阅互相撤销:订阅第二路时覆盖轨道订阅白名单、撤销第一路;现按参与者累加想要的轨道 SID 并统一重新授权。
- ResilientSession re-entrant reconnect double scheduling: the
_recoveringguard was set afterawait pause(), letting two racing events both schedule a backoff timer. The guard is now taken synchronously before the await.- ResilientSession 重入重连双调度:
_recovering守卫在await pause()之后才置位,两类并发事件可同时穿过并各调度一个退避定时器;现改为在 await 前同步加锁。
- ResilientSession 重入重连双调度:
- ResilientSession never emitted
RtcConnected: the session's ownRtcConnectedwas suppressed in_onSessionEventbut never re-emitted byResilientSession, so consumers never learned a link was (re)established. It is now emitted from_establish.- ResilientSession 从不对外发出
RtcConnected:会话自身的RtcConnected在_onSessionEvent中被抑制,而ResilientSession又从未补发,导致消费者永远收不到连接成功事件;现由_establish补发。
- ResilientSession 从不对外发出
setBackground(false)duplicate resume: whenautoResumeAfterReconnectis enabled,_afterReconnectalready resumed the gate, yet the foreground path requested a second (orphaned) resume ticket. The foreground path now skips resume in that case.setBackground(false)重复恢复:开启autoResumeAfterReconnect时_afterReconnect已处理门的恢复,回到前台又发起一个被废弃的恢复票据;现已在该情况下跳过。
- LanDiscovery.discoverStream early-cancel crash:
onCanceltouchedlatediscovery/listener fields that were not yet initialized if the stream was cancelled beforestartDiscoveryresolved, throwingLateInitializationError. They are now nullable with null checks.- LanDiscovery.discoverStream 提前取消崩溃:
onCancel访问尚未初始化的late字段(流在startDiscovery完成前被取消时),抛LateInitializationError;现改为可空并加空判断。
- LanDiscovery.discoverStream 提前取消崩溃:
Release v0.1.0
Added / 新增
- Initial release of
flutter_rtc_link: a Flutter plugin for real-time audio/video and IoT device management with a dual-engine architecture (WhipWhepEngineoverflutter_webrtc,LiveKitEngineoverlivekit_client) behind one unified abstraction (RtcEngine/RtcSession/LocalPublisher/RemoteSubscriber).flutter_rtc_link首个版本:实时音视频 + 物联网设备管理插件,双引擎架构(基于flutter_webrtc的WhipWhepEngine与基于livekit_client的LiveKitEngine)统一抽象(RtcEngine/RtcSession/LocalPublisher/RemoteSubscriber)。
- Lead-operator publishing with simulcast:
startCamera/startMic/startScreenShare, zero-renegotiationswitchCameraviareplaceTrack(RFC 9725 friendly), andsetPublishClaritythat caps the top simulcast layer.- 牵头操作者推流(simulcast 多层):
startCamera/startMic/startScreenShare、经replaceTrack的零重协商switchCamera(符合 RFC 9725),以及只限制最高层的setPublishClarity。
- 牵头操作者推流(simulcast 多层):
- Subscription and picture switching: WHEP playback, per-stream
RemoteSubscriber.setClarity, and a pure-DartVideoGridController(main/pip/grid layouts, max visible, global clarity).- 订阅与画面切换:WHEP 拉流、每路独立的
RemoteSubscriber.setClarity,以及纯 Dart 的VideoGridController(主画面 / 画中画 / 网格布局、最大可见数、全局清晰度)。
- 订阅与画面切换:WHEP 拉流、每路独立的
- Live relay:
RoleTransfer.promote/handover(identity handover) andStreamRelay.toRtmp/cascade(server-side Egress or secondary WHIP push).- 直播转接:
RoleTransfer.promote/handover(身份交接)与StreamRelay.toRtmp/cascade(服务端 Egress 或二次 WHIP 推流)。
- 直播转接:
- Robot teleoperation:
RobotControllerwith joystick velocity integration, PTZ, telemetry, voice intercom hookup, and a 500 ms watchdog that auto-stops the robot on command timeout or link loss.- 机器人远控:
RobotController支持摇杆速度积分、云台 PTZ、遥测、语音对讲接入,以及指令超时 / 断链 500ms 内自动停车的看门狗保护。
- 机器人远控:
- IoT device management suite: multi-channel
DeviceProvisioning(BLE → DPP/QR → NFC → SoftAP → SmartConfig strategy chain with automatic degradation),OtaUpdater(BLE/HTTP with SHA-256 verification),DeviceLogCollector(local cache + batch upload), andDiagnostics(WebRTC stats + network probe + device logs → JSON/Markdown report).- 物联网设备管理四件套:多通道
DeviceProvisioning(BLE → DPP/QR → NFC → SoftAP → SmartConfig 策略链,失败自动降级)、OtaUpdater(BLE/HTTP,SHA-256 校验)、DeviceLogCollector(本地缓存 + 批量补传)、Diagnostics(WebRTC stats + 网络探测 + 设备日志 → JSON/Markdown 报告)。
- 物联网设备管理四件套:多通道
- Unified permission gate
RtcPermissions.requestAll(capabilities)covering the Android 13/14+ and iOS pitfalls (foreground-service microphone, nearby Wi-Fi devices, NFC entitlement); denials degrade features and emitRtcEvent.permissionDeniedinstead of crashing.- 统一权限入口
RtcPermissions.requestAll(capabilities),覆盖 Android 13/14+ 与 iOS 的权限坑(前台服务麦克风、附近 Wi-Fi 设备、NFC entitlement);权限被拒时功能降级并上报RtcEvent.permissionDenied,不崩溃。
- 统一权限入口
- Native modules: Android DPP (Wi-Fi Easy Connect) platform channel and a microphone foreground service; iOS Swift method-channel stub. Method channel prefix
pkg.flutter.dev/rtc_link/with centralizedRtcErrorCodes.- 原生模块:Android DPP(Wi-Fi Easy Connect)平台通道与麦克风前台服务;iOS Swift method channel 桩。Method channel 前缀
pkg.flutter.dev/rtc_link/,错误码集中定义于RtcErrorCodes。
- 原生模块:Android DPP(Wi-Fi Easy Connect)平台通道与麦克风前台服务;iOS Swift method channel 桩。Method channel 前缀
- Ready-to-run example app (publish/subscribe, robot joystick, device management demos) and unit tests for the layout, clarity, relay, watchdog, provisioning, log-cache and diagnostics paths.
- 可直接运行的 example 应用(推流 / 订阅、机器人摇杆、设备管理演示)以及布局、清晰度、转接、看门狗、配网、日志缓存与诊断路径的单元测试。
- Resilience layer for overseas / cross-public-network links:
ResilientSession(supervised connect, jittered backoff reconnect with automatic re-subscription),RelayPlanner(per-region TURN ordering +RelayMode.forcedescalation for CGNAT / cross-border paths),NetworkPathMonitor(Wi-Fi ↔ cellular handover → ICE restart) andMediaHealthMonitor(stutter / congestion / frozen-picture detection with keyframe → downgrade → re-subscribe recovery).- 面向海外 / 跨公网链路的韧性层:
ResilientSession(受控建链、带抖动退避重连并自动重新订阅)、RelayPlanner(按区域排序 TURN + 面向 CGNAT / 跨境路径的RelayMode.forced升级)、NetworkPathMonitor(Wi-Fi ↔ 蜂窝切换触发 ICE 重启)与MediaHealthMonitor(卡顿 / 拥塞 / 画面冻结检测,并按请求关键帧 → 降档 → 重建订阅逐级恢复)。
- 面向海外 / 跨公网链路的韧性层:
- App-side pause/resume confirmation flow:
PauseResumeGatestamps every operation with an epoch; pausing bumps the epoch so buffered operations are dropped instead of replayed, and resuming is a two-step ticket handshake (requestResume→confirmResume) that expires.EpochOperationQueueadds latest-wins buffering for teleoperation.- 应用侧暂停 / 恢复确认流程:
PauseResumeGate为每个操作盖上 epoch 戳;暂停会递增 epoch,使缓存操作被丢弃而非补发;恢复是一次会过期的两步票据握手(requestResume→confirmResume)。EpochOperationQueue为遥控提供"最新者胜"缓冲。
- 应用侧暂停 / 恢复确认流程:
- Low-latency control link helpers:
ControlLinkRouter(data channel preferred, MQTT fallback, latency budget),ControlRttTrackerandCommandRateLimiter.- 低时延控制链路辅助:
ControlLinkRouter(优先数据通道、回退 MQTT、带时延预算)、ControlRttTracker与CommandRateLimiter。
- 低时延控制链路辅助:
AppLifecycleGate: maps Flutter lifecycle states (paused/hidden/detached) to background suspension and drives the pause/resume gate.AppLifecycleGate:把 Flutter 生命周期状态(paused/hidden/detached)映射为后台暂停,并驱动暂停 / 恢复门。
Changed / 变更
RobotControlleraccepts an optionalPauseResumeGateandCommandRateLimiter;pause()stops the robot immediately and invalidates every command issued before it, and the keepalive loop never replays a pre-pause velocity.RobotController可接收可选的PauseResumeGate与CommandRateLimiter;pause()立即停车并让此前所有指令失效,保活循环绝不补发暂停前的速度。
WhipWhepSessionimplementsIceRestartable: handover now rebuilds the peer connections with a fresh ICE configuration (WHIP/WHEP forbids renegotiation, RFC 9725).WhipWhepSession实现了IceRestartable:切换时会用全新的 ICE 配置重建 peer connection(RFC 9725 规定 WHIP/WHEP 不可重协商)。