sos_device

This commit is contained in:
mohammad
2024-11-13 14:19:50 +03:00
parent b547a126ed
commit 69de4b4c00
38 changed files with 3651 additions and 80 deletions
@@ -0,0 +1,259 @@
import 'dart:async';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/sos_bloc/sos_event.dart';
import 'package:syncrow_app/features/devices/bloc/sos_bloc/sos_state.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_report_model.dart';
import 'package:syncrow_app/features/devices/model/question_model.dart';
import 'package:syncrow_app/features/devices/model/sos_model.dart';
import 'package:syncrow_app/features/devices/model/status_model.dart';
import 'package:syncrow_app/features/devices/model/subspace_model.dart';
import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/services/api/spaces_api.dart';
class SosBloc extends Bloc<SosEvent, SosState> {
final String sosId;
SosBloc({
required this.sosId,
}) : super(const SosState()) {
on<SosInitial>(_fetchStatus);
on<ReportLogsInitial>(fetchLogsForLastMonth);
on<ToggleEnableAlarmEvent>(_toggleLowBattery);
on<ToggleClosingReminderEvent>(_toggleClosingReminder);
on<ChangeNameEvent>(_changeName);
on<SearchFaqEvent>(_onSearchFaq);
on<SosInitialQuestion>(_onSosInitial);
on<FetchRoomsEvent>(_fetchRoomsAndDevices);
on<SelectOptionEvent>(_onOptionSelected);
on<SaveSelectionEvent>(_onSaveSelection);
// on<ToggleWaterLeakAlarmEvent>(_toggleWaterLeakAlarm);
}
final TextEditingController nameController =
TextEditingController(text: '${'firstName'}');
bool isSaving = false;
bool editName = false;
final FocusNode focusNode = FocusNode();
Timer? _timer;
bool enableAlarm = false;
bool closingReminder = false;
bool waterAlarm = false;
SosModel deviceStatus =
SosModel(waterContactState: 'normal', batteryPercentage: 0);
void _fetchStatus(SosInitial event, Emitter<SosState> emit) async {
emit(SosLoadingState());
try {
var response = await DevicesAPI.getDeviceStatus(sosId);
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
}
deviceStatus = SosModel.fromJson(
statusModelList,
);
emit(UpdateState(sensor: deviceStatus));
Future.delayed(const Duration(milliseconds: 500));
// _listenToChanges();
} catch (e) {
emit(SosFailedState(errorMessage: e.toString()));
return;
}
}
void _onSearchFaq(SearchFaqEvent event, Emitter<SosState> emit) {
emit(SosLoadingState());
List<QuestionModel> _faqQuestions = faqQuestions.where((question) {
return question.question
.toLowerCase()
.contains(event.query.toLowerCase());
}).toList();
emit(FaqSearchState(filteredFaqQuestions: _faqQuestions));
}
void _changeName(ChangeNameEvent event, Emitter<SosState> emit) {
emit(SosLoadingState());
editName = event.value!;
if (editName) {
Future.delayed(const Duration(milliseconds: 500), () {
focusNode.requestFocus();
});
} else {
focusNode.unfocus();
}
emit(NameEditingState(editName: editName));
}
void _toggleLowBattery(
ToggleEnableAlarmEvent event, Emitter<SosState> emit) async {
emit(LoadingNewSate(sosSensor: deviceStatus));
try {
enableAlarm = event.isLowBatteryEnabled;
emit(UpdateState(sensor: deviceStatus));
await DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: sosId,
code: 'low_battery',
value: enableAlarm,
),
sosId,
);
} catch (e) {
emit(SosFailedState(errorMessage: e.toString()));
}
}
void _toggleClosingReminder(
ToggleClosingReminderEvent event, Emitter<SosState> emit) async {
emit(LoadingNewSate(sosSensor: deviceStatus));
try {
closingReminder = event.isClosingReminderEnabled;
emit(UpdateState(sensor: deviceStatus));
// API call to update the state, if necessary
// await DevicesAPI.controlDevice(
// DeviceControlModel(
// deviceId: sosId,
// code: 'closing_reminder',
// value: closingReminder,
// ),
// sosId,
// );
} catch (e) {
emit(SosFailedState(errorMessage: e.toString()));
}
}
DeviceReport recordGroups =
DeviceReport(startTime: '0', endTime: '0', data: []);
Future<void> fetchLogsForLastMonth(
ReportLogsInitial event, Emitter<SosState> emit) async {
DateTime now = DateTime.now();
DateTime lastMonth = DateTime(now.year, now.month - 1, now.day);
int startTime = lastMonth.millisecondsSinceEpoch;
int endTime = now.millisecondsSinceEpoch;
try {
emit(SosLoadingState());
var response = await DevicesAPI.getReportLogs(
startTime: startTime.toString(),
endTime: endTime.toString(),
deviceUuid: sosId,
code: 'sossensor_state',
);
recordGroups = response;
emit(UpdateState(sensor: deviceStatus));
} on DioException catch (e) {
final errorData = e.response!.data;
String errorMessage = errorData['message'];
emit(SosFailedState(errorMessage: e.toString()));
}
}
// _listenToChanges() {
// try {
// DatabaseReference ref =
// FirebaseDatabase.instance.ref('device-status/$WLId');
// Stream<DatabaseEvent> stream = ref.onValue;
// stream.listen((DatabaseEvent event) async {
// if (_timer != null) {
// await Future.delayed(const Duration(seconds: 2));
// }
// Map<dynamic, dynamic> usersMap =
// event.snapshot.value as Map<dynamic, dynamic>;
// List<StatusModel> statusList = [];
// usersMap['status'].forEach((element) {
// statusList.add(StatusModel(code: element['code'], value: true));
// });
// deviceStatus = WaterLeakModel.fromJson(statusList);
// if (!isClosed) {
// add(
// WaterLeakSwitch(switchD: deviceStatus.waterContactState),
// );
// }
// });
// } catch (_) {}
// }
// Demo list of FAQ questions using the QuestionModel class
final List<QuestionModel> faqQuestions = [
QuestionModel(
id: 1,
question: 'How does an SOS emergency button work?',
answer:
'The SOS emergency button sends an alert to your contacts when pressed.',
),
QuestionModel(
id: 2,
question: 'How long will an SOS alarm persist?',
answer:
'The SOS alarm will persist until it is manually turned off or after a set time.',
),
QuestionModel(
id: 3,
question: 'What should I do if the SOS button is unresponsive?',
answer: 'Try restarting the device. If it persists, contact support.',
),
QuestionModel(
id: 4,
question: 'Can I use the SOS feature without a network connection?',
answer:
'No, a network connection is required to send the alert to your contacts.',
),
QuestionModel(
id: 5,
question: 'How often should I check the SOS battery?',
answer:
'Check the SOS battery at least once a month to ensure it is operational.',
),
];
Future<void> _onSosInitial(
SosInitialQuestion event, Emitter<SosState> emit) async {
emit(SosLoadingState());
// SosModel sosModel = await fetchSosData(sosId); // Define this function as needed
emit(FaqLoadedState(filteredFaqQuestions: faqQuestions));
}
List<DeviceModel> allDevices = [];
List<SubSpaceModel> roomsList = [];
void _fetchRoomsAndDevices(
FetchRoomsEvent event, Emitter<SosState> emit) async {
try {
emit(SosLoadingState());
roomsList = await SpacesAPI.getSubSpaceBySpaceId(
event.unit.community.uuid, event.unit.id);
emit(FetchRoomsState(devicesList: allDevices, roomsList: roomsList));
} catch (e) {
emit(const SosFailedState(errorMessage: 'Something went wrong'));
return;
}
}
String _selectedOption = '';
bool _hasSelectionChanged = false;
void _onOptionSelected(SelectOptionEvent event, Emitter<SosState> emit) {
emit(SosLoadingState());
_selectedOption = event.selectedOption;
_hasSelectionChanged = true;
emit(OptionSelectedState(
selectedOption: _selectedOption,
hasSelectionChanged: _hasSelectionChanged));
}
void _onSaveSelection(SaveSelectionEvent event, Emitter<SosState> emit) {
if (_hasSelectionChanged) {
print('Save button clicked with selected option: $_selectedOption');
_hasSelectionChanged = false;
emit(SaveSelectionSuccessState());
}
}
}
@@ -0,0 +1,129 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
abstract class SosEvent extends Equatable {
const SosEvent();
@override
List<Object> get props => [];
}
class SosLoading extends SosEvent {}
class SosSwitch extends SosEvent {
final String switchD;
final String deviceId;
final String productId;
const SosSwitch(
{required this.switchD, this.deviceId = '', this.productId = ''});
@override
List<Object> get props => [switchD, deviceId, productId];
}
class SosUpdated extends SosEvent {}
class SosInitial extends SosEvent {
const SosInitial();
}
class ReportLogsInitial extends SosEvent {
const ReportLogsInitial();
}
class SosChangeStatus extends SosEvent {}
class GetCounterEvent extends SosEvent {
final String deviceCode;
const GetCounterEvent({required this.deviceCode});
@override
List<Object> get props => [deviceCode];
}
class ToggleEnableAlarmEvent extends SosEvent {
final bool isLowBatteryEnabled;
const ToggleEnableAlarmEvent(this.isLowBatteryEnabled);
@override
List<Object> get props => [isLowBatteryEnabled];
}
class ToggleClosingReminderEvent extends SosEvent {
final bool isClosingReminderEnabled;
const ToggleClosingReminderEvent(this.isClosingReminderEnabled);
@override
List<Object> get props => [isClosingReminderEnabled];
}
class ToggleSosAlarmEvent extends SosEvent {
final bool isSosAlarmEnabled;
const ToggleSosAlarmEvent(this.isSosAlarmEnabled);
@override
List<Object> get props => [isSosAlarmEnabled];
}
class SetCounterValue extends SosEvent {
final Duration duration;
final String deviceCode;
const SetCounterValue({required this.duration, required this.deviceCode});
@override
List<Object> get props => [duration, deviceCode];
}
class StartTimer extends SosEvent {
final int duration;
const StartTimer(this.duration);
@override
List<Object> get props => [duration];
}
class TickTimer extends SosEvent {
final int remainingTime;
const TickTimer(this.remainingTime);
@override
List<Object> get props => [remainingTime];
}
class StopTimer extends SosEvent {}
class OnClose extends SosEvent {}
class ChangeNameEvent extends SosEvent {
final bool? value;
const ChangeNameEvent({this.value});
}
class SearchFaqEvent extends SosEvent {
final String query;
const SearchFaqEvent(this.query);
}
class SosInitialQuestion extends SosEvent {
const SosInitialQuestion();
}
class FetchRoomsEvent extends SosEvent {
final SpaceModel unit;
const FetchRoomsEvent({required this.unit});
@override
List<Object> get props => [unit];
}
class SelectOptionEvent extends SosEvent {
final String selectedOption;
SelectOptionEvent({required this.selectedOption});
}
class SaveSelectionEvent extends SosEvent {}
@@ -0,0 +1,87 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/question_model.dart';
import 'package:syncrow_app/features/devices/model/sos_model.dart';
import 'package:syncrow_app/features/devices/model/subspace_model.dart';
class SosState extends Equatable {
const SosState();
@override
List<Object> get props => [];
}
class SosInitialState extends SosState {}
class SosLoadingState extends SosState {}
class SosFailedState extends SosState {
final String errorMessage;
const SosFailedState({required this.errorMessage});
@override
List<Object> get props => [errorMessage];
}
class UpdateState extends SosState {
final SosModel sensor;
const UpdateState({required this.sensor});
@override
List<Object> get props => [sensor];
}
class LoadingNewSate extends SosState {
final SosModel sosSensor;
const LoadingNewSate({required this.sosSensor});
@override
List<Object> get props => [sosSensor];
}
class NameEditingState extends SosState {
final bool editName;
NameEditingState({required this.editName});
}
class FaqLoadedState extends SosState {
final List<QuestionModel> filteredFaqQuestions;
FaqLoadedState({this.filteredFaqQuestions = const []});
}
class FaqSearchState extends SosState {
final List<QuestionModel> filteredFaqQuestions;
const FaqSearchState({this.filteredFaqQuestions = const []});
}
class FetchRoomsState extends SosState {
final List<SubSpaceModel> roomsList;
final List<DeviceModel> devicesList;
const FetchRoomsState({required this.devicesList, required this.roomsList});
@override
List<Object> get props => [devicesList];
}
class OptionSelectedState extends SosState {
final String selectedOption;
final bool hasSelectionChanged;
OptionSelectedState({
required this.selectedOption,
required this.hasSelectionChanged,
});
@override
List<Object> get props => [selectedOption, hasSelectionChanged];
}
class SaveSelectionSuccessState extends SosState {
@override
List<Object> get props => [];
}