From 3bd2bd114b0e461900fc0211d6dc2a7099b7ebde Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Mon, 2 Jun 2025 11:13:56 +0300 Subject: [PATCH] migrate `CeilingSensorBloc` to use the new services. --- .../ceiling_sensor/bloc/ceiling_bloc.dart | 224 ++++++++---------- .../ceiling_sensor_bloc_factory.dart | 18 ++ .../view/ceiling_sensor_batch_control.dart | 8 +- .../view/ceiling_sensor_controls.dart | 6 +- 4 files changed, 129 insertions(+), 127 deletions(-) create mode 100644 lib/pages/device_managment/ceiling_sensor/factories/ceiling_sensor_bloc_factory.dart diff --git a/lib/pages/device_managment/ceiling_sensor/bloc/ceiling_bloc.dart b/lib/pages/device_managment/ceiling_sensor/bloc/ceiling_bloc.dart index 4e8d5a8b..42387e57 100644 --- a/lib/pages/device_managment/ceiling_sensor/bloc/ceiling_bloc.dart +++ b/lib/pages/device_managment/ceiling_sensor/bloc/ceiling_bloc.dart @@ -1,5 +1,3 @@ -import 'dart:async'; - import 'package:firebase_database/firebase_database.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart'; @@ -7,14 +5,21 @@ import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/ceiling_e import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/ceiling_state.dart'; import 'package:syncrow_web/pages/device_managment/ceiling_sensor/model/ceiling_sensor_model.dart'; import 'package:syncrow_web/pages/device_managment/ceiling_sensor/model/help_description.dart'; +import 'package:syncrow_web/services/batch_control_devices_service.dart'; +import 'package:syncrow_web/services/control_device_service.dart'; import 'package:syncrow_web/services/devices_mang_api.dart'; class CeilingSensorBloc extends Bloc { final String deviceId; + final ControlDeviceService controlDeviceService; + final BatchControlDevicesService batchControlDevicesService; late CeilingSensorModel deviceStatus; - Timer? _timer; - CeilingSensorBloc({required this.deviceId}) : super(CeilingInitialState()) { + CeilingSensorBloc({ + required this.deviceId, + required this.controlDeviceService, + required this.batchControlDevicesService, + }) : super(CeilingInitialState()) { on(_fetchCeilingSensorStatus); on(_fetchCeilingSensorBatchControl); on(_changeValue); @@ -26,35 +31,34 @@ class CeilingSensorBloc extends Bloc { on(_onStatusUpdated); } - void _fetchCeilingSensorStatus( - CeilingInitialEvent event, Emitter emit) async { + Future _fetchCeilingSensorStatus( + CeilingInitialEvent event, + Emitter emit, + ) async { emit(CeilingLoadingInitialState()); try { - var response = - await DevicesManagementApi().getDeviceStatus(event.deviceId); + final response = await DevicesManagementApi().getDeviceStatus(event.deviceId); deviceStatus = CeilingSensorModel.fromJson(response.status); emit(CeilingUpdateState(ceilingSensorModel: deviceStatus)); _listenToChanges(event.deviceId); } catch (e) { emit(CeilingFailedState(error: e.toString())); - return; } } - _listenToChanges(deviceId) { + void _listenToChanges(String deviceId) { try { - DatabaseReference ref = - FirebaseDatabase.instance.ref('device-status/$deviceId'); - Stream stream = ref.onValue; + final ref = FirebaseDatabase.instance.ref('device-status/$deviceId'); + final stream = ref.onValue; stream.listen((DatabaseEvent event) { - Map usersMap = - event.snapshot.value as Map; + if (event.snapshot.value == null) return; + + final usersMap = event.snapshot.value as Map; + final statusList = []; - List statusList = []; usersMap['status'].forEach((element) { - statusList - .add(Status(code: element['code'], value: element['value'])); + statusList.add(Status(code: element['code'], value: element['value'])); }); deviceStatus = CeilingSensorModel.fromJson(statusList); @@ -65,149 +69,127 @@ class CeilingSensorBloc extends Bloc { } catch (_) {} } - void _onStatusUpdated(StatusUpdated event, Emitter emit) { + void _onStatusUpdated( + StatusUpdated event, + Emitter emit, + ) { deviceStatus = event.deviceStatus; emit(CeilingUpdateState(ceilingSensorModel: deviceStatus)); } - void _changeValue( - CeilingChangeValueEvent event, Emitter emit) async { + Future _changeValue( + CeilingChangeValueEvent event, + Emitter emit, + ) async { emit(CeilingLoadingNewSate(ceilingSensorModel: deviceStatus)); - if (event.code == 'sensitivity') { - deviceStatus.sensitivity = event.value; - } else if (event.code == 'none_body_time') { - deviceStatus.noBodyTime = event.value; - } else if (event.code == 'moving_max_dis') { - deviceStatus.maxDistance = event.value; - } else if (event.code == 'scene') { - deviceStatus.spaceType = getSpaceType(event.value); - } + _updateDeviceFunctionFromCode(event.code, event.value); emit(CeilingUpdateState(ceilingSensorModel: deviceStatus)); - await _runDeBouncer( - deviceId: deviceId, - code: event.code, - value: event.value, - emit: emit, - isBatch: false, - ); + + try { + await controlDeviceService.controlDevice( + deviceUuid: deviceId, + status: Status(code: event.code, value: event.value), + ); + } catch (e) { + emit(CeilingFailedState(error: e.toString())); + } } Future _onBatchControl( - CeilingBatchControlEvent event, Emitter emit) async { + CeilingBatchControlEvent event, + Emitter emit, + ) async { emit(CeilingLoadingNewSate(ceilingSensorModel: deviceStatus)); - if (event.code == 'sensitivity') { - deviceStatus.sensitivity = event.value; - } else if (event.code == 'none_body_time') { - deviceStatus.noBodyTime = event.value; - } else if (event.code == 'moving_max_dis') { - deviceStatus.maxDistance = event.value; - } else if (event.code == 'scene') { - deviceStatus.spaceType = getSpaceType(event.value); - } + _updateDeviceFunctionFromCode(event.code, event.value); emit(CeilingUpdateState(ceilingSensorModel: deviceStatus)); - await _runDeBouncer( - deviceId: event.deviceIds, - code: event.code, - value: event.value, - emit: emit, - isBatch: true, - ); - } - _runDeBouncer({ - required dynamic deviceId, - required String code, - required dynamic value, - required Emitter emit, - required bool isBatch, - }) { - late String id; + try { + final success = await batchControlDevicesService.batchControlDevices( + uuids: event.deviceIds, + code: event.code, + value: event.value, + ); - if (deviceId is List) { - id = deviceId.first; - } else { - id = deviceId; - } - - if (_timer != null) { - _timer!.cancel(); - } - _timer = Timer(const Duration(seconds: 1), () async { - try { - late bool response; - if (isBatch) { - response = await DevicesManagementApi() - .deviceBatchControl(deviceId, code, value); - } else { - response = await DevicesManagementApi() - .deviceControl(deviceId, Status(code: code, value: value)); - } - - if (!response) { - add(CeilingInitialEvent(id)); - } - if (response == true && code == 'scene') { - emit(CeilingLoadingInitialState()); - await Future.delayed(const Duration(seconds: 1)); - add(CeilingInitialEvent(id)); - } - } catch (_) { - await Future.delayed(const Duration(milliseconds: 500)); - add(CeilingInitialEvent(id)); + if (!success) { + emit(const CeilingFailedState(error: 'Failed to control devices')); } - }); + } catch (e) { + emit(CeilingFailedState(error: e.toString())); + } } - FutureOr _getDeviceReports(GetCeilingDeviceReportsEvent event, - Emitter emit) async { + void _updateDeviceFunctionFromCode(String code, dynamic value) { + switch (code) { + case 'sensitivity': + deviceStatus.sensitivity = value; + break; + case 'none_body_time': + deviceStatus.noBodyTime = value; + break; + case 'moving_max_dis': + deviceStatus.maxDistance = value; + break; + case 'scene': + deviceStatus.spaceType = getSpaceType(value); + break; + default: + break; + } + } + + Future _getDeviceReports( + GetCeilingDeviceReportsEvent event, + Emitter emit, + ) async { if (event.code.isEmpty) { emit(ShowCeilingDescriptionState(description: reportString)); return; - } else { - emit(CeilingReportsLoadingState()); - // final from = DateTime.now().subtract(const Duration(days: 30)).millisecondsSinceEpoch; - // final to = DateTime.now().millisecondsSinceEpoch; + } - try { - // await DevicesManagementApi.getDeviceReportsByDate(deviceId, event.code, from.toString(), to.toString()) - await DevicesManagementApi.getDeviceReports(deviceId, event.code) - .then((value) { - emit(CeilingReportsState(deviceReport: value)); - }); - } catch (e) { - emit(CeilingReportsFailedState(error: e.toString())); - return; - } + emit(CeilingReportsLoadingState()); + try { + final value = await DevicesManagementApi.getDeviceReports( + deviceId, + event.code, + ); + emit(CeilingReportsState(deviceReport: value)); + } catch (e) { + emit(CeilingReportsFailedState(error: e.toString())); } } void _showDescription( - ShowCeilingDescriptionEvent event, Emitter emit) { + ShowCeilingDescriptionEvent event, + Emitter emit, + ) { emit(ShowCeilingDescriptionState(description: event.description)); } void _backToGridView( - BackToCeilingGridViewEvent event, Emitter emit) { + BackToCeilingGridViewEvent event, + Emitter emit, + ) { emit(CeilingUpdateState(ceilingSensorModel: deviceStatus)); } - FutureOr _fetchCeilingSensorBatchControl( - CeilingFetchDeviceStatusEvent event, - Emitter emit) async { + Future _fetchCeilingSensorBatchControl( + CeilingFetchDeviceStatusEvent event, + Emitter emit, + ) async { emit(CeilingLoadingInitialState()); try { - var response = - await DevicesManagementApi().getBatchStatus(event.devicesIds); + final response = await DevicesManagementApi().getBatchStatus(event.devicesIds); deviceStatus = CeilingSensorModel.fromJson(response.status); emit(CeilingUpdateState(ceilingSensorModel: deviceStatus)); } catch (e) { emit(CeilingFailedState(error: e.toString())); - return; } } - FutureOr _onFactoryReset( - CeilingFactoryResetEvent event, Emitter emit) async { + Future _onFactoryReset( + CeilingFactoryResetEvent event, + Emitter emit, + ) async { emit(CeilingLoadingNewSate(ceilingSensorModel: deviceStatus)); try { final response = await DevicesManagementApi().factoryReset( diff --git a/lib/pages/device_managment/ceiling_sensor/factories/ceiling_sensor_bloc_factory.dart b/lib/pages/device_managment/ceiling_sensor/factories/ceiling_sensor_bloc_factory.dart new file mode 100644 index 00000000..d371efb1 --- /dev/null +++ b/lib/pages/device_managment/ceiling_sensor/factories/ceiling_sensor_bloc_factory.dart @@ -0,0 +1,18 @@ +import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/ceiling_bloc.dart'; +import 'package:syncrow_web/pages/device_managment/factories/device_bloc_dependencies_factory.dart'; + +abstract final class CeilingSensorBlocFactory { + const CeilingSensorBlocFactory._(); + + static CeilingSensorBloc create({ + required String deviceId, + }) { + return CeilingSensorBloc( + deviceId: deviceId, + controlDeviceService: + DeviceBlocDependenciesFactory.createControlDeviceService(), + batchControlDevicesService: + DeviceBlocDependenciesFactory.createBatchControlDevicesService(), + ); + } +} diff --git a/lib/pages/device_managment/ceiling_sensor/view/ceiling_sensor_batch_control.dart b/lib/pages/device_managment/ceiling_sensor/view/ceiling_sensor_batch_control.dart index cf645b6f..9b5ab360 100644 --- a/lib/pages/device_managment/ceiling_sensor/view/ceiling_sensor_batch_control.dart +++ b/lib/pages/device_managment/ceiling_sensor/view/ceiling_sensor_batch_control.dart @@ -4,9 +4,9 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_re import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/ceiling_bloc.dart'; import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/ceiling_event.dart'; import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/ceiling_state.dart'; +import 'package:syncrow_web/pages/device_managment/ceiling_sensor/factories/ceiling_sensor_bloc_factory.dart'; import 'package:syncrow_web/pages/device_managment/ceiling_sensor/model/ceiling_sensor_model.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; -// import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_space_type.dart'; import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_update_data.dart'; import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presense_nobody_time.dart'; @@ -23,8 +23,9 @@ class CeilingSensorBatchControlView extends StatelessWidget with HelperResponsiv final isLarge = isLargeScreenSize(context); final isMedium = isMediumScreenSize(context); return BlocProvider( - create: (context) => CeilingSensorBloc(deviceId: devicesIds.first) - ..add(CeilingFetchDeviceStatusEvent(devicesIds)), + create: (context) => CeilingSensorBlocFactory.create( + deviceId: devicesIds.first, + )..add(CeilingFetchDeviceStatusEvent(devicesIds)), child: BlocBuilder( builder: (context, state) { if (state is CeilingLoadingInitialState || state is CeilingReportsLoadingState) { @@ -110,7 +111,6 @@ class CeilingSensorBatchControlView extends StatelessWidget with HelperResponsiv ), ), ), - // FirmwareUpdateWidget(deviceId: devicesIds.first, version: 4), FactoryResetWidget( callFactoryReset: () { context.read().add( diff --git a/lib/pages/device_managment/ceiling_sensor/view/ceiling_sensor_controls.dart b/lib/pages/device_managment/ceiling_sensor/view/ceiling_sensor_controls.dart index 36b676e9..f3017a7c 100644 --- a/lib/pages/device_managment/ceiling_sensor/view/ceiling_sensor_controls.dart +++ b/lib/pages/device_managment/ceiling_sensor/view/ceiling_sensor_controls.dart @@ -4,6 +4,7 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_mo import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/ceiling_bloc.dart'; import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/ceiling_event.dart'; import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/ceiling_state.dart'; +import 'package:syncrow_web/pages/device_managment/ceiling_sensor/factories/ceiling_sensor_bloc_factory.dart'; import 'package:syncrow_web/pages/device_managment/ceiling_sensor/model/ceiling_sensor_model.dart'; import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_display_data.dart'; import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_space_type.dart'; @@ -28,8 +29,9 @@ class CeilingSensorControlsView extends StatelessWidget final isLarge = isLargeScreenSize(context); final isMedium = isMediumScreenSize(context); return BlocProvider( - create: (context) => CeilingSensorBloc(deviceId: device.uuid ?? '') - ..add(CeilingInitialEvent(device.uuid ?? '')), + create: (context) => CeilingSensorBlocFactory.create( + deviceId: device.uuid ?? '', + )..add(CeilingInitialEvent(device.uuid ?? '')), child: BlocBuilder( builder: (context, state) { if (state is CeilingLoadingInitialState ||