mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2026-10-25 06:27:56 +00:00
Implemented ceiling, wall sensors functionality
This commit is contained in:
@@ -0,0 +1,344 @@
|
||||
part of "wall_sensor_interface.dart";
|
||||
|
||||
class ParametersList extends StatelessWidget {
|
||||
const ParametersList({
|
||||
super.key,
|
||||
required this.wallSensor,
|
||||
required this.presenceSensorsModel,
|
||||
});
|
||||
|
||||
final DeviceModel wallSensor;
|
||||
final WallSensorModel presenceSensorsModel;
|
||||
@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: () async {
|
||||
if ((wallSensor.isOnline ?? false) == false) {
|
||||
return;
|
||||
}
|
||||
String controlCode = 'motion_sensitivity_value';
|
||||
final result = await showDialog(
|
||||
context: context,
|
||||
builder: (context) => ParameterControlDialog(
|
||||
title: 'Motion Detection Sensitivity',
|
||||
sensor: wallSensor,
|
||||
controlCode: controlCode,
|
||||
value: presenceSensorsModel.motionSensitivity,
|
||||
min: wallSensor.functions
|
||||
.firstWhere((element) => element.code == controlCode)
|
||||
.values
|
||||
?.min ??
|
||||
0,
|
||||
max: wallSensor.functions
|
||||
.firstWhere((element) => element.code == controlCode)
|
||||
.values
|
||||
?.max ??
|
||||
0,
|
||||
),
|
||||
);
|
||||
if (result != null) {
|
||||
BlocProvider.of<WallSensorBloc>(context)
|
||||
.add(ChangeValueEvent(value: result, code: controlCode));
|
||||
}
|
||||
},
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const BodySmall(
|
||||
text: 'Motion\nDetection\nSensitivity',
|
||||
textAlign: TextAlign.center),
|
||||
BodyLarge(
|
||||
text: presenceSensorsModel.motionSensitivity.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: () async {
|
||||
if ((wallSensor.isOnline ?? false) == false) {
|
||||
return;
|
||||
}
|
||||
String controlCode = 'motionless_sensitivity';
|
||||
final result = await showDialog(
|
||||
context: context,
|
||||
builder: (context) => ParameterControlDialog(
|
||||
title: 'Motionless Detection Sensitivity',
|
||||
sensor: wallSensor,
|
||||
controlCode: controlCode,
|
||||
value: presenceSensorsModel.motionlessSensitivity,
|
||||
min: wallSensor.functions
|
||||
.firstWhere((element) => element.code == controlCode)
|
||||
.values
|
||||
?.min ??
|
||||
0,
|
||||
max: wallSensor.functions
|
||||
.firstWhere((element) => element.code == controlCode)
|
||||
.values
|
||||
?.max ??
|
||||
0,
|
||||
),
|
||||
);
|
||||
|
||||
if (result != null) {
|
||||
BlocProvider.of<WallSensorBloc>(context)
|
||||
.add(ChangeValueEvent(value: result, code: controlCode));
|
||||
}
|
||||
},
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const BodySmall(
|
||||
text: 'Motionless\nDetection\nSensitivity',
|
||||
textAlign: TextAlign.center),
|
||||
BodyLarge(
|
||||
text: presenceSensorsModel.motionlessSensitivity.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: () async {
|
||||
if ((wallSensor.isOnline ?? false) == false) {
|
||||
return;
|
||||
}
|
||||
String controlCode = 'far_detection';
|
||||
final result = await showDialog(
|
||||
context: context,
|
||||
builder: (context) => ParameterControlDialog(
|
||||
title: 'Far Detection',
|
||||
sensor: wallSensor,
|
||||
controlCode: controlCode,
|
||||
value: presenceSensorsModel.farDetection,
|
||||
min: wallSensor.functions
|
||||
.firstWhere((element) => element.code == controlCode)
|
||||
.values
|
||||
?.min ??
|
||||
0,
|
||||
max: wallSensor.functions
|
||||
.firstWhere((element) => element.code == controlCode)
|
||||
.values
|
||||
?.max ??
|
||||
0,
|
||||
),
|
||||
);
|
||||
if (result != null) {
|
||||
BlocProvider.of<WallSensorBloc>(context)
|
||||
.add(ChangeValueEvent(value: result, code: controlCode));
|
||||
}
|
||||
},
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const BodySmall(
|
||||
text: 'Far\nDetection', textAlign: TextAlign.center),
|
||||
BodyLarge(
|
||||
text:
|
||||
'${presenceSensorsModel.farDetection.toString()}${wallSensor.functions.firstWhere((element) => element.code == 'far_detection').values?.unit ?? ''}',
|
||||
style: context.bodyLarge.copyWith(
|
||||
fontWeight: FontsManager.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
listItem(wallSensorButtons[index], context, wallSensor, presenceSensorsModel)
|
||||
],
|
||||
);
|
||||
}
|
||||
return listItem(wallSensorButtons[index], context, wallSensor, presenceSensorsModel);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
//{"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.assetsIconsPresenceSensorAssetsTime,
|
||||
'title': 'Presence Time',
|
||||
'code': 'presence_time',
|
||||
},
|
||||
{
|
||||
'icon': Assets.assetsIconsPresenceSensorAssetsDistance,
|
||||
'title': 'Current Distance',
|
||||
'code': 'dis_current',
|
||||
},
|
||||
{
|
||||
'icon': Assets.assetsIconsPresenceSensorAssetsIlluminanceValue,
|
||||
'title': 'Illuminance Value',
|
||||
'code': 'illuminance_value',
|
||||
},
|
||||
{
|
||||
'icon': Assets.assetsIconsPresenceSensorAssetsEmpty,
|
||||
'title': 'Nobody Time',
|
||||
'code': null,
|
||||
//TODO: Implement the nobody time
|
||||
},
|
||||
{
|
||||
'icon': Assets.assetsIconsPresenceSensorAssetsIndicator,
|
||||
'title': 'Indicator',
|
||||
'code': 'indicator',
|
||||
},
|
||||
{
|
||||
'icon': Assets.assetsIconsPresenceSensorAssetsRecord,
|
||||
'title': 'Presence Record',
|
||||
'code': null
|
||||
},
|
||||
{
|
||||
'icon': Assets.assetsIconsPresenceSensorAssetsIlluminanceRecord,
|
||||
'title': 'Illuminance Record',
|
||||
'code': null
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
Widget listItem(Map<String, Object?> wallSensorButton, BuildContext context, DeviceModel wallSensor,
|
||||
WallSensorModel wallSensorStatus) {
|
||||
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;
|
||||
// }
|
||||
if (wallSensorButton['code'] == 'presence_time') {
|
||||
unit = unitsMap[wallSensorButton['code'] as String];
|
||||
value = wallSensorStatus.presenceTime;
|
||||
} else if (wallSensorButton['code'] == 'dis_current') {
|
||||
unit = unitsMap[wallSensorButton['code'] as String];
|
||||
value = wallSensorStatus.currentDistance;
|
||||
} else if (wallSensorButton['code'] == 'illuminance_value') {
|
||||
unit = unitsMap[wallSensorButton['code'] as String];
|
||||
value = wallSensorStatus.illuminance;
|
||||
}
|
||||
}
|
||||
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: wallSensorStatus.indicator,
|
||||
onChanged: (value) {
|
||||
if (wallSensor.isOnline ?? false) {
|
||||
BlocProvider.of<WallSensorBloc>(context)
|
||||
.add(ChangeIndicatorEvent(value: wallSensorStatus.indicator));
|
||||
} 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': '',
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
part of "wall_sensor_interface.dart";
|
||||
|
||||
class PresenceIndicator extends StatelessWidget {
|
||||
const PresenceIndicator({super.key, required this.state});
|
||||
final String state;
|
||||
@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(
|
||||
state == 'presence'
|
||||
? Assets.assetsIconsPresenceSensorAssetsPresence
|
||||
: Assets.assetsIconsPresenceSensorAssetsPresenceSensorMotion,
|
||||
width: 100,
|
||||
height: 100,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
BodyMedium(
|
||||
text: StringHelpers.toTitleCase(state),
|
||||
style: context.bodyMedium.copyWith(fontWeight: FontsManager.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/wall_sensor_bloc/wall_sensor_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/wall_sensor_bloc/wall_sensor_state.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/wall_sensor_bloc/wall_sensor_event.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/wall_sensor_model.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_medium.dart';
|
||||
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/helpers/snack_bar.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 "../ceiling_sensor/parameter_control_dialog.dart";
|
||||
|
||||
class WallMountedInterface extends StatelessWidget {
|
||||
const WallMountedInterface({super.key, required this.deviceModel});
|
||||
final DeviceModel deviceModel;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => WallSensorBloc(deviceId: deviceModel.uuid ?? '')..add(InitialEvent()),
|
||||
child: BlocBuilder<WallSensorBloc, WallSensorState>(builder: (context, state) {
|
||||
WallSensorModel wallSensorModel = WallSensorModel(
|
||||
presenceState: 'none',
|
||||
farDetection: 0,
|
||||
presenceTime: 0,
|
||||
motionSensitivity: 0,
|
||||
motionlessSensitivity: 0,
|
||||
currentDistance: 0,
|
||||
illuminance: 0,
|
||||
indicator: false);
|
||||
|
||||
if (state is UpdateState) {
|
||||
wallSensorModel = state.wallSensorModel;
|
||||
} else if (state is LoadingNewSate) {
|
||||
wallSensorModel = state.wallSensorModel;
|
||||
}
|
||||
return AnnotatedRegion(
|
||||
value: SystemUiOverlayStyle(
|
||||
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
|
||||
statusBarIconBrightness: Brightness.light,
|
||||
),
|
||||
child: SafeArea(
|
||||
child: Scaffold(
|
||||
backgroundColor: ColorsManager.backgroundColor,
|
||||
extendBodyBehindAppBar: true,
|
||||
extendBody: true,
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
centerTitle: true,
|
||||
title: BodyLarge(
|
||||
text: deviceModel.name ?? "",
|
||||
fontColor: ColorsManager.primaryColor,
|
||||
fontWeight: FontsManager.bold,
|
||||
),
|
||||
),
|
||||
body: Container(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
height: MediaQuery.sizeOf(context).height,
|
||||
padding: const EdgeInsets.all(Constants.defaultPadding),
|
||||
decoration: const BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage(
|
||||
Assets.assetsImagesBackground,
|
||||
),
|
||||
fit: BoxFit.cover,
|
||||
opacity: 0.4,
|
||||
),
|
||||
),
|
||||
child: state is LoadingInitialState
|
||||
? const Center(
|
||||
child: RefreshProgressIndicator(),
|
||||
)
|
||||
: Column(
|
||||
children: [
|
||||
PresenceIndicator(
|
||||
state: wallSensorModel.presenceState,
|
||||
),
|
||||
ParametersList(
|
||||
wallSensor: deviceModel,
|
||||
presenceSensorsModel: wallSensorModel,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user