Panels error handling

This commit is contained in:
Yegor Vialov 2020-05-01 13:47:41 +00:00
parent ba343fbd98
commit 8a180c4c0e
8 changed files with 57 additions and 53 deletions

View File

@ -79,7 +79,7 @@ class HomeAssistant {
_fetchCompleter.complete(); _fetchCompleter.complete();
if (!uiOnly) MobileAppIntegrationManager.checkAppRegistration(); if (!uiOnly) MobileAppIntegrationManager.checkAppRegistration();
} else { } else {
_fetchCompleter.completeError(HAError("Mobile app component not found", actions: [HAErrorAction.tryAgain(), HAErrorAction(type: HAErrorActionType.URL ,title: "Help",url: "http://ha-client.app/docs#mobile-app-integration")])); _fetchCompleter.completeError(HACException("Mobile app component not found", actions: [HAErrorAction.tryAgain(), HAErrorAction(type: HAErrorActionType.URL ,title: "Help",url: "http://ha-client.app/docs#mobile-app-integration")]));
} }
}).catchError((e) { }).catchError((e) {
_fetchCompleter.completeError(e); _fetchCompleter.completeError(e);
@ -144,11 +144,11 @@ class HomeAssistant {
var data = json.decode(sharedPrefs.getString('cached_config')); var data = json.decode(sharedPrefs.getString('cached_config'));
_parseConfig(data); _parseConfig(data);
} catch (e) { } catch (e) {
throw HAError("Error getting config: $e"); throw HACException("Error getting config: $e");
} }
} else { } else {
await ConnectionManager().sendSocketMessage(type: "get_config").then((data) => _parseConfig(data)).catchError((e) { await ConnectionManager().sendSocketMessage(type: "get_config").then((data) => _parseConfig(data)).catchError((e) {
throw HAError("Error getting config: $e"); throw HACException("Error getting config: $e");
}); });
} }
} }
@ -164,13 +164,13 @@ class HomeAssistant {
var data = json.decode(sharedPrefs.getString('cached_states')); var data = json.decode(sharedPrefs.getString('cached_states'));
_parseStates(data); _parseStates(data);
} catch (e) { } catch (e) {
throw HAError("Error getting states: $e"); throw HACException("Error getting states: $e");
} }
} else { } else {
await ConnectionManager().sendSocketMessage(type: "get_states").then( await ConnectionManager().sendSocketMessage(type: "get_states").then(
(data) => _parseStates(data) (data) => _parseStates(data)
).catchError((e) { ).catchError((e) {
throw HAError("Error getting states: $e"); throw HACException("Error getting states: $e");
}); });
} }
} }
@ -209,7 +209,7 @@ class HomeAssistant {
_rawLovelaceData = null; _rawLovelaceData = null;
completer.complete(); completer.complete();
} else { } else {
completer.completeError(HAError("Error getting lovelace config: $e")); completer.completeError(HACException("Error getting lovelace config: $e"));
} }
}); });
return completer.future; return completer.future;
@ -249,14 +249,17 @@ class HomeAssistant {
Future _getPanels(SharedPreferences sharedPrefs) async { Future _getPanels(SharedPreferences sharedPrefs) async {
if (sharedPrefs != null) { if (sharedPrefs != null) {
try { try {
var data = json.decode(sharedPrefs.getString('cached_panels')); var data = json.decode(sharedPrefs.getString('cached_panels') ?? '{}');
_parsePanels(data); _parsePanels(data);
} catch (e) { } catch (e, stacktrace) {
throw HAError("Error getting panels list: $e"); Crashlytics.instance.recordError(e, stacktrace);
panels.clear();
} }
} else { } else {
await ConnectionManager().sendSocketMessage(type: "get_panels").then((data) => _parsePanels(data)).catchError((e) { await ConnectionManager().sendSocketMessage(type: "get_panels").then((data) => _parsePanels(data)).catchError((e, stacktrace) {
throw HAError("Error getting panels list: $e"); panels.clear();
Crashlytics.instance.recordError(e, stacktrace);
throw HACException('Can\'t get panles: $e');
}); });
} }
} }

View File

@ -33,7 +33,7 @@ class AuthManager {
}).catchError((e) { }).catchError((e) {
Logger.e("Error getting temp token: ${e.toString()}"); Logger.e("Error getting temp token: ${e.toString()}");
eventBus.fire(StartAuthEvent(oauthUrl, false)); eventBus.fire(StartAuthEvent(oauthUrl, false));
completer.completeError(HAError("Error getting temp token")); completer.completeError(HACException("Error getting temp token"));
}).whenComplete(() => flutterWebviewPlugin.close()); }).whenComplete(() => flutterWebviewPlugin.close());
} }
}); });

View File

@ -53,7 +53,7 @@ class ConnectionManager {
Logger.d('$_domain$_port'); Logger.d('$_domain$_port');
if ((_domain == null) || (_port == null) || if ((_domain == null) || (_port == null) ||
(_domain.isEmpty) || (_port.isEmpty)) { (_domain.isEmpty) || (_port.isEmpty)) {
completer.completeError(HAError.checkConnectionSettings()); completer.completeError(HACException.checkConnectionSettings());
stopInit = true; stopInit = true;
} else { } else {
final storage = new FlutterSecureStorage(); final storage = new FlutterSecureStorage();
@ -66,7 +66,7 @@ class ConnectionManager {
'https://ha-client.app/service/auth_callback.html')}"; 'https://ha-client.app/service/auth_callback.html')}";
settingsLoaded = true; settingsLoaded = true;
} catch (e) { } catch (e) {
completer.completeError(HAError("Error reading login details", actions: [HAErrorAction.tryAgain(type: HAErrorActionType.FULL_RELOAD), HAErrorAction.loginAgain()])); completer.completeError(HACException("Error reading login details", actions: [HAErrorAction.tryAgain(type: HAErrorActionType.FULL_RELOAD), HAErrorAction.loginAgain()]));
Logger.e("Cannt read secure storage. Need to relogin."); Logger.e("Cannt read secure storage. Need to relogin.");
stopInit = true; stopInit = true;
} }
@ -74,7 +74,7 @@ class ConnectionManager {
} else { } else {
if ((_domain == null) || (_port == null) || if ((_domain == null) || (_port == null) ||
(_domain.isEmpty) || (_port.isEmpty)) { (_domain.isEmpty) || (_port.isEmpty)) {
completer.completeError(HAError.checkConnectionSettings()); completer.completeError(HACException.checkConnectionSettings());
stopInit = true; stopInit = true;
} }
} }
@ -107,13 +107,13 @@ class ConnectionManager {
_disconnect().then((_) { _disconnect().then((_) {
if (e is TimeoutException) { if (e is TimeoutException) {
if (connecting != null && !connecting.isCompleted) { if (connecting != null && !connecting.isCompleted) {
connecting.completeError(HAError("Connection timeout")); connecting.completeError(HACException("Connection timeout"));
} }
completer?.completeError(HAError("Connection timeout")); completer?.completeError(HACException("Connection timeout"));
} else if (e is HAError) { } else if (e is HACException) {
completer?.completeError(e); completer?.completeError(e);
} else { } else {
completer?.completeError(HAError("${e.toString()}")); completer?.completeError(HACException("${e.toString()}"));
} }
}); });
}); });
@ -167,9 +167,9 @@ class ConnectionManager {
}); });
} else if (data["type"] == "auth_invalid") { } else if (data["type"] == "auth_invalid") {
Logger.d("[Received] <== ${data.toString()}"); Logger.d("[Received] <== ${data.toString()}");
_messageResolver["auth"]?.completeError(HAError("${data["message"]}", actions: [HAErrorAction.loginAgain()])); _messageResolver["auth"]?.completeError(HACException("${data["message"]}", actions: [HAErrorAction.loginAgain()]));
_messageResolver.remove("auth"); _messageResolver.remove("auth");
if (!connecting.isCompleted) connecting.completeError(HAError("${data["message"]}", actions: [HAErrorAction.tryAgain(title: "Retry"), HAErrorAction.loginAgain(title: "Relogin")])); if (!connecting.isCompleted) connecting.completeError(HACException("${data["message"]}", actions: [HAErrorAction.tryAgain(title: "Retry"), HAErrorAction.loginAgain(title: "Relogin")]));
} else { } else {
_handleMessage(data); _handleMessage(data);
} }
@ -179,7 +179,7 @@ class ConnectionManager {
onError: (e) => _handleSocketError(e, connecting) onError: (e) => _handleSocketError(e, connecting)
); );
} catch(exeption) { } catch(exeption) {
connecting.completeError(HAError("${exeption.toString()}")); connecting.completeError(HACException("${exeption.toString()}"));
} }
}); });
return connecting.future; return connecting.future;
@ -213,7 +213,7 @@ class ConnectionManager {
_messageResolver["${data["id"]}"]?.complete(data["result"]); _messageResolver["${data["id"]}"]?.complete(data["result"]);
} else if (data["id"] != null) { } else if (data["id"] != null) {
Logger.e("[Received] <== Error received on request id ${data['id']}: ${data['error']}"); Logger.e("[Received] <== Error received on request id ${data['id']}: ${data['error']}");
_messageResolver["${data["id"]}"]?.completeError("${data["error"]["code"]}"); _messageResolver["${data["id"]}"]?.completeError("${data["error"]["code"]}: ${data["error"]["message"]}");
} }
_messageResolver.remove("${data["id"]}"); _messageResolver.remove("${data["id"]}");
} else if (data["type"] == "event") { } else if (data["type"] == "event") {
@ -236,9 +236,9 @@ class ConnectionManager {
_disconnect().then((_) { _disconnect().then((_) {
if (!connectionCompleter.isCompleted) { if (!connectionCompleter.isCompleted) {
isConnected = false; isConnected = false;
connectionCompleter.completeError(HAError("Disconnected", actions: [HAErrorAction.reconnect()])); connectionCompleter.completeError(HACException("Disconnected", actions: [HAErrorAction.reconnect()]));
} }
eventBus.fire(ShowErrorEvent(HAError("Unable to connect to Home Assistant"))); eventBus.fire(ShowErrorEvent(HACException("Unable to connect to Home Assistant")));
}); });
} }
@ -247,9 +247,9 @@ class ConnectionManager {
_disconnect().then((_) { _disconnect().then((_) {
if (!connectionCompleter.isCompleted) { if (!connectionCompleter.isCompleted) {
isConnected = false; isConnected = false;
connectionCompleter.completeError(HAError("Disconnected", actions: [HAErrorAction.reconnect()])); connectionCompleter.completeError(HACException("Disconnected", actions: [HAErrorAction.reconnect()]));
} }
eventBus.fire(ShowErrorEvent(HAError("Unable to connect to Home Assistant"))); eventBus.fire(ShowErrorEvent(HACException("Unable to connect to Home Assistant")));
}); });
} }
@ -282,7 +282,7 @@ class ConnectionManager {
}); });
}).catchError((e) => completer.completeError(e)); }).catchError((e) => completer.completeError(e));
} else { } else {
completer.completeError(HAError("General login error")); completer.completeError(HACException("General login error"));
} }
return completer.future; return completer.future;
} }
@ -317,7 +317,7 @@ class ConnectionManager {
throw e; throw e;
}); });
}).catchError((e) { }).catchError((e) {
completer.completeError(HAError("Authentication error: $e", actions: [HAErrorAction.reload(title: "Retry"), HAErrorAction.loginAgain(title: "Relogin")])); completer.completeError(HACException("Authentication error: $e", actions: [HAErrorAction.reload(title: "Retry"), HAErrorAction.loginAgain(title: "Relogin")]));
}); });
return completer.future; return completer.future;
} }
@ -344,7 +344,7 @@ class ConnectionManager {
_socket.sink.add(rawMessage); _socket.sink.add(rawMessage);
}).catchError((e) { }).catchError((e) {
if (!_completer.isCompleted) { if (!_completer.isCompleted) {
_completer.completeError(HAError("No connection to Home Assistant", actions: [HAErrorAction.reconnect()])); _completer.completeError(HACException("No connection to Home Assistant", actions: [HAErrorAction.reconnect()]));
} }
}); });
} else { } else {
@ -373,12 +373,12 @@ class ConnectionManager {
sendHTTPPost( sendHTTPPost(
endPoint: "/api/services/$domain/$service", endPoint: "/api/services/$domain/$service",
data: json.encode(serviceData) data: json.encode(serviceData)
).then((data) => completer.complete(data)).catchError((e) => completer.completeError(HAError(e.toString()))); ).then((data) => completer.complete(data)).catchError((e) => completer.completeError(HACException(e.toString())));
//return sendSocketMessage(type: "call_service", additionalData: {"domain": domain, "service": service, "service_data": serviceData}); //return sendSocketMessage(type: "call_service", additionalData: {"domain": domain, "service": service, "service_data": serviceData});
else else
sendHTTPPost( sendHTTPPost(
endPoint: "/api/services/$domain/$service" endPoint: "/api/services/$domain/$service"
).then((data) => completer.complete(data)).catchError((e) => completer.completeError(HAError(e.toString()))); ).then((data) => completer.complete(data)).catchError((e) => completer.completeError(HACException(e.toString())));
//return sendSocketMessage(type: "call_service", additionalData: {"domain": domain, "service": service}); //return sendSocketMessage(type: "call_service", additionalData: {"domain": domain, "service": service});
return completer.future; return completer.future;
} }

View File

@ -131,10 +131,10 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
}); });
HomeAssistant().saveCache(); HomeAssistant().saveCache();
}).catchError((e) { }).catchError((e) {
if (e is HAError) { if (e is HACException) {
_setErrorState(e); _setErrorState(e);
} else { } else {
_setErrorState(HAError(e.toString())); _setErrorState(HACException(e.toString()));
} }
}); });
eventBus.fire(RefreshDataFinishedEvent()); eventBus.fire(RefreshDataFinishedEvent());
@ -254,10 +254,10 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
Navigator.of(context).pushNamed("/auth", arguments: {"url": ConnectionManager().oauthUrl}); Navigator.of(context).pushNamed("/auth", arguments: {"url": ConnectionManager().oauthUrl});
} }
_setErrorState(HAError e) { _setErrorState(HACException e) {
if (e == null) { if (e == null) {
_bottomInfoBarController.showErrorBottomBar( _bottomInfoBarController.showErrorBottomBar(
HAError("Unknown error") HACException("Unknown error")
); );
} else { } else {
_bottomInfoBarController.showErrorBottomBar(e); _bottomInfoBarController.showErrorBottomBar(e);

View File

@ -40,12 +40,12 @@ class BottomInfoBarController {
} }
} }
void showErrorBottomBar(HAError error) { void showErrorBottomBar(HACException error) {
actions.clear(); actions.clear();
actions.addAll(error.actions); actions.addAll(error.actions);
bottomBarErrorColor = true; bottomBarErrorColor = true;
bottomBarProgress = false; bottomBarProgress = false;
bottomBarText = "${error.message}"; bottomBarText = "${error.cause}";
if (show == null) { if (show == null) {
initialState = true; initialState = true;
} else { } else {

View File

@ -24,7 +24,7 @@ class Panel {
icon = Panel.iconsByComponent[componentName]; icon = Panel.iconsByComponent[componentName];
} }
isHidden = (componentName == 'kiosk' || componentName == 'states' || componentName == 'profile' || componentName == 'developer-tools'); isHidden = (componentName == 'kiosk' || componentName == 'states' || componentName == 'profile' || componentName == 'developer-tools');
isWebView = (componentName != 'config' && componentName != 'lovelace' && !componentName.startsWith('haclient')); isWebView = (componentName != 'lovelace' && !componentName.startsWith('haclient'));
} }
void handleOpen(BuildContext context) { void handleOpen(BuildContext context) {
@ -68,10 +68,6 @@ class Panel {
Widget getWidget() { Widget getWidget() {
switch (componentName) { switch (componentName) {
case "config": {
return ConfigPanelWidget();
}
default: { default: {
return Text("Unsupported panel component: $componentName"); return Text("Unsupported panel component: $componentName");
} }

View File

@ -90,7 +90,7 @@ class ShowPageEvent {
} }
class ShowErrorEvent { class ShowErrorEvent {
final HAError error; final HACException error;
ShowErrorEvent(this.error); ShowErrorEvent(this.error);
} }

View File

@ -1,21 +1,26 @@
part of '../main.dart'; part of '../main.dart';
class HAError { class HACException implements Exception {
String message; String cause;
final List<HAErrorAction> actions; final List<HAErrorAction> actions;
HAError(this.message, {this.actions: const [HAErrorAction.tryAgain()]}); HACException(this.cause, {this.actions: const [HAErrorAction.tryAgain()]});
HAError.unableToConnect({this.actions = const [HAErrorAction.tryAgain()]}) { HACException.unableToConnect({this.actions = const [HAErrorAction.tryAgain()]}) {
this.message = "Unable to connect to Home Assistant"; this.cause = "Unable to connect to Home Assistant";
} }
HAError.disconnected({this.actions = const [HAErrorAction.reconnect()]}) { HACException.disconnected({this.actions = const [HAErrorAction.reconnect()]}) {
this.message = "Disconnected"; this.cause = "Disconnected";
} }
HAError.checkConnectionSettings({this.actions = const [HAErrorAction.reload(), HAErrorAction(title: "Settings", type: HAErrorActionType.OPEN_CONNECTION_SETTINGS)]}) { HACException.checkConnectionSettings({this.actions = const [HAErrorAction.reload(), HAErrorAction(title: "Settings", type: HAErrorActionType.OPEN_CONNECTION_SETTINGS)]}) {
this.message = "Check connection settings"; this.cause = "Check connection settings";
}
@override
String toString() {
return 'HACException: $cause';
} }
} }