[#19] Implement Home Assistant state events listener

This commit is contained in:
estevez 2018-09-16 18:02:12 +03:00
parent 1b7a081ae5
commit bf6559c990
4 changed files with 56 additions and 11 deletions

View File

@ -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"] = [];

View File

@ -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 {

View File

@ -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

View File

@ -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.