Compare commits

..

4 Commits
0.2.3 ... 0.2.4

Author SHA1 Message Date
e0d35d07dc Version 0.2.4 2018-10-03 14:37:54 +03:00
285447a5b7 Resolves #114 Error going back from settings 2018-10-03 14:36:23 +03:00
ed3e4ba272 COnnection closing improvements 2018-10-03 10:35:40 +03:00
908563063a Fix input_boolean control 2018-10-03 09:50:14 +03:00
5 changed files with 138 additions and 65 deletions

View File

@ -106,7 +106,7 @@ class EntityWidget extends StatefulWidget {
_EntityWidgetState createState() {
switch (entity.domain) {
case "automation":
case "input_boolean ":
case "input_boolean":
case "switch":
case "light": {
return _SwitchEntityWidgetState();

View File

@ -25,9 +25,11 @@ class HomeAssistant {
Timer _connectionTimer;
Timer _fetchTimer;
StreamSubscription _socketSubscription;
int messageExpirationTime = 50; //seconds
Duration fetchTimeout = Duration(seconds: 30);
Duration connectTimeout = Duration(seconds: 10);
Duration fetchTimeout = Duration(seconds: 45);
Duration connectTimeout = Duration(seconds: 15);
String get locationName => _instanceConfig["location_name"] ?? "";
int get viewsCount => _entities.viewList.length ?? 0;
@ -35,15 +37,18 @@ class HomeAssistant {
EntityCollection get entities => _entities;
HomeAssistant(String url, String password, String authType) {
_hassioAPIEndpoint = url;
_hassioPassword = password;
_hassioAuthType = authType;
HomeAssistant() {
_entities = EntityCollection();
_uiBuilder = UIBuilder();
_messageQueue = SendMessageQueue(messageExpirationTime);
}
void updateConnectionSettings(String url, String password, String authType) {
_hassioAPIEndpoint = url;
_hassioPassword = password;
_hassioAuthType = authType;
}
Future fetch() {
if ((_fetchCompleter != null) && (!_fetchCompleter.isCompleted)) {
TheLogger.log("Warning","Previous fetch is not complited");
@ -51,6 +56,7 @@ class HomeAssistant {
_fetchCompleter = new Completer();
_fetchTimer = Timer(fetchTimeout, () {
closeConnection();
TheLogger.log("Error", "Data fetching timeout");
_finishFetching({"errorCode" : 9,"errorMessage": "Couldn't get data from server"});
});
_connection().then((r) {
@ -63,10 +69,15 @@ class HomeAssistant {
}
closeConnection() {
if (_hassioChannel?.closeCode == null) {
_hassioChannel?.sink?.close();
if (_socketSubscription != null) {
_socketSubscription.cancel();
}
if (_hassioChannel != null) {
if (_hassioChannel.closeCode == null) {
_hassioChannel.sink?.close();
}
_hassioChannel = null;
}
_hassioChannel = null;
}
Future _connection() {
@ -74,10 +85,12 @@ class HomeAssistant {
TheLogger.log("Debug","Previous connection is not complited");
} else {
if ((_hassioChannel == null) || (_hassioChannel.sink == null) || (_hassioChannel.closeCode != null)) {
closeConnection();
TheLogger.log("Debug", "Socket connecting...");
_connectionCompleter = new Completer();
_connectionTimer = Timer(connectTimeout, () {
closeConnection();
TheLogger.log("Error", "Socket connection timeout");
_finishConnecting({"errorCode" : 1,"errorMessage": "Couldn't connect to Home Assistant. Looks like a network issues"});
});
_hassioChannel = IOWebSocketChannel.connect(
@ -85,7 +98,8 @@ class HomeAssistant {
_hassioChannel.stream.handleError((e) {
TheLogger.log("Error", "Unhandled socket error: ${e.toString()}");
});
_hassioChannel.stream.listen((message) =>
if (_socketSubscription != null) _socketSubscription.cancel();
_socketSubscription = _hassioChannel.stream.listen((message) =>
_handleMessage(_connectionCompleter, message));
_hassioChannel.sink.done.whenComplete(() {
TheLogger.log("Debug","Socket sink finished. Assuming it is closed.");

View File

@ -34,7 +34,7 @@ part 'badge_class.dart';
EventBus eventBus = new EventBus();
const String appName = "HA Client";
const appVersion = "0.2.3";
const appVersion = "0.2.4";
String homeAssistantWebHost;
@ -88,6 +88,9 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
HomeAssistant _homeAssistant;
EntityCollection _entities;
//Map _instanceConfig;
String _apiEndpoint;
String _apiPassword;
String _authType;
int _uiViewsCount = 0;
String _instanceHost;
int _errorCodeToBeShown = 0;
@ -107,14 +110,35 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
_homeAssistant = HomeAssistant();
_settingsSubscription = eventBus.on<SettingsChangedEvent>().listen((event) {
TheLogger.log("Debug","Settings change event: reconnect=${event.reconnect}");
setState(() {
_errorCodeToBeShown = 0;
});
_initConnection();
if (event.reconnect) {
_homeAssistant.closeConnection();
_initConnection().then((b){
setState(() {
_homeAssistant.updateConnectionSettings(_apiEndpoint, _apiPassword, _authType);
_errorCodeToBeShown = 10;
_lastErrorMessage = "Connection settings was changed.";
});
}, onError: (_) {
setState(() {
_lastErrorMessage = _;
_errorCodeToBeShown = 5;
});
});
}
});
_initConnection().then((_){
_createConnection();
}, onError: (_) {
setState(() {
_lastErrorMessage = _;
_errorCodeToBeShown = 5;
});
});
_initConnection();
}
@override
@ -130,62 +154,62 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
String domain = prefs.getString('hassio-domain');
String port = prefs.getString('hassio-port');
_instanceHost = "$domain:$port";
String apiEndpoint = "${prefs.getString('hassio-protocol')}://$domain:$port/api/websocket";
_apiEndpoint = "${prefs.getString('hassio-protocol')}://$domain:$port/api/websocket";
homeAssistantWebHost = "${prefs.getString('hassio-res-protocol')}://$domain:$port";
String apiPassword = prefs.getString('hassio-password');
String authType = prefs.getString('hassio-auth-type');
if ((domain == null) || (port == null) || (apiPassword == null) ||
(domain.length == 0) || (port.length == 0) || (apiPassword.length == 0)) {
setState(() {
_errorCodeToBeShown = 5;
});
} else {
if (_homeAssistant != null) _homeAssistant.closeConnection();
_createConnection(apiEndpoint, apiPassword, authType);
_apiPassword = prefs.getString('hassio-password');
_authType = prefs.getString('hassio-auth-type');
if ((domain == null) || (port == null) || (_apiPassword == null) ||
(domain.length == 0) || (port.length == 0) || (_apiPassword.length == 0)) {
throw("Check connection settings");
}
}
_createConnection(String apiEndpoint, String apiPassword, String authType) {
_homeAssistant = HomeAssistant(apiEndpoint, apiPassword, authType);
_createConnection() {
_refreshData();
if (_stateSubscription != null) _stateSubscription.cancel();
_stateSubscription = eventBus.on<StateChangedEvent>().listen((event) {
setState(() {
if (event.localChange) {
_entities
.get(event.entityId)
.state = event.newState;
}
if (_stateSubscription == null) {
_stateSubscription = eventBus.on<StateChangedEvent>().listen((event) {
setState(() {
if (event.localChange) {
_entities
.get(event.entityId)
.state = event.newState;
}
});
});
});
if (_serviceCallSubscription != null) _serviceCallSubscription.cancel();
_serviceCallSubscription = eventBus.on<ServiceCallEvent>().listen((event) {
_callService(event.domain, event.service, event.entityId, event.additionalParams);
});
}
if (_serviceCallSubscription == null) {
_serviceCallSubscription =
eventBus.on<ServiceCallEvent>().listen((event) {
_callService(event.domain, event.service, event.entityId,
event.additionalParams);
});
}
if (_showEntityPageSubscription != null) _showEntityPageSubscription.cancel();
_showEntityPageSubscription = eventBus.on<ShowEntityPageEvent>().listen((event) {
_showEntityPage(event.entity);
});
if (_showEntityPageSubscription == null) {
_showEntityPageSubscription =
eventBus.on<ShowEntityPageEvent>().listen((event) {
_showEntityPage(event.entity);
});
}
}
_refreshData() async {
_homeAssistant.updateConnectionSettings(_apiEndpoint, _apiPassword, _authType);
setState(() {
_isLoading = true;
});
_errorCodeToBeShown = 0;
if (_homeAssistant != null) {
await _homeAssistant.fetch().then((result) {
setState(() {
//_instanceConfig = _homeAssistant.instanceConfig;
_entities = _homeAssistant.entities;
_uiViewsCount = _homeAssistant.viewsCount;
_isLoading = false;
});
}).catchError((e) {
_setErrorState(e);
_lastErrorMessage = "";
await _homeAssistant.fetch().then((result) {
setState(() {
//_instanceConfig = _homeAssistant.instanceConfig;
_entities = _homeAssistant.entities;
_uiViewsCount = _homeAssistant.viewsCount;
_isLoading = false;
});
}
}).catchError((e) {
_setErrorState(e);
});
}
_setErrorState(e) {
@ -483,6 +507,25 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
HAUtils.launchURL("https://github.com/estevez-dev/ha_client_pub/issues/new");
},
),
Container(
height: 30.0,
decoration: new BoxDecoration(
border: new Border(
top: BorderSide(
width: 2.0,
color: Colors.black26,
)
),
)
),
new ListTile(
leading: Icon(MaterialDesignIcons.createIconDataFromIconName("mdi:coffee")),
title: Text("By me a coffee"),
onTap: () {
Navigator.of(context).pop();
HAUtils.launchURL("https://www.buymeacoffee.com/estevez");
},
),
new AboutListTile(
applicationName: appName,
applicationVersion: appVersion,
@ -499,6 +542,8 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
SnackBarAction action;
switch (_errorCodeToBeShown) {
case 9:
case 11:
case 7:
case 1: {
action = SnackBarAction(
label: "Retry",
@ -533,9 +578,9 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
break;
}
case 7: {
case 10: {
action = SnackBarAction(
label: "Retry",
label: "Refresh",
onPressed: () {
_scaffoldKey?.currentState?.hideCurrentSnackBar();
_refreshData();

View File

@ -15,6 +15,7 @@ class _ConnectionSettingsPageState extends State<ConnectionSettingsPage> {
String _hassioPassword = "";
String _socketProtocol = "wss";
String _authType = "access_token";
bool _connectionSettingsChanged = false;
@override
void initState() {
@ -45,6 +46,7 @@ class _ConnectionSettingsPageState extends State<ConnectionSettingsPage> {
prefs.setString("hassio-protocol", _socketProtocol);
prefs.setString("hassio-res-protocol", _socketProtocol == "wss" ? "https" : "http");
prefs.setString("hassio-auth-type", _authType);
_connectionSettingsChanged = true;
}
@override
@ -52,12 +54,24 @@ class _ConnectionSettingsPageState extends State<ConnectionSettingsPage> {
return new Scaffold(
appBar: new AppBar(
leading: IconButton(icon: Icon(Icons.arrow_back), onPressed: (){
_saveSettings().then((r){
Navigator.pop(context);
});
eventBus.fire(SettingsChangedEvent(true));
Navigator.pop(context);
}),
title: new Text(widget.title),
actions: <Widget>[
IconButton(
icon: Icon(Icons.check),
onPressed:(){
if (_connectionSettingsChanged) {
_saveSettings().then((r){
Navigator.pop(context);
eventBus.fire(SettingsChangedEvent(_connectionSettingsChanged));
});
} else {
Navigator.pop(context);
}
}
)
],
),
body: ListView(
padding: const EdgeInsets.all(20.0),

View File

@ -1,7 +1,7 @@
name: hass_client
description: Home Assistant Android Client
version: 0.2.3+25
version: 0.2.4+26
environment:
sdk: ">=2.0.0-dev.68.0 <3.0.0"