diff --git a/lib/pages/device_managment/ac/bloc/ac_bloc.dart b/lib/pages/device_managment/ac/bloc/ac_bloc.dart index af5a7b0a..9a8e18a2 100644 --- a/lib/pages/device_managment/ac/bloc/ac_bloc.dart +++ b/lib/pages/device_managment/ac/bloc/ac_bloc.dart @@ -45,7 +45,8 @@ class AcBloc extends Bloc { ) async { emit(AcsLoadingState()); try { - final status = await DevicesManagementApi().getDeviceStatus(event.deviceId); + final status = + await DevicesManagementApi().getDeviceStatus(event.deviceId); deviceStatus = AcStatusModel.fromJson(event.deviceId, status.status); if (deviceStatus.countdown1 != 0) { final totalMinutes = deviceStatus.countdown1 * 6; @@ -82,10 +83,12 @@ class AcBloc extends Bloc { 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 = AcStatusModel.fromJson(usersMap['productUuid'], statusList); + deviceStatus = + AcStatusModel.fromJson(usersMap['productUuid'], statusList); if (!isClosed) { add(AcStatusUpdated(deviceStatus)); } @@ -129,8 +132,10 @@ class AcBloc extends Bloc { ) async { emit(AcsLoadingState()); try { - final status = await DevicesManagementApi().getBatchStatus(event.devicesIds); - deviceStatus = AcStatusModel.fromJson(event.devicesIds.first, status.status); + final status = + await DevicesManagementApi().getBatchStatus(event.devicesIds); + deviceStatus = + AcStatusModel.fromJson(event.devicesIds.first, status.status); emit(ACStatusLoaded(status: deviceStatus)); } catch (e) { emit(AcsFailedState(error: e.toString())); diff --git a/lib/pages/device_managment/all_devices/helper/route_controls_based_code.dart b/lib/pages/device_managment/all_devices/helper/route_controls_based_code.dart index cc09260e..08bca73c 100644 --- a/lib/pages/device_managment/all_devices/helper/route_controls_based_code.dart +++ b/lib/pages/device_managment/all_devices/helper/route_controls_based_code.dart @@ -213,7 +213,7 @@ mixin RouteControlsBasedCode { case 'CUR_2': return CurtainModuleBatchView( devicesIds: devices - .where((e) => e.productType == 'AC') + .where((e) => e.productType == 'CUR_2') .map((e) => e.uuid!) .toList(), ); diff --git a/lib/pages/device_managment/curtain_module/bloc/batch/curtain_module_batch_bloc.dart b/lib/pages/device_managment/curtain_module/bloc/batch/curtain_module_batch_bloc.dart deleted file mode 100644 index 87dd53f7..00000000 --- a/lib/pages/device_managment/curtain_module/bloc/batch/curtain_module_batch_bloc.dart +++ /dev/null @@ -1,45 +0,0 @@ -import 'dart:async'; - -import 'package:bloc/bloc.dart'; -import 'package:equatable/equatable.dart'; -import 'package:firebase_database/firebase_database.dart'; -import 'package:syncrow_web/pages/device_managment/curtain_module/models/curtain_module_model.dart'; -import 'package:syncrow_web/services/control_device_service.dart'; -import 'package:syncrow_web/services/devices_mang_api.dart'; - -part 'curtain_module_batch_event.dart'; -part 'curtain_module_batch_state.dart'; - -class CurtainModuleBatchBloc - extends Bloc { - final ControlDeviceService controlDeviceService; - StreamSubscription? _firebaseSubscription; - - CurtainModuleBatchBloc(this.controlDeviceService) - : super(CurtainModuleBatchInitial()) { - on(_onFetchAcBatchStatus); - } - - Future _onFetchAcBatchStatus( - CutrainModuleFetchBatchStatusEvent event, - Emitter emit, - ) async { - emit(CurtainModuleBatchLoadingState()); - try { - final status = - await DevicesManagementApi().getBatchStatus(event.devicesIds); - status.status.forEach( - (element) => print( - 'this is code ${element.code} - this is value ${element.value}'), - ); - - emit( - CurtainModuleBatchLoadedState( - curtainModuleStatusModel: CurtainModuleStatusModel.fromJson({}), - ), - ); - } catch (e) { - emit(CurtainModuleBatchFailedState(error: e.toString())); - } - } -} diff --git a/lib/pages/device_managment/curtain_module/bloc/batch/curtain_module_batch_event.dart b/lib/pages/device_managment/curtain_module/bloc/batch/curtain_module_batch_event.dart deleted file mode 100644 index 351773f9..00000000 --- a/lib/pages/device_managment/curtain_module/bloc/batch/curtain_module_batch_event.dart +++ /dev/null @@ -1,19 +0,0 @@ -part of 'curtain_module_batch_bloc.dart'; - -sealed class CurtainModuleBatchEvent extends Equatable { - const CurtainModuleBatchEvent(); - - @override - List get props => []; -} - -class CutrainModuleFetchBatchStatusEvent extends CurtainModuleBatchEvent { - final List devicesIds; - - const CutrainModuleFetchBatchStatusEvent({ - required this.devicesIds, - }); - - @override - List get props => [devicesIds]; -} diff --git a/lib/pages/device_managment/curtain_module/bloc/batch/curtain_module_batch_state.dart b/lib/pages/device_managment/curtain_module/bloc/batch/curtain_module_batch_state.dart deleted file mode 100644 index bb8bb7d0..00000000 --- a/lib/pages/device_managment/curtain_module/bloc/batch/curtain_module_batch_state.dart +++ /dev/null @@ -1,28 +0,0 @@ -part of 'curtain_module_batch_bloc.dart'; - -sealed class CurtainModuleBatchState extends Equatable { - const CurtainModuleBatchState(); - - @override - List get props => []; -} - -final class CurtainModuleBatchInitial extends CurtainModuleBatchState {} - -final class CurtainModuleBatchLoadingState extends CurtainModuleBatchState {} - -final class CurtainModuleBatchLoadedState extends CurtainModuleBatchState { - final CurtainModuleStatusModel curtainModuleStatusModel; - const CurtainModuleBatchLoadedState({ - required this.curtainModuleStatusModel, - }); -} - -final class CurtainModuleBatchFailedState extends CurtainModuleBatchState { - final String error; - - const CurtainModuleBatchFailedState({required this.error}); - - @override - List get props => [error]; -} diff --git a/lib/pages/device_managment/curtain_module/bloc/curtain_module_bloc.dart b/lib/pages/device_managment/curtain_module/bloc/curtain_module_bloc.dart index d79380cf..c3cd0b92 100644 --- a/lib/pages/device_managment/curtain_module/bloc/curtain_module_bloc.dart +++ b/lib/pages/device_managment/curtain_module/bloc/curtain_module_bloc.dart @@ -3,7 +3,9 @@ import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:firebase_database/firebase_database.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/curtain_module/models/curtain_module_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'; @@ -12,9 +14,13 @@ part 'curtain_module_state.dart'; class CurtainModuleBloc extends Bloc { final ControlDeviceService controlDeviceService; + final BatchControlDevicesService batchControlDevicesService; StreamSubscription? _firebaseSubscription; - CurtainModuleBloc(this.controlDeviceService) : super(CurtainModuleInitial()) { + CurtainModuleBloc({ + required this.controlDeviceService, + required this.batchControlDevicesService, + }) : super(CurtainModuleInitial()) { on(_onFetchCurtainModuleStatusEvent); on(_onSendCurtainPercentToApiEvent); on(_onOpenCurtainEvent); @@ -26,6 +32,13 @@ class CurtainModuleBloc extends Bloc { on(_onChangeControlBackEvent); on(_onChangeControlBackModeEvent); on(_onChangeCurtainModuleStatusEvent); + //batch + on(_onFetchCurtainModuleBatchStatus); + on(_onSendCurtainBatchPercentToApiEvent); + on(_onOpenCurtainBatchEvent); + on(_onCloseCurtainBatchEvent); + on(_onStopCurtainBatchEvent); + on(_onFactoryReset); } Future _onFetchCurtainModuleStatusEvent( @@ -224,6 +237,109 @@ class CurtainModuleBloc extends Bloc { } } + FutureOr _onFetchCurtainModuleBatchStatus( + CurtainModuleFetchBatchStatusEvent event, + Emitter emit, + ) async { + emit(CurtainModuleLoading()); + try { + final status = + await DevicesManagementApi().getBatchStatus(event.devicesIds); + + final result = Map.fromEntries( + status.status.map((element) => MapEntry(element.code, element.value)), + ); + + emit(CurtainModuleStatusLoaded( + curtainModuleStatus: CurtainModuleStatusModel.fromJson(result), + )); + } catch (e) { + emit(CurtainModuleError(message: e.toString())); + } + } + + Future _onSendCurtainBatchPercentToApiEvent( + SendCurtainBatchPercentToApiEvent event, + Emitter emit, + ) async { + try { + await batchControlDevicesService.batchControlDevices( + uuids: event.devicesId, + code: event.status.code, + value: event.status.value, + ); + } catch (e) { + emit(CurtainModuleError(message: 'Failed to send control command: $e')); + } + } + + Future _onOpenCurtainBatchEvent( + OpenCurtainBatchEvent event, + Emitter emit, + ) async { + try { + await batchControlDevicesService.batchControlDevices( + uuids: event.devicesId, + code: 'control', + value: 'open', + ); + } catch (e) { + emit(CurtainModuleError(message: 'Failed to open curtain: $e')); + } + } + + Future _onCloseCurtainBatchEvent( + CloseCurtainBatchEvent event, + Emitter emit, + ) async { + try { + await batchControlDevicesService.batchControlDevices( + uuids: event.devicesId, + code: 'control', + value: 'close', + ); + } catch (e) { + emit(CurtainModuleError(message: 'Failed to close curtain: $e')); + } + } + + Future _onStopCurtainBatchEvent( + StopCurtainBatchEvent event, + Emitter emit, + ) async { + try { + await batchControlDevicesService.batchControlDevices( + uuids: event.devicesId, + code: 'control', + value: 'stop', + ); + } catch (e) { + emit(CurtainModuleError(message: 'Failed to stop curtain: $e')); + } + } + + Future _onFactoryReset( + CurtainModuleFactoryReset event, + Emitter emit, + ) async { + emit(CurtainModuleLoading()); + try { + final response = await DevicesManagementApi().factoryReset( + event.factoryReset, + event.deviceId, + ); + if (!response) { + emit(const CurtainModuleError(message: 'Failed')); + } else { + add( + FetchCurtainModuleStatusEvent(deviceId: event.deviceId), + ); + } + } catch (e) { + emit(CurtainModuleError(message: e.toString())); + } + } + @override Future close() async { await _firebaseSubscription?.cancel(); diff --git a/lib/pages/device_managment/curtain_module/bloc/curtain_module_event.dart b/lib/pages/device_managment/curtain_module/bloc/curtain_module_event.dart index 6b0d89ae..4eec030d 100644 --- a/lib/pages/device_managment/curtain_module/bloc/curtain_module_event.dart +++ b/lib/pages/device_managment/curtain_module/bloc/curtain_module_event.dart @@ -129,4 +129,65 @@ class ChangeCurtainModuleStatusEvent extends CurtainModuleEvent { @override List get props => [deviceId, status]; -} \ No newline at end of file +} + +///batch +class CurtainModuleFetchBatchStatusEvent extends CurtainModuleEvent { + final List devicesIds; + + const CurtainModuleFetchBatchStatusEvent(this.devicesIds); + + @override + List get props => [devicesIds]; +} + +class SendCurtainBatchPercentToApiEvent extends CurtainModuleEvent { + final List devicesId; + final Status status; + + const SendCurtainBatchPercentToApiEvent({ + required this.devicesId, + required this.status, + }); + + @override + List get props => [devicesId, status]; +} + +class OpenCurtainBatchEvent extends CurtainModuleEvent { + final List devicesId; + + const OpenCurtainBatchEvent({required this.devicesId}); + + @override + List get props => [devicesId]; +} + +class CloseCurtainBatchEvent extends CurtainModuleEvent { + final List devicesId; + + const CloseCurtainBatchEvent({required this.devicesId}); + + @override + List get props => [devicesId]; +} + +class StopCurtainBatchEvent extends CurtainModuleEvent { + final List devicesId; + + const StopCurtainBatchEvent({required this.devicesId}); + + @override + List get props => [devicesId]; +} + +class CurtainModuleFactoryReset extends CurtainModuleEvent { + final String deviceId; + final FactoryResetModel factoryReset; + + const CurtainModuleFactoryReset( + {required this.deviceId, required this.factoryReset}); + + @override + List get props => [deviceId, factoryReset]; +} diff --git a/lib/pages/device_managment/curtain_module/view/curtain_module_batch.dart b/lib/pages/device_managment/curtain_module/view/curtain_module_batch.dart index 0e0dfdc3..bd28cd8a 100644 --- a/lib/pages/device_managment/curtain_module/view/curtain_module_batch.dart +++ b/lib/pages/device_managment/curtain_module/view/curtain_module_batch.dart @@ -1,8 +1,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:syncrow_web/pages/device_managment/curtain_module/bloc/batch/curtain_module_batch_bloc.dart'; +import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart'; +import 'package:syncrow_web/pages/device_managment/curtain_module/bloc/curtain_module_bloc.dart'; import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/curtain_movment_widget.dart'; +import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/icon_name_status_container.dart'; +import 'package:syncrow_web/services/batch_control_devices_service.dart'; import 'package:syncrow_web/services/control_device_service.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; @@ -17,8 +20,10 @@ class CurtainModuleBatchView extends StatelessWidget { @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => CurtainModuleBatchBloc(RemoteControlDeviceService()) - ..add(CutrainModuleFetchBatchStatusEvent(devicesIds: devicesIds)), + create: (context) => CurtainModuleBloc( + controlDeviceService: RemoteControlDeviceService(), + batchControlDevicesService: RemoteBatchControlDevicesService()) + ..add(CurtainModuleFetchBatchStatusEvent(devicesIds)), child: _buildStatusControls(context), ); } @@ -30,37 +35,41 @@ class CurtainModuleBatchView extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ ControlCurtainMovementWidget( - deviceId: devicesIds.first, + devicesId: devicesIds, ), const SizedBox( height: 10, ), SizedBox( height: 120, - width: 350, + // width: 350, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Expanded( - child: IconNameStatusContainer( - isFullIcon: false, - name: 'Factory Reset', - icon: Assets.factoryReset, - onTap: () {}, - status: false, - textColor: ColorsManager.blackColor, - ), - ), - Expanded( - child: IconNameStatusContainer( - isFullIcon: false, - name: 'Firmware Update', - icon: Assets.firmware, - onTap: () {}, - status: false, - textColor: ColorsManager.blackColor, - ), + // Expanded( + // child: + FactoryResetWidget( + callFactoryReset: () { + context.read().add( + CurtainModuleFactoryReset( + deviceId: devicesIds.first, + factoryReset: + FactoryResetModel(devicesUuid: devicesIds), + ), + ); + }, ), + // ), + // Expanded( + // child: IconNameStatusContainer( + // isFullIcon: false, + // name: 'Firmware Update', + // icon: Assets.firmware, + // onTap: () {}, + // status: false, + // textColor: ColorsManager.blackColor, + // ), + // ) ], ), ), diff --git a/lib/pages/device_managment/curtain_module/view/curtain_module_items.dart b/lib/pages/device_managment/curtain_module/view/curtain_module_items.dart index 22ccf90e..198c8713 100644 --- a/lib/pages/device_managment/curtain_module/view/curtain_module_items.dart +++ b/lib/pages/device_managment/curtain_module/view/curtain_module_items.dart @@ -4,6 +4,7 @@ import 'package:syncrow_web/pages/device_managment/curtain_module/bloc/curtain_m import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/curtain_movment_widget.dart'; import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/prefrences_dialog.dart'; import 'package:syncrow_web/pages/device_managment/shared/icon_name_status_container.dart'; +import 'package:syncrow_web/services/batch_control_devices_service.dart'; import 'package:syncrow_web/services/control_device_service.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; @@ -19,7 +20,9 @@ class CurtainModuleItems extends StatelessWidget with HelperResponsiveLayout { @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => CurtainModuleBloc(RemoteControlDeviceService()) + create: (context) => CurtainModuleBloc( + controlDeviceService: RemoteControlDeviceService(), + batchControlDevicesService: RemoteBatchControlDevicesService()) ..add(FetchCurtainModuleStatusEvent(deviceId: deviceId)), child: _buildStatusControls(context), ); @@ -32,7 +35,7 @@ class CurtainModuleItems extends StatelessWidget with HelperResponsiveLayout { crossAxisAlignment: CrossAxisAlignment.start, children: [ ControlCurtainMovementWidget( - deviceId: deviceId, + devicesId: [deviceId], ), const SizedBox( height: 10, @@ -70,12 +73,15 @@ class CurtainModuleItems extends StatelessWidget with HelperResponsiveLayout { icon: Assets.preferences, onTap: () => showDialog( context: context, - builder: (_) => CurtainModulePrefrencesDialog( - curtainModuleBloc: - context.watch(), - deviceId: deviceId, - curtainModuleStatusModel: - state.curtainModuleStatus, + builder: (_) => BlocProvider.value( + value: context.read(), + child: CurtainModulePrefrencesDialog( + curtainModuleBloc: + context.watch(), + deviceId: deviceId, + curtainModuleStatusModel: + state.curtainModuleStatus, + ), ), ), status: false, diff --git a/lib/pages/device_managment/curtain_module/widgets/curtain_movment_widget.dart b/lib/pages/device_managment/curtain_module/widgets/curtain_movment_widget.dart index 076c5a9c..e98ff11d 100644 --- a/lib/pages/device_managment/curtain_module/widgets/curtain_movment_widget.dart +++ b/lib/pages/device_managment/curtain_module/widgets/curtain_movment_widget.dart @@ -9,10 +9,10 @@ import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; class ControlCurtainMovementWidget extends StatelessWidget { - final String deviceId; + final List devicesId; const ControlCurtainMovementWidget({ super.key, - required this.deviceId, + required this.devicesId, }); @override @@ -26,9 +26,15 @@ class ControlCurtainMovementWidget extends StatelessWidget { CurtainActionWidget( icon: Assets.openCurtain, onTap: () { - context.read().add( - OpenCurtainEvent(deviceId: deviceId), - ); + if (devicesId.length == 1) { + context.read().add( + OpenCurtainEvent(deviceId: devicesId.first), + ); + } else { + context.read().add( + OpenCurtainBatchEvent(devicesId: devicesId), + ); + } }, ), const SizedBox( @@ -37,9 +43,15 @@ class ControlCurtainMovementWidget extends StatelessWidget { CurtainActionWidget( icon: Assets.pauseCurtain, onTap: () { - context.read().add( - StopCurtainEvent(deviceId: deviceId), - ); + if (devicesId.length == 1) { + context.read().add( + StopCurtainEvent(deviceId: devicesId.first), + ); + } else { + context.read().add( + StopCurtainBatchEvent(devicesId: devicesId), + ); + } }, ), const SizedBox( @@ -48,9 +60,15 @@ class ControlCurtainMovementWidget extends StatelessWidget { CurtainActionWidget( icon: Assets.closeCurtain, onTap: () { - context.read().add( - CloseCurtainEvent(deviceId: deviceId), - ); + if (devicesId.length == 1) { + context.read().add( + CloseCurtainEvent(deviceId: devicesId.first), + ); + } else { + context.read().add( + CloseCurtainBatchEvent(devicesId: devicesId), + ); + } }, ), BlocBuilder( @@ -84,7 +102,7 @@ class ControlCurtainMovementWidget extends StatelessWidget { } else if (state is CurtainModuleStatusLoaded) { return CurtainSliderWidget( status: state.curtainModuleStatus, - deviceId: deviceId, + devicesId: devicesId, ); } else { return const Center( @@ -108,12 +126,12 @@ class ControlCurtainMovementWidget extends StatelessWidget { class CurtainSliderWidget extends StatefulWidget { final CurtainModuleStatusModel status; - final String deviceId; + final List devicesId; const CurtainSliderWidget({ super.key, required this.status, - required this.deviceId, + required this.devicesId, }); @override @@ -167,16 +185,27 @@ class _CurtainSliderWidgetState extends State { onChangeEnd: (value) { final int targetPercent = (value * 100).round(); - // Dispatch API call - context.read().add( - SendCurtainPercentToApiEvent( - deviceId: widget.deviceId, - status: Status( - code: 'percent_control', - value: targetPercent, + if (widget.devicesId.length == 1) { + context.read().add( + SendCurtainPercentToApiEvent( + deviceId: widget.devicesId.first, + status: Status( + code: 'percent_control', + value: targetPercent, + ), ), - ), - ); + ); + } else { + context.read().add( + SendCurtainBatchPercentToApiEvent( + devicesId: widget.devicesId, + status: Status( + code: 'percent_control', + value: targetPercent, + ), + ), + ); + } // Revert back to Firebase-synced stream setState(() { diff --git a/lib/pages/device_managment/shared/device_batch_control_dialog.dart b/lib/pages/device_managment/shared/device_batch_control_dialog.dart index f2dc68f5..c7ea6c71 100644 --- a/lib/pages/device_managment/shared/device_batch_control_dialog.dart +++ b/lib/pages/device_managment/shared/device_batch_control_dialog.dart @@ -4,7 +4,8 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_mo import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart'; -class DeviceBatchControlDialog extends StatelessWidget with RouteControlsBasedCode { +class DeviceBatchControlDialog extends StatelessWidget + with RouteControlsBasedCode { final List devices; const DeviceBatchControlDialog({super.key, required this.devices}); @@ -18,7 +19,7 @@ class DeviceBatchControlDialog extends StatelessWidget with RouteControlsBasedCo borderRadius: BorderRadius.circular(20), ), child: SizedBox( - width: devices.length < 2 ? 500 : 800, + width: devices.length < 2 ? 600 : 800, // height: context.screenHeight * 0.7, child: SingleChildScrollView( child: Padding( diff --git a/lib/services/batch_control_devices_service.dart b/lib/services/batch_control_devices_service.dart index f78cdef4..16542c8c 100644 --- a/lib/services/batch_control_devices_service.dart +++ b/lib/services/batch_control_devices_service.dart @@ -11,7 +11,8 @@ abstract interface class BatchControlDevicesService { }); } -final class RemoteBatchControlDevicesService implements BatchControlDevicesService { +final class RemoteBatchControlDevicesService + implements BatchControlDevicesService { @override Future batchControlDevices({ required List uuids,