implemented ceiling and wall sensors, and bug fixes

This commit is contained in:
Abdullah Alassaf
2024-08-26 15:35:18 +03:00
parent 929b72d11a
commit afee0eb5b1
98 changed files with 920 additions and 671 deletions

View File

@ -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,

View File

@ -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:

View 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());
}
});
}
}

View 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];
}

View 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];
}

View File

@ -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);
}
}

View File

@ -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'));
}
},
),
);
}
}

View File

@ -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,
);
}
}

View File

@ -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(

View File

@ -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),
),
],
),
),
);
}
}

View File

@ -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),
),
],
),
),
);
}
}

View File

@ -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),
),
],
),
),
);
}
}

View File

@ -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);
}
}),
],
),
),
);
}
}

View File

@ -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));
});
}
}

View File

@ -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];

View File

@ -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];

View File

@ -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);
}
}

View File

@ -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 {

View File

@ -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),
),
],
),
);
}
}

View File

@ -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),
),
],
),
);
}
}

View File

@ -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);
}),
],
),
);
}
}