Read devices status from Firebase realtime database

This commit is contained in:
Abdullah Alassaf
2024-08-12 12:32:20 +03:00
parent f6fbf452a0
commit 8e104aeea7
15 changed files with 412 additions and 159 deletions
+74 -42
View File
@@ -1,46 +1,54 @@
PODS: PODS:
- device_info_plus (0.0.1): - device_info_plus (0.0.1):
- Flutter - Flutter
- Firebase/Analytics (10.20.0): - Firebase/Analytics (10.25.0):
- Firebase/Core - Firebase/Core
- Firebase/Core (10.20.0): - Firebase/Core (10.25.0):
- Firebase/CoreOnly - Firebase/CoreOnly
- FirebaseAnalytics (~> 10.20.0) - FirebaseAnalytics (~> 10.25.0)
- Firebase/CoreOnly (10.20.0): - Firebase/CoreOnly (10.25.0):
- FirebaseCore (= 10.20.0) - FirebaseCore (= 10.25.0)
- Firebase/Crashlytics (10.20.0): - Firebase/Crashlytics (10.25.0):
- Firebase/CoreOnly - Firebase/CoreOnly
- FirebaseCrashlytics (~> 10.20.0) - FirebaseCrashlytics (~> 10.25.0)
- Firebase/Database (10.25.0):
- Firebase/CoreOnly
- FirebaseDatabase (~> 10.25.0)
- firebase_analytics (10.8.7): - firebase_analytics (10.8.7):
- Firebase/Analytics (= 10.20.0) - Firebase/Analytics (= 10.25.0)
- firebase_core - firebase_core
- Flutter - Flutter
- firebase_core (2.25.5): - firebase_core (2.32.0):
- Firebase/CoreOnly (= 10.20.0) - Firebase/CoreOnly (= 10.25.0)
- Flutter - Flutter
- firebase_crashlytics (3.4.16): - firebase_crashlytics (3.4.16):
- Firebase/Crashlytics (= 10.20.0) - Firebase/Crashlytics (= 10.25.0)
- firebase_core - firebase_core
- Flutter - Flutter
- FirebaseAnalytics (10.20.0): - firebase_database (10.5.7):
- FirebaseAnalytics/AdIdSupport (= 10.20.0) - Firebase/Database (= 10.25.0)
- firebase_core
- Flutter
- FirebaseAnalytics (10.25.0):
- FirebaseAnalytics/AdIdSupport (= 10.25.0)
- FirebaseCore (~> 10.0) - FirebaseCore (~> 10.0)
- FirebaseInstallations (~> 10.0) - FirebaseInstallations (~> 10.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.11) - GoogleUtilities/AppDelegateSwizzler (~> 7.11)
- GoogleUtilities/MethodSwizzler (~> 7.11) - GoogleUtilities/MethodSwizzler (~> 7.11)
- GoogleUtilities/Network (~> 7.11) - GoogleUtilities/Network (~> 7.11)
- "GoogleUtilities/NSData+zlib (~> 7.11)" - "GoogleUtilities/NSData+zlib (~> 7.11)"
- nanopb (< 2.30910.0, >= 2.30908.0) - nanopb (< 2.30911.0, >= 2.30908.0)
- FirebaseAnalytics/AdIdSupport (10.20.0): - FirebaseAnalytics/AdIdSupport (10.25.0):
- FirebaseCore (~> 10.0) - FirebaseCore (~> 10.0)
- FirebaseInstallations (~> 10.0) - FirebaseInstallations (~> 10.0)
- GoogleAppMeasurement (= 10.20.0) - GoogleAppMeasurement (= 10.25.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.11) - GoogleUtilities/AppDelegateSwizzler (~> 7.11)
- GoogleUtilities/MethodSwizzler (~> 7.11) - GoogleUtilities/MethodSwizzler (~> 7.11)
- GoogleUtilities/Network (~> 7.11) - GoogleUtilities/Network (~> 7.11)
- "GoogleUtilities/NSData+zlib (~> 7.11)" - "GoogleUtilities/NSData+zlib (~> 7.11)"
- nanopb (< 2.30910.0, >= 2.30908.0) - nanopb (< 2.30911.0, >= 2.30908.0)
- FirebaseCore (10.20.0): - FirebaseAppCheckInterop (10.29.0)
- FirebaseCore (10.25.0):
- FirebaseCoreInternal (~> 10.0) - FirebaseCoreInternal (~> 10.0)
- GoogleUtilities/Environment (~> 7.12) - GoogleUtilities/Environment (~> 7.12)
- GoogleUtilities/Logger (~> 7.12) - GoogleUtilities/Logger (~> 7.12)
@@ -48,19 +56,27 @@ PODS:
- FirebaseCore (~> 10.0) - FirebaseCore (~> 10.0)
- FirebaseCoreInternal (10.29.0): - FirebaseCoreInternal (10.29.0):
- "GoogleUtilities/NSData+zlib (~> 7.8)" - "GoogleUtilities/NSData+zlib (~> 7.8)"
- FirebaseCrashlytics (10.20.0): - FirebaseCrashlytics (10.25.0):
- FirebaseCore (~> 10.5) - FirebaseCore (~> 10.5)
- FirebaseInstallations (~> 10.0) - FirebaseInstallations (~> 10.0)
- FirebaseRemoteConfigInterop (~> 10.23)
- FirebaseSessions (~> 10.5) - FirebaseSessions (~> 10.5)
- GoogleDataTransport (~> 9.2) - GoogleDataTransport (~> 9.2)
- GoogleUtilities/Environment (~> 7.8) - GoogleUtilities/Environment (~> 7.8)
- nanopb (< 2.30910.0, >= 2.30908.0) - nanopb (< 2.30911.0, >= 2.30908.0)
- PromisesObjC (~> 2.1) - PromisesObjC (~> 2.1)
- FirebaseDatabase (10.25.0):
- FirebaseAppCheckInterop (~> 10.17)
- FirebaseCore (~> 10.0)
- FirebaseSharedSwift (~> 10.0)
- GoogleUtilities/UserDefaults (~> 7.13)
- leveldb-library (~> 1.22)
- FirebaseInstallations (10.29.0): - FirebaseInstallations (10.29.0):
- FirebaseCore (~> 10.0) - FirebaseCore (~> 10.0)
- GoogleUtilities/Environment (~> 7.8) - GoogleUtilities/Environment (~> 7.8)
- GoogleUtilities/UserDefaults (~> 7.8) - GoogleUtilities/UserDefaults (~> 7.8)
- PromisesObjC (~> 2.1) - PromisesObjC (~> 2.1)
- FirebaseRemoteConfigInterop (10.29.0)
- FirebaseSessions (10.29.0): - FirebaseSessions (10.29.0):
- FirebaseCore (~> 10.5) - FirebaseCore (~> 10.5)
- FirebaseCoreExtension (~> 10.0) - FirebaseCoreExtension (~> 10.0)
@@ -70,31 +86,32 @@ PODS:
- GoogleUtilities/UserDefaults (~> 7.13) - GoogleUtilities/UserDefaults (~> 7.13)
- nanopb (< 2.30911.0, >= 2.30908.0) - nanopb (< 2.30911.0, >= 2.30908.0)
- PromisesSwift (~> 2.1) - PromisesSwift (~> 2.1)
- FirebaseSharedSwift (10.29.0)
- Flutter (1.0.0) - Flutter (1.0.0)
- flutter_localization (0.0.1): - flutter_localization (0.0.1):
- Flutter - Flutter
- flutter_secure_storage (6.0.0): - flutter_secure_storage (6.0.0):
- Flutter - Flutter
- GoogleAppMeasurement (10.20.0): - GoogleAppMeasurement (10.25.0):
- GoogleAppMeasurement/AdIdSupport (= 10.20.0) - GoogleAppMeasurement/AdIdSupport (= 10.25.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.11) - GoogleUtilities/AppDelegateSwizzler (~> 7.11)
- GoogleUtilities/MethodSwizzler (~> 7.11) - GoogleUtilities/MethodSwizzler (~> 7.11)
- GoogleUtilities/Network (~> 7.11) - GoogleUtilities/Network (~> 7.11)
- "GoogleUtilities/NSData+zlib (~> 7.11)" - "GoogleUtilities/NSData+zlib (~> 7.11)"
- nanopb (< 2.30910.0, >= 2.30908.0) - nanopb (< 2.30911.0, >= 2.30908.0)
- GoogleAppMeasurement/AdIdSupport (10.20.0): - GoogleAppMeasurement/AdIdSupport (10.25.0):
- GoogleAppMeasurement/WithoutAdIdSupport (= 10.20.0) - GoogleAppMeasurement/WithoutAdIdSupport (= 10.25.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.11) - GoogleUtilities/AppDelegateSwizzler (~> 7.11)
- GoogleUtilities/MethodSwizzler (~> 7.11) - GoogleUtilities/MethodSwizzler (~> 7.11)
- GoogleUtilities/Network (~> 7.11) - GoogleUtilities/Network (~> 7.11)
- "GoogleUtilities/NSData+zlib (~> 7.11)" - "GoogleUtilities/NSData+zlib (~> 7.11)"
- nanopb (< 2.30910.0, >= 2.30908.0) - nanopb (< 2.30911.0, >= 2.30908.0)
- GoogleAppMeasurement/WithoutAdIdSupport (10.20.0): - GoogleAppMeasurement/WithoutAdIdSupport (10.25.0):
- GoogleUtilities/AppDelegateSwizzler (~> 7.11) - GoogleUtilities/AppDelegateSwizzler (~> 7.11)
- GoogleUtilities/MethodSwizzler (~> 7.11) - GoogleUtilities/MethodSwizzler (~> 7.11)
- GoogleUtilities/Network (~> 7.11) - GoogleUtilities/Network (~> 7.11)
- "GoogleUtilities/NSData+zlib (~> 7.11)" - "GoogleUtilities/NSData+zlib (~> 7.11)"
- nanopb (< 2.30910.0, >= 2.30908.0) - nanopb (< 2.30911.0, >= 2.30908.0)
- GoogleDataTransport (9.4.1): - GoogleDataTransport (9.4.1):
- GoogleUtilities/Environment (~> 7.7) - GoogleUtilities/Environment (~> 7.7)
- nanopb (< 2.30911.0, >= 2.30908.0) - nanopb (< 2.30911.0, >= 2.30908.0)
@@ -129,11 +146,12 @@ PODS:
- GoogleUtilities/Privacy - GoogleUtilities/Privacy
- image_picker_ios (0.0.1): - image_picker_ios (0.0.1):
- Flutter - Flutter
- nanopb (2.30909.1): - leveldb-library (1.22.5)
- nanopb/decode (= 2.30909.1) - nanopb (2.30910.0):
- nanopb/encode (= 2.30909.1) - nanopb/decode (= 2.30910.0)
- nanopb/decode (2.30909.1) - nanopb/encode (= 2.30910.0)
- nanopb/encode (2.30909.1) - nanopb/decode (2.30910.0)
- nanopb/encode (2.30910.0)
- onesignal_flutter (5.2.0): - onesignal_flutter (5.2.0):
- Flutter - Flutter
- OneSignalXCFramework (= 5.2.0) - OneSignalXCFramework (= 5.2.0)
@@ -207,6 +225,7 @@ DEPENDENCIES:
- firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`) - firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`)
- firebase_core (from `.symlinks/plugins/firebase_core/ios`) - firebase_core (from `.symlinks/plugins/firebase_core/ios`)
- firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`) - firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`)
- firebase_database (from `.symlinks/plugins/firebase_database/ios`)
- Flutter (from `Flutter`) - Flutter (from `Flutter`)
- flutter_localization (from `.symlinks/plugins/flutter_localization/ios`) - flutter_localization (from `.symlinks/plugins/flutter_localization/ios`)
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
@@ -223,15 +242,20 @@ SPEC REPOS:
trunk: trunk:
- Firebase - Firebase
- FirebaseAnalytics - FirebaseAnalytics
- FirebaseAppCheckInterop
- FirebaseCore - FirebaseCore
- FirebaseCoreExtension - FirebaseCoreExtension
- FirebaseCoreInternal - FirebaseCoreInternal
- FirebaseCrashlytics - FirebaseCrashlytics
- FirebaseDatabase
- FirebaseInstallations - FirebaseInstallations
- FirebaseRemoteConfigInterop
- FirebaseSessions - FirebaseSessions
- FirebaseSharedSwift
- GoogleAppMeasurement - GoogleAppMeasurement
- GoogleDataTransport - GoogleDataTransport
- GoogleUtilities - GoogleUtilities
- leveldb-library
- nanopb - nanopb
- OneSignalXCFramework - OneSignalXCFramework
- PromisesObjC - PromisesObjC
@@ -246,6 +270,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/firebase_core/ios" :path: ".symlinks/plugins/firebase_core/ios"
firebase_crashlytics: firebase_crashlytics:
:path: ".symlinks/plugins/firebase_crashlytics/ios" :path: ".symlinks/plugins/firebase_crashlytics/ios"
firebase_database:
:path: ".symlinks/plugins/firebase_database/ios"
Flutter: Flutter:
:path: Flutter :path: Flutter
flutter_localization: flutter_localization:
@@ -271,25 +297,31 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS: SPEC CHECKSUMS:
device_info_plus: 97af1d7e84681a90d0693e63169a5d50e0839a0d device_info_plus: 97af1d7e84681a90d0693e63169a5d50e0839a0d
Firebase: 10c8cb12fb7ad2ae0c09ffc86cd9c1ab392a0031 Firebase: 0312a2352584f782ea56f66d91606891d4607f06
firebase_analytics: 2c1c3057d5da3bd3aab819f7e6ee153a4e46c59e firebase_analytics: 3a9263fedec72970e6bd30a7132bbdd386de2c14
firebase_core: c8628c7ce80f79439149549052bff22f6784fbf5 firebase_core: a626d00494efa398e7c54f25f1454a64c8abf197
firebase_crashlytics: 012078b4eec6fc9716f97ba3da0f0e44a04e95b1 firebase_crashlytics: 0b7cb41f5fb3b6889d0fb408cfce3cc7a4247061
FirebaseAnalytics: a2731bf3670747ce8f65368b118d18aa8e368246 firebase_database: 2713033e426b176d4fe5e7195f3d19aa1b549a91
FirebaseCore: 28045c1560a2600d284b9c45a904fe322dc890b6 FirebaseAnalytics: ec00fe8b93b41dc6fe4a28784b8e51da0647a248
FirebaseAppCheckInterop: 6a1757cfd4067d8e00fccd14fcc1b8fd78cfac07
FirebaseCore: 7ec4d0484817f12c3373955bc87762d96842d483
FirebaseCoreExtension: 705ca5b14bf71d2564a0ddc677df1fc86ffa600f FirebaseCoreExtension: 705ca5b14bf71d2564a0ddc677df1fc86ffa600f
FirebaseCoreInternal: df84dd300b561c27d5571684f389bf60b0a5c934 FirebaseCoreInternal: df84dd300b561c27d5571684f389bf60b0a5c934
FirebaseCrashlytics: 81530595edb6d99f1918f723a6c33766a24a4c86 FirebaseCrashlytics: 4b96efb0ce73b38b2a85e8b8bd1bd8f63f09d015
FirebaseDatabase: faa489a42f5f868d23a55dd442d6e2099348458e
FirebaseInstallations: 913cf60d0400ebd5d6b63a28b290372ab44590dd FirebaseInstallations: 913cf60d0400ebd5d6b63a28b290372ab44590dd
FirebaseRemoteConfigInterop: 6efda51fb5e2f15b16585197e26eaa09574e8a4d
FirebaseSessions: dbd14adac65ce996228652c1fc3a3f576bdf3ecc FirebaseSessions: dbd14adac65ce996228652c1fc3a3f576bdf3ecc
FirebaseSharedSwift: 20530f495084b8d840f78a100d8c5ee613375f6e
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_localization: f43b18844a2b3d2c71fd64f04ffd6b1e64dd54d4 flutter_localization: f43b18844a2b3d2c71fd64f04ffd6b1e64dd54d4
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
GoogleAppMeasurement: bb3c564c3efb933136af0e94899e0a46167466a8 GoogleAppMeasurement: 9abf64b682732fed36da827aa2a68f0221fd2356
GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a
GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15 GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15
image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1 image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1
nanopb: d4d75c12cd1316f4a64e3c6963f879ecd4b5e0d5 leveldb-library: e8eadf9008a61f9e1dde3978c086d2b6d9b9dc28
nanopb: 438bc412db1928dac798aa6fd75726007be04262
onesignal_flutter: 5ce68a29861960168e81101cb1bd685d264361de onesignal_flutter: 5ce68a29861960168e81101cb1bd685d264361de
OneSignalXCFramework: bdf74fdc06888f9466dc21e826fe1549ed143095 OneSignalXCFramework: bdf74fdc06888f9466dc21e826fe1549ed143095
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
@@ -1,5 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart'; import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart'; import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart';
@@ -40,6 +40,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
on<ChangeAllSwitch>(_changeAllAcSwitch); on<ChangeAllSwitch>(_changeAllAcSwitch);
on<IncreaseAllTemp>(_increaseAllTemp); on<IncreaseAllTemp>(_increaseAllTemp);
on<DecreaseAllTemp>(_decreaseAllTemp); on<DecreaseAllTemp>(_decreaseAllTemp);
on<AcUpdated>(_onAcUpdated);
} }
void _fetchAcsStatus(AcsInitial event, Emitter<AcsState> emit) async { void _fetchAcsStatus(AcsInitial event, Emitter<AcsState> emit) async {
@@ -62,6 +63,8 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
} }
deviceStatus = AcStatusModel.fromJson(response['productUuid'], statusModelList); deviceStatus = AcStatusModel.fromJson(response['productUuid'], statusModelList);
emit(GetAcStatusState(acStatusModel: deviceStatus)); emit(GetAcStatusState(acStatusModel: deviceStatus));
Future.delayed(const Duration(milliseconds: 500));
_listenToChanges();
} }
} catch (e) { } catch (e) {
emit(AcsFailedState(errorMessage: e.toString())); emit(AcsFailedState(errorMessage: e.toString()));
@@ -69,6 +72,29 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
} }
} }
_listenToChanges() {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$acId');
Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) {
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: element['value']));
});
deviceStatus = AcStatusModel.fromJson(usersMap['productUuid'], statusList);
add(AcUpdated());
});
} catch (_) {}
}
_onAcUpdated(AcUpdated event, Emitter<AcsState> emit) {
emit(GetAcStatusState(acStatusModel: deviceStatus));
}
_getAllAcs() async { _getAllAcs() async {
deviceStatusList = []; deviceStatusList = [];
devicesList = []; devicesList = [];
@@ -164,7 +190,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
deviceStatus.childLock = lockValue; deviceStatus.childLock = lockValue;
emit(AcModifyingState(acStatusModel: deviceStatus)); emit(AcModifyingState(acStatusModel: deviceStatus));
_runDeBouncerForOneDevice(deviceId: acId, code: 'child_lock', value: lockValue); await _runDeBouncerForOneDevice(deviceId: acId, code: 'child_lock', value: lockValue);
} }
void _increaseCoolTo(IncreaseCoolToTemp event, Emitter<AcsState> emit) async { void _increaseCoolTo(IncreaseCoolToTemp event, Emitter<AcsState> emit) async {
@@ -20,6 +20,8 @@ class AcSwitch extends AcsEvent {
List<Object> get props => [acSwitch, deviceId, productId]; List<Object> get props => [acSwitch, deviceId, productId];
} }
class AcUpdated extends AcsEvent {}
class AcsInitial extends AcsEvent { class AcsInitial extends AcsEvent {
final bool allAcs; final bool allAcs;
const AcsInitial({required this.allAcs}); const AcsInitial({required this.allAcs});
@@ -1,3 +1,4 @@
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/ceiling_bloc/ceiling_sensor_event.dart'; import 'package:syncrow_app/features/devices/bloc/ceiling_bloc/ceiling_sensor_event.dart';
import 'package:syncrow_app/features/devices/bloc/ceiling_bloc/ceiling_sensor_state.dart'; import 'package:syncrow_app/features/devices/bloc/ceiling_bloc/ceiling_sensor_state.dart';
@@ -15,6 +16,7 @@ class CeilingSensorBloc extends Bloc<CeilingSensorEvent, CeilingSensorState> {
CeilingSensorBloc({required this.deviceId}) : super(InitialState()) { CeilingSensorBloc({required this.deviceId}) : super(InitialState()) {
on<InitialEvent>(_fetchCeilingSensorStatus); on<InitialEvent>(_fetchCeilingSensorStatus);
on<ChangeValueEvent>(_changeValue); on<ChangeValueEvent>(_changeValue);
on<CeilingSensorUpdated>(_onCeilingSensorUpdated);
} }
void _fetchCeilingSensorStatus(InitialEvent event, Emitter<CeilingSensorState> emit) async { void _fetchCeilingSensorStatus(InitialEvent event, Emitter<CeilingSensorState> emit) async {
@@ -27,12 +29,36 @@ class CeilingSensorBloc extends Bloc<CeilingSensorEvent, CeilingSensorState> {
} }
deviceStatus = CeilingSensorModel.fromJson(statusModelList); deviceStatus = CeilingSensorModel.fromJson(statusModelList);
emit(UpdateState(ceilingSensorModel: deviceStatus)); emit(UpdateState(ceilingSensorModel: deviceStatus));
_listenToChanges();
} catch (e) { } catch (e) {
emit(FailedState(error: e.toString())); emit(FailedState(error: e.toString()));
return; return;
} }
} }
_listenToChanges() {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$deviceId');
Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) {
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: element['value']));
});
deviceStatus = CeilingSensorModel.fromJson(statusList);
add(CeilingSensorUpdated());
});
} catch (_) {}
}
_onCeilingSensorUpdated(CeilingSensorUpdated event, Emitter<CeilingSensorState> emit) {
emit(UpdateState(ceilingSensorModel: deviceStatus));
}
void _changeValue(ChangeValueEvent event, Emitter<CeilingSensorState> emit) async { void _changeValue(ChangeValueEvent event, Emitter<CeilingSensorState> emit) async {
emit(LoadingNewSate(ceilingSensorModel: deviceStatus)); emit(LoadingNewSate(ceilingSensorModel: deviceStatus));
try { try {
@@ -11,6 +11,8 @@ class LoadingEvent extends CeilingSensorEvent {}
class InitialEvent extends CeilingSensorEvent {} class InitialEvent extends CeilingSensorEvent {}
class CeilingSensorUpdated extends CeilingSensorEvent {}
class ChangeValueEvent extends CeilingSensorEvent { class ChangeValueEvent extends CeilingSensorEvent {
final int value; final int value;
final String code; final String code;
@@ -1,5 +1,5 @@
import 'dart:math'; import 'dart:math';
import 'package:flutter/cupertino.dart'; import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
@@ -25,6 +25,7 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
SmartDoorBloc({required this.deviceId}) : super(InitialState()) { SmartDoorBloc({required this.deviceId}) : super(InitialState()) {
on<InitialEvent>(_fetchSmartDoorStatus); on<InitialEvent>(_fetchSmartDoorStatus);
on<DoorLockUpdated>(_doorLockUpdated);
on<InitialPasswordsPage>(getTemporaryPasswords); on<InitialPasswordsPage>(getTemporaryPasswords);
on<InitialOneTimePassword>(getOneTimePasswords); on<InitialOneTimePassword>(getOneTimePasswords);
on<InitialTimeLimitPassword>(getTimeLimitPasswords); on<InitialTimeLimitPassword>(getTimeLimitPasswords);
@@ -69,23 +70,24 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
return passwordController.text; return passwordController.text;
} }
Future generateAndSavePasswordOneTime (GenerateAndSavePasswordOneTimeEvent event, Emitter<SmartDoorState> emit) async { Future generateAndSavePasswordOneTime(
GenerateAndSavePasswordOneTimeEvent event, Emitter<SmartDoorState> emit) async {
try { try {
if (isSavingPassword) return; if (isSavingPassword) return;
isSavingPassword = true; isSavingPassword = true;
emit(LoadingInitialState()); emit(LoadingInitialState());
var res = await DevicesAPI.generateOneTimePassword(deviceId: deviceId); var res = await DevicesAPI.generateOneTimePassword(deviceId: deviceId);
ApiResponse pass= ApiResponse.fromJson(res); ApiResponse pass = ApiResponse.fromJson(res);
passwordController.text =pass.data.offlineTempPassword; passwordController.text = pass.data.offlineTempPassword;
passwordId=pass.data.offlineTempPasswordId; passwordId = pass.data.offlineTempPasswordId;
Future.delayed(const Duration(seconds: 1), () { Future.delayed(const Duration(seconds: 1), () {
Clipboard.setData(ClipboardData(text: passwordController.text)); Clipboard.setData(ClipboardData(text: passwordController.text));
}); });
emit(const GeneratePasswordOneTimestate(generated: true)); emit(const GeneratePasswordOneTimestate(generated: true));
} catch (_) { } catch (_) {
emit(FailedState(errorMessage: _.toString())); emit(FailedState(errorMessage: _.toString()));
}finally { } finally {
isSavingPassword = false; isSavingPassword = false;
} }
} }
@@ -100,20 +102,41 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
} }
deviceStatus = SmartDoorModel.fromJson(statusModelList); deviceStatus = SmartDoorModel.fromJson(statusModelList);
emit(UpdateState(smartDoorModel: deviceStatus)); emit(UpdateState(smartDoorModel: deviceStatus));
_listenToChanges();
} catch (e) { } catch (e) {
emit(FailedState(errorMessage: e.toString())); emit(FailedState(errorMessage: e.toString()));
return; return;
} }
} }
_listenToChanges() {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$deviceId');
Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) {
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: element['value']));
});
deviceStatus = SmartDoorModel.fromJson(statusList);
add(DoorLockUpdated());
});
} catch (_) {}
}
_doorLockUpdated(DoorLockUpdated event, Emitter<SmartDoorState> emit) {
emit(UpdateState(smartDoorModel: deviceStatus));
}
void _renamePassword(RenamePasswordEvent event, Emitter<SmartDoorState> emit) async { void _renamePassword(RenamePasswordEvent event, Emitter<SmartDoorState> emit) async {
try { try {
emit(LoadingInitialState()); emit(LoadingInitialState());
var response = await DevicesAPI.renamePass( await DevicesAPI.renamePass(
name:passwordNameController.text , name: passwordNameController.text, doorLockUuid: deviceId, passwordId: passwordId);
doorLockUuid:deviceId ,
passwordId:passwordId
);
add(InitialOneTimePassword()); add(InitialOneTimePassword());
add(InitialTimeLimitPassword()); add(InitialTimeLimitPassword());
emit(UpdateState(smartDoorModel: deviceStatus)); emit(UpdateState(smartDoorModel: deviceStatus));
@@ -126,11 +149,14 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
void getTemporaryPasswords(InitialPasswordsPage event, Emitter<SmartDoorState> emit) async { void getTemporaryPasswords(InitialPasswordsPage event, Emitter<SmartDoorState> emit) async {
try { try {
emit(LoadingInitialState()); emit(LoadingInitialState());
var response = await DevicesAPI.getTemporaryPasswords(deviceId, ); var response = await DevicesAPI.getTemporaryPasswords(
deviceId,
);
if (response is List) { if (response is List) {
temporaryPasswords = response.map((item) => TemporaryPassword.fromJson(item)).toList(); temporaryPasswords = response.map((item) => TemporaryPassword.fromJson(item)).toList();
} else if (response is Map && response.containsKey('data')) { } else if (response is Map && response.containsKey('data')) {
temporaryPasswords = (response['data'] as List).map((item) => TemporaryPassword.fromJson(item)).toList(); temporaryPasswords =
(response['data'] as List).map((item) => TemporaryPassword.fromJson(item)).toList();
} }
emit(TemporaryPasswordsLoadedState(temporaryPassword: temporaryPasswords!)); emit(TemporaryPasswordsLoadedState(temporaryPassword: temporaryPasswords!));
} catch (e) { } catch (e) {
@@ -183,7 +209,7 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
bool setStartEndTime(SetStartEndTimeEvent event, Emitter<SmartDoorState> emit) { bool setStartEndTime(SetStartEndTimeEvent event, Emitter<SmartDoorState> emit) {
emit(LoadingInitialState()); emit(LoadingInitialState());
isStartEndTime = event.val; isStartEndTime = event.val;
emit(IsStartEndState(isStartEndTime:isStartEndTime)); emit(IsStartEndState(isStartEndTime: isStartEndTime));
return isStartEndTime; return isStartEndTime;
} }
@@ -201,7 +227,6 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
emit(UpdateState(smartDoorModel: deviceStatus)); emit(UpdateState(smartDoorModel: deviceStatus));
} }
Future<void> selectTimeOfLinePassword(SelectTimeEvent event, Emitter<SmartDoorState> emit) async { Future<void> selectTimeOfLinePassword(SelectTimeEvent event, Emitter<SmartDoorState> emit) async {
emit(ChangeTimeState()); emit(ChangeTimeState());
final DateTime? picked = await showDatePicker( final DateTime? picked = await showDatePicker(
@@ -224,24 +249,28 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
0, 0,
); );
final selectedTimestamp = DateTime( final selectedTimestamp = DateTime(
selectedDateTime.year, selectedDateTime.year,
selectedDateTime.month, selectedDateTime.month,
selectedDateTime.day, selectedDateTime.day,
selectedDateTime.hour, selectedDateTime.hour,
selectedDateTime.minute, selectedDateTime.minute,
).millisecondsSinceEpoch ~/ 1000; // Divide by 1000 to remove milliseconds ).millisecondsSinceEpoch ~/
1000; // Divide by 1000 to remove milliseconds
if (event.isEffective) { if (event.isEffective) {
if (expirationTimeTimeStamp != null && selectedTimestamp > expirationTimeTimeStamp!) { if (expirationTimeTimeStamp != null && selectedTimestamp > expirationTimeTimeStamp!) {
CustomSnackBar.displaySnackBar('Effective Time cannot be later than Expiration Time.'); CustomSnackBar.displaySnackBar('Effective Time cannot be later than Expiration Time.');
} else { } else {
effectiveTime = selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds effectiveTime =
selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds
effectiveTimeTimeStamp = selectedTimestamp; effectiveTimeTimeStamp = selectedTimestamp;
} }
} else { } else {
if (effectiveTimeTimeStamp != null && selectedTimestamp < effectiveTimeTimeStamp!) { if (effectiveTimeTimeStamp != null && selectedTimestamp < effectiveTimeTimeStamp!) {
CustomSnackBar.displaySnackBar('Expiration Time cannot be earlier than Effective Time.'); CustomSnackBar.displaySnackBar(
'Expiration Time cannot be earlier than Effective Time.');
} else { } else {
expirationTime = selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds expirationTime =
selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds
expirationTimeTimeStamp = selectedTimestamp; expirationTimeTimeStamp = selectedTimestamp;
} }
} }
@@ -250,7 +279,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
} }
} }
Future<void> selectTimeOnlinePassword(SelectTimeOnlinePasswordEvent event, Emitter<SmartDoorState> emit) async { Future<void> selectTimeOnlinePassword(
SelectTimeOnlinePasswordEvent event, Emitter<SmartDoorState> emit) async {
emit(ChangeTimeState()); emit(ChangeTimeState());
final DateTime? picked = await showDatePicker( final DateTime? picked = await showDatePicker(
context: event.context, context: event.context,
@@ -288,12 +318,12 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
timePicked.minute, timePicked.minute,
); );
final selectedTimestamp = DateTime( final selectedTimestamp = DateTime(
selectedDateTime.year, selectedDateTime.year,
selectedDateTime.month, selectedDateTime.month,
selectedDateTime.day, selectedDateTime.day,
selectedDateTime.hour, selectedDateTime.hour,
selectedDateTime.minute, selectedDateTime.minute,
).millisecondsSinceEpoch ~/ ).millisecondsSinceEpoch ~/
1000; // Divide by 1000 to remove milliseconds 1000; // Divide by 1000 to remove milliseconds
if (event.isEffective) { if (event.isEffective) {
if (expirationTimeTimeStamp != null && selectedTimestamp > expirationTimeTimeStamp!) { if (expirationTimeTimeStamp != null && selectedTimestamp > expirationTimeTimeStamp!) {
@@ -305,7 +335,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
} }
} else { } else {
if (effectiveTimeTimeStamp != null && selectedTimestamp < effectiveTimeTimeStamp!) { if (effectiveTimeTimeStamp != null && selectedTimestamp < effectiveTimeTimeStamp!) {
CustomSnackBar.displaySnackBar('Expiration Time cannot be earlier than Effective Time.'); CustomSnackBar.displaySnackBar(
'Expiration Time cannot be earlier than Effective Time.');
} else { } else {
expirationTime = expirationTime =
selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds
@@ -341,25 +372,25 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
CustomSnackBar.displaySnackBar('Save Successfully'); CustomSnackBar.displaySnackBar('Save Successfully');
emit(SaveState()); emit(SaveState());
} catch (_) { } catch (_) {
} finally {
}finally {
isSavingPassword = false; isSavingPassword = false;
} }
} }
Future<void> generateAndSavePasswordTimeLimited (GenerateAndSavePasswordTimeLimitEvent event, Emitter<SmartDoorState> emit) async { Future<void> generateAndSavePasswordTimeLimited(
GenerateAndSavePasswordTimeLimitEvent event, Emitter<SmartDoorState> emit) async {
if (timeLimitValidate() || isSavingPassword) return; if (timeLimitValidate() || isSavingPassword) return;
try { try {
isSavingPassword = true; isSavingPassword = true;
emit(LoadingInitialState()); emit(LoadingInitialState());
var res = await DevicesAPI.generateMultiTimePassword( var res = await DevicesAPI.generateMultiTimePassword(
deviceId: deviceId, deviceId: deviceId,
effectiveTime: effectiveTimeTimeStamp.toString(), effectiveTime: effectiveTimeTimeStamp.toString(),
invalidTime: expirationTimeTimeStamp.toString(), invalidTime: expirationTimeTimeStamp.toString(),
); );
ApiResponse pass= ApiResponse.fromJson(res); ApiResponse pass = ApiResponse.fromJson(res);
passwordController.text =pass.data.offlineTempPassword; passwordController.text = pass.data.offlineTempPassword;
passwordId=pass.data.offlineTempPasswordId; passwordId = pass.data.offlineTempPasswordId;
CustomSnackBar.displaySnackBar('Save Successfully'); CustomSnackBar.displaySnackBar('Save Successfully');
add(InitialTimeLimitPassword()); add(InitialTimeLimitPassword());
Future.delayed(const Duration(seconds: 1), () { Future.delayed(const Duration(seconds: 1), () {
@@ -368,8 +399,7 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
emit(const GeneratePasswordOneTimestate(generated: true)); emit(const GeneratePasswordOneTimestate(generated: true));
} catch (_) { } catch (_) {
add(InitialPasswordsPage()); add(InitialPasswordsPage());
} } finally {
finally {
isSavingPassword = false; isSavingPassword = false;
} }
} }
@@ -378,8 +408,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
try { try {
emit(LoadingInitialState()); emit(LoadingInitialState());
var response = var response =
await DevicesAPI.deletePassword(deviceId: deviceId, passwordId: event.passwordId) await DevicesAPI.deletePassword(deviceId: deviceId, passwordId: event.passwordId)
.then((value) async { .then((value) async {
add(InitialPasswordsPage()); add(InitialPasswordsPage());
}); });
} catch (e) { } catch (e) {
@@ -388,7 +418,7 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
} }
bool _validateInputs() { bool _validateInputs() {
if (passwordController.text.length < 7 ) { if (passwordController.text.length < 7) {
CustomSnackBar.displaySnackBar('Password less than 7'); CustomSnackBar.displaySnackBar('Password less than 7');
return true; return true;
} }
@@ -397,7 +427,7 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
CustomSnackBar.displaySnackBar('Password required'); CustomSnackBar.displaySnackBar('Password required');
return true; return true;
} }
if (passwordNameController.text.isEmpty ) { if (passwordNameController.text.isEmpty) {
CustomSnackBar.displaySnackBar('Password name required'); CustomSnackBar.displaySnackBar('Password name required');
return true; return true;
} }
@@ -420,7 +450,6 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
} }
bool timeLimitValidate() { bool timeLimitValidate() {
if (effectiveTime == 'Select Time' || effectiveTimeTimeStamp == null) { if (effectiveTime == 'Select Time' || effectiveTimeTimeStamp == null) {
CustomSnackBar.displaySnackBar('Select effective time'); CustomSnackBar.displaySnackBar('Select effective time');
return true; return true;
@@ -444,7 +473,10 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
List<String> selectedDays = []; List<String> selectedDays = [];
Future<void> toggleDaySelection(ToggleDaySelectionEvent event, Emitter<SmartDoorState> emit,)async { Future<void> toggleDaySelection(
ToggleDaySelectionEvent event,
Emitter<SmartDoorState> emit,
) async {
emit(LoadingInitialState()); emit(LoadingInitialState());
if (selectedDays.contains(event.key)) { if (selectedDays.contains(event.key)) {
selectedDays.remove(event.key); selectedDays.remove(event.key);
@@ -459,8 +491,3 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
return DateFormat('HH:mm').format(dateTime); return DateFormat('HH:mm').format(dateTime);
} }
} }
@@ -9,10 +9,15 @@ abstract class SmartDoorEvent extends Equatable {
} }
class InitialEvent extends SmartDoorEvent {} class InitialEvent extends SmartDoorEvent {}
class InitialPasswordsPage extends SmartDoorEvent {} class InitialPasswordsPage extends SmartDoorEvent {}
class InitialOneTimePassword extends SmartDoorEvent {} class InitialOneTimePassword extends SmartDoorEvent {}
class InitialTimeLimitPassword extends SmartDoorEvent {} class InitialTimeLimitPassword extends SmartDoorEvent {}
class DoorLockUpdated extends SmartDoorEvent {}
class UpdateLockEvent extends SmartDoorEvent { class UpdateLockEvent extends SmartDoorEvent {
final bool value; final bool value;
const UpdateLockEvent({required this.value}); const UpdateLockEvent({required this.value});
@@ -26,6 +31,7 @@ class SavePasswordEvent extends SmartDoorEvent {
@override @override
List<Object> get props => [context]; List<Object> get props => [context];
} }
class GenerateAndSavePasswordTimeLimitEvent extends SmartDoorEvent { class GenerateAndSavePasswordTimeLimitEvent extends SmartDoorEvent {
final BuildContext context; final BuildContext context;
const GenerateAndSavePasswordTimeLimitEvent({required this.context}); const GenerateAndSavePasswordTimeLimitEvent({required this.context});
@@ -40,28 +46,26 @@ class GenerateAndSavePasswordOneTimeEvent extends SmartDoorEvent {
List<Object> get props => [context]; List<Object> get props => [context];
} }
class GeneratePasswordEvent extends SmartDoorEvent { class GeneratePasswordEvent extends SmartDoorEvent {}
}
class SelectTimeEvent extends SmartDoorEvent { class SelectTimeEvent extends SmartDoorEvent {
final BuildContext context; final BuildContext context;
final bool isEffective; final bool isEffective;
const SelectTimeEvent({required this.context,required this.isEffective}); const SelectTimeEvent({required this.context, required this.isEffective});
@override @override
List<Object> get props => [context,isEffective]; List<Object> get props => [context, isEffective];
} }
class SelectTimeOnlinePasswordEvent extends SmartDoorEvent { class SelectTimeOnlinePasswordEvent extends SmartDoorEvent {
final BuildContext context; final BuildContext context;
final bool isEffective; final bool isEffective;
const SelectTimeOnlinePasswordEvent({required this.context,required this.isEffective}); const SelectTimeOnlinePasswordEvent({required this.context, required this.isEffective});
@override @override
List<Object> get props => [context,isEffective]; List<Object> get props => [context, isEffective];
} }
class ToggleRepeatEvent extends SmartDoorEvent {} class ToggleRepeatEvent extends SmartDoorEvent {}
class SetStartEndTimeEvent extends SmartDoorEvent { class SetStartEndTimeEvent extends SmartDoorEvent {
final bool val; final bool val;
const SetStartEndTimeEvent({required this.val}); const SetStartEndTimeEvent({required this.val});
@@ -70,7 +74,7 @@ class SetStartEndTimeEvent extends SmartDoorEvent {
} }
class DeletePasswordEvent extends SmartDoorEvent { class DeletePasswordEvent extends SmartDoorEvent {
final String passwordId; final String passwordId;
const DeletePasswordEvent({required this.passwordId}); const DeletePasswordEvent({required this.passwordId});
@override @override
@@ -78,7 +82,7 @@ class DeletePasswordEvent extends SmartDoorEvent {
} }
class ToggleDaySelectionEvent extends SmartDoorEvent { class ToggleDaySelectionEvent extends SmartDoorEvent {
final String key; final String key;
const ToggleDaySelectionEvent({required this.key}); const ToggleDaySelectionEvent({required this.key});
@override @override
@@ -89,12 +93,9 @@ class ChangeTimeEvent extends SmartDoorEvent {
final dynamic val; final dynamic val;
final bool isStartEndTime; final bool isStartEndTime;
const ChangeTimeEvent({required this.val,required this.isStartEndTime}); const ChangeTimeEvent({required this.val, required this.isStartEndTime});
@override @override
List<Object> get props => [val,isStartEndTime]; List<Object> get props => [val, isStartEndTime];
} }
class RenamePasswordEvent extends SmartDoorEvent { class RenamePasswordEvent extends SmartDoorEvent {}
}
@@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart'; import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_event.dart'; import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_event.dart';
@@ -20,6 +21,10 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
secondCountDown: 0, secondCountDown: 0,
thirdCountDown: 0); thirdCountDown: 0);
Timer? _timer; Timer? _timer;
// Timer? _firstSwitchTimer;
// Timer? _secondSwitchTimer;
// Timer? _thirdSwitchTimer;
bool threeGangGroup = false; bool threeGangGroup = false;
List<DeviceModel> devicesList = []; List<DeviceModel> devicesList = [];
List<GroupThreeGangModel> groupThreeGangList = []; List<GroupThreeGangModel> groupThreeGangList = [];
@@ -27,6 +32,7 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
ThreeGangBloc({required this.threeGangId}) : super(InitialState()) { ThreeGangBloc({required this.threeGangId}) : super(InitialState()) {
on<InitialEvent>(_fetchThreeGangStatus); on<InitialEvent>(_fetchThreeGangStatus);
on<ThreeGangUpdated>(_threeGangUpdated);
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch); on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
on<ChangeSecondSwitchStatusEvent>(_changeSecondSwitch); on<ChangeSecondSwitchStatusEvent>(_changeSecondSwitch);
on<ChangeThirdSwitchStatusEvent>(_changeThirdSwitch); on<ChangeThirdSwitchStatusEvent>(_changeThirdSwitch);
@@ -85,6 +91,7 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
} }
deviceStatus = ThreeGangModel.fromJson(statusModelList); deviceStatus = ThreeGangModel.fromJson(statusModelList);
emit(UpdateState(threeGangModel: deviceStatus)); emit(UpdateState(threeGangModel: deviceStatus));
_listenToChanges();
} }
} catch (e) { } catch (e) {
emit(FailedState(error: e.toString())); emit(FailedState(error: e.toString()));
@@ -92,6 +99,34 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
} }
} }
_listenToChanges() {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$threeGangId');
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: element['value']));
});
deviceStatus = ThreeGangModel.fromJson(statusList);
if (!isClosed) {
add(ThreeGangUpdated());
}
});
} catch (_) {}
}
_threeGangUpdated(ThreeGangUpdated event, Emitter<ThreeGangState> emit) {
emit(UpdateState(threeGangModel: deviceStatus));
}
void _changeFirstSwitch(ChangeFirstSwitchStatusEvent event, Emitter<ThreeGangState> emit) async { void _changeFirstSwitch(ChangeFirstSwitchStatusEvent event, Emitter<ThreeGangState> emit) async {
emit(LoadingNewSate(threeGangModel: deviceStatus)); emit(LoadingNewSate(threeGangModel: deviceStatus));
try { try {
@@ -111,16 +146,22 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
emit(UpdateState(threeGangModel: deviceStatus)); emit(UpdateState(threeGangModel: deviceStatus));
} }
final response = await DevicesAPI.controlDevice( if (_timer != null) {
DeviceControlModel( _timer!.cancel();
deviceId: threeGangGroup ? event.deviceId : threeGangId,
code: 'switch_1',
value: !event.value),
threeGangGroup ? event.deviceId : threeGangId);
if (!response['success']) {
add(InitialEvent(groupScreen: threeGangGroup));
} }
_timer = Timer(const Duration(milliseconds: 500), () async {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeGangGroup ? event.deviceId : threeGangId,
code: 'switch_1',
value: !event.value),
threeGangGroup ? event.deviceId : threeGangId);
if (!response['success']) {
add(InitialEvent(groupScreen: threeGangGroup));
}
});
} catch (_) { } catch (_) {
add(InitialEvent(groupScreen: threeGangGroup)); add(InitialEvent(groupScreen: threeGangGroup));
} }
@@ -146,16 +187,22 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
emit(UpdateState(threeGangModel: deviceStatus)); emit(UpdateState(threeGangModel: deviceStatus));
} }
final response = await DevicesAPI.controlDevice( if (_timer != null) {
DeviceControlModel( _timer!.cancel();
deviceId: threeGangGroup ? event.deviceId : threeGangId,
code: 'switch_2',
value: !event.value),
threeGangGroup ? event.deviceId : threeGangId);
if (!response['success']) {
add(InitialEvent(groupScreen: threeGangGroup));
} }
_timer = Timer(const Duration(milliseconds: 500), () async {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeGangGroup ? event.deviceId : threeGangId,
code: 'switch_2',
value: !event.value),
threeGangGroup ? event.deviceId : threeGangId);
if (!response['success']) {
add(InitialEvent(groupScreen: threeGangGroup));
}
});
} catch (_) { } catch (_) {
add(InitialEvent(groupScreen: threeGangGroup)); add(InitialEvent(groupScreen: threeGangGroup));
} }
@@ -180,16 +227,22 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
emit(UpdateState(threeGangModel: deviceStatus)); emit(UpdateState(threeGangModel: deviceStatus));
} }
final response = await DevicesAPI.controlDevice( if (_timer != null) {
DeviceControlModel( _timer!.cancel();
deviceId: threeGangGroup ? event.deviceId : threeGangId,
code: 'switch_3',
value: !event.value),
threeGangGroup ? event.deviceId : threeGangId);
if (!response['success']) {
add(InitialEvent(groupScreen: threeGangGroup));
} }
_timer = Timer(const Duration(milliseconds: 500), () async {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeGangGroup ? event.deviceId : threeGangId,
code: 'switch_3',
value: !event.value),
threeGangGroup ? event.deviceId : threeGangId);
if (!response['success']) {
add(InitialEvent(groupScreen: threeGangGroup));
}
});
} catch (_) { } catch (_) {
add(InitialEvent(groupScreen: threeGangGroup)); add(InitialEvent(groupScreen: threeGangGroup));
} }
@@ -407,6 +460,9 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
void _onClose(OnClose event, Emitter<ThreeGangState> emit) { void _onClose(OnClose event, Emitter<ThreeGangState> emit) {
_timer?.cancel(); _timer?.cancel();
// _firstSwitchTimer?.cancel();
// _secondSwitchTimer?.cancel();
// _thirdSwitchTimer?.cancel();
} }
void _onStartTimer(int seconds) { void _onStartTimer(int seconds) {
@@ -9,6 +9,8 @@ abstract class ThreeGangEvent extends Equatable {
class LoadingEvent extends ThreeGangEvent {} class LoadingEvent extends ThreeGangEvent {}
class ThreeGangUpdated extends ThreeGangEvent {}
class InitialEvent extends ThreeGangEvent { class InitialEvent extends ThreeGangEvent {
final bool groupScreen; final bool groupScreen;
const InitialEvent({required this.groupScreen}); const InitialEvent({required this.groupScreen});
@@ -1,3 +1,4 @@
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_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_state.dart';
import 'package:syncrow_app/features/devices/bloc/wall_sensor_bloc/wall_sensor_event.dart'; import 'package:syncrow_app/features/devices/bloc/wall_sensor_bloc/wall_sensor_event.dart';
@@ -16,6 +17,7 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
on<InitialEvent>(_fetchCeilingSensorStatus); on<InitialEvent>(_fetchCeilingSensorStatus);
on<ChangeIndicatorEvent>(_changeIndicator); on<ChangeIndicatorEvent>(_changeIndicator);
on<ChangeValueEvent>(_changeValue); on<ChangeValueEvent>(_changeValue);
on<WallSensorUpdatedEvent>(_wallSensorUpdated);
} }
void _fetchCeilingSensorStatus(InitialEvent event, Emitter<WallSensorState> emit) async { void _fetchCeilingSensorStatus(InitialEvent event, Emitter<WallSensorState> emit) async {
@@ -28,12 +30,36 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
} }
deviceStatus = WallSensorModel.fromJson(statusModelList); deviceStatus = WallSensorModel.fromJson(statusModelList);
emit(UpdateState(wallSensorModel: deviceStatus)); emit(UpdateState(wallSensorModel: deviceStatus));
_listenToChanges();
} catch (e) { } catch (e) {
emit(FailedState(error: e.toString())); emit(FailedState(error: e.toString()));
return; return;
} }
} }
_listenToChanges() {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$deviceId');
Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) {
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: element['value']));
});
deviceStatus = WallSensorModel.fromJson(statusList);
add(WallSensorUpdatedEvent());
});
} catch (_) {}
}
_wallSensorUpdated(WallSensorUpdatedEvent event, Emitter<WallSensorState> emit) {
emit(UpdateState(wallSensorModel: deviceStatus));
}
void _changeIndicator(ChangeIndicatorEvent event, Emitter<WallSensorState> emit) async { void _changeIndicator(ChangeIndicatorEvent event, Emitter<WallSensorState> emit) async {
emit(LoadingNewSate(wallSensorModel: deviceStatus)); emit(LoadingNewSate(wallSensorModel: deviceStatus));
try { try {
@@ -11,6 +11,8 @@ class LoadingEvent extends WallSensorEvent {}
class InitialEvent extends WallSensorEvent {} class InitialEvent extends WallSensorEvent {}
class WallSensorUpdatedEvent extends WallSensorEvent {}
class ChangeIndicatorEvent extends WallSensorEvent { class ChangeIndicatorEvent extends WallSensorEvent {
final bool value; final bool value;
const ChangeIndicatorEvent({required this.value}); const ChangeIndicatorEvent({required this.value});
@@ -4,17 +4,25 @@ class CeilingSensorModel {
String presenceState; String presenceState;
int sensitivity; int sensitivity;
String checkingResult; String checkingResult;
int presenceRange;
int sportsPara;
String bodyMovement;
CeilingSensorModel({ CeilingSensorModel(
required this.presenceState, {required this.presenceState,
required this.sensitivity, required this.sensitivity,
required this.checkingResult, required this.checkingResult,
}); required this.presenceRange,
required this.sportsPara,
required this.bodyMovement});
factory CeilingSensorModel.fromJson(List<StatusModel> jsonList) { factory CeilingSensorModel.fromJson(List<StatusModel> jsonList) {
late String _presenceState; late String _presenceState;
late int _sensitivity; late int _sensitivity;
late String _checkingResult; late String _checkingResult;
int _presenceRange = 1;
int _sportsPara = 1;
String _bodyMovement = 'none';
for (int i = 0; i < jsonList.length; i++) { for (int i = 0; i < jsonList.length; i++) {
if (jsonList[i].code == 'presence_state') { if (jsonList[i].code == 'presence_state') {
@@ -23,9 +31,20 @@ class CeilingSensorModel {
_sensitivity = jsonList[i].value ?? false; _sensitivity = jsonList[i].value ?? false;
} else if (jsonList[i].code == 'checking_result') { } else if (jsonList[i].code == 'checking_result') {
_checkingResult = jsonList[i].value ?? false; _checkingResult = jsonList[i].value ?? false;
} else if (jsonList[i].code == 'presence_range') {
_presenceRange = jsonList[i].value ?? false;
} else if (jsonList[i].code == 'sports_para') {
_sportsPara = jsonList[i].value ?? false;
} else if (jsonList[i].code == 'body_movement') {
_bodyMovement = jsonList[i].value ?? false;
} }
} }
return CeilingSensorModel( return CeilingSensorModel(
presenceState: _presenceState, sensitivity: _sensitivity, checkingResult: _checkingResult); presenceState: _presenceState,
sensitivity: _sensitivity,
checkingResult: _checkingResult,
presenceRange: _presenceRange,
sportsPara: _sportsPara,
bodyMovement: _bodyMovement);
} }
} }
@@ -34,8 +34,13 @@ class CeilingSensorInterface extends StatelessWidget {
create: (context) => create: (context) =>
CeilingSensorBloc(deviceId: ceilingSensor.uuid ?? '')..add(InitialEvent()), CeilingSensorBloc(deviceId: ceilingSensor.uuid ?? '')..add(InitialEvent()),
child: BlocBuilder<CeilingSensorBloc, CeilingSensorState>(builder: (context, state) { child: BlocBuilder<CeilingSensorBloc, CeilingSensorState>(builder: (context, state) {
CeilingSensorModel ceilingSensorModel = CeilingSensorModel ceilingSensorModel = CeilingSensorModel(
CeilingSensorModel(presenceState: 'none', sensitivity: 1, checkingResult: ''); presenceState: 'none',
sensitivity: 1,
checkingResult: '',
presenceRange: 1,
sportsPara: 1,
bodyMovement: 'none');
if (state is UpdateState) { if (state is UpdateState) {
ceilingSensorModel = state.ceilingSensorModel; ceilingSensorModel = state.ceilingSensorModel;
} else if (state is LoadingNewSate) { } else if (state is LoadingNewSate) {
@@ -178,7 +183,8 @@ class CeilingSensorInterface extends StatelessWidget {
children: [ children: [
const BodySmall(text: 'Sports Para'), const BodySmall(text: 'Sports Para'),
BodyLarge( BodyLarge(
text: '0', text: ceilingSensorModel.sportsPara
.toString(),
style: context.bodyLarge.copyWith( style: context.bodyLarge.copyWith(
fontWeight: FontsManager.bold, fontWeight: FontsManager.bold,
), ),
@@ -204,7 +210,8 @@ class CeilingSensorInterface extends StatelessWidget {
textOverflow: TextOverflow.ellipsis, textOverflow: TextOverflow.ellipsis,
), ),
BodyLarge( BodyLarge(
text: '0.0M', text:
'${ceilingSensorModel.presenceRange}M',
textOverflow: TextOverflow.ellipsis, textOverflow: TextOverflow.ellipsis,
style: context.bodyLarge.copyWith( style: context.bodyLarge.copyWith(
fontWeight: FontsManager.bold, fontWeight: FontsManager.bold,
@@ -231,7 +238,7 @@ class CeilingSensorInterface extends StatelessWidget {
textOverflow: TextOverflow.ellipsis, textOverflow: TextOverflow.ellipsis,
), ),
BodyLarge( BodyLarge(
text: 'none', text: ceilingSensorModel.bodyMovement,
textOverflow: TextOverflow.ellipsis, textOverflow: TextOverflow.ellipsis,
style: context.bodyLarge.copyWith( style: context.bodyLarge.copyWith(
fontWeight: FontsManager.bold, fontWeight: FontsManager.bold,
+28 -4
View File
@@ -5,10 +5,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: _flutterfire_internals name: _flutterfire_internals
sha256: fe4c077084ddda88f327dc1c96d16631cd68d4948644593fcbcd911c2c89e2fa sha256: "37a42d06068e2fe3deddb2da079a8c4d105f241225ba27b7122b37e9865fd8f7"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.23" version: "1.3.35"
args: args:
dependency: transitive dependency: transitive
description: description:
@@ -245,10 +245,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: firebase_core name: firebase_core
sha256: "797379ea206eaeeb62499775de812761493d0692890fdc7f90b6183a3369176d" sha256: "26de145bb9688a90962faec6f838247377b0b0d32cc0abecd9a4e43525fc856c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.25.5" version: "2.32.0"
firebase_core_platform_interface: firebase_core_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -281,6 +281,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.6.23" version: "3.6.23"
firebase_database:
dependency: "direct main"
description:
name: firebase_database
sha256: "3b9ca306d26ad243ccbc4c717ff6e8563a080ebe11ee77fa7349b419c894b42d"
url: "https://pub.dev"
source: hosted
version: "10.5.7"
firebase_database_platform_interface:
dependency: transitive
description:
name: firebase_database_platform_interface
sha256: "5864cc362275465e9bd682b243f19419c9d78b861c2db820241eea596ae3b320"
url: "https://pub.dev"
source: hosted
version: "0.2.5+35"
firebase_database_web:
dependency: transitive
description:
name: firebase_database_web
sha256: a6008395dd20e8b8dde0691b441c181a1216c3866f89f48dcb6889d34fd35905
url: "https://pub.dev"
source: hosted
version: "0.2.5+7"
fixnum: fixnum:
dependency: transitive dependency: transitive
description: description:
+2 -1
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.2+19 version: 1.0.2+20
environment: environment:
sdk: ">=3.0.6 <4.0.0" sdk: ">=3.0.6 <4.0.0"
@@ -45,6 +45,7 @@ dependencies:
time_picker_spinner: ^1.0.0 time_picker_spinner: ^1.0.0
image_picker: ^1.1.2 image_picker: ^1.1.2
device_info_plus: ^10.1.0 device_info_plus: ^10.1.0
firebase_database: ^10.5.7
dev_dependencies: dev_dependencies:
flutter_lints: ^3.0.1 flutter_lints: ^3.0.1