Merge pull request #19 from SyncrowIOT/configure_wall_presence_sensors

Configure_wall_presence_sensors
This commit is contained in:
Mohammad Salameh
2024-04-22 15:37:09 +03:00
committed by GitHub
11 changed files with 767 additions and 400 deletions

View File

@ -1,7 +1,9 @@
import 'package:syncrow_app/utils/resource_manager/constants.dart';
class FunctionModel {
String? code;
String? type;
String? values;
FunctionType? type;
ValueModel? values;
FunctionModel({
required this.code,
@ -25,3 +27,41 @@ class FunctionModel {
};
}
}
//"values": "{\"unit\":\"\",\"min\":1,\"max\":10,\"scale\":0,\"step\":1}",
class ValueModel {
String? unit;
int? min;
int? max;
int? scale;
int? step;
ValueModel({
required this.unit,
required this.min,
required this.max,
required this.scale,
required this.step,
});
factory ValueModel.fromJson(Map<String, dynamic> json) {
return ValueModel(
unit: json['unit'],
min: json['min'],
max: json['max'],
scale: json['scale'],
step: json['step'],
);
}
Map<String, dynamic> toJson() {
return {
'unit': unit,
'min': min,
'max': max,
'scale': scale,
'step': step,
};
}
}

View File

@ -1,349 +0,0 @@
part of "wall_sensor_interface.dart";
class ParametersList extends StatelessWidget {
const ParametersList({
super.key,
required this.wallSensor,
});
final DeviceModel wallSensor;
@override
Widget build(BuildContext context) {
return Expanded(
flex: 7,
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: List.generate(
wallSensorButtons.length,
(index) {
if (index == 3) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
DefaultContainer(
padding: const EdgeInsets.symmetric(
vertical: 12, horizontal: 15),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
InkWell(
onTap: () {
showParameterDialog(
context,
'Motion Detection Sensitivity',
wallSensor,
5,
0,
10,
);
},
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
children: [
const BodySmall(
text: 'Motion\nDetectionn\nSensitivity',
textAlign: TextAlign.center),
BodyLarge(
text: '5',
style: context.bodyLarge
.copyWith(fontWeight: FontsManager.bold),
),
],
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Container(
width: 1,
height: 45,
color: ColorsManager.greyColor,
),
),
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const BodySmall(
text: 'Motionless\nDetection\nSensitivity',
textAlign: TextAlign.center),
BodyLarge(
text: '5',
style: context.bodyLarge.copyWith(
fontWeight: FontsManager.bold,
),
),
],
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Container(
width: 1,
height: 45,
color: ColorsManager.greyColor,
),
),
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const BodySmall(
text: 'Far\nDetection',
textAlign: TextAlign.center),
BodyLarge(
text: '600cm',
style: context.bodyLarge.copyWith(
fontWeight: FontsManager.bold,
),
),
],
),
],
),
),
listItem(wallSensorButtons[index], context, wallSensor)
],
);
}
return listItem(wallSensorButtons[index], context, wallSensor);
},
),
),
),
);
}
final List<Map<String, Object?>> wallSensorButtons = const [
{
'icon': Assets.presenceSensorAssetsTime,
'title': 'Presence Time',
'value': 0,
'unit': 'min',
'page': null,
},
{
'icon': Assets.presenceSensorAssetsDistance,
'title': 'Current Distance',
'value': 279,
'unit': 'cm',
'dialog': null,
},
{
'icon': Assets.presenceSensorAssetsIlluminanceValue,
'title': 'Illuminance Value',
'value': 0,
'unit': 'Lux',
'page': null,
},
{
'icon': Assets.presenceSensorAssetsEmpty,
'title': 'Nobody Time',
'value': 10,
'unit': 'sec',
'dialog': null,
},
{
'icon': Assets.presenceSensorAssetsIndicator,
'title': 'Indicator',
'page': null,
},
{
'icon': Assets.presenceSensorAssetsRecord,
'title': 'Presence Record',
'page': null,
},
{
'icon': Assets.presenceSensorAssetsIlluminanceRecord,
'title': 'Illuminance Record',
'page': null,
},
];
}
Widget listItem(
Map<String, Object?> wallSensorButton,
BuildContext context,
DeviceModel wallSensor,
) {
return DefaultContainer(
margin: const EdgeInsets.only(bottom: 5),
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 20),
onTap: () {
if (wallSensorButton['page'] != null) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => wallSensorButton['page'] as Widget,
),
);
}
},
child: Row(
children: [
SvgPicture.asset(
wallSensorButton['icon'] as String,
),
const SizedBox(
width: 25,
),
BodyMedium(text: wallSensorButton['title'] as String),
if (wallSensorButton['value'] != null) const Spacer(),
if (wallSensorButton['value'] != null)
BodyMedium(
text: '${wallSensorButton['value']}${wallSensorButton['unit']}',
style: context.bodyMedium.copyWith(color: ColorsManager.greyColor),
),
if (wallSensorButton['value'] != null)
if (wallSensorButton['title'] == 'Indicator')
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Transform.scale(
scale: .8,
child: CupertinoSwitch(
value: false,
onChanged: (value) {},
applyTheme: true,
)),
],
),
),
// CustomSwitch(device: wallSensor),
if (wallSensorButton['title'] == 'Nobody Time')
const Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Icon(
Icons.arrow_forward_ios,
color: ColorsManager.greyColor,
size: 15,
),
],
),
],
),
);
}
showParameterDialog(
BuildContext context,
String title,
DeviceModel wallSensor,
int value,
int min,
int max,
) {
showDialog(
context: context,
builder: (context) => Dialog(
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
),
padding: const EdgeInsets.only(top: 20),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
BodyMedium(
text: title,
style: context.bodyMedium.copyWith(
color: ColorsManager.primaryColorWithOpacity,
fontWeight: FontsManager.extraBold,
),
),
Padding(
padding: const EdgeInsets.symmetric(
vertical: 15,
horizontal: 50,
),
child: Container(
height: 1,
width: double.infinity,
color: ColorsManager.greyColor,
),
),
Padding(
padding: const EdgeInsets.symmetric(
vertical: 10,
),
child: TitleMedium(
text: value.toString(),
style: context.titleMedium.copyWith(
color: Colors.black,
fontWeight: FontsManager.bold,
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Icon(Icons.minus),
IconButton(
onPressed: () {
value--;
},
icon: const Icon(
Icons.remove,
color: Colors.grey,
),
),
Slider(
value: value.toDouble(),
onChanged: (value) {
// value = value;
},
min: 0,
max: 10,
label: value.toString(),
inactiveColor: ColorsManager.greyColor,
),
IconButton(
onPressed: () {
value++;
},
icon: const Icon(
Icons.add,
color: Colors.grey,
),
),
],
),
Container(
height: 1,
width: double.infinity,
color: ColorsManager.greyColor,
),
Row(
children: [
Expanded(
child: Center(
child: BodyMedium(
text: 'Cancel',
style: context.bodyMedium
.copyWith(color: ColorsManager.greyColor),
),
)),
Container(
height: 50,
width: 1,
color: ColorsManager.greyColor,
),
Expanded(
child: Center(
child: BodyMedium(
text: 'Confirm',
style: context.bodyMedium.copyWith(
color: ColorsManager.primaryColorWithOpacity),
),
)),
],
)
],
),
),
));
}

View File

@ -1,5 +1,3 @@
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart';
@ -10,16 +8,23 @@ import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dar
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/helpers/misc_string_helpers.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
import 'wall_sensor_interface.dart';
class CeilingSensorInterface extends StatelessWidget {
const CeilingSensorInterface({super.key, required this.ceilingSensor});
final DeviceModel ceilingSensor;
@override
Widget build(BuildContext context) {
String state = ceilingSensor.status
.firstWhere((element) => element.code == "presence_state")
.value
.toString();
return AnnotatedRegion(
value: SystemUiOverlayStyle(
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
@ -58,13 +63,71 @@ class CeilingSensorInterface extends StatelessWidget {
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
Assets.presenceSensorAssetsPresenceSensorMotion,
width: 100,
height: 100,
InkWell(
onTap: () {
if ((ceilingSensor.isOnline ?? false) == false) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text(
'Device is offline',
),
backgroundColor: Colors.red,
),
);
return;
}
String controlCode = 'sensitivity';
showDialog(
context: context,
builder: (context) => ParameterControlDialog(
title: 'Sensitivity',
sensor: ceilingSensor,
controlCode: controlCode,
value: ceilingSensor.status
.firstWhere(
(element) => element.code == controlCode)
.value as int,
min: ceilingSensor.functions
.firstWhere((element) =>
element.code == controlCode)
.values
?.min ??
0,
max: ceilingSensor.functions
.firstWhere((element) =>
element.code == controlCode)
.values
?.max ??
0,
),
);
},
child: SvgPicture.asset(
state == 'presence'
? Assets.presenceSensorAssetsPresence
: Assets.presenceSensorAssetsPresenceSensorMotion,
width: 100,
height: 100,
// colorFilter: ColorFilter.mode(
// (ceilingSensor.isOnline ?? false)
// ? ColorsManager.primaryColor
// : Colors.grey.withOpacity(0.9),
// BlendMode.srcIn,
// ),
),
),
const SizedBox(
height: 10,
),
BodyMedium(
text: 'Motion',
text: StringHelpers.toTitleCase(state),
// (ceilingSensor.isOnline ?? false)
// ? StringHelpers.toTitleCase(ceilingSensor.status
// .firstWhere((element) =>
// element.code == 'presence_state')
// .value
// .toString())
// : "Offline",
style: context.bodyMedium.copyWith(
fontWeight: FontsManager.bold,
),

View File

@ -0,0 +1,173 @@
part of 'wall_sensor_interface.dart';
class ParameterControlDialog extends StatefulWidget {
final String title;
final DeviceModel sensor;
final int value;
final int min;
final int max;
final String controlCode;
const ParameterControlDialog({
super.key,
required this.title,
required this.sensor,
required this.value,
required this.min,
required this.max,
required this.controlCode,
});
@override
ParameterControlDialogState createState() => ParameterControlDialogState();
}
class ParameterControlDialogState extends State<ParameterControlDialog> {
late int _value;
@override
void initState() {
super.initState();
_value = widget.value;
}
@override
Widget build(BuildContext context) {
return Dialog(
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
),
padding: const EdgeInsets.only(top: 20),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
BodyMedium(
text: widget.title,
style: context.bodyMedium.copyWith(
color: ColorsManager.primaryColorWithOpacity,
fontWeight: FontsManager.extraBold,
),
),
Padding(
padding: const EdgeInsets.symmetric(
vertical: 15,
horizontal: 50,
),
child: Container(
height: 1,
width: double.infinity,
color: ColorsManager.greyColor,
),
),
Padding(
padding: const EdgeInsets.symmetric(
vertical: 10,
),
child: TitleMedium(
text: _value.toString(),
style: context.titleMedium.copyWith(
color: Colors.black,
fontWeight: FontsManager.bold,
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
onPressed: () {
setState(() {
_value = (_value - 1).clamp(widget.min, widget.max);
});
},
icon: const Icon(
Icons.remove,
color: Colors.grey,
),
),
Slider(
value: _value.toDouble(),
onChanged: (value) {
setState(() {
_value = value.toInt();
});
},
min: widget.min.toDouble(),
max: widget.max.toDouble(),
label: _value.toString(),
inactiveColor: ColorsManager.greyColor,
),
IconButton(
onPressed: () {
setState(() {
_value = (_value + 1).clamp(widget.min, widget.max);
});
},
icon: const Icon(
Icons.add,
color: Colors.grey,
),
),
],
),
Container(
height: 1,
width: double.infinity,
color: ColorsManager.greyColor,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
InkWell(
onTap: () {
Navigator.pop(context);
},
child: Center(
child: BodyMedium(
text: 'Cancel',
style: context.bodyMedium
.copyWith(color: ColorsManager.greyColor),
),
),
),
Container(
height: 50,
width: 1,
color: ColorsManager.greyColor,
),
InkWell(
onTap: () {
Navigator.pop(context, _value);
if (widget.sensor.isOnline == null) {
return;
}
if (!widget.sensor.isOnline!) {
debugPrint('Device is offline');
return;
}
DevicesCubit.getInstance().deviceControl(
DeviceControlModel(
deviceId: widget.sensor.id,
code: widget.controlCode,
value: widget.value),
widget.sensor.id ?? '');
},
child: Center(
child: BodyMedium(
text: 'Confirm',
style: context.bodyMedium.copyWith(
color: ColorsManager.primaryColorWithOpacity),
),
),
),
],
)
],
),
),
);
}
}

View File

@ -0,0 +1,358 @@
part of "wall_sensor_interface.dart";
class ParametersList extends StatelessWidget {
const ParametersList({
super.key,
required this.wallSensor,
});
final DeviceModel wallSensor;
@override
Widget build(BuildContext context) {
return Expanded(
flex: 7,
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: List.generate(
wallSensorButtons.length,
(index) {
if (index == 3) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
DefaultContainer(
padding: const EdgeInsets.symmetric(
vertical: 12, horizontal: 15),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
InkWell(
onTap: () {
if ((wallSensor.isOnline ?? false) == false) {
return;
}
String controlCode = 'motion_sensitivity_value';
showDialog(
context: context,
builder: (context) => ParameterControlDialog(
title: 'Motion Detection Sensitivity',
sensor: wallSensor,
controlCode: controlCode,
value: wallSensor.status
.firstWhere((element) =>
element.code == controlCode)
.value as int,
min: wallSensor.functions
.firstWhere((element) =>
element.code == controlCode)
.values
?.min ??
0,
max: wallSensor.functions
.firstWhere((element) =>
element.code == controlCode)
.values
?.max ??
0,
),
);
},
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
children: [
const BodySmall(
text: 'Motion\nDetection\nSensitivity',
textAlign: TextAlign.center),
BodyLarge(
text: wallSensor.status
.firstWhere((element) =>
element.code ==
'motion_sensitivity_value')
.value
.toString(),
style: context.bodyLarge
.copyWith(fontWeight: FontsManager.bold),
),
],
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Container(
width: 1,
height: 45,
color: ColorsManager.greyColor,
),
),
InkWell(
onTap: () {
if ((wallSensor.isOnline ?? false) == false) {
return;
}
String controlCode = 'motionless_sensitivity';
showDialog(
context: context,
builder: (context) => ParameterControlDialog(
title: 'Motionless Detection Sensitivity',
sensor: wallSensor,
controlCode: controlCode,
value: wallSensor.status
.firstWhere((element) =>
element.code == controlCode)
.value as int,
min: wallSensor.functions
.firstWhere((element) =>
element.code == controlCode)
.values
?.min ??
0,
max: wallSensor.functions
.firstWhere((element) =>
element.code == controlCode)
.values
?.max ??
0,
),
);
},
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const BodySmall(
text: 'Motionless\nDetection\nSensitivity',
textAlign: TextAlign.center),
BodyLarge(
text: wallSensor.status
.firstWhere((element) =>
element.code ==
'motionless_sensitivity')
.value
.toString(),
style: context.bodyLarge.copyWith(
fontWeight: FontsManager.bold,
),
),
],
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Container(
width: 1,
height: 45,
color: ColorsManager.greyColor,
),
),
InkWell(
onTap: () {
if ((wallSensor.isOnline ?? false) == false) {
return;
}
String controlCode = 'far_detection';
showDialog(
context: context,
builder: (context) => ParameterControlDialog(
title: 'Far Detection',
sensor: wallSensor,
controlCode: controlCode,
value: wallSensor.status
.firstWhere((element) =>
element.code == controlCode)
.value as int,
min: wallSensor.functions
.firstWhere((element) =>
element.code == controlCode)
.values
?.min ??
0,
max: wallSensor.functions
.firstWhere((element) =>
element.code == controlCode)
.values
?.max ??
0,
),
);
},
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const BodySmall(
text: 'Far\nDetection',
textAlign: TextAlign.center),
BodyLarge(
text:
'${wallSensor.status.firstWhere((element) => element.code == 'far_detection').value.toString()}${wallSensor.functions.firstWhere((element) => element.code == 'far_detection').values?.unit ?? ''}',
style: context.bodyLarge.copyWith(
fontWeight: FontsManager.bold,
),
),
],
),
),
],
),
),
listItem(wallSensorButtons[index], context, wallSensor)
],
);
}
return listItem(wallSensorButtons[index], context, wallSensor);
},
),
),
),
);
}
//{"result":{"productId":"awarhusb","productType":"WPS","status":[{"code":"presence_state","value":"none"},{"code":"far_detection","value":75},{"code":"presence_time","value":0},{"code":"motion_sensitivity_value","value":5},{"code":"motionless_sensitivity","value":5},{"code":"dis_current","value":214},{"code":"illuminance_value","value":231},{"code":"indicator","value":true}]},"success":true}
final List<Map<String, Object?>> wallSensorButtons = const [
{
'icon': Assets.presenceSensorAssetsTime,
'title': 'Presence Time',
'code': 'presence_time',
},
{
'icon': Assets.presenceSensorAssetsDistance,
'title': 'Current Distance',
'code': 'dis_current',
},
{
'icon': Assets.presenceSensorAssetsIlluminanceValue,
'title': 'Illuminance Value',
'code': 'illuminance_value',
},
{
'icon': Assets.presenceSensorAssetsEmpty,
'title': 'Nobody Time',
'code': null,
//TODO: Implement the nobody time
},
{
'icon': Assets.presenceSensorAssetsIndicator,
'title': 'Indicator',
'code': 'indicator',
},
{
'icon': Assets.presenceSensorAssetsRecord,
'title': 'Presence Record',
'code': null
},
{
'icon': Assets.presenceSensorAssetsIlluminanceRecord,
'title': 'Illuminance Record',
'code': null
},
];
}
Widget listItem(
Map<String, Object?> wallSensorButton,
BuildContext context,
DeviceModel wallSensor,
) {
String? unit;
dynamic value;
if (wallSensorButton['code'] != null) {
if (wallSensor.status
.any((element) => element.code == wallSensorButton['code'] as String)) {
unit = unitsMap[wallSensorButton['code'] as String];
value = wallSensor.status
.firstWhere(
(element) => element.code == wallSensorButton['code'] as String)
.value;
}
}
return DefaultContainer(
margin: const EdgeInsets.only(bottom: 5),
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 20),
onTap: () {
if (wallSensorButton['page'] != null) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => wallSensorButton['page'] as Widget,
),
);
}
},
child: Row(
children: [
SvgPicture.asset(
wallSensorButton['icon'] as String,
),
const SizedBox(
width: 25,
),
BodyMedium(
text: wallSensorButton['title'] as String,
),
if (wallSensorButton['code'] != null) const Spacer(),
if (wallSensorButton['code'] != null)
if (wallSensorButton['title'] != 'Indicator')
BodyMedium(
text: '${value ?? 'N/A'}${unit ?? ''}',
style:
context.bodyMedium.copyWith(color: ColorsManager.greyColor),
),
if (wallSensorButton['title'] == 'Indicator')
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Transform.scale(
scale: .8,
child: CupertinoSwitch(
value: value ?? false,
onChanged: (value) {
if (wallSensor.isOnline ?? false) {
DevicesCubit.getInstance().deviceControl(
DeviceControlModel(
deviceId: wallSensor.id,
code: 'indicator',
value: value,
),
wallSensor.id ?? '');
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Device is offline'),
backgroundColor: Colors.red,
),
);
}
},
applyTheme: true,
)),
],
),
),
if (wallSensorButton['title'] == 'Nobody Time')
const Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Icon(
Icons.arrow_forward_ios,
color: ColorsManager.greyColor,
size: 15,
),
],
),
],
),
);
}
Map<String, String> unitsMap = {
'presence_time': 's',
'dis_current': 'cm',
'illuminance_value': 'lux',
'far_detection': 'cm',
'motion_sensitivity_value': '',
'motionless_sensitivity': '',
};

View File

@ -1,17 +1,23 @@
part of "wall_sensor_interface.dart";
class PresenceIndicator extends StatelessWidget {
const PresenceIndicator({super.key});
const PresenceIndicator({super.key, required this.wallSensor});
final DeviceModel wallSensor;
@override
Widget build(BuildContext context) {
String state = wallSensor.status
.firstWhere((element) => element.code == "presence_state")
.value
.toString();
return Expanded(
flex: 6,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
Assets.presenceSensorAssetsPresence,
state == 'presence'
? Assets.presenceSensorAssetsPresence
: Assets.presenceSensorAssetsPresenceSensorMotion,
width: 100,
height: 100,
),
@ -19,7 +25,7 @@ class PresenceIndicator extends StatelessWidget {
height: 10,
),
BodyMedium(
text: 'Presence',
text: StringHelpers.toTitleCase(state),
style: context.bodyMedium.copyWith(fontWeight: FontsManager.bold),
),
],

View File

@ -2,6 +2,8 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
@ -10,12 +12,14 @@ import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart
import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/helpers/misc_string_helpers.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
part "parameters_list.dart";
part "presence_indicator.dart";
part "parameter_control_dialog.dart";
class WallMountedInterface extends StatelessWidget {
const WallMountedInterface({super.key, required this.wallSensor});
@ -56,7 +60,9 @@ class WallMountedInterface extends StatelessWidget {
),
child: Column(
children: [
const PresenceIndicator(),
PresenceIndicator(
wallSensor: wallSensor,
),
ParametersList(wallSensor: wallSensor),
],
),

View File

@ -12,7 +12,7 @@ import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/ac_interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/lights/light_interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/presence_sensor/wall_sensor_interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/presence_sensors/wall_sensor_interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/presence_sensors/ceiling_sensor_interface.dart';

View File

@ -35,7 +35,10 @@ class WizartSwitches extends StatelessWidget {
onTap: () {
// DevicesCubit.getInstance().selectCategory(index);
//Navigate to the chosen category view without animation
if (DevicesCubit.getInstance().chosenCategoryView ==
null) {
return;
}
Navigator.push(context,
CustomPageRoute(builder: (context) {
return DevicesCubit.getInstance()

View File

@ -61,4 +61,11 @@ class StringHelpers {
return 0;
}
}
static String toTitleCase(String text) {
return text
.split(' ')
.map((word) => word[0].toUpperCase() + word.substring(1))
.join(' ');
}
}

View File

@ -50,7 +50,15 @@ enum DeviceType {
// DL awu7anehyu5q1iu8
// WPS awarhusb
// 3G 1a6vgvyi
enum FunctionType { Boolean, Enum, Integer, Raw, String }
Map<String, FunctionType> functionTypesMap = {
"Boolean": FunctionType.Boolean,
"Enum": FunctionType.Enum,
"Integer": FunctionType.Integer,
"Raw": FunctionType.Raw,
"String": FunctionType.String,
};
Map<String, DeviceType> devicesTypesMap = {
"wzdcrqh0": DeviceType.AC,
"wp8ticoo2bhumwgb": DeviceType.Gateway,
@ -61,75 +69,127 @@ Map<String, DeviceType> devicesTypesMap = {
};
Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
DeviceType.AC: [
FunctionModel(code: 'switch', type: 'Boolean', values: '{}'),
FunctionModel(
code: 'mode', type: 'Enum', values: '{"range":["cold","hot","wind"]}'),
code: 'switch',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'mode',
type: functionTypesMap['Enum'],
values: ValueModel.fromJson({
"range": ["cold", "hot", "wind"]
})),
FunctionModel(
code: 'temp_set',
type: 'Integer',
values: '{"unit":"℃","min":200,"max":300,"scale":1,"step":5}'),
type: functionTypesMap['Integer'],
values: ValueModel.fromJson(
{"unit": "", "min": 200, "max": 300, "scale": 1, "step": 5})),
FunctionModel(
code: 'level',
type: 'Enum',
values: '{"range":["low","middle","high","auto"]}'),
FunctionModel(code: 'child_lock', type: 'Boolean', values: '{}'),
type: functionTypesMap['Enum'],
values: ValueModel.fromJson({
"range": ["low", "middle", "high", "auto"]
})),
FunctionModel(
code: 'child_lock',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
],
DeviceType.Gateway: [
FunctionModel(code: 'switch_alarm_sound', type: 'Boolean', values: '{}'),
FunctionModel(
code: 'switch_alarm_sound',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'master_state',
type: 'Enum',
values: '{"range":["normal","alarm"]}'),
FunctionModel(code: 'factory_reset', type: 'Boolean', values: '{}'),
type: functionTypesMap['Enum'],
values: ValueModel.fromJson({
"range": ["normal", "alarm"]
})),
FunctionModel(
code: 'alarm_active', type: 'String', values: '{"maxlen":255}'),
code: 'factory_reset',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'alarm_active',
type: functionTypesMap['String'],
values: ValueModel.fromJson({"maxlen": 255})),
],
DeviceType.CeilingSensor: [
FunctionModel(
code: 'sensitivity',
type: 'Integer',
values: '{"unit":"","min":1,"max":10,"scale":0,"step":1}'),
type: functionTypesMap['Integer'],
values: ValueModel.fromJson(
{"unit": "", "min": 1, "max": 10, "scale": 0, "step": 1})),
],
DeviceType.DoorLock: [
FunctionModel(code: 'remote_no_pd_setkey', type: 'Raw', values: '{}'),
FunctionModel(code: 'remote_no_dp_key', type: 'Raw', values: '{}'),
FunctionModel(code: 'normal_open_switch', type: 'Boolean', values: '{}'),
FunctionModel(
code: 'remote_no_pd_setkey',
type: functionTypesMap['Raw'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'remote_no_dp_key',
type: functionTypesMap['Raw'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'normal_open_switch',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
],
DeviceType.WallSensor: [
FunctionModel(
code: 'far_detection',
type: 'Integer',
values: '{"unit":"cm","min":75,"max":600,"scale":0,"step":75}'),
type: functionTypesMap['Integer'],
values: ValueModel.fromJson(
{"unit": "cm", "min": 75, "max": 600, "scale": 0, "step": 75})),
FunctionModel(
code: 'presence_time',
type: 'Integer',
values: '{"unit":"Min","min":0,"max":65535,"scale":0,"step":1}'),
type: functionTypesMap['Integer'],
values: ValueModel.fromJson(
{"unit": "Min", "min": 0, "max": 65535, "scale": 0, "step": 1})),
FunctionModel(
code: 'motion_sensitivity_value',
type: 'Integer',
values: '{"unit":"","min":1,"max":5,"scale":0,"step":1}'),
type: functionTypesMap['Integer'],
values: ValueModel.fromJson(
{"unit": "", "min": 1, "max": 5, "scale": 0, "step": 1})),
FunctionModel(
code: 'motionless_sensitivity',
type: 'Integer',
values: '{"unit":"","min":1,"max":5,"scale":0,"step":1}'),
FunctionModel(code: 'indicator', type: 'Boolean', values: '{}'),
type: functionTypesMap['Integer'],
values: ValueModel.fromJson(
{"unit": "", "min": 1, "max": 5, "scale": 0, "step": 1})),
FunctionModel(
code: 'indicator',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
],
DeviceType.ThreeGang: [
FunctionModel(code: 'switch_1', type: 'Boolean', values: '{}'),
FunctionModel(code: 'switch_2', type: 'Boolean', values: '{}'),
FunctionModel(code: 'switch_3', type: 'Boolean', values: '{}'),
FunctionModel(
code: 'switch_1',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'switch_2',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'switch_3',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'countdown_1',
type: 'Integer',
values: '{"unit":"s","min":0,"max":43200,"scale":0,"step":1}'),
type: functionTypesMap['Integer'],
values: ValueModel.fromJson(
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
FunctionModel(
code: 'countdown_2',
type: 'Integer',
values: '{"unit":"s","min":0,"max":43200,"scale":0,"step":1}'),
type: functionTypesMap['Integer'],
values: ValueModel.fromJson(
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
FunctionModel(
code: 'countdown_3',
type: 'Integer',
values: '{"unit":"s","min":0,"max":43200,"scale":0,"step":1}'),
type: functionTypesMap['Integer'],
values: ValueModel.fromJson(
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
],
};