diff --git a/lib/badge_class.dart b/lib/badge_class.dart new file mode 100644 index 0000000..b62fc65 --- /dev/null +++ b/lib/badge_class.dart @@ -0,0 +1,9 @@ +part of 'main.dart'; + +class Badge { + String _entityId; + + Badge(String groupId) { + _entityId = groupId; + } +} \ No newline at end of file diff --git a/lib/card_class.dart b/lib/card_class.dart new file mode 100644 index 0000000..59731db --- /dev/null +++ b/lib/card_class.dart @@ -0,0 +1,25 @@ +part of 'main.dart'; + +class HACard { + String _entityId; + List _entities; + String _friendlyName; + + List get entities => _entities; + String get friendlyName => _friendlyName; + + HACard(String groupId, String friendlyName) { + _entityId = groupId; + _entities = []; + _friendlyName = friendlyName; + } + + void addEntity(String entityId) { + _entities.add(entityId); + } + + void addEntities(List entities) { + _entities.addAll(entities); + } + +} \ No newline at end of file diff --git a/lib/entity_collection.class.dart b/lib/entity_collection.class.dart index f776848..e587eb4 100644 --- a/lib/entity_collection.class.dart +++ b/lib/entity_collection.class.dart @@ -3,30 +3,25 @@ part of 'main.dart'; class EntityCollection { Map _entities; - Map _uiStructure = {}; - - List _topBadgeDomains = ["alarm_control_panel", "binary_sensor", "device_tracker", "updater", "sun", "timer", "sensor"]; + List viewList; EntityCollection() { _entities = {}; + viewList = []; } - Map get ui => _uiStructure; - void parse(List rawData) { _entities.clear(); - _uiStructure.clear(); + viewList.clear(); TheLogger.log("Debug","Parsing ${rawData.length} Home Assistant entities"); rawData.forEach((rawEntityData) { Entity newEntity = addFromRaw(rawEntityData); if (newEntity.isView) { - _uiStructure.addAll({newEntity.entityId: {}}); + viewList.add(newEntity.entityId); } }); - - _createViews(); } void updateState(Map rawStateData) { @@ -60,66 +55,4 @@ class EntityCollection { return _entities[entityId] != null; } - void _createViews() async { - TheLogger.log("Debug","Gethering views"); - int viewCounter = 0; - _uiStructure.forEach((viewId, viewStructure) { //Each view - try { - viewCounter += 1; - Entity viewGroupData = get(viewId); - if (viewGroupData != null) { - viewStructure["groups"] = {}; - viewStructure["state"] = "on"; - viewStructure["entity_id"] = viewGroupData.entityId; - viewStructure["badges"] = {"children": []}; - viewStructure["attributes"] = { - "icon": viewGroupData.icon - }; - - viewGroupData.childEntities.forEach(( - entityId) { //Each entity or group in view - Map newGroup = {}; - if (isExist(entityId)) { - Entity cardOrEntityData = get(entityId); - if (!cardOrEntityData.isGroup) { - if (_topBadgeDomains.contains(cardOrEntityData.domain)) { - viewStructure["badges"]["children"].add(entityId); - } else { - String autoGroupID = "${cardOrEntityData.domain}.${cardOrEntityData.domain}$viewCounter"; - if (viewStructure["groups"]["$autoGroupID"] == null) { - newGroup["entity_id"] = autoGroupID; - newGroup["friendly_name"] = cardOrEntityData.domain; - newGroup["children"] = []; - newGroup["children"].add(entityId); - viewStructure["groups"]["$autoGroupID"] = - Map.from(newGroup); - } else { - viewStructure["groups"]["$autoGroupID"]["children"].add( - entityId); - } - } - } else { - newGroup["entity_id"] = entityId; - newGroup["friendly_name"] = cardOrEntityData.displayName; - newGroup["children"] = List(); - cardOrEntityData.childEntities.forEach(( - groupedEntityId) { - newGroup["children"].add(groupedEntityId); - }); - viewStructure["groups"]["$entityId"] = Map.from(newGroup); - } - } else { - TheLogger.log("Warning", "Unknown entity inside view: $entityId"); - } - }); - } else { - TheLogger.log("Warning", "No state or attributes found for view: $viewId"); - } - - } catch (error) { - TheLogger.log("Error","Error parsing view: $viewId"); - } - }); - } - } \ No newline at end of file diff --git a/lib/home_assistant.class.dart b/lib/home_assistant.class.dart index eb9f874..38df25c 100644 --- a/lib/home_assistant.class.dart +++ b/lib/home_assistant.class.dart @@ -13,6 +13,7 @@ class HomeAssistant { int _subscriptionMessageId = 0; int _configMessageId = 0; EntityCollection _entities; + UIBuilder _uiBuilder; Map _instanceConfig = {}; Completer _fetchCompleter; @@ -22,7 +23,8 @@ class HomeAssistant { Timer _fetchingTimer; String get locationName => _instanceConfig["location_name"] ?? ""; - + int get viewsCount => _entities.viewList.length ?? 0; + UIBuilder get uiBuilder => _uiBuilder; EntityCollection get entities => _entities; @@ -31,6 +33,7 @@ class HomeAssistant { _hassioPassword = password; _hassioAuthType = authType; _entities = EntityCollection(); + _uiBuilder = UIBuilder(); } Future fetch() { @@ -226,6 +229,7 @@ class HomeAssistant { return; } _entities.parse(response["result"]); + _uiBuilder.build(_entities); _statesCompleter.complete(); } diff --git a/lib/main.dart b/lib/main.dart index d15d821..fc6b18c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -18,6 +18,10 @@ part 'utils.class.dart'; part 'mdi.class.dart'; part 'entity.class.dart'; part 'entity_collection.class.dart'; +part 'ui_builder_class.dart'; +part 'view_class.dart'; +part 'card_class.dart'; +part 'badge_class.dart'; EventBus eventBus = new EventBus(); const String appName = "HA Client"; @@ -74,7 +78,6 @@ class MainPage extends StatefulWidget { class _MainPageState extends State with WidgetsBindingObserver { HomeAssistant _homeAssistant; EntityCollection _entities; - Map _uiStructure; //Map _instanceConfig; int _uiViewsCount = 0; String _instanceHost; @@ -158,8 +161,7 @@ class _MainPageState extends State with WidgetsBindingObserver { setState(() { //_instanceConfig = _homeAssistant.instanceConfig; _entities = _homeAssistant.entities; - _uiStructure = _entities.ui; - _uiViewsCount = _uiStructure.length; + _uiViewsCount = _homeAssistant.viewsCount; _isLoading = false; }); }).catchError((e) { @@ -189,14 +191,14 @@ class _MainPageState extends State with WidgetsBindingObserver { List _buildViews() { List result = []; - if ((_entities != null) && (_uiStructure != null)) { - _uiStructure.forEach((viewId, structure) { + if ((_entities != null) && (!_homeAssistant.uiBuilder.isEmpty)) { + _homeAssistant.uiBuilder.views.forEach((viewId, view) { result.add( RefreshIndicator( color: Colors.amber, child: ListView( physics: const AlwaysScrollableScrollPhysics(), - children: _buildSingleView(structure), + children: _buildSingleView(view), ), onRefresh: () => _refreshData(), ) @@ -206,36 +208,35 @@ class _MainPageState extends State with WidgetsBindingObserver { return result; } - List _buildSingleView(structure) { + List _buildSingleView(View view) { List result = []; - if (structure["badges"]["children"].length > 0) { + if (view.isThereBadges) { result.add( Wrap( alignment: WrapAlignment.center, spacing: 10.0, runSpacing: 4.0, - children: _buildBadges(structure["badges"]["children"]), + children: _buildBadges(view.badges), ) ); } - structure["groups"].forEach((id, group) { - if (group["children"].length > 0) { - result.add(_buildCard( - group["children"], group["friendly_name"].toString())); + view.cards.forEach((id, card) { + if (card.entities.isNotEmpty) { + result.add(_buildCard(card)); } }); return result; } - List _buildBadges(List ids) { + List _buildBadges( Map badges) { List result = []; - ids.forEach((entityId) { - var data = _entities.get(entityId); - if (data != null) { + badges.forEach((id, badge) { + var badgeEntity = _entities.get(id); + if (badgeEntity != null) { result.add( - _buildSingleBadge(data) + _buildSingleBadge(badgeEntity) ); } }); @@ -351,12 +352,13 @@ class _MainPageState extends State with WidgetsBindingObserver { ); } - Card _buildCard(List ids, String name) { + Card _buildCard(HACard card) { List body = []; - body.add(_buildCardHeader(name)); - body.addAll(_buildCardBody(ids)); - Card result = - Card(child: new Column(mainAxisSize: MainAxisSize.min, children: body)); + body.add(_buildCardHeader(card.friendlyName)); + body.addAll(_buildCardBody(card.entities)); + Card result = Card( + child: new Column(mainAxisSize: MainAxisSize.min, children: body) + ); return result; } @@ -462,8 +464,8 @@ class _MainPageState extends State with WidgetsBindingObserver { List buildUIViewTabs() { List result = []; - if ((_entities != null) && (_uiStructure != null)) { - _uiStructure.forEach((viewId, structure) { + if ((_entities != null) && (!_homeAssistant.uiBuilder.isEmpty)) { + _homeAssistant.uiBuilder.views.forEach((viewId, view) { result.add( Tab( icon: MaterialDesignIcons.createIconFromEntityData(_entities.get(viewId), 24.0, null) diff --git a/lib/ui_builder_class.dart b/lib/ui_builder_class.dart new file mode 100644 index 0000000..f7e0648 --- /dev/null +++ b/lib/ui_builder_class.dart @@ -0,0 +1,61 @@ +part of 'main.dart'; + +class UIBuilder { + EntityCollection _entities; + Map _views; + List _topBadgeDomains = ["alarm_control_panel", "binary_sensor", "device_tracker", "updater", "sun", "timer", "sensor"]; + + bool get isEmpty => _views.length == 0; + Map get views => _views ?? {}; + + UIBuilder() { + _views = {}; + } + + void build(EntityCollection entitiesCollection) { + _entities = entitiesCollection; + _views.clear(); + _createViewsContainers(entitiesCollection.viewList); + } + + void _createViewsContainers(List viewsList) { + int counter = 0; + viewsList.forEach((viewId) { + counter += 1; + _views[viewId] = View(viewId, counter); + }); + //TODO merge this two func into one + _createViews(); + } + + void _createViews() { + TheLogger.log("Debug","Gethering views"); + _views.forEach((viewId, view) { //Each view + try { + Entity viewGroupEntity = _entities.get(viewId); + viewGroupEntity.childEntities.forEach(( + entityId) { //Each entity or group in view + if (_entities.isExist(entityId)) { + Entity entityToAdd = _entities.get(entityId); + if (!entityToAdd.isGroup) { + if (_topBadgeDomains.contains(entityToAdd.domain)) { + //This is badge + view.addBadge(entityId); + } else { + //This is a standalone entity + view.addEntityWithoutGroup(entityToAdd); + } + } else { + view.addCardWithEntities(entityId, entityToAdd.displayName, entityToAdd.childEntities); + } + } else { + TheLogger.log("Warning", "Unknown entity inside view: $entityId"); + } + }); + } catch (error) { + TheLogger.log("Error","Error parsing view: $viewId"); + } + }); + } + +} \ No newline at end of file diff --git a/lib/view_class.dart b/lib/view_class.dart new file mode 100644 index 0000000..b5f949c --- /dev/null +++ b/lib/view_class.dart @@ -0,0 +1,39 @@ +part of 'main.dart'; + +class View { + String _entityId; + int _count; + Map cards; + Map badges; + + bool get isThereBadges => (badges != null) && (badges.isNotEmpty); + + View(String groupId, int viewCount) { + _entityId = groupId; + _count = viewCount; + cards = {}; + badges = {}; + } + + void addBadge(String entityId) { + badges.addAll({entityId: Badge(entityId)}); + } + + void addEntityWithoutGroup(Entity entity) { + String groupIdToAdd = "${entity.domain}.${entity.domain}$_count"; + if (cards[groupIdToAdd] == null) { + addCard(groupIdToAdd, entity.domain); + } + cards[groupIdToAdd].addEntity(entity.entityId); + } + + void addCard(String entityId, String friendlyName) { + cards.addAll({"$entityId": HACard(entityId, friendlyName)}); + } + + void addCardWithEntities(String entityId, String friendlyName, List entities) { + cards.addAll({"$entityId": HACard(entityId, friendlyName)}); + cards[entityId].addEntities(entities); + } + +} \ No newline at end of file