Skip to content

Commit

Permalink
Merge pull request #1665 from bitmark-inc/2058/improve_scanning
Browse files Browse the repository at this point in the history
fix: improve fetching device
  • Loading branch information
phuocbitmark authored May 8, 2024
2 parents f5cfcd3 + a52c55a commit 1fe6581
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 66 deletions.
21 changes: 7 additions & 14 deletions lib/screen/detail/preview/canvas_device_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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 CanvasDeviceGetControllingStatusEvent extends CanvasDeviceEvent {}
Expand Down Expand Up @@ -177,10 +173,8 @@ class CanvasDeviceState {
List<DeviceState> get controllingDevices =>
devices.where((element) => isDeviceControlling(element.device)).toList();

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 {
Expand Down Expand Up @@ -225,8 +219,8 @@ class CanvasDeviceBloc extends AuBloc<CanvasDeviceEvent, CanvasDeviceState> {
on<CanvasDeviceGetDevicesEvent>((event, emit) async {
emit(state.copyWith(
devices: state.devices, isLoaded: state.devices.isNotEmpty));
final devices = await _canvasClientService.getConnectingDevices(
doSync: event.syncAll);
final devices = await _canvasClientService.scanDevices();

final newState = state.copyWith(
devices: devices.map((e) => DeviceState(device: e)).toList(),
isLoaded: true);
Expand All @@ -236,7 +230,7 @@ class CanvasDeviceBloc extends AuBloc<CanvasDeviceEvent, CanvasDeviceState> {
await Future.forEach<CanvasDevice>(devices, (device) async {
try {
final status =
await _canvasClientServiceV2.getDeviceCastingStatus(device);
await _canvasClientServiceV2.getDeviceCastingStatus(device);
if (thisDevice.deviceId == status.connectedDevice.deviceId) {
controllingDeviceStatus[device.id] = status;
}
Expand All @@ -257,7 +251,6 @@ class CanvasDeviceBloc extends AuBloc<CanvasDeviceEvent, CanvasDeviceState> {
(element) => element.device.id == event.device.device.id)
..add(DeviceState(
device: event.device.device,
duration: null,
isPlaying: false)));
emit(newState);
});
Expand Down Expand Up @@ -312,7 +305,7 @@ class CanvasDeviceBloc extends AuBloc<CanvasDeviceEvent, CanvasDeviceState> {
on<CanvasDeviceUnCastingEvent>((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 (_) {}
Expand Down
6 changes: 1 addition & 5 deletions lib/screen/playlists/view_playlist/view_playlist.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -70,7 +69,6 @@ class _ViewPlaylistScreenState extends State<ViewPlaylistScreen> {
late CanvasDeviceBloc _canvasDeviceBloc;
late SortOrder _sortOrder;
late bool editable;
final _canvasClientServiceV2 = injector<CanvasClientServiceV2>();

List<SortOrder> _getAvailableOrders() {
switch (widget.payload.collectionType) {
Expand Down Expand Up @@ -577,9 +575,7 @@ class _ViewPlaylistScreenState extends State<ViewPlaylistScreen> {
}

Future<void> _fetchDevice() async {
_canvasDeviceBloc.add(CanvasDeviceGetDevicesEvent(
widget.payload.playListModel?.id ?? '',
syncAll: false));
_canvasDeviceBloc.add(CanvasDeviceGetDevicesEvent());
}
}

Expand Down
72 changes: 28 additions & 44 deletions lib/service/canvas_client_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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<void> shutdownAll() async {
await Future.wait(_viewingDevices.map((e) => shutDown(e)));
}

Future<void> shutDown(CanvasDevice device) async {
final channel = _getChannel(device);
await channel.shutdown();
Expand Down Expand Up @@ -151,63 +147,51 @@ class CanvasClientService {
return Pair(status, sceneId);
}

Future<void> syncDevices() async {
final devices = await _getAllDevices();
final List<CanvasDevice> devicesToAdd = [];
Future<List<CanvasDevice>> _findRawDevices() async {
final devices = <CanvasDevice>[];
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<List<CanvasDevice>> refreshDevices(List<CanvasDevice> devices) async {
final List<CanvasDevice> workingDevices = [];
await Future.forEach<CanvasDevice>(devices, (device) async {
final status = await checkDeviceStatus(device);
switch (status.first) {
case CanvasServerStatus.playing:
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;
case CanvasServerStatus.error:
break;
}
});
_viewingDevices
..clear()
..addAll(devicesToAdd)
..unique((element) => element.ip);
log.info(
'CanvasClientService sync device available ${_viewingDevices.length}');
}

Future<List<CanvasDevice>> _getAllDevices() async => fetchDevices();

Future<List<CanvasDevice>> 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<List<CanvasDevice>> _findRawDevices() async {
final devices = <CanvasDevice>[];
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<List<CanvasDevice>> getConnectingDevices() async => _viewingDevices;

Future<List<CanvasDevice>> 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<List<CanvasDevice>> scanDevices() async {
final devices = await _findRawDevices();

// remove devices that are not available
Expand Down Expand Up @@ -258,10 +242,10 @@ class CanvasClientService {
return response.ok;
}

Future<void> uncastSingleArtwork(CanvasDevice device) async {
Future<void> 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)
Expand Down
11 changes: 9 additions & 2 deletions lib/service/mdns_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<List<CanvasDevice>> findCanvas() async {
final devices = <CanvasDevice>[];
log.info('[MDnsService] Looking for devices');
await _client.start();
if (!_isStarted) {
await start();
}
await _client
.lookup<PtrResourceRecord>(
ResourceRecordQuery.serverPointer(_serviceType),
Expand Down Expand Up @@ -44,10 +47,14 @@ class MDnsService {
}
}
});
await stop();
return devices;
}

Future<void> start() async {
await _client.start();
_isStarted = true;
}

Future<void> stop() async {
_client.stop();
}
Expand Down
2 changes: 1 addition & 1 deletion lib/view/stream_device_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class _StreamDeviceViewState extends State<StreamDeviceView> {
}

Future<void> _fetchDevice() async {
_canvasDeviceBloc.add(CanvasDeviceGetDevicesEvent(''));
_canvasDeviceBloc.add(CanvasDeviceGetDevicesEvent());
}

@override
Expand Down

0 comments on commit 1fe6581

Please sign in to comment.