diff --git a/lib/pages/device_managment/two_g_glass_switch/bloc/two_gang_glass_switch_bloc.dart b/lib/pages/device_managment/two_g_glass_switch/bloc/two_gang_glass_switch_bloc.dart index 406821da..8f82c198 100644 --- a/lib/pages/device_managment/two_g_glass_switch/bloc/two_gang_glass_switch_bloc.dart +++ b/lib/pages/device_managment/two_g_glass_switch/bloc/two_gang_glass_switch_bloc.dart @@ -1,26 +1,33 @@ import 'dart:async'; +import 'dart:developer'; + import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; import 'package:firebase_database/firebase_database.dart'; -import 'package:meta/meta.dart'; +import 'package:flutter/foundation.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart'; import 'package:syncrow_web/pages/device_managment/two_g_glass_switch/models/two_gang_glass_status_model.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'; + part 'two_gang_glass_switch_event.dart'; part 'two_gang_glass_switch_state.dart'; class TwoGangGlassSwitchBloc extends Bloc { - TwoGangGlassStatusModel deviceStatus; - Timer? _timer; - TwoGangGlassSwitchBloc({required String deviceId}) - : deviceStatus = TwoGangGlassStatusModel( - uuid: deviceId, - switch1: false, - countDown1: 0, - switch2: false, - countDown2: 0), - super(TwoGangGlassSwitchInitial()) { + final String deviceId; + final ControlDeviceService controlDeviceService; + final BatchControlDevicesService batchControlDevicesService; + + late TwoGangGlassStatusModel deviceStatus; + + TwoGangGlassSwitchBloc({ + required this.deviceId, + required this.controlDeviceService, + required this.batchControlDevicesService, + }) : super(TwoGangGlassSwitchInitial()) { on(_onFetchDeviceStatus); on(_onControl); on(_onBatchControl); @@ -29,14 +36,14 @@ class TwoGangGlassSwitchBloc on(_onStatusUpdated); } - Future _onFetchDeviceStatus(TwoGangGlassSwitchFetchDeviceEvent event, - Emitter emit) async { + Future _onFetchDeviceStatus( + TwoGangGlassSwitchFetchDeviceEvent event, + Emitter emit, + ) async { emit(TwoGangGlassSwitchLoading()); try { - final status = - await DevicesManagementApi().getDeviceStatus(event.deviceId); - deviceStatus = - TwoGangGlassStatusModel.fromJson(event.deviceId, status.status); + final status = await DevicesManagementApi().getDeviceStatus(event.deviceId); + deviceStatus = TwoGangGlassStatusModel.fromJson(event.deviceId, status.status); _listenToChanges(event.deviceId); emit(TwoGangGlassSwitchStatusLoaded(deviceStatus)); } catch (e) { @@ -46,200 +53,121 @@ class TwoGangGlassSwitchBloc void _listenToChanges(String deviceId) { try { - DatabaseReference ref = - FirebaseDatabase.instance.ref('device-status/$deviceId'); - ref.onValue.listen((DatabaseEvent event) { - if (event.snapshot.value == null) return; + final ref = FirebaseDatabase.instance.ref( + 'device-status/$deviceId', + ); + + ref.onValue.listen((event) { + final eventsMap = event.snapshot.value as Map; - Map data = - event.snapshot.value as Map; List statusList = []; - - data['status'].forEach((element) { - statusList - .add(Status(code: element['code'], value: element['value'])); + eventsMap['status'].forEach((element) { + statusList.add(Status(code: element['code'], value: element['value'])); }); - // Parse the new status and add the event - final updatedStatus = - TwoGangGlassStatusModel.fromJson(data['productUuid'], statusList); - if (!isClosed) { - add(StatusUpdated(updatedStatus)); - } + deviceStatus = TwoGangGlassStatusModel.fromJson(deviceId, statusList); + add(StatusUpdated(deviceStatus)); }); - } catch (e) { - // Handle errors and emit an error state if necessary - if (!isClosed) { - // add(TwoGangGlassSwitchError('Error listening to updates: $e')); - } + } catch (_) { + log( + 'Error listening to changes', + name: 'TwoGangGlassSwitchBloc._listenToChanges', + ); } } - Future _onControl(TwoGangGlassSwitchControl event, - Emitter emit) async { - final oldValue = _getValueByCode(event.code); - + Future _onControl( + TwoGangGlassSwitchControl event, + Emitter emit, + ) async { + emit(TwoGangGlassSwitchLoading()); _updateLocalValue(event.code, event.value); emit(TwoGangGlassSwitchStatusLoaded(deviceStatus)); - await _runDebounce( - deviceId: event.deviceId, - code: event.code, - value: event.value, - oldValue: oldValue, - emit: emit, - isBatch: false, - ); + try { + await controlDeviceService.controlDevice( + deviceUuid: event.deviceId, + status: Status(code: event.code, value: event.value), + ); + } catch (e) { + _updateLocalValue(event.code, !event.value); + emit(TwoGangGlassSwitchError(e.toString())); + } } - Future _onBatchControl(TwoGangGlassSwitchBatchControl event, - Emitter emit) async { - final oldValue = _getValueByCode(event.code); - + Future _onBatchControl( + TwoGangGlassSwitchBatchControl event, + Emitter emit, + ) async { + emit(TwoGangGlassSwitchLoading()); _updateLocalValue(event.code, event.value); emit(TwoGangGlassSwitchBatchStatusLoaded(deviceStatus)); - await _runDebounce( - deviceId: event.deviceIds, - code: event.code, - value: event.value, - oldValue: oldValue, - emit: emit, - isBatch: true, - ); + try { + await batchControlDevicesService.batchControlDevices( + uuids: event.deviceIds, + code: event.code, + value: event.value, + ); + } catch (e) { + _updateLocalValue(event.code, !event.value); + emit(TwoGangGlassSwitchError(e.toString())); + } } Future _onFetchBatchStatus( - TwoGangGlassSwitchFetchBatchStatusEvent event, - Emitter emit) async { + TwoGangGlassSwitchFetchBatchStatusEvent event, + Emitter emit, + ) async { emit(TwoGangGlassSwitchLoading()); try { - final status = - await DevicesManagementApi().getBatchStatus(event.deviceIds); + final status = await DevicesManagementApi().getBatchStatus(event.deviceIds); deviceStatus = TwoGangGlassStatusModel.fromJson( - event.deviceIds.first, status.status); + event.deviceIds.first, + status.status, + ); emit(TwoGangGlassSwitchBatchStatusLoaded(deviceStatus)); } catch (e) { emit(TwoGangGlassSwitchError(e.toString())); } } - Future _onFactoryReset(TwoGangGlassFactoryReset event, - Emitter emit) async { + Future _onFactoryReset( + TwoGangGlassFactoryReset event, + Emitter emit, + ) async { emit(TwoGangGlassSwitchLoading()); try { - final response = await DevicesManagementApi() - .factoryReset(event.factoryReset, event.deviceId); + final response = await DevicesManagementApi().factoryReset( + event.factoryReset, + event.deviceId, + ); if (!response) { - emit(TwoGangGlassSwitchError('Failed')); + emit(TwoGangGlassSwitchError('Failed to reset device')); } else { - emit(TwoGangGlassSwitchStatusLoaded(deviceStatus)); + add(TwoGangGlassSwitchFetchDeviceEvent(event.deviceId)); } } catch (e) { emit(TwoGangGlassSwitchError(e.toString())); } } - Future _runDebounce({ - required dynamic deviceId, - required String code, - required bool value, - required bool oldValue, - required Emitter emit, - required bool isBatch, - }) async { - late String id; - if (deviceId is List) { - id = deviceId.first; - } else { - id = deviceId; - } - - if (_timer != null) { - _timer!.cancel(); - } - - _timer = Timer(const Duration(milliseconds: 500), () 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) { - _revertValueAndEmit(id, code, oldValue, emit); - } - } catch (e) { - _revertValueAndEmit(id, code, oldValue, emit); - } - }); - } - - void _revertValueAndEmit(String deviceId, String code, bool oldValue, - Emitter emit) { - _updateLocalValue(code, oldValue); + void _onStatusUpdated( + StatusUpdated event, + Emitter emit, + ) { + deviceStatus = event.deviceStatus; emit(TwoGangGlassSwitchStatusLoaded(deviceStatus)); } void _updateLocalValue(String code, bool value) { - if (code == 'switch_1') { - deviceStatus = deviceStatus.copyWith(switch1: value); - } else if (code == 'switch_2') { - deviceStatus = deviceStatus.copyWith(switch2: value); - } - } - - bool _getValueByCode(String code) { switch (code) { case 'switch_1': - return deviceStatus.switch1; + deviceStatus = deviceStatus.copyWith(switch1: value); + break; case 'switch_2': - return deviceStatus.switch2; - default: - return false; + deviceStatus = deviceStatus.copyWith(switch2: value); + break; } } - - @override - Future close() { - _timer?.cancel(); - return super.close(); - } - - // _listenToChanges(deviceId) { - // try { - // DatabaseReference ref = - // FirebaseDatabase.instance.ref('device-status/$deviceId'); - // Stream stream = ref.onValue; - - // stream.listen((DatabaseEvent event) { - // Map usersMap = - // event.snapshot.value as Map; - - // List statusList = []; - // usersMap['status'].forEach((element) { - // statusList - // .add(Status(code: element['code'], value: element['value'])); - // }); - - // deviceStatus = TwoGangGlassStatusModel.fromJson( - // usersMap['productUuid'], statusList); - // if (!isClosed) { - // add(StatusUpdated(deviceStatus)); - // } - // }); - // } catch (_) {} - // } - - void _onStatusUpdated( - StatusUpdated event, Emitter emit) { - // Update the local deviceStatus with the new status from the event - deviceStatus = event.deviceStatus; - // Emit the new state with the updated status - emit(TwoGangGlassSwitchStatusLoaded(deviceStatus)); - } } diff --git a/lib/pages/device_managment/two_g_glass_switch/bloc/two_gang_glass_switch_event.dart b/lib/pages/device_managment/two_g_glass_switch/bloc/two_gang_glass_switch_event.dart index 02b61bd0..46444cce 100644 --- a/lib/pages/device_managment/two_g_glass_switch/bloc/two_gang_glass_switch_event.dart +++ b/lib/pages/device_managment/two_g_glass_switch/bloc/two_gang_glass_switch_event.dart @@ -1,12 +1,17 @@ part of 'two_gang_glass_switch_bloc.dart'; @immutable -abstract class TwoGangGlassSwitchEvent {} +abstract class TwoGangGlassSwitchEvent extends Equatable { + const TwoGangGlassSwitchEvent(); +} class TwoGangGlassSwitchFetchDeviceEvent extends TwoGangGlassSwitchEvent { final String deviceId; - TwoGangGlassSwitchFetchDeviceEvent(this.deviceId); + const TwoGangGlassSwitchFetchDeviceEvent(this.deviceId); + + @override + List get props => [deviceId]; } class TwoGangGlassSwitchControl extends TwoGangGlassSwitchEvent { @@ -14,11 +19,14 @@ class TwoGangGlassSwitchControl extends TwoGangGlassSwitchEvent { final String code; final bool value; - TwoGangGlassSwitchControl({ + const TwoGangGlassSwitchControl({ required this.deviceId, required this.code, required this.value, }); + + @override + List get props => [deviceId, code, value]; } class TwoGangGlassSwitchBatchControl extends TwoGangGlassSwitchEvent { @@ -26,33 +34,43 @@ class TwoGangGlassSwitchBatchControl extends TwoGangGlassSwitchEvent { final String code; final bool value; - TwoGangGlassSwitchBatchControl({ + const TwoGangGlassSwitchBatchControl({ required this.deviceIds, required this.code, required this.value, }); + + @override + List get props => [deviceIds, code, value]; } class TwoGangGlassSwitchFetchBatchStatusEvent extends TwoGangGlassSwitchEvent { final List deviceIds; - TwoGangGlassSwitchFetchBatchStatusEvent(this.deviceIds); + const TwoGangGlassSwitchFetchBatchStatusEvent(this.deviceIds); + + @override + List get props => [deviceIds]; } class TwoGangGlassFactoryReset extends TwoGangGlassSwitchEvent { final String deviceId; final FactoryResetModel factoryReset; - TwoGangGlassFactoryReset({ + const TwoGangGlassFactoryReset({ required this.deviceId, required this.factoryReset, }); + + @override + List get props => [deviceId, factoryReset]; } class StatusUpdated extends TwoGangGlassSwitchEvent { final TwoGangGlassStatusModel deviceStatus; - StatusUpdated(this.deviceStatus); + + const StatusUpdated(this.deviceStatus); + @override List get props => [deviceStatus]; } - diff --git a/lib/pages/device_managment/two_g_glass_switch/factories/two_gang_glass_switch_bloc_factory.dart b/lib/pages/device_managment/two_g_glass_switch/factories/two_gang_glass_switch_bloc_factory.dart new file mode 100644 index 00000000..bd832d8f --- /dev/null +++ b/lib/pages/device_managment/two_g_glass_switch/factories/two_gang_glass_switch_bloc_factory.dart @@ -0,0 +1,18 @@ +import 'package:syncrow_web/pages/device_managment/factories/device_bloc_dependencies_factory.dart'; +import 'package:syncrow_web/pages/device_managment/two_g_glass_switch/bloc/two_gang_glass_switch_bloc.dart'; + +abstract final class TwoGangGlassSwitchBlocFactory { + const TwoGangGlassSwitchBlocFactory._(); + + static TwoGangGlassSwitchBloc create({ + required String deviceId, + }) { + return TwoGangGlassSwitchBloc( + deviceId: deviceId, + controlDeviceService: + DeviceBlocDependenciesFactory.createControlDeviceService(), + batchControlDevicesService: + DeviceBlocDependenciesFactory.createBatchControlDevicesService(), + ); + } +} diff --git a/lib/pages/device_managment/two_g_glass_switch/view/two_gang_glass_switch_batch_control_view.dart b/lib/pages/device_managment/two_g_glass_switch/view/two_gang_glass_switch_batch_control_view.dart index c84c1d07..9d120ad6 100644 --- a/lib/pages/device_managment/two_g_glass_switch/view/two_gang_glass_switch_batch_control_view.dart +++ b/lib/pages/device_managment/two_g_glass_switch/view/two_gang_glass_switch_batch_control_view.dart @@ -5,6 +5,7 @@ import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_ // import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart'; import 'package:syncrow_web/pages/device_managment/two_g_glass_switch/bloc/two_gang_glass_switch_bloc.dart'; +import 'package:syncrow_web/pages/device_managment/two_g_glass_switch/factories/two_gang_glass_switch_bloc_factory.dart'; import 'package:syncrow_web/pages/device_managment/two_g_glass_switch/models/two_gang_glass_status_model.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; @@ -16,7 +17,7 @@ class TwoGangGlassSwitchBatchControlView extends StatelessWidget with HelperResp @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => TwoGangGlassSwitchBloc(deviceId: deviceIds.first) + create: (context) => TwoGangGlassSwitchBlocFactory.create(deviceId: deviceIds.first) ..add(TwoGangGlassSwitchFetchBatchStatusEvent(deviceIds)), child: BlocBuilder( builder: (context, state) { diff --git a/lib/pages/device_managment/two_g_glass_switch/view/two_gang_glass_switch_control_view.dart b/lib/pages/device_managment/two_g_glass_switch/view/two_gang_glass_switch_control_view.dart index cca794e9..575deeac 100644 --- a/lib/pages/device_managment/two_g_glass_switch/view/two_gang_glass_switch_control_view.dart +++ b/lib/pages/device_managment/two_g_glass_switch/view/two_gang_glass_switch_control_view.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart'; import 'package:syncrow_web/pages/device_managment/two_g_glass_switch/bloc/two_gang_glass_switch_bloc.dart'; +import 'package:syncrow_web/pages/device_managment/two_g_glass_switch/factories/two_gang_glass_switch_bloc_factory.dart'; import 'package:syncrow_web/pages/device_managment/two_g_glass_switch/models/two_gang_glass_status_model.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; @@ -15,7 +16,7 @@ class TwoGangGlassSwitchControlView extends StatelessWidget @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => TwoGangGlassSwitchBloc(deviceId: deviceId) + create: (context) => TwoGangGlassSwitchBlocFactory.create(deviceId: deviceId) ..add(TwoGangGlassSwitchFetchDeviceEvent(deviceId)), child: BlocBuilder( builder: (context, state) {