New error class

This commit is contained in:
estevez-dev
2019-04-19 21:43:52 +03:00
parent 5a8a207f2e
commit 209ccd4f7f
5 changed files with 131 additions and 127 deletions

View File

@ -33,7 +33,7 @@ class AuthManager {
flutterWebviewPlugin.close(); flutterWebviewPlugin.close();
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({"errorCode": 61, "errorMessage": "Error getting temp token"}); completer.completeError(HAError("Error getting temp token"));
}); });
} }
}); });

View File

@ -63,7 +63,7 @@ class Connection {
} }
if ((_domain == null) || (_port == null) || if ((_domain == null) || (_port == null) ||
(_domain.isEmpty) || (_port.isEmpty)) { (_domain.isEmpty) || (_port.isEmpty)) {
completer.completeError({"errorCode": 5, "errorMessage": "Check connection settings"}); completer.completeError(HAError.checkConnectionSettings());
} }
if (_token == null) { if (_token == null) {
@ -87,8 +87,7 @@ class Connection {
if (forceReconnect || !isConnected) { if (forceReconnect || !isConnected) {
_connect().timeout(connectTimeout, onTimeout: () { _connect().timeout(connectTimeout, onTimeout: () {
_disconnect().then((_) { _disconnect().then((_) {
completer?.completeError( completer?.completeError(HAError("Connection timeout"));
{"errorCode": 1, "errorMessage": "Connection timeout"});
}); });
}).then((_) => completer?.complete()).catchError((e) { }).then((_) => completer?.complete()).catchError((e) {
completer?.completeError(e); completer?.completeError(e);
@ -127,12 +126,10 @@ class Connection {
if (!connecting.isCompleted) connecting.complete(); if (!connecting.isCompleted) connecting.complete();
} 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( _messageResolver["auth"]?.completeError(HAError("${data["message"]}", actions: [HAErrorAction.loginAgain()]));
{"errorCode": 62, "errorMessage": "${data["message"]}"});
_messageResolver.remove("auth"); _messageResolver.remove("auth");
logout().then((_) { logout().then((_) {
if (!connecting.isCompleted) connecting.completeError( if (!connecting.isCompleted) connecting.completeError(HAError("${data["message"]}", actions: [HAErrorAction.loginAgain()]));
{"errorCode": 62, "errorMessage": "${data["message"]}"});
}); });
} else { } else {
_handleMessage(data); _handleMessage(data);
@ -146,6 +143,8 @@ class Connection {
} }
} }
Future _disconnect() { Future _disconnect() {
Completer completer = Completer(); Completer completer = Completer();
if (!isConnected) { if (!isConnected) {
@ -173,7 +172,7 @@ class Connection {
_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({"errorMessage": "${data['error']["message"]}"}); _messageResolver["${data["id"]}"]?.completeError("${data['error']["message"]}");
} }
_messageResolver.remove("${data["id"]}"); _messageResolver.remove("${data["id"]}");
} else if (data["type"] == "event") { } else if (data["type"] == "event") {
@ -194,14 +193,14 @@ class Connection {
Logger.d("Socket disconnected."); Logger.d("Socket disconnected.");
if (!connectionCompleter.isCompleted) { if (!connectionCompleter.isCompleted) {
isConnected = false; isConnected = false;
connectionCompleter.completeError({"errorCode": 82, "errorMessage": "Disconnected"}); connectionCompleter.completeError(HAError("Disconnected", actions: [HAErrorAction.reconnect()]));
} else { } else {
_disconnect().then((_) { _disconnect().then((_) {
Timer(Duration(seconds: 5), () { Timer(Duration(seconds: 5), () {
Logger.d("Trying to reconnect..."); Logger.d("Trying to reconnect...");
_connect().catchError((e) { _connect().catchError((e) {
isConnected = false; isConnected = false;
eventBus.fire(ShowErrorEvent("Unable to connect to Home Assistant", 81)); eventBus.fire(ShowErrorEvent(HAError("Unable to connect to Home Assistant")));
}); });
}); });
}); });
@ -212,14 +211,14 @@ class Connection {
Logger.e("Socket stream Error: $e"); Logger.e("Socket stream Error: $e");
if (!connectionCompleter.isCompleted) { if (!connectionCompleter.isCompleted) {
isConnected = false; isConnected = false;
connectionCompleter.completeError({"errorCode": 81, "errorMessage": "Unable to connect to Home Assistant"}); connectionCompleter.completeError(HAError("Unable to connect to Home Assistant"));
} else { } else {
_disconnect().then((_) { _disconnect().then((_) {
Timer(Duration(seconds: 5), () { Timer(Duration(seconds: 5), () {
Logger.d("Trying to reconnect..."); Logger.d("Trying to reconnect...");
_connect().catchError((e) { _connect().catchError((e) {
isConnected = false; isConnected = false;
eventBus.fire(ShowErrorEvent("Unable to connect to Home Assistant", 81)); eventBus.fire(ShowErrorEvent(HAError("Unable to connect to Home Assistant")));
}); });
}); });
}); });
@ -254,7 +253,7 @@ class Connection {
}); });
}).catchError((e) => completer.completeError(e)); }).catchError((e) => completer.completeError(e));
} else { } else {
completer.completeError({"errorCode": 63, "errorMessage": "General login error"}); completer.completeError(HAError("General login error"));
} }
return completer.future; return completer.future;
} }
@ -286,7 +285,7 @@ class Connection {
}); });
}).catchError((e) { }).catchError((e) {
logout(); logout();
completer.completeError({"errorCode": 63, "errorMessage": "Authentication error: $e"}); completer.completeError(HAError("Authentication error: $e", actions: [HAErrorAction.loginAgain()]));
}); });
return completer.future; return completer.future;
} }
@ -309,7 +308,7 @@ class Connection {
String rawMessage = json.encode(dataObject); String rawMessage = json.encode(dataObject);
if (!isConnected) { if (!isConnected) {
_connect().timeout(connectTimeout, onTimeout: (){ _connect().timeout(connectTimeout, onTimeout: (){
_completer.completeError({"errorCode": 8, "errorMessage": "No connection to Home Assistant"}); _completer.completeError(HAError("No connection to Home Assistant", actions: [HAErrorAction.reconnect()]));
}).then((_) { }).then((_) {
Logger.d("[Sending] ==> $rawMessage"); Logger.d("[Sending] ==> $rawMessage");
_socket.sink.add(rawMessage); _socket.sink.add(rawMessage);

View File

@ -54,8 +54,12 @@ class HomeAssistant {
additionalData: {"event_type": "state_changed"}, additionalData: {"event_type": "state_changed"},
)); ));
Future.wait(futures).then((_) { Future.wait(futures).then((_) {
if (isMobileAppEnabled) {
_createUI(); _createUI();
_fetchCompleter.complete(); _fetchCompleter.complete();
} else {
_fetchCompleter.completeError(HAError("Mobile app component not found", actions: [HAErrorAction.tryAgain(), HAErrorAction(type: HAErrorActionType.URL ,title: "Help",url: "http://ha-client.homemade.systems/docs#mobile-app")]));
}
}).catchError((e) { }).catchError((e) {
_fetchCompleter.completeError(e); _fetchCompleter.completeError(e);
}); });
@ -75,7 +79,7 @@ class HomeAssistant {
await Connection().sendSocketMessage(type: "get_config").then((data) { await Connection().sendSocketMessage(type: "get_config").then((data) {
_instanceConfig = Map.from(data); _instanceConfig = Map.from(data);
}).catchError((e) { }).catchError((e) {
throw {"errorCode": 1, "errorMessage": "Error getting config: $e"}; throw HAError("Error getting config: ${e}");
}); });
} }
@ -83,13 +87,13 @@ class HomeAssistant {
await Connection().sendSocketMessage(type: "get_states").then( await Connection().sendSocketMessage(type: "get_states").then(
(data) => entities.parse(data) (data) => entities.parse(data)
).catchError((e) { ).catchError((e) {
throw {"errorCode": 1, "errorMessage": "Error getting states: $e"}; throw HAError("Error getting states: $e");
}); });
} }
Future _getLovelace() async { Future _getLovelace() async {
await Connection().sendSocketMessage(type: "lovelace/config").then((data) => _rawLovelaceData = data).catchError((e) { await Connection().sendSocketMessage(type: "lovelace/config").then((data) => _rawLovelaceData = data).catchError((e) {
throw {"errorCode": 1, "errorMessage": "Error getting lovelace config: $e"}; throw HAError("Error getting lovelace config: $e");
}); });
} }
@ -122,7 +126,7 @@ class HomeAssistant {
); );
}); });
}).catchError((e) { }).catchError((e) {
throw {"errorCode": 1, "errorMessage": "Error getting panels list: $e"}; throw HAError("Error getting panels list: $e");
}); });
} }

View File

@ -277,7 +277,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
if (_showErrorSubscription == null) { if (_showErrorSubscription == null) {
_showErrorSubscription = eventBus.on<ShowErrorEvent>().listen((event){ _showErrorSubscription = eventBus.on<ShowErrorEvent>().listen((event){
_showErrorBottomBar(message: event.text, errorCode: event.errorCode); _showErrorBottomBar(event.error);
}); });
} }
@ -326,17 +326,13 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
); );
} }
_setErrorState(e) { _setErrorState(HAError e) {
if (e["errorCode"] == null) { if (e == null) {
_showErrorBottomBar( _showErrorBottomBar(
message: "Unknown error", HAError("Unknown error")
errorCode: 13
); );
} else { } else {
_showErrorBottomBar( _showErrorBottomBar(e);
message: e != null ? e["errorMessage"] ?? "$e" : "Unknown error",
errorCode: e["errorCode"] != null ? e["errorCode"] : 99
);
} }
} }
@ -538,106 +534,68 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
} }
} }
void _showErrorBottomBar({Key key, @required String message, @required int errorCode}) { void _showErrorBottomBar(HAError error) {
TextStyle textStyle = TextStyle( TextStyle textStyle = TextStyle(
color: Colors.blue, color: Colors.blue,
fontSize: Sizes.nameFontSize fontSize: Sizes.nameFontSize
); );
_bottomBarColor = Colors.red.shade100; _bottomBarColor = Colors.red.shade100;
switch (errorCode) { List<Widget> actions = [];
case 9: error.actions.forEach((HAErrorAction action) {
case 11: switch (action.type) {
case 7: case HAErrorActionType.FULL_RELOAD: {
case 1: { actions.add(FlatButton(
_bottomBarAction = FlatButton( child: Text("${action.title}", style: textStyle),
child: Text("Retry", style: textStyle), onPressed: () {
_fullLoad();
},
));
break;
}
case HAErrorActionType.QUICK_RELOAD: {
actions.add(FlatButton(
child: Text("${action.title}", style: textStyle),
onPressed: () { onPressed: () {
//_scaffoldKey?.currentState?.hideCurrentSnackBar();
_quickLoad(); _quickLoad();
}, },
); ));
break; break;
} }
case 5: { case HAErrorActionType.URL: {
message = "Check connection settings"; actions.add(FlatButton(
_bottomBarAction = FlatButton( child: Text("${action.title}", style: textStyle),
child: Text("Open", style: textStyle), onPressed: () {
HAUtils.launchURLInCustomTab(context, "${action.url}");
},
));
break;
}
case HAErrorActionType.OPEN_CONNECTION_SETTINGS: {
actions.add(FlatButton(
child: Text("${action.title}", style: textStyle),
onPressed: () { onPressed: () {
//_scaffoldKey?.currentState?.hideCurrentSnackBar();
Navigator.pushNamed(context, '/connection-settings'); Navigator.pushNamed(context, '/connection-settings');
}, },
); ));
break; break;
} }
case 60: {
_bottomBarAction = FlatButton(
child: Text("Login", style: textStyle),
onPressed: () {
_fullLoad();
},
);
break;
} }
});
case 63: if (actions.isNotEmpty) {
case 61: { _bottomBarAction = Row(
_bottomBarAction = FlatButton( mainAxisSize: MainAxisSize.min,
child: Text("Try again", style: textStyle), children: actions,
onPressed: () { mainAxisAlignment: MainAxisAlignment.end,
_fullLoad();
},
); );
break; } else {
} _bottomBarAction = Container(height: 0.0, width: 0.0,);
case 62: {
_bottomBarAction = FlatButton(
child: Text("Login again", style: textStyle),
onPressed: () {
_fullLoad();
},
);
break;
}
case 10: {
_bottomBarAction = FlatButton(
child: Text("Reload", style: textStyle),
onPressed: () {
//_scaffoldKey?.currentState?.hideCurrentSnackBar();
_fullLoad();
},
);
break;
}
case 82:
case 81:
case 8: {
_bottomBarAction = FlatButton(
child: Text("Reconnect", style: textStyle),
onPressed: () {
_fullLoad();
},
);
break;
}
default: {
_bottomBarAction = FlatButton(
child: Text("Try again", style: textStyle),
onPressed: () {
_fullLoad();
},
);
break;
}
} }
setState(() { setState(() {
_bottomBarProgress = false; _bottomBarProgress = false;
_bottomBarText = "$message"; _bottomBarText = "${error.message}";
_showBottomBar = true; _showBottomBar = true;
}); });
} }

View File

@ -45,6 +45,50 @@ class Logger {
} }
class HAError {
String message;
final List<HAErrorAction> actions;
HAError(this.message, {this.actions: const [HAErrorAction.tryAgain()]});
HAError.unableToConnect({this.actions = const [HAErrorAction.tryAgain()]}) {
this.message = "Unable to connect to Home Assistant";
}
HAError.disconnected({this.actions = const [HAErrorAction.reconnect()]}) {
this.message = "Disconnected";
}
HAError.checkConnectionSettings({this.actions = const [HAErrorAction.reload(), HAErrorAction(title: "Settings", type: HAErrorActionType.OPEN_CONNECTION_SETTINGS)]}) {
this.message = "Check connection settings";
}
}
class HAErrorAction {
final String title;
final int type;
final String url;
const HAErrorAction({@required this.title, this.type: HAErrorActionType.FULL_RELOAD, this.url});
const HAErrorAction.tryAgain({this.title = "Try again", this.type = HAErrorActionType.FULL_RELOAD, this.url});
const HAErrorAction.reconnect({this.title = "Reconnect", this.type = HAErrorActionType.FULL_RELOAD, this.url});
const HAErrorAction.reload({this.title = "Reload", this.type = HAErrorActionType.FULL_RELOAD, this.url});
const HAErrorAction.loginAgain({this.title = "Login again", this.type = HAErrorActionType.FULL_RELOAD, this.url});
}
class HAErrorActionType {
static const FULL_RELOAD = 0;
static const QUICK_RELOAD = 1;
static const LOGOUT = 2;
static const URL = 3;
static const OPEN_CONNECTION_SETTINGS = 4;
}
class HAUtils { class HAUtils {
static void launchURL(String url) async { static void launchURL(String url) async {
if (await urlLauncher.canLaunch(url)) { if (await urlLauncher.canLaunch(url)) {
@ -136,8 +180,7 @@ class ShowEntityPageEvent {
} }
class ShowErrorEvent { class ShowErrorEvent {
String text; final HAError error;
int errorCode;
ShowErrorEvent(this.text, this.errorCode); ShowErrorEvent(this.error);
} }