diff --git a/lib/pages/common/buttons/search_reset_buttons.dart b/lib/pages/common/buttons/search_reset_buttons.dart index 7b63a485..6fdbfd2a 100644 --- a/lib/pages/common/buttons/search_reset_buttons.dart +++ b/lib/pages/common/buttons/search_reset_buttons.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:syncrow_web/pages/common/buttons/default_button.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/style.dart'; -import 'package:syncrow_web/utils/color_manager.dart'; class SearchResetButtons extends StatelessWidget { const SearchResetButtons({ @@ -17,8 +17,10 @@ class SearchResetButtons extends StatelessWidget { @override Widget build(BuildContext context) { return Row( + mainAxisSize: MainAxisSize.min, children: [ Column( + mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ const SizedBox(height: 25), diff --git a/lib/pages/device_managment/all_devices/widgets/device_managment_body.dart b/lib/pages/device_managment/all_devices/widgets/device_managment_body.dart index 907e5390..a3c975c1 100644 --- a/lib/pages/device_managment/all_devices/widgets/device_managment_body.dart +++ b/lib/pages/device_managment/all_devices/widgets/device_managment_body.dart @@ -72,6 +72,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout { child: state is DeviceManagementLoading ? const Center(child: CircularProgressIndicator()) : Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( padding: isLargeScreenSize(context) diff --git a/lib/pages/device_managment/all_devices/widgets/device_search_filters.dart b/lib/pages/device_managment/all_devices/widgets/device_search_filters.dart index fbbe65ab..18d72fc9 100644 --- a/lib/pages/device_managment/all_devices/widgets/device_search_filters.dart +++ b/lib/pages/device_managment/all_devices/widgets/device_search_filters.dart @@ -14,29 +14,29 @@ class DeviceSearchFilters extends StatefulWidget { class _DeviceSearchFiltersState extends State with HelperResponsiveLayout { - final _unitNameController = TextEditingController(); - final _productNameController = TextEditingController(); + late final TextEditingController _unitNameController; + late final TextEditingController _productNameController; - List get _widgets => [ - _buildSearchField("Space Name", _unitNameController, 200), - _buildSearchField("Device Name / Product Name", _productNameController, 300), - _buildSearchResetButtons(), - ]; + @override + void initState() { + _unitNameController = TextEditingController(); + _productNameController = TextEditingController(); + super.initState(); + } @override Widget build(BuildContext context) { - if (isExtraLargeScreenSize(context)) { - return Row( - children: _widgets - .map((e) => Padding(padding: const EdgeInsets.all(10), child: e)) - .toList(), - ); - } - return Wrap( + alignment: WrapAlignment.start, + runAlignment: WrapAlignment.start, + crossAxisAlignment: WrapCrossAlignment.center, spacing: 20, runSpacing: 10, - children: _widgets, + children: [ + _buildSearchField("Space Name", _unitNameController, 200), + _buildSearchField("Device Name / Product Name", _productNameController, 300), + _buildSearchResetButtons(), + ], ); } diff --git a/lib/pages/device_managment/flush_mounted_presence_sensor/bloc/flush_mounted_presence_sensor_event.dart b/lib/pages/device_managment/flush_mounted_presence_sensor/bloc/flush_mounted_presence_sensor_event.dart index f70e7f3a..08a01615 100644 --- a/lib/pages/device_managment/flush_mounted_presence_sensor/bloc/flush_mounted_presence_sensor_event.dart +++ b/lib/pages/device_managment/flush_mounted_presence_sensor/bloc/flush_mounted_presence_sensor_event.dart @@ -24,11 +24,10 @@ class FlushMountedPresenceSensorChangeValueEvent extends FlushMountedPresenceSensorEvent { final int value; final String code; - final bool isBatchControl; + const FlushMountedPresenceSensorChangeValueEvent({ required this.value, required this.code, - this.isBatchControl = false, }); @override diff --git a/lib/pages/device_managment/flush_mounted_presence_sensor/views/flush_mounted_presence_sensor_batch_control_view.dart b/lib/pages/device_managment/flush_mounted_presence_sensor/views/flush_mounted_presence_sensor_batch_control_view.dart index 78db6e2e..2860e5cc 100644 --- a/lib/pages/device_managment/flush_mounted_presence_sensor/views/flush_mounted_presence_sensor_batch_control_view.dart +++ b/lib/pages/device_managment/flush_mounted_presence_sensor/views/flush_mounted_presence_sensor_batch_control_view.dart @@ -75,7 +75,7 @@ class FlushMountedPresenceSensorBatchControlView extends StatelessWidget ), ), PresenceUpdateData( - value: (model.nearDetection / 100).toDouble(), + value: (model.nearDetection / 100).clamp(0.0, double.infinity), title: 'Nearest Detect Dist:', description: 'm', minValue: 0.0, @@ -92,7 +92,7 @@ class FlushMountedPresenceSensorBatchControlView extends StatelessWidget ), ), PresenceUpdateData( - value: (model.farDetection / 100).toDouble(), + value: (model.farDetection / 100).clamp(0.0, double.infinity), title: 'Max Detect Dist:', description: 'm', minValue: 0.0, @@ -109,7 +109,7 @@ class FlushMountedPresenceSensorBatchControlView extends StatelessWidget ), ), PresenceUpdateData( - value: model.presenceDelay.toDouble(), + value: model.sensiReduce.toDouble(), title: 'Trigger Level:', minValue: 0, maxValue: 3, @@ -117,7 +117,7 @@ class FlushMountedPresenceSensorBatchControlView extends StatelessWidget action: (int value) => context.read().add( FlushMountedPresenceSensorBatchControlEvent( deviceIds: devicesIds, - code: FlushMountedPresenceSensorModel.codePresenceDelay, + code: FlushMountedPresenceSensorModel.codeSensiReduce, value: value, ), ), @@ -137,19 +137,21 @@ class FlushMountedPresenceSensorBatchControlView extends StatelessWidget ), ), PresenceUpdateData( - value: (model.sensiReduce.toDouble()), + value: (model.presenceDelay / 10).toDouble(), title: 'Target Confirm Time:', description: 's', - minValue: 0, - maxValue: 3, - steps: 1, - action: (int value) => context.read().add( - FlushMountedPresenceSensorBatchControlEvent( - deviceIds: devicesIds, - code: FlushMountedPresenceSensorModel.codeSensiReduce, - value: value, - ), - ), + minValue: 0.0, + maxValue: 0.5, + steps: 0.1, + valuesPercision: 1, + action: (double value) => + context.read().add( + FlushMountedPresenceSensorBatchControlEvent( + deviceIds: devicesIds, + code: FlushMountedPresenceSensorModel.codePresenceDelay, + value: (value * 10).toInt(), + ), + ), ), PresenceUpdateData( value: ((model.noneDelay / 10).toDouble()), diff --git a/lib/pages/device_managment/flush_mounted_presence_sensor/views/flush_mounted_presence_sensor_control_view.dart b/lib/pages/device_managment/flush_mounted_presence_sensor/views/flush_mounted_presence_sensor_control_view.dart index f0815c60..08ad809d 100644 --- a/lib/pages/device_managment/flush_mounted_presence_sensor/views/flush_mounted_presence_sensor_control_view.dart +++ b/lib/pages/device_managment/flush_mounted_presence_sensor/views/flush_mounted_presence_sensor_control_view.dart @@ -15,7 +15,7 @@ import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_la class FlushMountedPresenceSensorControlView extends StatelessWidget with HelperResponsiveLayout { - const FlushMountedPresenceSensorControlView({super.key, required this.device}); + const FlushMountedPresenceSensorControlView({required this.device, super.key}); final AllDevicesModel device; @@ -113,7 +113,7 @@ class FlushMountedPresenceSensorControlView extends StatelessWidget ), ), PresenceUpdateData( - value: (model.nearDetection / 100).toDouble(), + value: (model.nearDetection / 100).clamp(0.0, double.infinity), title: 'Nearest Detect Dist:', description: 'm', minValue: 0.0, @@ -129,7 +129,7 @@ class FlushMountedPresenceSensorControlView extends StatelessWidget ), ), PresenceUpdateData( - value: (model.farDetection / 100).toDouble(), + value: (model.farDetection / 100).clamp(0.0, double.infinity), title: 'Max Detect Dist:', description: 'm', minValue: 0.0, @@ -145,20 +145,20 @@ class FlushMountedPresenceSensorControlView extends StatelessWidget ), ), PresenceUpdateData( - value: (model.presenceDelay.toDouble()), + value: model.sensiReduce.toDouble(), title: 'Trigger Level:', minValue: 0, maxValue: 3, steps: 1, action: (int value) => context.read().add( FlushMountedPresenceSensorChangeValueEvent( - code: FlushMountedPresenceSensorModel.codePresenceDelay, + code: FlushMountedPresenceSensorModel.codeSensiReduce, value: value, ), ), ), PresenceUpdateData( - value: (model.occurDistReduce.toDouble()), + value: model.occurDistReduce.toDouble(), title: 'Indent Level:', minValue: 0, maxValue: 3, @@ -171,21 +171,23 @@ class FlushMountedPresenceSensorControlView extends StatelessWidget ), ), PresenceUpdateData( - value: (model.sensiReduce.toDouble()), + value: (model.presenceDelay / 10).toDouble(), + valuesPercision: 1, title: 'Target Confirm Time:', description: 's', - minValue: 0, - maxValue: 3, - steps: 1, - action: (int value) => context.read().add( - FlushMountedPresenceSensorChangeValueEvent( - code: FlushMountedPresenceSensorModel.codeSensiReduce, - value: value, - ), - ), + minValue: 0.0, + maxValue: 0.5, + steps: 0.1, + action: (double value) => + context.read().add( + FlushMountedPresenceSensorChangeValueEvent( + code: FlushMountedPresenceSensorModel.codePresenceDelay, + value: (value * 10).toInt(), + ), + ), ), PresenceUpdateData( - value: ((model.noneDelay / 10).toDouble()), + value: (model.noneDelay / 10).toDouble(), description: 's', title: 'Disappe Delay:', minValue: 20, diff --git a/lib/pages/device_managment/power_clamp/bloc/smart_power_bloc.dart b/lib/pages/device_managment/power_clamp/bloc/smart_power_bloc.dart index 52cccff4..24c5138f 100644 --- a/lib/pages/device_managment/power_clamp/bloc/smart_power_bloc.dart +++ b/lib/pages/device_managment/power_clamp/bloc/smart_power_bloc.dart @@ -217,29 +217,31 @@ class SmartPowerBloc extends Bloc { try { var status = await DevicesManagementApi().getPowerClampInfo(event.deviceId); - deviceStatus = PowerClampModel.fromJson(status); - + deviceStatus = PowerClampModel.fromJson(status as Map? ??{}); + final phaseADataPoints = deviceStatus.status.phaseA.dataPoints; + final phaseBDataPoints = deviceStatus.status.phaseB.dataPoints; + final phaseCDataPoints = deviceStatus.status.phaseC.dataPoints; phaseData = [ { 'name': 'Phase A', - 'voltage': '${deviceStatus.status.phaseA.dataPoints[0].value / 10} V', - 'current': '${deviceStatus.status.phaseA.dataPoints[1].value / 10} A', - 'activePower': '${deviceStatus.status.phaseA.dataPoints[2].value} W', - 'powerFactor': '${deviceStatus.status.phaseA.dataPoints[3].value}', + 'voltage': '${(phaseADataPoints.elementAtOrNull(0)?.value as num? ?? 0) / 10} V', + 'current': '${(phaseADataPoints.elementAtOrNull(1)?.value as num? ?? 0) / 10} A', + 'activePower': '${phaseADataPoints.elementAtOrNull(2)?.value??'N/A'} W', + 'powerFactor': '${phaseADataPoints.elementAtOrNull(3)?.value??'N/A'}', }, { 'name': 'Phase B', - 'voltage': '${deviceStatus.status.phaseB.dataPoints[0].value / 10} V', - 'current': '${deviceStatus.status.phaseB.dataPoints[1].value / 10} A', - 'activePower': '${deviceStatus.status.phaseB.dataPoints[2].value} W', - 'powerFactor': '${deviceStatus.status.phaseB.dataPoints[3].value}', + 'voltage': '${(phaseBDataPoints .elementAtOrNull(0)?.value as num? ?? 0) / 10} V', + 'current': '${(phaseBDataPoints .elementAtOrNull(1)?.value as num? ?? 0) / 10} A', + 'activePower': '${phaseBDataPoints.elementAtOrNull(2)?.value??'N/A'} W', + 'powerFactor': '${phaseBDataPoints.elementAtOrNull(3)?.value??'N/A'}', }, { 'name': 'Phase C', - 'voltage': '${deviceStatus.status.phaseC.dataPoints[0].value / 10} V', - 'current': '${deviceStatus.status.phaseC.dataPoints[1].value / 10} A', - 'activePower': '${deviceStatus.status.phaseC.dataPoints[2].value} W', - 'powerFactor': '${deviceStatus.status.phaseC.dataPoints[3].value}', + 'voltage': '${(phaseCDataPoints.elementAtOrNull(0)?.value as num? ?? 0) / 10} V', + 'current': '${(phaseCDataPoints.elementAtOrNull(1)?.value as num? ?? 0) / 10} A', + 'activePower': '${phaseCDataPoints.elementAtOrNull(2)?.value ?? 'N/A'} W', + 'powerFactor': '${phaseCDataPoints.elementAtOrNull(3)?.value ?? 'N/A'}', }, ]; emit(GetDeviceStatus()); @@ -785,7 +787,7 @@ class SmartPowerBloc extends Bloc { void selectDateRange() async { DateTime startDate = dateTime!; DateTime endDate = DateTime(startDate.year, startDate.month + 1, 1) - .subtract(Duration(days: 1)); + .subtract(const Duration(days: 1)); String formattedEndDate = DateFormat('dd/MM/yyyy').format(endDate); endChartDate = ' - $formattedEndDate'; } diff --git a/lib/pages/device_managment/power_clamp/models/power_clamp_model.dart b/lib/pages/device_managment/power_clamp/models/power_clamp_model.dart index 914a255b..4318d5ee 100644 --- a/lib/pages/device_managment/power_clamp/models/power_clamp_model.dart +++ b/lib/pages/device_managment/power_clamp/models/power_clamp_model.dart @@ -12,9 +12,9 @@ class PowerClampModel { factory PowerClampModel.fromJson(Map json) { return PowerClampModel( - productUuid: json['productUuid'], - productType: json['productType'], - status: PowerStatus.fromJson(json['status']), + productUuid: json['productUuid'] as String? ?? '', + productType: json['productType'] as String? ?? '', + status: PowerStatus.fromJson(json['status'] as Map? ?? {}), ); } @@ -26,7 +26,7 @@ class PowerClampModel { return PowerClampModel( productUuid: productUuid ?? this.productUuid, productType: productType ?? this.productType, - status: statusPower ?? this.status, + status: statusPower ?? status, ); } } @@ -46,12 +46,10 @@ class PowerStatus { factory PowerStatus.fromJson(Map json) { return PowerStatus( - phaseA: Phase.fromJson(json['phaseA']), - phaseB: Phase.fromJson(json['phaseB']), - phaseC: Phase.fromJson(json['phaseC']), - general: Phase.fromJson(json['general'] - // List.from( - // json['general'].map((x) => DataPoint.fromJson(x))), + phaseA: Phase.fromJson(json['phaseA']as List? ?? []), + phaseB: Phase.fromJson(json['phaseB']as List? ?? []), + phaseC: Phase.fromJson(json['phaseC']as List? ?? []), + general: Phase.fromJson(json['general']as List? ?? [] )); } } @@ -69,30 +67,30 @@ class Phase { } class DataPoint { - dynamic code; - dynamic customName; - dynamic dpId; - dynamic time; - dynamic type; - dynamic value; + final String? code; + final String? customName; + final int? dpId; + final int? time; + final String? type; + final dynamic value; DataPoint({ - required this.code, - required this.customName, - required this.dpId, - required this.time, - required this.type, - required this.value, + this.code, + this.customName, + this.dpId, + this.time, + this.type, + this.value, }); factory DataPoint.fromJson(Map json) { return DataPoint( - code: json['code'], - customName: json['customName'], - dpId: json['dpId'], - time: json['time'], - type: json['type'], - value: json['value'], + code: json['code'] as String?, + customName: json['customName'] as String?, + dpId: json['dpId'] as int?, + time: json['time'] as int?, + type: json['type'] as String?, + value: json['value'] as dynamic, ); } } diff --git a/lib/pages/device_managment/power_clamp/view/power_chart.dart b/lib/pages/device_managment/power_clamp/view/power_chart.dart index 19050b8a..7d6371f4 100644 --- a/lib/pages/device_managment/power_clamp/view/power_chart.dart +++ b/lib/pages/device_managment/power_clamp/view/power_chart.dart @@ -1,5 +1,5 @@ -import 'package:flutter/material.dart'; import 'package:fl_chart/fl_chart.dart'; +import 'package:flutter/material.dart'; import 'package:syncrow_web/utils/color_manager.dart'; class EnergyConsumptionPage extends StatefulWidget { @@ -10,7 +10,8 @@ class EnergyConsumptionPage extends StatefulWidget { final Widget widget; final Function()? onTap; - EnergyConsumptionPage({ + const EnergyConsumptionPage({ + super.key, required this.chartData, required this.totalConsumption, required this.date, @@ -91,11 +92,12 @@ class _EnergyConsumptionPageState extends State { ], ), Column( + mainAxisSize: MainAxisSize.min, children: [ Padding( padding: const EdgeInsets.only(top: 10), child: SizedBox( - height: MediaQuery.of(context).size.height * 0.11, + height: MediaQuery.sizeOf(context).height * 0.09, child: LineChart( LineChartData( lineTouchData: LineTouchData( @@ -151,7 +153,7 @@ class _EnergyConsumptionPageState extends State { child: RotatedBox( quarterTurns: -1, child: Text(_chartData[index].time, - style: TextStyle(fontSize: 10)), + style: const TextStyle(fontSize: 10)), ), ); } @@ -190,8 +192,8 @@ class _EnergyConsumptionPageState extends State { spots: _chartData .asMap() .entries - .map((entry) => FlSpot(entry.key.toDouble(), - entry.value.consumption)) + .map((entry) => FlSpot( + entry.key.toDouble(), entry.value.consumption)) .toList(), isCurved: true, color: ColorsManager.primaryColor.withOpacity(0.6), @@ -218,7 +220,7 @@ class _EnergyConsumptionPageState extends State { borderData: FlBorderData( show: false, border: Border.all( - color: Color(0xff023DFE).withOpacity(0.7), + color: const Color(0xff023DFE).withOpacity(0.7), width: 10, ), ), @@ -253,11 +255,9 @@ class _EnergyConsumptionPageState extends State { child: InkWell( onTap: widget.onTap, child: Center( - child: SizedBox( - child: Padding( - padding: const EdgeInsets.all(5), - child: Text(widget.date), - ), + child: Padding( + padding: const EdgeInsets.all(5), + child: Text(widget.date), ), ), ), diff --git a/lib/pages/device_managment/power_clamp/view/smart_power_device_control.dart b/lib/pages/device_managment/power_clamp/view/smart_power_device_control.dart index 03d649fa..67313802 100644 --- a/lib/pages/device_managment/power_clamp/view/smart_power_device_control.dart +++ b/lib/pages/device_managment/power_clamp/view/smart_power_device_control.dart @@ -12,8 +12,7 @@ import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; //Smart Power Clamp -class SmartPowerDeviceControl extends StatelessWidget - with HelperResponsiveLayout { +class SmartPowerDeviceControl extends StatelessWidget with HelperResponsiveLayout { final String deviceId; const SmartPowerDeviceControl({super.key, required this.deviceId}); @@ -25,27 +24,27 @@ class SmartPowerDeviceControl extends StatelessWidget ..add(SmartPowerFetchDeviceEvent(deviceId)), child: BlocBuilder( builder: (context, state) { - final _blocProvider = BlocProvider.of(context); + final blocProvider = BlocProvider.of(context); if (state is SmartPowerLoading) { return const Center(child: CircularProgressIndicator()); } else if (state is FakeState) { return _buildStatusControls( - currentPage: _blocProvider.currentPage, + currentPage: blocProvider.currentPage, context: context, - blocProvider: _blocProvider, + blocProvider: blocProvider, ); } else if (state is GetDeviceStatus) { return _buildStatusControls( - currentPage: _blocProvider.currentPage, + currentPage: blocProvider.currentPage, context: context, - blocProvider: _blocProvider, + blocProvider: blocProvider, ); } else if (state is FilterRecordsState) { return _buildStatusControls( - currentPage: _blocProvider.currentPage, + currentPage: blocProvider.currentPage, context: context, - blocProvider: _blocProvider, + blocProvider: blocProvider, ); } return const Center(child: CircularProgressIndicator()); @@ -60,7 +59,7 @@ class SmartPowerDeviceControl extends StatelessWidget required SmartPowerBloc blocProvider, required int currentPage, }) { - PageController _pageController = PageController(initialPage: currentPage); + PageController pageController = PageController(initialPage: currentPage); return Container( padding: const EdgeInsets.symmetric(horizontal: 50), child: DeviceControlsContainer( @@ -85,25 +84,31 @@ class SmartPowerDeviceControl extends StatelessWidget PowerClampInfoCard( iconPath: Assets.powerActiveIcon, title: 'Active', - value: blocProvider - .deviceStatus.status.general.dataPoints[2].value - .toString(), + value: blocProvider.deviceStatus.status.general.dataPoints + .elementAtOrNull(2) + ?.value + .toString() ?? + '', unit: '', ), PowerClampInfoCard( iconPath: Assets.voltMeterIcon, title: 'Current', - value: blocProvider - .deviceStatus.status.general.dataPoints[1].value - .toString(), + value: blocProvider.deviceStatus.status.general.dataPoints + .elementAtOrNull(1) + ?.value + .toString() ?? + '', unit: ' A', ), PowerClampInfoCard( iconPath: Assets.frequencyIcon, title: 'Frequency', - value: blocProvider - .deviceStatus.status.general.dataPoints[4].value - .toString(), + value: blocProvider.deviceStatus.status.general.dataPoints + .elementAtOrNull(4) + ?.value + .toString() ?? + '', unit: ' Hz', ), ], @@ -142,7 +147,7 @@ class SmartPowerDeviceControl extends StatelessWidget icon: const Icon(Icons.arrow_left), onPressed: () { blocProvider.add(SmartPowerArrowPressedEvent(-1)); - _pageController.previousPage( + pageController.previousPage( duration: const Duration(milliseconds: 300), curve: Curves.easeInOut, ); @@ -162,7 +167,7 @@ class SmartPowerDeviceControl extends StatelessWidget icon: const Icon(Icons.arrow_right), onPressed: () { blocProvider.add(SmartPowerArrowPressedEvent(1)); - _pageController.nextPage( + pageController.nextPage( duration: const Duration(milliseconds: 300), curve: Curves.easeInOut, ); @@ -177,7 +182,7 @@ class SmartPowerDeviceControl extends StatelessWidget Expanded( flex: 2, child: PageView( - controller: _pageController, + controller: pageController, onPageChanged: (int page) { blocProvider.add(SmartPowerPageChangedEvent(page)); }, @@ -190,8 +195,8 @@ class SmartPowerDeviceControl extends StatelessWidget blocProvider.add(SelectDateEvent(context: context)); blocProvider.add(FilterRecordsByDateEvent( selectedDate: blocProvider.dateTime!, - viewType: blocProvider - .views[blocProvider.currentIndex])); + viewType: + blocProvider.views[blocProvider.currentIndex])); }, widget: blocProvider.dateSwitcher(), chartData: blocProvider.energyDataList.isNotEmpty diff --git a/lib/services/batch_control_devices_service.dart b/lib/services/batch_control_devices_service.dart index de5af9ee..f78cdef4 100644 --- a/lib/services/batch_control_devices_service.dart +++ b/lib/services/batch_control_devices_service.dart @@ -46,14 +46,14 @@ final class DebouncedBatchControlDevicesService final BatchControlDevicesService decoratee; final Duration debounceDuration; - final _pendingRequests = <(List uuids, String code, Object value)>[]; - var _isProcessing = false; - DebouncedBatchControlDevicesService({ required this.decoratee, - this.debounceDuration = const Duration(milliseconds: 800), + this.debounceDuration = const Duration(milliseconds: 1500), }); + final _pendingRequests = <(List uuids, String code, Object value)>[]; + var _isProcessing = false; + @override Future batchControlDevices({ required List uuids, @@ -68,16 +68,26 @@ final class DebouncedBatchControlDevicesService await Future.delayed(debounceDuration); - final lastRequest = _pendingRequests.last; + final groupedRequests = + uuids, String code, Object value)>{}; + for (final request in _pendingRequests) { + final (_, requestCode, requestValue) = request; + groupedRequests[requestCode] = request; + } _pendingRequests.clear(); try { - final (lastRequestUuids, lastRequestCode, lastRequestValue) = lastRequest; - return decoratee.batchControlDevices( - uuids: lastRequestUuids, - code: lastRequestCode, - value: lastRequestValue, - ); + var allSuccessful = true; + for (final request in groupedRequests.values) { + final (lastRequestUuids, lastRequestCode, lastRequestValue) = request; + final success = await decoratee.batchControlDevices( + uuids: lastRequestUuids, + code: lastRequestCode, + value: lastRequestValue, + ); + if (!success) allSuccessful = false; + } + return allSuccessful; } finally { _isProcessing = false; } diff --git a/lib/services/control_device_service.dart b/lib/services/control_device_service.dart index 9913b52e..49463306 100644 --- a/lib/services/control_device_service.dart +++ b/lib/services/control_device_service.dart @@ -40,7 +40,7 @@ final class DebouncedControlDeviceService implements ControlDeviceService { DebouncedControlDeviceService({ required this.decoratee, - this.debounceDuration = const Duration(milliseconds: 800), + this.debounceDuration = const Duration(milliseconds: 1500), }); final _pendingRequests = <(String deviceUuid, Status status)>[]; @@ -59,15 +59,24 @@ final class DebouncedControlDeviceService implements ControlDeviceService { await Future.delayed(debounceDuration); - final lastRequest = _pendingRequests.last; + final groupedRequests = {}; + for (final request in _pendingRequests) { + final (_, requestStatus) = request; + groupedRequests[requestStatus.code] = request; + } _pendingRequests.clear(); try { - final (lastRequestDeviceUuid, lastRequestStatus) = lastRequest; - return decoratee.controlDevice( - deviceUuid: lastRequestDeviceUuid, - status: lastRequestStatus, - ); + var allSuccessful = true; + for (final request in groupedRequests.values) { + final (lastRequestDeviceUuid, lastRequestStatus) = request; + final success = await decoratee.controlDevice( + deviceUuid: lastRequestDeviceUuid, + status: lastRequestStatus, + ); + if (!success) allSuccessful = false; + } + return allSuccessful; } finally { _isProcessing = false; }