mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 15:17:31 +00:00
Merge pull request #154 from SyncrowIOT/Add-Flush-Mounted-Presence-Sensor-Single-Control
Add flush mounted presence sensor single control
This commit is contained in:
@ -9,6 +9,7 @@ import 'package:syncrow_web/pages/device_managment/curtain/view/curtain_batch_st
|
||||
import 'package:syncrow_web/pages/device_managment/curtain/view/curtain_status_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/door_lock/view/door_lock_batch_control_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/door_lock/view/door_lock_control_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/flush_mounted_presence_sensor/views/flush_mounted_presence_sensor_control_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/garage_door/view/garage_door_batch_control_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/garage_door/view/garage_door_control_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/gateway/view/gateway_batch_control.dart';
|
||||
@ -104,6 +105,9 @@ mixin RouteControlsBasedCode {
|
||||
);
|
||||
case 'SOS':
|
||||
return SosDeviceControlsView(device: device);
|
||||
|
||||
case 'NCPS':
|
||||
return FlushMountedPresenceSensorControlView(device: device);
|
||||
default:
|
||||
return const SizedBox();
|
||||
}
|
||||
|
@ -0,0 +1,237 @@
|
||||
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:syncrow_web/pages/device_managment/all_devices/models/device_reports.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/flush_mounted_presence_sensor/models/flush_mounted_presence_sensor_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 'flush_mounted_presence_sensor_event.dart';
|
||||
part 'flush_mounted_presence_sensor_state.dart';
|
||||
|
||||
class FlushMountedPresenceSensorBloc
|
||||
extends Bloc<FlushMountedPresenceSensorEvent, FlushMountedPresenceSensorState> {
|
||||
final String deviceId;
|
||||
final ControlDeviceService controlDeviceService;
|
||||
final BatchControlDevicesService batchControlDevicesService;
|
||||
|
||||
late FlushMountedPresenceSensorModel deviceStatus;
|
||||
FlushMountedPresenceSensorBloc({
|
||||
required this.deviceId,
|
||||
required this.controlDeviceService,
|
||||
required this.batchControlDevicesService,
|
||||
}) : super(FlushMountedPresenceSensorInitialState()) {
|
||||
on<FlushMountedPresenceSensorFetchStatusEvent>(
|
||||
_onFlushMountedPresenceSensorFetchStatusEvent,
|
||||
);
|
||||
on<FlushMountedPresenceSensorFetchBatchStatusEvent>(
|
||||
_onFlushMountedPresenceSensorFetchBatchStatusEvent);
|
||||
on<FlushMountedPresenceSensorChangeValueEvent>(
|
||||
_onFlushMountedPresenceSensorChangeValueEvent,
|
||||
);
|
||||
on<FlushMountedPresenceSensorBatchControlEvent>(
|
||||
_onFlushMountedPresenceSensorBatchControlEvent,
|
||||
);
|
||||
on<FlushMountedPresenceSensorGetDeviceReportsEvent>(
|
||||
_onFlushMountedPresenceSensorGetDeviceReportsEvent);
|
||||
on<FlushMountedPresenceSensorShowDescriptionEvent>(
|
||||
_onFlushMountedPresenceSensorShowDescriptionEvent,
|
||||
);
|
||||
on<FlushMountedPresenceSensorBackToGridViewEvent>(
|
||||
_onFlushMountedPresenceSensorBackToGridViewEvent,
|
||||
);
|
||||
on<FlushMountedPresenceSensorFactoryResetEvent>(
|
||||
_onFlushMountedPresenceSensorFactoryResetEvent,
|
||||
);
|
||||
}
|
||||
|
||||
void _onFlushMountedPresenceSensorFetchStatusEvent(
|
||||
FlushMountedPresenceSensorFetchStatusEvent event,
|
||||
Emitter<FlushMountedPresenceSensorState> emit,
|
||||
) async {
|
||||
emit(FlushMountedPresenceSensorLoadingInitialState());
|
||||
try {
|
||||
final response = await DevicesManagementApi().getDeviceStatus(deviceId);
|
||||
deviceStatus = FlushMountedPresenceSensorModel.fromJson(response.status);
|
||||
emit(FlushMountedPresenceSensorUpdateState(model: deviceStatus));
|
||||
_listenToChanges(emit, deviceId);
|
||||
} catch (e) {
|
||||
emit(FlushMountedPresenceSensorFailedState(error: e.toString()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onFlushMountedPresenceSensorFetchBatchStatusEvent(
|
||||
FlushMountedPresenceSensorFetchBatchStatusEvent event,
|
||||
Emitter<FlushMountedPresenceSensorState> emit,
|
||||
) async {
|
||||
emit(FlushMountedPresenceSensorLoadingInitialState());
|
||||
try {
|
||||
final response = await DevicesManagementApi().getBatchStatus(event.devicesIds);
|
||||
deviceStatus = FlushMountedPresenceSensorModel.fromJson(response.status);
|
||||
emit(FlushMountedPresenceSensorUpdateState(model: deviceStatus));
|
||||
} catch (e) {
|
||||
emit(FlushMountedPresenceSensorFailedState(error: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _listenToChanges(
|
||||
Emitter<FlushMountedPresenceSensorState> emit,
|
||||
String deviceId,
|
||||
) async {
|
||||
final ref = FirebaseDatabase.instance.ref(
|
||||
'device-status/$deviceId',
|
||||
);
|
||||
|
||||
await ref.onValue.listen(
|
||||
(DatabaseEvent event) async {
|
||||
Map<dynamic, dynamic> usersMap =
|
||||
event.snapshot.value as Map<dynamic, dynamic>;
|
||||
List<Status> statusList = [];
|
||||
|
||||
(usersMap['status'] as List<dynamic>?)?.forEach((element) {
|
||||
statusList.add(Status(code: element['code'], value: element['value']));
|
||||
});
|
||||
|
||||
deviceStatus = FlushMountedPresenceSensorModel.fromJson(statusList);
|
||||
if (!emit.isDone) {
|
||||
emit(FlushMountedPresenceSensorLoadingNewSate(model: deviceStatus));
|
||||
}
|
||||
},
|
||||
onError: (error) => log(error.toString(), name: 'FirebaseDatabaseError'),
|
||||
).asFuture();
|
||||
}
|
||||
|
||||
void _onFlushMountedPresenceSensorChangeValueEvent(
|
||||
FlushMountedPresenceSensorChangeValueEvent event,
|
||||
Emitter<FlushMountedPresenceSensorState> emit,
|
||||
) async {
|
||||
emit(FlushMountedPresenceSensorLoadingNewSate(model: deviceStatus));
|
||||
_updateDeviceFunctionFromCode(event.code, event.value);
|
||||
emit(FlushMountedPresenceSensorUpdateState(model: deviceStatus));
|
||||
try {
|
||||
await controlDeviceService.controlDevice(
|
||||
deviceUuid: deviceId,
|
||||
status: Status(code: event.code, value: event.value),
|
||||
);
|
||||
} catch (_) {
|
||||
await _reloadDeviceStatus();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onFlushMountedPresenceSensorBatchControlEvent(
|
||||
FlushMountedPresenceSensorBatchControlEvent event,
|
||||
Emitter<FlushMountedPresenceSensorState> emit,
|
||||
) async {
|
||||
emit(FlushMountedPresenceSensorLoadingNewSate(model: deviceStatus));
|
||||
_updateDeviceFunctionFromCode(event.code, event.value);
|
||||
emit(FlushMountedPresenceSensorUpdateState(model: deviceStatus));
|
||||
|
||||
try {
|
||||
await batchControlDevicesService.batchControlDevices(
|
||||
uuids: event.deviceIds,
|
||||
code: event.code,
|
||||
value: event.value,
|
||||
);
|
||||
} catch (_) {
|
||||
await _reloadDeviceStatus();
|
||||
}
|
||||
}
|
||||
|
||||
void _updateDeviceFunctionFromCode(String code, int value) {
|
||||
switch (code) {
|
||||
case FlushMountedPresenceSensorModel.codeFarDetection:
|
||||
deviceStatus.farDetection = value;
|
||||
break;
|
||||
case FlushMountedPresenceSensorModel.codeSensitivity:
|
||||
deviceStatus.sensitivity = value;
|
||||
break;
|
||||
case FlushMountedPresenceSensorModel.codeNoneDelay:
|
||||
deviceStatus.noneDelay = value;
|
||||
break;
|
||||
case FlushMountedPresenceSensorModel.codePresenceDelay:
|
||||
deviceStatus.presenceDelay = value;
|
||||
break;
|
||||
case FlushMountedPresenceSensorModel.codeNearDetection:
|
||||
deviceStatus.nearDetection = value;
|
||||
break;
|
||||
case FlushMountedPresenceSensorModel.codeOccurDistReduce:
|
||||
deviceStatus.occurDistReduce = value;
|
||||
break;
|
||||
case FlushMountedPresenceSensorModel.codeSensiReduce:
|
||||
deviceStatus.sensiReduce = value;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _reloadDeviceStatus() async {
|
||||
await Future.delayed(const Duration(milliseconds: 500), () {
|
||||
add(FlushMountedPresenceSensorFetchStatusEvent());
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _onFlushMountedPresenceSensorGetDeviceReportsEvent(
|
||||
FlushMountedPresenceSensorGetDeviceReportsEvent event,
|
||||
Emitter<FlushMountedPresenceSensorState> emit,
|
||||
) async {
|
||||
emit(FlushMountedPresenceSensorDeviceReportsLoadingState());
|
||||
|
||||
try {
|
||||
await DevicesManagementApi.getDeviceReports(deviceId, event.code)
|
||||
.then((value) {
|
||||
emit(FlushMountedPresenceSensorDeviceReportsState(
|
||||
deviceReport: value, code: event.code));
|
||||
});
|
||||
} catch (e) {
|
||||
emit(FlushMountedPresenceSensorDeviceReportsFailedState(error: e.toString()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void _onFlushMountedPresenceSensorShowDescriptionEvent(
|
||||
FlushMountedPresenceSensorShowDescriptionEvent event,
|
||||
Emitter<FlushMountedPresenceSensorState> emit,
|
||||
) {
|
||||
emit(FlushMountedPresenceSensorShowDescriptionState(
|
||||
description: event.description));
|
||||
}
|
||||
|
||||
void _onFlushMountedPresenceSensorBackToGridViewEvent(
|
||||
FlushMountedPresenceSensorBackToGridViewEvent event,
|
||||
Emitter<FlushMountedPresenceSensorState> emit,
|
||||
) {
|
||||
emit(FlushMountedPresenceSensorUpdateState(model: deviceStatus));
|
||||
}
|
||||
|
||||
Future<void> _onFlushMountedPresenceSensorFactoryResetEvent(
|
||||
FlushMountedPresenceSensorFactoryResetEvent event,
|
||||
Emitter<FlushMountedPresenceSensorState> emit,
|
||||
) async {
|
||||
emit(FlushMountedPresenceSensorLoadingNewSate(model: deviceStatus));
|
||||
try {
|
||||
final response = await DevicesManagementApi().factoryReset(
|
||||
event.factoryReset,
|
||||
event.deviceId,
|
||||
);
|
||||
if (!response) {
|
||||
emit(
|
||||
const FlushMountedPresenceSensorFailedState(
|
||||
error: 'Something went wrong with factory reset, please try again',
|
||||
),
|
||||
);
|
||||
} else {
|
||||
emit(FlushMountedPresenceSensorUpdateState(model: deviceStatus));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(FlushMountedPresenceSensorFailedState(error: e.toString()));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
part of 'flush_mounted_presence_sensor_bloc.dart';
|
||||
|
||||
sealed class FlushMountedPresenceSensorEvent extends Equatable {
|
||||
const FlushMountedPresenceSensorEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class FlushMountedPresenceSensorFetchStatusEvent
|
||||
extends FlushMountedPresenceSensorEvent {}
|
||||
|
||||
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
|
||||
List<Object> get props => [value, code];
|
||||
}
|
||||
|
||||
class FlushMountedPresenceSensorFetchBatchStatusEvent
|
||||
extends FlushMountedPresenceSensorEvent {
|
||||
final List<String> devicesIds;
|
||||
const FlushMountedPresenceSensorFetchBatchStatusEvent(this.devicesIds);
|
||||
|
||||
@override
|
||||
List<Object> get props => [devicesIds];
|
||||
}
|
||||
|
||||
class FlushMountedPresenceSensorGetDeviceReportsEvent
|
||||
extends FlushMountedPresenceSensorEvent {
|
||||
final String deviceUuid;
|
||||
final String code;
|
||||
const FlushMountedPresenceSensorGetDeviceReportsEvent({
|
||||
required this.deviceUuid,
|
||||
required this.code,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [deviceUuid, code];
|
||||
}
|
||||
|
||||
class FlushMountedPresenceSensorShowDescriptionEvent
|
||||
extends FlushMountedPresenceSensorEvent {
|
||||
final String description;
|
||||
const FlushMountedPresenceSensorShowDescriptionEvent({required this.description});
|
||||
}
|
||||
|
||||
class FlushMountedPresenceSensorBackToGridViewEvent
|
||||
extends FlushMountedPresenceSensorEvent {}
|
||||
|
||||
class FlushMountedPresenceSensorBatchControlEvent
|
||||
extends FlushMountedPresenceSensorEvent {
|
||||
final List<String> deviceIds;
|
||||
final String code;
|
||||
final dynamic value;
|
||||
|
||||
const FlushMountedPresenceSensorBatchControlEvent({
|
||||
required this.deviceIds,
|
||||
required this.code,
|
||||
required this.value,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [deviceIds, code, value];
|
||||
}
|
||||
|
||||
class FlushMountedPresenceSensorFactoryResetEvent
|
||||
extends FlushMountedPresenceSensorEvent {
|
||||
final String deviceId;
|
||||
final FactoryResetModel factoryReset;
|
||||
|
||||
const FlushMountedPresenceSensorFactoryResetEvent({
|
||||
required this.deviceId,
|
||||
required this.factoryReset,
|
||||
});
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
part of 'flush_mounted_presence_sensor_bloc.dart';
|
||||
|
||||
sealed class FlushMountedPresenceSensorState extends Equatable {
|
||||
const FlushMountedPresenceSensorState();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class FlushMountedPresenceSensorInitialState
|
||||
extends FlushMountedPresenceSensorState {}
|
||||
|
||||
class FlushMountedPresenceSensorLoadingInitialState
|
||||
extends FlushMountedPresenceSensorState {}
|
||||
|
||||
class FlushMountedPresenceSensorUpdateState extends FlushMountedPresenceSensorState {
|
||||
final FlushMountedPresenceSensorModel model;
|
||||
const FlushMountedPresenceSensorUpdateState({required this.model});
|
||||
|
||||
@override
|
||||
List<Object> get props => [model];
|
||||
}
|
||||
|
||||
class FlushMountedPresenceSensorLoadingNewSate
|
||||
extends FlushMountedPresenceSensorState {
|
||||
final FlushMountedPresenceSensorModel model;
|
||||
const FlushMountedPresenceSensorLoadingNewSate({required this.model});
|
||||
|
||||
@override
|
||||
List<Object> get props => [model];
|
||||
}
|
||||
|
||||
class FlushMountedPresenceSensorFailedState extends FlushMountedPresenceSensorState {
|
||||
final String error;
|
||||
|
||||
const FlushMountedPresenceSensorFailedState({required this.error});
|
||||
|
||||
@override
|
||||
List<Object> get props => [error];
|
||||
}
|
||||
|
||||
class FlushMountedPresenceSensorDeviceReportsLoadingState
|
||||
extends FlushMountedPresenceSensorState {}
|
||||
|
||||
class FlushMountedPresenceSensorDeviceReportsState
|
||||
extends FlushMountedPresenceSensorState {
|
||||
const FlushMountedPresenceSensorDeviceReportsState({
|
||||
required this.deviceReport,
|
||||
required this.code,
|
||||
});
|
||||
|
||||
final DeviceReport deviceReport;
|
||||
final String code;
|
||||
|
||||
@override
|
||||
List<Object> get props => [deviceReport, code];
|
||||
}
|
||||
|
||||
class FlushMountedPresenceSensorDeviceReportsFailedState
|
||||
extends FlushMountedPresenceSensorState {
|
||||
const FlushMountedPresenceSensorDeviceReportsFailedState({required this.error});
|
||||
|
||||
final String error;
|
||||
|
||||
@override
|
||||
List<Object> get props => [error];
|
||||
}
|
||||
|
||||
class FlushMountedPresenceSensorShowDescriptionState
|
||||
extends FlushMountedPresenceSensorState {
|
||||
const FlushMountedPresenceSensorShowDescriptionState({required this.description});
|
||||
|
||||
final String description;
|
||||
@override
|
||||
List<Object> get props => [description];
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
import 'package:syncrow_web/pages/device_managment/flush_mounted_presence_sensor/bloc/flush_mounted_presence_sensor_bloc.dart';
|
||||
import 'package:syncrow_web/services/batch_control_devices_service.dart';
|
||||
import 'package:syncrow_web/services/control_device_service.dart';
|
||||
|
||||
abstract final class FlushMountedPresenceSensorBlocFactory {
|
||||
const FlushMountedPresenceSensorBlocFactory._();
|
||||
|
||||
static FlushMountedPresenceSensorBloc create({
|
||||
required String deviceId,
|
||||
}) {
|
||||
return FlushMountedPresenceSensorBloc(
|
||||
deviceId: deviceId,
|
||||
controlDeviceService: DebouncedControlDeviceService(
|
||||
decoratee: RemoteControlDeviceService(),
|
||||
),
|
||||
batchControlDevicesService: DebouncedBatchControlDevicesService(
|
||||
decoratee: RemoteBatchControlDevicesService(),
|
||||
),
|
||||
)..add(FlushMountedPresenceSensorFetchStatusEvent());
|
||||
}
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
|
||||
|
||||
class FlushMountedPresenceSensorModel {
|
||||
FlushMountedPresenceSensorModel({
|
||||
required this.presenceState,
|
||||
required this.farDetection,
|
||||
required this.illuminance,
|
||||
required this.sensitivity,
|
||||
required this.occurDistReduce,
|
||||
required this.noneDelay,
|
||||
required this.presenceDelay,
|
||||
required this.nearDetection,
|
||||
required this.sensiReduce,
|
||||
required this.checkingResult,
|
||||
});
|
||||
|
||||
static const String codePresenceState = 'presence_state';
|
||||
static const String codeSensitivity = 'sensitivity';
|
||||
static const String codeNearDetection = 'near_detection';
|
||||
static const String codeFarDetection = 'far_detection';
|
||||
static const String codeCheckingResult = 'checking_result';
|
||||
static const String codePresenceDelay = 'presence_delay';
|
||||
static const String codeNoneDelay = 'none_delay';
|
||||
static const String codeOccurDistReduce = 'occur_dist_reduce';
|
||||
static const String codeIlluminance = 'illum_value';
|
||||
static const String codeSensiReduce = 'sensi_reduce';
|
||||
|
||||
String presenceState;
|
||||
int sensitivity;
|
||||
int nearDetection;
|
||||
int farDetection;
|
||||
String checkingResult;
|
||||
int presenceDelay;
|
||||
int noneDelay;
|
||||
int occurDistReduce;
|
||||
int illuminance;
|
||||
int sensiReduce;
|
||||
|
||||
factory FlushMountedPresenceSensorModel.fromJson(List<Status> jsonList) {
|
||||
String presenceState = 'none';
|
||||
int sensitivity = 0;
|
||||
int nearDetection = 0;
|
||||
int farDetection = 0;
|
||||
String checkingResult = 'none';
|
||||
int presenceDelay = 0;
|
||||
int noneDelay = 0;
|
||||
int occurDistReduce = 0;
|
||||
int illuminance = 0;
|
||||
int sensiReduce = 0;
|
||||
|
||||
for (var status in jsonList) {
|
||||
switch (status.code) {
|
||||
case codePresenceState:
|
||||
presenceState = status.value ?? 'presence';
|
||||
break;
|
||||
case codeSensitivity:
|
||||
sensitivity = status.value ?? 0;
|
||||
break;
|
||||
case codeNearDetection:
|
||||
nearDetection = status.value ?? 0;
|
||||
break;
|
||||
case codeFarDetection:
|
||||
farDetection = status.value ?? 0;
|
||||
break;
|
||||
case codeCheckingResult:
|
||||
checkingResult = status.value ?? 'check_success';
|
||||
break;
|
||||
case codePresenceDelay:
|
||||
presenceDelay = status.value ?? 0;
|
||||
break;
|
||||
case codeNoneDelay:
|
||||
noneDelay = status.value ?? 0;
|
||||
break;
|
||||
case codeOccurDistReduce:
|
||||
occurDistReduce = status.value ?? 0;
|
||||
break;
|
||||
case codeIlluminance:
|
||||
illuminance = status.value ?? 0;
|
||||
break;
|
||||
case codeSensiReduce:
|
||||
sensiReduce = status.value ?? 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return FlushMountedPresenceSensorModel(
|
||||
presenceState: presenceState,
|
||||
sensitivity: sensitivity,
|
||||
nearDetection: nearDetection,
|
||||
farDetection: farDetection,
|
||||
checkingResult: checkingResult,
|
||||
presenceDelay: presenceDelay,
|
||||
noneDelay: noneDelay,
|
||||
occurDistReduce: occurDistReduce,
|
||||
illuminance: illuminance,
|
||||
sensiReduce: sensiReduce,
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,176 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/flush_mounted_presence_sensor/bloc/flush_mounted_presence_sensor_bloc.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/flush_mounted_presence_sensor/factories/flush_mounted_presence_sensor_bloc_factory.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/flush_mounted_presence_sensor/models/flush_mounted_presence_sensor_model.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_update_data.dart';
|
||||
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
||||
|
||||
class FlushMountedPresenceSensorBatchControlView extends StatelessWidget
|
||||
with HelperResponsiveLayout {
|
||||
const FlushMountedPresenceSensorBatchControlView({
|
||||
required this.devicesIds,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final List<String> devicesIds;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => FlushMountedPresenceSensorBlocFactory.create(
|
||||
deviceId: devicesIds.first,
|
||||
),
|
||||
child: BlocBuilder<FlushMountedPresenceSensorBloc,
|
||||
FlushMountedPresenceSensorState>(
|
||||
builder: (context, state) {
|
||||
if (state is FlushMountedPresenceSensorLoadingInitialState ||
|
||||
state is FlushMountedPresenceSensorDeviceReportsLoadingState) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
} else if (state is FlushMountedPresenceSensorUpdateState) {
|
||||
return _buildGridView(context, state.model);
|
||||
}
|
||||
return const Center(child: Text('Error fetching status'));
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildGridView(
|
||||
BuildContext context,
|
||||
FlushMountedPresenceSensorModel model,
|
||||
) {
|
||||
final isExtraLarge = isExtraLargeScreenSize(context);
|
||||
final isLarge = isLargeScreenSize(context);
|
||||
final isMedium = isMediumScreenSize(context);
|
||||
return GridView(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 50),
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: isLarge || isExtraLarge
|
||||
? 3
|
||||
: isMedium
|
||||
? 2
|
||||
: 1,
|
||||
mainAxisExtent: 140,
|
||||
crossAxisSpacing: 12,
|
||||
mainAxisSpacing: 12,
|
||||
),
|
||||
children: [
|
||||
PresenceUpdateData(
|
||||
value: model.sensitivity.toDouble(),
|
||||
title: 'Sensitivity:',
|
||||
minValue: 0,
|
||||
maxValue: 9,
|
||||
steps: 1,
|
||||
action: (int value) => context.read<FlushMountedPresenceSensorBloc>().add(
|
||||
FlushMountedPresenceSensorChangeValueEvent(
|
||||
code: FlushMountedPresenceSensorModel.codeSensitivity,
|
||||
value: value,
|
||||
),
|
||||
),
|
||||
),
|
||||
PresenceUpdateData(
|
||||
value: (model.nearDetection / 100).toDouble(),
|
||||
title: 'Nearest Detect Dist:',
|
||||
description: 'm',
|
||||
minValue: 0.0,
|
||||
maxValue: 9.5,
|
||||
steps: 0.1,
|
||||
valuesPercision: 1,
|
||||
action: (double value) =>
|
||||
context.read<FlushMountedPresenceSensorBloc>().add(
|
||||
FlushMountedPresenceSensorChangeValueEvent(
|
||||
code: FlushMountedPresenceSensorModel.codeNearDetection,
|
||||
value: (value * 100).toInt(),
|
||||
),
|
||||
),
|
||||
),
|
||||
PresenceUpdateData(
|
||||
value: (model.farDetection / 100).toDouble(),
|
||||
title: 'Max Detect Dist:',
|
||||
description: 'm',
|
||||
minValue: 0.0,
|
||||
maxValue: 9.5,
|
||||
steps: 0.1,
|
||||
valuesPercision: 1,
|
||||
action: (double value) =>
|
||||
context.read<FlushMountedPresenceSensorBloc>().add(
|
||||
FlushMountedPresenceSensorChangeValueEvent(
|
||||
code: FlushMountedPresenceSensorModel.codeFarDetection,
|
||||
value: (value * 100).toInt(),
|
||||
),
|
||||
),
|
||||
),
|
||||
PresenceUpdateData(
|
||||
value: model.presenceDelay.toDouble(),
|
||||
title: 'Trigger Level:',
|
||||
minValue: 0,
|
||||
maxValue: 3,
|
||||
steps: 1,
|
||||
action: (int value) => context.read<FlushMountedPresenceSensorBloc>().add(
|
||||
FlushMountedPresenceSensorChangeValueEvent(
|
||||
code: FlushMountedPresenceSensorModel.codePresenceDelay,
|
||||
value: value,
|
||||
),
|
||||
),
|
||||
),
|
||||
PresenceUpdateData(
|
||||
value: (model.occurDistReduce.toDouble()),
|
||||
title: 'Indent Level:',
|
||||
minValue: 0,
|
||||
maxValue: 3,
|
||||
steps: 1,
|
||||
action: (int value) => context.read<FlushMountedPresenceSensorBloc>().add(
|
||||
FlushMountedPresenceSensorChangeValueEvent(
|
||||
code: FlushMountedPresenceSensorModel.codeOccurDistReduce,
|
||||
value: value,
|
||||
),
|
||||
),
|
||||
),
|
||||
PresenceUpdateData(
|
||||
value: (model.sensiReduce.toDouble()),
|
||||
title: 'Target Confirm Time:',
|
||||
description: 's',
|
||||
minValue: 0,
|
||||
maxValue: 3,
|
||||
steps: 1,
|
||||
action: (int value) => context.read<FlushMountedPresenceSensorBloc>().add(
|
||||
FlushMountedPresenceSensorChangeValueEvent(
|
||||
code: FlushMountedPresenceSensorModel.codeSensiReduce,
|
||||
value: value,
|
||||
),
|
||||
),
|
||||
),
|
||||
PresenceUpdateData(
|
||||
value: ((model.noneDelay / 10).toDouble()),
|
||||
description: 's',
|
||||
title: 'Disappe Delay:',
|
||||
minValue: 20,
|
||||
maxValue: 300,
|
||||
steps: 1,
|
||||
action: (double value) =>
|
||||
context.read<FlushMountedPresenceSensorBloc>().add(
|
||||
FlushMountedPresenceSensorChangeValueEvent(
|
||||
code: FlushMountedPresenceSensorModel.codeNoneDelay,
|
||||
value: (value * 10).round(),
|
||||
),
|
||||
),
|
||||
),
|
||||
FactoryResetWidget(
|
||||
callFactoryReset: () {
|
||||
context.read<FlushMountedPresenceSensorBloc>().add(
|
||||
FlushMountedPresenceSensorFactoryResetEvent(
|
||||
deviceId: devicesIds.first,
|
||||
factoryReset: FactoryResetModel(devicesUuid: devicesIds),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,217 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/flush_mounted_presence_sensor/bloc/flush_mounted_presence_sensor_bloc.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/flush_mounted_presence_sensor/factories/flush_mounted_presence_sensor_bloc_factory.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/flush_mounted_presence_sensor/models/flush_mounted_presence_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_static_widget.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_status.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_update_data.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/shared/table/description_view.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/shared/table/report_table.dart';
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
||||
|
||||
class FlushMountedPresenceSensorControlView extends StatelessWidget
|
||||
with HelperResponsiveLayout {
|
||||
const FlushMountedPresenceSensorControlView({super.key, required this.device});
|
||||
|
||||
final AllDevicesModel device;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => FlushMountedPresenceSensorBlocFactory.create(
|
||||
deviceId: device.uuid ?? '-1',
|
||||
),
|
||||
child: BlocBuilder<FlushMountedPresenceSensorBloc,
|
||||
FlushMountedPresenceSensorState>(
|
||||
builder: (context, state) {
|
||||
if (state is FlushMountedPresenceSensorLoadingInitialState ||
|
||||
state is FlushMountedPresenceSensorDeviceReportsLoadingState) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
} else if (state is FlushMountedPresenceSensorUpdateState) {
|
||||
return _buildGridView(context, state.model);
|
||||
} else if (state is FlushMountedPresenceSensorDeviceReportsState) {
|
||||
return ReportsTable(
|
||||
report: state.deviceReport,
|
||||
thirdColumnTitle:
|
||||
state.code == 'illuminance_value' ? "Value" : 'Status',
|
||||
thirdColumnDescription:
|
||||
state.code == 'illuminance_value' ? "Lux" : null,
|
||||
onRowTap: (index) {},
|
||||
onClose: () {
|
||||
context
|
||||
.read<FlushMountedPresenceSensorBloc>()
|
||||
.add(FlushMountedPresenceSensorBackToGridViewEvent());
|
||||
},
|
||||
);
|
||||
} else if (state is FlushMountedPresenceSensorShowDescriptionState) {
|
||||
return DescriptionView(
|
||||
description: state.description,
|
||||
onClose: () {
|
||||
context
|
||||
.read<FlushMountedPresenceSensorBloc>()
|
||||
.add(FlushMountedPresenceSensorBackToGridViewEvent());
|
||||
},
|
||||
);
|
||||
} else if (state is FlushMountedPresenceSensorDeviceReportsFailedState) {
|
||||
final model =
|
||||
context.read<FlushMountedPresenceSensorBloc>().deviceStatus;
|
||||
return _buildGridView(context, model);
|
||||
}
|
||||
return const Center(
|
||||
child: Text('Error fetching status', textAlign: TextAlign.center),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildGridView(
|
||||
BuildContext context,
|
||||
FlushMountedPresenceSensorModel model,
|
||||
) {
|
||||
final isExtraLarge = isExtraLargeScreenSize(context);
|
||||
final isLarge = isLargeScreenSize(context);
|
||||
final isMedium = isMediumScreenSize(context);
|
||||
return GridView(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 50),
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: isLarge || isExtraLarge
|
||||
? 3
|
||||
: isMedium
|
||||
? 2
|
||||
: 1,
|
||||
mainAxisExtent: 140,
|
||||
crossAxisSpacing: 12,
|
||||
mainAxisSpacing: 12,
|
||||
),
|
||||
children: [
|
||||
PresenceState(
|
||||
value: model.presenceState,
|
||||
),
|
||||
PresenceDisplayValue(
|
||||
value: model.illuminance.toString(),
|
||||
postfix: 'Lux',
|
||||
description: 'Illuminance Value',
|
||||
),
|
||||
PresenceUpdateData(
|
||||
value: model.sensitivity.toDouble(),
|
||||
title: 'Sensitivity:',
|
||||
minValue: 0,
|
||||
maxValue: 9,
|
||||
steps: 1,
|
||||
action: (int value) => context.read<FlushMountedPresenceSensorBloc>().add(
|
||||
FlushMountedPresenceSensorChangeValueEvent(
|
||||
code: FlushMountedPresenceSensorModel.codeSensitivity,
|
||||
value: value,
|
||||
),
|
||||
),
|
||||
),
|
||||
PresenceUpdateData(
|
||||
value: (model.nearDetection / 100).toDouble(),
|
||||
title: 'Nearest Detect Dist:',
|
||||
description: 'm',
|
||||
minValue: 0.0,
|
||||
maxValue: 9.5,
|
||||
steps: 0.1,
|
||||
valuesPercision: 1,
|
||||
action: (double value) =>
|
||||
context.read<FlushMountedPresenceSensorBloc>().add(
|
||||
FlushMountedPresenceSensorChangeValueEvent(
|
||||
code: FlushMountedPresenceSensorModel.codeNearDetection,
|
||||
value: (value * 100).toInt(),
|
||||
),
|
||||
),
|
||||
),
|
||||
PresenceUpdateData(
|
||||
value: (model.farDetection / 100).toDouble(),
|
||||
title: 'Max Detect Dist:',
|
||||
description: 'm',
|
||||
minValue: 0.0,
|
||||
maxValue: 9.5,
|
||||
steps: 0.1,
|
||||
valuesPercision: 1,
|
||||
action: (double value) =>
|
||||
context.read<FlushMountedPresenceSensorBloc>().add(
|
||||
FlushMountedPresenceSensorChangeValueEvent(
|
||||
code: FlushMountedPresenceSensorModel.codeFarDetection,
|
||||
value: (value * 100).toInt(),
|
||||
),
|
||||
),
|
||||
),
|
||||
PresenceUpdateData(
|
||||
value: (model.presenceDelay.toDouble()),
|
||||
title: 'Trigger Level:',
|
||||
minValue: 0,
|
||||
maxValue: 3,
|
||||
steps: 1,
|
||||
action: (int value) => context.read<FlushMountedPresenceSensorBloc>().add(
|
||||
FlushMountedPresenceSensorChangeValueEvent(
|
||||
code: FlushMountedPresenceSensorModel.codePresenceDelay,
|
||||
value: value,
|
||||
),
|
||||
),
|
||||
),
|
||||
PresenceUpdateData(
|
||||
value: (model.occurDistReduce.toDouble()),
|
||||
title: 'Indent Level:',
|
||||
minValue: 0,
|
||||
maxValue: 3,
|
||||
steps: 1,
|
||||
action: (int value) => context.read<FlushMountedPresenceSensorBloc>().add(
|
||||
FlushMountedPresenceSensorChangeValueEvent(
|
||||
code: FlushMountedPresenceSensorModel.codeOccurDistReduce,
|
||||
value: value,
|
||||
),
|
||||
),
|
||||
),
|
||||
PresenceUpdateData(
|
||||
value: (model.sensiReduce.toDouble()),
|
||||
title: 'Target Confirm Time:',
|
||||
description: 's',
|
||||
minValue: 0,
|
||||
maxValue: 3,
|
||||
steps: 1,
|
||||
action: (int value) => context.read<FlushMountedPresenceSensorBloc>().add(
|
||||
FlushMountedPresenceSensorChangeValueEvent(
|
||||
code: FlushMountedPresenceSensorModel.codeSensiReduce,
|
||||
value: value,
|
||||
),
|
||||
),
|
||||
),
|
||||
PresenceUpdateData(
|
||||
value: ((model.noneDelay / 10).toDouble()),
|
||||
description: 's',
|
||||
title: 'Disappe Delay:',
|
||||
minValue: 20,
|
||||
maxValue: 300,
|
||||
steps: 1,
|
||||
action: (double value) =>
|
||||
context.read<FlushMountedPresenceSensorBloc>().add(
|
||||
FlushMountedPresenceSensorChangeValueEvent(
|
||||
code: FlushMountedPresenceSensorModel.codeNoneDelay,
|
||||
value: (value * 10).round(),
|
||||
),
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () => context.read<FlushMountedPresenceSensorBloc>().add(
|
||||
FlushMountedPresenceSensorGetDeviceReportsEvent(
|
||||
code: 'presence_state',
|
||||
deviceUuid: device.uuid!,
|
||||
),
|
||||
),
|
||||
child: const PresenceStaticWidget(
|
||||
icon: Assets.presenceRecordIcon,
|
||||
description: 'Presence Record',
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/shared/device_controls_container.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/shared/increament_decreament.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||
|
||||
class PresenceUpdateData extends StatefulWidget {
|
||||
const PresenceUpdateData({
|
||||
@ -13,6 +14,7 @@ class PresenceUpdateData extends StatefulWidget {
|
||||
required this.maxValue,
|
||||
required this.steps,
|
||||
this.description,
|
||||
this.valuesPercision = 0,
|
||||
});
|
||||
|
||||
final String title;
|
||||
@ -22,6 +24,7 @@ class PresenceUpdateData extends StatefulWidget {
|
||||
final double steps;
|
||||
final Function action;
|
||||
final String? description;
|
||||
final int valuesPercision;
|
||||
|
||||
@override
|
||||
State<PresenceUpdateData> createState() => _CurrentTempState();
|
||||
@ -45,7 +48,7 @@ class _CurrentTempState extends State<PresenceUpdateData> {
|
||||
}
|
||||
|
||||
void _onValueChanged(double newValue) {
|
||||
widget.action(newValue.toInt());
|
||||
widget.action(newValue);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -62,11 +65,14 @@ class _CurrentTempState extends State<PresenceUpdateData> {
|
||||
children: [
|
||||
Text(
|
||||
widget.title,
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
color: ColorsManager.blackColor, fontWeight: FontWeight.w400, fontSize: 10),
|
||||
style: context.textTheme.bodySmall?.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 10,
|
||||
),
|
||||
),
|
||||
IncrementDecrementWidget(
|
||||
value: widget.value.toString(),
|
||||
value: widget.value.toStringAsFixed(widget.valuesPercision),
|
||||
description: widget.description ?? '',
|
||||
descriptionColor: ColorsManager.blackColor,
|
||||
onIncrement: () {
|
||||
|
85
lib/services/batch_control_devices_service.dart
Normal file
85
lib/services/batch_control_devices_service.dart
Normal file
@ -0,0 +1,85 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:syncrow_web/services/api/http_service.dart';
|
||||
import 'package:syncrow_web/utils/constants/api_const.dart';
|
||||
|
||||
abstract interface class BatchControlDevicesService {
|
||||
Future<bool> batchControlDevices({
|
||||
required List<String> uuids,
|
||||
required String code,
|
||||
required Object value,
|
||||
});
|
||||
}
|
||||
|
||||
final class RemoteBatchControlDevicesService implements BatchControlDevicesService {
|
||||
@override
|
||||
Future<bool> batchControlDevices({
|
||||
required List<String> uuids,
|
||||
required String code,
|
||||
required Object value,
|
||||
}) async {
|
||||
try {
|
||||
final body = {
|
||||
'devicesUuid': uuids,
|
||||
'code': code,
|
||||
'value': value,
|
||||
'operationType': 'COMMAND',
|
||||
};
|
||||
|
||||
final response = await HTTPService().post(
|
||||
path: ApiEndpoints.deviceBatchControl,
|
||||
body: body,
|
||||
showServerMessage: true,
|
||||
expectedResponseModel: (json) => (json['success'] as bool?) ?? false,
|
||||
);
|
||||
|
||||
return response;
|
||||
} catch (e) {
|
||||
log('Error fetching $e', name: 'BatchControlDevicesService');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class DebouncedBatchControlDevicesService
|
||||
implements BatchControlDevicesService {
|
||||
final BatchControlDevicesService decoratee;
|
||||
final Duration debounceDuration;
|
||||
|
||||
final _pendingRequests = <(List<String> uuids, String code, Object value)>[];
|
||||
var _isProcessing = false;
|
||||
|
||||
DebouncedBatchControlDevicesService({
|
||||
required this.decoratee,
|
||||
this.debounceDuration = const Duration(milliseconds: 1500),
|
||||
});
|
||||
|
||||
@override
|
||||
Future<bool> batchControlDevices({
|
||||
required List<String> uuids,
|
||||
required String code,
|
||||
required Object value,
|
||||
}) async {
|
||||
_pendingRequests.add((uuids, code, value));
|
||||
|
||||
if (_isProcessing) return false;
|
||||
|
||||
_isProcessing = true;
|
||||
|
||||
await Future.delayed(debounceDuration);
|
||||
|
||||
final lastRequest = _pendingRequests.last;
|
||||
_pendingRequests.clear();
|
||||
|
||||
try {
|
||||
final (lastRequestUuids, lastRequestCode, lastRequestValue) = lastRequest;
|
||||
return decoratee.batchControlDevices(
|
||||
uuids: lastRequestUuids,
|
||||
code: lastRequestCode,
|
||||
value: lastRequestValue,
|
||||
);
|
||||
} finally {
|
||||
_isProcessing = false;
|
||||
}
|
||||
}
|
||||
}
|
75
lib/services/control_device_service.dart
Normal file
75
lib/services/control_device_service.dart
Normal file
@ -0,0 +1,75 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
|
||||
import 'package:syncrow_web/services/api/http_service.dart';
|
||||
import 'package:syncrow_web/utils/constants/api_const.dart';
|
||||
|
||||
abstract interface class ControlDeviceService {
|
||||
Future<bool> controlDevice({
|
||||
required String deviceUuid,
|
||||
required Status status,
|
||||
});
|
||||
}
|
||||
|
||||
final class RemoteControlDeviceService implements ControlDeviceService {
|
||||
@override
|
||||
Future<bool> controlDevice({
|
||||
required String deviceUuid,
|
||||
required Status status,
|
||||
}) async {
|
||||
try {
|
||||
final response = await HTTPService().post(
|
||||
path: ApiEndpoints.deviceControl.replaceAll('{uuid}', deviceUuid),
|
||||
body: status.toMap(),
|
||||
showServerMessage: true,
|
||||
expectedResponseModel: (json) {
|
||||
return (json['success'] as bool?) ?? false;
|
||||
},
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
log('Error fetching $e', name: 'ControlDeviceService');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class DebouncedControlDeviceService implements ControlDeviceService {
|
||||
final ControlDeviceService decoratee;
|
||||
final Duration debounceDuration;
|
||||
|
||||
DebouncedControlDeviceService({
|
||||
required this.decoratee,
|
||||
this.debounceDuration = const Duration(milliseconds: 1500),
|
||||
});
|
||||
|
||||
final _pendingRequests = <(String deviceUuid, Status status)>[];
|
||||
var _isProcessing = false;
|
||||
|
||||
@override
|
||||
Future<bool> controlDevice({
|
||||
required String deviceUuid,
|
||||
required Status status,
|
||||
}) async {
|
||||
_pendingRequests.add((deviceUuid, status));
|
||||
|
||||
if (_isProcessing) return false;
|
||||
|
||||
_isProcessing = true;
|
||||
|
||||
await Future.delayed(debounceDuration);
|
||||
|
||||
final lastRequest = _pendingRequests.last;
|
||||
_pendingRequests.clear();
|
||||
|
||||
try {
|
||||
final (lastRequestDeviceUuid, lastRequestStatus) = lastRequest;
|
||||
return decoratee.controlDevice(
|
||||
deviceUuid: lastRequestDeviceUuid,
|
||||
status: lastRequestStatus,
|
||||
);
|
||||
} finally {
|
||||
_isProcessing = false;
|
||||
}
|
||||
}
|
||||
}
|
@ -60,6 +60,7 @@ dependencies:
|
||||
firebase_core: ^3.11.0
|
||||
firebase_crashlytics: ^4.3.2
|
||||
firebase_database: ^11.3.2
|
||||
bloc: ^8.1.4
|
||||
|
||||
|
||||
dev_dependencies:
|
||||
|
Reference in New Issue
Block a user