import 'dart:async'; import 'package:firebase_database/firebase_database.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart'; import 'package:syncrow_web/pages/device_managment/curtain/bloc/curtain_event.dart'; import 'package:syncrow_web/pages/device_managment/curtain/bloc/curtain_state.dart'; import 'package:syncrow_web/services/devices_mang_api.dart'; class CurtainBloc extends Bloc { late bool deviceStatus; final String deviceId; Timer? _timer; CurtainBloc({required this.deviceId}) : super(CurtainInitial()) { on(_onFetchDeviceStatus); on(_onFetchBatchStatus); on(_onCurtainControl); on(_onCurtainBatchControl); on(_onFactoryReset); } FutureOr _onFetchDeviceStatus( CurtainFetchDeviceStatus event, Emitter emit) async { emit(CurtainStatusLoading()); try { final status = await DevicesManagementApi().getDeviceStatus(event.deviceId); deviceStatus = _checkStatus(status.status[0].value); emit(CurtainStatusLoaded(deviceStatus)); } catch (e) { emit(CurtainError(e.toString())); } } // _listenToChanges(deviceId) { // try { // DatabaseReference ref = // FirebaseDatabase.instance.ref('device-status/$deviceId'); // Stream stream = ref.onValue; // stream.listen((DatabaseEvent event) { // Map usersMap = // event.snapshot.value as Map; // List statusList = []; // usersMap['status'].forEach((element) { // statusList // .add(Status(code: element['code'], value: element['value'])); // }); // deviceStatus = // GarageDoorStatusModel.fromJson(usersMap['productUuid'], statusList); // if (!isClosed) { // add(StatusUpdated(deviceStatus)); // } // }); // } catch (_) {} // } // void _onStatusUpdated(StatusUpdated event, Emitter emit) { // deviceStatus = event.deviceStatus; // emit(GarageDoorLoadedState(status: deviceStatus)); // } FutureOr _onCurtainControl( CurtainControl event, Emitter emit) async { final oldValue = deviceStatus; _updateLocalValue(event.value, emit); emit(CurtainStatusLoaded(deviceStatus)); await _runDebounce( deviceId: event.deviceId, code: event.code, value: event.value, oldValue: oldValue, emit: emit, isBatch: false, ); } Future _runDebounce({ required dynamic deviceId, required String code, required bool value, required bool oldValue, required Emitter emit, required bool isBatch, }) async { late String id; if (deviceId is List) { id = deviceId.first; } else { id = deviceId; } if (_timer != null) { _timer!.cancel(); } _timer = Timer(const Duration(seconds: 1), () async { try { final controlValue = value ? 'open' : 'close'; late bool response; if (isBatch) { response = await DevicesManagementApi() .deviceBatchControl(deviceId, code, controlValue); } else { response = await DevicesManagementApi() .deviceControl(deviceId, Status(code: code, value: controlValue)); } if (!response) { _revertValueAndEmit(id, oldValue, emit); } } catch (e) { _revertValueAndEmit(id, oldValue, emit); } }); } void _revertValueAndEmit( String deviceId, bool oldValue, Emitter emit) { _updateLocalValue(oldValue, emit); emit(CurtainStatusLoaded(deviceStatus)); emit(const CurtainControlError('Failed to control the device.')); } void _updateLocalValue(bool value, Emitter emit) { deviceStatus = value; emit(CurtainStatusLoaded(deviceStatus)); } bool _checkStatus(String command) { return command.toLowerCase() == 'open'; } FutureOr _onFetchBatchStatus( CurtainFetchBatchStatus event, Emitter emit) async { emit(CurtainStatusLoading()); try { final status = await DevicesManagementApi().getBatchStatus(event.devicesIds); deviceStatus = _checkStatus(status.status[0].value); emit(CurtainStatusLoaded(deviceStatus)); } catch (e) { emit(CurtainError(e.toString())); } } FutureOr _onCurtainBatchControl( CurtainBatchControl event, Emitter emit) async { final oldValue = deviceStatus; _updateLocalValue(event.value, emit); emit(CurtainStatusLoaded(deviceStatus)); await _runDebounce( deviceId: event.devicesIds, code: event.code, value: event.value, oldValue: oldValue, emit: emit, isBatch: true, ); } FutureOr _onFactoryReset( CurtainFactoryReset event, Emitter emit) async { emit(CurtainStatusLoading()); try { final response = await DevicesManagementApi().factoryReset( event.factoryReset, event.deviceId, ); if (!response) { emit(const CurtainControlError('Failed')); } else { add(CurtainFetchDeviceStatus(event.deviceId)); } } catch (e) { emit(CurtainControlError(e.toString())); } } }