Compare commits

..

55 Commits

Author SHA1 Message Date
f2412aa867 refactor: extract device fetching logic into a separate method for improved readability 2025-04-16 16:10:36 +03:00
e4768c95aa refactor: rename tab change events and states for consistency, and to match blocs naming convention. 2025-04-16 16:07:30 +03:00
f25b4dbf6d implement SceneDevicesBodyTabBar for improved tab management in SceneDevicesBody. 2025-04-16 15:57:21 +03:00
9eff9ab371 refactor: consolidate device loading and error handling in SceneDevicesBody and implement SceneDevicesList widget 2025-04-16 15:46:56 +03:00
a2e68d6194 fix: restore title in DefaultScaffold for SceneRoomsTabBarDevicesView 2025-04-16 15:25:23 +03:00
94c94b170f fix: correct order of dispose method calls in SceneRoomsTabBarDevicesView 2025-04-16 15:24:47 +03:00
253cf15559 refactor: simplify SceneDevicesBody widget structure and improve loading indicator handling 2025-04-16 15:24:37 +03:00
443eea9421 SP-1397 2025-04-16 15:11:43 +03:00
87a2c08f64 Merge pull request #82 from SyncrowIOT/SP-1416
added client token login
2025-04-16 12:35:31 +04:00
dd66e7c747 added client token login 2025-04-16 12:02:19 +04:00
7af61d2f65 added client id and secret 2025-04-16 11:34:24 +04:00
f37eacb0ee Merge pull request #81 from SyncrowIOT/feat/update-additional-device-endpoints
updated endpoint for device
2025-04-14 15:11:36 +03:00
c7dcc297aa fix conflict 2025-04-14 15:11:02 +03:00
aefe5ad081 Merge branch 'dev' into feat/update-additional-device-endpoints 2025-04-14 15:10:42 +03:00
8d9af8519d Merge pull request #78 from SyncrowIOT/SP-1246
updated device endpoint
2025-04-14 14:58:09 +03:00
b1d52937c9 Merge branch 'dev' of https://github.com/SyncrowIOT/syncrow-app into feat/update-additional-device-endpoints 2025-04-14 10:31:09 +04:00
5fedf37421 updated endpoint for device 2025-04-14 10:30:48 +04:00
ccde857c29 Merge pull request #80 from SyncrowIOT/SP-1398-FE-in-the-wizerd-the-batch-control-title-doesn-t-represent-the-the-accurate-device-name
SP-1398-FE-in-the-wizerd-the-batch-control-title-doesn-t-represent-the-the-accurate-device-name
2025-04-13 16:23:49 +03:00
b2a8086e0e Merge pull request #79 from SyncrowIOT/sp-1268-rework-v2
Sp 1268 rework v2
2025-04-13 16:20:10 +03:00
408e78962c SP-1398 2025-04-13 16:18:49 +03:00
dcdbc02ca0 Adds AppLoadingIndicator widget and replaces CircularProgressIndicator in SceneView. 2025-04-13 15:50:52 +03:00
31025e9176 Refactors SceneView constructor and improves conditional rendering for automation list 2025-04-13 15:49:13 +03:00
8219de6821 Injects SceneBloc using the new factory. 2025-04-13 15:28:44 +03:00
fbdf3817ab Created a factory helper to create a SceneBloc. 2025-04-13 15:25:48 +03:00
17422edd0d sp-1268-rework-v2. 2025-04-13 15:21:20 +03:00
4c8f2c72df Merge branch 'dev' of https://github.com/SyncrowIOT/syncrow-app into SP-1246 2025-04-03 10:47:27 +04:00
fb867e5df3 updated device endpoint 2025-04-03 10:47:09 +04:00
9472390284 Merge pull request #76 from SyncrowIOT/bugifx/empty-subspace-routine-creation
fixed issue on empty subspace
2025-03-28 11:38:14 +04:00
731ba0f3d6 Merge pull request #77 from SyncrowIOT/SP-1268-FE-Implement-UX-Behavior-for-No-Tab-to-Run-Scene-in-Device-Screen
Sp 1268 fe implement ux behavior for no tab to run scene in device screen
2025-03-26 15:24:34 +03:00
56407c6426 indentation and trailing commas. 2025-03-26 13:49:54 +03:00
02d61ca0bb Refactor DevicesViewBody and SceneView to improve widget structure and replace CreateUnitWidget with EmptyDevicesWidget for better handling of empty states. 2025-03-26 13:44:49 +03:00
99ee4b9878 Add EmptyDevicesWidget to display message when no routines are available. 2025-03-26 13:34:07 +03:00
19edd0a275 Added /android/app/.cxx/ to .gitIgnore, because they're auto generated files that dont need to be checked into source control. 2025-03-26 13:14:23 +03:00
ef5e7c3154 fixed issue on empty subspace 2025-03-25 14:15:14 +04:00
80dd0f696f Merge pull request #75 from SyncrowIOT/SP-1245
updated endpoint for automation
2025-03-17 09:34:46 +04:00
a64a41548f updated delete endpoint for automation 2025-03-14 13:02:14 +04:00
0d50aa68fa updated endpoint for update automation 2025-03-14 12:58:12 +04:00
88aac86b10 updated endpoint for getting automation by id 2025-03-14 12:55:33 +04:00
0673548745 changed endpoint for getting automations by space 2025-03-14 12:53:29 +04:00
c2fc8fa0ae changed endpoint for create automation endpoint 2025-03-14 12:40:52 +04:00
cbf10bbf78 Merge pull request #74 from SyncrowIOT/real_time_app
Real time app
2025-03-03 17:34:34 +03:00
d95588ce84 remove unused code 2025-03-03 17:34:15 +03:00
7e2e591d71 remove unused code 2025-03-01 15:19:15 +03:00
2ec81bda9c connect the real time for all devices 2025-03-01 15:08:51 +03:00
3b0f51473c Merge pull request #73 from SyncrowIOT/SP-1190
Sp 1190
2025-02-26 12:20:06 +03:00
13757d89ee Merged with dev 2025-02-26 12:17:57 +03:00
d3068b8e14 changes in threeGang 2025-02-26 10:58:32 +03:00
7c5d7e1dda remove unused code 2025-02-25 12:45:23 +03:00
0a97a4867d disconnect real-time to some devices 2025-02-25 12:41:49 +03:00
6e55b488aa Merge pull request #72 from SyncrowIOT/feat/change-hardcode-projectid
updated project hardcoded values
2025-02-24 12:06:06 +03:00
22789234fe Sensitivity Start from 1 2025-02-23 16:30:50 +03:00
8393ec353a fetchDevices by projectUuid 2025-02-20 16:02:25 +03:00
0b45d61b25 Fixed list issue in the manage home screen 2025-02-20 10:50:47 +03:00
2dc4e16a75 connect all devices to real-time and change the channel function 2025-02-16 14:54:39 +03:00
cd41720244 active the implemented device 2025-02-16 10:04:34 +03:00
59 changed files with 2569 additions and 1241 deletions

View File

@ -1,3 +1,5 @@
ENV_NAME=development ENV_NAME=development
BASE_URL=https://syncrow-dev.azurewebsites.net BASE_URL=https://syncrow-dev.azurewebsites.net
PROJECT_ID=0e62577c-06fa-41b9-8a92-99a21fbaf51c PROJECT_ID=0e62577c-06fa-41b9-8a92-99a21fbaf51c
CLIENT_ID=c024573d191a327ce74db7d4502fdc29
CLIENT_SECRET=fec6ccbc33664f94a3b84a45c7cceef3f3ebd1613ef4307db8946ede530cd1ed

1
.gitignore vendored
View File

@ -42,3 +42,4 @@ app.*.map.json
/android/app/debug /android/app/debug
/android/app/profile /android/app/profile
/android/app/release /android/app/release
/android/app/.cxx/

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:syncrow_app/features/auth/model/login_with_email_model.dart'; import 'package:syncrow_app/features/auth/model/login_with_email_model.dart';
import 'package:syncrow_app/features/auth/model/signup_model.dart'; import 'package:syncrow_app/features/auth/model/signup_model.dart';
@ -217,9 +218,22 @@ class AuthCubit extends Cubit<AuthState> {
signUp() async { signUp() async {
emit(AuthLoginLoading()); emit(AuthLoginLoading());
final response; final response;
final clientId = dotenv.env['CLIENT_ID'] ?? '';
final clientSecret = dotenv.env['CLIENT_SECRET'] ?? '';
try { try {
List<String> userFullName = fullName.split(' '); List<String> userFullName = fullName.split(' ');
final clientToken = await AuthenticationAPI.fetchClientToken(
clientId: clientId,
clientSecret: clientSecret,
);
final accessToken = clientToken['accessToken'];
response = await AuthenticationAPI.signUp( response = await AuthenticationAPI.signUp(
accessToken: accessToken,
model: SignUpModel( model: SignUpModel(
hasAcceptedAppAgreement: true, hasAcceptedAppAgreement: true,
email: email.toLowerCase(), email: email.toLowerCase(),

View File

@ -71,7 +71,7 @@ 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)); Future.delayed(const Duration(milliseconds: 500));
// _listenToChanges(); _listenToChanges(acId);
} }
} catch (e) { } catch (e) {
emit(AcsFailedState(errorMessage: e.toString())); emit(AcsFailedState(errorMessage: e.toString()));
@ -79,25 +79,38 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
} }
} }
_listenToChanges() { StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges(acId) {
try { try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$acId'); _streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$acId');
Stream<DatabaseEvent> stream = ref.onValue; Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) { _streamSubscription = stream.listen((DatabaseEvent event) {
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>; Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = []; List<StatusModel> statusList = [];
usersMap['status'].forEach((element) { usersMap['status'].forEach((element) {
statusList.add(StatusModel(code: element['code'], value: element['value'])); statusList.add(StatusModel(code: element['code'], value: element['value']));
}); });
deviceStatus =
AcStatusModel.fromJson(usersMap['productUuid'], statusList);
deviceStatus = AcStatusModel.fromJson(usersMap['productUuid'], statusList);
add(AcUpdated()); add(AcUpdated());
}); });
} catch (_) {} } catch (_) {}
} }
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_onAcUpdated(AcUpdated event, Emitter<AcsState> emit) { _onAcUpdated(AcUpdated event, Emitter<AcsState> emit) {
emit(GetAcStatusState(acStatusModel: deviceStatus)); emit(GetAcStatusState(acStatusModel: deviceStatus));
} }
@ -109,13 +122,16 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
HomeCubit.getInstance().selectedSpace?.id ?? '', 'AC'); HomeCubit.getInstance().selectedSpace?.id ?? '', 'AC');
for (int i = 0; i < devicesList.length; i++) { for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? ''); _listenToChanges(devicesList[i].uuid);
var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = []; List<StatusModel> statusModelList = [];
for (var status in response['status']) { for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status)); statusModelList.add(StatusModel.fromJson(status));
} }
deviceStatusList.add(AcStatusModel.fromJson(devicesList[i].uuid ?? '', statusModelList)); deviceStatusList.add(AcStatusModel.fromJson(devicesList[i].uuid ?? '', statusModelList));
} }
_setAllAcsTempsAndSwitches(); _setAllAcsTempsAndSwitches();
} }

View File

@ -1,4 +1,4 @@
import 'dart:convert'; import 'dart:async';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:firebase_database/firebase_database.dart'; import 'package:firebase_database/firebase_database.dart';
@ -35,35 +35,49 @@ class CeilingSensorBloc extends Bloc<CeilingSensorEvent, CeilingSensorState> {
} }
deviceStatus = CeilingSensorModel.fromJson(statusModelList); deviceStatus = CeilingSensorModel.fromJson(statusModelList);
emit(UpdateState(ceilingSensorModel: deviceStatus)); emit(UpdateState(ceilingSensorModel: deviceStatus));
// _listenToChanges(); _listenToChanges();
} catch (e) { } catch (e) {
emit(FailedState(error: e.toString())); emit(FailedState(error: e.toString()));
return; return;
} }
} }
_listenToChanges() { StreamSubscription<DatabaseEvent>? _streamSubscription;
Timer? _timer;
void _listenToChanges() {
try { try {
_streamSubscription?.cancel();
DatabaseReference ref = DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$deviceId'); FirebaseDatabase.instance.ref('device-status/$deviceId');
Stream<DatabaseEvent> stream = ref.onValue; Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) { _streamSubscription = stream.listen((DatabaseEvent event) async {
if (_timer != null) {
await Future.delayed(const Duration(seconds: 2));
}
Map<dynamic, dynamic> usersMap = Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>; event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = []; List<StatusModel> statusList = [];
usersMap['status'].forEach((element) { usersMap['status'].forEach((element) {
statusList statusList
.add(StatusModel(code: element['code'], value: element['value'])); .add(StatusModel(code: element['code'], value: element['value']));
}); });
deviceStatus = CeilingSensorModel.fromJson(statusList); deviceStatus = CeilingSensorModel.fromJson(statusList);
add(CeilingSensorUpdated()); if (!isClosed) {
add(CeilingSensorUpdated());
}
}); });
} catch (_) {} } catch (_) {}
} }
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_onCeilingSensorUpdated( _onCeilingSensorUpdated(
CeilingSensorUpdated event, Emitter<CeilingSensorState> emit) { CeilingSensorUpdated event, Emitter<CeilingSensorState> emit) {
emit(UpdateState(ceilingSensorModel: deviceStatus)); emit(UpdateState(ceilingSensorModel: deviceStatus));

View File

@ -1,3 +1,5 @@
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/curtain_bloc/curtain_event.dart'; import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_event.dart';
@ -30,6 +32,7 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
on<InitialWizardEvent>(_fetchWizardStatus); on<InitialWizardEvent>(_fetchWizardStatus);
on<GroupAllOffEvent>(_groupAllOff); on<GroupAllOffEvent>(_groupAllOff);
on<GroupAllOnEvent>(_groupAllOn); on<GroupAllOnEvent>(_groupAllOn);
on<UpdateCurtainEvent>(_updateCurtain);
} }
Future<void> _onOpenCurtain( Future<void> _onOpenCurtain(
@ -161,7 +164,10 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
void _fetchStatus(InitCurtain event, Emitter<CurtainState> emit) async { void _fetchStatus(InitCurtain event, Emitter<CurtainState> emit) async {
try { try {
emit(CurtainLoadingState()); emit(CurtainLoadingState());
_listenToChanges(curtainId);
var response = await DevicesAPI.getDeviceStatus(curtainId); var response = await DevicesAPI.getDeviceStatus(curtainId);
List<StatusModel> statusModelList = []; List<StatusModel> statusModelList = [];
for (var status in response['status']) { for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status)); statusModelList.add(StatusModel.fromJson(status));
@ -169,7 +175,6 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
openPercentage = double.tryParse(statusModelList[1].value.toString())!; openPercentage = double.tryParse(statusModelList[1].value.toString())!;
curtainWidth = 270 - (openPercentage / 100) * curtainOpeningSpace; curtainWidth = 270 - (openPercentage / 100) * curtainOpeningSpace;
blindHeight = 310 - (openPercentage / 100) * blindOpeningSpace; blindHeight = 310 - (openPercentage / 100) * blindOpeningSpace;
emit(CurtainsOpening( emit(CurtainsOpening(
curtainWidth: curtainWidth, curtainWidth: curtainWidth,
blindHeight: blindHeight, blindHeight: blindHeight,
@ -181,6 +186,76 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
} }
} }
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges(curtainId) {
try {
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$curtainId');
Stream<DatabaseEvent> stream = ref.onValue;
_streamSubscription = 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']));
});
openPercentage = double.tryParse(statusList[1].value.toString())!;
curtainWidth = 270 - (openPercentage / 100) * curtainOpeningSpace;
blindHeight = 310 - (openPercentage / 100) * blindOpeningSpace;
add(UpdateCurtainEvent());
});
} catch (_) {}
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
// _listenToChanges(curtainId) {
// try {
// print('curtainId=$curtainId');
// DatabaseReference ref =
// FirebaseDatabase.instance.ref('device-status/$curtainId');
// 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> statusModelList = [];
// for (var status in usersMap['status']) {
// statusModelList.add(StatusModel.fromJson(status));
// print('statusModelList==${statusModelList}');
// }
// openPercentage = double.tryParse(statusModelList[1].value.toString())!;
// curtainWidth = 270 - (openPercentage / 100) * curtainOpeningSpace;
// blindHeight = 310 - (openPercentage / 100) * blindOpeningSpace;
// add(UpdateCurtainEvent());
// });
// } catch (_) {}
// }
_updateCurtain(UpdateCurtainEvent event, Emitter<CurtainState> emit) {
curtainWidth = 270 - (openPercentage / 100) * curtainOpeningSpace;
blindHeight = 310 - (openPercentage / 100) * blindOpeningSpace;
emit(CurtainsOpening(
curtainWidth: curtainWidth,
blindHeight: blindHeight,
openPercentage: openPercentage,
));
}
List<GroupCurtainModel> groupList = []; List<GroupCurtainModel> groupList = [];
bool allSwitchesOn = true; bool allSwitchesOn = true;
List<DeviceModel> devicesList = []; List<DeviceModel> devicesList = [];

View File

@ -33,6 +33,7 @@ class InitCurtain extends CurtainEvent {}
class PauseCurtain extends CurtainEvent {} class PauseCurtain extends CurtainEvent {}
class useCurtainEvent extends CurtainEvent {} class useCurtainEvent extends CurtainEvent {}
class InitialWizardEvent extends CurtainEvent {} class InitialWizardEvent extends CurtainEvent {}
class UpdateCurtainEvent extends CurtainEvent {}
class ChangeFirstWizardSwitchStatusEvent extends CurtainEvent { class ChangeFirstWizardSwitchStatusEvent extends CurtainEvent {

View File

@ -1,6 +1,9 @@
// ignore_for_file: constant_identifier_names, unused_import // ignore_for_file: constant_identifier_names, unused_import
import 'dart:async';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.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';
@ -63,6 +66,43 @@ class DevicesCubit extends Cubit<DevicesState> {
} }
} }
Timer? _timer;
final Map<String, StreamSubscription<DatabaseEvent>> _deviceSubscriptions =
{};
void _listenToChanges(deviceId) {
try {
if (_deviceSubscriptions.containsKey(deviceId)) {
_deviceSubscriptions[deviceId]?.cancel();
_deviceSubscriptions.remove(deviceId);
}
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$deviceId');
Stream<DatabaseEvent> stream = ref.onValue;
final subscription = 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>;
// print('object-----${usersMap['status']}');
List<StatusModel> statusList = [];
usersMap['status'].forEach((element) {
statusList
.add(StatusModel(code: element['code'], value: element['value']));
});
emitSafe(GetDevicesLoading());
final deviceIndex = allDevices.indexWhere((d) => d.uuid == deviceId);
if (deviceIndex != -1) {
allDevices[deviceIndex].status = statusList;
}
emitSafe(GetDevicesSuccess(allDevices));
});
_deviceSubscriptions[deviceId] = subscription;
} catch (_) {}
}
static DevicesCubit get(context) => BlocProvider.of(context); static DevicesCubit get(context) => BlocProvider.of(context);
List<DevicesCategoryModel>? allCategories; List<DevicesCategoryModel>? allCategories;
@ -422,6 +462,19 @@ class DevicesCubit extends Cubit<DevicesState> {
spaceUuid: unit.id, spaceUuid: unit.id,
projectId: project?.uuid ?? TempConst.projectIdDev); projectId: project?.uuid ?? TempConst.projectIdDev);
allDevices = devices; allDevices = devices;
for (var deviceId in allDevices) {
if (deviceId.type == "3G" ||
deviceId.type == "2G" ||
deviceId.type == "1G" ||
deviceId.type == "3GT" ||
deviceId.type == "2GT" ||
deviceId.type == "1GT" ||
deviceId.type == "WH" ||
deviceId.type == "CUR" ||
deviceId.type == "AC") {
_listenToChanges(deviceId.uuid);
}
}
emitSafe(GetDevicesSuccess(allDevices)); emitSafe(GetDevicesSuccess(allDevices));
} catch (e) { } catch (e) {
emitSafe(GetDevicesError(e.toString())); emitSafe(GetDevicesError(e.toString()));
@ -480,25 +533,35 @@ class DevicesCubit extends Cubit<DevicesState> {
} }
final device = allDevices[deviceIndex]; final device = allDevices[deviceIndex];
final switches = ['switch_1', 'switch_2', 'switch_3']; final switches = ['switch_1', 'switch_2', 'switch_3'];
final anySwitchOff = device.status.any(
(s) => (s.code?.startsWith('switch_') ?? false) && (s.value == false),
);
final targetState = anySwitchOff ? true : false;
for (final switchCode in switches) { for (final switchCode in switches) {
final statusIndex = final statusIndex =
device.status.indexWhere((s) => s.code == switchCode); device.status.indexWhere((s) => s.code == switchCode);
if (statusIndex != -1) { if (statusIndex != -1) {
final toggledValue = control.value; final currentValue = device.status[statusIndex].value ?? false;
if (!targetState && !currentValue) {
continue;
}
final controlRequest = DeviceControlModel( final controlRequest = DeviceControlModel(
code: switchCode, value: toggledValue, deviceId: deviceUuid); code: switchCode, value: targetState, deviceId: deviceUuid);
final response = final response =
await DevicesAPI.controlDevice(controlRequest, deviceUuid); await DevicesAPI.controlDevice(controlRequest, deviceUuid);
if (response['success'] != true) { if (response['success'] != true) {
throw Exception('Failed to toggle $switchCode'); throw Exception('Failed to toggle $switchCode');
} }
device.status[statusIndex].value = toggledValue;
device.status[statusIndex].value = targetState;
} }
} }
final anySwitchOff = device.status.any( device.toggleStatus = device.status.every(
(s) => (s.code?.startsWith('switch_') ?? false) && (s.value == false), (s) => (s.code?.startsWith('switch_') ?? false) && (s.value == true),
); );
device.toggleStatus = !anySwitchOff;
allDevices[deviceIndex] = device; allDevices[deviceIndex] = device;
emit(DeviceControlSuccess(code: control.code)); emit(DeviceControlSuccess(code: control.code));
} catch (failure) { } catch (failure) {
@ -597,7 +660,6 @@ class DevicesCubit extends Cubit<DevicesState> {
code: 'switch_1', value: toggledValue, deviceId: deviceUuid); code: 'switch_1', value: toggledValue, deviceId: deviceUuid);
final response = final response =
await DevicesAPI.controlDevice(controlRequest, deviceUuid); await DevicesAPI.controlDevice(controlRequest, deviceUuid);
print(response);
if (response['result'] != true) { if (response['result'] != true) {
throw Exception('Failed to toggle switch_1'); throw Exception('Failed to toggle switch_1');
} }

View File

@ -21,13 +21,14 @@ class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
on<ToggleClosingReminderEvent>(_toggleClosingReminder); on<ToggleClosingReminderEvent>(_toggleClosingReminder);
on<ToggleDoorAlarmEvent>(_toggleDoorAlarm); on<ToggleDoorAlarmEvent>(_toggleDoorAlarm);
} }
Timer? _timer;
bool lowBattery = false; bool lowBattery = false;
bool closingReminder = false; bool closingReminder = false;
bool doorAlarm = false; bool doorAlarm = false;
DoorSensorModel deviceStatus = DoorSensorModel(doorContactState: false, batteryPercentage: 0); DoorSensorModel deviceStatus =
DoorSensorModel(doorContactState: false, batteryPercentage: 0);
void _fetchStatus(DoorSensorInitial event, Emitter<DoorSensorState> emit) async { void _fetchStatus(
DoorSensorInitial event, Emitter<DoorSensorState> emit) async {
emit(DoorSensorLoadingState()); emit(DoorSensorLoadingState());
try { try {
var response = await DevicesAPI.getDeviceStatus(DSId); var response = await DevicesAPI.getDeviceStatus(DSId);
@ -40,7 +41,7 @@ class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
); );
emit(UpdateState(doorSensor: deviceStatus)); emit(UpdateState(doorSensor: deviceStatus));
Future.delayed(const Duration(milliseconds: 500)); Future.delayed(const Duration(milliseconds: 500));
// _listenToChanges(); _listenToChanges();
} catch (e) { } catch (e) {
emit(DoorSensorFailedState(errorMessage: e.toString())); emit(DoorSensorFailedState(errorMessage: e.toString()));
return; return;
@ -48,7 +49,8 @@ class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
} }
// Toggle functions for each switch // Toggle functions for each switch
void _toggleLowBattery(ToggleLowBatteryEvent event, Emitter<DoorSensorState> emit) async { void _toggleLowBattery(
ToggleLowBatteryEvent event, Emitter<DoorSensorState> emit) async {
emit(LoadingNewSate(doorSensor: deviceStatus)); emit(LoadingNewSate(doorSensor: deviceStatus));
try { try {
lowBattery = event.isLowBatteryEnabled; lowBattery = event.isLowBatteryEnabled;
@ -89,7 +91,8 @@ class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
} }
} }
void _toggleDoorAlarm(ToggleDoorAlarmEvent event, Emitter<DoorSensorState> emit) async { void _toggleDoorAlarm(
ToggleDoorAlarmEvent event, Emitter<DoorSensorState> emit) async {
emit(LoadingNewSate(doorSensor: deviceStatus)); emit(LoadingNewSate(doorSensor: deviceStatus));
try { try {
doorAlarm = event.isDoorAlarmEnabled; doorAlarm = event.isDoorAlarmEnabled;
@ -108,9 +111,11 @@ class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
} }
} }
DeviceReport recordGroups = DeviceReport(startTime: '0', endTime: '0', data: []); DeviceReport recordGroups =
DeviceReport(startTime: '0', endTime: '0', data: []);
Future<void> fetchLogsForLastMonth(ReportLogsInitial event, Emitter<DoorSensorState> emit) async { Future<void> fetchLogsForLastMonth(
ReportLogsInitial event, Emitter<DoorSensorState> emit) async {
DateTime now = DateTime.now(); DateTime now = DateTime.now();
DateTime lastMonth = DateTime(now.year, now.month - 1, now.day); DateTime lastMonth = DateTime(now.year, now.month - 1, now.day);
@ -133,22 +138,27 @@ class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
} }
} }
_listenToChanges() { // real-time database
Timer? _timer;
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges() {
try { try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$DSId'); _streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$DSId');
Stream<DatabaseEvent> stream = ref.onValue; Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) async { _streamSubscription = stream.listen((DatabaseEvent event) async {
if (_timer != null) { if (_timer != null) {
await Future.delayed(const Duration(seconds: 2)); await Future.delayed(const Duration(seconds: 2));
} }
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>; Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = []; List<StatusModel> statusList = [];
usersMap['status'].forEach((element) { usersMap['status'].forEach((element) {
statusList.add(StatusModel(code: element['code'], value: true)); statusList
.add(StatusModel(code: element['code'], value: element['value']));
}); });
deviceStatus = DoorSensorModel.fromJson(statusList); deviceStatus = DoorSensorModel.fromJson(statusList);
if (!isClosed) { if (!isClosed) {
add( add(
@ -158,4 +168,11 @@ class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
}); });
} catch (_) {} } catch (_) {}
} }
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
} }

View File

@ -233,6 +233,7 @@ class FourSceneBloc extends Bloc<FourSceneEvent, FourSceneState> {
deviceStatus = FourSceneModelState.fromJson( deviceStatus = FourSceneModelState.fromJson(
statusModelList, statusModelList,
); );
// _listenToChanges();
add(const FourSceneSwitchInitial()); add(const FourSceneSwitchInitial());
} catch (e) { } catch (e) {
emit(FourSceneFailedState(errorMessage: e.toString())); emit(FourSceneFailedState(errorMessage: e.toString()));
@ -332,4 +333,33 @@ class FourSceneBloc extends Bloc<FourSceneEvent, FourSceneState> {
}).toList(); }).toList();
emit(SearchResultsState()); emit(SearchResultsState());
} }
// Real-time database
// Timer? _timer;
// _listenToChanges() {
// try {
// DatabaseReference ref =
// FirebaseDatabase.instance.ref('device-status/$fourSceneId');
// 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 = FourSceneModelState.fromJson(statusList);
// // if (!isClosed) {
// // add(
// // DoorSensorSwitch(switchD: deviceStatus.doorContactState),
// // );
// // }
// });
// } catch (_) {}
// }
} }

View File

@ -42,7 +42,8 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
on<ChangeFirstWizardSwitchStatusEvent>(_changeFirstWizardSwitch); on<ChangeFirstWizardSwitchStatusEvent>(_changeFirstWizardSwitch);
on<ToggleAlarmEvent>(_toggleAlarmEvent); on<ToggleAlarmEvent>(_toggleAlarmEvent);
on<DeleteScheduleEvent>(deleteSchedule); on<DeleteScheduleEvent>(deleteSchedule);
//_toggleAlarmEvent
on<UpdateStateEvent>(_updateState);
} }
void _onClose(OnClose event, Emitter<GarageDoorSensorState> emit) { void _onClose(OnClose event, Emitter<GarageDoorSensorState> emit) {
_timer?.cancel(); _timer?.cancel();
@ -81,7 +82,7 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
toggleDoor = deviceStatus.switch1; toggleDoor = deviceStatus.switch1;
emit(UpdateState(garageSensor: deviceStatus)); emit(UpdateState(garageSensor: deviceStatus));
Future.delayed(const Duration(milliseconds: 500)); Future.delayed(const Duration(milliseconds: 500));
// _listenToChanges(); _listenToChanges();
} catch (e) { } catch (e) {
emit(GarageDoorFailedState(errorMessage: e.toString())); emit(GarageDoorFailedState(errorMessage: e.toString()));
return; return;
@ -180,33 +181,59 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
} }
} }
_listenToChanges() { // Real-time db
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges() {
try { try {
_streamSubscription?.cancel();
DatabaseReference ref = DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$GDId'); FirebaseDatabase.instance.ref('device-status/$GDId');
Stream<DatabaseEvent> stream = ref.onValue; Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) async { _streamSubscription = stream.listen((DatabaseEvent event) async {
if (_timer != null) { if (_timer != null) {
await Future.delayed(const Duration(seconds: 2)); await Future.delayed(const Duration(seconds: 1));
} }
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 = GarageDoorModel.fromJson(statusList); if (event.snapshot.value != null) {
if (!isClosed) { Map<dynamic, dynamic> usersMap =
// add( event.snapshot.value as Map<dynamic, dynamic>;
// DoorSensorSwitch(switchD: deviceStatus.doorContactState), List<StatusModel> statusList = [];
// );
usersMap['status'].forEach((element) {
statusList.add(
StatusModel(code: element['code'], value: element['value']));
});
deviceStatus.tr_timecon = statusList
.firstWhere((status) => status.code == "tr_timecon",
orElse: () => StatusModel(code: "tr_timecon", value: 0))
.value as int;
deviceStatus.switch1 = statusList
.firstWhere((status) => status.code == "switch_1",
orElse: () => StatusModel(code: "switch_1", value: false))
.value as bool;
secondSelected = deviceStatus.tr_timecon;
toggleDoor = deviceStatus.switch1;
add(UpdateStateEvent());
} }
}); });
} catch (_) {} } catch (_) {}
} }
Future<void> _updateState(
UpdateStateEvent event, Emitter<GarageDoorSensorState> emit) async {
emit(GarageDoorLoadingState());
emit(UpdateState(garageSensor: deviceStatus));
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
List<Map<String, String>> days = [ List<Map<String, String>> days = [
{"day": "Sun", "key": "Sun"}, {"day": "Sun", "key": "Sun"},
{"day": "Mon", "key": "Mon"}, {"day": "Mon", "key": "Mon"},

View File

@ -109,6 +109,8 @@ class GetScheduleEvent extends GarageDoorEvent {}
class ScheduleSaveapp extends GarageDoorEvent {} class ScheduleSaveapp extends GarageDoorEvent {}
class UpdateStateEvent extends GarageDoorEvent {}
class ToggleScheduleEvent extends GarageDoorEvent { class ToggleScheduleEvent extends GarageDoorEvent {
final String id; final String id;
final bool toggle; final bool toggle;

View File

@ -26,7 +26,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
bool oneGangGroup = false; bool oneGangGroup = false;
List<DeviceModel> devicesList = []; List<DeviceModel> devicesList = [];
OneGangBloc({required this.oneGangId, required this.switchCode}) : super(InitialState()) { OneGangBloc({required this.oneGangId, required this.switchCode})
: super(InitialState()) {
on<InitialEvent>(_fetchOneGangStatus); on<InitialEvent>(_fetchOneGangStatus);
on<OneGangUpdated>(_oneGangUpdated); on<OneGangUpdated>(_oneGangUpdated);
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch); on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
@ -49,7 +50,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
on<GroupAllOffEvent>(_groupAllOff); on<GroupAllOffEvent>(_groupAllOff);
} }
void _fetchOneGangStatus(InitialEvent event, Emitter<OneGangState> emit) async { void _fetchOneGangStatus(
InitialEvent event, Emitter<OneGangState> emit) async {
emit(LoadingInitialState()); emit(LoadingInitialState());
try { try {
var response = await DevicesAPI.getDeviceStatus(oneGangId); var response = await DevicesAPI.getDeviceStatus(oneGangId);
@ -59,42 +61,51 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
} }
deviceStatus = OneGangModel.fromJson(statusModelList); deviceStatus = OneGangModel.fromJson(statusModelList);
emit(UpdateState(oneGangModel: deviceStatus)); emit(UpdateState(oneGangModel: deviceStatus));
// _listenToChanges(); _listenToChanges(oneGangId);
} catch (e) { } catch (e) {
emit(FailedState(error: e.toString())); emit(FailedState(error: e.toString()));
return; return;
} }
} }
_listenToChanges() { // Real-time db
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges(String id) {
try { try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$oneGangId'); _streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$id');
Stream<DatabaseEvent> stream = ref.onValue; Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) async { _streamSubscription = stream.listen((DatabaseEvent event) {
if (_timer != null) { Map<dynamic, dynamic> usersMap =
await Future.delayed(const Duration(seconds: 2)); event.snapshot.value as Map<dynamic, dynamic>;
}
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = []; List<StatusModel> statusList = [];
usersMap['status'].forEach((element) { usersMap['status'].forEach((element) {
statusList.add(StatusModel(code: element['code'], value: element['value'])); statusList
.add(StatusModel(code: element['code'], value: element['value']));
}); });
deviceStatus = OneGangModel.fromJson(statusList); deviceStatus = OneGangModel.fromJson(statusList);
if (!isClosed) { add(OneGangUpdated());
add(OneGangUpdated());
}
}); });
} catch (_) {} } catch (_) {}
} }
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_oneGangUpdated(OneGangUpdated event, Emitter<OneGangState> emit) { _oneGangUpdated(OneGangUpdated event, Emitter<OneGangState> emit) {
emit(LoadingInitialState());
emit(UpdateState(oneGangModel: deviceStatus)); emit(UpdateState(oneGangModel: deviceStatus));
} }
void _changeFirstSwitch(ChangeFirstSwitchStatusEvent event, Emitter<OneGangState> emit) async { void _changeFirstSwitch(
ChangeFirstSwitchStatusEvent event, Emitter<OneGangState> emit) async {
emit(LoadingNewSate(oneGangModel: deviceStatus)); emit(LoadingNewSate(oneGangModel: deviceStatus));
try { try {
deviceStatus.firstSwitch = !event.value; deviceStatus.firstSwitch = !event.value;
@ -119,17 +130,20 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
} }
} }
void _changeSliding(ChangeSlidingSegment event, Emitter<OneGangState> emit) async { void _changeSliding(
ChangeSlidingSegment event, Emitter<OneGangState> emit) async {
emit(ChangeSlidingSegmentState(value: event.value)); emit(ChangeSlidingSegmentState(value: event.value));
} }
void _setCounterValue(SetCounterValue event, Emitter<OneGangState> emit) async { void _setCounterValue(
SetCounterValue event, Emitter<OneGangState> emit) async {
emit(LoadingNewSate(oneGangModel: deviceStatus)); emit(LoadingNewSate(oneGangModel: deviceStatus));
int seconds = 0; int seconds = 0;
try { try {
seconds = event.duration.inSeconds; seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice( final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: oneGangId, code: event.deviceCode, value: seconds), DeviceControlModel(
deviceId: oneGangId, code: event.deviceCode, value: seconds),
oneGangId); oneGangId);
if (response['success'] ?? false) { if (response['success'] ?? false) {
@ -152,7 +166,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
} }
} }
void _getCounterValue(GetCounterEvent event, Emitter<OneGangState> emit) async { void _getCounterValue(
GetCounterEvent event, Emitter<OneGangState> emit) async {
emit(LoadingInitialState()); emit(LoadingInitialState());
try { try {
var response = await DevicesAPI.getDeviceStatus(oneGangId); var response = await DevicesAPI.getDeviceStatus(oneGangId);
@ -241,7 +256,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
deviceId: oneGangId, deviceId: oneGangId,
); );
List<dynamic> jsonData = response; List<dynamic> jsonData = response;
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList(); listSchedule =
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
emit(InitialState()); emit(InitialState());
} on DioException catch (e) { } on DioException catch (e) {
final errorData = e.response!.data; final errorData = e.response!.data;
@ -252,12 +268,13 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
int? getTimeStampWithoutSeconds(DateTime? dateTime) { int? getTimeStampWithoutSeconds(DateTime? dateTime) {
if (dateTime == null) return null; if (dateTime == null) return null;
DateTime dateTimeWithoutSeconds = DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute); dateTime.day, dateTime.hour, dateTime.minute);
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000; return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
} }
Future toggleChange(ToggleScheduleEvent event, Emitter<OneGangState> emit) async { Future toggleChange(
ToggleScheduleEvent event, Emitter<OneGangState> emit) async {
try { try {
emit(LoadingInitialState()); emit(LoadingInitialState());
final response = await DevicesAPI.changeSchedule( final response = await DevicesAPI.changeSchedule(
@ -276,7 +293,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
} }
} }
Future deleteSchedule(DeleteScheduleEvent event, Emitter<OneGangState> emit) async { Future deleteSchedule(
DeleteScheduleEvent event, Emitter<OneGangState> emit) async {
try { try {
emit(LoadingInitialState()); emit(LoadingInitialState());
final response = await DevicesAPI.deleteSchedule( final response = await DevicesAPI.deleteSchedule(
@ -296,7 +314,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
} }
} }
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<OneGangState> emit) { void toggleCreateSchedule(
ToggleCreateScheduleEvent event, Emitter<OneGangState> emit) {
emit(LoadingInitialState()); emit(LoadingInitialState());
createSchedule = !createSchedule; createSchedule = !createSchedule;
selectedDays.clear(); selectedDays.clear();
@ -325,7 +344,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
int selectedTabIndex = 0; int selectedTabIndex = 0;
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<OneGangState> emit) { void toggleSelectedIndex(
ToggleSelectedEvent event, Emitter<OneGangState> emit) {
emit(LoadingInitialState()); emit(LoadingInitialState());
selectedTabIndex = event.index; selectedTabIndex = event.index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex)); emit(ChangeSlidingSegmentState(value: selectedTabIndex));
@ -334,7 +354,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
List<GroupOneGangModel> groupOneGangList = []; List<GroupOneGangModel> groupOneGangList = [];
bool allSwitchesOn = true; bool allSwitchesOn = true;
void _fetchOneGangWizardStatus(InitialWizardEvent event, Emitter<OneGangState> emit) async { void _fetchOneGangWizardStatus(
InitialWizardEvent event, Emitter<OneGangState> emit) async {
emit(LoadingInitialState()); emit(LoadingInitialState());
try { try {
devicesList = []; devicesList = [];
@ -344,7 +365,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
HomeCubit.getInstance().selectedSpace?.id ?? '', '1G'); HomeCubit.getInstance().selectedSpace?.id ?? '', '1G');
for (int i = 0; i < devicesList.length; i++) { for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? ''); var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = []; List<StatusModel> statusModelList = [];
for (var status in response['status']) { for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status)); statusModelList.add(StatusModel.fromJson(status));
@ -365,15 +387,16 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
return true; return true;
}); });
} }
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: allSwitchesOn)); emit(UpdateGroupState(
oneGangList: groupOneGangList, allSwitches: allSwitchesOn));
} catch (e) { } catch (e) {
emit(FailedState(error: e.toString())); emit(FailedState(error: e.toString()));
return; return;
} }
} }
void _changeFirstWizardSwitch( void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
ChangeFirstWizardSwitchStatusEvent event, Emitter<OneGangState> emit) async { Emitter<OneGangState> emit) async {
emit(LoadingNewSate(oneGangModel: deviceStatus)); emit(LoadingNewSate(oneGangModel: deviceStatus));
try { try {
bool allSwitchesValue = true; bool allSwitchesValue = true;
@ -386,7 +409,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
} }
}); });
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: allSwitchesValue)); emit(UpdateGroupState(
oneGangList: groupOneGangList, allSwitches: allSwitchesValue));
final response = await DevicesAPI.deviceBatchController( final response = await DevicesAPI.deviceBatchController(
code: 'switch_1', code: 'switch_1',
@ -414,7 +438,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: true)); emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: true));
// Get a list of all device IDs // Get a list of all device IDs
List<String> allDeviceIds = groupOneGangList.map((device) => device.deviceId).toList(); List<String> allDeviceIds =
groupOneGangList.map((device) => device.deviceId).toList();
// First call for switch_1 // First call for switch_1
final response = await DevicesAPI.deviceBatchController( final response = await DevicesAPI.deviceBatchController(
@ -446,7 +471,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: false)); emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: false));
// Get a list of all device IDs // Get a list of all device IDs
List<String> allDeviceIds = groupOneGangList.map((device) => device.deviceId).toList(); List<String> allDeviceIds =
groupOneGangList.map((device) => device.deviceId).toList();
// First call for switch_1 // First call for switch_1
final response = await DevicesAPI.deviceBatchController( final response = await DevicesAPI.deviceBatchController(

View File

@ -30,7 +30,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
bool oneTouchGroup = false; bool oneTouchGroup = false;
List<DeviceModel> devicesList = []; List<DeviceModel> devicesList = [];
OneTouchBloc({required this.oneTouchId, required this.switchCode}) : super(InitialState()) { OneTouchBloc({required this.oneTouchId, required this.switchCode})
: super(InitialState()) {
on<InitialEvent>(_fetchOneTouchStatus); on<InitialEvent>(_fetchOneTouchStatus);
on<OneTouchUpdated>(_oneTouchUpdated); on<OneTouchUpdated>(_oneTouchUpdated);
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch); on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
@ -53,7 +54,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
on<ChangeStatusEvent>(_changeStatus); on<ChangeStatusEvent>(_changeStatus);
} }
void _fetchOneTouchStatus(InitialEvent event, Emitter<OneTouchState> emit) async { void _fetchOneTouchStatus(
InitialEvent event, Emitter<OneTouchState> emit) async {
emit(LoadingInitialState()); emit(LoadingInitialState());
try { try {
var response = await DevicesAPI.getDeviceStatus(oneTouchId); var response = await DevicesAPI.getDeviceStatus(oneTouchId);
@ -62,43 +64,59 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
statusModelList.add(StatusModel.fromJson(status)); statusModelList.add(StatusModel.fromJson(status));
} }
deviceStatus = OneTouchModel.fromJson(statusModelList); deviceStatus = OneTouchModel.fromJson(statusModelList);
_listenToChanges(oneTouchId);
emit(UpdateState(oneTouchModel: deviceStatus)); emit(UpdateState(oneTouchModel: deviceStatus));
// _listenToChanges();
} catch (e) { } catch (e) {
emit(FailedState(error: e.toString())); emit(FailedState(error: e.toString()));
return; return;
} }
} }
_listenToChanges() { StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges(String id) {
try { try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$oneTouchId'); _streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$id');
Stream<DatabaseEvent> stream = ref.onValue; Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) async { _streamSubscription = stream.listen((DatabaseEvent event) {
if (_timer != null) { if (event.snapshot.value != null) {
await Future.delayed(const Duration(seconds: 2)); Map<dynamic, dynamic> usersMap =
} event.snapshot.value as Map<dynamic, dynamic>;
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>; List<StatusModel> statusList = [];
List<StatusModel> statusList = [];
usersMap['status'].forEach((element) { usersMap['status'].forEach((element) {
statusList.add(StatusModel(code: element['code'], value: element['value'])); statusList.add(
}); StatusModel(code: element['code'], value: element['value']));
});
var switchStatus = statusList.firstWhere(
(status) => status.code == "switch_1",
orElse: () => StatusModel(code: "switch_1", value: false));
deviceStatus = OneTouchModel.fromJson(statusList); deviceStatus.firstSwitch = switchStatus.value as bool;
if (!isClosed) {
add(OneTouchUpdated()); add(OneTouchUpdated());
} }
}); });
} catch (_) {} } catch (_) {
}
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
} }
_oneTouchUpdated(OneTouchUpdated event, Emitter<OneTouchState> emit) { _oneTouchUpdated(OneTouchUpdated event, Emitter<OneTouchState> emit) {
emit(LoadingNewSate(oneTouchModel: deviceStatus));
emit(UpdateState(oneTouchModel: deviceStatus)); emit(UpdateState(oneTouchModel: deviceStatus));
} }
void _changeFirstSwitch(ChangeFirstSwitchStatusEvent event, Emitter<OneTouchState> emit) async { void _changeFirstSwitch(
ChangeFirstSwitchStatusEvent event, Emitter<OneTouchState> emit) async {
emit(LoadingNewSate(oneTouchModel: deviceStatus)); emit(LoadingNewSate(oneTouchModel: deviceStatus));
try { try {
deviceStatus.firstSwitch = !event.value; deviceStatus.firstSwitch = !event.value;
@ -123,17 +141,20 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
} }
} }
void _changeSliding(ChangeSlidingSegment event, Emitter<OneTouchState> emit) async { void _changeSliding(
ChangeSlidingSegment event, Emitter<OneTouchState> emit) async {
emit(ChangeSlidingSegmentState(value: event.value)); emit(ChangeSlidingSegmentState(value: event.value));
} }
void _setCounterValue(SetCounterValue event, Emitter<OneTouchState> emit) async { void _setCounterValue(
SetCounterValue event, Emitter<OneTouchState> emit) async {
emit(LoadingNewSate(oneTouchModel: deviceStatus)); emit(LoadingNewSate(oneTouchModel: deviceStatus));
int seconds = 0; int seconds = 0;
try { try {
seconds = event.duration.inSeconds; seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice( final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: oneTouchId, code: event.deviceCode, value: seconds), DeviceControlModel(
deviceId: oneTouchId, code: event.deviceCode, value: seconds),
oneTouchId); oneTouchId);
if (response['success'] ?? false) { if (response['success'] ?? false) {
@ -156,7 +177,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
} }
} }
void _getCounterValue(GetCounterEvent event, Emitter<OneTouchState> emit) async { void _getCounterValue(
GetCounterEvent event, Emitter<OneTouchState> emit) async {
emit(LoadingInitialState()); emit(LoadingInitialState());
try { try {
var response = await DevicesAPI.getDeviceStatus(oneTouchId); var response = await DevicesAPI.getDeviceStatus(oneTouchId);
@ -245,7 +267,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
deviceId: oneTouchId, deviceId: oneTouchId,
); );
List<dynamic> jsonData = response; List<dynamic> jsonData = response;
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList(); listSchedule =
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
emit(InitialState()); emit(InitialState());
} on DioException catch (e) { } on DioException catch (e) {
final errorData = e.response!.data; final errorData = e.response!.data;
@ -256,12 +279,13 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
int? getTimeStampWithoutSeconds(DateTime? dateTime) { int? getTimeStampWithoutSeconds(DateTime? dateTime) {
if (dateTime == null) return null; if (dateTime == null) return null;
DateTime dateTimeWithoutSeconds = DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute); dateTime.day, dateTime.hour, dateTime.minute);
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000; return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
} }
Future toggleChange(ToggleScheduleEvent event, Emitter<OneTouchState> emit) async { Future toggleChange(
ToggleScheduleEvent event, Emitter<OneTouchState> emit) async {
try { try {
emit(LoadingInitialState()); emit(LoadingInitialState());
final response = await DevicesAPI.changeSchedule( final response = await DevicesAPI.changeSchedule(
@ -280,7 +304,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
} }
} }
Future deleteSchedule(DeleteScheduleEvent event, Emitter<OneTouchState> emit) async { Future deleteSchedule(
DeleteScheduleEvent event, Emitter<OneTouchState> emit) async {
try { try {
emit(LoadingInitialState()); emit(LoadingInitialState());
final response = await DevicesAPI.deleteSchedule( final response = await DevicesAPI.deleteSchedule(
@ -300,7 +325,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
} }
} }
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<OneTouchState> emit) { void toggleCreateSchedule(
ToggleCreateScheduleEvent event, Emitter<OneTouchState> emit) {
emit(LoadingInitialState()); emit(LoadingInitialState());
createSchedule = !createSchedule; createSchedule = !createSchedule;
selectedDays.clear(); selectedDays.clear();
@ -329,7 +355,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
int selectedTabIndex = 0; int selectedTabIndex = 0;
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<OneTouchState> emit) { void toggleSelectedIndex(
ToggleSelectedEvent event, Emitter<OneTouchState> emit) {
emit(LoadingInitialState()); emit(LoadingInitialState());
selectedTabIndex = event.index; selectedTabIndex = event.index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex)); emit(ChangeSlidingSegmentState(value: selectedTabIndex));
@ -338,7 +365,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
List<GroupOneTouchModel> groupOneTouchList = []; List<GroupOneTouchModel> groupOneTouchList = [];
bool allSwitchesOn = true; bool allSwitchesOn = true;
void _fetchOneTouchWizardStatus(InitialWizardEvent event, Emitter<OneTouchState> emit) async { void _fetchOneTouchWizardStatus(
InitialWizardEvent event, Emitter<OneTouchState> emit) async {
emit(LoadingInitialState()); emit(LoadingInitialState());
try { try {
devicesList = []; devicesList = [];
@ -348,7 +376,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
HomeCubit.getInstance().selectedSpace?.id ?? '', '1GT'); HomeCubit.getInstance().selectedSpace?.id ?? '', '1GT');
for (int i = 0; i < devicesList.length; i++) { for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? ''); var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = []; List<StatusModel> statusModelList = [];
for (var status in response['status']) { for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status)); statusModelList.add(StatusModel.fromJson(status));
@ -369,15 +398,16 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
return true; return true;
}); });
} }
emit(UpdateGroupState(oneTouchList: groupOneTouchList, allSwitches: allSwitchesOn)); emit(UpdateGroupState(
oneTouchList: groupOneTouchList, allSwitches: allSwitchesOn));
} catch (e) { } catch (e) {
emit(FailedState(error: e.toString())); emit(FailedState(error: e.toString()));
return; return;
} }
} }
void _changeFirstWizardSwitch( void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
ChangeFirstWizardSwitchStatusEvent event, Emitter<OneTouchState> emit) async { Emitter<OneTouchState> emit) async {
emit(LoadingNewSate(oneTouchModel: deviceStatus)); emit(LoadingNewSate(oneTouchModel: deviceStatus));
try { try {
bool allSwitchesValue = true; bool allSwitchesValue = true;
@ -395,7 +425,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
value: !event.value, value: !event.value,
); );
emit(UpdateGroupState(oneTouchList: groupOneTouchList, allSwitches: allSwitchesValue)); emit(UpdateGroupState(
oneTouchList: groupOneTouchList, allSwitches: allSwitchesValue));
if (response['success']) { if (response['success']) {
add(InitialEvent(groupScreen: oneTouchGroup)); add(InitialEvent(groupScreen: oneTouchGroup));
} }
@ -413,10 +444,12 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
} }
// Emit the state with updated values // Emit the state with updated values
emit(UpdateGroupState(oneTouchList: groupOneTouchList, allSwitches: true)); emit(
UpdateGroupState(oneTouchList: groupOneTouchList, allSwitches: true));
// Get a list of all device IDs // Get a list of all device IDs
List<String> allDeviceIds = groupOneTouchList.map((device) => device.deviceId).toList(); List<String> allDeviceIds =
groupOneTouchList.map((device) => device.deviceId).toList();
// First call for switch_1 // First call for switch_1
final response1 = await DevicesAPI.deviceBatchController( final response1 = await DevicesAPI.deviceBatchController(
@ -445,10 +478,12 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
} }
// Emit the state with updated values // Emit the state with updated values
emit(UpdateGroupState(oneTouchList: groupOneTouchList, allSwitches: false)); emit(UpdateGroupState(
oneTouchList: groupOneTouchList, allSwitches: false));
// Get a list of all device IDs // Get a list of all device IDs
List<String> allDeviceIds = groupOneTouchList.map((device) => device.deviceId).toList(); List<String> allDeviceIds =
groupOneTouchList.map((device) => device.deviceId).toList();
// First call for switch_1 // First call for switch_1
final response1 = await DevicesAPI.deviceBatchController( final response1 = await DevicesAPI.deviceBatchController(
@ -472,7 +507,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
String statusSelected = ''; String statusSelected = '';
String optionSelected = ''; String optionSelected = '';
Future<void> _changeStatus(ChangeStatusEvent event, Emitter<OneTouchState> emit) async { Future<void> _changeStatus(
ChangeStatusEvent event, Emitter<OneTouchState> emit) async {
try { try {
emit(LoadingInitialState()); emit(LoadingInitialState());
@ -497,7 +533,10 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
final selectedControl = controlMap[optionSelected]?[statusSelected]; final selectedControl = controlMap[optionSelected]?[statusSelected];
if (selectedControl != null) { if (selectedControl != null) {
await DevicesAPI.controlDevice( await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: oneTouchId, code: optionSelected, value: selectedControl), DeviceControlModel(
deviceId: oneTouchId,
code: optionSelected,
value: selectedControl),
oneTouchId, oneTouchId,
); );
} else { } else {

View File

@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:math'; import 'dart:math';
import 'package:firebase_database/firebase_database.dart'; import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -37,7 +38,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
on<SelectTimeEvent>(selectTimeOfLinePassword); on<SelectTimeEvent>(selectTimeOfLinePassword);
on<SelectTimeOnlinePasswordEvent>(selectTimeOnlinePassword); on<SelectTimeOnlinePasswordEvent>(selectTimeOnlinePassword);
on<DeletePasswordEvent>(deletePassword); on<DeletePasswordEvent>(deletePassword);
on<GenerateAndSavePasswordTimeLimitEvent>(generateAndSavePasswordTimeLimited); on<GenerateAndSavePasswordTimeLimitEvent>(
generateAndSavePasswordTimeLimited);
on<GenerateAndSavePasswordOneTimeEvent>(generateAndSavePasswordOneTime); on<GenerateAndSavePasswordOneTimeEvent>(generateAndSavePasswordOneTime);
on<ToggleDaySelectionEvent>(toggleDaySelection); on<ToggleDaySelectionEvent>(toggleDaySelection);
on<RenamePasswordEvent>(_renamePassword); on<RenamePasswordEvent>(_renamePassword);
@ -59,7 +61,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
List<OfflinePasswordModel>? oneTimePasswords = []; List<OfflinePasswordModel>? oneTimePasswords = [];
List<OfflinePasswordModel>? timeLimitPasswords = []; List<OfflinePasswordModel>? timeLimitPasswords = [];
Future generate7DigitNumber(GeneratePasswordEvent event, Emitter<SmartDoorState> emit) async { Future generate7DigitNumber(
GeneratePasswordEvent event, Emitter<SmartDoorState> emit) async {
emit(LoadingInitialState()); emit(LoadingInitialState());
passwordController.clear(); passwordController.clear();
Random random = Random(); Random random = Random();
@ -71,7 +74,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
} }
Future generateAndSavePasswordOneTime( Future generateAndSavePasswordOneTime(
GenerateAndSavePasswordOneTimeEvent event, Emitter<SmartDoorState> emit) async { GenerateAndSavePasswordOneTimeEvent event,
Emitter<SmartDoorState> emit) async {
try { try {
if (isSavingPassword) return; if (isSavingPassword) return;
isSavingPassword = true; isSavingPassword = true;
@ -92,7 +96,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
} }
} }
void _fetchSmartDoorStatus(InitialEvent event, Emitter<SmartDoorState> emit) async { void _fetchSmartDoorStatus(
InitialEvent event, Emitter<SmartDoorState> emit) async {
try { try {
emit(LoadingInitialState()); emit(LoadingInitialState());
var response = await DevicesAPI.getDeviceStatus(deviceId); var response = await DevicesAPI.getDeviceStatus(deviceId);
@ -102,42 +107,63 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
} }
deviceStatus = SmartDoorModel.fromJson(statusModelList); deviceStatus = SmartDoorModel.fromJson(statusModelList);
emit(UpdateState(smartDoorModel: deviceStatus)); emit(UpdateState(smartDoorModel: deviceStatus));
// _listenToChanges(); _listenToChanges();
} catch (e) { } catch (e) {
emit(FailedState(errorMessage: e.toString())); emit(FailedState(errorMessage: e.toString()));
return; return;
} }
} }
_listenToChanges() { StreamSubscription<DatabaseEvent>? _streamSubscription;
Timer? _timer;
void _listenToChanges() {
try { try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$deviceId'); _streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$deviceId');
Stream<DatabaseEvent> stream = ref.onValue; Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) { _streamSubscription = stream.listen((DatabaseEvent event) async {
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>; if (_timer != null) {
await Future.delayed(const Duration(seconds: 2));
}
Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = []; List<StatusModel> statusList = [];
usersMap['status'].forEach((element) { usersMap['status'].forEach((element) {
statusList.add(StatusModel(code: element['code'], value: element['value'])); statusList
.add(StatusModel(code: element['code'], value: element['value']));
}); });
deviceStatus = SmartDoorModel.fromJson(statusList); deviceStatus = SmartDoorModel.fromJson(statusList);
add(DoorLockUpdated()); if (!isClosed) {
add(DoorLockUpdated());
}
}); });
} catch (_) {} } catch (_) {}
} }
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_doorLockUpdated(DoorLockUpdated event, Emitter<SmartDoorState> emit) { _doorLockUpdated(DoorLockUpdated event, Emitter<SmartDoorState> emit) {
unlockRequest = deviceStatus.unlockRequest; unlockRequest = deviceStatus.unlockRequest;
emit(UpdateState(smartDoorModel: deviceStatus)); 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());
await DevicesAPI.renamePass( await DevicesAPI.renamePass(
name: passwordNameController.text, doorLockUuid: deviceId, passwordId: passwordId); name: passwordNameController.text,
doorLockUuid: deviceId,
passwordId: passwordId);
add(InitialOneTimePassword()); add(InitialOneTimePassword());
add(InitialTimeLimitPassword()); add(InitialTimeLimitPassword());
emit(UpdateState(smartDoorModel: deviceStatus)); emit(UpdateState(smartDoorModel: deviceStatus));
@ -147,46 +173,58 @@ 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( var response = await DevicesAPI.getTemporaryPasswords(
deviceId, deviceId,
); );
if (response is List) { if (response is List) {
temporaryPasswords = response.map((item) => TemporaryPassword.fromJson(item)).toList();
} else if (response is Map && response.containsKey('data')) {
temporaryPasswords = temporaryPasswords =
(response['data'] as List).map((item) => TemporaryPassword.fromJson(item)).toList(); response.map((item) => TemporaryPassword.fromJson(item)).toList();
} else if (response is Map && response.containsKey('data')) {
temporaryPasswords = (response['data'] as List)
.map((item) => TemporaryPassword.fromJson(item))
.toList();
} }
emit(TemporaryPasswordsLoadedState(temporaryPassword: temporaryPasswords!)); emit(TemporaryPasswordsLoadedState(
temporaryPassword: temporaryPasswords!));
} catch (e) { } catch (e) {
emit(FailedState(errorMessage: e.toString())); emit(FailedState(errorMessage: e.toString()));
} }
} }
void getOneTimePasswords(InitialOneTimePassword event, Emitter<SmartDoorState> emit) async { void getOneTimePasswords(
InitialOneTimePassword event, Emitter<SmartDoorState> emit) async {
try { try {
emit(LoadingInitialState()); emit(LoadingInitialState());
var response = await DevicesAPI.getOneTimePasswords(deviceId); var response = await DevicesAPI.getOneTimePasswords(deviceId);
if (response is List) { if (response is List) {
oneTimePasswords = response.map((item) => OfflinePasswordModel.fromJson(item)).toList(); oneTimePasswords = response
.map((item) => OfflinePasswordModel.fromJson(item))
.toList();
} }
emit(TemporaryPasswordsLoadedState(temporaryPassword: temporaryPasswords!)); emit(TemporaryPasswordsLoadedState(
temporaryPassword: temporaryPasswords!));
} catch (e) { } catch (e) {
emit(FailedState(errorMessage: e.toString())); emit(FailedState(errorMessage: e.toString()));
} }
} }
void getTimeLimitPasswords(InitialTimeLimitPassword event, Emitter<SmartDoorState> emit) async { void getTimeLimitPasswords(
InitialTimeLimitPassword event, Emitter<SmartDoorState> emit) async {
try { try {
emit(LoadingInitialState()); emit(LoadingInitialState());
var response = await DevicesAPI.getTimeLimitPasswords(deviceId); var response = await DevicesAPI.getTimeLimitPasswords(deviceId);
if (response is List) { if (response is List) {
timeLimitPasswords = response.map((item) => OfflinePasswordModel.fromJson(item)).toList(); timeLimitPasswords = response
.map((item) => OfflinePasswordModel.fromJson(item))
.toList();
} }
emit(TemporaryPasswordsLoadedState(temporaryPassword: temporaryPasswords!)); emit(TemporaryPasswordsLoadedState(
temporaryPassword: temporaryPasswords!));
} catch (e) { } catch (e) {
emit(FailedState(errorMessage: e.toString())); emit(FailedState(errorMessage: e.toString()));
} }
@ -207,7 +245,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
return repeat; return repeat;
} }
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));
@ -230,7 +269,8 @@ 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(
context: event.context, context: event.context,
@ -260,20 +300,27 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
).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 &&
CustomSnackBar.displaySnackBar('Effective Time cannot be later than Expiration Time.'); selectedTimestamp > expirationTimeTimeStamp!) {
CustomSnackBar.displaySnackBar(
'Effective Time cannot be later than Expiration Time.');
} else { } else {
effectiveTime = effectiveTime = selectedDateTime
selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds .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( CustomSnackBar.displaySnackBar(
'Expiration Time cannot be earlier than Effective Time.'); 'Expiration Time cannot be earlier than Effective Time.');
} else { } else {
expirationTime = expirationTime = selectedDateTime
selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds .toString()
.split('.')
.first; // Remove seconds and milliseconds
expirationTimeTimeStamp = selectedTimestamp; expirationTimeTimeStamp = selectedTimestamp;
} }
} }
@ -329,20 +376,27 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
).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 &&
CustomSnackBar.displaySnackBar('Effective Time cannot be later than Expiration Time.'); selectedTimestamp > expirationTimeTimeStamp!) {
CustomSnackBar.displaySnackBar(
'Effective Time cannot be later than Expiration Time.');
} else { } else {
effectiveTime = effectiveTime = selectedDateTime
selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds .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( CustomSnackBar.displaySnackBar(
'Expiration Time cannot be earlier than Effective Time.'); 'Expiration Time cannot be earlier than Effective Time.');
} else { } else {
expirationTime = expirationTime = selectedDateTime
selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds .toString()
.split('.')
.first; // Remove seconds and milliseconds
expirationTimeTimeStamp = selectedTimestamp; expirationTimeTimeStamp = selectedTimestamp;
} }
} }
@ -351,7 +405,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
} }
} }
Future<void> savePassword(SavePasswordEvent event, Emitter<SmartDoorState> emit) async { Future<void> savePassword(
SavePasswordEvent event, Emitter<SmartDoorState> emit) async {
if (_validateInputs() || isSavingPassword) return; if (_validateInputs() || isSavingPassword) return;
try { try {
isSavingPassword = true; isSavingPassword = true;
@ -381,7 +436,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
} }
Future<void> generateAndSavePasswordTimeLimited( Future<void> generateAndSavePasswordTimeLimited(
GenerateAndSavePasswordTimeLimitEvent event, Emitter<SmartDoorState> emit) async { GenerateAndSavePasswordTimeLimitEvent event,
Emitter<SmartDoorState> emit) async {
if (timeLimitValidate() || isSavingPassword) return; if (timeLimitValidate() || isSavingPassword) return;
try { try {
isSavingPassword = true; isSavingPassword = true;
@ -407,10 +463,12 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
} }
} }
Future<void> deletePassword(DeletePasswordEvent event, Emitter<SmartDoorState> emit) async { Future<void> deletePassword(
DeletePasswordEvent event, Emitter<SmartDoorState> emit) async {
try { try {
emit(LoadingInitialState()); emit(LoadingInitialState());
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());
}); });
@ -445,7 +503,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
} }
if (repeat == true && (endTime == null || startTime == null)) { if (repeat == true && (endTime == null || startTime == null)) {
CustomSnackBar.displaySnackBar('Start Time and End time and the days required '); CustomSnackBar.displaySnackBar(
'Start Time and End time and the days required ');
return true; return true;
} }
return false; return false;

View File

@ -1,5 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.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';
@ -173,6 +174,7 @@ class SosBloc extends Bloc<SosEvent, SosState> {
); );
emit(UpdateState(sensor: deviceStatus)); emit(UpdateState(sensor: deviceStatus));
Future.delayed(const Duration(milliseconds: 500)); Future.delayed(const Duration(milliseconds: 500));
// _listenToChanges();
} catch (e) { } catch (e) {
emit(SosFailedState(errorMessage: e.toString())); emit(SosFailedState(errorMessage: e.toString()));
return; return;
@ -434,4 +436,39 @@ class SosBloc extends Bloc<SosEvent, SosState> {
emit(SosFailedState(errorMessage: e.toString())); emit(SosFailedState(errorMessage: e.toString()));
} }
} }
//real-time db
// StreamSubscription<DatabaseEvent>? _streamSubscription;
// Timer? _timer;
// void _listenToChanges() {
// try {
// _streamSubscription?.cancel();
// DatabaseReference ref =
// FirebaseDatabase.instance.ref('device-status/$sosId');
// Stream<DatabaseEvent> stream = ref.onValue;
// _streamSubscription = 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 = SosModel.fromJson(statusList);
// });
// } catch (_) {}
// }
// @override
// Future<void> close() async {
// _streamSubscription?.cancel();
// _streamSubscription = null;
// return super.close();
// }
} }

View File

@ -31,7 +31,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
List<GroupThreeGangModel> groupThreeGangList = []; List<GroupThreeGangModel> groupThreeGangList = [];
bool allSwitchesOn = true; bool allSwitchesOn = true;
ThreeGangBloc({required this.threeGangId, required this.switchCode}) : super(InitialState()) { ThreeGangBloc({required this.threeGangId, required this.switchCode})
: super(InitialState()) {
on<InitialEvent>(_fetchThreeGangStatus); on<InitialEvent>(_fetchThreeGangStatus);
on<ThreeGangUpdated>(_threeGangUpdated); on<ThreeGangUpdated>(_threeGangUpdated);
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch); on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
@ -57,7 +58,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
on<ToggleCreateScheduleEvent>(toggleCreateSchedule); on<ToggleCreateScheduleEvent>(toggleCreateSchedule);
} }
void _fetchThreeGangStatus(InitialEvent event, Emitter<ThreeGangState> emit) async { void _fetchThreeGangStatus(
InitialEvent event, Emitter<ThreeGangState> emit) async {
emit(LoadingInitialState()); emit(LoadingInitialState());
try { try {
threeGangGroup = event.groupScreen; threeGangGroup = event.groupScreen;
@ -69,7 +71,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
HomeCubit.getInstance().selectedSpace?.id ?? '', '3G'); HomeCubit.getInstance().selectedSpace?.id ?? '', '3G');
for (int i = 0; i < devicesList.length; i++) { for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? ''); var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = []; List<StatusModel> statusModelList = [];
for (var status in response['status']) { for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status)); statusModelList.add(StatusModel.fromJson(status));
@ -86,13 +89,16 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
if (groupThreeGangList.isNotEmpty) { if (groupThreeGangList.isNotEmpty) {
groupThreeGangList.firstWhere((element) { groupThreeGangList.firstWhere((element) {
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) { if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesOn = false; allSwitchesOn = false;
} }
return true; return true;
}); });
} }
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: allSwitchesOn)); emit(UpdateGroupState(
threeGangList: groupThreeGangList, allSwitches: allSwitchesOn));
} else { } else {
var response = await DevicesAPI.getDeviceStatus(threeGangId); var response = await DevicesAPI.getDeviceStatus(threeGangId);
List<StatusModel> statusModelList = []; List<StatusModel> statusModelList = [];
@ -101,7 +107,7 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
} }
deviceStatus = ThreeGangModel.fromJson(statusModelList); deviceStatus = ThreeGangModel.fromJson(statusModelList);
emit(UpdateState(threeGangModel: deviceStatus)); emit(UpdateState(threeGangModel: deviceStatus));
// _listenToChanges(); _listenToChanges();
} }
} catch (e) { } catch (e) {
emit(FailedState(error: e.toString())); emit(FailedState(error: e.toString()));
@ -109,22 +115,26 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
} }
} }
_listenToChanges() { StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges() {
try { try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$threeGangId'); _streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$threeGangId');
Stream<DatabaseEvent> stream = ref.onValue; Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) async { _streamSubscription = stream.listen((DatabaseEvent event) async {
if (_timer != null) { if (_timer != null) {
await Future.delayed(const Duration(seconds: 2)); await Future.delayed(const Duration(seconds: 1));
} }
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>; Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = []; List<StatusModel> statusList = [];
usersMap['status'].forEach((element) { usersMap['status'].forEach((element) {
statusList.add(StatusModel(code: element['code'], value: element['value'])); statusList
.add(StatusModel(code: element['code'], value: element['value']));
}); });
deviceStatus = ThreeGangModel.fromJson(statusList); deviceStatus = ThreeGangModel.fromJson(statusList);
if (!isClosed) { if (!isClosed) {
add(ThreeGangUpdated()); add(ThreeGangUpdated());
@ -133,11 +143,19 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
} catch (_) {} } catch (_) {}
} }
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_threeGangUpdated(ThreeGangUpdated event, Emitter<ThreeGangState> emit) { _threeGangUpdated(ThreeGangUpdated event, Emitter<ThreeGangState> emit) {
emit(UpdateState(threeGangModel: deviceStatus)); 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 {
if (threeGangGroup) { if (threeGangGroup) {
@ -146,11 +164,14 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
if (element.deviceId == event.deviceId) { if (element.deviceId == event.deviceId) {
element.firstSwitch = !event.value; element.firstSwitch = !event.value;
} }
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) { if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesValue = false; allSwitchesValue = false;
} }
}); });
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: allSwitchesValue)); emit(UpdateGroupState(
threeGangList: groupThreeGangList, allSwitches: allSwitchesValue));
} else { } else {
deviceStatus.firstSwitch = !event.value; deviceStatus.firstSwitch = !event.value;
emit(UpdateState(threeGangModel: deviceStatus)); emit(UpdateState(threeGangModel: deviceStatus));
@ -187,11 +208,14 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
if (element.deviceId == event.deviceId) { if (element.deviceId == event.deviceId) {
element.secondSwitch = !event.value; element.secondSwitch = !event.value;
} }
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) { if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesValue = false; allSwitchesValue = false;
} }
}); });
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: allSwitchesValue)); emit(UpdateGroupState(
threeGangList: groupThreeGangList, allSwitches: allSwitchesValue));
} else { } else {
deviceStatus.secondSwitch = !event.value; deviceStatus.secondSwitch = !event.value;
emit(UpdateState(threeGangModel: deviceStatus)); emit(UpdateState(threeGangModel: deviceStatus));
@ -217,7 +241,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
} }
} }
void _changeThirdSwitch(ChangeThirdSwitchStatusEvent event, Emitter<ThreeGangState> emit) async { void _changeThirdSwitch(
ChangeThirdSwitchStatusEvent event, Emitter<ThreeGangState> emit) async {
emit(LoadingNewSate(threeGangModel: deviceStatus)); emit(LoadingNewSate(threeGangModel: deviceStatus));
try { try {
if (threeGangGroup) { if (threeGangGroup) {
@ -226,11 +251,14 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
if (element.deviceId == event.deviceId) { if (element.deviceId == event.deviceId) {
element.thirdSwitch = !event.value; element.thirdSwitch = !event.value;
} }
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) { if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesValue = false; allSwitchesValue = false;
} }
}); });
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: allSwitchesValue)); emit(UpdateGroupState(
threeGangList: groupThreeGangList, allSwitches: allSwitchesValue));
} else { } else {
deviceStatus.thirdSwitch = !event.value; deviceStatus.thirdSwitch = !event.value;
emit(UpdateState(threeGangModel: deviceStatus)); emit(UpdateState(threeGangModel: deviceStatus));
@ -269,15 +297,21 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
final response = await Future.wait([ final response = await Future.wait([
DevicesAPI.controlDevice( DevicesAPI.controlDevice(
DeviceControlModel( DeviceControlModel(
deviceId: threeGangId, code: 'switch_1', value: deviceStatus.firstSwitch), deviceId: threeGangId,
code: 'switch_1',
value: deviceStatus.firstSwitch),
threeGangId), threeGangId),
DevicesAPI.controlDevice( DevicesAPI.controlDevice(
DeviceControlModel( DeviceControlModel(
deviceId: threeGangId, code: 'switch_2', value: deviceStatus.secondSwitch), deviceId: threeGangId,
code: 'switch_2',
value: deviceStatus.secondSwitch),
threeGangId), threeGangId),
DevicesAPI.controlDevice( DevicesAPI.controlDevice(
DeviceControlModel( DeviceControlModel(
deviceId: threeGangId, code: 'switch_3', value: deviceStatus.thirdSwitch), deviceId: threeGangId,
code: 'switch_3',
value: deviceStatus.thirdSwitch),
threeGangId), threeGangId),
]); ]);
@ -303,15 +337,21 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
final response = await Future.wait([ final response = await Future.wait([
DevicesAPI.controlDevice( DevicesAPI.controlDevice(
DeviceControlModel( DeviceControlModel(
deviceId: threeGangId, code: 'switch_1', value: deviceStatus.firstSwitch), deviceId: threeGangId,
code: 'switch_1',
value: deviceStatus.firstSwitch),
threeGangId), threeGangId),
DevicesAPI.controlDevice( DevicesAPI.controlDevice(
DeviceControlModel( DeviceControlModel(
deviceId: threeGangId, code: 'switch_2', value: deviceStatus.secondSwitch), deviceId: threeGangId,
code: 'switch_2',
value: deviceStatus.secondSwitch),
threeGangId), threeGangId),
DevicesAPI.controlDevice( DevicesAPI.controlDevice(
DeviceControlModel( DeviceControlModel(
deviceId: threeGangId, code: 'switch_3', value: deviceStatus.thirdSwitch), deviceId: threeGangId,
code: 'switch_3',
value: deviceStatus.thirdSwitch),
threeGangId), threeGangId),
]); ]);
@ -333,9 +373,11 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
groupThreeGangList[i].secondSwitch = true; groupThreeGangList[i].secondSwitch = true;
groupThreeGangList[i].thirdSwitch = true; groupThreeGangList[i].thirdSwitch = true;
} }
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: true)); emit(UpdateGroupState(
threeGangList: groupThreeGangList, allSwitches: true));
List<String> allDeviceIds = groupThreeGangList.map((device) => device.deviceId).toList(); List<String> allDeviceIds =
groupThreeGangList.map((device) => device.deviceId).toList();
final response1 = await DevicesAPI.deviceBatchController( final response1 = await DevicesAPI.deviceBatchController(
code: 'switch_1', code: 'switch_1',
@ -365,7 +407,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
} }
} }
void _groupAllOff(GroupAllOffEvent event, Emitter<ThreeGangState> emit) async { void _groupAllOff(
GroupAllOffEvent event, Emitter<ThreeGangState> emit) async {
emit(LoadingNewSate(threeGangModel: deviceStatus)); emit(LoadingNewSate(threeGangModel: deviceStatus));
try { try {
for (int i = 0; i < groupThreeGangList.length; i++) { for (int i = 0; i < groupThreeGangList.length; i++) {
@ -373,8 +416,10 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
groupThreeGangList[i].secondSwitch = false; groupThreeGangList[i].secondSwitch = false;
groupThreeGangList[i].thirdSwitch = false; groupThreeGangList[i].thirdSwitch = false;
} }
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: false)); emit(UpdateGroupState(
List<String> allDeviceIds = groupThreeGangList.map((device) => device.deviceId).toList(); threeGangList: groupThreeGangList, allSwitches: false));
List<String> allDeviceIds =
groupThreeGangList.map((device) => device.deviceId).toList();
final response1 = await DevicesAPI.deviceBatchController( final response1 = await DevicesAPI.deviceBatchController(
code: 'switch_1', code: 'switch_1',
@ -404,17 +449,20 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
} }
} }
void _changeSliding(ChangeSlidingSegment event, Emitter<ThreeGangState> emit) async { void _changeSliding(
ChangeSlidingSegment event, Emitter<ThreeGangState> emit) async {
emit(ChangeSlidingSegmentState(value: event.value)); emit(ChangeSlidingSegmentState(value: event.value));
} }
void _setCounterValue(SetCounterValue event, Emitter<ThreeGangState> emit) async { void _setCounterValue(
SetCounterValue event, Emitter<ThreeGangState> emit) async {
emit(LoadingNewSate(threeGangModel: deviceStatus)); emit(LoadingNewSate(threeGangModel: deviceStatus));
int seconds = 0; int seconds = 0;
try { try {
seconds = event.duration.inSeconds; seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice( final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: threeGangId, code: event.deviceCode, value: seconds), DeviceControlModel(
deviceId: threeGangId, code: event.deviceCode, value: seconds),
threeGangId); threeGangId);
if (response['success'] ?? false) { if (response['success'] ?? false) {
@ -441,7 +489,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
} }
} }
void _getCounterValue(GetCounterEvent event, Emitter<ThreeGangState> emit) async { void _getCounterValue(
GetCounterEvent event, Emitter<ThreeGangState> emit) async {
emit(LoadingInitialState()); emit(LoadingInitialState());
try { try {
var response = await DevicesAPI.getDeviceStatus(threeGangId); var response = await DevicesAPI.getDeviceStatus(threeGangId);
@ -551,7 +600,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
deviceId: threeGangId, deviceId: threeGangId,
); );
List<dynamic> jsonData = response; List<dynamic> jsonData = response;
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList(); listSchedule =
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
emit(InitialState()); emit(InitialState());
} on DioException catch (e) { } on DioException catch (e) {
final errorData = e.response!.data; final errorData = e.response!.data;
@ -562,12 +612,13 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
int? getTimeStampWithoutSeconds(DateTime? dateTime) { int? getTimeStampWithoutSeconds(DateTime? dateTime) {
if (dateTime == null) return null; if (dateTime == null) return null;
DateTime dateTimeWithoutSeconds = DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute); dateTime.day, dateTime.hour, dateTime.minute);
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000; return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
} }
Future toggleChange(ToggleScheduleEvent event, Emitter<ThreeGangState> emit) async { Future toggleChange(
ToggleScheduleEvent event, Emitter<ThreeGangState> emit) async {
try { try {
emit(LoadingInitialState()); emit(LoadingInitialState());
final response = await DevicesAPI.changeSchedule( final response = await DevicesAPI.changeSchedule(
@ -586,7 +637,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
} }
} }
Future deleteSchedule(DeleteScheduleEvent event, Emitter<ThreeGangState> emit) async { Future deleteSchedule(
DeleteScheduleEvent event, Emitter<ThreeGangState> emit) async {
try { try {
emit(LoadingInitialState()); emit(LoadingInitialState());
final response = await DevicesAPI.deleteSchedule( final response = await DevicesAPI.deleteSchedule(
@ -606,13 +658,15 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
} }
} }
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<ThreeGangState> emit) { void toggleSelectedIndex(
ToggleSelectedEvent event, Emitter<ThreeGangState> emit) {
emit(LoadingInitialState()); emit(LoadingInitialState());
selectedTabIndex = event.index; selectedTabIndex = event.index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex)); emit(ChangeSlidingSegmentState(value: selectedTabIndex));
} }
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<ThreeGangState> emit) { void toggleCreateSchedule(
ToggleCreateScheduleEvent event, Emitter<ThreeGangState> emit) {
emit(LoadingInitialState()); emit(LoadingInitialState());
createSchedule = !createSchedule; createSchedule = !createSchedule;
selectedDays.clear(); selectedDays.clear();

View File

@ -38,7 +38,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
List<GroupThreeTouchModel> groupThreeTouchList = []; List<GroupThreeTouchModel> groupThreeTouchList = [];
bool allSwitchesOn = true; bool allSwitchesOn = true;
ThreeTouchBloc({required this.threeTouchId, required this.switchCode}) : super(InitialState()) { ThreeTouchBloc({required this.threeTouchId, required this.switchCode})
: super(InitialState()) {
on<InitialEvent>(_fetchThreeTouchStatus); on<InitialEvent>(_fetchThreeTouchStatus);
on<ThreeTouchUpdated>(_threeTouchUpdated); on<ThreeTouchUpdated>(_threeTouchUpdated);
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch); on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
@ -63,7 +64,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
on<ChangeStatusEvent>(_changeStatus); on<ChangeStatusEvent>(_changeStatus);
} }
void _fetchThreeTouchStatus(InitialEvent event, Emitter<ThreeTouchState> emit) async { void _fetchThreeTouchStatus(
InitialEvent event, Emitter<ThreeTouchState> emit) async {
emit(LoadingInitialState()); emit(LoadingInitialState());
try { try {
threeTouchGroup = event.groupScreen; threeTouchGroup = event.groupScreen;
@ -75,7 +77,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
HomeCubit.getInstance().selectedSpace?.id ?? '', '3GT'); HomeCubit.getInstance().selectedSpace?.id ?? '', '3GT');
for (int i = 0; i < devicesList.length; i++) { for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? ''); var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = []; List<StatusModel> statusModelList = [];
for (var status in response['status']) { for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status)); statusModelList.add(StatusModel.fromJson(status));
@ -92,13 +95,16 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
if (groupThreeTouchList.isNotEmpty) { if (groupThreeTouchList.isNotEmpty) {
groupThreeTouchList.firstWhere((element) { groupThreeTouchList.firstWhere((element) {
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) { if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesOn = false; allSwitchesOn = false;
} }
return true; return true;
}); });
} }
emit(UpdateGroupState(threeTouchList: groupThreeTouchList, allSwitches: allSwitchesOn)); emit(UpdateGroupState(
threeTouchList: groupThreeTouchList, allSwitches: allSwitchesOn));
} else { } else {
var response = await DevicesAPI.getDeviceStatus(threeTouchId); var response = await DevicesAPI.getDeviceStatus(threeTouchId);
List<StatusModel> statusModelList = []; List<StatusModel> statusModelList = [];
@ -107,7 +113,7 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
} }
deviceStatus = ThreeTouchModel.fromJson(statusModelList); deviceStatus = ThreeTouchModel.fromJson(statusModelList);
emit(UpdateState(threeTouchModel: deviceStatus)); emit(UpdateState(threeTouchModel: deviceStatus));
// _listenToChanges(); _listenToChanges();
} }
} catch (e) { } catch (e) {
emit(FailedState(error: e.toString())); emit(FailedState(error: e.toString()));
@ -117,18 +123,21 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
_listenToChanges() { _listenToChanges() {
try { try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$threeTouchId'); DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$threeTouchId');
Stream<DatabaseEvent> stream = ref.onValue; Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) async { stream.listen((DatabaseEvent event) async {
if (_timer != null) { if (_timer != null) {
await Future.delayed(const Duration(seconds: 2)); await Future.delayed(const Duration(seconds: 2));
} }
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>; Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = []; List<StatusModel> statusList = [];
usersMap['status'].forEach((element) { usersMap['status'].forEach((element) {
statusList.add(StatusModel(code: element['code'], value: element['value'])); statusList
.add(StatusModel(code: element['code'], value: element['value']));
}); });
deviceStatus = ThreeTouchModel.fromJson(statusList); deviceStatus = ThreeTouchModel.fromJson(statusList);
@ -143,7 +152,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
emit(UpdateState(threeTouchModel: deviceStatus)); emit(UpdateState(threeTouchModel: deviceStatus));
} }
void _changeFirstSwitch(ChangeFirstSwitchStatusEvent event, Emitter<ThreeTouchState> emit) async { void _changeFirstSwitch(
ChangeFirstSwitchStatusEvent event, Emitter<ThreeTouchState> emit) async {
emit(LoadingNewSate(threeTouchModel: deviceStatus)); emit(LoadingNewSate(threeTouchModel: deviceStatus));
try { try {
if (threeTouchGroup) { if (threeTouchGroup) {
@ -152,11 +162,15 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
if (element.deviceId == event.deviceId) { if (element.deviceId == event.deviceId) {
element.firstSwitch = !event.value; element.firstSwitch = !event.value;
} }
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) { if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesValue = false; allSwitchesValue = false;
} }
}); });
emit(UpdateGroupState(threeTouchList: groupThreeTouchList, allSwitches: allSwitchesValue)); emit(UpdateGroupState(
threeTouchList: groupThreeTouchList,
allSwitches: allSwitchesValue));
} else { } else {
deviceStatus.firstSwitch = !event.value; deviceStatus.firstSwitch = !event.value;
emit(UpdateState(threeTouchModel: deviceStatus)); emit(UpdateState(threeTouchModel: deviceStatus));
@ -183,8 +197,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
} }
} }
void _changeSecondSwitch( void _changeSecondSwitch(ChangeSecondSwitchStatusEvent event,
ChangeSecondSwitchStatusEvent event, Emitter<ThreeTouchState> emit) async { Emitter<ThreeTouchState> emit) async {
emit(LoadingNewSate(threeTouchModel: deviceStatus)); emit(LoadingNewSate(threeTouchModel: deviceStatus));
try { try {
if (threeTouchGroup) { if (threeTouchGroup) {
@ -193,11 +207,15 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
if (element.deviceId == event.deviceId) { if (element.deviceId == event.deviceId) {
element.secondSwitch = !event.value; element.secondSwitch = !event.value;
} }
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) { if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesValue = false; allSwitchesValue = false;
} }
}); });
emit(UpdateGroupState(threeTouchList: groupThreeTouchList, allSwitches: allSwitchesValue)); emit(UpdateGroupState(
threeTouchList: groupThreeTouchList,
allSwitches: allSwitchesValue));
} else { } else {
deviceStatus.secondSwitch = !event.value; deviceStatus.secondSwitch = !event.value;
emit(UpdateState(threeTouchModel: deviceStatus)); emit(UpdateState(threeTouchModel: deviceStatus));
@ -223,7 +241,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
} }
} }
void _changeThirdSwitch(ChangeThirdSwitchStatusEvent event, Emitter<ThreeTouchState> emit) async { void _changeThirdSwitch(
ChangeThirdSwitchStatusEvent event, Emitter<ThreeTouchState> emit) async {
emit(LoadingNewSate(threeTouchModel: deviceStatus)); emit(LoadingNewSate(threeTouchModel: deviceStatus));
try { try {
if (threeTouchGroup) { if (threeTouchGroup) {
@ -232,11 +251,15 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
if (element.deviceId == event.deviceId) { if (element.deviceId == event.deviceId) {
element.thirdSwitch = !event.value; element.thirdSwitch = !event.value;
} }
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) { if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesValue = false; allSwitchesValue = false;
} }
}); });
emit(UpdateGroupState(threeTouchList: groupThreeTouchList, allSwitches: allSwitchesValue)); emit(UpdateGroupState(
threeTouchList: groupThreeTouchList,
allSwitches: allSwitchesValue));
} else { } else {
deviceStatus.thirdSwitch = !event.value; deviceStatus.thirdSwitch = !event.value;
emit(UpdateState(threeTouchModel: deviceStatus)); emit(UpdateState(threeTouchModel: deviceStatus));
@ -275,15 +298,21 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
final response = await Future.wait([ final response = await Future.wait([
DevicesAPI.controlDevice( DevicesAPI.controlDevice(
DeviceControlModel( DeviceControlModel(
deviceId: threeTouchId, code: 'switch_1', value: deviceStatus.firstSwitch), deviceId: threeTouchId,
code: 'switch_1',
value: deviceStatus.firstSwitch),
threeTouchId), threeTouchId),
DevicesAPI.controlDevice( DevicesAPI.controlDevice(
DeviceControlModel( DeviceControlModel(
deviceId: threeTouchId, code: 'switch_2', value: deviceStatus.secondSwitch), deviceId: threeTouchId,
code: 'switch_2',
value: deviceStatus.secondSwitch),
threeTouchId), threeTouchId),
DevicesAPI.controlDevice( DevicesAPI.controlDevice(
DeviceControlModel( DeviceControlModel(
deviceId: threeTouchId, code: 'switch_3', value: deviceStatus.thirdSwitch), deviceId: threeTouchId,
code: 'switch_3',
value: deviceStatus.thirdSwitch),
threeTouchId), threeTouchId),
]); ]);
@ -309,15 +338,21 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
final response = await Future.wait([ final response = await Future.wait([
DevicesAPI.controlDevice( DevicesAPI.controlDevice(
DeviceControlModel( DeviceControlModel(
deviceId: threeTouchId, code: 'switch_1', value: deviceStatus.firstSwitch), deviceId: threeTouchId,
code: 'switch_1',
value: deviceStatus.firstSwitch),
threeTouchId), threeTouchId),
DevicesAPI.controlDevice( DevicesAPI.controlDevice(
DeviceControlModel( DeviceControlModel(
deviceId: threeTouchId, code: 'switch_2', value: deviceStatus.secondSwitch), deviceId: threeTouchId,
code: 'switch_2',
value: deviceStatus.secondSwitch),
threeTouchId), threeTouchId),
DevicesAPI.controlDevice( DevicesAPI.controlDevice(
DeviceControlModel( DeviceControlModel(
deviceId: threeTouchId, code: 'switch_3', value: deviceStatus.thirdSwitch), deviceId: threeTouchId,
code: 'switch_3',
value: deviceStatus.thirdSwitch),
threeTouchId), threeTouchId),
]); ]);
@ -339,8 +374,10 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
groupThreeTouchList[i].secondSwitch = true; groupThreeTouchList[i].secondSwitch = true;
groupThreeTouchList[i].thirdSwitch = true; groupThreeTouchList[i].thirdSwitch = true;
} }
emit(UpdateGroupState(threeTouchList: groupThreeTouchList, allSwitches: true)); emit(UpdateGroupState(
List<String> allDeviceIds = groupThreeTouchList.map((device) => device.deviceId).toList(); threeTouchList: groupThreeTouchList, allSwitches: true));
List<String> allDeviceIds =
groupThreeTouchList.map((device) => device.deviceId).toList();
final response1 = await DevicesAPI.deviceBatchController( final response1 = await DevicesAPI.deviceBatchController(
code: 'switch_1', code: 'switch_1',
devicesUuid: allDeviceIds, devicesUuid: allDeviceIds,
@ -369,7 +406,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
} }
} }
void _groupAllOff(GroupAllOffEvent event, Emitter<ThreeTouchState> emit) async { void _groupAllOff(
GroupAllOffEvent event, Emitter<ThreeTouchState> emit) async {
emit(LoadingNewSate(threeTouchModel: deviceStatus)); emit(LoadingNewSate(threeTouchModel: deviceStatus));
try { try {
for (int i = 0; i < groupThreeTouchList.length; i++) { for (int i = 0; i < groupThreeTouchList.length; i++) {
@ -377,8 +415,10 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
groupThreeTouchList[i].secondSwitch = false; groupThreeTouchList[i].secondSwitch = false;
groupThreeTouchList[i].thirdSwitch = false; groupThreeTouchList[i].thirdSwitch = false;
} }
List<String> allDeviceIds = groupThreeTouchList.map((device) => device.deviceId).toList(); List<String> allDeviceIds =
emit(UpdateGroupState(threeTouchList: groupThreeTouchList, allSwitches: false)); groupThreeTouchList.map((device) => device.deviceId).toList();
emit(UpdateGroupState(
threeTouchList: groupThreeTouchList, allSwitches: false));
final response1 = await DevicesAPI.deviceBatchController( final response1 = await DevicesAPI.deviceBatchController(
code: 'switch_1', code: 'switch_1',
devicesUuid: allDeviceIds, devicesUuid: allDeviceIds,
@ -407,17 +447,20 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
} }
} }
void _changeSliding(ChangeSlidingSegment event, Emitter<ThreeTouchState> emit) async { void _changeSliding(
ChangeSlidingSegment event, Emitter<ThreeTouchState> emit) async {
emit(ChangeSlidingSegmentState(value: event.value)); emit(ChangeSlidingSegmentState(value: event.value));
} }
void _setCounterValue(SetCounterValue event, Emitter<ThreeTouchState> emit) async { void _setCounterValue(
SetCounterValue event, Emitter<ThreeTouchState> emit) async {
emit(LoadingNewSate(threeTouchModel: deviceStatus)); emit(LoadingNewSate(threeTouchModel: deviceStatus));
int seconds = 0; int seconds = 0;
try { try {
seconds = event.duration.inSeconds; seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice( final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: threeTouchId, code: event.deviceCode, value: seconds), DeviceControlModel(
deviceId: threeTouchId, code: event.deviceCode, value: seconds),
threeTouchId); threeTouchId);
if (response['success'] ?? false) { if (response['success'] ?? false) {
@ -444,7 +487,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
} }
} }
void _getCounterValue(GetCounterEvent event, Emitter<ThreeTouchState> emit) async { void _getCounterValue(
GetCounterEvent event, Emitter<ThreeTouchState> emit) async {
emit(LoadingInitialState()); emit(LoadingInitialState());
try { try {
var response = await DevicesAPI.getDeviceStatus(threeTouchId); var response = await DevicesAPI.getDeviceStatus(threeTouchId);
@ -554,7 +598,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
deviceId: threeTouchId, deviceId: threeTouchId,
); );
List<dynamic> jsonData = response; List<dynamic> jsonData = response;
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList(); listSchedule =
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
emit(InitialState()); emit(InitialState());
} on DioException catch (e) { } on DioException catch (e) {
final errorData = e.response!.data; final errorData = e.response!.data;
@ -565,12 +610,13 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
int? getTimeStampWithoutSeconds(DateTime? dateTime) { int? getTimeStampWithoutSeconds(DateTime? dateTime) {
if (dateTime == null) return null; if (dateTime == null) return null;
DateTime dateTimeWithoutSeconds = DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute); dateTime.day, dateTime.hour, dateTime.minute);
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000; return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
} }
Future toggleChange(ToggleScheduleEvent event, Emitter<ThreeTouchState> emit) async { Future toggleChange(
ToggleScheduleEvent event, Emitter<ThreeTouchState> emit) async {
try { try {
emit(LoadingInitialState()); emit(LoadingInitialState());
final response = await DevicesAPI.changeSchedule( final response = await DevicesAPI.changeSchedule(
@ -589,7 +635,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
} }
} }
Future deleteSchedule(DeleteScheduleEvent event, Emitter<ThreeTouchState> emit) async { Future deleteSchedule(
DeleteScheduleEvent event, Emitter<ThreeTouchState> emit) async {
try { try {
emit(LoadingInitialState()); emit(LoadingInitialState());
final response = await DevicesAPI.deleteSchedule( final response = await DevicesAPI.deleteSchedule(
@ -609,13 +656,15 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
} }
} }
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<ThreeTouchState> emit) { void toggleSelectedIndex(
ToggleSelectedEvent event, Emitter<ThreeTouchState> emit) {
emit(LoadingInitialState()); emit(LoadingInitialState());
selectedTabIndex = event.index; selectedTabIndex = event.index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex)); emit(ChangeSlidingSegmentState(value: selectedTabIndex));
} }
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<ThreeTouchState> emit) { void toggleCreateSchedule(
ToggleCreateScheduleEvent event, Emitter<ThreeTouchState> emit) {
emit(LoadingInitialState()); emit(LoadingInitialState());
createSchedule = !createSchedule; createSchedule = !createSchedule;
selectedDays.clear(); selectedDays.clear();
@ -633,7 +682,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
String statusSelected = ''; String statusSelected = '';
String optionSelected = ''; String optionSelected = '';
Future<void> _changeStatus(ChangeStatusEvent event, Emitter<ThreeTouchState> emit) async { Future<void> _changeStatus(
ChangeStatusEvent event, Emitter<ThreeTouchState> emit) async {
try { try {
emit(LoadingInitialState()); emit(LoadingInitialState());
final Map<String, Map<String, String>> controlMap = { final Map<String, Map<String, String>> controlMap = {
@ -667,11 +717,15 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
final selectedControl = controlMap[optionSelected]?[statusSelected]; final selectedControl = controlMap[optionSelected]?[statusSelected];
if (selectedControl != null) { if (selectedControl != null) {
await DevicesAPI.controlDevice( await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: threeTouchId, code: optionSelected, value: selectedControl), DeviceControlModel(
deviceId: threeTouchId,
code: optionSelected,
value: selectedControl),
threeTouchId, threeTouchId,
); );
} else { } else {
emit(const FailedState(error: 'Invalid statusSelected or optionSelected')); emit(const FailedState(
error: 'Invalid statusSelected or optionSelected'));
} }
} on DioException catch (e) { } on DioException catch (e) {
final errorData = e.response!.data; final errorData = e.response!.data;

View File

@ -35,7 +35,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
bool createSchedule = false; bool createSchedule = false;
List<ScheduleModel> listSchedule = []; List<ScheduleModel> listSchedule = [];
TwoGangBloc({required this.twoGangId, required this.switchCode}) : super(InitialState()) { TwoGangBloc({required this.twoGangId, required this.switchCode})
: super(InitialState()) {
on<InitialEvent>(_fetchTwoGangStatus); on<InitialEvent>(_fetchTwoGangStatus);
on<TwoGangUpdated>(_twoGangUpdated); on<TwoGangUpdated>(_twoGangUpdated);
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch); on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
@ -65,13 +66,15 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
int selectedTabIndex = 0; int selectedTabIndex = 0;
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<TwoGangState> emit) { void toggleSelectedIndex(
ToggleSelectedEvent event, Emitter<TwoGangState> emit) {
emit(LoadingInitialState()); emit(LoadingInitialState());
selectedTabIndex = event.index; selectedTabIndex = event.index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex)); emit(ChangeSlidingSegmentState(value: selectedTabIndex));
} }
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<TwoGangState> emit) { void toggleCreateSchedule(
ToggleCreateScheduleEvent event, Emitter<TwoGangState> emit) {
emit(LoadingInitialState()); emit(LoadingInitialState());
createSchedule = !createSchedule; createSchedule = !createSchedule;
selectedDays.clear(); selectedDays.clear();
@ -79,7 +82,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
emit(UpdateCreateScheduleState(createSchedule)); emit(UpdateCreateScheduleState(createSchedule));
} }
void _fetchTwoGangStatus(InitialEvent event, Emitter<TwoGangState> emit) async { void _fetchTwoGangStatus(
InitialEvent event, Emitter<TwoGangState> emit) async {
emit(LoadingInitialState()); emit(LoadingInitialState());
try { try {
var response = await DevicesAPI.getDeviceStatus(twoGangId); var response = await DevicesAPI.getDeviceStatus(twoGangId);
@ -89,42 +93,50 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
} }
deviceStatus = TwoGangModel.fromJson(statusModelList); deviceStatus = TwoGangModel.fromJson(statusModelList);
emit(UpdateState(twoGangModel: deviceStatus)); emit(UpdateState(twoGangModel: deviceStatus));
// _listenToChanges(); _listenToChanges(twoGangId);
} catch (e) { } catch (e) {
emit(FailedState(error: e.toString())); emit(FailedState(error: e.toString()));
return; return;
} }
} }
_listenToChanges() { StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges(String id) {
try { try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$twoGangId'); _streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$id');
Stream<DatabaseEvent> stream = ref.onValue; Stream<DatabaseEvent> stream = ref.onValue;
_streamSubscription = stream.listen((DatabaseEvent event) {
stream.listen((DatabaseEvent event) async { Map<dynamic, dynamic> usersMap =
if (_timer != null) { event.snapshot.value as Map<dynamic, dynamic>;
await Future.delayed(const Duration(seconds: 2));
}
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = []; List<StatusModel> statusList = [];
usersMap['status'].forEach((element) { usersMap['status'].forEach((element) {
statusList.add(StatusModel(code: element['code'], value: element['value'])); statusList
.add(StatusModel(code: element['code'], value: element['value']));
}); });
deviceStatus = TwoGangModel.fromJson(statusList); deviceStatus = TwoGangModel.fromJson(statusList);
if (!isClosed) { add(TwoGangUpdated());
add(TwoGangUpdated());
}
}); });
} catch (_) {} } catch (_) {}
} }
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_twoGangUpdated(TwoGangUpdated event, Emitter<TwoGangState> emit) { _twoGangUpdated(TwoGangUpdated event, Emitter<TwoGangState> emit) {
emit(LoadingNewSate(twoGangModel: deviceStatus));
emit(UpdateState(twoGangModel: deviceStatus)); emit(UpdateState(twoGangModel: deviceStatus));
} }
void _changeFirstSwitch(ChangeFirstSwitchStatusEvent event, Emitter<TwoGangState> emit) async { void _changeFirstSwitch(
ChangeFirstSwitchStatusEvent event, Emitter<TwoGangState> emit) async {
emit(LoadingNewSate(twoGangModel: deviceStatus)); emit(LoadingNewSate(twoGangModel: deviceStatus));
try { try {
deviceStatus.firstSwitch = !event.value; deviceStatus.firstSwitch = !event.value;
@ -135,7 +147,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
_timer = Timer(const Duration(milliseconds: 100), () async { _timer = Timer(const Duration(milliseconds: 100), () async {
final response = await DevicesAPI.controlDevice( final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: twoGangId, code: 'switch_1', value: !event.value), DeviceControlModel(
deviceId: twoGangId, code: 'switch_1', value: !event.value),
twoGangId); twoGangId);
if (!response['success']) { if (!response['success']) {
@ -147,7 +160,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
} }
} }
void _changeSecondSwitch(ChangeSecondSwitchStatusEvent event, Emitter<TwoGangState> emit) async { void _changeSecondSwitch(
ChangeSecondSwitchStatusEvent event, Emitter<TwoGangState> emit) async {
emit(LoadingNewSate(twoGangModel: deviceStatus)); emit(LoadingNewSate(twoGangModel: deviceStatus));
try { try {
deviceStatus.secondSwitch = !event.value; deviceStatus.secondSwitch = !event.value;
@ -157,7 +171,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
} }
_timer = Timer(const Duration(milliseconds: 100), () async { _timer = Timer(const Duration(milliseconds: 100), () async {
final response = await DevicesAPI.controlDevice( final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: twoGangId, code: 'switch_2', value: !event.value), DeviceControlModel(
deviceId: twoGangId, code: 'switch_2', value: !event.value),
twoGangId); twoGangId);
if (!response['success']) { if (!response['success']) {
@ -180,11 +195,15 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
final response = await Future.wait([ final response = await Future.wait([
DevicesAPI.controlDevice( DevicesAPI.controlDevice(
DeviceControlModel( DeviceControlModel(
deviceId: twoGangId, code: 'switch_1', value: deviceStatus.firstSwitch), deviceId: twoGangId,
code: 'switch_1',
value: deviceStatus.firstSwitch),
twoGangId), twoGangId),
DevicesAPI.controlDevice( DevicesAPI.controlDevice(
DeviceControlModel( DeviceControlModel(
deviceId: twoGangId, code: 'switch_2', value: deviceStatus.secondSwitch), deviceId: twoGangId,
code: 'switch_2',
value: deviceStatus.secondSwitch),
twoGangId), twoGangId),
]); ]);
@ -207,11 +226,15 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
final response = await Future.wait([ final response = await Future.wait([
DevicesAPI.controlDevice( DevicesAPI.controlDevice(
DeviceControlModel( DeviceControlModel(
deviceId: twoGangId, code: 'switch_1', value: deviceStatus.firstSwitch), deviceId: twoGangId,
code: 'switch_1',
value: deviceStatus.firstSwitch),
twoGangId), twoGangId),
DevicesAPI.controlDevice( DevicesAPI.controlDevice(
DeviceControlModel( DeviceControlModel(
deviceId: twoGangId, code: 'switch_2', value: deviceStatus.secondSwitch), deviceId: twoGangId,
code: 'switch_2',
value: deviceStatus.secondSwitch),
twoGangId), twoGangId),
]); ]);
if (response.every((element) => !element['success'])) { if (response.every((element) => !element['success'])) {
@ -232,7 +255,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
groupTwoGangList[i].secondSwitch = true; groupTwoGangList[i].secondSwitch = true;
} }
emit(UpdateGroupState(twoGangList: groupTwoGangList, allSwitches: true)); emit(UpdateGroupState(twoGangList: groupTwoGangList, allSwitches: true));
List<String> allDeviceIds = groupTwoGangList.map((device) => device.deviceId).toList(); List<String> allDeviceIds =
groupTwoGangList.map((device) => device.deviceId).toList();
final response1 = await DevicesAPI.deviceBatchController( final response1 = await DevicesAPI.deviceBatchController(
code: 'switch_1', code: 'switch_1',
@ -267,7 +291,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
emit(UpdateGroupState(twoGangList: groupTwoGangList, allSwitches: false)); emit(UpdateGroupState(twoGangList: groupTwoGangList, allSwitches: false));
List<String> allDeviceIds = groupTwoGangList.map((device) => device.deviceId).toList(); List<String> allDeviceIds =
groupTwoGangList.map((device) => device.deviceId).toList();
final response1 = await DevicesAPI.deviceBatchController( final response1 = await DevicesAPI.deviceBatchController(
code: 'switch_1', code: 'switch_1',
@ -292,17 +317,20 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
} }
} }
void _changeSliding(ChangeSlidingSegment event, Emitter<TwoGangState> emit) async { void _changeSliding(
ChangeSlidingSegment event, Emitter<TwoGangState> emit) async {
emit(ChangeSlidingSegmentState(value: event.value)); emit(ChangeSlidingSegmentState(value: event.value));
} }
void _setCounterValue(SetCounterValue event, Emitter<TwoGangState> emit) async { void _setCounterValue(
SetCounterValue event, Emitter<TwoGangState> emit) async {
emit(LoadingNewSate(twoGangModel: deviceStatus)); emit(LoadingNewSate(twoGangModel: deviceStatus));
int seconds = 0; int seconds = 0;
try { try {
seconds = event.duration.inSeconds; seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice( final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: twoGangId, code: event.deviceCode, value: seconds), DeviceControlModel(
deviceId: twoGangId, code: event.deviceCode, value: seconds),
twoGangId); twoGangId);
if (response['success'] ?? false) { if (response['success'] ?? false) {
@ -327,7 +355,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
} }
} }
void _getCounterValue(GetCounterEvent event, Emitter<TwoGangState> emit) async { void _getCounterValue(
GetCounterEvent event, Emitter<TwoGangState> emit) async {
emit(LoadingInitialState()); emit(LoadingInitialState());
try { try {
add(GetScheduleEvent()); add(GetScheduleEvent());
@ -435,7 +464,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
deviceId: twoGangId, deviceId: twoGangId,
); );
List<dynamic> jsonData = response; List<dynamic> jsonData = response;
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList(); listSchedule =
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
emit(InitialState()); emit(InitialState());
} on DioException catch (e) { } on DioException catch (e) {
final errorData = e.response!.data; final errorData = e.response!.data;
@ -446,12 +476,13 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
int? getTimeStampWithoutSeconds(DateTime? dateTime) { int? getTimeStampWithoutSeconds(DateTime? dateTime) {
if (dateTime == null) return null; if (dateTime == null) return null;
DateTime dateTimeWithoutSeconds = DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute); dateTime.day, dateTime.hour, dateTime.minute);
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000; return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
} }
Future toggleRepeat(ToggleScheduleEvent event, Emitter<TwoGangState> emit) async { Future toggleRepeat(
ToggleScheduleEvent event, Emitter<TwoGangState> emit) async {
try { try {
emit(LoadingInitialState()); emit(LoadingInitialState());
final response = await DevicesAPI.changeSchedule( final response = await DevicesAPI.changeSchedule(
@ -470,7 +501,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
} }
} }
Future deleteSchedule(DeleteScheduleEvent event, Emitter<TwoGangState> emit) async { Future deleteSchedule(
DeleteScheduleEvent event, Emitter<TwoGangState> emit) async {
try { try {
emit(LoadingInitialState()); emit(LoadingInitialState());
final response = await DevicesAPI.deleteSchedule( final response = await DevicesAPI.deleteSchedule(
@ -490,7 +522,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
} }
} }
void _fetchTwoGangWizardStatus(InitialWizardEvent event, Emitter<TwoGangState> emit) async { void _fetchTwoGangWizardStatus(
InitialWizardEvent event, Emitter<TwoGangState> emit) async {
emit(LoadingInitialState()); emit(LoadingInitialState());
try { try {
devicesList = []; devicesList = [];
@ -500,7 +533,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
HomeCubit.getInstance().selectedSpace?.id ?? '', '2G'); HomeCubit.getInstance().selectedSpace?.id ?? '', '2G');
for (int i = 0; i < devicesList.length; i++) { for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? ''); var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = []; List<StatusModel> statusModelList = [];
for (var status in response['status']) { for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status)); statusModelList.add(StatusModel.fromJson(status));
@ -523,15 +557,16 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
return true; return true;
}); });
} }
emit(UpdateGroupState(twoGangList: groupTwoGangList, allSwitches: allSwitchesOn)); emit(UpdateGroupState(
twoGangList: groupTwoGangList, allSwitches: allSwitchesOn));
} catch (e) { } catch (e) {
emit(FailedState(error: e.toString())); emit(FailedState(error: e.toString()));
return; return;
} }
} }
void _changeFirstWizardSwitch( void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
ChangeFirstWizardSwitchStatusEvent event, Emitter<TwoGangState> emit) async { Emitter<TwoGangState> emit) async {
emit(LoadingNewSate(twoGangModel: deviceStatus)); emit(LoadingNewSate(twoGangModel: deviceStatus));
try { try {
bool allSwitchesValue = true; bool allSwitchesValue = true;
@ -544,9 +579,11 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
} }
}); });
emit(UpdateGroupState(twoGangList: groupTwoGangList, allSwitches: allSwitchesValue)); emit(UpdateGroupState(
twoGangList: groupTwoGangList, allSwitches: allSwitchesValue));
List<String> allDeviceIds = groupTwoGangList.map((device) => device.deviceId).toList(); List<String> allDeviceIds =
groupTwoGangList.map((device) => device.deviceId).toList();
final response = await DevicesAPI.deviceBatchController( final response = await DevicesAPI.deviceBatchController(
code: 'switch_1', code: 'switch_1',
devicesUuid: allDeviceIds, devicesUuid: allDeviceIds,
@ -561,8 +598,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
} }
} }
void _changeSecondWizardSwitch( void _changeSecondWizardSwitch(ChangeSecondWizardSwitchStatusEvent event,
ChangeSecondWizardSwitchStatusEvent event, Emitter<TwoGangState> emit) async { Emitter<TwoGangState> emit) async {
emit(LoadingNewSate(twoGangModel: deviceStatus)); emit(LoadingNewSate(twoGangModel: deviceStatus));
try { try {
bool allSwitchesValue = true; bool allSwitchesValue = true;
@ -574,9 +611,11 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
allSwitchesValue = false; allSwitchesValue = false;
} }
}); });
List<String> allDeviceIds = groupTwoGangList.map((device) => device.deviceId).toList(); List<String> allDeviceIds =
groupTwoGangList.map((device) => device.deviceId).toList();
emit(UpdateGroupState(twoGangList: groupTwoGangList, allSwitches: allSwitchesValue)); emit(UpdateGroupState(
twoGangList: groupTwoGangList, allSwitches: allSwitchesValue));
final response = await DevicesAPI.deviceBatchController( final response = await DevicesAPI.deviceBatchController(
code: 'switch_2', code: 'switch_2',

View File

@ -99,41 +99,61 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
} }
deviceStatus = TwoTouchModel.fromJson(statusModelList); deviceStatus = TwoTouchModel.fromJson(statusModelList);
emit(UpdateState(twoTouchModel: deviceStatus)); emit(UpdateState(twoTouchModel: deviceStatus));
// _listenToChanges(); _listenToChanges();
} catch (e) { } catch (e) {
emit(FailedState(error: e.toString())); emit(FailedState(error: e.toString()));
return; return;
} }
} }
_listenToChanges() { StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges() {
try { try {
_streamSubscription?.cancel();
DatabaseReference ref = DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$twoTouchId'); FirebaseDatabase.instance.ref('device-status/$twoTouchId');
Stream<DatabaseEvent> stream = ref.onValue; Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) async { _streamSubscription = stream.listen((DatabaseEvent event) async {
if (_timer != null) { if (_timer != null) {
await Future.delayed(const Duration(seconds: 2)); await Future.delayed(const Duration(seconds: 1));
} }
Map<dynamic, dynamic> usersMap = if (event.snapshot.value != null) {
event.snapshot.value as Map<dynamic, dynamic>; Map<dynamic, dynamic> usersMap =
List<StatusModel> statusList = []; event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = [];
usersMap['status'].forEach((element) { usersMap['status'].forEach((element) {
statusList statusList.add(
.add(StatusModel(code: element['code'], value: element['value'])); StatusModel(code: element['code'], value: element['value']));
}); });
var switch1Status = statusList.firstWhere(
(status) => status.code == "switch_1",
orElse: () => StatusModel(code: "switch_1", value: false));
var switch2Status = statusList.firstWhere(
(status) => status.code == "switch_2",
orElse: () => StatusModel(code: "switch_2", value: false));
deviceStatus.firstSwitch = switch1Status.value as bool;
deviceStatus.secondSwitch = switch2Status.value as bool;
deviceStatus = TwoTouchModel.fromJson(statusList);
if (!isClosed) {
add(TwoTouchUpdated()); add(TwoTouchUpdated());
} }
}); });
} catch (_) {} } catch (_) {
}
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
} }
_twoTouchUpdated(TwoTouchUpdated event, Emitter<TwoTouchState> emit) { _twoTouchUpdated(TwoTouchUpdated event, Emitter<TwoTouchState> emit) {
emit(LoadingInitialState());
emit(UpdateState(twoTouchModel: deviceStatus)); emit(UpdateState(twoTouchModel: deviceStatus));
} }

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:firebase_database/firebase_database.dart'; 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';
@ -21,7 +23,8 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
on<GetDeviceReportsEvent>(_getDeviceReports); on<GetDeviceReportsEvent>(_getDeviceReports);
} }
void _fetchCeilingSensorStatus(InitialEvent event, Emitter<WallSensorState> emit) async { void _fetchCeilingSensorStatus(
InitialEvent event, Emitter<WallSensorState> emit) async {
emit(LoadingInitialState()); emit(LoadingInitialState());
try { try {
var response = await DevicesAPI.getDeviceStatus(deviceId); var response = await DevicesAPI.getDeviceStatus(deviceId);
@ -31,41 +34,62 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
} }
deviceStatus = WallSensorModel.fromJson(statusModelList); deviceStatus = WallSensorModel.fromJson(statusModelList);
emit(UpdateState(wallSensorModel: deviceStatus)); emit(UpdateState(wallSensorModel: deviceStatus));
// _listenToChanges(); _listenToChanges();
} catch (e) { } catch (e) {
emit(FailedState(error: e.toString())); emit(FailedState(error: e.toString()));
return; return;
} }
} }
_listenToChanges() { Timer? _timer;
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges() {
try { try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$deviceId'); _streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$deviceId');
Stream<DatabaseEvent> stream = ref.onValue; Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) { _streamSubscription = stream.listen((DatabaseEvent event) async {
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>; if (_timer != null) {
await Future.delayed(const Duration(seconds: 2));
}
Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = []; List<StatusModel> statusList = [];
usersMap['status'].forEach((element) { usersMap['status'].forEach((element) {
statusList.add(StatusModel(code: element['code'], value: element['value'])); statusList
.add(StatusModel(code: element['code'], value: element['value']));
}); });
deviceStatus = WallSensorModel.fromJson(statusList); deviceStatus = WallSensorModel.fromJson(statusList);
add(WallSensorUpdatedEvent()); if (!isClosed) {
add(WallSensorUpdatedEvent());
}
}); });
} catch (_) {} } catch (_) {}
} }
_wallSensorUpdated(WallSensorUpdatedEvent event, Emitter<WallSensorState> emit) { @override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_wallSensorUpdated(
WallSensorUpdatedEvent event, Emitter<WallSensorState> emit) {
emit(UpdateState(wallSensorModel: deviceStatus)); 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 {
final response = await DevicesAPI.controlDevice( final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: deviceId, code: 'indicator', value: !event.value), deviceId); DeviceControlModel(
deviceId: deviceId, code: 'indicator', value: !event.value),
deviceId);
if (response['success'] ?? false) { if (response['success'] ?? false) {
deviceStatus.indicator = !event.value; deviceStatus.indicator = !event.value;
@ -74,11 +98,14 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
emit(UpdateState(wallSensorModel: deviceStatus)); emit(UpdateState(wallSensorModel: deviceStatus));
} }
void _changeValue(ChangeValueEvent event, Emitter<WallSensorState> emit) async { void _changeValue(
ChangeValueEvent event, Emitter<WallSensorState> emit) async {
emit(LoadingNewSate(wallSensorModel: deviceStatus)); emit(LoadingNewSate(wallSensorModel: deviceStatus));
try { try {
final response = await DevicesAPI.controlDevice( final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: deviceId, code: event.code, value: event.value), deviceId); DeviceControlModel(
deviceId: deviceId, code: event.code, value: event.value),
deviceId);
if (response['success'] ?? false) { if (response['success'] ?? false) {
if (event.code == 'far_detection') { if (event.code == 'far_detection') {
@ -93,7 +120,8 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
emit(UpdateState(wallSensorModel: deviceStatus)); emit(UpdateState(wallSensorModel: deviceStatus));
} }
void _getDeviceReports(GetDeviceReportsEvent event, Emitter<WallSensorState> emit) async { void _getDeviceReports(
GetDeviceReportsEvent event, Emitter<WallSensorState> emit) async {
emit(LoadingInitialState()); emit(LoadingInitialState());
try { try {

View File

@ -35,7 +35,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
List<ScheduleModel> listSchedule = []; List<ScheduleModel> listSchedule = [];
DateTime? selectedTime = DateTime.now(); DateTime? selectedTime = DateTime.now();
WaterHeaterBloc({required this.whId, required this.switchCode}) : super(WHInitialState()) { WaterHeaterBloc({required this.whId, required this.switchCode})
: super(WHInitialState()) {
on<WaterHeaterInitial>(_fetchWaterHeaterStatus); on<WaterHeaterInitial>(_fetchWaterHeaterStatus);
on<WaterHeaterSwitch>(_changeFirstSwitch); on<WaterHeaterSwitch>(_changeFirstSwitch);
on<SetCounterValue>(_setCounterValue); on<SetCounterValue>(_setCounterValue);
@ -60,7 +61,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
on<WaterHeaterUpdated>(_waterHeaterUpdated); on<WaterHeaterUpdated>(_waterHeaterUpdated);
} }
void _fetchWaterHeaterStatus(WaterHeaterInitial event, Emitter<WaterHeaterState> emit) async { void _fetchWaterHeaterStatus(
WaterHeaterInitial event, Emitter<WaterHeaterState> emit) async {
emit(WHLoadingState()); emit(WHLoadingState());
try { try {
var response = await DevicesAPI.getDeviceStatus(whId); var response = await DevicesAPI.getDeviceStatus(whId);
@ -72,29 +74,33 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
statusModelList, statusModelList,
); );
emit(UpdateState(whModel: deviceStatus)); emit(UpdateState(whModel: deviceStatus));
// _listenToChanges(); _listenToChanges();
} catch (e) { } catch (e) {
emit(WHFailedState(errorMessage: e.toString())); emit(WHFailedState(errorMessage: e.toString()));
return; return;
} }
} }
_listenToChanges() { //real-time db
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges() {
try { try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$whId'); _streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$whId');
Stream<DatabaseEvent> stream = ref.onValue; Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) async { _streamSubscription = stream.listen((DatabaseEvent event) async {
if (_timer != null) { if (_timer != null) {
await Future.delayed(const Duration(seconds: 2)); await Future.delayed(const Duration(seconds: 2));
} }
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>; Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = []; List<StatusModel> statusList = [];
usersMap['status'].forEach((element) { usersMap['status'].forEach((element) {
statusList.add(StatusModel(code: element['code'], value: element['value'])); statusList
.add(StatusModel(code: element['code'], value: element['value']));
}); });
deviceStatus = WHModel.fromJson(statusList); deviceStatus = WHModel.fromJson(statusList);
if (!isClosed) { if (!isClosed) {
add(WaterHeaterUpdated()); add(WaterHeaterUpdated());
@ -103,12 +109,21 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
} catch (_) {} } catch (_) {}
} }
_waterHeaterUpdated(WaterHeaterUpdated event, Emitter<WaterHeaterState> emit) async { @override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_waterHeaterUpdated(
WaterHeaterUpdated event, Emitter<WaterHeaterState> emit) async {
emit(WHLoadingState()); emit(WHLoadingState());
emit(UpdateState(whModel: deviceStatus)); emit(UpdateState(whModel: deviceStatus));
} }
void _changeFirstSwitch(WaterHeaterSwitch event, Emitter<WaterHeaterState> emit) async { void _changeFirstSwitch(
WaterHeaterSwitch event, Emitter<WaterHeaterState> emit) async {
emit(LoadingNewSate(whModel: deviceStatus)); emit(LoadingNewSate(whModel: deviceStatus));
try { try {
deviceStatus.firstSwitch = !event.whSwitch; deviceStatus.firstSwitch = !event.whSwitch;
@ -118,7 +133,10 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
} }
_timer = Timer(const Duration(milliseconds: 500), () async { _timer = Timer(const Duration(milliseconds: 500), () async {
final response = await DevicesAPI.controlDevice( final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: whId, code: 'switch_1', value: deviceStatus.firstSwitch), DeviceControlModel(
deviceId: whId,
code: 'switch_1',
value: deviceStatus.firstSwitch),
whId); whId);
if (!response['success']) { if (!response['success']) {
@ -132,13 +150,16 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
//=====================---------- timer ---------------------------------------- //=====================---------- timer ----------------------------------------
void _setCounterValue(SetCounterValue event, Emitter<WaterHeaterState> emit) async { void _setCounterValue(
SetCounterValue event, Emitter<WaterHeaterState> emit) async {
emit(LoadingNewSate(whModel: deviceStatus)); emit(LoadingNewSate(whModel: deviceStatus));
int seconds = 0; int seconds = 0;
try { try {
seconds = event.duration.inSeconds; seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice( final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: whId, code: event.deviceCode, value: seconds), whId); DeviceControlModel(
deviceId: whId, code: event.deviceCode, value: seconds),
whId);
if (response['success'] ?? false) { if (response['success'] ?? false) {
if (event.deviceCode == 'countdown_1') { if (event.deviceCode == 'countdown_1') {
@ -160,7 +181,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
} }
} }
void _getCounterValue(GetCounterEvent event, Emitter<WaterHeaterState> emit) async { void _getCounterValue(
GetCounterEvent event, Emitter<WaterHeaterState> emit) async {
emit(WHLoadingState()); emit(WHLoadingState());
try { try {
var response = await DevicesAPI.getDeviceStatus(whId); var response = await DevicesAPI.getDeviceStatus(whId);
@ -250,7 +272,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
deviceId: whId, deviceId: whId,
); );
List<dynamic> jsonData = response; List<dynamic> jsonData = response;
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList(); listSchedule =
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
emit(WHInitialState()); emit(WHInitialState());
} on DioException catch (e) { } on DioException catch (e) {
final errorData = e.response!.data; final errorData = e.response!.data;
@ -261,12 +284,13 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
int? getTimeStampWithoutSeconds(DateTime? dateTime) { int? getTimeStampWithoutSeconds(DateTime? dateTime) {
if (dateTime == null) return null; if (dateTime == null) return null;
DateTime dateTimeWithoutSeconds = DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute); dateTime.day, dateTime.hour, dateTime.minute);
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000; return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
} }
Future toggleChange(ToggleScheduleEvent event, Emitter<WaterHeaterState> emit) async { Future toggleChange(
ToggleScheduleEvent event, Emitter<WaterHeaterState> emit) async {
try { try {
emit(WHLoadingState()); emit(WHLoadingState());
final response = await DevicesAPI.changeSchedule( final response = await DevicesAPI.changeSchedule(
@ -284,7 +308,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
} }
} }
Future deleteSchedule(DeleteScheduleEvent event, Emitter<WaterHeaterState> emit) async { Future deleteSchedule(
DeleteScheduleEvent event, Emitter<WaterHeaterState> emit) async {
try { try {
emit(WHLoadingState()); emit(WHLoadingState());
final response = await DevicesAPI.deleteSchedule( final response = await DevicesAPI.deleteSchedule(
@ -303,7 +328,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
} }
} }
void _toggleCreateCirculate(ToggleCreateCirculate event, Emitter<WaterHeaterState> emit) { void _toggleCreateCirculate(
ToggleCreateCirculate event, Emitter<WaterHeaterState> emit) {
emit(WHLoadingState()); emit(WHLoadingState());
createCirculate = !createCirculate; createCirculate = !createCirculate;
selectedDays.clear(); selectedDays.clear();
@ -311,13 +337,15 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
emit(UpdateCreateScheduleState(createCirculate)); emit(UpdateCreateScheduleState(createCirculate));
} }
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<WaterHeaterState> emit) { void toggleSelectedIndex(
ToggleSelectedEvent event, Emitter<WaterHeaterState> emit) {
emit(WHLoadingState()); emit(WHLoadingState());
selectedTabIndex = event.index; selectedTabIndex = event.index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex)); emit(ChangeSlidingSegmentState(value: selectedTabIndex));
} }
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<WaterHeaterState> emit) { void toggleCreateSchedule(
ToggleCreateScheduleEvent event, Emitter<WaterHeaterState> emit) {
emit(WHLoadingState()); emit(WHLoadingState());
createSchedule = !createSchedule; createSchedule = !createSchedule;
selectedDays.clear(); selectedDays.clear();
@ -366,8 +394,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
List<GroupWHModel> groupWaterHeaterList = []; List<GroupWHModel> groupWaterHeaterList = [];
bool allSwitchesOn = true; bool allSwitchesOn = true;
void _changeFirstWizardSwitch( void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
ChangeFirstWizardSwitchStatusEvent event, Emitter<WaterHeaterState> emit) async { Emitter<WaterHeaterState> emit) async {
emit(LoadingNewSate(whModel: deviceStatus)); emit(LoadingNewSate(whModel: deviceStatus));
try { try {
bool allSwitchesValue = true; bool allSwitchesValue = true;
@ -379,7 +407,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
allSwitchesValue = false; allSwitchesValue = false;
} }
}); });
emit(UpdateGroupState(twoGangList: groupWaterHeaterList, allSwitches: allSwitchesValue)); emit(UpdateGroupState(
twoGangList: groupWaterHeaterList, allSwitches: allSwitchesValue));
final response = await DevicesAPI.deviceBatchController( final response = await DevicesAPI.deviceBatchController(
code: 'switch_1', code: 'switch_1',
@ -394,7 +423,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
} }
} }
void _fetchWHWizardStatus(InitialWizardEvent event, Emitter<WaterHeaterState> emit) async { void _fetchWHWizardStatus(
InitialWizardEvent event, Emitter<WaterHeaterState> emit) async {
emit(WHLoadingState()); emit(WHLoadingState());
try { try {
devicesList = []; devicesList = [];
@ -404,7 +434,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
HomeCubit.getInstance().selectedSpace?.id ?? '', 'WH'); HomeCubit.getInstance().selectedSpace?.id ?? '', 'WH');
for (int i = 0; i < devicesList.length; i++) { for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? ''); var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = []; List<StatusModel> statusModelList = [];
for (var status in response['status']) { for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status)); statusModelList.add(StatusModel.fromJson(status));
@ -426,23 +457,27 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
return true; return true;
}); });
} }
emit(UpdateGroupState(twoGangList: groupWaterHeaterList, allSwitches: allSwitchesOn)); emit(UpdateGroupState(
twoGangList: groupWaterHeaterList, allSwitches: allSwitchesOn));
} catch (e) { } catch (e) {
// emit(FailedState(error: e.toString())); // emit(FailedState(error: e.toString()));
return; return;
} }
} }
void _groupAllOn(GroupAllOnEvent event, Emitter<WaterHeaterState> emit) async { void _groupAllOn(
GroupAllOnEvent event, Emitter<WaterHeaterState> emit) async {
emit(LoadingNewSate(whModel: deviceStatus)); emit(LoadingNewSate(whModel: deviceStatus));
try { try {
for (int i = 0; i < groupWaterHeaterList.length; i++) { for (int i = 0; i < groupWaterHeaterList.length; i++) {
groupWaterHeaterList[i].firstSwitch = true; groupWaterHeaterList[i].firstSwitch = true;
} }
emit(UpdateGroupState(twoGangList: groupWaterHeaterList, allSwitches: true)); emit(UpdateGroupState(
twoGangList: groupWaterHeaterList, allSwitches: true));
List<String> allDeviceIds = groupWaterHeaterList.map((device) => device.deviceId).toList(); List<String> allDeviceIds =
groupWaterHeaterList.map((device) => device.deviceId).toList();
final response = await DevicesAPI.deviceBatchController( final response = await DevicesAPI.deviceBatchController(
code: 'switch_1', code: 'switch_1',
@ -460,15 +495,18 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
} }
} }
void _groupAllOff(GroupAllOffEvent event, Emitter<WaterHeaterState> emit) async { void _groupAllOff(
GroupAllOffEvent event, Emitter<WaterHeaterState> emit) async {
emit(LoadingNewSate(whModel: deviceStatus)); emit(LoadingNewSate(whModel: deviceStatus));
try { try {
for (int i = 0; i < groupWaterHeaterList.length; i++) { for (int i = 0; i < groupWaterHeaterList.length; i++) {
groupWaterHeaterList[i].firstSwitch = false; groupWaterHeaterList[i].firstSwitch = false;
} }
emit(UpdateGroupState(twoGangList: groupWaterHeaterList, allSwitches: false)); emit(UpdateGroupState(
twoGangList: groupWaterHeaterList, allSwitches: false));
List<String> allDeviceIds = groupWaterHeaterList.map((device) => device.deviceId).toList(); List<String> allDeviceIds =
groupWaterHeaterList.map((device) => device.deviceId).toList();
final response = await DevicesAPI.deviceBatchController( final response = await DevicesAPI.deviceBatchController(
code: 'switch_1', code: 'switch_1',

View File

@ -1,6 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
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/water_leak_bloc/water_leak_event.dart'; import 'package:syncrow_app/features/devices/bloc/water_leak_bloc/water_leak_event.dart';
import 'package:syncrow_app/features/devices/bloc/water_leak_bloc/water_leak_state.dart'; import 'package:syncrow_app/features/devices/bloc/water_leak_bloc/water_leak_state.dart';
@ -21,7 +20,6 @@ class WaterLeakBloc extends Bloc<WaterLeakEvent, WaterLeakState> {
on<ToggleClosingReminderEvent>(_toggleClosingReminder); on<ToggleClosingReminderEvent>(_toggleClosingReminder);
on<ToggleWaterLeakAlarmEvent>(_toggleWaterLeakAlarm); on<ToggleWaterLeakAlarmEvent>(_toggleWaterLeakAlarm);
} }
Timer? _timer;
bool lowBattery = false; bool lowBattery = false;
bool closingReminder = false; bool closingReminder = false;
bool waterAlarm = false; bool waterAlarm = false;
@ -134,32 +132,42 @@ class WaterLeakBloc extends Bloc<WaterLeakEvent, WaterLeakState> {
emit(WaterLeakFailedState(errorMessage: errorMessage)); emit(WaterLeakFailedState(errorMessage: errorMessage));
} }
} }
// Timer? _timer;
// StreamSubscription<DatabaseEvent>? _streamSubscription;
// void _listenToChanges() {
// try {
// _streamSubscription?.cancel();
// DatabaseReference ref =
// FirebaseDatabase.instance.ref('device-status/$WLId');
// Stream<DatabaseEvent> stream = ref.onValue;
_listenToChanges() { // _streamSubscription = stream.listen((DatabaseEvent event) async {
try { // if (_timer != null) {
DatabaseReference ref = // await Future.delayed(const Duration(seconds: 2));
FirebaseDatabase.instance.ref('device-status/$WLId'); // }
Stream<DatabaseEvent> stream = ref.onValue; // 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 = WaterLeakModel.fromJson(statusList);
// if (!isClosed) {
// add(
// WaterLeakSwitch(switchD: deviceStatus.waterContactState),
// );
// }
// });
// } catch (_) {}
// }
stream.listen((DatabaseEvent event) async { // @override
if (_timer != null) { // Future<void> close() async {
await Future.delayed(const Duration(seconds: 2)); // _streamSubscription?.cancel();
} // _streamSubscription = null;
Map<dynamic, dynamic> usersMap = // return super.close();
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 (_) {}
}
} }

View File

@ -23,6 +23,7 @@ class ACsView extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return BlocProvider(
create: (context) => ACsBloc(acId: deviceModel?.uuid ?? '') create: (context) => ACsBloc(acId: deviceModel?.uuid ?? '')
..add(AcsInitial(allAcs: deviceModel != null ? false : true)), ..add(AcsInitial(allAcs: deviceModel != null ? false : true)),
child: BlocBuilder<ACsBloc, AcsState>( child: BlocBuilder<ACsBloc, AcsState>(

View File

@ -332,7 +332,7 @@ class CeilingSensorInterface extends StatelessWidget {
title: title.toString(), title: title.toString(),
sensor: ceilingSensor, sensor: ceilingSensor,
value: model.sensitivity, value: model.sensitivity,
min: 0, min: 1,
max: 10, max: 10,
)); ));
if (result != null) { if (result != null) {

View File

@ -1,8 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:smooth_page_indicator/smooth_page_indicator.dart'; import 'package:smooth_page_indicator/smooth_page_indicator.dart';
import 'package:syncrow_app/features/devices/bloc/devices_cubit.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/devices_cubit.dart';
import 'package:syncrow_app/features/devices/view/widgets/all_devices.dart'; import 'package:syncrow_app/features/devices/view/widgets/all_devices.dart';
import 'package:syncrow_app/features/devices/view/widgets/room_page.dart'; import 'package:syncrow_app/features/devices/view/widgets/room_page.dart';
import 'package:syncrow_app/features/devices/view/widgets/rooms_slider.dart'; import 'package:syncrow_app/features/devices/view/widgets/rooms_slider.dart';
@ -15,7 +15,7 @@ import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart'; import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
class DevicesViewBody extends StatelessWidget { class DevicesViewBody extends StatelessWidget {
const DevicesViewBody({Key? key}) : super(key: key); const DevicesViewBody({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<HomeCubit, HomeState>( return BlocBuilder<HomeCubit, HomeState>(
@ -80,10 +80,7 @@ class DevicesViewBody extends StatelessWidget {
), ),
], ],
), ),
SizedBox( const SceneView(pageType: true),
height: MediaQuery.of(context).size.height * 0.1,
child: const SceneView(pageType: true),
),
const SizedBox(height: 20), const SizedBox(height: 20),
const RoomsSlider(), const RoomsSlider(),
const SizedBox(height: 10), const SizedBox(height: 10),

View File

@ -8,8 +8,7 @@ import 'package:syncrow_app/features/shared_widgets/devices_default_switch.dart'
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
class GarageList extends StatelessWidget { class GarageList extends StatelessWidget {
const GarageList( const GarageList({super.key, required this.garageList, required this.allSwitches});
{super.key, required this.garageList, required this.allSwitches});
final List<GroupGarageModel> garageList; final List<GroupGarageModel> garageList;
final bool allSwitches; final bool allSwitches;
@ -23,43 +22,42 @@ class GarageList extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
const SizedBox(height: 10), const SizedBox(height: 10),
const BodySmall(text: 'All Lights'), const BodySmall(text: 'All Garages'),
const SizedBox(height: 5), const SizedBox(height: 5),
DevicesDefaultSwitch( DevicesDefaultSwitch(
off: 'OFF', off: 'Close',
on: 'ON', on: 'Open',
switchValue: allSwitches, switchValue: allSwitches,
action: () { action: () => BlocProvider.of<GarageDoorBloc>(context).add(
BlocProvider.of<GarageDoorBloc>(context) GroupAllOnEvent(),
.add(GroupAllOnEvent()); ),
}, secondAction: () => BlocProvider.of<GarageDoorBloc>(context).add(
secondAction: () { GroupAllOffEvent(),
BlocProvider.of<GarageDoorBloc>(context) ),
.add(GroupAllOffEvent());
},
), ),
ListView.builder( ListView.builder(
shrinkWrap: true, shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.all(0), padding: EdgeInsetsDirectional.zero,
itemCount: garageList.length, itemCount: garageList.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final garageDoor = garageList[index];
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const SizedBox(height: 10), const SizedBox(height: 10),
BodySmall(text: garageList[index].deviceName), BodySmall(text: garageDoor.deviceName),
const SizedBox(height: 5), const SizedBox(height: 5),
DevicesDefaultSwitch( DevicesDefaultSwitch(
off: 'OFF', off: 'Close',
on: 'ON', on: 'Open',
switchValue: garageList[index].firstSwitch, switchValue: garageDoor.firstSwitch,
action: () { action: () => BlocProvider.of<GarageDoorBloc>(context).add(
BlocProvider.of<GarageDoorBloc>(context).add( ChangeFirstWizardSwitchStatusEvent(
ChangeFirstWizardSwitchStatusEvent( value: garageDoor.firstSwitch,
value: garageList[index].firstSwitch, deviceId: garageDoor.deviceId,
deviceId: garageList[index].deviceId)); ),
}, ),
), ),
], ],
); );

View File

@ -20,8 +20,9 @@ class OneGangScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return BlocProvider(
create: (context) => OneGangBloc(switchCode: 'switch_1', oneGangId: device?.uuid ?? '') create: (context) =>
..add(const InitialEvent(groupScreen: false)), OneGangBloc(switchCode: 'switch_1', oneGangId: device?.uuid ?? '')
..add(const InitialEvent(groupScreen: false)),
child: BlocBuilder<OneGangBloc, OneGangState>( child: BlocBuilder<OneGangBloc, OneGangState>(
builder: (context, state) { builder: (context, state) {
OneGangModel oneGangModel = OneGangModel( OneGangModel oneGangModel = OneGangModel(
@ -36,13 +37,15 @@ class OneGangScreen extends StatelessWidget {
} }
return state is LoadingInitialState return state is LoadingInitialState
? const Center( ? const Center(
child: child: DefaultContainer(
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()), width: 50,
height: 50,
child: CircularProgressIndicator()),
) )
: RefreshIndicator( : RefreshIndicator(
onRefresh: () async { onRefresh: () async {
BlocProvider.of<OneGangBloc>(context) BlocProvider.of<OneGangBloc>(context).add(InitialEvent(
.add(InitialEvent(groupScreen: device != null ? false : true)); groupScreen: device != null ? false : true));
}, },
child: ListView( child: ListView(
children: [ children: [
@ -55,7 +58,8 @@ class OneGangScreen extends StatelessWidget {
const Expanded(child: SizedBox.shrink()), const Expanded(child: SizedBox.shrink()),
Expanded( Expanded(
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisAlignment:
MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Column( Column(
@ -64,9 +68,10 @@ class OneGangScreen extends StatelessWidget {
threeGangSwitch: device!, threeGangSwitch: device!,
value: oneGangModel.firstSwitch, value: oneGangModel.firstSwitch,
action: () { action: () {
BlocProvider.of<OneGangBloc>(context).add( BlocProvider.of<OneGangBloc>(context)
ChangeFirstSwitchStatusEvent( .add(ChangeFirstSwitchStatusEvent(
value: oneGangModel.firstSwitch)); value: oneGangModel
.firstSwitch));
}, },
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
@ -74,7 +79,8 @@ class OneGangScreen extends StatelessWidget {
width: 70, width: 70,
child: BodySmall( child: BodySmall(
text: " Entrance Light", text: " Entrance Light",
fontColor: ColorsManager.textPrimaryColor, fontColor:
ColorsManager.textPrimaryColor,
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
), ),
@ -94,20 +100,24 @@ class OneGangScreen extends StatelessWidget {
Card( Card(
elevation: 3, elevation: 3,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100), borderRadius:
BorderRadius.circular(100),
), ),
child: GestureDetector( child: GestureDetector(
onTap: () { onTap: () {
Navigator.push( Navigator.push(
context, context,
PageRouteBuilder( PageRouteBuilder(
pageBuilder: pageBuilder: (context,
(context, animation1, animation2) => animation1,
TimerScheduleScreen( animation2) =>
switchCode: 'switch_1', TimerScheduleScreen(
device: device!, switchCode:
deviceCode: 'countdown_1', 'switch_1',
))); device: device!,
deviceCode:
'countdown_1',
)));
}, },
child: Stack( child: Stack(
alignment: Alignment.center, alignment: Alignment.center,
@ -117,7 +127,9 @@ class OneGangScreen extends StatelessWidget {
height: 60, height: 60,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey[300], color: Colors.grey[300],
borderRadius: BorderRadius.circular(100), borderRadius:
BorderRadius.circular(
100),
), ),
), ),
Container( Container(
@ -125,12 +137,15 @@ class OneGangScreen extends StatelessWidget {
height: 40, height: 40,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(100), borderRadius:
BorderRadius.circular(
100),
), ),
child: Center( child: Center(
child: Icon( child: Icon(
Icons.access_time, Icons.access_time,
color: ColorsManager.primaryColorWithOpacity, color: ColorsManager
.primaryColorWithOpacity,
size: 25, size: 25,
), ),
), ),

View File

@ -119,6 +119,8 @@ Future<void> showDeviceInterface(
required BuildContext context, required BuildContext context,
required isAllDevices, required isAllDevices,
List<DeviceModel>? allDevices}) async { List<DeviceModel>? allDevices}) async {
print('object-----${device.uuid} ${device.name}');
final devicesCubit = context.read<DevicesCubit>(); final devicesCubit = context.read<DevicesCubit>();
switch (device.productType) { switch (device.productType) {

View File

@ -8,7 +8,11 @@ import 'package:syncrow_app/features/shared_widgets/devices_default_switch.dart'
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
class WHList extends StatelessWidget { class WHList extends StatelessWidget {
const WHList({super.key, required this.whList, required this.allSwitches}); const WHList({
required this.whList,
required this.allSwitches,
super.key,
});
final List<GroupWHModel> whList; final List<GroupWHModel> whList;
final bool allSwitches; final bool allSwitches;
@ -22,43 +26,42 @@ class WHList extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
const SizedBox(height: 10), const SizedBox(height: 10),
const BodySmall(text: 'All Lights'), const BodySmall(text: 'All Water Heaters'),
const SizedBox(height: 5), const SizedBox(height: 5),
DevicesDefaultSwitch( DevicesDefaultSwitch(
off: 'OFF', off: 'OFF',
on: 'ON', on: 'ON',
switchValue: allSwitches, switchValue: allSwitches,
action: () { action: () => context.read<WaterHeaterBloc>().add(
BlocProvider.of<WaterHeaterBloc>(context) GroupAllOnEvent(),
.add(GroupAllOnEvent()); ),
}, secondAction: () => context.read<WaterHeaterBloc>().add(
secondAction: () { GroupAllOffEvent(),
BlocProvider.of<WaterHeaterBloc>(context) ),
.add(GroupAllOffEvent());
},
), ),
ListView.builder( ListView.builder(
shrinkWrap: true, shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.all(0), padding: EdgeInsetsDirectional.zero,
itemCount: whList.length, itemCount: whList.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final waterHeater = whList[index];
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const SizedBox(height: 10), const SizedBox(height: 10),
BodySmall(text: whList[index].deviceName), BodySmall(text: waterHeater.deviceName),
const SizedBox(height: 5), const SizedBox(height: 5),
DevicesDefaultSwitch( DevicesDefaultSwitch(
off: 'OFF', off: 'OFF',
on: 'ON', on: 'ON',
switchValue: whList[index].firstSwitch, switchValue: waterHeater.firstSwitch,
action: () { action: () => context.read<WaterHeaterBloc>().add(
BlocProvider.of<WaterHeaterBloc>(context).add(
ChangeFirstWizardSwitchStatusEvent( ChangeFirstWizardSwitchStatusEvent(
value: whList[index].firstSwitch, value: waterHeater.firstSwitch,
deviceId: whList[index].deviceId)); deviceId: waterHeater.deviceId,
}, ),
),
), ),
], ],
); );

View File

@ -51,7 +51,8 @@ class ManageUnitBloc extends Bloc<ManageUnitEvent, ManageUnitState> {
spaceUuid: event.unit.id, spaceUuid: event.unit.id,
roomId: event.roomId, roomId: event.roomId,
projectId: project?.uuid ?? TempConst.projectIdDev); projectId: project?.uuid ?? TempConst.projectIdDev);
allDevices = await HomeManagementAPI.fetchDevicesByUserId(); allDevices = await HomeManagementAPI.fetchDevices(
project?.uuid ?? TempConst.projectIdDev);
List<String> allDevicesIds = []; List<String> allDevicesIds = [];

View File

@ -28,8 +28,7 @@ class AssignDeviceView extends StatelessWidget {
listener: (context, state) { listener: (context, state) {
if (state is FetchDeviceByRoomIdState) { if (state is FetchDeviceByRoomIdState) {
if (state.allDevices.isEmpty) { if (state.allDevices.isEmpty) {
CustomSnackBar.displaySnackBar( CustomSnackBar.displaySnackBar('You do not have the devices');
'You do not have the permission to assign devices');
Navigator.of(context).pop(); Navigator.of(context).pop();
} }
} }

View File

@ -16,85 +16,74 @@ class ManageHomeView extends StatelessWidget {
var spaces = HomeCubit.getInstance().spaces; var spaces = HomeCubit.getInstance().spaces;
return DefaultScaffold( return DefaultScaffold(
title: 'Manage Your Home', title: 'Manage Your Home',
child: spaces == null height: MediaQuery.sizeOf(context).height,
child: spaces.isEmpty
? const Center( ? const Center(
child: BodyMedium(text: 'No spaces found'), child: BodyMedium(text: 'No spaces found'),
) )
: Column( : DefaultContainer(
children: [ padding: EdgeInsets.symmetric(horizontal: 20, vertical: 25),
DefaultContainer( child: ListView.builder(
padding: const EdgeInsets.symmetric( itemCount: spaces.length,
horizontal: 25, itemBuilder: (context, index) {
vertical: 20, if (index == spaces.length - 1) {
), return InkWell(
child: Column( onTap: () {
mainAxisSize: MainAxisSize.min, Navigator.of(context).push(CustomPageRoute(
mainAxisAlignment: MainAxisAlignment.start, builder: (context) => HomeSettingsView(
children: List.generate( space: spaces[index],
spaces.length, )));
(index) { },
if (index == spaces.length - 1) { child: Row(
return InkWell( mainAxisAlignment: MainAxisAlignment.spaceBetween,
onTap: () { children: [
Navigator.of(context).push(CustomPageRoute( BodyMedium(text: StringHelpers.toTitleCase(spaces[index].name)),
builder: (context) => HomeSettingsView( const Icon(
space: spaces[index], Icons.arrow_forward_ios,
))); color: ColorsManager.greyColor,
}, size: 15,
child: Row( )
mainAxisAlignment: MainAxisAlignment.spaceBetween, ],
children: [ ),
BodyMedium(text: StringHelpers.toTitleCase(spaces[index].name)), );
const Icon( }
Icons.arrow_forward_ios, return InkWell(
color: ColorsManager.greyColor, onTap: () {
size: 15, //TODO refactor the routing to use named routes
) // Navigator.of(context).pushNamed(
], // '/home_settings',
), // arguments: spaces[index],
); // );
}
return InkWell(
onTap: () {
//TODO refactor the routing to use named routes
// Navigator.of(context).pushNamed(
// '/home_settings',
// arguments: spaces[index],
// );
Navigator.of(context).push(CustomPageRoute( Navigator.of(context).push(CustomPageRoute(
builder: (context) => HomeSettingsView( builder: (context) => HomeSettingsView(
space: spaces[index], space: spaces[index],
))); )));
}, },
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Row( BodyMedium(text: HomeCubit.getInstance().spaces[index].name),
mainAxisAlignment: MainAxisAlignment.spaceBetween, const Icon(
children: [ Icons.arrow_forward_ios,
BodyMedium(text: HomeCubit.getInstance().spaces![index].name),
const Icon(
Icons.arrow_forward_ios,
color: ColorsManager.greyColor,
size: 15,
)
],
),
Container(
margin: const EdgeInsets.symmetric(vertical: 15),
height: 1,
color: ColorsManager.greyColor, color: ColorsManager.greyColor,
), size: 15,
)
], ],
), ),
); Container(
}, margin: const EdgeInsets.symmetric(vertical: 15),
), height: 1,
), color: ColorsManager.greyColor,
), ),
], ],
),
);
}),
)); ));
} }
} }

View File

@ -1,6 +1,8 @@
import 'dart:async'; import 'dart:async';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.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/auth/model/project_model.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart'; import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart';
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart'; import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart';
@ -348,15 +350,18 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
emit(CreateSceneLoading()); emit(CreateSceneLoading());
try { try {
dynamic response; dynamic response;
Project? project = HomeCubit.getInstance().project;
if (event.createSceneModel != null) { if (event.createSceneModel != null) {
response = event.updateScene response = event.updateScene
? await SceneApi.updateScene(event.createSceneModel!, event.sceneId) ? await SceneApi.updateScene(event.createSceneModel!, event.sceneId)
: await SceneApi.createScene(event.createSceneModel!); : await SceneApi.createScene(event.createSceneModel!);
} else if (event.createAutomationModel != null) { } else if (event.createAutomationModel != null) {
response = event.updateScene response = event.updateScene
? await SceneApi.updateAutomation( ? await SceneApi.updateAutomation(event.createAutomationModel!,
event.createAutomationModel!, event.sceneId) event.sceneId, project?.uuid ?? '')
: await SceneApi.createAutomation(event.createAutomationModel!); : await SceneApi.createAutomation(
event.createAutomationModel!, project?.uuid ?? '');
} }
if (response['success'] == true) { if (response['success'] == true) {
@ -421,6 +426,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
emit(CreateSceneLoading()); emit(CreateSceneLoading());
try { try {
Project? project = HomeCubit.getInstance().project;
tasksList.clear(); tasksList.clear();
tempTasksList.clear(); tempTasksList.clear();
selectedValues.clear(); selectedValues.clear();
@ -436,7 +443,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
conditionRule = 'or'; conditionRule = 'or';
final response = event.isAutomation final response = event.isAutomation
? await SceneApi.getAutomationDetails(event.sceneId) ? await SceneApi.getAutomationDetails(
event.sceneId, project?.uuid ?? '')
: await SceneApi.getSceneDetails(event.sceneId); : await SceneApi.getSceneDetails(event.sceneId);
if (response.id.isNotEmpty) { if (response.id.isNotEmpty) {
if (event.isAutomation) { if (event.isAutomation) {
@ -605,10 +613,14 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
emit(DeleteSceneLoading()); emit(DeleteSceneLoading());
try { try {
Project? project = HomeCubit.getInstance().project;
final response = final response =
sceneType.name == CreateSceneEnum.deviceStatusChanges.name sceneType.name == CreateSceneEnum.deviceStatusChanges.name
? await SceneApi.deleteAutomation( ? await SceneApi.deleteAutomation(
automationId: event.sceneId, unitUuid: event.unitUuid) automationId: event.sceneId,
unitUuid: event.unitUuid,
projectId: project?.uuid ?? '')
: await SceneApi.deleteScene( : await SceneApi.deleteScene(
sceneId: event.sceneId, sceneId: event.sceneId,
); );

View File

@ -46,8 +46,11 @@ class SceneBloc extends Bloc<SceneEvent, SceneState> {
emit(SceneLoading()); emit(SceneLoading());
try { try {
Project? project = HomeCubit.getInstance().project;
if (event.unitId.isNotEmpty) { if (event.unitId.isNotEmpty) {
automationList = await SceneApi.getAutomationByUnitId(event.unitId); automationList = await SceneApi.getAutomationByUnitId(
event.unitId, event.communityId, project?.uuid ?? '');
emit(SceneLoaded(scenes, automationList)); emit(SceneLoaded(scenes, automationList));
} else { } else {
emit(const SceneError(message: 'Unit ID is empty')); emit(const SceneError(message: 'Unit ID is empty'));
@ -96,11 +99,17 @@ class SceneBloc extends Bloc<SceneEvent, SceneState> {
)); ));
try { try {
Project? project = HomeCubit.getInstance().project;
final success = await SceneApi.updateAutomationStatus( final success = await SceneApi.updateAutomationStatus(
event.automationId, event.automationStatusUpdate); event.automationId,
event.automationStatusUpdate,
project?.uuid ?? '');
if (success) { if (success) {
automationList = await SceneApi.getAutomationByUnitId( automationList = await SceneApi.getAutomationByUnitId(
event.automationStatusUpdate.spaceUuid); event.automationStatusUpdate.spaceUuid,
event.communityId,
project?.uuid ?? '');
newLoadingStates[event.automationId] = false; newLoadingStates[event.automationId] = false;
emit(SceneLoaded( emit(SceneLoaded(
currentState.scenes, currentState.scenes,

View File

@ -22,11 +22,13 @@ class LoadScenes extends SceneEvent {
class LoadAutomation extends SceneEvent { class LoadAutomation extends SceneEvent {
final String unitId; final String unitId;
final String communityId;
const LoadAutomation(this.unitId);
const LoadAutomation(this.unitId, this.communityId);
@override @override
List<Object> get props => [unitId]; List<Object> get props => [unitId, communityId];
} }
class SceneTrigger extends SceneEvent { class SceneTrigger extends SceneEvent {
@ -43,8 +45,9 @@ class SceneTrigger extends SceneEvent {
class UpdateAutomationStatus extends SceneEvent { class UpdateAutomationStatus extends SceneEvent {
final String automationId; final String automationId;
final AutomationStatusUpdate automationStatusUpdate; final AutomationStatusUpdate automationStatusUpdate;
final String communityId;
const UpdateAutomationStatus({required this.automationStatusUpdate, required this.automationId}); const UpdateAutomationStatus({required this.automationStatusUpdate, required this.automationId, required this.communityId});
@override @override
List<Object> get props => [automationStatusUpdate]; List<Object> get props => [automationStatusUpdate];

View File

@ -1,5 +1,3 @@
import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_bloc.dart'; import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_event.dart'; import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_event.dart';
@ -7,19 +5,31 @@ import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_event.dart
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_state.dart'; import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_state.dart';
class TabBarBloc extends Bloc<TabBarEvent, TabBarState> { class TabBarBloc extends Bloc<TabBarEvent, TabBarState> {
final DeviceManagerBloc deviceManagerBloc; TabBarBloc(this.deviceManagerBloc) : super(const TabBarInitialState()) {
TabBarBloc(this.deviceManagerBloc) : super(const Initial()) { on<TabBarTabChangedEvent>(_onTabBarTabChangedEvent);
on<TabChanged>(_handleTabChanged);
} }
FutureOr<void> _handleTabChanged( final DeviceManagerBloc deviceManagerBloc;
TabChanged event, Emitter<TabBarState> emit) {
void _onTabBarTabChangedEvent(
TabBarTabChangedEvent event,
Emitter<TabBarState> emit,
) {
_getDevices(event);
emit(
TabBarTabSelectedState(
roomId: event.roomId,
selectedTabIndex: event.selectedIndex,
),
);
}
void _getDevices(TabBarTabChangedEvent event) {
if (event.roomId == "-1") { if (event.roomId == "-1") {
deviceManagerBloc.add(FetchAllDevices()); deviceManagerBloc.add(FetchAllDevices());
} else { } else {
deviceManagerBloc.add(FetchDevicesByRoomId(event.roomId,event.unit)); deviceManagerBloc.add(FetchDevicesByRoomId(event.roomId, event.unit));
} }
emit(TabSelected(
roomId: event.roomId, selectedTabIndex: event.selectedIndex));
} }
} }

View File

@ -4,10 +4,14 @@ abstract class TabBarEvent {
const TabBarEvent(); const TabBarEvent();
} }
class TabChanged extends TabBarEvent { class TabBarTabChangedEvent extends TabBarEvent {
const TabBarTabChangedEvent({
required this.selectedIndex,
required this.roomId,
required this.unit,
});
final int selectedIndex; final int selectedIndex;
final String roomId; final String roomId;
final SpaceModel unit; final SpaceModel unit;
const TabChanged(
{required this.selectedIndex, required this.roomId, required this.unit});
} }

View File

@ -2,12 +2,16 @@ abstract class TabBarState {
const TabBarState(); const TabBarState();
} }
class Initial extends TabBarState { class TabBarInitialState extends TabBarState {
const Initial(); const TabBarInitialState();
} }
class TabSelected extends TabBarState { class TabBarTabSelectedState extends TabBarState {
const TabBarTabSelectedState({
required this.roomId,
required this.selectedTabIndex,
});
final int selectedTabIndex; final int selectedTabIndex;
final String roomId; final String roomId;
const TabSelected({required this.roomId, required this.selectedTabIndex});
} }

View File

@ -0,0 +1,48 @@
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/app_layout/model/community_model.dart';
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_bloc.dart';
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_event.dart';
abstract final class SceneBlocFactory {
static SceneBloc create({
required bool pageType,
required HomeCubit homeCubit,
}) {
final selectedSpace = homeCubit.selectedSpace;
final defaultSpace = SpaceModel(
id: '-1',
name: '',
community: Community(
uuid: '-1',
name: '',
),
);
final spaceId = selectedSpace?.id ?? defaultSpace.id;
final space = selectedSpace ?? defaultSpace;
final communityUuid =
selectedSpace?.community.uuid ?? defaultSpace.community.uuid;
final sceneBloc = SceneBloc();
sceneBloc.add(
LoadScenes(
spaceId,
space,
showInDevice: pageType,
),
);
if (!pageType) {
sceneBloc.add(
LoadAutomation(
spaceId,
communityUuid,
),
);
}
return sceneBloc;
}
}

View File

@ -20,69 +20,69 @@ class SceneRoomsTabBarDevicesView extends StatefulWidget {
_SceneRoomsTabBarDevicesViewState(); _SceneRoomsTabBarDevicesViewState();
} }
class _SceneRoomsTabBarDevicesViewState class _SceneRoomsTabBarDevicesViewState extends State<SceneRoomsTabBarDevicesView>
extends State<SceneRoomsTabBarDevicesView>
with SingleTickerProviderStateMixin { with SingleTickerProviderStateMixin {
late final TabController _tabController; late final TabController _tabController;
List<SubSpaceModel>? rooms = [];
late final SpaceModel selectedSpace; late final SpaceModel selectedSpace;
var rooms = <SubSpaceModel>[];
@override @override
void initState() { void initState() {
selectedSpace = HomeCubit.getInstance().selectedSpace!;
rooms = List.from(HomeCubit.getInstance().selectedSpace?.subspaces ?? []);
if (rooms != null) {
if (rooms![0].id != '-1') {
rooms?.insert(
0,
SubSpaceModel(
name: 'All Devices',
devices: context.read<DevicesCubit>().allDevices,
id: '-1',
),
);
}
}
_tabController =
TabController(length: rooms!.length, vsync: this, initialIndex: 0);
_tabController.addListener(_handleTabSwitched);
super.initState(); super.initState();
}
void _handleTabSwitched() { selectedSpace = HomeCubit.getInstance().selectedSpace!;
if (_tabController.indexIsChanging) {
final value = _tabController.index;
/// select tab rooms = List.from(selectedSpace.subspaces);
context.read<TabBarBloc>().add(TabChanged( final defaultSubSpaceModel = SubSpaceModel(
selectedIndex: value, name: 'All Devices',
roomId: rooms?[value].id ?? '', devices: context.read<DevicesCubit>().allDevices,
unit: selectedSpace)); id: '-1',
return; );
if (rooms.isNotEmpty) {
final isFirstRoomIdValid = rooms[0].id != '-1';
if (isFirstRoomIdValid) {
rooms.insert(0, defaultSubSpaceModel);
}
} else {
rooms = [defaultSubSpaceModel];
} }
_tabController = TabController(length: rooms.length, vsync: this);
_tabController.addListener(_handleTabSwitched);
} }
@override @override
void dispose() { void dispose() {
super.dispose(); super.dispose();
_tabController.dispose();
_tabController.removeListener(() {}); _tabController.removeListener(() {});
_tabController.dispose();
}
void _handleTabSwitched() {
if (_tabController.indexIsChanging) {
final index = _tabController.index;
context.read<TabBarBloc>().add(
TabBarTabChangedEvent(
selectedIndex: index,
roomId: rooms[index].id ?? '',
unit: selectedSpace,
),
);
return;
}
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return DefaultScaffold( return DefaultScaffold(
title: StringsManager.createScene, padding: EdgeInsetsDirectional.zero,
padding: EdgeInsets.zero,
leading: IconButton( leading: IconButton(
onPressed: () { onPressed: () => navigateToRoute(context, Routes.sceneTasksRoute),
navigateToRoute(context, Routes.sceneTasksRoute); icon: const Icon(Icons.arrow_back_ios),
},
icon: const Icon(
Icons.arrow_back_ios,
),
), ),
title: StringsManager.createScene,
child: SceneDevicesBody(tabController: _tabController, rooms: rooms), child: SceneDevicesBody(tabController: _tabController, rooms: rooms),
); );
} }

View File

@ -1,75 +1,45 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.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/app_layout/model/community_model.dart';
import 'package:syncrow_app/features/app_layout/model/space_model.dart'; import 'package:syncrow_app/features/app_layout/model/space_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/scene_listview.dart'; import 'package:syncrow_app/features/devices/view/widgets/scene_listview.dart';
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_bloc.dart';
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_event.dart'; import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_event.dart';
import 'package:syncrow_app/features/scene/bloc/smart_scene/smart_scene_select_dart_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/smart_scene/smart_scene_select_dart_bloc.dart';
import 'package:syncrow_app/features/scene/helper/scene_bloc_factory.dart';
import 'package:syncrow_app/features/scene/widgets/empty_devices_widget.dart';
import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_grid_view.dart'; import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_grid_view.dart';
import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_header.dart'; import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_header.dart';
import 'package:syncrow_app/features/shared_widgets/create_unit.dart'; import 'package:syncrow_app/features/shared_widgets/app_loading_indicator.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/utils/context_extension.dart'; import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class SceneView extends StatelessWidget { class SceneView extends StatelessWidget {
const SceneView({
this.pageType = false,
super.key,
});
final bool pageType; final bool pageType;
const SceneView({super.key, this.pageType = false});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return BlocProvider(
create: (BuildContext context) { create: (context) => SceneBlocFactory.create(
if (pageType) { pageType: pageType,
return SceneBloc() homeCubit: HomeCubit.getInstance(),
..add(LoadScenes( ),
HomeCubit.getInstance().selectedSpace?.id ?? '',
HomeCubit.getInstance().selectedSpace ??
SpaceModel(
id: '-1',
name: '',
community: Community(
uuid: '-1',
name: '',
)),
showInDevice: pageType));
} else {
return SceneBloc()
..add(LoadScenes(
HomeCubit.getInstance().selectedSpace?.id ?? '',
HomeCubit.getInstance().selectedSpace ??
SpaceModel(
id: '-1',
name: '',
community: Community(
uuid: '-1',
name: '',
)),
showInDevice: pageType))
..add(LoadAutomation(HomeCubit.getInstance().selectedSpace?.id ?? ''));
}
},
child: BlocBuilder<CreateSceneBloc, CreateSceneState>( child: BlocBuilder<CreateSceneBloc, CreateSceneState>(
builder: (context, state) { builder: (context, state) {
final selectedSpace = HomeCubit.getInstance().selectedSpace;
if (state is DeleteSceneSuccess) { if (state is DeleteSceneSuccess) {
if (state.success) { if (state.success) _loadScenesAndAutomations(context, selectedSpace);
BlocProvider.of<SceneBloc>(context).add(LoadScenes(
HomeCubit.getInstance().selectedSpace!.id, HomeCubit.getInstance().selectedSpace!,
showInDevice: pageType));
BlocProvider.of<SceneBloc>(context)
.add(LoadAutomation(HomeCubit.getInstance().selectedSpace!.id));
}
} }
if (state is CreateSceneWithTasks) { if (state is CreateSceneWithTasks) {
if (state.success == true) { if (state.success) {
BlocProvider.of<SceneBloc>(context).add(LoadScenes( _loadScenesAndAutomations(context, selectedSpace);
HomeCubit.getInstance().selectedSpace!.id, HomeCubit.getInstance().selectedSpace!,
showInDevice: pageType));
BlocProvider.of<SceneBloc>(context)
.add(LoadAutomation(HomeCubit.getInstance().selectedSpace!.id));
context.read<SmartSceneSelectBloc>().add(const SmartSceneClearEvent()); context.read<SmartSceneSelectBloc>().add(const SmartSceneClearEvent());
} }
} }
@ -77,23 +47,24 @@ class SceneView extends StatelessWidget {
listener: (context, state) { listener: (context, state) {
if (state is SceneTriggerSuccess) { if (state is SceneTriggerSuccess) {
context.showCustomSnackbar( context.showCustomSnackbar(
message: 'Scene ${state.sceneName} triggered successfully!'); message: 'Scene ${state.sceneName} triggered successfully!',
);
} }
}, },
child: HomeCubit.getInstance().spaces?.isEmpty ?? true child: HomeCubit.getInstance().spaces.isEmpty
? const CreateUnitWidget() ? const EmptyDevicesWidget()
: Column( : Column(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
if (pageType == false) const SceneHeader(), if (!pageType) ...[
if (pageType == false) const SizedBox(height: 8), const SceneHeader(),
const SizedBox(height: 8),
],
BlocBuilder<SceneBloc, SceneState>( BlocBuilder<SceneBloc, SceneState>(
builder: (context, state) { builder: (context, state) {
if (state is SceneLoading) { if (state is SceneLoading) {
return const Center( return const AppLoadingIndicator();
child: CircularProgressIndicator(),
);
} }
if (state is SceneError) { if (state is SceneError) {
return Center( return Center(
@ -103,80 +74,83 @@ class SceneView extends StatelessWidget {
if (state is SceneLoaded) { if (state is SceneLoaded) {
final scenes = state.scenes; final scenes = state.scenes;
final automationList = state.automationList; final automationList = state.automationList;
if (scenes.isEmpty) return const EmptyDevicesWidget();
return pageType if (pageType) {
? Expanded( return SizedBox(
child: SceneListview( height: context.height * 0.1,
scenes: scenes, child: SceneListview(
loadingSceneId: state.loadingSceneId, scenes: scenes,
)) loadingSceneId: state.loadingSceneId,
: Expanded( ),
child: ListView( );
}
return Theme(
data: Theme.of(context).copyWith(
dividerColor: Colors.transparent,
),
child: Expanded(
child: ListView(
children: [
ExpansionTile(
tilePadding: const EdgeInsets.symmetric(
horizontal: 6,
),
initiallyExpanded: true,
iconColor: ColorsManager.grayColor,
title: const BodyMedium(
text: 'Tap to run routines',
),
children: [ children: [
Theme( if (scenes.isNotEmpty)
data: ThemeData() SceneGrid(
.copyWith(dividerColor: Colors.transparent), scenes: scenes,
child: ExpansionTile( loadingSceneId: state.loadingSceneId,
tilePadding: const EdgeInsets.symmetric(horizontal: 6), disablePlayButton: false,
initiallyExpanded: true, loadingStates: state.loadingStates,
iconColor: ColorsManager.grayColor, )
title: const BodyMedium(text: 'Tap to run routines'), else
children: [ const Center(
scenes.isNotEmpty child: BodyMedium(
? SceneGrid( text: 'No scenes have been added yet',
scenes: scenes, ),
loadingSceneId: state.loadingSceneId,
disablePlayButton: false,
loadingStates:
state.loadingStates, // Add this line
)
: const Center(
child: BodyMedium(
text: 'No scenes have been added yet',
),
),
const SizedBox(
height: 10,
),
],
), ),
), const SizedBox(height: 10),
Theme(
data: ThemeData()
.copyWith(dividerColor: Colors.transparent),
child: ExpansionTile(
initiallyExpanded: true,
iconColor: ColorsManager.grayColor,
tilePadding: const EdgeInsets.symmetric(horizontal: 6),
title: const BodyMedium(text: 'Automation'),
children: [
automationList.isNotEmpty
? SceneGrid(
scenes: automationList,
loadingSceneId: state.loadingSceneId,
disablePlayButton: true,
loadingStates:
state.loadingStates, // Add this line
)
: const Center(
child: BodyMedium(
text: 'No automations have been added yet',
),
),
const SizedBox(
height: 10,
),
],
),
),
const SizedBox(
height: 15,
),
], ],
), ),
); ExpansionTile(
initiallyExpanded: true,
iconColor: ColorsManager.grayColor,
tilePadding: const EdgeInsets.symmetric(
horizontal: 6,
),
title: const BodyMedium(text: 'Automation'),
children: [
if (automationList.isNotEmpty)
SceneGrid(
scenes: automationList,
loadingSceneId: state.loadingSceneId,
disablePlayButton: true,
loadingStates: state.loadingStates,
)
else
const Center(
child: BodyMedium(
text:
'No automations have been added yet',
),
),
const SizedBox(height: 10),
],
),
const SizedBox(height: 15),
],
),
),
);
} }
return const SizedBox(); return const SizedBox.shrink();
}, },
), ),
], ],
@ -186,4 +160,21 @@ class SceneView extends StatelessWidget {
), ),
); );
} }
void _loadScenesAndAutomations(BuildContext context, SpaceModel? selectedSpace) {
BlocProvider.of<SceneBloc>(context)
..add(
LoadScenes(
selectedSpace!.id,
selectedSpace,
showInDevice: pageType,
),
)
..add(
LoadAutomation(
selectedSpace.id,
selectedSpace.community.uuid,
),
);
}
} }

View File

@ -25,7 +25,7 @@ class DeleteRoutineButton extends StatelessWidget {
BlocProvider.of<SceneBloc>(context).add(LoadScenes( BlocProvider.of<SceneBloc>(context).add(LoadScenes(
HomeCubit.getInstance().selectedSpace!.id, HomeCubit.getInstance().selectedSpace!)); HomeCubit.getInstance().selectedSpace!.id, HomeCubit.getInstance().selectedSpace!));
BlocProvider.of<SceneBloc>(context) BlocProvider.of<SceneBloc>(context)
.add(LoadAutomation(HomeCubit.getInstance().selectedSpace!.id)); .add(LoadAutomation(HomeCubit.getInstance().selectedSpace!.id,HomeCubit.getInstance().selectedSpace!.community.uuid));
} }
} }
}, },

View File

@ -0,0 +1,22 @@
import 'package:flutter/material.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class EmptyDevicesWidget extends StatelessWidget {
const EmptyDevicesWidget({super.key});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 48),
child: Text(
"No routines.\nEnable 'Show on Home Screen' to add routines",
textAlign: TextAlign.center,
style: TextStyle(
color: ColorsManager.grayColor,
fontWeight: FontWeight.w400,
fontSize: 12,
),
),
);
}
}

View File

@ -1,6 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_bloc.dart'; import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_state.dart'; import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_state.dart';
import 'package:syncrow_app/features/devices/model/subspace_model.dart'; import 'package:syncrow_app/features/devices/model/subspace_model.dart';
@ -8,60 +7,44 @@ import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_bloc.dart'
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_state.dart'; import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_state.dart';
import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart'; import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart';
import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart'; import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart';
import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; import 'package:syncrow_app/features/scene/widgets/scene_devices/scene_devices_body_tab_bar.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/scene/widgets/scene_devices/scene_devices_list.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; import 'package:syncrow_app/features/shared_widgets/app_loading_indicator.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/navigation/routing_constants.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class SceneDevicesBody extends StatelessWidget { class SceneDevicesBody extends StatelessWidget {
const SceneDevicesBody({ const SceneDevicesBody({
super.key, required this.tabController,
required TabController tabController,
required this.rooms, required this.rooms,
}) : _tabController = tabController; super.key,
});
final TabController _tabController; final TabController tabController;
final List<SubSpaceModel>? rooms; final List<SubSpaceModel> rooms;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final isAutomationDeviceStatus =
((ModalRoute.of(context)?.settings.arguments as SceneSettingsRouteArguments?)?.sceneType ==
CreateSceneEnum.deviceStatusChanges.name);
return BlocBuilder<TabBarBloc, TabBarState>( return BlocBuilder<TabBarBloc, TabBarState>(
builder: (context, tabState) { builder: (context, state) {
return Column( return Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
TabBar( SceneDevicesBodyTabBar(
controller: _tabController, tabController: tabController,
dividerColor: Colors.transparent, rooms: rooms,
indicatorColor: Colors.transparent, selectedRoomId: state is TabBarTabSelectedState ? state.roomId : '-1',
tabs: [
...rooms!.map((e) => Tab(
child: BodyLarge(
text: e.name ?? '',
textAlign: TextAlign.start,
style: context.bodyLarge.copyWith(
color: (tabState is TabSelected) && tabState.roomId == e.id
? ColorsManager.textPrimaryColor
: ColorsManager.textPrimaryColor.withOpacity(0.2),
),
),
)),
],
isScrollable: true,
tabAlignment: TabAlignment.start,
), ),
Expanded( Expanded(
child: TabBarView( child: TabBarView(
controller: _tabController,
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
children: controller: tabController,
rooms!.map((e) => _buildRoomTab(e, context, isAutomationDeviceStatus)).toList(), children: rooms
.map(
(room) => _buildRoomTab(
room,
_isAutomationDeviceStatus(context),
),
)
.toList(),
), ),
), ),
], ],
@ -70,52 +53,46 @@ class SceneDevicesBody extends StatelessWidget {
); );
} }
Widget _buildRoomTab(SubSpaceModel room, BuildContext context, bool isAutomationDeviceStatus) { bool _isAutomationDeviceStatus(BuildContext context) {
final routeArguments =
ModalRoute.of(context)?.settings.arguments as SceneSettingsRouteArguments?;
final deviceStatusChangesScene = CreateSceneEnum.deviceStatusChanges.name;
final sceneType = routeArguments?.sceneType;
return sceneType == deviceStatusChangesScene;
}
Widget _buildRoomTab(
SubSpaceModel room,
bool isAutomationDeviceStatus,
) {
return BlocBuilder<DeviceManagerBloc, DeviceManagerState>( return BlocBuilder<DeviceManagerBloc, DeviceManagerState>(
builder: (context, state) { builder: (context, state) {
if (state.loading && state.devices == null) { final isLoading = state.loading && state.devices == null;
return const Center(child: CircularProgressIndicator()); final hasData =
} else if (state.devices != null && state.devices!.isNotEmpty) { state.devices != null && (state.devices?.isNotEmpty ?? false);
return ListView.builder( final hasError = state.error != null;
itemCount: state.devices!.length,
itemBuilder: (context, index) { final widgets = <bool, Widget>{
final device = state.devices![index]; isLoading: const AppLoadingIndicator(),
return DefaultContainer( hasError: Center(child: Text('${state.error}')),
child: SceneListTile( hasData: SceneDevicesList(
minLeadingWidth: 40, devices: state.devices ?? [],
leadingWidget: SvgPicture.asset(device.icon ?? ''), isAutomationDeviceStatus: isAutomationDeviceStatus,
titleWidget: BodyMedium( ),
text: device.name ?? '', };
style: context.titleSmall.copyWith(
color: ColorsManager.secondaryTextColor, final invalidWidgetEntry = MapEntry(
fontWeight: FontWeight.w400, true,
fontSize: 20, Center(child: Text('This subspace has no devices')),
), );
),
trailingWidget: const Icon( final validWidgetEntry = widgets.entries.firstWhere(
Icons.arrow_forward_ios_rounded, (entry) => entry.key == true,
color: ColorsManager.greyColor, orElse: () => invalidWidgetEntry,
size: 16, );
),
onPressed: () { return validWidgetEntry.value;
Navigator.pushNamed(
context,
Routes.deviceFunctionsRoute,
arguments: {
"device": device,
"isAutomationDeviceStatus": isAutomationDeviceStatus
},
);
},
),
);
},
);
} else if (state.error != null) {
return const Center(child: Text('Something went wrong'));
} else {
return const SizedBox();
}
}, },
); );
} }

View File

@ -0,0 +1,46 @@
import 'package:flutter/material.dart';
import 'package:syncrow_app/features/devices/model/subspace_model.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class SceneDevicesBodyTabBar extends StatelessWidget {
const SceneDevicesBodyTabBar({
required this.tabController,
required this.rooms,
required this.selectedRoomId,
super.key,
});
final String selectedRoomId;
final TabController tabController;
final List<SubSpaceModel> rooms;
@override
Widget build(BuildContext context) {
return TabBar(
controller: tabController,
dividerColor: Colors.transparent,
indicatorColor: Colors.transparent,
isScrollable: true,
tabAlignment: TabAlignment.start,
tabs: rooms.map((e) {
final isSelected = selectedRoomId == e.id;
return Tab(
child: BodyLarge(
text: e.name ?? '',
textAlign: TextAlign.start,
style: context.bodyLarge.copyWith(
color: isSelected
? ColorsManager.textPrimaryColor
: ColorsManager.textPrimaryColor.withValues(
alpha: 0.2,
),
),
),
);
}).toList(),
);
}
}

View File

@ -0,0 +1,66 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/navigation/routing_constants.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class SceneDevicesList extends StatelessWidget {
const SceneDevicesList({
required this.isAutomationDeviceStatus,
required this.devices,
super.key,
});
final List<DeviceModel> devices;
final bool isAutomationDeviceStatus;
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: devices.length,
itemBuilder: (context, index) => _buildDeviceTile(context, devices[index]),
);
}
Widget _buildDeviceTile(
BuildContext context,
DeviceModel device,
) {
return DefaultContainer(
child: SceneListTile(
minLeadingWidth: 40,
leadingWidget: SvgPicture.asset(device.icon ?? ''),
titleWidget: BodyMedium(
text: device.name ?? '',
style: context.titleSmall.copyWith(
color: ColorsManager.secondaryTextColor,
fontWeight: FontWeight.w400,
fontSize: 20,
),
),
trailingWidget: const Icon(
Icons.arrow_forward_ios_rounded,
color: ColorsManager.greyColor,
size: 16,
),
onPressed: () => _navigateToDeviceFunctions(context, device),
),
);
}
void _navigateToDeviceFunctions(
BuildContext context,
DeviceModel device,
) {
Navigator.of(context).pushNamed(
Routes.deviceFunctionsRoute,
arguments: {
"device": device,
"isAutomationDeviceStatus": isAutomationDeviceStatus,
},
);
}
}

View File

@ -132,6 +132,10 @@ class SceneItem extends StatelessWidget {
spaceUuid: HomeCubit.getInstance() spaceUuid: HomeCubit.getInstance()
.selectedSpace! .selectedSpace!
.id), .id),
communityId: HomeCubit.getInstance()
.selectedSpace!
.community
.uuid,
automationId: scene.id)); automationId: scene.id));
}, },
), ),

View File

@ -22,7 +22,7 @@ class SmartEnableAutomation extends StatelessWidget {
child: BlocBuilder<SceneBloc, SceneState>( child: BlocBuilder<SceneBloc, SceneState>(
bloc: context.read<SceneBloc>() bloc: context.read<SceneBloc>()
..add( ..add(
LoadAutomation(HomeCubit.getInstance().selectedSpace?.id ?? '')), LoadAutomation(HomeCubit.getInstance().selectedSpace?.id ?? '',HomeCubit.getInstance().selectedSpace?.community.uuid ?? '')),
builder: (context, state) { builder: (context, state) {
if (state is SceneLoading) { if (state is SceneLoading) {
return const Align( return const Align(

View File

@ -0,0 +1,12 @@
import 'package:flutter/material.dart';
class AppLoadingIndicator extends StatelessWidget {
const AppLoadingIndicator({super.key});
@override
Widget build(BuildContext context) {
return Center(
child: CircularProgressIndicator.adaptive(),
);
}
}

View File

@ -3,8 +3,8 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/model/community_model.dart'; import 'package:syncrow_app/features/app_layout/model/community_model.dart';
import 'package:syncrow_app/features/app_layout/model/space_model.dart'; import 'package:syncrow_app/features/app_layout/model/space_model.dart';
import 'package:syncrow_app/features/app_layout/view/app_layout.dart'; import 'package:syncrow_app/features/app_layout/view/app_layout.dart';
import 'package:syncrow_app/features/auth/view/otp_view.dart';
import 'package:syncrow_app/features/auth/view/login_view.dart'; import 'package:syncrow_app/features/auth/view/login_view.dart';
import 'package:syncrow_app/features/auth/view/otp_view.dart';
import 'package:syncrow_app/features/auth/view/sign_up_view.dart'; import 'package:syncrow_app/features/auth/view/sign_up_view.dart';
import 'package:syncrow_app/features/dashboard/view/dashboard_view.dart'; import 'package:syncrow_app/features/dashboard/view/dashboard_view.dart';
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_bloc.dart'; import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_bloc.dart';
@ -17,11 +17,12 @@ import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_bloc.dart'
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_event.dart'; import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_event.dart';
import 'package:syncrow_app/features/scene/view/device_functions_view.dart'; import 'package:syncrow_app/features/scene/view/device_functions_view.dart';
import 'package:syncrow_app/features/scene/view/scene_auto_settings.dart'; import 'package:syncrow_app/features/scene/view/scene_auto_settings.dart';
import 'package:syncrow_app/features/scene/view/scene_tasks_view.dart';
import 'package:syncrow_app/features/scene/view/scene_rooms_tabbar.dart'; import 'package:syncrow_app/features/scene/view/scene_rooms_tabbar.dart';
import 'package:syncrow_app/features/scene/view/scene_tasks_view.dart';
import 'package:syncrow_app/features/scene/view/scene_view.dart'; import 'package:syncrow_app/features/scene/view/scene_view.dart';
import 'package:syncrow_app/features/scene/view/smart_automation_select_route.dart'; import 'package:syncrow_app/features/scene/view/smart_automation_select_route.dart';
import 'package:syncrow_app/features/splash/view/splash_view.dart'; import 'package:syncrow_app/features/splash/view/splash_view.dart';
import 'routing_constants.dart'; import 'routing_constants.dart';
class Router { class Router {
@ -88,7 +89,7 @@ class Router {
BlocProvider( BlocProvider(
create: (BuildContext context) => create: (BuildContext context) =>
TabBarBloc(context.read<DeviceManagerBloc>()) TabBarBloc(context.read<DeviceManagerBloc>())
..add(TabChanged( ..add(TabBarTabChangedEvent(
selectedIndex: 0, selectedIndex: 0,
roomId: '-1', roomId: '-1',
unit: SpaceModel( unit: SpaceModel(

View File

@ -11,7 +11,7 @@ abstract class ApiEndpoints {
static const String sendOtp = '/authentication/user/send-otp'; static const String sendOtp = '/authentication/user/send-otp';
static const String verifyOtp = '/authentication/user/verify-otp'; static const String verifyOtp = '/authentication/user/verify-otp';
static const String forgetPassword = '/authentication/user/forget-password'; static const String forgetPassword = '/authentication/user/forget-password';
static const String clientLogin = 'client/token';
////////////////////////////////////// Spaces /////////////////////////////////////// ////////////////////////////////////// Spaces ///////////////////////////////////////
///Community Module ///Community Module
@ -88,6 +88,8 @@ abstract class ApiEndpoints {
//SPACE Module //SPACE Module
//GET //GET
static const String userSpaces = '/user/{userUuid}/spaces'; static const String userSpaces = '/user/{userUuid}/spaces';
static const String devices = '/projects/{projectUuid}/devices';
static const String spaceDevices = static const String spaceDevices =
'/projects/{projectUuid}/communities/{communityUuid}/spaces/{spaceUuid}/devices'; '/projects/{projectUuid}/communities/{communityUuid}/spaces/{spaceUuid}/devices';
@ -109,9 +111,9 @@ abstract class ApiEndpoints {
//POST //POST
static const String addDeviceToRoom = '/device/room'; static const String addDeviceToRoom = '/device/room';
static const String addDeviceToGroup = '/device/group'; static const String addDeviceToGroup = '/device/group';
static const String controlDevice = '/device/{deviceUuid}/control'; static const String controlDevice = '/devices/{deviceUuid}/command';
static const String firmwareDevice = static const String firmwareDevice =
'/device/{deviceUuid}/firmware/{firmwareVersion}'; '/devices/{deviceUuid}/firmware/{firmwareVersion}';
static const String getDevicesByUserId = '/device/user/{userId}'; static const String getDevicesByUserId = '/device/user/{userId}';
static const String getDevicesByUnitId = '/device/unit/{unitUuid}'; static const String getDevicesByUnitId = '/device/unit/{unitUuid}';
static const String openDoorLock = '/door-lock/open/{doorLockUuid}'; static const String openDoorLock = '/door-lock/open/{doorLockUuid}';
@ -119,13 +121,13 @@ abstract class ApiEndpoints {
//GET //GET
static const String deviceByRoom = static const String deviceByRoom =
'/projects/{projectUuid}/communities/{communityUuid}/spaces/{spaceUuid}/subspaces/{subSpaceUuid}/devices'; '/projects/{projectUuid}/communities/{communityUuid}/spaces/{spaceUuid}/subspaces/{subSpaceUuid}/devices';
static const String deviceByUuid = '/device/{deviceUuid}'; static const String deviceByUuid = '/devices/{deviceUuid}';
static const String deviceFunctions = '/device/{deviceUuid}/functions'; static const String deviceFunctions = '/devices/{deviceUuid}/functions';
static const String gatewayApi = '/device/gateway/{gatewayUuid}/devices'; static const String gatewayApi = '/devices/gateway/{gatewayUuid}/devices';
static const String deviceFunctionsStatus = static const String deviceFunctionsStatus =
'/device/{deviceUuid}/functions/status'; '/devices/{deviceUuid}/functions/status';
static const String powerClamp = static const String powerClamp =
'/device/{powerClampUuid}/power-clamp/status'; '/devices/{deviceUuid}/functions/status';
///Device Permission Module ///Device Permission Module
//POST //POST
@ -142,7 +144,7 @@ abstract class ApiEndpoints {
/// POST /// POST
static const String createScene = '/scene/tap-to-run'; static const String createScene = '/scene/tap-to-run';
static const String triggerScene = '/scene/tap-to-run/{sceneId}/trigger'; static const String triggerScene = '/scene/tap-to-run/{sceneId}/trigger';
static const String createAutomation = '/automation'; static const String createAutomation = '/projects/{projectId}/automations';
/// GET /// GET
static const String getUnitScenes = static const String getUnitScenes =
@ -151,23 +153,26 @@ abstract class ApiEndpoints {
static const String getScene = '/scene/tap-to-run/{sceneId}'; static const String getScene = '/scene/tap-to-run/{sceneId}';
static const String getIconScene = '/scene/icon'; static const String getIconScene = '/scene/icon';
static const String getUnitAutomation = '/automation/{unitUuid}'; static const String getUnitAutomation =
'/projects/{projectId}/communities/{communityId}/spaces/{unitUuid}/automations';
static const String getAutomationDetails = static const String getAutomationDetails =
'/automation/details/{automationId}'; '/projects/{projectId}/automations/{automationId}';
/// PUT /// PUT
static const String updateScene = '/scene/tap-to-run/{sceneId}'; static const String updateScene = '/scene/tap-to-run/{sceneId}';
static const String updateAutomation = '/automation/{automationId}'; static const String updateAutomation =
'/projects/{projectId}/automations/{automationId}';
static const String updateAutomationStatus = static const String updateAutomationStatus =
'/automation/status/{automationId}'; '/projects/{projectId}/automations/{automationId}';
/// DELETE /// DELETE
static const String deleteScene = '/scene/tap-to-run/{sceneId}'; static const String deleteScene = '/scene/tap-to-run/{sceneId}';
static const String deleteAutomation = '/automation/{automationId}'; static const String deleteAutomation =
'/projects/{projectId}/automations/{automationId}';
//////////////////////Door Lock ////////////////////// //////////////////////Door Lock //////////////////////
//online //online
@ -211,18 +216,18 @@ abstract class ApiEndpoints {
static const String changeSchedule = '/schedule/enable/{deviceUuid}'; static const String changeSchedule = '/schedule/enable/{deviceUuid}';
static const String deleteSchedule = '/schedule/{deviceUuid}/{scheduleId}'; static const String deleteSchedule = '/schedule/{deviceUuid}/{scheduleId}';
static const String reportLogs = static const String reportLogs =
'/device/report-logs/{deviceUuid}?code={code}&startTime={startTime}&endTime={endTime}'; '/devices/report-logs/{deviceUuid}?code={code}&startTime={startTime}&endTime={endTime}';
static const String controlBatch = '/device/control/batch'; static const String controlBatch = '/devices/batch';
static const String statusBatch = '/device/status/batch'; static const String statusBatch = '/devices/batch';
static const String deviceScene = '/device/{deviceUuid}/scenes'; static const String deviceScene = '/devices/{deviceUuid}/scenes';
static const String fourSceneByName = static const String fourSceneByName =
'/device/{deviceUuid}/scenes?switchName={switchName}'; '/devices/{deviceUuid}/scenes?switchName={switchName}';
static const String resetDevice = '/factory/reset/{deviceUuid}'; static const String resetDevice = '/factory/reset/{deviceUuid}';
static const String unAssignScenesDevice = static const String unAssignScenesDevice =
'/device/{deviceUuid}/scenes?switchName={switchName}'; '/devices/{deviceUuid}/scenes?switchName={switchName}';
static const String getDeviceLogs = '/device/report-logs/{uuid}?code={code}'; static const String getDeviceLogs = '/devices/report-logs/{uuid}?code={code}';
static const String terms = '/terms'; static const String terms = '/terms';
static const String policy = '/policy'; static const String policy = '/policy';
static const String getPermission = '/permission/{roleUuid}'; static const String getPermission = '/permission/{roleUuid}';

View File

@ -25,11 +25,15 @@ class AuthenticationAPI {
return response; return response;
} }
static Future<bool> signUp({required SignUpModel model}) async { static Future<bool> signUp({
required SignUpModel model,
required String accessToken,
}) async {
final response = await HTTPService().post( final response = await HTTPService().post(
path: ApiEndpoints.signUp, path: ApiEndpoints.signUp,
body: model.toJson(), body: model.toJson(),
showServerMessage: false, showServerMessage: false,
accessToken: accessToken,
expectedResponseModel: (json) => json['statusCode'] == 201); expectedResponseModel: (json) => json['statusCode'] == 201);
return response; return response;
} }
@ -63,4 +67,20 @@ class AuthenticationAPI {
expectedResponseModel: (json) => json['data']); expectedResponseModel: (json) => json['data']);
return response; return response;
} }
static Future<Map<String, dynamic>> fetchClientToken({
required String clientId,
required String clientSecret,
}) async {
final response = await HTTPService().post(
path: ApiEndpoints.clientLogin,
body: {
'clientId': clientId,
'clientSecret': clientSecret,
},
showServerMessage: false,
expectedResponseModel: (json) => json['data'],
);
return response;
}
} }

View File

@ -1,6 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:developer';
import 'package:syncrow_app/features/devices/model/device_category_model.dart'; import 'package:syncrow_app/features/devices/model/device_category_model.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart'; import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart';
@ -8,7 +7,6 @@ import 'package:syncrow_app/features/devices/model/device_report_model.dart';
import 'package:syncrow_app/features/devices/model/function_model.dart'; import 'package:syncrow_app/features/devices/model/function_model.dart';
import 'package:syncrow_app/services/api/api_links_endpoints.dart'; import 'package:syncrow_app/services/api/api_links_endpoints.dart';
import 'package:syncrow_app/services/api/http_service.dart'; import 'package:syncrow_app/services/api/http_service.dart';
import 'package:syncrow_app/utils/constants/temp_const.dart';
import '../../features/devices/model/create_temporary_password_model.dart'; import '../../features/devices/model/create_temporary_password_model.dart';
class DevicesAPI { class DevicesAPI {
@ -39,7 +37,7 @@ class DevicesAPI {
path: ApiEndpoints.deviceByUuid.replaceAll('{deviceUuid}', deviceId), path: ApiEndpoints.deviceByUuid.replaceAll('{deviceUuid}', deviceId),
body: {"deviceName": deviceName}, body: {"deviceName": deviceName},
expectedResponseModel: (json) { expectedResponseModel: (json) {
return json; return json['data'];
}, },
); );
return response; return response;
@ -92,7 +90,7 @@ class DevicesAPI {
.replaceAll('{deviceUuid}', deviceId), .replaceAll('{deviceUuid}', deviceId),
showServerMessage: false, showServerMessage: false,
expectedResponseModel: (json) { expectedResponseModel: (json) {
return json; return json['data'];
}, },
); );
return response; return response;
@ -101,7 +99,7 @@ class DevicesAPI {
static Future<Map<String, dynamic>> getPowerClampStatus( static Future<Map<String, dynamic>> getPowerClampStatus(
String deviceId) async { String deviceId) async {
final response = await _httpService.get( final response = await _httpService.get(
path: ApiEndpoints.powerClamp.replaceAll('{powerClampUuid}', deviceId), path: ApiEndpoints.deviceFunctionsStatus.replaceAll('{powerClampUuid}', deviceId),
showServerMessage: false, showServerMessage: false,
expectedResponseModel: (json) { expectedResponseModel: (json) {
return json; return json;
@ -132,7 +130,7 @@ class DevicesAPI {
path: ApiEndpoints.deviceFunctions.replaceAll('{deviceUuid}', deviceId), path: ApiEndpoints.deviceFunctions.replaceAll('{deviceUuid}', deviceId),
showServerMessage: false, showServerMessage: false,
expectedResponseModel: (json) { expectedResponseModel: (json) {
final functions = FunctionModel.fromJson(json); final functions = FunctionModel.fromJson(json['data']);
return functions; return functions;
}); });
return response; return response;
@ -188,7 +186,7 @@ class DevicesAPI {
path: ApiEndpoints.deviceByUuid.replaceAll('{deviceUuid}', deviceId), path: ApiEndpoints.deviceByUuid.replaceAll('{deviceUuid}', deviceId),
showServerMessage: false, showServerMessage: false,
expectedResponseModel: (json) { expectedResponseModel: (json) {
return json; return json['data'];
}); });
return response; return response;
} }
@ -264,7 +262,7 @@ class DevicesAPI {
if (json == null || json.isEmpty || json == []) { if (json == null || json.isEmpty || json == []) {
return devices; return devices;
} }
for (var device in json['devices']) { for (var device in json['data']['devices']) {
devices.add(DeviceModel.fromJson(device)); devices.add(DeviceModel.fromJson(device));
} }
return devices; return devices;
@ -491,7 +489,12 @@ class DevicesAPI {
}) async { }) async {
final response = await _httpService.post( final response = await _httpService.post(
path: ApiEndpoints.controlBatch, path: ApiEndpoints.controlBatch,
body: {"devicesUuid": devicesUuid, "code": code, "value": value}, body: {
"devicesUuid": devicesUuid,
"code": code,
"value": value,
"operationType": 'COMMAND',
},
showServerMessage: true, showServerMessage: true,
expectedResponseModel: (json) { expectedResponseModel: (json) {
return json; return json;

View File

@ -27,7 +27,23 @@ class HomeManagementAPI {
return list; return list;
} }
static Future<List<DeviceModel>> fetchDevicesByUnitId(String projectUuid) async { static Future<List<DeviceModel>> fetchDevices(projectUuid) async {
List<DeviceModel> list = [];
await _httpService.get(
path: ApiEndpoints.devices.replaceAll("{projectUuid}", projectUuid),
showServerMessage: false,
expectedResponseModel: (json) {
json['data'].forEach((value) {
list.add(DeviceModel.fromJson(value));
});
});
return list;
}
static Future<List<DeviceModel>> fetchDevicesByUnitId(
String projectUuid) async {
List<DeviceModel> list = []; List<DeviceModel> list = [];
try { try {
@ -62,8 +78,12 @@ class HomeManagementAPI {
return list; return list;
} }
static Future<Map<String, dynamic>> assignDeviceToRoom(String communityId, static Future<Map<String, dynamic>> assignDeviceToRoom(
String spaceId, String subSpaceId, String deviceId, String projectId) async { String communityId,
String spaceId,
String subSpaceId,
String deviceId,
String projectId) async {
try { try {
final response = await _httpService.post( final response = await _httpService.post(
path: ApiEndpoints.assignDeviceToRoom path: ApiEndpoints.assignDeviceToRoom
@ -82,8 +102,12 @@ class HomeManagementAPI {
} }
} }
static Future<Map<String, dynamic>> unAssignDeviceToRoom(String communityId, static Future<Map<String, dynamic>> unAssignDeviceToRoom(
String spaceId, String subSpaceId, String deviceId, String projectId) async { String communityId,
String spaceId,
String subSpaceId,
String deviceId,
String projectId) async {
try { try {
final response = await _httpService.delete( final response = await _httpService.delete(
path: ApiEndpoints.assignDeviceToRoom path: ApiEndpoints.assignDeviceToRoom

View File

@ -48,13 +48,26 @@ class HTTPService {
Options? options, Options? options,
dynamic body, dynamic body,
bool showServerMessage = true, bool showServerMessage = true,
String? accessToken,
required T Function(dynamic) expectedResponseModel}) async { required T Function(dynamic) expectedResponseModel}) async {
try { try {
final authOptions = options ??
Options(
headers: accessToken != null
? {
'Authorization': 'Bearer $accessToken',
'Content-Type': 'application/json',
}
: {
'Content-Type': 'application/json',
},
);
final response = await client.post( final response = await client.post(
path, path,
data: body, data: body,
queryParameters: queryParameters, queryParameters: queryParameters,
options: options, options: authOptions,
); );
return expectedResponseModel(response.data); return expectedResponseModel(response.data);
} catch (error) { } catch (error) {

View File

@ -6,7 +6,6 @@ import 'package:syncrow_app/features/scene/model/scenes_model.dart';
import 'package:syncrow_app/features/scene/model/update_automation.dart'; import 'package:syncrow_app/features/scene/model/update_automation.dart';
import 'package:syncrow_app/services/api/api_links_endpoints.dart'; import 'package:syncrow_app/services/api/api_links_endpoints.dart';
import 'package:syncrow_app/services/api/http_service.dart'; import 'package:syncrow_app/services/api/http_service.dart';
import 'package:syncrow_app/utils/constants/temp_const.dart';
class SceneApi { class SceneApi {
static final HTTPService _httpService = HTTPService(); static final HTTPService _httpService = HTTPService();
@ -31,10 +30,11 @@ class SceneApi {
// create automation // create automation
static Future<Map<String, dynamic>> createAutomation( static Future<Map<String, dynamic>> createAutomation(
CreateAutomationModel createAutomationModel) async { CreateAutomationModel createAutomationModel, String projectId) async {
try { try {
final response = await _httpService.post( final response = await _httpService.post(
path: ApiEndpoints.createAutomation, path:
ApiEndpoints.createAutomation.replaceAll('{projectId}', projectId),
body: createAutomationModel.toMap(), body: createAutomationModel.toMap(),
showServerMessage: false, showServerMessage: false,
expectedResponseModel: (json) { expectedResponseModel: (json) {
@ -78,10 +78,17 @@ class SceneApi {
//getAutomation //getAutomation
static Future<List<ScenesModel>> getAutomationByUnitId(String unitId) async { static Future<List<ScenesModel>> getAutomationByUnitId(
String unitId,
String communityId,
String projectId,
) async {
try { try {
final response = await _httpService.get( final response = await _httpService.get(
path: ApiEndpoints.getUnitAutomation.replaceAll('{unitUuid}', unitId), path: ApiEndpoints.getUnitAutomation
.replaceAll('{unitUuid}', unitId)
.replaceAll('{communityId}', communityId)
.replaceAll('{projectId}', projectId),
showServerMessage: false, showServerMessage: false,
expectedResponseModel: (json) { expectedResponseModel: (json) {
List<ScenesModel> scenes = []; List<ScenesModel> scenes = [];
@ -112,11 +119,12 @@ class SceneApi {
//automation details //automation details
static Future<SceneDetailsModel> getAutomationDetails( static Future<SceneDetailsModel> getAutomationDetails(
String automationId) async { String automationId, String projectId) async {
try { try {
final response = await _httpService.get( final response = await _httpService.get(
path: ApiEndpoints.getAutomationDetails path: ApiEndpoints.getAutomationDetails
.replaceAll('{automationId}', automationId), .replaceAll('{automationId}', automationId)
.replaceAll('{projectId}', projectId),
showServerMessage: false, showServerMessage: false,
expectedResponseModel: (json) => SceneDetailsModel.fromJson(json), expectedResponseModel: (json) => SceneDetailsModel.fromJson(json),
); );
@ -128,11 +136,12 @@ class SceneApi {
//updateAutomationStatus //updateAutomationStatus
static Future<bool> updateAutomationStatus(String automationId, static Future<bool> updateAutomationStatus(String automationId,
AutomationStatusUpdate createAutomationEnable) async { AutomationStatusUpdate createAutomationEnable, String projectId) async {
try { try {
final response = await _httpService.put( final response = await _httpService.patch(
path: ApiEndpoints.updateAutomationStatus path: ApiEndpoints.updateAutomationStatus
.replaceAll('{automationId}', automationId), .replaceAll('{automationId}', automationId)
.replaceAll('{projectId}', projectId),
body: createAutomationEnable.toMap(), body: createAutomationEnable.toMap(),
expectedResponseModel: (json) => json['success'], expectedResponseModel: (json) => json['success'],
); );
@ -194,12 +203,13 @@ class SceneApi {
} }
//update automation //update automation
static updateAutomation( static updateAutomation(CreateAutomationModel createAutomationModel,
CreateAutomationModel createAutomationModel, String automationId) async { String automationId, String projectId) async {
try { try {
final response = await _httpService.put( final response = await _httpService.put(
path: ApiEndpoints.updateAutomation path: ApiEndpoints.updateAutomation
.replaceAll('{automationId}', automationId), .replaceAll('{automationId}', automationId)
.replaceAll('{projectId}', projectId),
body: createAutomationModel body: createAutomationModel
.toJson(automationId.isNotEmpty == true ? automationId : null), .toJson(automationId.isNotEmpty == true ? automationId : null),
expectedResponseModel: (json) { expectedResponseModel: (json) {
@ -229,11 +239,14 @@ class SceneApi {
// delete automation // delete automation
static Future<bool> deleteAutomation( static Future<bool> deleteAutomation(
{required String unitUuid, required String automationId}) async { {required String unitUuid,
required String automationId,
required String projectId}) async {
try { try {
final response = await _httpService.delete( final response = await _httpService.delete(
path: ApiEndpoints.deleteAutomation path: ApiEndpoints.deleteAutomation
.replaceAll('{automationId}', automationId), .replaceAll('{automationId}', automationId)
.replaceAll('{projectId}', projectId),
showServerMessage: false, showServerMessage: false,
expectedResponseModel: (json) => json['statusCode'] == 200, expectedResponseModel: (json) => json['statusCode'] == 200,
); );

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.27+64 version: 1.0.30+1
environment: environment:
sdk: ">=3.0.6 <4.0.0" sdk: ">=3.0.6 <4.0.0"