Files
2026-07-11 21:51:34 -05:00

106 lines
3.0 KiB
Dart

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:mirror_core/mirror_core.dart';
import 'settings_provider.dart';
final haServiceProvider = Provider<HomeAssistantService?>((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, HaEntitiesState>(HaEntitiesNotifier.new);
class HaEntitiesState {
final List<HaEntity> entities;
final HaWeather? weather;
final List<HaCalendarEvent> calendarEvents;
final String? error;
const HaEntitiesState({
this.entities = const [],
this.weather,
this.calendarEvents = const [],
this.error,
});
}
class HaEntitiesNotifier extends AsyncNotifier<HaEntitiesState> {
@override
Future<HaEntitiesState> 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<void> 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<void> 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(),
);
}
}