Connection improvements
This commit is contained in:
@ -10,6 +10,8 @@ class Connection {
|
|||||||
|
|
||||||
Connection._internal();
|
Connection._internal();
|
||||||
|
|
||||||
|
String _domain;
|
||||||
|
String _port;
|
||||||
String displayHostname;
|
String displayHostname;
|
||||||
String _webSocketAPIEndpoint;
|
String _webSocketAPIEndpoint;
|
||||||
String httpWebHost;
|
String httpWebHost;
|
||||||
@ -17,6 +19,8 @@ class Connection {
|
|||||||
String _tempToken;
|
String _tempToken;
|
||||||
String oauthUrl;
|
String oauthUrl;
|
||||||
String deviceName;
|
String deviceName;
|
||||||
|
bool useLovelace = true;
|
||||||
|
bool settingsLoaded = false;
|
||||||
bool get isAuthenticated => _token != null;
|
bool get isAuthenticated => _token != null;
|
||||||
StreamSubscription _socketSubscription;
|
StreamSubscription _socketSubscription;
|
||||||
Duration connectTimeout = Duration(seconds: 15);
|
Duration connectTimeout = Duration(seconds: 15);
|
||||||
@ -30,40 +34,55 @@ class Connection {
|
|||||||
int _currentMessageId = 0;
|
int _currentMessageId = 0;
|
||||||
Map<String, Completer> _messageResolver = {};
|
Map<String, Completer> _messageResolver = {};
|
||||||
|
|
||||||
Future init(onStateChange) async {
|
Future init({bool loadSettings, bool forceReconnect: false}) async {
|
||||||
Completer completer = Completer();
|
Completer completer = Completer();
|
||||||
onStateChangeCallback = onStateChange;
|
if (loadSettings) {
|
||||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
Logger.e("Loading settings...");
|
||||||
String domain = prefs.getString('hassio-domain');
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
String port = prefs.getString('hassio-port');
|
useLovelace = prefs.getBool('use-lovelace') ?? true;
|
||||||
displayHostname = "$domain:$port";
|
_domain = prefs.getString('hassio-domain');
|
||||||
_webSocketAPIEndpoint = "${prefs.getString('hassio-protocol')}://$domain:$port/api/websocket";
|
_port = prefs.getString('hassio-port');
|
||||||
httpWebHost = "${prefs.getString('hassio-res-protocol')}://$domain:$port";
|
displayHostname = "$_domain:$_port";
|
||||||
//_token = prefs.getString('hassio-token');
|
_webSocketAPIEndpoint = "${prefs.getString('hassio-protocol')}://$_domain:$_port/api/websocket";
|
||||||
final storage = new FlutterSecureStorage();
|
httpWebHost = "${prefs.getString('hassio-res-protocol')}://$_domain:$_port";
|
||||||
try {
|
//_token = prefs.getString('hassio-token');
|
||||||
_token = await storage.read(key: "hacl_llt");
|
final storage = new FlutterSecureStorage();
|
||||||
} catch (e) {
|
try {
|
||||||
Logger.e("Cannt read secure storage. Need to relogin.");
|
_token = await storage.read(key: "hacl_llt");
|
||||||
_token = null;
|
Logger.e("Long-lived token read successful");
|
||||||
await storage.delete(key: "hacl_llt");
|
} catch (e) {
|
||||||
}
|
Logger.e("Cannt read secure storage. Need to relogin.");
|
||||||
if ((domain == null) || (port == null) ||
|
_token = null;
|
||||||
(domain.length == 0) || (port.length == 0)) {
|
await storage.delete(key: "hacl_llt");
|
||||||
completer.completeError({"errorCode": 5, "errorMessage": "Check connection settings"});
|
}
|
||||||
} else {
|
|
||||||
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
|
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
|
||||||
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
|
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
|
||||||
deviceName = androidInfo.model;
|
deviceName = androidInfo.model;
|
||||||
oauthUrl = "$httpWebHost/auth/authorize?client_id=${Uri.encodeComponent('http://ha-client.homemade.systems/')}&redirect_uri=${Uri.encodeComponent('http://ha-client.homemade.systems/service/auth_callback.html')}";
|
oauthUrl = "$httpWebHost/auth/authorize?client_id=${Uri.encodeComponent('http://ha-client.homemade.systems/')}&redirect_uri=${Uri.encodeComponent('http://ha-client.homemade.systems/service/auth_callback.html')}";
|
||||||
if (_token == null) {
|
settingsLoaded = true;
|
||||||
await AuthManager().getTempToken(
|
}
|
||||||
oauthUrl: oauthUrl
|
if ((_domain == null) || (_port == null) ||
|
||||||
).then((token) {
|
(_domain.isEmpty) || (_port.isEmpty)) {
|
||||||
Logger.d("Token from AuthManager recived");
|
completer.completeError({"errorCode": 5, "errorMessage": "Check connection settings"});
|
||||||
_tempToken = token;
|
}
|
||||||
});
|
|
||||||
}
|
if (_token == null) {
|
||||||
|
AuthManager().getTempToken(
|
||||||
|
oauthUrl: oauthUrl
|
||||||
|
).then((token) {
|
||||||
|
Logger.d("Token from AuthManager recived");
|
||||||
|
_tempToken = token;
|
||||||
|
_doConnect(completer: completer, forceReconnect: forceReconnect);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
_doConnect(completer: completer, forceReconnect: forceReconnect);
|
||||||
|
}
|
||||||
|
|
||||||
|
return completer.future;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _doConnect({Completer completer, bool forceReconnect}) {
|
||||||
|
if (forceReconnect || !isConnected) {
|
||||||
_connect().timeout(connectTimeout, onTimeout: () {
|
_connect().timeout(connectTimeout, onTimeout: () {
|
||||||
_disconnect().then((_) {
|
_disconnect().then((_) {
|
||||||
completer.completeError(
|
completer.completeError(
|
||||||
@ -72,8 +91,9 @@ class Connection {
|
|||||||
}).then((_) => completer.complete()).catchError((e) {
|
}).then((_) => completer.complete()).catchError((e) {
|
||||||
completer.completeError(e);
|
completer.completeError(e);
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
completer.complete();
|
||||||
}
|
}
|
||||||
return completer.future;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Completer connecting;
|
Completer connecting;
|
||||||
@ -121,6 +141,7 @@ class Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_disconnect() async {
|
_disconnect() async {
|
||||||
|
isConnected = false;
|
||||||
Logger.d( "Socket disconnecting...");
|
Logger.d( "Socket disconnecting...");
|
||||||
if (_socketSubscription != null) {
|
if (_socketSubscription != null) {
|
||||||
await _socketSubscription?.cancel();
|
await _socketSubscription?.cancel();
|
||||||
|
@ -4,7 +4,7 @@ class HomeAssistant {
|
|||||||
|
|
||||||
final Connection connection = Connection();
|
final Connection connection = Connection();
|
||||||
|
|
||||||
bool _useLovelace = false;
|
//bool _useLovelace = false;
|
||||||
//bool isSettingsLoaded = false;
|
//bool isSettingsLoaded = false;
|
||||||
|
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ class HomeAssistant {
|
|||||||
Duration fetchTimeout = Duration(seconds: 30);
|
Duration fetchTimeout = Duration(seconds: 30);
|
||||||
|
|
||||||
String get locationName {
|
String get locationName {
|
||||||
if (_useLovelace) {
|
if (Connection().useLovelace) {
|
||||||
return ui?.title ?? "";
|
return ui?.title ?? "";
|
||||||
} else {
|
} else {
|
||||||
return _instanceConfig["location_name"] ?? "";
|
return _instanceConfig["location_name"] ?? "";
|
||||||
@ -36,38 +36,22 @@ class HomeAssistant {
|
|||||||
bool get isNoViews => ui == null || ui.isEmpty;
|
bool get isNoViews => ui == null || ui.isEmpty;
|
||||||
//int get viewsCount => entities.views.length ?? 0;
|
//int get viewsCount => entities.views.length ?? 0;
|
||||||
|
|
||||||
HomeAssistant();
|
HomeAssistant() {
|
||||||
|
Connection().onStateChangeCallback = _handleEntityStateChange;
|
||||||
Completer _connectCompleter;
|
|
||||||
|
|
||||||
Future init() {
|
|
||||||
if (_connectCompleter != null && !_connectCompleter.isCompleted) {
|
|
||||||
Logger.w("Previous connection pending...");
|
|
||||||
return _connectCompleter.future;
|
|
||||||
}
|
|
||||||
Logger.d("init...");
|
|
||||||
_connectCompleter = Completer();
|
|
||||||
connection.init(_handleEntityStateChange).then((_) {
|
|
||||||
SharedPreferences.getInstance().then((prefs) {
|
|
||||||
if (entities == null) entities = EntityCollection(connection.httpWebHost);
|
|
||||||
_useLovelace = prefs.getBool('use-lovelace') ?? true;
|
|
||||||
_connectCompleter.complete();
|
|
||||||
}).catchError((e) => _connectCompleter.completeError(e));
|
|
||||||
}).catchError((e) => _connectCompleter.completeError(e));
|
|
||||||
return _connectCompleter.future;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Completer _fetchCompleter;
|
Completer _fetchCompleter;
|
||||||
|
|
||||||
Future fetch() {
|
Future fetchData() {
|
||||||
if (_fetchCompleter != null && !_fetchCompleter.isCompleted) {
|
if (_fetchCompleter != null && !_fetchCompleter.isCompleted) {
|
||||||
Logger.w("Previous data fetch is not completed yet");
|
Logger.w("Previous data fetch is not completed yet");
|
||||||
return _fetchCompleter.future;
|
return _fetchCompleter.future;
|
||||||
}
|
}
|
||||||
|
if (entities == null) entities = EntityCollection(connection.httpWebHost);
|
||||||
_fetchCompleter = Completer();
|
_fetchCompleter = Completer();
|
||||||
List<Future> futures = [];
|
List<Future> futures = [];
|
||||||
futures.add(_getStates());
|
futures.add(_getStates());
|
||||||
if (_useLovelace) {
|
if (Connection().useLovelace) {
|
||||||
futures.add(_getLovelace());
|
futures.add(_getLovelace());
|
||||||
}
|
}
|
||||||
futures.add(_getConfig());
|
futures.add(_getConfig());
|
||||||
@ -319,7 +303,7 @@ class HomeAssistant {
|
|||||||
|
|
||||||
void _createUI() {
|
void _createUI() {
|
||||||
ui = HomeAssistantUI();
|
ui = HomeAssistantUI();
|
||||||
if ((_useLovelace) && (_rawLovelaceData != null)) {
|
if ((Connection().useLovelace) && (_rawLovelaceData != null)) {
|
||||||
Logger.d("Creating Lovelace UI");
|
Logger.d("Creating Lovelace UI");
|
||||||
_parseLovelace();
|
_parseLovelace();
|
||||||
} else {
|
} else {
|
||||||
|
@ -191,27 +191,28 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
_settingsSubscription = eventBus.on<SettingsChangedEvent>().listen((event) {
|
_settingsSubscription = eventBus.on<SettingsChangedEvent>().listen((event) {
|
||||||
Logger.d("Settings change event: reconnect=${event.reconnect}");
|
Logger.d("Settings change event: reconnect=${event.reconnect}");
|
||||||
if (event.reconnect) {
|
if (event.reconnect) {
|
||||||
_reLoad();
|
_fullLoad();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
_initialLoad();
|
_fullLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _initialLoad() async {
|
void _fullLoad() async {
|
||||||
_showInfoBottomBar(progress: true,);
|
_showInfoBottomBar(progress: true,);
|
||||||
widget.homeAssistant.init().then((_){
|
_subscribe().then((_) {
|
||||||
_subscribe();
|
Connection().init(loadSettings: true, forceReconnect: true).then((__){
|
||||||
_fetchData();
|
_fetchData();
|
||||||
|
});
|
||||||
}, onError: (e) {
|
}, onError: (e) {
|
||||||
_setErrorState(e);
|
_setErrorState(e);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _reLoad() {
|
void _quickLoad() {
|
||||||
_hideBottomBar();
|
_hideBottomBar();
|
||||||
_showInfoBottomBar(progress: true,);
|
_showInfoBottomBar(progress: true,);
|
||||||
widget.homeAssistant.init().then((_){
|
Connection().init(loadSettings: false, forceReconnect: false).then((_){
|
||||||
_fetchData();
|
_fetchData();
|
||||||
}, onError: (e) {
|
}, onError: (e) {
|
||||||
_setErrorState(e);
|
_setErrorState(e);
|
||||||
@ -219,7 +220,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
}
|
}
|
||||||
|
|
||||||
_fetchData() async {
|
_fetchData() async {
|
||||||
await widget.homeAssistant.fetch().then((_) {
|
await widget.homeAssistant.fetchData().then((_) {
|
||||||
_hideBottomBar();
|
_hideBottomBar();
|
||||||
int currentViewCount = widget.homeAssistant.ui?.views?.length ?? 0;
|
int currentViewCount = widget.homeAssistant.ui?.views?.length ?? 0;
|
||||||
if (_previousViewCount != currentViewCount) {
|
if (_previousViewCount != currentViewCount) {
|
||||||
@ -236,8 +237,8 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
@override
|
@override
|
||||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||||
Logger.d("$state");
|
Logger.d("$state");
|
||||||
if (state == AppLifecycleState.resumed) {
|
if (state == AppLifecycleState.resumed && Connection().settingsLoaded) {
|
||||||
_reLoad();
|
_quickLoad();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,7 +248,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
_stateSubscription = eventBus.on<StateChangedEvent>().listen((event) {
|
_stateSubscription = eventBus.on<StateChangedEvent>().listen((event) {
|
||||||
if (event.needToRebuildUI) {
|
if (event.needToRebuildUI) {
|
||||||
Logger.d("New entity. Need to rebuild UI");
|
Logger.d("New entity. Need to rebuild UI");
|
||||||
_reLoad();
|
_quickLoad();
|
||||||
} else {
|
} else {
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
@ -255,7 +256,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
}
|
}
|
||||||
if (_reloadUISubscription == null) {
|
if (_reloadUISubscription == null) {
|
||||||
_reloadUISubscription = eventBus.on<ReloadUIEvent>().listen((event){
|
_reloadUISubscription = eventBus.on<ReloadUIEvent>().listen((event){
|
||||||
_reLoad();
|
_quickLoad();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (_serviceCallSubscription == null) {
|
if (_serviceCallSubscription == null) {
|
||||||
@ -549,7 +550,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
child: Text("Retry", style: textStyle),
|
child: Text("Retry", style: textStyle),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
//_scaffoldKey?.currentState?.hideCurrentSnackBar();
|
//_scaffoldKey?.currentState?.hideCurrentSnackBar();
|
||||||
_reLoad();
|
_quickLoad();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@ -571,7 +572,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
_bottomBarAction = FlatButton(
|
_bottomBarAction = FlatButton(
|
||||||
child: Text("Login", style: textStyle),
|
child: Text("Login", style: textStyle),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_reLoad();
|
_fullLoad();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@ -582,7 +583,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
_bottomBarAction = FlatButton(
|
_bottomBarAction = FlatButton(
|
||||||
child: Text("Try again", style: textStyle),
|
child: Text("Try again", style: textStyle),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_reLoad();
|
_fullLoad();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@ -592,7 +593,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
_bottomBarAction = FlatButton(
|
_bottomBarAction = FlatButton(
|
||||||
child: Text("Login again", style: textStyle),
|
child: Text("Login again", style: textStyle),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_reLoad();
|
_fullLoad();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@ -603,7 +604,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
child: Text("Reload", style: textStyle),
|
child: Text("Reload", style: textStyle),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
//_scaffoldKey?.currentState?.hideCurrentSnackBar();
|
//_scaffoldKey?.currentState?.hideCurrentSnackBar();
|
||||||
_reLoad();
|
_fullLoad();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@ -615,7 +616,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
_bottomBarAction = FlatButton(
|
_bottomBarAction = FlatButton(
|
||||||
child: Text("Reconnect", style: textStyle),
|
child: Text("Reconnect", style: textStyle),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_reLoad();
|
_fullLoad();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@ -625,7 +626,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
_bottomBarAction = FlatButton(
|
_bottomBarAction = FlatButton(
|
||||||
child: Text("Try again", style: textStyle),
|
child: Text("Try again", style: textStyle),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_reLoad();
|
_fullLoad();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@ -672,10 +673,10 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
items: popupMenuItems
|
items: popupMenuItems
|
||||||
).then((String val) {
|
).then((String val) {
|
||||||
if (val == "reload") {
|
if (val == "reload") {
|
||||||
_reLoad();
|
_quickLoad();
|
||||||
} else if (val == "logout") {
|
} else if (val == "logout") {
|
||||||
widget.homeAssistant.logout().then((_) {
|
widget.homeAssistant.logout().then((_) {
|
||||||
_reLoad();
|
_quickLoad();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user