Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
e0d35d07dc | |||
285447a5b7 | |||
ed3e4ba272 | |||
908563063a |
@ -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,21 +69,28 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
Future _connection() {
|
||||
if ((_connectionCompleter != null) && (!_connectionCompleter.isCompleted)) {
|
||||
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.");
|
||||
|
105
lib/main.dart
105
lib/main.dart
@ -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}");
|
||||
if (event.reconnect) {
|
||||
_homeAssistant.closeConnection();
|
||||
_initConnection().then((b){
|
||||
setState(() {
|
||||
_errorCodeToBeShown = 0;
|
||||
_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();
|
||||
});
|
||||
_initConnection();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -130,25 +154,19 @@ 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();
|
||||
if (_stateSubscription == null) {
|
||||
_stateSubscription = eventBus.on<StateChangedEvent>().listen((event) {
|
||||
setState(() {
|
||||
if (event.localChange) {
|
||||
@ -158,23 +176,30 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
|
||||
}
|
||||
});
|
||||
});
|
||||
if (_serviceCallSubscription != null) _serviceCallSubscription.cancel();
|
||||
_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 (_serviceCallSubscription == null) {
|
||||
_serviceCallSubscription =
|
||||
eventBus.on<ServiceCallEvent>().listen((event) {
|
||||
_callService(event.domain, event.service, event.entityId,
|
||||
event.additionalParams);
|
||||
});
|
||||
}
|
||||
|
||||
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) {
|
||||
_lastErrorMessage = "";
|
||||
await _homeAssistant.fetch().then((result) {
|
||||
setState(() {
|
||||
//_instanceConfig = _homeAssistant.instanceConfig;
|
||||
@ -186,7 +211,6 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
|
||||
_setErrorState(e);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_setErrorState(e) {
|
||||
setState(() {
|
||||
@ -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();
|
||||
|
@ -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));
|
||||
}),
|
||||
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),
|
||||
|
@ -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"
|
||||
|
Reference in New Issue
Block a user