import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:mirror_core/mirror_core.dart'; import 'settings_provider.dart'; final haServiceProvider = Provider((ref) { final settings = ref.watch(settingsProvider).valueOrNull; if (settings == null || settings.haBaseUrl == null || settings.haToken == null) { return null; } return HomeAssistantService( baseUrl: settings.haBaseUrl!, token: settings.haToken!, ); }); final haEntitiesProvider = AsyncNotifierProvider(HaEntitiesNotifier.new); class HaEntitiesState { final List entities; final HaWeather? weather; final List calendarEvents; final String? error; const HaEntitiesState({ this.entities = const [], this.weather, this.calendarEvents = const [], this.error, }); } class HaEntitiesNotifier extends AsyncNotifier { @override Future build() async { final service = ref.watch(haServiceProvider); if (service == null) { return const HaEntitiesState(error: 'Configure Home Assistant in Settings'); } try { final entities = await service.getStates(); // Find weather entity final weatherEntity = entities.firstWhere( (e) => e.entityId.startsWith('weather.'), orElse: () => HaEntity(entityId: '', state: '', attributes: {}, lastChanged: null), ); HaWeather? weather; if (weatherEntity.entityId.isNotEmpty) { weather = HaWeather.fromEntity(weatherEntity); } return HaEntitiesState( entities: entities, weather: weather, ); } catch (e) { return HaEntitiesState(error: 'HA connection failed: $e'); } } Future toggleEntity(String entityId) async { final service = ref.read(haServiceProvider); if (service == null) return; final entity = state.valueOrNull?.entities.firstWhere( (e) => e.entityId == entityId, orElse: () => HaEntity(entityId: '', state: '', attributes: {}, lastChanged: null), ); if (entity == null || entity.entityId.isEmpty) return; final isOn = entity.state == 'on'; if (isOn) { await service.turnOff(entityId); } else { await service.turnOn(entityId); } // Refresh state ref.invalidateSelf(); } Future callScene(String entityId) async { final service = ref.read(haServiceProvider); if (service == null) return; await service.callService('scene', 'turn_on', entityId: entityId); ref.invalidateSelf(); } void refresh() => ref.invalidateSelf(); } class HaWeather { final double? temperature; final String? condition; final double? humidity; const HaWeather({this.temperature, this.condition, this.humidity}); factory HaWeather.fromEntity(HaEntity entity) { final attrs = entity.attributes; return HaWeather( temperature: (attrs['temperature'] as num?)?.toDouble(), condition: entity.state, humidity: (attrs['humidity'] as num?)?.toDouble(), ); } }