[#5, #9] Instance info in app drawer. Connection settings

This commit is contained in:
estevez 2018-09-17 00:28:19 +03:00
parent c2724466d0
commit b1d426bafd
5 changed files with 71 additions and 35 deletions

BIN
images/hassio-192x192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -14,17 +14,21 @@ class HassioDataModel {
int _statesMessageId = 0; int _statesMessageId = 0;
int _servicesMessageId = 0; int _servicesMessageId = 0;
int _subscriptionMessageId = 0; int _subscriptionMessageId = 0;
int _configMessageId = 0;
Map _entitiesData = {}; Map _entitiesData = {};
Map _servicesData = {}; Map _servicesData = {};
Map _uiStructure = {}; Map _uiStructure = {};
Map _instanceConfig = {};
Completer _fetchCompleter; Completer _fetchCompleter;
Completer _statesCompleter; Completer _statesCompleter;
Completer _servicesCompleter; Completer _servicesCompleter;
Completer _configCompleter;
Timer _fetchingTimer; Timer _fetchingTimer;
Map get entities => _entitiesData; Map get entities => _entitiesData;
Map get services => _servicesData; Map get services => _servicesData;
Map get uiStructure => _uiStructure; Map get uiStructure => _uiStructure;
Map get instanceConfig => _instanceConfig;
HassioDataModel(String url, String password) { HassioDataModel(String url, String password) {
_hassioAPIEndpoint = url; _hassioAPIEndpoint = url;
@ -75,20 +79,30 @@ class HassioDataModel {
} }
_getData() { _getData() {
_getStates().then((result) { _getConfig().then((result) {
_getServices().then((result) { _getStates().then((result) {
_fetchingTimer.cancel(); _getServices().then((result) {
_fetchCompleter.complete(); _finishFetching(null);
}).catchError((e) {
_finishFetching(e);
});
}).catchError((e) { }).catchError((e) {
_fetchingTimer.cancel(); _finishFetching(e);
_fetchCompleter.completeError(e);
}); });
}).catchError((e) { }).catchError((e) {
_fetchingTimer.cancel(); _finishFetching(e);
_fetchCompleter.completeError(e);
}); });
} }
_finishFetching(error) {
_fetchingTimer.cancel();
if (error != null) {
_fetchCompleter.completeError(error);
} else {
_fetchCompleter.complete();
}
}
_handleMessage(Completer connectionCompleter, String message) { _handleMessage(Completer connectionCompleter, String message) {
var data = json.decode(message); var data = json.decode(message);
debugPrint("[Received]Message type: ${data['type']}"); debugPrint("[Received]Message type: ${data['type']}");
@ -101,7 +115,10 @@ class HassioDataModel {
connectionCompleter.completeError({message: "Auth error: ${data["message"]}"}); connectionCompleter.completeError({message: "Auth error: ${data["message"]}"});
} else if (data["type"] == "result") { } else if (data["type"] == "result") {
if (data["success"] == true) { if (data["success"] == true) {
if (data["id"] == _statesMessageId) { if (data["id"] == _configMessageId) {
_parseConfig(data["result"]);
_configCompleter.complete();
} else if (data["id"] == _statesMessageId) {
_parseEntities(data["result"]); _parseEntities(data["result"]);
_statesCompleter.complete(); _statesCompleter.complete();
} else if (data["id"] == _servicesMessageId) { } else if (data["id"] == _servicesMessageId) {
@ -142,11 +159,20 @@ class HassioDataModel {
_sendMessageRaw('{"id": $_subscriptionMessageId, "type": "subscribe_events", "event_type": "state_changed"}'); _sendMessageRaw('{"id": $_subscriptionMessageId, "type": "subscribe_events", "event_type": "state_changed"}');
} }
Future _getConfig() {
_configCompleter = new Completer();
_incrementMessageId();
_configMessageId = _currentMssageId;
_sendMessageRaw('{"id": $_configMessageId, "type": "get_config"}');
return _configCompleter.future;
}
Future _getStates() { Future _getStates() {
_statesCompleter = new Completer(); _statesCompleter = new Completer();
_incrementMessageId(); _incrementMessageId();
_statesMessageId = _currentMssageId; _statesMessageId = _currentMssageId;
_sendMessageRaw('{"id": $_currentMssageId, "type": "get_states"}'); _sendMessageRaw('{"id": $_statesMessageId, "type": "get_states"}');
return _statesCompleter.future; return _statesCompleter.future;
} }
@ -155,7 +181,7 @@ class HassioDataModel {
_servicesCompleter = new Completer(); _servicesCompleter = new Completer();
_incrementMessageId(); _incrementMessageId();
_servicesMessageId = _currentMssageId; _servicesMessageId = _currentMssageId;
_sendMessageRaw('{"id": $_currentMssageId, "type": "get_services"}'); _sendMessageRaw('{"id": $_servicesMessageId, "type": "get_services"}');
return _servicesCompleter.future; return _servicesCompleter.future;
} }
@ -171,8 +197,16 @@ class HassioDataModel {
void _handleEntityStateChange(Map eventData) { void _handleEntityStateChange(Map eventData) {
String entityId = eventData["entity_id"]; String entityId = eventData["entity_id"];
_entitiesData[entityId].addAll(eventData["new_state"]); if (_entitiesData[entityId] != null) {
eventBus.fire(new StateChangedEvent(eventData["entity_id"])); _entitiesData[entityId].addAll(eventData["new_state"]);
eventBus.fire(new StateChangedEvent(eventData["entity_id"]));
} else {
debugPrint("Unknown enity $entityId");
}
}
void _parseConfig(Map data) {
_instanceConfig = Map.from(data);
} }
void _parseServices(Map data) { void _parseServices(Map data) {

View File

@ -29,7 +29,7 @@ class HassClientApp extends StatelessWidget {
initialRoute: "/", initialRoute: "/",
routes: { routes: {
"/": (context) => MainPage(title: 'Hass Client'), "/": (context) => MainPage(title: 'Hass Client'),
"/settings": (context) => SettingsPage(title: "Settings") "/connection-settings": (context) => ConnectionSettingsPage(title: "Connection Settings")
}, },
); );
} }
@ -48,8 +48,10 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
HassioDataModel _dataModel; HassioDataModel _dataModel;
Map _entitiesData; Map _entitiesData;
Map _uiStructure; Map _uiStructure;
Map _instanceConfig;
int _uiViewsCount = 0; int _uiViewsCount = 0;
String _dataModelErrorMessage = ""; String _dataModelErrorMessage = "";
String _instanceHost;
bool loading = true; bool loading = true;
Map _stateIconColors = { Map _stateIconColors = {
"on": Colors.amber, "on": Colors.amber,
@ -76,10 +78,13 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
_init() async { _init() async {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
String domain = prefs.getString('hassio-domain');
String port = prefs.getString('hassio-port');
_instanceHost = domain+":"+port;
String _hassioAPIEndpoint = prefs.getString('hassio-protocol')+"://" + String _hassioAPIEndpoint = prefs.getString('hassio-protocol')+"://" +
prefs.getString('hassio-domain') + domain +
":" + ":" +
prefs.getString('hassio-port') + port +
"/api/websocket"; "/api/websocket";
String _hassioPassword = prefs.getString('hassio-password'); String _hassioPassword = prefs.getString('hassio-password');
_dataModel = HassioDataModel(_hassioAPIEndpoint, _hassioPassword); _dataModel = HassioDataModel(_hassioAPIEndpoint, _hassioPassword);
@ -100,6 +105,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
if (_dataModel != null) { if (_dataModel != null) {
await _dataModel.fetch().then((result) { await _dataModel.fetch().then((result) {
setState(() { setState(() {
_instanceConfig = _dataModel.instanceConfig;
_entitiesData = _dataModel.entities; _entitiesData = _dataModel.entities;
_uiStructure = _dataModel.uiStructure; _uiStructure = _dataModel.uiStructure;
_uiViewsCount = _uiStructure.length; _uiViewsCount = _uiStructure.length;
@ -249,15 +255,15 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
Widget _buildTitle() { Widget _buildTitle() {
Row titleRow = Row( Row titleRow = Row(
children: <Widget>[Text(widget.title)], children: [Text(_instanceConfig != null ? _instanceConfig["location_name"] : "...")],
); );
if (loading) { if (loading) {
titleRow.children.add(Padding( titleRow.children.add(Padding(
child: JumpingDotsProgressIndicator( child: JumpingDotsProgressIndicator(
fontSize: 30.0, fontSize: 26.0,
color: Colors.white, color: Colors.white,
), ),
padding: const EdgeInsets.fromLTRB(5.0, 0.0, 0.0, 40.0), padding: const EdgeInsets.fromLTRB(5.0, 0.0, 0.0, 30.0),
)); ));
} }
return titleRow; return titleRow;
@ -268,18 +274,15 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
child: ListView( child: ListView(
children: <Widget>[ children: <Widget>[
new UserAccountsDrawerHeader( new UserAccountsDrawerHeader(
accountName: Text("Edwin Home"), accountName: Text(_instanceConfig != null ? _instanceConfig["location_name"] : "Unknown"),
accountEmail: Text("edwin-home.duckdns.org"), accountEmail: Text(_instanceHost ?? "Not configured"),
currentAccountPicture: new CircleAvatar( currentAccountPicture: new Image.asset('images/hassio-192x192.png'),
backgroundImage: new NetworkImage(
"https://edwin-home.duckdns.org:8123/static/icons/favicon-192x192.png"),
),
), ),
new ListTile( new ListTile(
leading: Icon(Icons.settings), leading: Icon(Icons.settings),
title: Text("Settings"), title: Text("Connection settings"),
onTap: () { onTap: () {
Navigator.pushNamed(context, '/settings'); Navigator.pushNamed(context, '/connection-settings');
}, },
), ),
new AboutListTile( new AboutListTile(
@ -309,7 +312,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
Padding( Padding(
padding: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 10.0), padding: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 10.0),
child: Text( child: Text(
_dataModelErrorMessage != null ? "Well... no.\n\nThere was an error: $_dataModelErrorMessage\n\nCheck your internet connection or something" : "Loading... or not...\n\nJust wait 10 seconds", _dataModelErrorMessage != null ? "Well... no.\n\nThere was an error: $_dataModelErrorMessage\n\nCheck your internet connection or restart the app" : "Loading... I hope...",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle(fontSize: 16.0), style: TextStyle(fontSize: 16.0),
), ),

View File

@ -1,15 +1,15 @@
part of 'main.dart'; part of 'main.dart';
class SettingsPage extends StatefulWidget { class ConnectionSettingsPage extends StatefulWidget {
SettingsPage({Key key, this.title}) : super(key: key); ConnectionSettingsPage({Key key, this.title}) : super(key: key);
final String title; final String title;
@override @override
_SettingsPageState createState() => new _SettingsPageState(); _ConnectionSettingsPageState createState() => new _ConnectionSettingsPageState();
} }
class _SettingsPageState extends State<SettingsPage> { class _ConnectionSettingsPageState extends State<ConnectionSettingsPage> {
String _hassioDomain = ""; String _hassioDomain = "";
String _hassioPort = ""; String _hassioPort = "";
String _hassioPassword = ""; String _hassioPassword = "";

View File

@ -40,9 +40,8 @@ flutter:
uses-material-design: true uses-material-design: true
# To add assets to your application, add an assets section, like this: # To add assets to your application, add an assets section, like this:
# assets: assets:
# - images/a_dot_burr.jpeg - images/hassio-192x192.png
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see # An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.io/assets-and-images/#resolution-aware. # https://flutter.io/assets-and-images/#resolution-aware.