parent
c2724466d0
commit
b1d426bafd
BIN
images/hassio-192x192.png
Normal file
BIN
images/hassio-192x192.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
@ -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,18 +79,28 @@ class HassioDataModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_getData() {
|
_getData() {
|
||||||
|
_getConfig().then((result) {
|
||||||
_getStates().then((result) {
|
_getStates().then((result) {
|
||||||
_getServices().then((result) {
|
_getServices().then((result) {
|
||||||
|
_finishFetching(null);
|
||||||
|
}).catchError((e) {
|
||||||
|
_finishFetching(e);
|
||||||
|
});
|
||||||
|
}).catchError((e) {
|
||||||
|
_finishFetching(e);
|
||||||
|
});
|
||||||
|
}).catchError((e) {
|
||||||
|
_finishFetching(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_finishFetching(error) {
|
||||||
_fetchingTimer.cancel();
|
_fetchingTimer.cancel();
|
||||||
|
if (error != null) {
|
||||||
|
_fetchCompleter.completeError(error);
|
||||||
|
} else {
|
||||||
_fetchCompleter.complete();
|
_fetchCompleter.complete();
|
||||||
}).catchError((e) {
|
}
|
||||||
_fetchingTimer.cancel();
|
|
||||||
_fetchCompleter.completeError(e);
|
|
||||||
});
|
|
||||||
}).catchError((e) {
|
|
||||||
_fetchingTimer.cancel();
|
|
||||||
_fetchCompleter.completeError(e);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleMessage(Completer connectionCompleter, String message) {
|
_handleMessage(Completer connectionCompleter, String message) {
|
||||||
@ -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"];
|
||||||
|
if (_entitiesData[entityId] != null) {
|
||||||
_entitiesData[entityId].addAll(eventData["new_state"]);
|
_entitiesData[entityId].addAll(eventData["new_state"]);
|
||||||
eventBus.fire(new StateChangedEvent(eventData["entity_id"]));
|
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) {
|
||||||
|
@ -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),
|
||||||
),
|
),
|
||||||
|
@ -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 = "";
|
||||||
|
@ -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.
|
||||||
|
Reference in New Issue
Block a user