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/batch_control_devices_service.dart'; import 'package:syncrow_web/services/control_device_service.dart'; import 'package:syncrow_web/services/devices_mang_api.dart'; class CurtainBloc extends Bloc { late bool deviceStatus; final String deviceId; final ControlDeviceService controlDeviceService; final BatchControlDevicesService batchControlDevicesService; CurtainBloc({ required this.deviceId, required this.controlDeviceService, required this.batchControlDevicesService, }) : super(CurtainInitial()) { on(_onFetchDeviceStatus); on(_onFetchBatchStatus); on(_onCurtainControl); on(_onCurtainBatchControl); on(_onFactoryReset); on(_onStatusUpdated); } Future _onFetchDeviceStatus( CurtainFetchDeviceStatus event, Emitter emit, ) async { emit(CurtainStatusLoading()); try { final status = await DevicesManagementApi().getDeviceStatus(event.deviceId); _listenToChanges(event.deviceId, emit); deviceStatus = _checkStatus(status.status[0].value); emit(CurtainStatusLoaded(deviceStatus)); } catch (e) { emit(CurtainError(e.toString())); } } void _listenToChanges(String deviceId, Emitter emit) { try { final ref = FirebaseDatabase.instance.ref('device-status/$deviceId'); final stream = ref.onValue; stream.listen((DatabaseEvent event) { final data = event.snapshot.value as Map?; if (data == null) return; final statusList = []; if (data['status'] != null) { for (var element in data['status']) { statusList.add( Status( code: element['code'].toString(), value: element['value'].toString(), ), ); } } if (statusList.isNotEmpty) { final newStatus = _checkStatus(statusList[0].value); if (newStatus != deviceStatus) { deviceStatus = newStatus; if (!isClosed) { add(StatusUpdated(deviceStatus)); } } } }); } catch (e) { emit(CurtainError('Failed to listen to changes: $e')); } } void _onStatusUpdated( StatusUpdated event, Emitter emit, ) { emit(CurtainStatusLoading()); deviceStatus = event.deviceStatus; emit(CurtainStatusLoaded(deviceStatus)); } Future _onCurtainControl( CurtainControl event, Emitter emit, ) async { emit(CurtainStatusLoading()); _updateLocalValue(event.value, emit); try { final controlValue = event.value ? 'open' : 'close'; await controlDeviceService.controlDevice( deviceUuid: event.deviceId, status: Status(code: event.code, value: controlValue), ); } catch (e) { _updateLocalValue(!event.value, emit); emit(CurtainControlError(e.toString())); } } void _updateLocalValue(bool value, Emitter emit) { deviceStatus = value; emit(CurtainStatusLoaded(deviceStatus)); } bool _checkStatus(String command) { return command.toLowerCase() == 'open'; } Future _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())); } } Future _onCurtainBatchControl( CurtainBatchControl event, Emitter emit, ) async { emit(CurtainStatusLoading()); _updateLocalValue(event.value, emit); try { final controlValue = event.value ? 'open' : 'stop'; await batchControlDevicesService.batchControlDevices( uuids: event.devicesIds, code: event.code, value: controlValue, ); } catch (e) { _updateLocalValue(!event.value, emit); emit(CurtainControlError(e.toString())); } } Future _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())); } } }