garage Alarm

This commit is contained in:
mohammad
2024-10-08 13:06:32 +03:00
parent e5af727144
commit f2172bd6e8
6 changed files with 289 additions and 33 deletions

View File

@ -34,11 +34,14 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
on<ToggleDoorEvent>(openCloseGarageDoor); on<ToggleDoorEvent>(openCloseGarageDoor);
on<GetCounterEvent>(_getCounterValue); on<GetCounterEvent>(_getCounterValue);
on<SetCounterValue>(_setCounterValue); on<SetCounterValue>(_setCounterValue);
on<SetTimeOutValue>(_setTimeOutAlarm);
on<TickTimer>(_onTickTimer); on<TickTimer>(_onTickTimer);
on<InitialWizardEvent>(_fetchWizardStatus); on<InitialWizardEvent>(_fetchWizardStatus);
on<GroupAllOnEvent>(_groupAllOn); on<GroupAllOnEvent>(_groupAllOn);
on<GroupAllOffEvent>(_groupAllOff); on<GroupAllOffEvent>(_groupAllOff);
on<ChangeFirstWizardSwitchStatusEvent>(_changeFirstWizardSwitch); on<ChangeFirstWizardSwitchStatusEvent>(_changeFirstWizardSwitch);
on<ToggleAlarmEvent>(_toggleAlarmEvent);
//_toggleAlarmEvent
} }
void _onClose(OnClose event, Emitter<GarageDoorSensorState> emit) { void _onClose(OnClose event, Emitter<GarageDoorSensorState> emit) {
_timer?.cancel(); _timer?.cancel();
@ -84,6 +87,32 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
} }
} }
void _toggleAlarmEvent(
ToggleAlarmEvent event,
Emitter<GarageDoorSensorState> emit,
) async {
emit(LoadingNewSate(doorSensor: deviceStatus));
try {
deviceStatus.doorState1 = event.isEnabled;
emit(UpdateState(garageSensor: deviceStatus));
await DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: GDId,
code: 'door_state_1',
value: event.isEnabled,
),
GDId,
);
emit(UpdateState(garageSensor: deviceStatus));
} catch (e) {
emit(GarageDoorFailedState(errorMessage: e.toString()));
}
}
void _toggleClosingReminder(ToggleClosingReminderEvent event, void _toggleClosingReminder(ToggleClosingReminderEvent event,
Emitter<GarageDoorSensorState> emit) async { Emitter<GarageDoorSensorState> emit) async {
emit(LoadingNewSate(doorSensor: deviceStatus)); emit(LoadingNewSate(doorSensor: deviceStatus));
@ -563,4 +592,29 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
add(InitialEvent(groupScreen: oneGangGroup)); add(InitialEvent(groupScreen: oneGangGroup));
} }
} }
void _setTimeOutAlarm(
SetTimeOutValue event, Emitter<GarageDoorSensorState> emit) async {
emit(LoadingNewSate(doorSensor: deviceStatus));
int seconds = 0;
try {
seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: GDId, code: 'countdown_alarm', value: seconds),
GDId);
if (response['success'] ?? false) {
deviceStatus.countdownAlarm = seconds;
CustomSnackBar.displaySnackBar('Save Successfully');
add(GetScheduleEvent());
} else {
emit(const GarageDoorFailedState(errorMessage: 'Something went wrong'));
return;
}
} catch (e) {
emit(GarageDoorFailedState(errorMessage: e.toString()));
return;
}
}
} }

View File

@ -39,13 +39,13 @@ class GetCounterEvent extends GarageDoorEvent {
List<Object> get props => [deviceCode]; List<Object> get props => [deviceCode];
} }
class ToggleLowBatteryEvent extends GarageDoorEvent { class ToggleAlarmEvent extends GarageDoorEvent {
final bool isLowBatteryEnabled; final String isEnabled;
const ToggleLowBatteryEvent(this.isLowBatteryEnabled); const ToggleAlarmEvent(this.isEnabled);
@override @override
List<Object> get props => [isLowBatteryEnabled]; List<Object> get props => [isEnabled];
} }
class ToggleClosingReminderEvent extends GarageDoorEvent { class ToggleClosingReminderEvent extends GarageDoorEvent {
@ -74,6 +74,14 @@ class SetCounterValue extends GarageDoorEvent {
List<Object> get props => [duration, deviceCode]; List<Object> get props => [duration, deviceCode];
} }
class SetTimeOutValue extends GarageDoorEvent {
final Duration duration;
final String deviceCode;
const SetTimeOutValue({required this.duration, required this.deviceCode});
@override
List<Object> get props => [duration, deviceCode];
}
class StartTimer extends GarageDoorEvent { class StartTimer extends GarageDoorEvent {
final int duration; final int duration;

View File

@ -21,7 +21,8 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
} }
void _fetchCeilingSensorStatus( void _fetchCeilingSensorStatus(
InitialEvent event, Emitter<WallSensorState> emit) async { InitialEvent event,
Emitter<WallSensorState> emit) async {
emit(LoadingInitialState()); emit(LoadingInitialState());
try { try {
var response = await DevicesAPI.getDeviceStatus(deviceId); var response = await DevicesAPI.getDeviceStatus(deviceId);

View File

@ -18,7 +18,8 @@ class PreferencesPage extends StatelessWidget {
return DefaultScaffold( return DefaultScaffold(
title: 'Preferences', title: 'Preferences',
child: BlocProvider( child: BlocProvider(
create: (context) => GarageDoorBloc(GDId: GDId)..add(const GarageDoorInitial()), create: (context) =>
GarageDoorBloc(GDId: GDId)..add(const GarageDoorInitial()),
child: BlocBuilder<GarageDoorBloc, GarageDoorSensorState>( child: BlocBuilder<GarageDoorBloc, GarageDoorSensorState>(
builder: (context, state) { builder: (context, state) {
final garageDoorBloc = BlocProvider.of<GarageDoorBloc>(context); final garageDoorBloc = BlocProvider.of<GarageDoorBloc>(context);
@ -26,7 +27,9 @@ class PreferencesPage extends StatelessWidget {
return state is GarageDoorLoadingState return state is GarageDoorLoadingState
? const Center( ? const Center(
child: DefaultContainer( child: DefaultContainer(
width: 50, height: 50, child: CircularProgressIndicator()), width: 50,
height: 50,
child: CircularProgressIndicator()),
) )
: Column( : Column(
children: [ children: [
@ -49,14 +52,42 @@ class PreferencesPage extends StatelessWidget {
height: 50, height: 50,
child: ListTile( child: ListTile(
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
leading: const BodyMedium( leading: InkWell(
text: 'Alarm when door is open', onTap: () {
fontWeight: FontWeight.normal, showDialog(
context: context,
builder: (context) {
return TimeoutDialog(
duration: Duration(
seconds: garageDoorBloc
.deviceStatus
.countdownAlarm),
title: 'Timeout Alarm',
cancelTab: () {
Navigator.of(context).pop();
},
confirmTab: (selectedSecond) {
garageDoorBloc.add(
SetTimeOutValue(
deviceCode:
'countdown_alarm',
duration:
selectedSecond));
Navigator.of(context).pop();
},
);
});
},
child: const BodyMedium(
text: 'Alarm when door is open',
fontWeight: FontWeight.normal,
),
), ),
trailing: Container( trailing: Container(
width: 100, width: 100,
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment:
MainAxisAlignment.end,
children: [ children: [
Container( Container(
height: 30, height: 30,
@ -64,18 +95,25 @@ class PreferencesPage extends StatelessWidget {
color: ColorsManager.graysColor, color: ColorsManager.graysColor,
), ),
Transform.scale( Transform.scale(
scale: .8, scale: .8,
child: CupertinoSwitch( child: CupertinoSwitch(
value: garageDoorBloc.lowBattery, value: garageDoorBloc.deviceStatus
onChanged: (value) { .doorState1 ==
// context 'unclosed_time',
// .read<GarageDoorBloc>() onChanged: (value) {
// .add( context
// ToggleLowBatteryEvent( .read<GarageDoorBloc>()
// value)); .add(
}, ToggleAlarmEvent(
applyTheme: true, value
)), ? 'unclosed_time'
: 'close_time_alarm',
),
);
},
applyTheme: true,
),
),
], ],
), ),
)), )),
@ -103,12 +141,15 @@ class PreferencesPage extends StatelessWidget {
builder: (context) { builder: (context) {
return SecondDialog( return SecondDialog(
label2: 'Close', label2: 'Close',
initialSelectedLabel: garageDoorBloc.secondSelected.toString(), initialSelectedLabel: garageDoorBloc
.secondSelected
.toString(),
cancelTab: () { cancelTab: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
confirmTab: (v) { confirmTab: (v) {
garageDoorBloc.add(SelectSecondsEvent(seconds: v)); garageDoorBloc
.add(SelectSecondsEvent(seconds: v));
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
title: 'Control', title: 'Control',
@ -129,8 +170,10 @@ class PreferencesPage extends StatelessWidget {
height: 90, height: 90,
width: 120, width: 120,
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment:
mainAxisAlignment: MainAxisAlignment.spaceBetween, CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [ children: [
BodyMedium( BodyMedium(
fontColor: ColorsManager.textGray, fontColor: ColorsManager.textGray,
@ -156,6 +199,7 @@ class PreferencesPage extends StatelessWidget {
)); ));
} }
} }
//Timeout
class SecondDialog extends StatefulWidget { class SecondDialog extends StatefulWidget {
final String label1; final String label1;
@ -183,15 +227,12 @@ class SecondDialog extends StatefulWidget {
} }
class _SecondDialogState extends State<SecondDialog> { class _SecondDialogState extends State<SecondDialog> {
// late String _selectedOption;
late int selectedSecond; late int selectedSecond;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
// Parse the initialSelectedLabel as an integer. Default to 10 if invalid or not provided.
selectedSecond = int.tryParse(widget.initialSelectedLabel ?? '10') ?? 10; selectedSecond = int.tryParse(widget.initialSelectedLabel ?? '10') ?? 10;
// _selectedOption = widget.initialSelectedLabel ?? '';
} }
@override @override
@ -229,7 +270,6 @@ class _SecondDialogState extends State<SecondDialog> {
child: CupertinoPicker( child: CupertinoPicker(
itemExtent: 40.0, itemExtent: 40.0,
scrollController: FixedExtentScrollController( scrollController: FixedExtentScrollController(
// Set the initial position based on selectedSecond
initialItem: selectedSecond - 10, initialItem: selectedSecond - 10,
), ),
onSelectedItemChanged: (int index) { onSelectedItemChanged: (int index) {
@ -242,7 +282,9 @@ class _SecondDialogState extends State<SecondDialog> {
child: BodyLarge( child: BodyLarge(
text: (index + 10).toString().padLeft(2, '0'), text: (index + 10).toString().padLeft(2, '0'),
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.w400, fontSize: 30, color: Colors.blue), fontWeight: FontWeight.w400,
fontSize: 30,
color: Colors.blue),
), ),
); );
}), }),
@ -326,3 +368,153 @@ class _SecondDialogState extends State<SecondDialog> {
); );
} }
} }
class TimeoutDialog extends StatefulWidget {
final String title;
final Function(String)? onTapLabel1;
final Function()? cancelTab;
final Function(Duration timeSelected)? confirmTab;
final Duration? duration;
TimeoutDialog({
required this.title,
this.onTapLabel1,
required this.cancelTab,
required this.confirmTab,
this.duration,
});
@override
_TimeoutDialogState createState() => _TimeoutDialogState();
}
class _TimeoutDialogState extends State<TimeoutDialog> {
late int selectedSecond;
Duration duration = Duration.zero;
int countNum = 0;
@override
void initState() {
super.initState();
duration = widget.duration!;
}
@override
Widget build(BuildContext context) {
return AlertDialog(
contentPadding: EdgeInsets.zero,
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const SizedBox(
height: 10,
),
BodyLarge(
text: widget.title,
fontWeight: FontWeight.w700,
fontColor: ColorsManager.primaryColor,
fontSize: 16,
),
const Padding(
padding: EdgeInsets.only(left: 15, right: 15),
child: Divider(
color: ColorsManager.textGray,
),
),
Padding(
padding: const EdgeInsets.only(left: 15, right: 15, bottom: 10),
child: Column(
children: [
Center(
child: Container(
height: 150,
width: MediaQuery.of(context).size.width * 1,
child: CupertinoTimerPicker(
initialTimerDuration: duration,
mode: CupertinoTimerPickerMode.hm,
onTimerDurationChanged: (Duration newDuration) {
duration = newDuration;
},
),
),
),
],
),
),
Row(
children: [
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
right: BorderSide(
color: ColorsManager.textGray,
width: 0.5,
),
top: BorderSide(
color: ColorsManager.textGray,
width: 1.0,
),
)),
child: SizedBox(
child: InkWell(
onTap: widget.cancelTab,
child: const Padding(
padding: EdgeInsets.all(15),
child: Center(
child: Text(
'Cancel',
style: TextStyle(
color: ColorsManager.textGray,
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
),
),
),
),
),
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
left: BorderSide(
color: ColorsManager.textGray,
width: 0.5,
),
top: BorderSide(
color: ColorsManager.textGray,
width: 1.0,
),
)),
child: InkWell(
onTap: () {
widget.confirmTab?.call(duration);
},
child: const Padding(
padding: EdgeInsets.all(15),
child: Center(
child: Text(
'Confirm',
style: TextStyle(
color: ColorsManager.primaryColor,
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
)),
))
],
)
],
),
);
}
String _formatDuration(int seconds) {
final hours = (seconds ~/ 3600).toString().padLeft(2, '0');
final minutes = ((seconds % 3600) ~/ 60).toString().padLeft(2, '0');
final secs = (seconds % 60).toString().padLeft(2, '0');
return '$hours:$minutes:$secs';
}
}

View File

@ -38,6 +38,7 @@ class DevicesAPI {
body: controlModel.toJson(), body: controlModel.toJson(),
showServerMessage: true, showServerMessage: true,
expectedResponseModel: (json) { expectedResponseModel: (json) {
print(json);
return json; return json;
}, },
); );

View File

@ -5,7 +5,7 @@ description: This is the mobile application project, developed with Flutter for
# pub.dev using `flutter pub publish`. This is preferred for private packages. # pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: "none" # Remove this line if you wish to publish to pub.dev publish_to: "none" # Remove this line if you wish to publish to pub.dev
version: 1.0.3+26 version: 1.0.4+26
environment: environment:
sdk: ">=3.0.6 <4.0.0" sdk: ">=3.0.6 <4.0.0"