From e85c005f6110992312a4a7e5c2377373caa9cb75 Mon Sep 17 00:00:00 2001 From: phuoc Date: Wed, 8 May 2024 09:19:43 +0700 Subject: [PATCH 1/2] fix: improve fetching device Signed-off-by: phuoc --- .../detail/preview/canvas_device_bloc.dart | 11 ++- lib/service/canvas_client_service.dart | 72 ++++++++----------- lib/service/mdns_service.dart | 11 ++- 3 files changed, 41 insertions(+), 53 deletions(-) diff --git a/lib/screen/detail/preview/canvas_device_bloc.dart b/lib/screen/detail/preview/canvas_device_bloc.dart index 662afd83b..f86594b39 100644 --- a/lib/screen/detail/preview/canvas_device_bloc.dart +++ b/lib/screen/detail/preview/canvas_device_bloc.dart @@ -161,10 +161,8 @@ class CanvasDeviceState { .firstWhereOrNull((deviceState) => deviceState.device.isConnecting) ?.device; - bool get isCasting { - return devices.any((element) => - element.device == controllingDevice && element.isPlaying == true); - } + bool get isCasting => devices.any((element) => + element.device == controllingDevice && element.isPlaying == true); } class DeviceState { @@ -209,8 +207,7 @@ class CanvasDeviceBloc extends AuBloc { on((event, emit) async { emit(CanvasDeviceState( devices: state.devices, isLoaded: state.devices.isNotEmpty)); - final devices = await _canvasClientService.getConnectingDevices( - doSync: event.syncAll); + final devices = await _canvasClientService.scanDevices(); emit( state.copyWith( devices: devices.map((e) => DeviceState(device: e)).toList(), @@ -280,7 +277,7 @@ class CanvasDeviceBloc extends AuBloc { on((event, emit) async { final device = event.device; try { - await _canvasClientService.uncastSingleArtwork(device); + await _canvasClientService.unCastSingleArtwork(device); emit(state.replaceDeviceState( device: device, deviceState: DeviceState(device: device))); } catch (_) {} diff --git a/lib/service/canvas_client_service.dart b/lib/service/canvas_client_service.dart index a3ec6efbd..6206a3636 100644 --- a/lib/service/canvas_client_service.dart +++ b/lib/service/canvas_client_service.dart @@ -4,7 +4,6 @@ import 'package:autonomy_flutter/common/injector.dart'; import 'package:autonomy_flutter/database/app_database.dart'; import 'package:autonomy_flutter/model/pair.dart'; import 'package:autonomy_flutter/model/play_list_model.dart'; -import 'package:autonomy_flutter/model/shared_postcard.dart'; import 'package:autonomy_flutter/screen/detail/preview/canvas_device_bloc.dart'; import 'package:autonomy_flutter/service/account_service.dart'; import 'package:autonomy_flutter/service/mdns_service.dart'; @@ -45,13 +44,10 @@ class CanvasClientService { _deviceName = await device.getMachineName() ?? 'Autonomy App'; final account = await _accountService.getDefaultAccount(); _deviceId = await account.getAccountDID(); + await _mdnsService.start(); _didInitialized = true; } - Future shutdownAll() async { - await Future.wait(_viewingDevices.map((e) => shutDown(e))); - } - Future shutDown(CanvasDevice device) async { final channel = _getChannel(device); await channel.shutdown(); @@ -151,9 +147,20 @@ class CanvasClientService { return Pair(status, sceneId); } - Future syncDevices() async { - final devices = await _getAllDevices(); - final List devicesToAdd = []; + Future> _findRawDevices() async { + final devices = []; + final discoverDevices = await _mdnsService.findCanvas(); + final localDevices = await _db.canvasDeviceDao.getCanvasDevices(); + localDevices.removeWhere((l) => discoverDevices.any((d) => d.ip == l.ip)); + devices + ..addAll(discoverDevices) + ..addAll(await refreshDevices(localDevices)); + return devices; + } + + /// This method will check the status of the devices by calling grpc + Future> refreshDevices(List devices) async { + final List workingDevices = []; await Future.forEach(devices, (device) async { final status = await checkDeviceStatus(device); switch (status.first) { @@ -161,12 +168,12 @@ class CanvasClientService { case CanvasServerStatus.connected: device.playingSceneId = status.second; device.isConnecting = true; - devicesToAdd.add(device); + workingDevices.add(device); break; case CanvasServerStatus.open: device.playingSceneId = status.second; device.isConnecting = false; - devicesToAdd.add(device); + workingDevices.add(device); break; case CanvasServerStatus.notServing: break; @@ -174,40 +181,17 @@ class CanvasClientService { break; } }); - _viewingDevices - ..clear() - ..addAll(devicesToAdd) - ..unique((element) => element.ip); - log.info( - 'CanvasClientService sync device available ${_viewingDevices.length}'); - } - - Future> _getAllDevices() async => fetchDevices(); - - Future> getConnectingDevices({bool doSync = false}) async { - if (doSync) { - await syncDevices(); - } else { - for (var device in _viewingDevices) { - final status = await checkDeviceStatus(device); - device.playingSceneId = status.second; - } - } - return _viewingDevices; + log.info('CanvasClientService refresh device ${workingDevices.length}'); + return workingDevices; } - Future> _findRawDevices() async { - final devices = []; - final discoverDevices = await _mdnsService.findCanvas(); - final localDevices = await _db.canvasDeviceDao.getCanvasDevices(); - localDevices.removeWhere((l) => discoverDevices.any((d) => d.ip == l.ip)); - devices - ..addAll(discoverDevices) - ..addAll(localDevices); - return devices; - } + /// This method will get devices saved in memory, no status check + Future> getConnectingDevices() async => _viewingDevices; - Future> fetchDevices() async { + /// This method will get devices via mDNS and local db, for local db devices + /// it will check the status of the device by calling grpc, + /// it will return the devices that are available and save in memory + Future> scanDevices() async { final devices = await _findRawDevices(); // remove devices that are not available @@ -258,10 +242,10 @@ class CanvasClientService { return response.ok; } - Future uncastSingleArtwork(CanvasDevice device) async { + Future unCastSingleArtwork(CanvasDevice device) async { final stub = _getStub(device); - final uncastRequest = UncastSingleRequest()..id = ''; - final response = await stub.uncastSingleArtwork(uncastRequest); + final unCastRequest = UncastSingleRequest()..id = ''; + final response = await stub.uncastSingleArtwork(unCastRequest); if (response.ok) { _viewingDevices .firstWhereOrNull((element) => element == device) diff --git a/lib/service/mdns_service.dart b/lib/service/mdns_service.dart index 1267224d5..19ceb4bef 100644 --- a/lib/service/mdns_service.dart +++ b/lib/service/mdns_service.dart @@ -5,13 +5,16 @@ import 'package:multicast_dns/multicast_dns.dart'; class MDnsService { static const String _serviceType = '_feralFileCanvas._tcp'; final MDnsClient _client; + bool _isStarted = false; MDnsService() : _client = MDnsClient(); Future> findCanvas() async { final devices = []; log.info('[MDnsService] Looking for devices'); - await _client.start(); + if (!_isStarted) { + await start(); + } await _client .lookup( ResourceRecordQuery.serverPointer(_serviceType), @@ -44,10 +47,14 @@ class MDnsService { } } }); - await stop(); return devices; } + Future start() async { + await _client.start(); + _isStarted = true; + } + Future stop() async { _client.stop(); } From a0e16d7beb9fba3801b78bb8b0402b8bf521aa4e Mon Sep 17 00:00:00 2001 From: phuoc Date: Wed, 8 May 2024 09:35:09 +0700 Subject: [PATCH 2/2] remove unused fields Signed-off-by: phuoc --- lib/screen/detail/preview/canvas_device_bloc.dart | 7 +------ lib/screen/home/home_navigation_page.dart | 2 +- lib/screen/playlists/view_playlist/view_playlist.dart | 8 ++------ lib/view/stream_device_view.dart | 2 +- 4 files changed, 5 insertions(+), 14 deletions(-) diff --git a/lib/screen/detail/preview/canvas_device_bloc.dart b/lib/screen/detail/preview/canvas_device_bloc.dart index f86594b39..4a679538a 100644 --- a/lib/screen/detail/preview/canvas_device_bloc.dart +++ b/lib/screen/detail/preview/canvas_device_bloc.dart @@ -10,11 +10,7 @@ import 'package:web3dart/json_rpc.dart'; abstract class CanvasDeviceEvent {} class CanvasDeviceGetDevicesEvent extends CanvasDeviceEvent { - final String sceneId; - final bool syncAll; - - // constructor - CanvasDeviceGetDevicesEvent(this.sceneId, {this.syncAll = true}); + CanvasDeviceGetDevicesEvent(); } class CanvasDeviceAddEvent extends CanvasDeviceEvent { @@ -222,7 +218,6 @@ class CanvasDeviceBloc extends AuBloc { (element) => element.device.id == event.device.device.id) ..add(DeviceState( device: event.device.device, - duration: null, isPlaying: false))); emit(newState); }); diff --git a/lib/screen/home/home_navigation_page.dart b/lib/screen/home/home_navigation_page.dart index cc9831942..93192cc2c 100644 --- a/lib/screen/home/home_navigation_page.dart +++ b/lib/screen/home/home_navigation_page.dart @@ -290,7 +290,7 @@ class HomeNavigationPageState extends State create: (_) => CanvasDeviceBloc( injector(), injector(), - )..add(CanvasDeviceGetDevicesEvent('')), + )..add(CanvasDeviceGetDevicesEvent()), child: CollectionHomePage(key: _collectionHomePageKey), ), OrganizeHomePage(key: _organizeHomePageKey), diff --git a/lib/screen/playlists/view_playlist/view_playlist.dart b/lib/screen/playlists/view_playlist/view_playlist.dart index 6d84951a1..9346e2c5a 100644 --- a/lib/screen/playlists/view_playlist/view_playlist.dart +++ b/lib/screen/playlists/view_playlist/view_playlist.dart @@ -9,7 +9,6 @@ import 'package:autonomy_flutter/screen/detail/preview/canvas_device_bloc.dart'; import 'package:autonomy_flutter/screen/interactive_postcard/postcard_detail_page.dart'; import 'package:autonomy_flutter/screen/playlists/view_playlist/view_playlist_bloc.dart'; import 'package:autonomy_flutter/screen/playlists/view_playlist/view_playlist_state.dart'; -import 'package:autonomy_flutter/service/canvas_client_service_v2.dart'; import 'package:autonomy_flutter/service/configuration_service.dart'; import 'package:autonomy_flutter/service/navigation_service.dart'; import 'package:autonomy_flutter/service/playlist_service.dart'; @@ -69,7 +68,6 @@ class _ViewPlaylistScreenState extends State { late CanvasDeviceBloc _canvasDeviceBloc; late SortOrder _sortOrder; late bool editable; - final _canvasClientServiceV2 = injector(); List _getAvailableOrders() { switch (widget.payload.collectionType) { @@ -389,7 +387,7 @@ class _ViewPlaylistScreenState extends State { log.info('Playlist tokenIds is null'); return; } - final duration = Duration(seconds: 10).inMilliseconds; + final duration = const Duration(seconds: 10).inMilliseconds; final listPlayArtwork = listTokenIds .map((e) => PlayArtworkV2( token: CastAssetToken(id: e), duration: duration)) @@ -576,9 +574,7 @@ class _ViewPlaylistScreenState extends State { } Future _fetchDevice() async { - _canvasDeviceBloc.add(CanvasDeviceGetDevicesEvent( - widget.payload.playListModel?.id ?? '', - syncAll: false)); + _canvasDeviceBloc.add(CanvasDeviceGetDevicesEvent()); } } diff --git a/lib/view/stream_device_view.dart b/lib/view/stream_device_view.dart index 7f921c21c..2ae9c6816 100644 --- a/lib/view/stream_device_view.dart +++ b/lib/view/stream_device_view.dart @@ -34,7 +34,7 @@ class _StreamDeviceViewState extends State { } Future _fetchDevice() async { - _canvasDeviceBloc.add(CanvasDeviceGetDevicesEvent('')); + _canvasDeviceBloc.add(CanvasDeviceGetDevicesEvent()); } @override