mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 07:07:19 +00:00
implemented ceiling and wall sensors, and bug fixes
This commit is contained in:
@ -3,9 +3,9 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_state.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/ac/control_list/ac_mode.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/ac/control_list/ac_toggle.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/ac/control_list/current_temp.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/ac/view/control_list/ac_mode.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/ac/view/control_list/ac_toggle.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/ac/view/control_list/current_temp.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/ac/model/ac_model.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
||||
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
||||
@ -35,8 +35,7 @@ class AcDeviceControl extends StatelessWidget with HelperResponsiveLayout {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildStatusControls(
|
||||
AcStatusModel statuses, bool isLarge, bool isMedium) {
|
||||
Widget _buildStatusControls(AcStatusModel statuses, bool isLarge, bool isMedium) {
|
||||
return GridView(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 50),
|
||||
shrinkWrap: true,
|
||||
|
@ -2,6 +2,7 @@ import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/ac/view/ac_device_control.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/view/ceiling_sensor_controls.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/living_room_switch/view/living_room_device_control.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/wall_sensor/view/wall_sensor_conrtols.dart';
|
||||
|
||||
@ -19,7 +20,9 @@ mixin RouteControlsBasedCode {
|
||||
case 'WPS':
|
||||
return WallSensorControls(device: device);
|
||||
case 'CPS':
|
||||
return const SizedBox();
|
||||
return CeilingSensorControls(
|
||||
device: device,
|
||||
);
|
||||
case 'AC':
|
||||
return AcDeviceControl(device: device);
|
||||
default:
|
||||
|
87
lib/pages/device_managment/ceiling_sensor/bloc/bloc.dart
Normal file
87
lib/pages/device_managment/ceiling_sensor/bloc/bloc.dart
Normal file
@ -0,0 +1,87 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/event.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/state.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/model/ceiling_sensor_model.dart';
|
||||
import 'package:syncrow_web/services/devices_mang_api.dart';
|
||||
|
||||
class CeilingSensorBloc extends Bloc<CeilingSensorEvent, CeilingSensorState> {
|
||||
final String deviceId;
|
||||
late CeilingSensorModel deviceStatus;
|
||||
Timer? _timer;
|
||||
|
||||
CeilingSensorBloc({required this.deviceId}) : super(CeilingInitialState()) {
|
||||
on<CeilingInitialEvent>(_fetchCeilingSensorStatus);
|
||||
on<CeilingChangeValueEvent>(_changeValue);
|
||||
}
|
||||
|
||||
void _fetchCeilingSensorStatus(
|
||||
CeilingInitialEvent event, Emitter<CeilingSensorState> emit) async {
|
||||
emit(CeilingLoadingInitialState());
|
||||
try {
|
||||
var response = await DevicesManagementApi().getDeviceStatus(deviceId);
|
||||
deviceStatus = CeilingSensorModel.fromJson(response.status);
|
||||
emit(CeilingUpdateState(ceilingSensorModel: deviceStatus));
|
||||
// _listenToChanges();
|
||||
} catch (e) {
|
||||
emit(CeilingFailedState(error: e.toString()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// _listenToChanges() {
|
||||
// try {
|
||||
// DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$deviceId');
|
||||
// Stream<DatabaseEvent> stream = ref.onValue;
|
||||
|
||||
// stream.listen((DatabaseEvent event) {
|
||||
// Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>;
|
||||
// List<StatusModel> statusList = [];
|
||||
|
||||
// usersMap['status'].forEach((element) {
|
||||
// statusList.add(StatusModel(code: element['code'], value: element['value']));
|
||||
// });
|
||||
|
||||
// deviceStatus = WallSensorModel.fromJson(statusList);
|
||||
// add(WallSensorUpdatedEvent());
|
||||
// });
|
||||
// } catch (_) {}
|
||||
// }
|
||||
|
||||
void _changeValue(CeilingChangeValueEvent event, Emitter<CeilingSensorState> emit) async {
|
||||
emit(CeilingLoadingNewSate(ceilingSensorModel: deviceStatus));
|
||||
if (event.code == 'sensitivity') {
|
||||
deviceStatus.sensitivity = event.value;
|
||||
} else if (event.code == 'none_body_time') {
|
||||
deviceStatus.noBodyTime = event.value;
|
||||
} else if (event.code == 'moving_max_dis') {
|
||||
deviceStatus.maxDistance = event.value;
|
||||
}
|
||||
emit(CeilingUpdateState(ceilingSensorModel: deviceStatus));
|
||||
await _runDeBouncer(deviceId: deviceId, code: event.code, value: event.value);
|
||||
}
|
||||
|
||||
_runDeBouncer({
|
||||
required String deviceId,
|
||||
required String code,
|
||||
required dynamic value,
|
||||
}) {
|
||||
if (_timer != null) {
|
||||
_timer!.cancel();
|
||||
}
|
||||
_timer = Timer(const Duration(seconds: 1), () async {
|
||||
try {
|
||||
final response =
|
||||
await DevicesManagementApi().deviceControl(deviceId, Status(code: code, value: value));
|
||||
|
||||
if (!response) {
|
||||
add(CeilingInitialEvent());
|
||||
}
|
||||
} catch (_) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(CeilingInitialEvent());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
19
lib/pages/device_managment/ceiling_sensor/bloc/event.dart
Normal file
19
lib/pages/device_managment/ceiling_sensor/bloc/event.dart
Normal file
@ -0,0 +1,19 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
abstract class CeilingSensorEvent extends Equatable {
|
||||
const CeilingSensorEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class CeilingInitialEvent extends CeilingSensorEvent {}
|
||||
|
||||
class CeilingChangeValueEvent extends CeilingSensorEvent {
|
||||
final int value;
|
||||
final String code;
|
||||
const CeilingChangeValueEvent({required this.value, required this.code});
|
||||
|
||||
@override
|
||||
List<Object> get props => [value, code];
|
||||
}
|
38
lib/pages/device_managment/ceiling_sensor/bloc/state.dart
Normal file
38
lib/pages/device_managment/ceiling_sensor/bloc/state.dart
Normal file
@ -0,0 +1,38 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/model/ceiling_sensor_model.dart';
|
||||
|
||||
class CeilingSensorState extends Equatable {
|
||||
const CeilingSensorState();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class CeilingInitialState extends CeilingSensorState {}
|
||||
|
||||
class CeilingLoadingInitialState extends CeilingSensorState {}
|
||||
|
||||
class CeilingUpdateState extends CeilingSensorState {
|
||||
final CeilingSensorModel ceilingSensorModel;
|
||||
const CeilingUpdateState({required this.ceilingSensorModel});
|
||||
|
||||
@override
|
||||
List<Object> get props => [ceilingSensorModel];
|
||||
}
|
||||
|
||||
class CeilingLoadingNewSate extends CeilingSensorState {
|
||||
final CeilingSensorModel ceilingSensorModel;
|
||||
const CeilingLoadingNewSate({required this.ceilingSensorModel});
|
||||
|
||||
@override
|
||||
List<Object> get props => [ceilingSensorModel];
|
||||
}
|
||||
|
||||
class CeilingFailedState extends CeilingSensorState {
|
||||
final String error;
|
||||
|
||||
const CeilingFailedState({required this.error});
|
||||
|
||||
@override
|
||||
List<Object> get props => [error];
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
|
||||
|
||||
class CeilingSensorModel {
|
||||
String presenceState;
|
||||
int sensitivity;
|
||||
String checkingResult;
|
||||
int presenceRange;
|
||||
int sportsPara;
|
||||
String bodyMovement;
|
||||
int noBodyTime;
|
||||
int maxDistance;
|
||||
|
||||
CeilingSensorModel(
|
||||
{required this.presenceState,
|
||||
required this.sensitivity,
|
||||
required this.checkingResult,
|
||||
required this.presenceRange,
|
||||
required this.sportsPara,
|
||||
required this.bodyMovement,
|
||||
required this.noBodyTime,
|
||||
required this.maxDistance});
|
||||
|
||||
factory CeilingSensorModel.fromJson(List<Status> jsonList) {
|
||||
late String _presenceState;
|
||||
late int _sensitivity;
|
||||
late String _checkingResult;
|
||||
int _presenceRange = 1;
|
||||
int _sportsPara = 1;
|
||||
String _bodyMovement = 'none';
|
||||
int _noBodyTime = 0;
|
||||
int _maxDis = 0;
|
||||
|
||||
for (int i = 0; i < jsonList.length; i++) {
|
||||
if (jsonList[i].code == 'presence_state') {
|
||||
_presenceState = jsonList[i].value ?? 'none';
|
||||
} else if (jsonList[i].code == 'sensitivity') {
|
||||
_sensitivity = jsonList[i].value ?? 1;
|
||||
} else if (jsonList[i].code == 'checking_result') {
|
||||
_checkingResult = jsonList[i].value ?? '';
|
||||
} else if (jsonList[i].code == 'presence_range') {
|
||||
_presenceRange = jsonList[i].value ?? 0;
|
||||
} else if (jsonList[i].code == 'sports_para') {
|
||||
_sportsPara = jsonList[i].value ?? 0;
|
||||
} else if (jsonList[i].code == 'body_movement') {
|
||||
_bodyMovement = jsonList[i].value ?? '';
|
||||
} else if (jsonList[i].code == 'none_body_time') {
|
||||
_noBodyTime = jsonList[i].value ?? 0;
|
||||
} else if (jsonList[i].code == 'moving_max_dis') {
|
||||
_maxDis = jsonList[i].value ?? 0;
|
||||
}
|
||||
}
|
||||
return CeilingSensorModel(
|
||||
presenceState: _presenceState,
|
||||
sensitivity: _sensitivity,
|
||||
checkingResult: _checkingResult,
|
||||
presenceRange: _presenceRange,
|
||||
sportsPara: _sportsPara,
|
||||
bodyMovement: _bodyMovement,
|
||||
noBodyTime: _noBodyTime,
|
||||
maxDistance: _maxDis);
|
||||
}
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
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/ceiling_sensor/bloc/bloc.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/event.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/state.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/utils/constants/assets.dart';
|
||||
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
||||
|
||||
class CeilingSensorControls extends StatelessWidget with HelperResponsiveLayout {
|
||||
const CeilingSensorControls({super.key, required this.device});
|
||||
|
||||
final AllDevicesModel device;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isLarge = isLargeScreenSize(context);
|
||||
final isMedium = isMediumScreenSize(context);
|
||||
return BlocProvider(
|
||||
create: (context) =>
|
||||
CeilingSensorBloc(deviceId: device.uuid ?? '')..add(CeilingInitialEvent()),
|
||||
child: BlocBuilder<CeilingSensorBloc, CeilingSensorState>(
|
||||
builder: (context, state) {
|
||||
if (state is CeilingLoadingInitialState) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
} else if (state is CeilingUpdateState) {
|
||||
return GridView(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 50),
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: isLarge
|
||||
? 3
|
||||
: isMedium
|
||||
? 2
|
||||
: 1,
|
||||
mainAxisExtent: 133,
|
||||
crossAxisSpacing: 12,
|
||||
mainAxisSpacing: 12,
|
||||
),
|
||||
children: [
|
||||
PresenceState(
|
||||
value: state.ceilingSensorModel.presenceState,
|
||||
),
|
||||
PresenceDisplayValue(
|
||||
value: state.ceilingSensorModel.sportsPara.toString(),
|
||||
postfix: '',
|
||||
description: 'Sports para',
|
||||
),
|
||||
PresenceDisplayValue(
|
||||
value: state.ceilingSensorModel.presenceRange.toString(),
|
||||
postfix: 'm',
|
||||
description: 'Detection Range',
|
||||
),
|
||||
PresenceUpdateData(
|
||||
value: state.ceilingSensorModel.sensitivity.toDouble(),
|
||||
title: 'Sensitivity:',
|
||||
minValue: 1,
|
||||
maxValue: 5,
|
||||
steps: 1,
|
||||
action: (int value) {
|
||||
context.read<CeilingSensorBloc>().add(
|
||||
CeilingChangeValueEvent(
|
||||
code: 'sensitivity',
|
||||
value: value,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
PresenceUpdateData(
|
||||
value: state.ceilingSensorModel.maxDistance.toDouble(),
|
||||
title: 'Maximum Distance:',
|
||||
minValue: 0,
|
||||
maxValue: 500,
|
||||
steps: 50,
|
||||
description: 'm',
|
||||
action: (int value) => context.read<CeilingSensorBloc>().add(
|
||||
CeilingChangeValueEvent(
|
||||
code: 'moving_max_dis',
|
||||
value: value,
|
||||
),
|
||||
),
|
||||
),
|
||||
PresenceUpdateData(
|
||||
value: (state.ceilingSensorModel.noBodyTime.toDouble() / 3600).roundToDouble(),
|
||||
title: 'Nobody Time:',
|
||||
minValue: 0,
|
||||
maxValue: 300000,
|
||||
steps: 5000,
|
||||
description: 'hr',
|
||||
action: (int value) =>
|
||||
context.read<CeilingSensorBloc>().add(CeilingChangeValueEvent(
|
||||
code: 'none_body_time',
|
||||
value: value,
|
||||
))),
|
||||
GestureDetector(
|
||||
onTap: () {},
|
||||
child: const PresenceStaticWidget(
|
||||
icon: Assets.illuminanceRecordIcon,
|
||||
description: 'Presence Record',
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {},
|
||||
child: const PresenceStaticWidget(
|
||||
icon: Assets.helpDescriptionIcon,
|
||||
description: 'Help Description',
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
return const Center(child: Text('Error fetching status'));
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
|
||||
class DeviceControlsContainer extends StatelessWidget {
|
||||
const DeviceControlsContainer({required this.child, super.key});
|
||||
final Widget child;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
color: ColorsManager.greyColor.withOpacity(0.2),
|
||||
border: Border.all(color: ColorsManager.boxDivider),
|
||||
),
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
@ -43,27 +43,32 @@ class IncrementDecrementWidget extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
text: '',
|
||||
children: [
|
||||
TextSpan(
|
||||
text: value,
|
||||
style: TextStyle(
|
||||
fontSize: 38,
|
||||
color: ColorsManager.dialogBlueTitle,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
Expanded(
|
||||
child: FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
text: '',
|
||||
children: [
|
||||
TextSpan(
|
||||
text: value,
|
||||
style: TextStyle(
|
||||
fontSize: 40,
|
||||
color: ColorsManager.dialogBlueTitle,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: description,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: descriptionColor ?? ColorsManager.blackColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
TextSpan(
|
||||
text: description,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: descriptionColor ?? ColorsManager.blackColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Material(
|
||||
|
@ -0,0 +1,51 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/shared/device_controls_container.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
|
||||
class PresenceDisplayValue extends StatelessWidget {
|
||||
const PresenceDisplayValue(
|
||||
{super.key, required this.value, required this.postfix, required this.description});
|
||||
|
||||
final String value;
|
||||
final String postfix;
|
||||
final String description;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DeviceControlsContainer(
|
||||
child: Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Text(
|
||||
value,
|
||||
style: Theme.of(context).textTheme.bodyLarge!.copyWith(
|
||||
color: ColorsManager.dialogBlueTitle,
|
||||
fontSize: 40,
|
||||
fontWeight: FontWeight.w700),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: Text(
|
||||
postfix,
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
color: ColorsManager.blackColor, fontSize: 16, fontWeight: FontWeight.w700),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Text(
|
||||
description,
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
color: ColorsManager.blackColor, fontWeight: FontWeight.w400, fontSize: 16),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/shared/device_controls_container.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
|
||||
class PresenceStaticWidget extends StatelessWidget {
|
||||
const PresenceStaticWidget({required this.icon, required this.description, super.key});
|
||||
final String icon;
|
||||
final String description;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DeviceControlsContainer(
|
||||
child: Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
icon,
|
||||
width: 60,
|
||||
height: 60,
|
||||
),
|
||||
Text(
|
||||
description,
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
color: ColorsManager.blackColor, fontWeight: FontWeight.w400, fontSize: 16),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/shared/device_controls_container.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
|
||||
class PresenceState extends StatelessWidget {
|
||||
const PresenceState({
|
||||
super.key,
|
||||
required this.value,
|
||||
});
|
||||
|
||||
final String value;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DeviceControlsContainer(
|
||||
child: Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Status:',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
color: ColorsManager.blackColor, fontWeight: FontWeight.w400, fontSize: 10),
|
||||
),
|
||||
],
|
||||
),
|
||||
SvgPicture.asset(
|
||||
value.toLowerCase() == 'motion'
|
||||
? Assets.sensorMotionIcon
|
||||
: value.toLowerCase() == 'presence'
|
||||
? Assets.sensorPresenceIcon
|
||||
: Assets.sensorVacantIcon,
|
||||
width: 60,
|
||||
height: 60,
|
||||
),
|
||||
Text(
|
||||
value,
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
color: ColorsManager.blackColor, fontWeight: FontWeight.w400, fontSize: 16),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
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';
|
||||
|
||||
class PresenceUpdateData extends StatefulWidget {
|
||||
const PresenceUpdateData({
|
||||
super.key,
|
||||
required this.title,
|
||||
required this.value,
|
||||
required this.action,
|
||||
required this.minValue,
|
||||
required this.maxValue,
|
||||
required this.steps,
|
||||
this.description,
|
||||
});
|
||||
|
||||
final String title;
|
||||
final double value;
|
||||
final double minValue;
|
||||
final double maxValue;
|
||||
final double steps;
|
||||
final Function action;
|
||||
final String? description;
|
||||
|
||||
@override
|
||||
State<PresenceUpdateData> createState() => _CurrentTempState();
|
||||
}
|
||||
|
||||
class _CurrentTempState extends State<PresenceUpdateData> {
|
||||
late double _adjustedValue;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_adjustedValue = _initialAdjustedValue(widget.value);
|
||||
}
|
||||
|
||||
double _initialAdjustedValue(dynamic value) {
|
||||
if (value is int || value is double) {
|
||||
return value;
|
||||
} else {
|
||||
throw ArgumentError('Invalid value type: Expected int or double');
|
||||
}
|
||||
}
|
||||
|
||||
void _onValueChanged(double newValue) {
|
||||
widget.action(newValue.toInt());
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DeviceControlsContainer(
|
||||
child: Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
widget.title,
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
color: ColorsManager.blackColor, fontWeight: FontWeight.w400, fontSize: 10),
|
||||
),
|
||||
IncrementDecrementWidget(
|
||||
value: widget.value.toString(),
|
||||
description: widget.description ?? '',
|
||||
descriptionColor: ColorsManager.blackColor,
|
||||
onIncrement: () {
|
||||
if (_adjustedValue < widget.maxValue) {
|
||||
setState(() {
|
||||
_adjustedValue = _adjustedValue + widget.steps;
|
||||
});
|
||||
_onValueChanged(_adjustedValue);
|
||||
}
|
||||
},
|
||||
onDecrement: () {
|
||||
if (_adjustedValue > widget.minValue) {
|
||||
setState(() {
|
||||
_adjustedValue = _adjustedValue - widget.steps;
|
||||
});
|
||||
_onValueChanged(_adjustedValue);
|
||||
}
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/event.dart';
|
||||
@ -8,24 +9,22 @@ import 'package:syncrow_web/services/devices_mang_api.dart';
|
||||
class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
|
||||
final String deviceId;
|
||||
late WallSensorModel deviceStatus;
|
||||
Timer? _timer;
|
||||
|
||||
WallSensorBloc({required this.deviceId}) : super(InitialState()) {
|
||||
on<WallSensorInitialEvent>(_fetchCeilingSensorStatus);
|
||||
on<ChangeIndicatorEvent>(_changeIndicator);
|
||||
on<ChangeValueEvent>(_changeValue);
|
||||
on<WallSensorUpdatedEvent>(_wallSensorUpdated);
|
||||
WallSensorBloc({required this.deviceId}) : super(WallSensorInitialState()) {
|
||||
on<WallSensorInitialEvent>(_fetchWallSensorStatus);
|
||||
on<WallSensorChangeValueEvent>(_changeValue);
|
||||
}
|
||||
|
||||
void _fetchCeilingSensorStatus(
|
||||
WallSensorInitialEvent event, Emitter<WallSensorState> emit) async {
|
||||
emit(LoadingInitialState());
|
||||
void _fetchWallSensorStatus(WallSensorInitialEvent event, Emitter<WallSensorState> emit) async {
|
||||
emit(WallSensorLoadingInitialState());
|
||||
try {
|
||||
var response = await DevicesManagementApi().getDeviceStatus(deviceId);
|
||||
deviceStatus = WallSensorModel.fromJson(response.status);
|
||||
emit(UpdateState(wallSensorModel: deviceStatus));
|
||||
emit(WallSensorUpdateState(wallSensorModel: deviceStatus));
|
||||
// _listenToChanges();
|
||||
} catch (e) {
|
||||
emit(FailedState(error: e.toString()));
|
||||
emit(WallSensorFailedState(error: e.toString()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -49,39 +48,41 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
|
||||
// } catch (_) {}
|
||||
// }
|
||||
|
||||
_wallSensorUpdated(WallSensorUpdatedEvent event, Emitter<WallSensorState> emit) {
|
||||
emit(UpdateState(wallSensorModel: deviceStatus));
|
||||
void _changeValue(WallSensorChangeValueEvent event, Emitter<WallSensorState> emit) async {
|
||||
emit(WallSensorLoadingNewSate(wallSensorModel: deviceStatus));
|
||||
if (event.code == 'far_detection') {
|
||||
deviceStatus.farDetection = event.value;
|
||||
} else if (event.code == 'motionless_sensitivity') {
|
||||
deviceStatus.motionlessSensitivity = event.value;
|
||||
} else if (event.code == 'motion_sensitivity_value') {
|
||||
deviceStatus.motionSensitivity = event.value;
|
||||
} else if (event.code == 'no_one_time') {
|
||||
deviceStatus.noBodyTime = event.value;
|
||||
}
|
||||
emit(WallSensorUpdateState(wallSensorModel: deviceStatus));
|
||||
await _runDeBouncer(deviceId: deviceId, code: event.code, value: event.value);
|
||||
}
|
||||
|
||||
void _changeIndicator(ChangeIndicatorEvent event, Emitter<WallSensorState> emit) async {
|
||||
emit(LoadingNewSate(wallSensorModel: deviceStatus));
|
||||
try {
|
||||
final response = await DevicesManagementApi()
|
||||
.deviceControl(deviceId, Status(code: 'indicator', value: !event.value));
|
||||
_runDeBouncer({
|
||||
required String deviceId,
|
||||
required String code,
|
||||
required dynamic value,
|
||||
}) {
|
||||
if (_timer != null) {
|
||||
_timer!.cancel();
|
||||
}
|
||||
_timer = Timer(const Duration(seconds: 1), () async {
|
||||
try {
|
||||
final response =
|
||||
await DevicesManagementApi().deviceControl(deviceId, Status(code: code, value: value));
|
||||
|
||||
if (response) {
|
||||
deviceStatus.indicator = !event.value;
|
||||
}
|
||||
} catch (_) {}
|
||||
emit(UpdateState(wallSensorModel: deviceStatus));
|
||||
}
|
||||
|
||||
void _changeValue(ChangeValueEvent event, Emitter<WallSensorState> emit) async {
|
||||
emit(LoadingNewSate(wallSensorModel: deviceStatus));
|
||||
try {
|
||||
final response = await DevicesManagementApi()
|
||||
.deviceControl(deviceId, Status(code: event.code, value: event.value));
|
||||
|
||||
if (response) {
|
||||
if (event.code == 'far_detection') {
|
||||
deviceStatus.farDetection = event.value;
|
||||
} else if (event.code == 'motionless_sensitivity') {
|
||||
deviceStatus.motionlessSensitivity = event.value;
|
||||
} else if (event.code == 'motion_sensitivity_value') {
|
||||
deviceStatus.motionSensitivity = event.value;
|
||||
if (!response) {
|
||||
add(WallSensorInitialEvent());
|
||||
}
|
||||
} catch (_) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(WallSensorInitialEvent());
|
||||
}
|
||||
} catch (_) {}
|
||||
emit(UpdateState(wallSensorModel: deviceStatus));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -7,24 +7,12 @@ abstract class WallSensorEvent extends Equatable {
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class WallSensorLoadingEvent extends WallSensorEvent {}
|
||||
|
||||
class WallSensorInitialEvent extends WallSensorEvent {}
|
||||
|
||||
class WallSensorUpdatedEvent extends WallSensorEvent {}
|
||||
|
||||
class ChangeIndicatorEvent extends WallSensorEvent {
|
||||
final bool value;
|
||||
const ChangeIndicatorEvent({required this.value});
|
||||
|
||||
@override
|
||||
List<Object> get props => [value];
|
||||
}
|
||||
|
||||
class ChangeValueEvent extends WallSensorEvent {
|
||||
class WallSensorChangeValueEvent extends WallSensorEvent {
|
||||
final int value;
|
||||
final String code;
|
||||
const ChangeValueEvent({required this.value, required this.code});
|
||||
const WallSensorChangeValueEvent({required this.value, required this.code});
|
||||
|
||||
@override
|
||||
List<Object> get props => [value, code];
|
||||
|
@ -8,30 +8,30 @@ class WallSensorState extends Equatable {
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class InitialState extends WallSensorState {}
|
||||
class WallSensorInitialState extends WallSensorState {}
|
||||
|
||||
class LoadingInitialState extends WallSensorState {}
|
||||
class WallSensorLoadingInitialState extends WallSensorState {}
|
||||
|
||||
class UpdateState extends WallSensorState {
|
||||
class WallSensorUpdateState extends WallSensorState {
|
||||
final WallSensorModel wallSensorModel;
|
||||
const UpdateState({required this.wallSensorModel});
|
||||
const WallSensorUpdateState({required this.wallSensorModel});
|
||||
|
||||
@override
|
||||
List<Object> get props => [wallSensorModel];
|
||||
}
|
||||
|
||||
class LoadingNewSate extends WallSensorState {
|
||||
class WallSensorLoadingNewSate extends WallSensorState {
|
||||
final WallSensorModel wallSensorModel;
|
||||
const LoadingNewSate({required this.wallSensorModel});
|
||||
const WallSensorLoadingNewSate({required this.wallSensorModel});
|
||||
|
||||
@override
|
||||
List<Object> get props => [wallSensorModel];
|
||||
}
|
||||
|
||||
class FailedState extends WallSensorState {
|
||||
class WallSensorFailedState extends WallSensorState {
|
||||
final String error;
|
||||
|
||||
const FailedState({required this.error});
|
||||
const WallSensorFailedState({required this.error});
|
||||
|
||||
@override
|
||||
List<Object> get props => [error];
|
||||
|
@ -9,17 +9,18 @@ class WallSensorModel {
|
||||
int currentDistance;
|
||||
int illuminance;
|
||||
bool indicator;
|
||||
int noBodyTime;
|
||||
|
||||
WallSensorModel({
|
||||
required this.presenceState,
|
||||
required this.farDetection,
|
||||
required this.presenceTime,
|
||||
required this.motionSensitivity,
|
||||
required this.motionlessSensitivity,
|
||||
required this.currentDistance,
|
||||
required this.illuminance,
|
||||
required this.indicator,
|
||||
});
|
||||
WallSensorModel(
|
||||
{required this.presenceState,
|
||||
required this.farDetection,
|
||||
required this.presenceTime,
|
||||
required this.motionSensitivity,
|
||||
required this.motionlessSensitivity,
|
||||
required this.currentDistance,
|
||||
required this.illuminance,
|
||||
required this.indicator,
|
||||
required this.noBodyTime});
|
||||
|
||||
factory WallSensorModel.fromJson(List<Status> jsonList) {
|
||||
late String _presenceState;
|
||||
@ -30,6 +31,7 @@ class WallSensorModel {
|
||||
late int _currentDistance;
|
||||
late int _illuminance;
|
||||
late bool _indicator;
|
||||
late int _noBodyTime;
|
||||
|
||||
for (int i = 0; i < jsonList.length; i++) {
|
||||
if (jsonList[i].code == 'presence_state') {
|
||||
@ -48,6 +50,8 @@ class WallSensorModel {
|
||||
_illuminance = jsonList[i].value ?? 0;
|
||||
} else if (jsonList[i].code == 'indicator') {
|
||||
_indicator = jsonList[i].value ?? false;
|
||||
} else if (jsonList[i].code == 'no_one_time') {
|
||||
_noBodyTime = jsonList[i].value ?? 0;
|
||||
}
|
||||
}
|
||||
return WallSensorModel(
|
||||
@ -58,6 +62,7 @@ class WallSensorModel {
|
||||
motionlessSensitivity: _motionlessSensitivity,
|
||||
currentDistance: _currentDistance,
|
||||
illuminance: _illuminance,
|
||||
indicator: _indicator);
|
||||
indicator: _indicator,
|
||||
noBodyTime: _noBodyTime);
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,11 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_mo
|
||||
import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/bloc.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/event.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/state.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/wall_sensor/view/widgets/presence_display_data.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/wall_sensor/view/widgets/presence_status.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/wall_sensor/view/widgets/presence_update_data.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/utils/constants/assets.dart';
|
||||
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
||||
|
||||
class WallSensorControls extends StatelessWidget with HelperResponsiveLayout {
|
||||
@ -22,9 +24,9 @@ class WallSensorControls extends StatelessWidget with HelperResponsiveLayout {
|
||||
create: (context) => WallSensorBloc(deviceId: device.uuid!)..add(WallSensorInitialEvent()),
|
||||
child: BlocBuilder<WallSensorBloc, WallSensorState>(
|
||||
builder: (context, state) {
|
||||
if (state is LoadingInitialState) {
|
||||
if (state is WallSensorLoadingInitialState) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
} else if (state is UpdateState) {
|
||||
} else if (state is WallSensorUpdateState) {
|
||||
return GridView(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 50),
|
||||
shrinkWrap: true,
|
||||
@ -62,10 +64,11 @@ class WallSensorControls extends StatelessWidget with HelperResponsiveLayout {
|
||||
value: state.wallSensorModel.motionSensitivity.toDouble(),
|
||||
title: 'Motion Detection Sensitivity:',
|
||||
minValue: 1,
|
||||
maxValue: 10,
|
||||
maxValue: 5,
|
||||
steps: 1,
|
||||
action: (int value) {
|
||||
context.read<WallSensorBloc>().add(
|
||||
ChangeValueEvent(
|
||||
WallSensorChangeValueEvent(
|
||||
code: 'motion_sensitivity_value',
|
||||
value: value,
|
||||
),
|
||||
@ -76,14 +79,55 @@ class WallSensorControls extends StatelessWidget with HelperResponsiveLayout {
|
||||
value: state.wallSensorModel.motionlessSensitivity.toDouble(),
|
||||
title: 'Motionless Detection Sensitivity:',
|
||||
minValue: 1,
|
||||
maxValue: 10,
|
||||
maxValue: 5,
|
||||
steps: 1,
|
||||
action: (int value) => context.read<WallSensorBloc>().add(
|
||||
ChangeValueEvent(
|
||||
WallSensorChangeValueEvent(
|
||||
code: 'motionless_sensitivity',
|
||||
value: value,
|
||||
),
|
||||
),
|
||||
),
|
||||
PresenceUpdateData(
|
||||
value: state.wallSensorModel.noBodyTime.toDouble(),
|
||||
title: 'Nobody Time:',
|
||||
minValue: 10,
|
||||
maxValue: 10000,
|
||||
steps: 1,
|
||||
description: 'hr',
|
||||
action: (int value) =>
|
||||
context.read<WallSensorBloc>().add(WallSensorChangeValueEvent(
|
||||
code: 'no_one_time',
|
||||
value: value,
|
||||
))),
|
||||
PresenceUpdateData(
|
||||
value: state.wallSensorModel.farDetection.toDouble(),
|
||||
title: 'Far Detection:',
|
||||
minValue: 75,
|
||||
maxValue: 600,
|
||||
steps: 75,
|
||||
description: 'cm',
|
||||
action: (int value) => context.read<WallSensorBloc>().add(
|
||||
WallSensorChangeValueEvent(
|
||||
code: 'far_detection',
|
||||
value: value,
|
||||
),
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {},
|
||||
child: const PresenceStaticWidget(
|
||||
icon: Assets.illuminanceRecordIcon,
|
||||
description: 'Illuminance Record',
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {},
|
||||
child: const PresenceStaticWidget(
|
||||
icon: Assets.presenceRecordIcon,
|
||||
description: 'Presence Record',
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
|
@ -1,52 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
|
||||
class PresenceDisplayValue extends StatelessWidget {
|
||||
const PresenceDisplayValue(
|
||||
{super.key, required this.value, required this.postfix, required this.description});
|
||||
|
||||
final String value;
|
||||
final String postfix;
|
||||
final String description;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
color: ColorsManager.greyColor.withOpacity(0.2),
|
||||
border: Border.all(color: ColorsManager.boxDivider),
|
||||
),
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
value,
|
||||
style: Theme.of(context).textTheme.bodyLarge!.copyWith(
|
||||
color: ColorsManager.dialogBlueTitle,
|
||||
fontSize: 40,
|
||||
fontWeight: FontWeight.w400),
|
||||
),
|
||||
Text(
|
||||
postfix,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodySmall!
|
||||
.copyWith(color: ColorsManager.blackColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
Text(
|
||||
description,
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
color: ColorsManager.blackColor, fontWeight: FontWeight.w400, fontSize: 16),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
|
||||
class PresenceState extends StatelessWidget {
|
||||
const PresenceState({
|
||||
super.key,
|
||||
required this.value,
|
||||
});
|
||||
|
||||
final String value;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
color: ColorsManager.greyColor.withOpacity(0.2),
|
||||
border: Border.all(color: ColorsManager.boxDivider),
|
||||
),
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Status:',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(color: ColorsManager.blackColor),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
SvgPicture.asset(
|
||||
value.toLowerCase() == 'motion' ? Assets.sensorMotion : Assets.sensorPresence,
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
Text(
|
||||
value,
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
color: ColorsManager.blackColor, fontWeight: FontWeight.w400, fontSize: 16),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/shared/increament_decreament.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
|
||||
class PresenceUpdateData extends StatefulWidget {
|
||||
const PresenceUpdateData({
|
||||
super.key,
|
||||
required this.title,
|
||||
required this.value,
|
||||
required this.action,
|
||||
required this.minValue,
|
||||
required this.maxValue,
|
||||
this.description,
|
||||
});
|
||||
final String title;
|
||||
final double value;
|
||||
final double minValue;
|
||||
final double maxValue;
|
||||
final Function action;
|
||||
final String? description;
|
||||
|
||||
@override
|
||||
State<PresenceUpdateData> createState() => _CurrentTempState();
|
||||
}
|
||||
|
||||
class _CurrentTempState extends State<PresenceUpdateData> {
|
||||
late double _adjustedValue;
|
||||
Timer? _debounce;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_adjustedValue = _initialAdjustedValue(widget.value);
|
||||
}
|
||||
|
||||
double _initialAdjustedValue(dynamic value) {
|
||||
if (value is int || value is double) {
|
||||
return value;
|
||||
} else {
|
||||
throw ArgumentError('Invalid value type: Expected int or double');
|
||||
}
|
||||
}
|
||||
|
||||
void _onValueChanged(double newValue) {
|
||||
if (_debounce?.isActive ?? false) {
|
||||
_debounce?.cancel();
|
||||
}
|
||||
_debounce = Timer(const Duration(milliseconds: 500), () {
|
||||
widget.action(newValue.toInt());
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_debounce?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
color: ColorsManager.greyColor.withOpacity(0.2),
|
||||
border: Border.all(color: ColorsManager.boxDivider),
|
||||
),
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
widget.title,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodySmall!
|
||||
.copyWith(color: ColorsManager.blackColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
IncrementDecrementWidget(
|
||||
value: widget.value.toString(),
|
||||
description: widget.description ?? '',
|
||||
descriptionColor: ColorsManager.dialogBlueTitle,
|
||||
onIncrement: () {
|
||||
if (_adjustedValue < widget.maxValue) {
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
_adjustedValue++;
|
||||
});
|
||||
_onValueChanged(_adjustedValue);
|
||||
},
|
||||
onDecrement: () {
|
||||
if (_adjustedValue > widget.minValue) {
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
_adjustedValue--;
|
||||
});
|
||||
_onValueChanged(_adjustedValue);
|
||||
}),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -29,96 +29,71 @@ class Assets {
|
||||
static const String emptyTable = "assets/images/empty_table.svg";
|
||||
|
||||
// General assets
|
||||
static const String motionlessDetection = "assets/functions_icons/motionless_detection.svg";
|
||||
static const String acHeating = "assets/functions_icons/ac_heating.svg";
|
||||
static const String acPowerOff = "assets/functions_icons/ac_power_off.svg";
|
||||
static const String acFanMiddle = "assets/functions_icons/ac_fan_middle.svg";
|
||||
static const String switchAlarmSound = "assets/functions_icons/switch_alarm_sound.svg";
|
||||
static const String resetOff = "assets/functions_icons/reset_off.svg";
|
||||
static const String sensitivityOperationIcon =
|
||||
"assets/functions_icons/sesitivity_operation_icon.svg";
|
||||
static const String motionDetection = "assets/functions_icons/motion_detection.svg";
|
||||
static const String freezing = "assets/functions_icons/freezing.svg";
|
||||
static const String indicator = "assets/functions_icons/indicator.svg";
|
||||
static const String sceneRefresh = "assets/functions_icons/scene_refresh.svg";
|
||||
static const String temperature = "assets/functions_icons/tempreture.svg";
|
||||
static const String acFanHigh = "assets/functions_icons/ac_fan_high.svg";
|
||||
static const String fanSpeed = "assets/functions_icons/fan_speed.svg";
|
||||
static const String acFanLow = "assets/functions_icons/ac_fan_low.svg";
|
||||
static const String sensitivity = "assets/functions_icons/sensitivity.svg";
|
||||
static const String lightCountdown = "assets/functions_icons/light_countdown.svg";
|
||||
static const String farDetection = "assets/functions_icons/far_detection.svg";
|
||||
static const String sceneChildUnlock = "assets/functions_icons/scene_child_unlock.svg";
|
||||
static const String acFanAuto = "assets/functions_icons/ac_fan_auto.svg";
|
||||
static const String childLock = "assets/functions_icons/child_lock.svg";
|
||||
static const String factoryReset = "assets/functions_icons/factory_reset.svg";
|
||||
static const String acCooling = "assets/functions_icons/ac_cooling.svg";
|
||||
static const String sceneChildLock = "assets/functions_icons/scene_child_lock.svg";
|
||||
static const String celsiusDegrees = "assets/functions_icons/celsius_degrees.svg";
|
||||
static const String masterState = "assets/functions_icons/master_state.svg";
|
||||
static const String acPower = "assets/functions_icons/ac_power.svg";
|
||||
static const String farDetectionFunction = "assets/functions_icons/far_detection_function.svg";
|
||||
static const String nobodyTime = "assets/functions_icons/nobody_time.svg";
|
||||
static const String motionlessDetection = "assets/icons/motionless_detection.svg";
|
||||
static const String acHeating = "assets/icons/ac_heating.svg";
|
||||
static const String acPowerOff = "assets/icons/ac_power_off.svg";
|
||||
static const String acFanMiddle = "assets/icons/ac_fan_middle.svg";
|
||||
static const String switchAlarmSound = "assets/icons/switch_alarm_sound.svg";
|
||||
static const String resetOff = "assets/icons/reset_off.svg";
|
||||
static const String sensitivityOperationIcon = "assets/icons/sesitivity_operation_icon.svg";
|
||||
static const String motionDetection = "assets/icons/motion_detection.svg";
|
||||
static const String freezing = "assets/icons/freezing.svg";
|
||||
static const String indicator = "assets/icons/indicator.svg";
|
||||
static const String sceneRefresh = "assets/icons/scene_refresh.svg";
|
||||
static const String temperature = "assets/icons/tempreture.svg";
|
||||
static const String acFanHigh = "assets/icons/ac_fan_high.svg";
|
||||
static const String fanSpeed = "assets/icons/fan_speed.svg";
|
||||
static const String acFanLow = "assets/icons/ac_fan_low.svg";
|
||||
static const String sensitivity = "assets/icons/sensitivity.svg";
|
||||
static const String lightCountdown = "assets/icons/light_countdown.svg";
|
||||
static const String farDetection = "assets/icons/far_detection.svg";
|
||||
static const String sceneChildUnlock = "assets/icons/scene_child_unlock.svg";
|
||||
static const String acFanAuto = "assets/icons/ac_fan_auto.svg";
|
||||
static const String childLock = "assets/icons/child_lock.svg";
|
||||
static const String factoryReset = "assets/icons/factory_reset.svg";
|
||||
static const String acCooling = "assets/icons/ac_cooling.svg";
|
||||
static const String sceneChildLock = "assets/icons/scene_child_lock.svg";
|
||||
static const String celsiusDegrees = "assets/icons/celsius_degrees.svg";
|
||||
static const String masterState = "assets/icons/master_state.svg";
|
||||
static const String acPower = "assets/icons/ac_power.svg";
|
||||
static const String farDetectionFunction = "assets/icons/far_detection_function.svg";
|
||||
static const String nobodyTime = "assets/icons/nobody_time.svg";
|
||||
|
||||
// Automation functions
|
||||
static const String tempPasswordUnlock =
|
||||
"assets/functions_icons/automation_functions/temp_password_unlock.svg";
|
||||
"assets/icons/automation_functions/temp_password_unlock.svg";
|
||||
static const String doorlockNormalOpen =
|
||||
"assets/functions_icons/automation_functions/doorlock_normal_open.svg";
|
||||
static const String doorbell = "assets/functions_icons/automation_functions/doorbell.svg";
|
||||
"assets/icons/automation_functions/doorlock_normal_open.svg";
|
||||
static const String doorbell = "assets/icons/automation_functions/doorbell.svg";
|
||||
static const String remoteUnlockViaApp =
|
||||
"assets/functions_icons/automation_functions/remote_unlock_via_app.svg";
|
||||
static const String doubleLock = "assets/functions_icons/automation_functions/double_lock.svg";
|
||||
static const String selfTestResult =
|
||||
"assets/functions_icons/automation_functions/self_test_result.svg";
|
||||
static const String lockAlarm = "assets/functions_icons/automation_functions/lock_alarm.svg";
|
||||
static const String presenceState =
|
||||
"assets/functions_icons/automation_functions/presence_state.svg";
|
||||
static const String currentTemp = "assets/functions_icons/automation_functions/current_temp.svg";
|
||||
static const String presence = "assets/functions_icons/automation_functions/presence.svg";
|
||||
"assets/icons/automation_functions/remote_unlock_via_app.svg";
|
||||
static const String doubleLock = "assets/icons/automation_functions/double_lock.svg";
|
||||
static const String selfTestResult = "assets/icons/automation_functions/self_test_result.svg";
|
||||
static const String lockAlarm = "assets/icons/automation_functions/lock_alarm.svg";
|
||||
static const String presenceState = "assets/icons/automation_functions/presence_state.svg";
|
||||
static const String currentTemp = "assets/icons/automation_functions/current_temp.svg";
|
||||
static const String presence = "assets/icons/automation_functions/presence.svg";
|
||||
static const String residualElectricity =
|
||||
"assets/functions_icons/automation_functions/residual_electricity.svg";
|
||||
static const String hijackAlarm = "assets/functions_icons/automation_functions/hijack_alarm.svg";
|
||||
static const String passwordUnlock =
|
||||
"assets/functions_icons/automation_functions/password_unlock.svg";
|
||||
"assets/icons/automation_functions/residual_electricity.svg";
|
||||
static const String hijackAlarm = "assets/icons/automation_functions/hijack_alarm.svg";
|
||||
static const String passwordUnlock = "assets/icons/automation_functions/password_unlock.svg";
|
||||
static const String remoteUnlockRequest =
|
||||
"assets/functions_icons/automation_functions/remote_unlock_req.svg";
|
||||
static const String cardUnlock = "assets/functions_icons/automation_functions/card_unlock.svg";
|
||||
static const String motion = "assets/functions_icons/automation_functions/motion.svg";
|
||||
"assets/icons/automation_functions/remote_unlock_req.svg";
|
||||
static const String cardUnlock = "assets/icons/automation_functions/card_unlock.svg";
|
||||
static const String motion = "assets/icons/automation_functions/motion.svg";
|
||||
static const String fingerprintUnlock =
|
||||
"assets/functions_icons/automation_functions/fingerprint_unlock.svg";
|
||||
"assets/icons/automation_functions/fingerprint_unlock.svg";
|
||||
|
||||
// Presence Sensor Assets
|
||||
static const String presenceIlluminanceRecord =
|
||||
"presence_sensor_assets/presence-sensor-assets/Illuminance-Record.svg";
|
||||
static const String presenceMaximumDistance =
|
||||
"presence_sensor_assets/presence-sensor-assets/maximum_distance.svg";
|
||||
static const String presenceDistance =
|
||||
"presence_sensor_assets/presence-sensor-assets/Distance.svg";
|
||||
static const String presenceIlluminanceValue =
|
||||
"presence_sensor_assets/presence-sensor-assets/Illuminance-Value.svg";
|
||||
static const String presenceEmpty = "presence_sensor_assets/presence-sensor-assets/Empty.svg";
|
||||
static const String presenceIndicator =
|
||||
"presence_sensor_assets/presence-sensor-assets/Indicator.svg";
|
||||
static const String presenceTime = "presence_sensor_assets/presence-sensor-assets/Time.svg";
|
||||
static const String presenceSpaceTypeIcon =
|
||||
"presence_sensor_assets/presence-sensor-assets/space_type_icon.svg";
|
||||
static const String presenceRecord = "presence_sensor_assets/presence-sensor-assets/Record.svg";
|
||||
static const String presenceHelpDescription =
|
||||
"presence_sensor_assets/presence-sensor-assets/help-description.svg";
|
||||
static const String presenceSensitivity =
|
||||
"presence_sensor_assets/presence-sensor-assets/Sensitivity.svg";
|
||||
static const String presenceParameterSettings =
|
||||
"presence_sensor_assets/presence-sensor-assets/parameter-settings.svg";
|
||||
static const String presenceInductionRecording =
|
||||
"presence_sensor_assets/presence-sensor-assets/induction-recording.svg";
|
||||
static const String sensorPresence = "presence_sensor_assets/Presence.svg";
|
||||
static const String sensorMotion = "presence-sensor-assets/presence-sensor-motion.svg";
|
||||
static const String sensorMotionIcon = "assets/icons/sensor_motion_ic.svg";
|
||||
static const String sensorPresenceIcon = "assets/icons/sensor_presence_ic.svg";
|
||||
static const String sensorVacantIcon = "assets/icons/sensor_vacant_ic.svg";
|
||||
static const String illuminanceRecordIcon = "assets/icons/illuminance_record_ic.svg";
|
||||
static const String presenceRecordIcon = "assets/icons/presence_record_ic.svg";
|
||||
static const String helpDescriptionIcon = "assets/icons/help_description_ic.svg";
|
||||
|
||||
static const String lightPulp = "functions_icons/light_pulb.svg";
|
||||
|
||||
static const String acDevice = "functions_icons/ac_device.svg";
|
||||
|
||||
static const String acAirConditioner = "functions_icons/ac_air.svg";
|
||||
static const String acSun = "functions_icons/ac_sun.svg";
|
||||
static const String lightPulp = "assets/icons/light_pulb.svg";
|
||||
static const String acDevice = "assets/icons/ac_device.svg";
|
||||
static const String acAirConditioner = "assets/icons/ac_air.svg";
|
||||
static const String acSun = "assets/icons/ac_sun.svg";
|
||||
}
|
||||
|
Reference in New Issue
Block a user