@@ -3,8 +3,10 @@ import 'dart:convert';
33import 'dart:io' ;
44
55import 'package:collection/collection.dart' ;
6+ import 'package:device_info_plus/device_info_plus.dart' ;
67import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc;
78import 'package:rxdart/rxdart.dart' ;
9+ import 'package:system_info2/system_info2.dart' ;
810import 'package:webrtc_interface/webrtc_interface.dart' ;
911
1012import '../../../protobuf/video/sfu/event/events.pb.dart' as sfu_events;
@@ -90,6 +92,8 @@ class CallSession extends Disposable {
9092 StreamSubscription <Map <String , dynamic >>? _statsSubscription;
9193 Timer ? _peerConnectionCheckTimer;
9294
95+ sfu_models.ClientDetails ? _clientDetails;
96+
9397 SharedEmitter <CallStats > get stats => _stats;
9498 late final _stats = MutableSharedEmitterImpl <CallStats >();
9599
@@ -107,10 +111,88 @@ class CallSession extends Disposable {
107111 onCancel: () => Result .error ('UpdateViewportVisibility cancelled' ),
108112 );
109113
114+ Future <void > _ensureClientDetails () async {
115+ if (_clientDetails != null ) return ;
116+
117+ try {
118+ sfu_models.Device ? device;
119+ sfu_models.Browser ? browser;
120+
121+ var os = sfu_models.OS (
122+ name: SysInfo .operatingSystemName,
123+ version: SysInfo .operatingSystemVersion,
124+ architecture: SysInfo .rawKernelArchitecture,
125+ );
126+
127+ if (CurrentPlatform .isAndroid) {
128+ final deviceInfo = await DeviceInfoPlugin ().androidInfo;
129+ os = sfu_models.OS (
130+ name: 'Android' ,
131+ version: deviceInfo.version.release,
132+ architecture: SysInfo .rawKernelArchitecture,
133+ );
134+ device = sfu_models.Device (
135+ name: '${deviceInfo .manufacturer } : ${deviceInfo .model }' ,
136+ );
137+ } else if (CurrentPlatform .isIos) {
138+ final deviceInfo = await DeviceInfoPlugin ().iosInfo;
139+ os = sfu_models.OS (
140+ name: 'iOS' ,
141+ version: deviceInfo.systemVersion,
142+ architecture: SysInfo .rawKernelArchitecture,
143+ );
144+ device = sfu_models.Device (
145+ name: deviceInfo.model,
146+ );
147+ } else if (CurrentPlatform .isWeb) {
148+ final browserInfo = await DeviceInfoPlugin ().webBrowserInfo;
149+ browser = sfu_models.Browser (
150+ name: browserInfo.browserName.name,
151+ version: browserInfo.vendorSub,
152+ );
153+ } else if (CurrentPlatform .isMacOS) {
154+ final deviceInfo = await DeviceInfoPlugin ().macOsInfo;
155+ device = sfu_models.Device (
156+ name: deviceInfo.model,
157+ version: deviceInfo.osRelease,
158+ );
159+ } else if (CurrentPlatform .isWindows) {
160+ final deviceInfo = await DeviceInfoPlugin ().windowsInfo;
161+ device = sfu_models.Device (
162+ name: deviceInfo.productName,
163+ version: deviceInfo.buildNumber.toString (),
164+ );
165+ } else if (CurrentPlatform .isLinux) {
166+ final deviceInfo = await DeviceInfoPlugin ().linuxInfo;
167+ device = sfu_models.Device (
168+ name: deviceInfo.name,
169+ version: deviceInfo.version,
170+ );
171+ }
172+
173+ final versionSplit = streamVideoVersion.split ('.' );
174+ _clientDetails = sfu_models.ClientDetails (
175+ sdk: sfu_models.Sdk (
176+ type: sfu_models.SdkType .SDK_TYPE_FLUTTER ,
177+ major: versionSplit.first,
178+ minor: versionSplit.skip (1 ).first,
179+ patch: versionSplit.last,
180+ ),
181+ os: os,
182+ device: device,
183+ browser: browser,
184+ );
185+ } catch (e) {
186+ _logger.e (() => '[_ensureClientDetails] failed: $e ' );
187+ }
188+ }
189+
110190 Future <Result <None >> start () async {
111191 try {
112192 _logger.d (() => '[start] no args' );
113193
194+ await _ensureClientDetails ();
195+
114196 await _eventsSubscription? .cancel ();
115197 await _rtcManagerSubject? .close ();
116198
@@ -140,6 +222,7 @@ class CallSession extends Disposable {
140222 sfuWS.send (
141223 sfu_events.SfuRequest (
142224 joinRequest: sfu_events.JoinRequest (
225+ clientDetails: _clientDetails,
143226 token: config.sfuToken,
144227 sessionId: sessionId,
145228 subscriberSdp: genericSdp,
@@ -202,13 +285,16 @@ class CallSession extends Disposable {
202285 final genericSdp = await RtcManager .getGenericSdp ();
203286 _logger.v (() => '[fastReconnect] genericSdp.len: ${genericSdp .length }' );
204287
288+ await _ensureClientDetails ();
289+
205290 await _eventsSubscription? .cancel ();
206291 _eventsSubscription = sfuWS.events.listen (_onSfuEvent);
207292 await sfuWS.connect ();
208293
209294 sfuWS.send (
210295 sfu_events.SfuRequest (
211296 joinRequest: sfu_events.JoinRequest (
297+ clientDetails: _clientDetails,
212298 token: config.sfuToken,
213299 sessionId: sessionId,
214300 subscriberSdp: genericSdp,
0 commit comments