Compare commits
	
		
			7 Commits
		
	
	
		
			v0.0.11-al
			...
			v0.1.0-alp
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 739e659a81 | ||
|  | 2fb8d8e26b | ||
|  | 2db432ccd2 | ||
|  | 4ad728d369 | ||
|  | e77c7df3e2 | ||
|  | cc0278ee55 | ||
|  | 1133a996b9 | 
| @@ -39,8 +39,8 @@ android { | ||||
|         applicationId "com.keyboardcrumbs.haclient" | ||||
|         minSdkVersion 21 | ||||
|         targetSdkVersion 27 | ||||
|         versionCode 16 | ||||
|         versionName "0.0.11-alpha" | ||||
|         versionCode 18 | ||||
|         versionName "0.1.0-alpha" | ||||
|         testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -17,7 +17,7 @@ class HassioDataModel { | ||||
|   String _hassioPassword; | ||||
|   String _hassioAuthType; | ||||
|   IOWebSocketChannel _hassioChannel; | ||||
|   int _currentMssageId = 0; | ||||
|   int _currentMessageId = 0; | ||||
|   int _statesMessageId = 0; | ||||
|   int _servicesMessageId = 0; | ||||
|   int _subscriptionMessageId = 0; | ||||
| @@ -128,8 +128,8 @@ class HassioDataModel { | ||||
|         _parseEntities(data); | ||||
|       } else if (data["id"] == _servicesMessageId) { | ||||
|         _parseServices(data); | ||||
|       } else if (data["id"] == _currentMssageId) { | ||||
|         debugPrint("Request id:$_currentMssageId was successful"); | ||||
|       } else if (data["id"] == _currentMessageId) { | ||||
|         debugPrint("Request id:$_currentMessageId was successful"); | ||||
|       } else { | ||||
|         debugPrint("Skipped message due to messageId:"); | ||||
|         debugPrint(message); | ||||
| @@ -150,14 +150,14 @@ class HassioDataModel { | ||||
|  | ||||
|   void _sendSubscribe() { | ||||
|     _incrementMessageId(); | ||||
|     _subscriptionMessageId = _currentMssageId; | ||||
|     _subscriptionMessageId = _currentMessageId; | ||||
|     _sendMessageRaw('{"id": $_subscriptionMessageId, "type": "subscribe_events", "event_type": "state_changed"}'); | ||||
|   } | ||||
|  | ||||
|   Future _getConfig() { | ||||
|     _configCompleter = new Completer(); | ||||
|     _incrementMessageId(); | ||||
|     _configMessageId = _currentMssageId; | ||||
|     _configMessageId = _currentMessageId; | ||||
|     _sendMessageRaw('{"id": $_configMessageId, "type": "get_config"}'); | ||||
|  | ||||
|     return _configCompleter.future; | ||||
| @@ -166,7 +166,7 @@ class HassioDataModel { | ||||
|   Future _getStates() { | ||||
|     _statesCompleter = new Completer(); | ||||
|     _incrementMessageId(); | ||||
|     _statesMessageId = _currentMssageId; | ||||
|     _statesMessageId = _currentMessageId; | ||||
|     _sendMessageRaw('{"id": $_statesMessageId, "type": "get_states"}'); | ||||
|  | ||||
|     return _statesCompleter.future; | ||||
| @@ -175,14 +175,14 @@ class HassioDataModel { | ||||
|   Future _getServices() { | ||||
|     _servicesCompleter = new Completer(); | ||||
|     _incrementMessageId(); | ||||
|     _servicesMessageId = _currentMssageId; | ||||
|     _servicesMessageId = _currentMessageId; | ||||
|     _sendMessageRaw('{"id": $_servicesMessageId, "type": "get_services"}'); | ||||
|  | ||||
|     return _servicesCompleter.future; | ||||
|   } | ||||
|  | ||||
|   _incrementMessageId() { | ||||
|     _currentMssageId += 1; | ||||
|     _currentMessageId += 1; | ||||
|   } | ||||
|  | ||||
|   _sendMessageRaw(message) { | ||||
| @@ -245,24 +245,10 @@ class HassioDataModel { | ||||
|       composedEntity["display_name"] = "${entity["attributes"]!=null ? entity["attributes"]["friendly_name"] ?? entity["attributes"]["name"] : "_"}"; | ||||
|       composedEntity["domain"] = entityDomain; | ||||
|  | ||||
|       if ((entityDomain == "automation") || (entityDomain == "switch") || (entityDomain == "light")) { | ||||
|         composedEntity["actionType"] = "switch"; | ||||
|       } else if ((entityDomain == "script") || (entityDomain == "scene")) { | ||||
|         composedEntity["actionType"] = "statelessIcon"; | ||||
|       } else { | ||||
|         composedEntity["actionType"] = "stateText"; | ||||
|       } | ||||
|  | ||||
|       if (composedEntity["attributes"] != null) { | ||||
|         if ((entityDomain == "group")&&(composedEntity["attributes"]["view"] == true)) { | ||||
|           uiGroups.add(entityId); | ||||
|         } | ||||
|         String iconName = composedEntity["attributes"]["icon"]; | ||||
|         if (iconName != null) { | ||||
|           composedEntity["iconCode"] = MaterialDesignIcons.getCustomIconByName(iconName); | ||||
|         } else { | ||||
|           composedEntity["iconCode"] = MaterialDesignIcons.getDefaultIconByEntityId(entityId); // | ||||
|         } | ||||
|       } | ||||
|  | ||||
|  | ||||
| @@ -284,30 +270,32 @@ class HassioDataModel { | ||||
|       var viewGroup = _entitiesData[viewId]; | ||||
|       Map viewGroupStructure = {}; | ||||
|       if (viewGroup != null) { | ||||
|         viewGroupStructure["standalone"] = {}; | ||||
|         viewGroupStructure["groups"] = {}; | ||||
|         viewGroupStructure["groups"]["haclientui.badges"] = {"children": [], "friendly_name": "Badges"}; | ||||
|         viewGroupStructure["iconCode"] = viewGroup["iconCode"]; | ||||
|         viewGroupStructure["state"] = "on"; | ||||
|         viewGroupStructure["entity_id"] = viewGroup["entity_id"]; | ||||
|         viewGroupStructure["badges"] = {"children": []}; | ||||
|         viewGroupStructure["attributes"] = viewGroup["attributes"] != null ? {"icon": viewGroup["attributes"]["icon"]} : {"icon": "none"}; | ||||
|  | ||||
|  | ||||
|         viewGroup["attributes"]["entity_id"].forEach((entityId) { //Each entity or group in view | ||||
|           Map newGroup = {}; | ||||
|           String domain = _entitiesData[entityId]["domain"]; | ||||
|           if (domain != "group") { | ||||
|             String autoGroupID; | ||||
|             if (_topBadgeDomains.contains(domain)) { | ||||
|               autoGroupID = "haclientui.badges"; | ||||
|               viewGroupStructure["badges"]["children"].add(entityId); | ||||
|             } else { | ||||
|               autoGroupID = "$domain.$domain$viewCounter"; | ||||
|             } | ||||
|               String autoGroupID = "$domain.$domain$viewCounter"; | ||||
|               if (viewGroupStructure["groups"]["$autoGroupID"] == null) { | ||||
|                 newGroup["entity_id"] = "$domain.$domain$viewCounter"; | ||||
|                 newGroup["friendly_name"] = "$domain"; | ||||
|                 newGroup["children"] = []; | ||||
|                 newGroup["children"].add(entityId); | ||||
|               viewGroupStructure["groups"]["$autoGroupID"] = Map.from(newGroup); | ||||
|                 viewGroupStructure["groups"]["$autoGroupID"] = | ||||
|                     Map.from(newGroup); | ||||
|               } else { | ||||
|               viewGroupStructure["groups"]["$autoGroupID"]["children"].add(entityId); | ||||
|                 viewGroupStructure["groups"]["$autoGroupID"]["children"].add( | ||||
|                     entityId); | ||||
|               } | ||||
|             } | ||||
|           } else { | ||||
|             newGroup["entity_id"] = entityId; | ||||
| @@ -337,7 +325,7 @@ class HassioDataModel { | ||||
|     }); | ||||
|     _reConnectSocket().then((r) { | ||||
|       _incrementMessageId(); | ||||
|       _sendMessageRaw('{"id": $_currentMssageId, "type": "call_service", "domain": "$domain", "service": "$service", "service_data": {"entity_id": "$entity_id"}}'); | ||||
|       _sendMessageRaw('{"id": $_currentMessageId, "type": "call_service", "domain": "$domain", "service": "$service", "service_data": {"entity_id": "$entity_id"}}'); | ||||
|       _sendTimer.cancel(); | ||||
|       sendCompleter.complete(); | ||||
|     }).catchError((e){ | ||||
| @@ -362,7 +350,59 @@ class MaterialDesignIcons { | ||||
|     "input_number": "mdi:ray-vertex", | ||||
|     "input_select": "mdi:format-list-bulleted", | ||||
|     "input_text": "mdi:textbox", | ||||
|     "sun": "mdi:white-balance-sunny", | ||||
|     "sun": "mdi:white-balance-sunny" | ||||
|   }; | ||||
|  | ||||
|   static Map _defaultIconsByDeviceClass = { | ||||
|     //"binary_sensor.battery": "mdi:", //TODO | ||||
|     "binary_sensor.cold.on": "mdi:snowflake", | ||||
|     "binary_sensor.cold.off": "mdi:thermometer", | ||||
|     "binary_sensor.connectivity.on": "mdi:server-network", | ||||
|     "binary_sensor.connectivity.off": "mdi:server-network-off", | ||||
|     "binary_sensor.door.on": "mdi:door-open", | ||||
|     "binary_sensor.door.off": "mdi:door-closed", | ||||
|     //"binary_sensor.garage_door": "mdi:", | ||||
|     //"binary_sensor.gas": "mdi:", | ||||
|     "binary_sensor.heat.on": "mdi:fire", | ||||
|     "binary_sensor.heat.off": "mdi:thermometer", | ||||
|     "binary_sensor.light.on": "mdi:brightness-7", | ||||
|     "binary_sensor.light.off": "mdi:brightness-5", | ||||
|     //"binary_sensor.lock.on": "mdi:", | ||||
|     //"binary_sensor.lock.off": "mdi:", | ||||
|     "binary_sensor.moisture.on": "mdi:water", | ||||
|     "binary_sensor.moisture.off": "mdi:water-off", | ||||
|     "binary_sensor.motion.on": "mdi:run", | ||||
|     "binary_sensor.motion.off": "mdi:walk", | ||||
|     "binary_sensor.moving.on": "mdi:checkbox-marked-circle", | ||||
|     "binary_sensor.moving.off": "mdi:checkbox-blank-circle-outline", | ||||
|     "binary_sensor.occupancy.on": "mdi:home", | ||||
|     "binary_sensor.occupancy.off": "mdi:home-outline", | ||||
|     "binary_sensor.opening.on": "mdi:square-outline", | ||||
|     "binary_sensor.opening.off": "mdi:square", | ||||
|     //"binary_sensor.plug.on": "mdi:", | ||||
|     //"binary_sensor.plug.off": "mdi:", | ||||
|     "binary_sensor.power.on": "mdi:alert", | ||||
|     "binary_sensor.power.off": "mdi:verified", | ||||
|     //"binary_sensor.presence.on": "mdi:", | ||||
|     //"binary_sensor.presence.off": "mdi:", | ||||
|     //"binary_sensor.problem.on": "mdi:", | ||||
|     //"binary_sensor.problem.off": "mdi:", | ||||
|     "binary_sensor.safety.on": "mdi:alert", | ||||
|     "binary_sensor.safety.off": "mdi:verified", | ||||
|     "binary_sensor.smoke.on": "mdi:alert", | ||||
|     "binary_sensor.smoke.off": "mdi:verified", | ||||
|     "binary_sensor.sound.on": "mdi:music-note", | ||||
|     "binary_sensor.sound.off": "mdi:music-note-off", | ||||
|     "binary_sensor.vibration.on": "mdi:vibrate", | ||||
|     "binary_sensor.vibration.off": "mdi:mdi-crop-portrait", | ||||
|     //"binary_sensor.window.on": "mdi:", | ||||
|     //"binary_sensor.window.off": "mdi:", | ||||
|     "sensor.battery": "mdi:battery-80", | ||||
|     "sensor.humidity": "mdi:water-percent", | ||||
|     //"sensor.illuminance": "mdi:", | ||||
|     "sensor.temperature": "mdi:thermometer", | ||||
|     //"cover.window": "mdi:", | ||||
|     //"cover.garage": "mdi:", | ||||
|   }; | ||||
|   static Map _iconsDataMap = { | ||||
|     "mdi:access-point": 0xf002, | ||||
| @@ -3162,13 +3202,59 @@ class MaterialDesignIcons { | ||||
|     "mdi:blank": 0xf68c | ||||
|   }; | ||||
|  | ||||
|   static int getCustomIconByName(String name) { | ||||
|   static Widget createIconFromEntityData(Map data, double size, Color color) { | ||||
|     if ((data["attributes"] != null) && (data["attributes"]["entity_picture"] != null)) { | ||||
|       if (homeAssistantWebHost != null) { | ||||
|         return CircleAvatar( | ||||
|           backgroundColor: Colors.white, | ||||
|           backgroundImage: CachedNetworkImageProvider( | ||||
|             "$homeAssistantWebHost${data["attributes"]["entity_picture"]}", | ||||
|           ), | ||||
|         ); | ||||
|       } else { | ||||
|         return Container(width: 0.0, height: 0.0); | ||||
|       } | ||||
|     } else { | ||||
|       String iconName = data["attributes"] != null | ||||
|           ? data["attributes"]["icon"] | ||||
|           : null; | ||||
|       int iconCode = 0; | ||||
|       if (iconName != null) { | ||||
|         iconCode = getIconCodeByIconName(iconName); | ||||
|       } else { | ||||
|         iconCode = getDefaultIconByEntityId(data["entity_id"], | ||||
|             data["attributes"] != null | ||||
|                 ? data["attributes"]["device_class"] | ||||
|                 : null, data["state"]); // | ||||
|       } | ||||
|       return Icon( | ||||
|           IconData(iconCode, fontFamily: 'Material Design Icons'), | ||||
|           size: size, | ||||
|           color: color, | ||||
|       ); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   static IconData createIconDataFromIconCode(int code) { | ||||
|     return IconData(code, fontFamily: 'Material Design Icons'); | ||||
|   } | ||||
|  | ||||
|   static IconData createIconDataFromIconName(String name) { | ||||
|     return IconData(getIconCodeByIconName(name), fontFamily: 'Material Design Icons'); | ||||
|   } | ||||
|  | ||||
|   static int getIconCodeByIconName(String name) { | ||||
|     return _iconsDataMap[name] ?? 0; | ||||
|   } | ||||
|  | ||||
|   static int getDefaultIconByEntityId(String entityId) { | ||||
|   static int getDefaultIconByEntityId(String entityId, String deviceClass, String state) { | ||||
|     String domain = entityId.split(".")[0]; | ||||
|     String iconName = _defaultIconsByDomains[domain]; | ||||
|     String iconNameByDomain = _defaultIconsByDomains[domain]; | ||||
|     String iconNameByDeviceClass; | ||||
|     if (deviceClass != null) { | ||||
|       iconNameByDeviceClass = _defaultIconsByDeviceClass["$domain.$deviceClass.$state"] ?? _defaultIconsByDeviceClass["$domain.$deviceClass"]; | ||||
|     } | ||||
|     String iconName = iconNameByDeviceClass ?? iconNameByDomain; | ||||
|     if (iconName != null) { | ||||
|       return _iconsDataMap[iconName] ?? 0; | ||||
|     } else { | ||||
|   | ||||
							
								
								
									
										209
									
								
								lib/main.dart
									
									
									
									
									
								
							
							
						
						
									
										209
									
								
								lib/main.dart
									
									
									
									
									
								
							| @@ -7,13 +7,16 @@ import 'package:web_socket_channel/io.dart'; | ||||
| import 'package:progress_indicators/progress_indicators.dart'; | ||||
| import 'package:event_bus/event_bus.dart'; | ||||
| import 'package:flutter/widgets.dart'; | ||||
| import 'package:cached_network_image/cached_network_image.dart'; | ||||
|  | ||||
| part 'settings.dart'; | ||||
| part 'data_model.dart'; | ||||
|  | ||||
| EventBus eventBus = new EventBus(); | ||||
| const String appName = "HA Client"; | ||||
| const appVersion = "0.0.11-alpha"; | ||||
| const appVersion = "0.1.0-alpha"; | ||||
|  | ||||
| String homeAssistantWebHost; | ||||
|  | ||||
| void main() => runApp(new HassClientApp()); | ||||
|  | ||||
| @@ -56,13 +59,17 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver { | ||||
|   StreamSubscription _stateSubscription; | ||||
|   StreamSubscription _settingsSubscription; | ||||
|   bool _isLoading = true; | ||||
|   Map _stateIconColors = { | ||||
|   Map<String, Color> _stateIconColors = { | ||||
|     "on": Colors.amber, | ||||
|     "off": Colors.blueGrey, | ||||
|     "off": Color.fromRGBO(68, 115, 158, 1.0), | ||||
|     "unavailable": Colors.black12, | ||||
|     "unknown": Colors.black12, | ||||
|     "playing": Colors.amber | ||||
|   }; | ||||
|   Map<String, Color> _badgeColors = { | ||||
|     "default": Color.fromRGBO(223, 76, 30, 1.0), | ||||
|     "binary_sensor": Color.fromRGBO(3, 155, 229, 1.0) | ||||
|   }; | ||||
|  | ||||
|   @override | ||||
|   void initState() { | ||||
| @@ -92,6 +99,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver { | ||||
|     String port = prefs.getString('hassio-port'); | ||||
|     _instanceHost = "$domain:$port"; | ||||
|     String apiEndpoint = "${prefs.getString('hassio-protocol')}://$domain:$port/api/websocket"; | ||||
|     homeAssistantWebHost = "${prefs.getString('hassio-res-protocol')}://$domain:$port"; | ||||
|     String apiPassword = prefs.getString('hassio-password'); | ||||
|     String authType = prefs.getString('hassio-auth-type'); | ||||
|     if ((domain == null) || (port == null) || (apiPassword == null) || | ||||
| @@ -177,9 +185,19 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver { | ||||
|  | ||||
|   List<Widget> _buildSingleView(structure) { | ||||
|     List<Widget> result = []; | ||||
|     /*structure["standalone"].forEach((entityId) { | ||||
|         result.add(_buildCard([entityId], "")); | ||||
|       });*/ | ||||
|     if (structure["badges"]["children"].length > 0) { | ||||
|       result.add( | ||||
|             Wrap( | ||||
|               alignment: WrapAlignment.center, | ||||
|               spacing: 10.0, | ||||
|               runSpacing: 4.0, | ||||
|               //padding: new EdgeInsets.all(8.0), | ||||
|               //itemExtent: 40.0, | ||||
|               children: _buildBadges(structure["badges"]["children"]), | ||||
|             ) | ||||
|       ); | ||||
|  | ||||
|     } | ||||
|     structure["groups"].forEach((id, group) { | ||||
|       if (group["children"].length > 0) { | ||||
|         result.add(_buildCard( | ||||
| @@ -190,6 +208,130 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver { | ||||
|     return result; | ||||
|   } | ||||
|  | ||||
|   List<Widget> _buildBadges(List ids) { | ||||
|     List<Widget> result = []; | ||||
|     ids.forEach((entityId) { | ||||
|       var data = _entitiesData[entityId]; | ||||
|       if (data == null) { | ||||
|         debugPrint("Hiding unknown entity from badges: $entityId"); | ||||
|       } else { | ||||
|         result.add( | ||||
|         _buildSingleBadge(data) | ||||
|         ); | ||||
|       } | ||||
|     }); | ||||
|     return result; | ||||
|   } | ||||
|  | ||||
|   Widget _buildSingleBadge(data) { | ||||
|     double iconSize = 26.0; | ||||
|     Widget badgeIcon; | ||||
|     String badgeTextValue; | ||||
|     Color iconColor = _badgeColors[data["domain"]] ?? _badgeColors["default"]; | ||||
|     switch (data["domain"]) { | ||||
|       case "sun": { | ||||
|         badgeIcon = data["state"] == "below_horizon" ? | ||||
|           Icon( | ||||
|             MaterialDesignIcons.createIconDataFromIconCode(0xf0dc), | ||||
|             size: iconSize, | ||||
|           ) : | ||||
|           Icon( | ||||
|             MaterialDesignIcons.createIconDataFromIconCode(0xf5a8), | ||||
|             size: iconSize, | ||||
|           ); | ||||
|         break; | ||||
|       } | ||||
|       case "sensor": { | ||||
|         badgeTextValue = data["attributes"]["unit_of_measurement"]; | ||||
|         badgeIcon = Center( | ||||
|           child: Text( | ||||
|             "${data['state']}", | ||||
|             overflow: TextOverflow.fade, | ||||
|             softWrap: false, | ||||
|             textAlign: TextAlign.center, | ||||
|             style: TextStyle(fontSize: 18.0), | ||||
|           ), | ||||
|         ); | ||||
|         break; | ||||
|       } | ||||
|       case "device_tracker": { | ||||
|         badgeIcon = MaterialDesignIcons.createIconFromEntityData(data, iconSize,Colors.black); | ||||
|         badgeTextValue = data["state"]; | ||||
|         break; | ||||
|       } | ||||
|       default: { | ||||
|        badgeIcon = MaterialDesignIcons.createIconFromEntityData(data, iconSize,Colors.black); | ||||
|       } | ||||
|     } | ||||
|     Widget badgeText; | ||||
|     if (badgeTextValue == null) { | ||||
|       badgeText = Container(width: 0.0, height: 0.0); | ||||
|     } else { | ||||
|       badgeText = Container( | ||||
|           padding: EdgeInsets.fromLTRB(6.0, 2.0, 6.0, 2.0), | ||||
|           child: Text("$badgeTextValue", | ||||
|               style: TextStyle(fontSize: 13.0, color: Colors.white), | ||||
|               textAlign: TextAlign.center, softWrap: false, overflow: TextOverflow.fade), | ||||
|           decoration: new BoxDecoration( | ||||
|             // Circle shape | ||||
|             //shape: BoxShape.circle, | ||||
|             color: iconColor, | ||||
|             borderRadius: BorderRadius.circular(9.0), | ||||
|           ) | ||||
|       ); | ||||
|     } | ||||
|     return Column( | ||||
|       children: <Widget>[ | ||||
|         Container( | ||||
|           margin: EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0), | ||||
|           width: 50.0, | ||||
|           height: 50.0, | ||||
|           decoration: new BoxDecoration( | ||||
|             // Circle shape | ||||
|             shape: BoxShape.circle, | ||||
|             color: Colors.white, | ||||
|             // The border you want | ||||
|             border: new Border.all( | ||||
|               width: 2.0, | ||||
|               color: iconColor, | ||||
|             ), | ||||
|           ), | ||||
|           child: Stack( | ||||
|             overflow: Overflow.visible, | ||||
|             children: <Widget>[ | ||||
|               Positioned( | ||||
|                 width: 46.0, | ||||
|                 height: 46.0, | ||||
|                 top: 0.0, | ||||
|                 left: 0.0, | ||||
|                 child: badgeIcon, | ||||
|               ), | ||||
|               Positioned( | ||||
|                 //width: 50.0, | ||||
|                 bottom: -9.0, | ||||
|                 left: -15.0, | ||||
|                 right: -15.0, | ||||
|                 child: Center( | ||||
|                   child: badgeText, | ||||
|                 ) | ||||
|               ) | ||||
|             ], | ||||
|           ), | ||||
|         ), | ||||
|         Container( | ||||
|           width: 60.0, | ||||
|           child: Text( | ||||
|             "${data['display_name']}", | ||||
|             textAlign: TextAlign.center, | ||||
|             softWrap: true, | ||||
|             maxLines: 2, | ||||
|             overflow: TextOverflow.ellipsis, | ||||
|           ), | ||||
|         ), | ||||
|       ], | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Card _buildCard(List ids, String name) { | ||||
|     List<Widget> body = []; | ||||
|     body.add(_buildCardHeader(name)); | ||||
| @@ -225,15 +367,13 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver { | ||||
|         debugPrint("Hiding unknown entity from card: $id"); | ||||
|       } else { | ||||
|         entities.add(new ListTile( | ||||
|           leading: Icon( | ||||
|             _createMDIfromCode(data["iconCode"]), | ||||
|             color: _stateIconColors[data["state"]] ?? Colors.blueGrey, | ||||
|           ), | ||||
|           leading: MaterialDesignIcons.createIconFromEntityData(data, 28.0, _stateIconColors[data["state"]] ?? Colors.blueGrey), | ||||
|           //subtitle: Text("${data['entity_id']}"), | ||||
|           trailing: _buildEntityAction(id), | ||||
|           trailing: _buildEntityActionWidget(data), | ||||
|           title: Text( | ||||
|             "${data["display_name"]}", | ||||
|             overflow: TextOverflow.ellipsis, | ||||
|             overflow: TextOverflow.fade, | ||||
|             softWrap: false, | ||||
|           ), | ||||
|         )); | ||||
|       } | ||||
| @@ -241,43 +381,58 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver { | ||||
|     return entities; | ||||
|   } | ||||
|  | ||||
|   Widget _buildEntityAction(String entityId) { | ||||
|     var entity = _entitiesData[entityId]; | ||||
|   Widget _buildEntityActionWidget(data) { | ||||
|     String entityId = data["entity_id"]; | ||||
|     Widget result; | ||||
|     if (entity["actionType"] == "switch") { | ||||
|     switch (data["domain"]) { | ||||
|       case "automation": | ||||
|       case "switch": | ||||
|       case "light": { | ||||
|         result = Switch( | ||||
|         value: (entity["state"] == "on"), | ||||
|           value: (data["state"] == "on"), | ||||
|           onChanged: ((state) { | ||||
|             _callService( | ||||
|               entity["domain"], state ? "turn_on" : "turn_off", entityId); | ||||
|                 data["domain"], state ? "turn_on" : "turn_off", entityId); | ||||
|             setState(() { | ||||
|               _entitiesData[entityId]["state"] = state ? "on" : "off"; | ||||
|             }); | ||||
|           }), | ||||
|         ); | ||||
|     } else if (entity["actionType"] == "statelessIcon") { | ||||
|         break; | ||||
|       } | ||||
|  | ||||
|       case "script": | ||||
|       case "scene": { | ||||
|         result = SizedBox( | ||||
|           width: 60.0, | ||||
|           child: FlatButton( | ||||
|             onPressed: (() { | ||||
|               _callService(entity["domain"], "turn_on", entityId); | ||||
|               _callService(data["domain"], "turn_on", entityId); | ||||
|             }), | ||||
|             child: Text( | ||||
|               "Run", | ||||
|               textAlign: TextAlign.right, | ||||
|               style: new TextStyle(fontSize: 16.0, color: Colors.blue), | ||||
|             ), | ||||
|           )); | ||||
|     } else { | ||||
|           ) | ||||
|         ); | ||||
|         break; | ||||
|       } | ||||
|  | ||||
|       default: { | ||||
|         result = Padding( | ||||
|           padding: EdgeInsets.fromLTRB(0.0, 0.0, 16.0, 0.0), | ||||
|           child: Text( | ||||
|               "${entity["state"]}${(entity["attributes"] != null && entity["attributes"]["unit_of_measurement"] != null) ? entity["attributes"]["unit_of_measurement"] : ''}", | ||||
|             "${data["state"]}${(data["attributes"] != null && data["attributes"]["unit_of_measurement"] != null) ? data["attributes"]["unit_of_measurement"] : ''}", | ||||
|             textAlign: TextAlign.right, | ||||
|             style: new TextStyle( | ||||
|               fontSize: 16.0, | ||||
|               ))); | ||||
|             ) | ||||
|           ) | ||||
|         ); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     /*return SizedBox( | ||||
|       width: 60.0, | ||||
|       // height: double.infinity, | ||||
| @@ -286,17 +441,13 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver { | ||||
|     return result; | ||||
|   } | ||||
|  | ||||
|   IconData _createMDIfromCode(int code) { | ||||
|     return IconData(code, fontFamily: 'Material Design Icons'); | ||||
|   } | ||||
|  | ||||
|   List<Tab> buildUIViewTabs() { | ||||
|     List<Tab> result = []; | ||||
|     if ((_entitiesData != null) && (_uiStructure != null)) { | ||||
|       _uiStructure.forEach((viewId, structure) { | ||||
|         result.add( | ||||
|             Tab( | ||||
|                 icon: Icon(_createMDIfromCode(structure["iconCode"])) | ||||
|                 icon: MaterialDesignIcons.createIconFromEntityData(structure, 24.0, null) | ||||
|             ) | ||||
|         ); | ||||
|       }); | ||||
| @@ -449,7 +600,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver { | ||||
|                 ), | ||||
|               ),*/ | ||||
|               Icon( | ||||
|                 _createMDIfromCode(MaterialDesignIcons.getCustomIconByName("mdi:home-assistant")), | ||||
|                 MaterialDesignIcons.createIconDataFromIconName("mdi:home-assistant"), | ||||
|                 size: 100.0, | ||||
|                 color: _errorCodeToBeShown == 0 ? Colors.blue : Colors.redAccent, | ||||
|               ), | ||||
|   | ||||
| @@ -40,6 +40,7 @@ class _ConnectionSettingsPageState extends State<ConnectionSettingsPage> { | ||||
|     prefs.setString("hassio-port", _hassioPort); | ||||
|     prefs.setString("hassio-password", _hassioPassword); | ||||
|     prefs.setString("hassio-protocol", _socketProtocol); | ||||
|     prefs.setString("hassio-res-protocol", _socketProtocol == "wss" ? "https" : "http"); | ||||
|     prefs.setString("hassio-auth-type", _authType); | ||||
|   } | ||||
|  | ||||
|   | ||||
							
								
								
									
										35
									
								
								pubspec.lock
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								pubspec.lock
									
									
									
									
									
								
							| @@ -36,6 +36,13 @@ packages: | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "1.0.4" | ||||
|   cached_network_image: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|       name: cached_network_image | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "0.4.2" | ||||
|   charcode: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -92,6 +99,13 @@ packages: | ||||
|     description: flutter | ||||
|     source: sdk | ||||
|     version: "0.0.0" | ||||
|   flutter_cache_manager: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: flutter_cache_manager | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "0.1.2" | ||||
|   flutter_launcher_icons: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
| @@ -251,6 +265,13 @@ packages: | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "1.6.2" | ||||
|   path_provider: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: path_provider | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "0.4.1" | ||||
|   petitparser: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -375,6 +396,13 @@ packages: | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "1.0.4" | ||||
|   synchronized: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: synchronized | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "1.5.3" | ||||
|   term_glyph: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -403,6 +431,13 @@ packages: | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "0.9.0+5" | ||||
|   uuid: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: uuid | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "1.0.3" | ||||
|   vector_math: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| name: hass_client | ||||
| description: Home Assistant Android Client | ||||
|  | ||||
| version: 0.0.11-alpha | ||||
| version: 0.1.0-alpha | ||||
|  | ||||
| environment: | ||||
|   sdk: ">=2.0.0-dev.68.0 <3.0.0" | ||||
| @@ -14,6 +14,7 @@ dependencies: | ||||
|   event_bus: ^1.0.1 | ||||
|   package_info: ^0.3.2 | ||||
|   flutter_launcher_icons: ^0.6.1 | ||||
|   cached_network_image: ^0.4.1 | ||||
|  | ||||
|   # The following adds the Cupertino Icons font to your application. | ||||
|   # Use with the CupertinoIcons class for iOS style icons. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user