mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2025-07-17 02:25:16 +00:00
Merge pull request #19 from SyncrowIOT/configure_wall_presence_sensors
Configure_wall_presence_sensors
This commit is contained in:
@ -1,7 +1,9 @@
|
|||||||
|
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||||
|
|
||||||
class FunctionModel {
|
class FunctionModel {
|
||||||
String? code;
|
String? code;
|
||||||
String? type;
|
FunctionType? type;
|
||||||
String? values;
|
ValueModel? values;
|
||||||
|
|
||||||
FunctionModel({
|
FunctionModel({
|
||||||
required this.code,
|
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,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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),
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
@ -1,5 +1,3 @@
|
|||||||
import 'dart:math';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.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/features/shared_widgets/text_widgets/body_small.dart';
|
||||||
import 'package:syncrow_app/generated/assets.dart';
|
import 'package:syncrow_app/generated/assets.dart';
|
||||||
import 'package:syncrow_app/utils/context_extension.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/color_manager.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||||
|
|
||||||
|
import 'wall_sensor_interface.dart';
|
||||||
|
|
||||||
class CeilingSensorInterface extends StatelessWidget {
|
class CeilingSensorInterface extends StatelessWidget {
|
||||||
const CeilingSensorInterface({super.key, required this.ceilingSensor});
|
const CeilingSensorInterface({super.key, required this.ceilingSensor});
|
||||||
|
|
||||||
final DeviceModel ceilingSensor;
|
final DeviceModel ceilingSensor;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
String state = ceilingSensor.status
|
||||||
|
.firstWhere((element) => element.code == "presence_state")
|
||||||
|
.value
|
||||||
|
.toString();
|
||||||
return AnnotatedRegion(
|
return AnnotatedRegion(
|
||||||
value: SystemUiOverlayStyle(
|
value: SystemUiOverlayStyle(
|
||||||
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
|
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
|
||||||
@ -58,13 +63,71 @@ class CeilingSensorInterface extends StatelessWidget {
|
|||||||
Column(
|
Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
SvgPicture.asset(
|
InkWell(
|
||||||
Assets.presenceSensorAssetsPresenceSensorMotion,
|
onTap: () {
|
||||||
width: 100,
|
if ((ceilingSensor.isOnline ?? false) == false) {
|
||||||
height: 100,
|
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(
|
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(
|
style: context.bodyMedium.copyWith(
|
||||||
fontWeight: FontsManager.bold,
|
fontWeight: FontsManager.bold,
|
||||||
),
|
),
|
||||||
|
@ -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),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -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': '',
|
||||||
|
};
|
@ -1,17 +1,23 @@
|
|||||||
part of "wall_sensor_interface.dart";
|
part of "wall_sensor_interface.dart";
|
||||||
|
|
||||||
class PresenceIndicator extends StatelessWidget {
|
class PresenceIndicator extends StatelessWidget {
|
||||||
const PresenceIndicator({super.key});
|
const PresenceIndicator({super.key, required this.wallSensor});
|
||||||
|
final DeviceModel wallSensor;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
String state = wallSensor.status
|
||||||
|
.firstWhere((element) => element.code == "presence_state")
|
||||||
|
.value
|
||||||
|
.toString();
|
||||||
return Expanded(
|
return Expanded(
|
||||||
flex: 6,
|
flex: 6,
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
SvgPicture.asset(
|
SvgPicture.asset(
|
||||||
Assets.presenceSensorAssetsPresence,
|
state == 'presence'
|
||||||
|
? Assets.presenceSensorAssetsPresence
|
||||||
|
: Assets.presenceSensorAssetsPresenceSensorMotion,
|
||||||
width: 100,
|
width: 100,
|
||||||
height: 100,
|
height: 100,
|
||||||
),
|
),
|
||||||
@ -19,7 +25,7 @@ class PresenceIndicator extends StatelessWidget {
|
|||||||
height: 10,
|
height: 10,
|
||||||
),
|
),
|
||||||
BodyMedium(
|
BodyMedium(
|
||||||
text: 'Presence',
|
text: StringHelpers.toTitleCase(state),
|
||||||
style: context.bodyMedium.copyWith(fontWeight: FontsManager.bold),
|
style: context.bodyMedium.copyWith(fontWeight: FontsManager.bold),
|
||||||
),
|
),
|
||||||
],
|
],
|
@ -2,6 +2,8 @@ import 'package:flutter/cupertino.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.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/devices/model/device_model.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.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/features/shared_widgets/text_widgets/title_medium.dart';
|
||||||
import 'package:syncrow_app/generated/assets.dart';
|
import 'package:syncrow_app/generated/assets.dart';
|
||||||
import 'package:syncrow_app/utils/context_extension.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/color_manager.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||||
|
|
||||||
part "parameters_list.dart";
|
part "parameters_list.dart";
|
||||||
part "presence_indicator.dart";
|
part "presence_indicator.dart";
|
||||||
|
part "parameter_control_dialog.dart";
|
||||||
|
|
||||||
class WallMountedInterface extends StatelessWidget {
|
class WallMountedInterface extends StatelessWidget {
|
||||||
const WallMountedInterface({super.key, required this.wallSensor});
|
const WallMountedInterface({super.key, required this.wallSensor});
|
||||||
@ -56,7 +60,9 @@ class WallMountedInterface extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
const PresenceIndicator(),
|
PresenceIndicator(
|
||||||
|
wallSensor: wallSensor,
|
||||||
|
),
|
||||||
ParametersList(wallSensor: wallSensor),
|
ParametersList(wallSensor: wallSensor),
|
||||||
],
|
],
|
||||||
),
|
),
|
@ -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/ACs/ac_interface.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/lights/light_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';
|
import 'package:syncrow_app/features/devices/view/widgets/presence_sensors/ceiling_sensor_interface.dart';
|
||||||
|
|
||||||
|
@ -35,7 +35,10 @@ class WizartSwitches extends StatelessWidget {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
// DevicesCubit.getInstance().selectCategory(index);
|
// DevicesCubit.getInstance().selectCategory(index);
|
||||||
//Navigate to the chosen category view without animation
|
//Navigate to the chosen category view without animation
|
||||||
|
if (DevicesCubit.getInstance().chosenCategoryView ==
|
||||||
|
null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
Navigator.push(context,
|
Navigator.push(context,
|
||||||
CustomPageRoute(builder: (context) {
|
CustomPageRoute(builder: (context) {
|
||||||
return DevicesCubit.getInstance()
|
return DevicesCubit.getInstance()
|
||||||
|
@ -61,4 +61,11 @@ class StringHelpers {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static String toTitleCase(String text) {
|
||||||
|
return text
|
||||||
|
.split(' ')
|
||||||
|
.map((word) => word[0].toUpperCase() + word.substring(1))
|
||||||
|
.join(' ');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,15 @@ enum DeviceType {
|
|||||||
// DL awu7anehyu5q1iu8
|
// DL awu7anehyu5q1iu8
|
||||||
// WPS awarhusb
|
// WPS awarhusb
|
||||||
// 3G 1a6vgvyi
|
// 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 = {
|
Map<String, DeviceType> devicesTypesMap = {
|
||||||
"wzdcrqh0": DeviceType.AC,
|
"wzdcrqh0": DeviceType.AC,
|
||||||
"wp8ticoo2bhumwgb": DeviceType.Gateway,
|
"wp8ticoo2bhumwgb": DeviceType.Gateway,
|
||||||
@ -61,75 +69,127 @@ Map<String, DeviceType> devicesTypesMap = {
|
|||||||
};
|
};
|
||||||
Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
|
Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
|
||||||
DeviceType.AC: [
|
DeviceType.AC: [
|
||||||
FunctionModel(code: 'switch', type: 'Boolean', values: '{}'),
|
|
||||||
FunctionModel(
|
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(
|
FunctionModel(
|
||||||
code: 'temp_set',
|
code: 'temp_set',
|
||||||
type: 'Integer',
|
type: functionTypesMap['Integer'],
|
||||||
values: '{"unit":"℃","min":200,"max":300,"scale":1,"step":5}'),
|
values: ValueModel.fromJson(
|
||||||
|
{"unit": "℃", "min": 200, "max": 300, "scale": 1, "step": 5})),
|
||||||
FunctionModel(
|
FunctionModel(
|
||||||
code: 'level',
|
code: 'level',
|
||||||
type: 'Enum',
|
type: functionTypesMap['Enum'],
|
||||||
values: '{"range":["low","middle","high","auto"]}'),
|
values: ValueModel.fromJson({
|
||||||
FunctionModel(code: 'child_lock', type: 'Boolean', values: '{}'),
|
"range": ["low", "middle", "high", "auto"]
|
||||||
|
})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'child_lock',
|
||||||
|
type: functionTypesMap['Boolean'],
|
||||||
|
values: ValueModel.fromJson({})),
|
||||||
],
|
],
|
||||||
DeviceType.Gateway: [
|
DeviceType.Gateway: [
|
||||||
FunctionModel(code: 'switch_alarm_sound', type: 'Boolean', values: '{}'),
|
FunctionModel(
|
||||||
|
code: 'switch_alarm_sound',
|
||||||
|
type: functionTypesMap['Boolean'],
|
||||||
|
values: ValueModel.fromJson({})),
|
||||||
FunctionModel(
|
FunctionModel(
|
||||||
code: 'master_state',
|
code: 'master_state',
|
||||||
type: 'Enum',
|
type: functionTypesMap['Enum'],
|
||||||
values: '{"range":["normal","alarm"]}'),
|
values: ValueModel.fromJson({
|
||||||
FunctionModel(code: 'factory_reset', type: 'Boolean', values: '{}'),
|
"range": ["normal", "alarm"]
|
||||||
|
})),
|
||||||
FunctionModel(
|
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: [
|
DeviceType.CeilingSensor: [
|
||||||
FunctionModel(
|
FunctionModel(
|
||||||
code: 'sensitivity',
|
code: 'sensitivity',
|
||||||
type: 'Integer',
|
type: functionTypesMap['Integer'],
|
||||||
values: '{"unit":"","min":1,"max":10,"scale":0,"step":1}'),
|
values: ValueModel.fromJson(
|
||||||
|
{"unit": "", "min": 1, "max": 10, "scale": 0, "step": 1})),
|
||||||
],
|
],
|
||||||
DeviceType.DoorLock: [
|
DeviceType.DoorLock: [
|
||||||
FunctionModel(code: 'remote_no_pd_setkey', type: 'Raw', values: '{}'),
|
FunctionModel(
|
||||||
FunctionModel(code: 'remote_no_dp_key', type: 'Raw', values: '{}'),
|
code: 'remote_no_pd_setkey',
|
||||||
FunctionModel(code: 'normal_open_switch', type: 'Boolean', values: '{}'),
|
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: [
|
DeviceType.WallSensor: [
|
||||||
FunctionModel(
|
FunctionModel(
|
||||||
code: 'far_detection',
|
code: 'far_detection',
|
||||||
type: 'Integer',
|
type: functionTypesMap['Integer'],
|
||||||
values: '{"unit":"cm","min":75,"max":600,"scale":0,"step":75}'),
|
values: ValueModel.fromJson(
|
||||||
|
{"unit": "cm", "min": 75, "max": 600, "scale": 0, "step": 75})),
|
||||||
FunctionModel(
|
FunctionModel(
|
||||||
code: 'presence_time',
|
code: 'presence_time',
|
||||||
type: 'Integer',
|
type: functionTypesMap['Integer'],
|
||||||
values: '{"unit":"Min","min":0,"max":65535,"scale":0,"step":1}'),
|
values: ValueModel.fromJson(
|
||||||
|
{"unit": "Min", "min": 0, "max": 65535, "scale": 0, "step": 1})),
|
||||||
FunctionModel(
|
FunctionModel(
|
||||||
code: 'motion_sensitivity_value',
|
code: 'motion_sensitivity_value',
|
||||||
type: 'Integer',
|
type: functionTypesMap['Integer'],
|
||||||
values: '{"unit":"","min":1,"max":5,"scale":0,"step":1}'),
|
values: ValueModel.fromJson(
|
||||||
|
{"unit": "", "min": 1, "max": 5, "scale": 0, "step": 1})),
|
||||||
FunctionModel(
|
FunctionModel(
|
||||||
code: 'motionless_sensitivity',
|
code: 'motionless_sensitivity',
|
||||||
type: 'Integer',
|
type: functionTypesMap['Integer'],
|
||||||
values: '{"unit":"","min":1,"max":5,"scale":0,"step":1}'),
|
values: ValueModel.fromJson(
|
||||||
FunctionModel(code: 'indicator', type: 'Boolean', values: '{}'),
|
{"unit": "", "min": 1, "max": 5, "scale": 0, "step": 1})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'indicator',
|
||||||
|
type: functionTypesMap['Boolean'],
|
||||||
|
values: ValueModel.fromJson({})),
|
||||||
],
|
],
|
||||||
DeviceType.ThreeGang: [
|
DeviceType.ThreeGang: [
|
||||||
FunctionModel(code: 'switch_1', type: 'Boolean', values: '{}'),
|
FunctionModel(
|
||||||
FunctionModel(code: 'switch_2', type: 'Boolean', values: '{}'),
|
code: 'switch_1',
|
||||||
FunctionModel(code: 'switch_3', type: 'Boolean', values: '{}'),
|
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(
|
FunctionModel(
|
||||||
code: 'countdown_1',
|
code: 'countdown_1',
|
||||||
type: 'Integer',
|
type: functionTypesMap['Integer'],
|
||||||
values: '{"unit":"s","min":0,"max":43200,"scale":0,"step":1}'),
|
values: ValueModel.fromJson(
|
||||||
|
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||||
FunctionModel(
|
FunctionModel(
|
||||||
code: 'countdown_2',
|
code: 'countdown_2',
|
||||||
type: 'Integer',
|
type: functionTypesMap['Integer'],
|
||||||
values: '{"unit":"s","min":0,"max":43200,"scale":0,"step":1}'),
|
values: ValueModel.fromJson(
|
||||||
|
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||||
FunctionModel(
|
FunctionModel(
|
||||||
code: 'countdown_3',
|
code: 'countdown_3',
|
||||||
type: 'Integer',
|
type: functionTypesMap['Integer'],
|
||||||
values: '{"unit":"s","min":0,"max":43200,"scale":0,"step":1}'),
|
values: ValueModel.fromJson(
|
||||||
|
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user