[#19] Implement Home Assistant state events listener
This commit is contained in:
parent
1b7a081ae5
commit
bf6559c990
@ -1,5 +1,11 @@
|
||||
part of 'main.dart';
|
||||
|
||||
class StateChangedEvent {
|
||||
String entityId;
|
||||
|
||||
StateChangedEvent(this.entityId);
|
||||
}
|
||||
|
||||
class HassioDataModel {
|
||||
String _hassioAPIEndpoint;
|
||||
String _hassioPassword;
|
||||
@ -28,7 +34,8 @@ class HassioDataModel {
|
||||
if ((_fetchCompleter != null) && (!_fetchCompleter.isCompleted)) {
|
||||
debugPrint("Previous fetch is not complited");
|
||||
} else {
|
||||
_fetchingTimer = new Timer(new Duration(seconds: 10), () {
|
||||
//Fetch timeout timer
|
||||
_fetchingTimer = Timer(Duration(seconds: 10), () {
|
||||
_fetchCompleter.completeError({"message": "Data fetching timeout."});
|
||||
_hassioChannel.sink.close();
|
||||
_hassioChannel = null;
|
||||
@ -76,15 +83,15 @@ class HassioDataModel {
|
||||
}
|
||||
|
||||
_handleMessage(Completer connectionCompleter, String message) {
|
||||
debugPrint("<[Receive]Message from Home Assistant:");
|
||||
var data = json.decode(message);
|
||||
debugPrint(" type: ${data['type']}");
|
||||
debugPrint("[Received]Message type: ${data['type']}");
|
||||
if (data["type"] == "auth_required") {
|
||||
debugPrint(" sending auth!");
|
||||
_sendMessageRaw('{"type": "auth","api_password": "$_hassioPassword"}');
|
||||
} else if (data["type"] == "auth_ok") {
|
||||
debugPrint(" auth done");
|
||||
debugPrint("Connection done");
|
||||
debugPrint("Connection done.");
|
||||
sendSubscribe();
|
||||
connectionCompleter.complete();
|
||||
} else if (data["type"] == "auth_invalid") {
|
||||
connectionCompleter.completeError({message: "Auth error: ${data["message"]}"});
|
||||
@ -99,18 +106,35 @@ class HassioDataModel {
|
||||
} else if (data["id"] == _currentMssageId) {
|
||||
debugPrint("Request id:$_currentMssageId was successful");
|
||||
} else {
|
||||
_handleErrorMessage({"message" : "Wrong message ID"});
|
||||
debugPrint("Skipped message due to messageId:");
|
||||
debugPrint(message);
|
||||
}
|
||||
} else {
|
||||
_handleErrorMessage(data["error"]);
|
||||
}
|
||||
} else if (data["type"] == "event") {
|
||||
if ((data["event"] != null) && (data["event"]["event_type"] == "state_changed")) {
|
||||
_handleEntityStateChange(data["event"]["data"]);
|
||||
} else if (data["event"] != null) {
|
||||
debugPrint("Unhandled event type: ${data["event"]["event_type"]}");
|
||||
} else {
|
||||
debugPrint("Event is null");
|
||||
}
|
||||
} else {
|
||||
debugPrint("Unknown message type");
|
||||
debugPrint(message);
|
||||
}
|
||||
}
|
||||
|
||||
_handleErrorMessage(Object error) {
|
||||
debugPrint("Error: ${error.toString()}");
|
||||
if (!_statesCompleter.isCompleted) _statesCompleter.completeError(error);
|
||||
if (!_servicesCompleter.isCompleted) _servicesCompleter.completeError(error);
|
||||
if ((_statesCompleter != null) && (!_statesCompleter.isCompleted)) _statesCompleter.completeError(error);
|
||||
if ((_servicesCompleter != null) && (!_servicesCompleter.isCompleted)) _servicesCompleter.completeError(error);
|
||||
}
|
||||
|
||||
void sendSubscribe() {
|
||||
_incrementMessageId();
|
||||
_sendMessageRaw('{"id": $_currentMssageId, "type": "subscribe_events"}');
|
||||
}
|
||||
|
||||
Future _getStates() {
|
||||
@ -137,14 +161,19 @@ class HassioDataModel {
|
||||
|
||||
_sendMessageRaw(message) {
|
||||
_reConnectSocket().then((r) {
|
||||
debugPrint(">[Send]Sending to Home Assistant:");
|
||||
debugPrint(" $message");
|
||||
debugPrint("[Sent]$message");
|
||||
_hassioChannel.sink.add(message);
|
||||
}).catchError((e){
|
||||
debugPrint("Unable to connect for sending: $e");
|
||||
});
|
||||
}
|
||||
|
||||
void _handleEntityStateChange(Map eventData) {
|
||||
String entityId = eventData["entity_id"];
|
||||
_entitiesData[entityId].addAll(eventData["new_state"]);
|
||||
eventBus.fire(new StateChangedEvent(eventData["entity_id"]));
|
||||
}
|
||||
|
||||
void _parseServices(Map data) {
|
||||
Map result = {};
|
||||
debugPrint("Parsing ${data.length} Home Assistant service domains");
|
||||
@ -202,11 +231,10 @@ class HassioDataModel {
|
||||
});
|
||||
|
||||
//Gethering information for UI
|
||||
|
||||
debugPrint("Gethering views");
|
||||
uiGroups.forEach((viewId) {
|
||||
var viewGroup = _entitiesData[viewId];
|
||||
Map viewGroupStructure = {};
|
||||
debugPrint("Gethering views");
|
||||
if (viewGroup != null) {
|
||||
viewGroupStructure["standalone"] = [];
|
||||
viewGroupStructure["groups"] = [];
|
||||
|
@ -7,10 +7,13 @@ import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:web_socket_channel/io.dart';
|
||||
import 'package:web_socket_channel/status.dart' as socketStatus;
|
||||
import 'package:progress_indicators/progress_indicators.dart';
|
||||
import 'package:event_bus/event_bus.dart';
|
||||
|
||||
part 'settings.dart';
|
||||
part 'data_model.dart';
|
||||
|
||||
EventBus eventBus = new EventBus();
|
||||
|
||||
void main() => runApp(new HassClientApp());
|
||||
|
||||
class HassClientApp extends StatelessWidget {
|
||||
@ -71,6 +74,12 @@ class _MainPageState extends State<MainPage> {
|
||||
String _hassioPassword = prefs.getString('hassio-password');
|
||||
_dataModel = HassioDataModel(_hassioAPIEndpoint, _hassioPassword);
|
||||
await _refreshData();
|
||||
eventBus.on<StateChangedEvent>().listen((event) {
|
||||
debugPrint("State change event for ${event.entityId}");
|
||||
setState(() {
|
||||
_entitiesData = _dataModel.entities;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
_refreshData() async {
|
||||
|
@ -71,6 +71,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.2"
|
||||
event_bus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: event_bus
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
|
@ -17,6 +17,7 @@ dependencies:
|
||||
sdk: flutter
|
||||
shared_preferences: any
|
||||
progress_indicators: ^0.1.2
|
||||
event_bus: ^1.0.1
|
||||
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
|
Reference in New Issue
Block a user