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/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_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/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_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/garage_door/view/garage_door_control_view.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/gateway/view/gateway_batch_control.dart';
|
import 'package:syncrow_web/pages/device_managment/gateway/view/gateway_batch_control.dart';
|
||||||
@ -104,6 +105,9 @@ mixin RouteControlsBasedCode {
|
|||||||
);
|
);
|
||||||
case 'SOS':
|
case 'SOS':
|
||||||
return SosDeviceControlsView(device: device);
|
return SosDeviceControlsView(device: device);
|
||||||
|
|
||||||
|
case 'NCPS':
|
||||||
|
return FlushMountedPresenceSensorControlView(device: device);
|
||||||
default:
|
default:
|
||||||
return const SizedBox();
|
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/device_controls_container.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/increament_decreament.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/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||||
|
|
||||||
class PresenceUpdateData extends StatefulWidget {
|
class PresenceUpdateData extends StatefulWidget {
|
||||||
const PresenceUpdateData({
|
const PresenceUpdateData({
|
||||||
@ -13,6 +14,7 @@ class PresenceUpdateData extends StatefulWidget {
|
|||||||
required this.maxValue,
|
required this.maxValue,
|
||||||
required this.steps,
|
required this.steps,
|
||||||
this.description,
|
this.description,
|
||||||
|
this.valuesPercision = 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String title;
|
final String title;
|
||||||
@ -22,6 +24,7 @@ class PresenceUpdateData extends StatefulWidget {
|
|||||||
final double steps;
|
final double steps;
|
||||||
final Function action;
|
final Function action;
|
||||||
final String? description;
|
final String? description;
|
||||||
|
final int valuesPercision;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<PresenceUpdateData> createState() => _CurrentTempState();
|
State<PresenceUpdateData> createState() => _CurrentTempState();
|
||||||
@ -45,7 +48,7 @@ class _CurrentTempState extends State<PresenceUpdateData> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _onValueChanged(double newValue) {
|
void _onValueChanged(double newValue) {
|
||||||
widget.action(newValue.toInt());
|
widget.action(newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -62,11 +65,14 @@ class _CurrentTempState extends State<PresenceUpdateData> {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
widget.title,
|
widget.title,
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
style: context.textTheme.bodySmall?.copyWith(
|
||||||
color: ColorsManager.blackColor, fontWeight: FontWeight.w400, fontSize: 10),
|
color: ColorsManager.blackColor,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
fontSize: 10,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
IncrementDecrementWidget(
|
IncrementDecrementWidget(
|
||||||
value: widget.value.toString(),
|
value: widget.value.toStringAsFixed(widget.valuesPercision),
|
||||||
description: widget.description ?? '',
|
description: widget.description ?? '',
|
||||||
descriptionColor: ColorsManager.blackColor,
|
descriptionColor: ColorsManager.blackColor,
|
||||||
onIncrement: () {
|
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_core: ^3.11.0
|
||||||
firebase_crashlytics: ^4.3.2
|
firebase_crashlytics: ^4.3.2
|
||||||
firebase_database: ^11.3.2
|
firebase_database: ^11.3.2
|
||||||
|
bloc: ^8.1.4
|
||||||
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
Reference in New Issue
Block a user