From 067ccfde0280434c324b50a18be3ba9ba7fa9bbc Mon Sep 17 00:00:00 2001 From: estevez Date: Sat, 29 Sep 2018 13:49:25 +0300 Subject: [PATCH] Refactoring: Entity classes by action type. Wntity widget building in entity --- lib/entity.class.dart | 126 ++++++++++++++++++++++++ lib/entity_collection.class.dart | 26 ++++- lib/home_assistant.class.dart | 2 +- lib/main.dart | 161 +++---------------------------- lib/utils.class.dart | 13 ++- 5 files changed, 180 insertions(+), 148 deletions(-) diff --git a/lib/entity.class.dart b/lib/entity.class.dart index eb6f89f..5f74719 100644 --- a/lib/entity.class.dart +++ b/lib/entity.class.dart @@ -1,6 +1,13 @@ part of 'main.dart'; class Entity { + static Map stateIconColors = { + "on": Colors.amber, + "off": Color.fromRGBO(68, 115, 158, 1.0), + "unavailable": Colors.black12, + "unknown": Colors.black12, + "playing": Colors.amber + }; Map _attributes; String _domain; String _entityId; @@ -43,4 +50,123 @@ class Entity { _state = rawData["state"]; } + Widget buildWidget() { + return SizedBox( + height: 34.0, + child: Row( + children: [ + Padding( + padding: EdgeInsets.fromLTRB(8.0, 0.0, 12.0, 0.0), + child: MaterialDesignIcons.createIconWidgetFromEntityData(this, 28.0, Entity.stateIconColors[_state] ?? Colors.blueGrey), + ), + Expanded( + child: Text( + "${this.displayName}", + overflow: TextOverflow.fade, + softWrap: false, + style: TextStyle( + fontSize: 16.0 + ), + ), + ), + _buildActionWidget() + ], + ), + ); + } + + Widget _buildActionWidget() { + return Padding( + padding: EdgeInsets.fromLTRB(0.0, 0.0, 14.0, 0.0), + child: Text( + "${_state}${this.unitOfMeasurement}", + textAlign: TextAlign.right, + style: new TextStyle( + fontSize: 16.0, + ) + ) + ); + } +} + +class SwitchEntity extends Entity { + + SwitchEntity(Map rawData) : super(rawData); + + @override + Widget _buildActionWidget() { + return Switch( + value: this.isOn, + onChanged: ((switchState) { + eventBus.fire(new ServiceCallEvent(_domain, switchState ? "turn_on" : "turn_off", entityId, null)); + }), + ); + } + +} + +class ButtonEntity extends Entity { + + ButtonEntity(Map rawData) : super(rawData); + + @override + Widget _buildActionWidget() { + return FlatButton( + onPressed: (() { + eventBus.fire(new ServiceCallEvent(_domain, "turn_on", _entityId, null)); + }), + child: Text( + "EXECUTE", + textAlign: TextAlign.right, + style: new TextStyle(fontSize: 16.0, color: Colors.blue), + ), + ); + } + +} + +class InputEntity extends Entity { + + InputEntity(Map rawData) : super(rawData); + + @override + Widget _buildActionWidget() { + if (this.isSlider) { + return Container( + width: 200.0, + child: Row( + children: [ + Expanded( + child: Slider( + min: this.minValue*10, + max: this.maxValue*10, + value: this.doubleState*10, + divisions: this.getValueDivisions(), + onChanged: (value) { + eventBus.fire(new StateChangedEvent(_entityId, (value.roundToDouble() / 10).toString(), true)); + }, + onChangeEnd: (value) { + eventBus.fire(new ServiceCallEvent(_domain, "set_value", _entityId,{"value": "${_state}"})); + }, + ), + ), + Padding( + padding: EdgeInsets.only(right: 16.0), + child: Text( + "${_state}${this.unitOfMeasurement}", + textAlign: TextAlign.right, + style: new TextStyle( + fontSize: 16.0, + ) + ), + ) + ], + ), + ); + } else { + //TODO draw box instead of slider + return Text("Not implemented"); + } + } + } \ No newline at end of file diff --git a/lib/entity_collection.class.dart b/lib/entity_collection.class.dart index 3c1ac66..cdd6ba4 100644 --- a/lib/entity_collection.class.dart +++ b/lib/entity_collection.class.dart @@ -26,6 +26,30 @@ class EntityCollection { }); } + Entity _createEntityInstance(rawEntityData) { + switch (rawEntityData["entity_id"].split(".")[0]) { + case "automation": + case "input_boolean ": + case "switch": + case "light": { + return SwitchEntity(rawEntityData); + } + + case "script": + case "scene": { + return ButtonEntity(rawEntityData); + } + + case "input_number": { + return InputEntity(rawEntityData); + } + + default: { + return Entity(rawEntityData); + } + } + } + void updateState(Map rawStateData) { if (isExist(rawStateData["entity_id"])) { updateFromRaw(rawStateData["new_state"] ?? rawStateData["old_state"]); @@ -39,7 +63,7 @@ class EntityCollection { } Entity addFromRaw(Map rawEntityData) { - Entity entity = Entity(rawEntityData); + Entity entity = _createEntityInstance(rawEntityData); _entities[entity.entityId] = entity; return entity; } diff --git a/lib/home_assistant.class.dart b/lib/home_assistant.class.dart index c48eba2..03790f3 100644 --- a/lib/home_assistant.class.dart +++ b/lib/home_assistant.class.dart @@ -185,7 +185,7 @@ class HomeAssistant { void _handleEntityStateChange(Map eventData) { TheLogger.log("Debug", "Parsing new state for ${eventData['entity_id']}"); _entities.updateState(eventData); - eventBus.fire(new StateChangedEvent(eventData["entity_id"])); + eventBus.fire(new StateChangedEvent(eventData["entity_id"], null, false)); } void _parseConfig(Map data) { diff --git a/lib/main.dart b/lib/main.dart index 8d3c33d..acae0da 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -85,14 +85,9 @@ class _MainPageState extends State with WidgetsBindingObserver { String _lastErrorMessage = ""; StreamSubscription _stateSubscription; StreamSubscription _settingsSubscription; + StreamSubscription _serviceCallSubscription; bool _isLoading = true; - Map _stateIconColors = { - "on": Colors.amber, - "off": Color.fromRGBO(68, 115, 158, 1.0), - "unavailable": Colors.black12, - "unknown": Colors.black12, - "playing": Colors.amber - }; + Map _badgeColors = { "default": Color.fromRGBO(223, 76, 30, 1.0), "binary_sensor": Color.fromRGBO(3, 155, 229, 1.0) @@ -146,9 +141,17 @@ class _MainPageState extends State with WidgetsBindingObserver { if (_stateSubscription != null) _stateSubscription.cancel(); _stateSubscription = eventBus.on().listen((event) { setState(() { - _entities = _homeAssistant.entities; + if (event.setToCollection) { + _entities + .get(event.entityId) + .state = event.newState; + } }); }); + if (_serviceCallSubscription != null) _serviceCallSubscription.cancel(); + _serviceCallSubscription = eventBus.on().listen((event) { + _callService(event.domain, event.service, event.entityId, event.additionalParams); + }); } _refreshData() async { @@ -384,151 +387,18 @@ class _MainPageState extends State with WidgetsBindingObserver { List _buildCardBody(List ids) { List entities = []; ids.forEach((id) { - var data = _entities.get(id); - if (data != null) { + var entity = _entities.get(id); + if (entity != null) { entities.add( Padding( padding: EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0), - child: SizedBox( - height: 34.0, - child: Row( - children: [ - Padding( - padding: EdgeInsets.fromLTRB(8.0, 0.0, 12.0, 0.0), - child: MaterialDesignIcons.createIconWidgetFromEntityData(data, 28.0, _stateIconColors[data.state] ?? Colors.blueGrey), - ), - Expanded( - child: Text( - "${data.displayName}", - overflow: TextOverflow.fade, - softWrap: false, - style: TextStyle( - fontSize: 16.0 - ), - ), - ), - _buildEntityActionWidget(data) - ], - ), - ), - ) - /*new ListTile( - leading: MaterialDesignIcons.createIconWidgetFromEntityData(data, 28.0, _stateIconColors[data.state] ?? Colors.blueGrey), - //subtitle: Text("${data['entity_id']}"), - trailing: _buildEntityActionWidget(data), - title: Text( - "${data.displayName}", - overflow: TextOverflow.fade, - softWrap: false, - ), - )*/); + child: entity.buildWidget(), + )); } }); return entities; } - Widget _buildEntityActionWidget(Entity entity) { - String entityId = entity.entityId; - Widget result; - switch (entity.domain) { - case "automation": - case "input_boolean": - case "switch": - case "light": { - result = Switch( - value: entity.isOn, - onChanged: ((state) { - _callService( - entity.domain, state ? "turn_on" : "turn_off", entityId, null - ); - //TODO remove after checking if state will chenge without setState but after socket event - /*setState(() { - _entities[entityId]["state"] = state ? "on" : "off"; - });*/ - }), - ); - break; - } - - case "script": - case "scene": { - result = FlatButton( - onPressed: (() { - _callService(entity.domain, "turn_on", entityId, null); - }), - child: Text( - "EXECUTE", - textAlign: TextAlign.right, - style: new TextStyle(fontSize: 16.0, color: Colors.blue), - ), - ); - break; - } - - case "input_number": { - if (entity.isSlider) { - result = Container( - width: 200.0, - child: Row( - children: [ - Expanded( - child: Slider( - min: entity.minValue*10, - max: entity.maxValue*10, - value: entity.doubleState*10, - divisions: entity.getValueDivisions(), - onChanged: (value) { - setState(() { - entity.state = (value.roundToDouble() / 10).toString(); - }); - }, - onChangeEnd: (value) { - _callService(entity.domain, "set_value", entityId, - {"value": "${entity.state}"}); - }, - ), - ), - Padding( - padding: EdgeInsets.only(right: 16.0), - child: Text( - "${entity.state}${entity.unitOfMeasurement}", - textAlign: TextAlign.right, - style: new TextStyle( - fontSize: 16.0, - ) - ), - ) - ], - ), - ); - } else { - //TODO draw box instead of slider - } - break; - } - - default: { - result = Padding( - padding: EdgeInsets.fromLTRB(0.0, 0.0, 14.0, 0.0), - child: Text( - "${entity.state}${entity.unitOfMeasurement}", - textAlign: TextAlign.right, - style: new TextStyle( - fontSize: 16.0, - ) - ) - ); - } - } - - /*return SizedBox( - width: 60.0, - // height: double.infinity, - child: result - );*/ - return result; - } - List buildUIViewTabs() { List result = []; if ((_entities != null) && (!_homeAssistant.uiBuilder.isEmpty)) { @@ -731,6 +601,7 @@ class _MainPageState extends State with WidgetsBindingObserver { WidgetsBinding.instance.removeObserver(this); if (_stateSubscription != null) _stateSubscription.cancel(); if (_settingsSubscription != null) _settingsSubscription.cancel(); + if (_serviceCallSubscription != null) _serviceCallSubscription.cancel(); _homeAssistant.closeConnection(); super.dispose(); } diff --git a/lib/utils.class.dart b/lib/utils.class.dart index c7f8633..3f40b84 100644 --- a/lib/utils.class.dart +++ b/lib/utils.class.dart @@ -44,12 +44,23 @@ class haUtils { class StateChangedEvent { String entityId; + String newState; + bool setToCollection; - StateChangedEvent(this.entityId); + StateChangedEvent(this.entityId, this.newState, this.setToCollection); } class SettingsChangedEvent { bool reconnect; SettingsChangedEvent(this.reconnect); +} + +class ServiceCallEvent { + String domain; + String service; + String entityId; + Map additionalParams; + + ServiceCallEvent(this.domain, this.service, this.entityId, this.additionalParams); } \ No newline at end of file