信息
局域网设备
更新时间:2026-04-03 11:20:37
当手机与设备处于同一局域网(非公网)时,即可通过局域网搜索设备,并与设备建立局域网连接,连接成功以后可以进行设备播放(包括:直播、SD卡回放)、PTZ操作、获取SD卡回放数据等。
// 导入头文件
import 'package:airtc_engine/src/wlan_link/rtcx_wlan_link_device.dart';
import 'package:airtc_engine/src/wlan_link/rtcx_wlan_link_controller.dart';
class RTCXFluWlanLinkApi {
/// 获取局域网设备
void startSearchWlanDeviceOnCallback();
/// 通过设备IP搜索局域网设备
void startSearchWlanDevice(String ip);
/// 停止搜索局域网设备
void stopSearchWlanDevice();
/// 开始局域网设备连接请求
void startConnect(RTCXFluWlanLinkDevModel req);
/// 断开局域网设备连接
void disConnect();
/// 请求网关的子设备列表
@async
List<RTCXFluWlanLinkDevModel> queryGatewaySubdeviceList(
RTCXFluWlanLinkDevModel req,
);
/// 退出局域网模式
void exitWlanLink();
}
RTCXFluWlanDeviceCallback {
void onWlanDeviceUpdate(RTCXFluWlanLinkDevModel model);
void onWlanDeviceComplete();
void onWlanConnectResult(RTCXFluWlanLinkResult result, RTCXFluWlanLinkDevModel model);
void onWlanConnectError(int errorCode, String errorMsg);
}
API初始化设置
late RTCXFluWlanLinkController _rtcxFluWlanLink;
List<RTCXFluWlanLinkDevModel> dataList = [];
bool _isRefreshing = false;
@override
void initState() {
super.initState();
_rtcxFluWlanLink = RTCXFluWlanLinkController();
_rtcxFluWlanLink.onConnectError.listen((data) {});
_rtcxFluWlanLink.onDeviceUpdate.listen((data) {
setState(() {
// 检查是否已存在,避免重复添加
final exists = dataList.any((item) => item.iotId == data.iotId);
if (!exists) {
dataList.add(data);
}
for (RTCXFluWlanLinkDevModel model in dataList) {
print("model:${model.deviceName},${model.productKey}");
}
});
});
_rtcxFluWlanLink.onConnectResult.listen((data) {
if (data.result.success) {
Fluttertoast.showToast(msg: "连接成功");
} else {
Fluttertoast.showToast(msg: "连接断开");
}
});
_rtcxFluWlanLink.onDeviceComplete.listen((data) {
Fluttertoast.showToast(msg: "搜索完成");
});
}
@override
void dispose() {
_rtcxFluWlanLink.stopSearchWlanDevice();
_rtcxFluWlanLink.exitWlanLink();
_rtcxFluWlanLink.destroy();
super.dispose();
}
搜索设备
当手机与设备处于同一局域网以后,可以通过调用搜索设备接口搜索周围局域网设备,如果周围有多台设备响应,该接口会回调多次,上层可通过UI列表展示。
try {
await _rtcxFluWlanLink.startSearchWlanDeviceOnCallback();
} catch (e) {
Fluttertoast.showToast(msg: "搜索失败:${e.toString()}");
}
也可以通过指定IP,直接搜索指定的设备
try {
await _rtcxFluWlanLink.startSearchWlanDevice(ip);
} catch (e) {
Fluttertoast.showToast(msg: "搜索失败:${e.toString()}");
}
停止搜索设备
当不再需要继续搜索局域网设备的时候,可通过调用该接口停止搜索设备
_rtcxFluWlanLink.stopSearchWlanDevice();
网关设备列表
当搜索到的是网关设备(即搜索返回数据模型:RTCXWlanLinkDevInfo.isGateway = YES)时,可以获取该网关下面的所有设备列表,非网关设备不需要调用此接口。
try {
RTCXFluWlanLinkDevModel req = RTCXFluWlanLinkDevModel(
productKey: "productKey",
deviceName: "deviceName"
);
List<RTCXFluWlanLinkDevModel> list = await _rtcxFluWlanLink.queryGatewaySubdeviceList(req);
print("queryGatewaySubdeviceList:${list}");
} catch (e) {
Fluttertoast.showToast(msg: "获取失败:${e.toString()}");
}
连接设备
在设备播放之前,需要先进行设备连接,只有设备连接成功以后才可以进行设备播放、PTZ操作等,建议在搜索到设备以后就提前建立设备连接。
Future<void> startConnect(RTCXFluWlanLinkDevModel? info) async {
if (info == null) {
return;
}
try {
await _rtcxFluWlanLink.startConnect(info);
} catch (e) {
Fluttertoast.showToast(msg: "${e.toString()}");
}
}
断开连接设备
当不再需要连接设备时,如:退出局域网设备列表,需要断开设备连接,释放资源。
Future<void> disconnect() async {
try {
await _rtcxFluWlanLink.disConnect();
} catch (e) {
Fluttertoast.showToast(msg: "${e.toString()}");
}
}
设备播放
局域网设备播放接口与通用版基本相同,请先阅读【通用版-音视频播放】相关接口,只是在构建PlayerView播放控件,需要设置deviceType = 2,即区分是局域网设备。
// 导入头文件
import 'package:airtc_engine/src/media/rtcx_media_player.dart';
import 'package:airtc_engine/src/audio_video_talk/rtcx_audio_video_talk.dart';
import 'package:airtc_engine/src/audio_video_talk/rtcx_audio_video_talk_controller.dart';
import 'package:airtc_engine/src/media/player_view.dart';
import 'package:airtc_engine/src/media/player_view_controller.dart';
调用示例如下:
- 直播
final PlayerViewController _controller = PlayerViewController();
@override
void initState() {
super.initState();
// 注册 _controller 的所有回调监听
_controller.playStateChangeStream.listen((data) {
print(
'播放状态变化: viewId=${data.viewId}, playState=${data.playState}, errorCode=${data.errorCode}',
);
});
_controller.playFrameChangeStream.listen((data) {
print(
'视频尺寸变化: viewId=${data.viewId}, width=${data.videoSize.width}, height=${data.videoSize.height}',
);
});
_controller.playTracesChangeStream.listen((data) {
print(
'播放Trace: viewId=${data.viewId}, playTrace=${data.playTrace}, timestamp=${data.timestamp}, msg=${data.msg}',
);
});
_controller.playerMp4RecordStream.listen((data) {
print(
'录制回调: viewId=${data.viewId}, currentTime=${data.currentTime}, filePath=${data.filePath}',
);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('视频播放')),
body: Column(
children: [
Expanded(
flex: 1,
child: PlayerView(
iotId: widget.iotId,
productKey: widget.productKey,
deviceName: widget.deviceName,
deviceType: 2,
controller: _controller,
),
),
]));}
@override
void dispose() {
// 取消所有回调订阅
_controller.disposeView();
_controller.destroy();
_talkApi.release();
super.dispose();
}
- PTZ控制
通过物模型服务来实现PTZ控制功能
// 导入物模型头文件
import 'package:airtc_engine/src/thing/rtcx_thing.dart';
import 'package:airtc_engine/src/thing/rtcx_thing_controller.dart';
late RTCXFluThingController _thingApi;
@override
void initState() {
super.initState();
// 物模型
RTCXFluThingReq req = RTCXFluThingReq(
productKey: widget.productKey,
deviceName: widget.deviceName,
iotId: widget.iotId,
deviceType: widget.deviceType,
);
_thingApi = RTCXFluThingController();
_thingApi.buildThing(req);
_thingApi.registerThingObserver();
_thingApi.onStatusChange.listen((data) {
print("onStatusChange:"+data.toString());
});
_thingApi.onDeviceTransferMessage.listen((RTCXFluThingObserver observer) {
print("onDeviceTransferMessage:"+observer.toString());
});
}
// 实现PTZ控制功能
// 传入command、params、extraData
Future<void> ptzActionControl() async {
try {
final result = await _thingApi.invokeService(
RTCXFluThingCommand(
command: "PTZActionControl",
params: {
"ActionType": 1,
"Step": 10,
},
),
);
if(result.success && result.dataObject != null) {
Map<String, dynamic> dataObjectMap = jsonDecode(result.dataObject!);
}
print("ptzActionControl result:${result.success},dataObject:${result.dataObject}");
} catch(e) {
print("ptzActionControl e:${e.toString()}");
}
}
// 不需要的时候需要做destroy释放操作
@override
void dispose() {
super.dispose();
_thingApi.destroy();
}