meishild 发表于 2019-8-26 23:36:01

篇五:几个界面优化插件

本帖最后由 meishild 于 2019-8-27 09:05 编辑

目录地址:https://bbs.hassbian.com/thread-8041-1-1.html

本篇没有讲详细怎么安装一个插件,请参考:https://bbs.hassbian.com/thread-8069-1-1.html

而且我也没有写的太细,这些都是偏向前端化的配置,我都测试趟了以下,只是给大家一些优化参考。


# 篇五:几个界面优化插件

都是一直用的默认hass的界面是不是很不爽,特别用在pad或者手机上,来我们看一下几个第三方界面的插件。

**注意:因为已经将过一版专门插件如何安装,以下每个插件我不再细讲,我一直觉得插件安装配置、问题查找是最重要的能力,否则弃坑的可能性非常大,一步一坎,所以大家还是要有自己研究探索能力,毕竟这都是软件层面上的,再出问题能有多大,大不了删了重装嘛,如果怕树莓派有问题,就装我蓝牙网关那篇的树莓派sd卡备份以下,出了问题恢复一份。**


## floorplan

这个是我玩hass最开始最喜欢的插件,特别是在[https://community.home-assistant.io/t/share-your-floorplan/](https://community.home-assistant.io/t/share-your-floorplan/)看到各路大神写的样式以后,发现简直不搞这个等于白玩hass啊。

最后一顿操作搞出来我现在的版本:


floorplan其实整体结构比较简单,就是首先一个html,然后我们自己画一个svg图,把图上的某某实体都绑定上数据,就可以了,其实这种图还挺方便的特别是看数据特别直观,哪个房间的温度,哪个设备运行了,在加上一个天气简直完美。

但是要承载这个图可能就需要一个设备了,放在入户,我在share里最喜欢的两个。



这个一看就是即实用又美观,首先数据又展示内容有,右面一排的情景控制解决了图上设备比较小不好控制的问题。



这个就是看着舒爽,用圆圈的颜色来区分等的开关状态。


### 做一个floorplan

注意虽然作者已经有2年没更新了,不过最近看到大神准备继续更新这个插件了。[https://github.com/pkozul/ha-floorplan](https://github.com/pkozul/ha-floorplan)

大家还是参照大神写好的教程,我想想我来写也不会比这个更详细。

[https://post.smzdm.com/p/597918/](https://post.smzdm.com/p/597918/)

我只能给大家几个我做过程中遇到的问题。

- 首先svg没什么比较好的编辑器,免费的(https://inkscape.org/en/develop/about-svg/)只能说凑合,我是用mac的一个画流程图一类的软件omni graffle来画,不过这个不是专门画svg的所有有个问题,就是不能设置实体id,为此我写了python脚本来替换,如果有需求可以找我单要,如果没有这个软件功底的不推荐实用。
- 画图尽量拆分好图层,比如第一层墙体,第二层地板,第三层家居,第四层设备。好处很多,特别是需要往复修改一个图纸的时候。
- 需要画户型图就比较耗时了大家有心里准备,我花了差不多3-4个小时,特别是我有详细尺寸的前提下。
- 作者推荐的酷家乐很好用,主要是有很多同小区户型该起来比较方便,但是只能导出原型图,墙体一类的还是要自己画。

!(https://cdn.nlark.com/yuque/0/20 ... tus=done&width=1900)

最后给一下我的svg方便大家参考。


### floorplan&lovelace



[https://github.com/pkozul/lovelace-floorplan](https://github.com/pkozul/lovelace-floorplan)

最近也支持lovelace环境了,有需要的可以参照上面的说明。


## Home Panel

最接近官方的插件,我用的也不多更多的是测试。



这个插件首先是按照所谓的区域方式拆分的,并且这个方式还不能取消。
看到图上的Scenes、Central Heatting、Weather、LivingRoot

这个插件比较简单,我是直接通过hass.io插件直接安装,安装好以后,需要配置映射端口地址。


配置好了直接启动,通过http://ip:8124就可以访问了,这里有个坑。

- home panle是独立的账号密码,需要先注册,然后在登陆。
- 登陆成功以后需要绑定到hass上然后再绑定。


### Home Panel配置

hp的配置算是很简单的,非常有官方的风格,基本上可以不手写,完全通过界面配置,比如:


点击 `edit config` 就可以直接通过这个+号新增,数据绑定也非常简单,直接选择对应的实体就可以了。

可以配置icon、宽度高度等,甚至支持直接配置group,group的每一个插件独立拆分成一个。

而且支持,hass、link、camera、iframe四种模式的配置,简单粗暴。


当然也支持多个page,并且由于这个针对手机做过优化,所以手机、平板展示的也不难看,更适合移动设备操作。



## tileboard
这个就更简单了,因为只是一个前端插件,所以只要配置几个前端相关的就可以,甚至都不需要重启hass。

[https://github.com/resoai/TileBoard](https://github.com/resoai/TileBoard)

去看作者写的readme.md其实已经写的比较清楚了。






我是觉得这个好看很多人想法不一样。

这个配置就一个超大的config.js通过很多js配置方式,把页面切割成多少个方块,然后指定如何填充,这个其实很简单,参考以下我的样式,以及我的config.js就可以配置。


```javascript
/*
This is an example configuration file.

COPY OR RENAME THIS FILE TO config.js.

Make sure you use real IDs from your HA entities.
*/

var CONFIG = {
    /* customTheme: specify a custom theme for your dashboard
    * Valid options: null, CUSTOM_THEMES.TRANSPARENT, CUSTOM_THEMES.MATERIAL, CUSTOM_THEMES.MOBILE, CUSTOM_THEMES.COMPACT, CUSTOM_THEMES.HOMEKIT, CUSTOM_THEMES.WINPHONE, CUSTOM_THEMES.WIN95 or a custom theme you have created
    * Default: null. Array supported
    */
    customTheme: CUSTOM_THEMES.COMPACT,

    /* transition: The transition effect used between Pages
    * Valid options: TRANSITIONS.ANIMATED, TRANSITIONS.ANIMATED_GPU, TRANSITIONS.SIMPLE
    */
    transition: TRANSITIONS.ANIMATED_GPU,

    /* tileSize: The default size (in pixels) of a tile */
    tileSize: 120,

    /* tileMargin: The default margin (in pixels) between tiles */
    tileMargin: 5,

    /* entitySize: Enum size of tile's content (SMALL, NORMAL, BIG)*/
    entitySize: ENTITY_SIZES.SMALL,

    /* groupMarginCss: CSS margin statement to override the default margin for groups */
    groupMarginCss: '10px 6px',

    /* serverUrl: The URL to your HomeAssistant server */
    serverUrl: "http://xxxx:8123",

    /* wsUrl: The URL to your HomeAssistant Websocket connection.
   * If HomeAssistant is behind SSL, replace ws:// with wss://
   */
    wsUrl: "ws://xxxx:8123/api/websocket",

    /* authToken: Optional Long live token that you can create in your HomeAssistant
   */
    authToken: null,

    /* pingConnection: Set to false disable pinging of the websocket connection.
   * Otherwise, a ping will be sent every five seconds, and if a response is not received in 3 seconds,
   * a reconnect will be attempted. If not included in the config file, setting defaults to true.
   */
    pingConnection: true,

    /* debug: Toggle for extra debugging information.
   * If enabled, will print info about state changes and entities to console.
   */
    debug: true,

    /* timeFormat: 12 for AM/PM marker, 24 for 24 hour time (default) */
    timeFormat: 24,

    /* googleApiKey: Google API key is required if you are using device tracker tiles along with Google Maps.
   * More info here: https://developers.google.com/ma ... c/usage-and-billing
   */
    googleApiKey: null,

    /* A Mapbox token is required if you are using device tracker tiles along with Mapbox.
   * More info here: https://www.mapbox.com/maps/
   */
    mapboxToken: null,

    /* mapboxStyle: Enter a style URL to change the mapbox style for device tracker tiles.
   * The format of the url is: mapbox://styles/username/style-id
   * If no style URL is entered, the style will default to mapbox/streets-v11.
   */
    mapboxStyle: null,

    /* menuPosition: LEFT (default) or BOTTOM */
    menuPosition: MENU_POSITIONS.LEFT,

    /* hideScrollbar: Hiding horizontal scrollbar */
    hideScrollbar: false,

    /* groupsAlign: Align groups HORIZONTALLY (default) or VERTICALLY */
    groupsAlign: GROUP_ALIGNS.HORIZONTALLY,

    /* events: A list of events. See documentation on Events below */
    events: [],

    /* screensaver: A digital picture frame with a clock. Appears when   
    * the dashboard has been idle
    * https://github.com/resoai/TileBo ... saver-configuration
    * (optional)
    */
    screensaver: { // optional. https://github.com/resoai/TileBo ... saver-configuration
      timeout: 300,
      // after 5 mins of inactive
      slidesTimeout: 10,
      // 10s for one slide
      styles: {
            fontSize: '40px'
      },
      leftBottom: [{
            type: SCREENSAVER_ITEMS.DATETIME
      }],
      // put datetime to the left-bottom of screensaver
      slides: [{
            bg: 'images/bg1.jpeg'
      },
      {
            bg: 'images/bg2.png',
            rightTop: [ // put text to the 2nd slide
            {
                type: SCREENSAVER_ITEMS.CUSTOM_HTML,
                html: 'Welcome to the <b>TileBoard</b>',
                styles: {
                  fontSize: '40px'
                }
            }]
      },
      {
            bg: 'images/bg3.jpg'
      }]
    },

    header: { // https://github.com/resoai/TileBoard/wiki/Header-configuration
      styles: {
            padding: '10px 80px 0',
            fontSize: '26px'
      },
      left: [{
            type: HEADER_ITEMS.DATETIME,
            dateFormat: 'EEEE, LLLL dd',
            //https://docs.angularjs.org/api/ng/filter/date
      }],
      right: [
            {
            type: HEADER_ITEMS.CUSTOM_HTML,
            html: 'Welcome to the <b>TileBoard</b>',
            styles: {
                margin: '0 0 0'
            }
      },
      {
            type: HEADER_ITEMS.WEATHER,
            styles: {
                margin: '0 0 0'
            },
            icon: '&weather.dieyuan.state',
            icons: {
                'sunny': 'clear',
                'clear': 'clear',
                'clear-night': 'nt-clear',
                'cloudy': 'cloudy',
                'rainy': 'rain',
                'hail': 'rain',
                'pouring': 'rain',
                'lightning': 'thunder',
                'lightning-rainy': 'thunder',
                'sleet': 'sleet',
                'snowy': 'snow',
                'snowy-rainy': 'snowy-rainy',
                'windy': 'hazy',
                'windy-variant': 'hazy',
                'fog': 'fog',
                'partlycloudy': 'partlycloudy',
                'partly-cloudy-night': 'nt-partlycloudy'
            },
            fields: {
                // summary: 'summary',
                temperature: '&weather.dieyuan.attributes.temperature',
                temperatureUnit: '℃',
            }
      }]
    },

    pages: [{
      title: 'Main page',
      bg: 'images/bg1.jpeg',
      icon: 'mdi-home-outline',
      // home icon
      groups: [{
            title: '天气',
            width: 2,
            height: 4,
            items: [{
                // please read README.md for more information
                // this is just an example
                position: ,
                height: 2,
                // 1 for compact
                width: 2,
                classes: ['-compact'],
                type: TYPES.WEATHER,
                id: 'weather.dieyuan',
                title: '西溪蝶园',
                state: '&weather.dieyuan.state',
                // label with weather summary (e.g. Sunny)
                icon: '&weather.dieyuan.state',
                // 天气状态定义
                icons: {
                  'sunny': 'clear',
                  'clear': 'clear',
                  'clear-night': 'nt-clear',
                  'cloudy': 'cloudy',
                  'rainy': 'rain',
                  'hail': 'rain',
                  'pouring': 'rain',
                  'lightning': 'thunder',
                  'lightning-rainy': 'thunder',
                  'sleet': 'sleet',
                  'snowy': 'snow',
                  'snowy-rainy': 'snowy-rainy',
                  'windy': 'hazy',
                  'windy-variant': 'hazy',
                  'fog': 'fog',
                  'partlycloudy': 'partlycloudy',
                  'partly-cloudy-night': 'nt-partlycloudy'
                },
                fields: { // most of that fields are optional
                  summary: 'summary',
                  temperature: '&weather.dieyuan.attributes.temperature',
                  temperatureUnit: '℃',
                  windSpeed: '&weather.dieyuan.attributes.wind_speed',
                  windSpeedUnit: '千米/小时',
                  humidity: '&weather.dieyuan.attributes.humidity',
                  humidityUnit: '%',

                  list: ['紫外线强度(0-11) ' + '&sensor.ultraviolet.state', '下雨概率 ' + '&sensor.weather_current_rain.state %', '今天气温 ' + '&sensor.weather_today_min_temp.state-&sensor.weather_today_max_temp.state ℃']
                }
            },
            {
                position: ,
                type: TYPES.WEATHER_LIST,
                width: 2,
                height: 2,
                title: '',
                id: {},
                icons: {
                  'sunny': 'clear',
                  'clear': 'clear',
                  'clear-night': 'nt-clear',
                  'cloudy': 'cloudy',
                  'rainy': 'rain',
                  'hail': 'rain',
                  'pouring': 'rain',
                  'lightning': 'thunder',
                  'lightning-rainy': 'thunder',
                  'sleet': 'sleet',
                  'snowy': 'snow',
                  'snowy-rainy': 'snowy-rainy',
                  'windy': 'hazy',
                  'windy-variant': 'hazy',
                  'fog': 'fog',
                  'partlycloudy': 'partlycloudy',
                  'partly-cloudy-night': 'nt-partlycloudy'
                },
                hideHeader: false,
                secondaryTitle: '降雨概率',
                list: .map(function(id) {
                  var forecast = "&weather.dieyuan.attributes.hourly_forecast." + id + ".temperature";
                  forecast += "℃";
                  var datetime = "&weather.dieyuan.attributes.hourly_forecast." + id + ".datetime";

                  var probable_precipitation = "&weather.dieyuan.attributes.hourly_forecast." + id + ".probable_precipitation";
                  probable_precipitation += "%";
                  return {
                        date: ((((Math.round(new Date(Date.now()).getHours() / 3)) + id) * 3) + 1) % 24 + ":00",
                        icon: "&weather.dieyuan.attributes.hourly_forecast." + id + ".condition",
                        //iconImage: null, replace icon with image
                        primary: forecast,
                        secondary: probable_precipitation
                  }
                }),
                filter: function(value) { // optional
                  return 111;
                }
            },
            {
                position: ,
                type: TYPES.WEATHER_LIST,
                width: 2,
                height: 1,
                title: '',
                id: {},
                icons: {
                  'sunny': 'clear',
                  'clear': 'clear',
                  'clear-night': 'nt-clear',
                  'cloudy': 'cloudy',
                  'rainy': 'rain',
                  'hail': 'rain',
                  'pouring': 'rain',
                  'lightning': 'thunder',
                  'lightning-rainy': 'thunder',
                  'sleet': 'sleet',
                  'snowy': 'snow',
                  'snowy-rainy': 'snowy-rainy',
                  'windy': 'hazy',
                  'windy-variant': 'hazy',
                  'fog': 'fog',
                  'partlycloudy': 'partlycloudy',
                  'partly-cloudy-night': 'nt-partlycloudy'
                },
                hideHeader: false,
                secondaryTitle: '降雨概率',
                list: .map(function(id) {
                  var forecast = "&weather.dieyuan.attributes.forecast." + id + ".templow";
                  forecast += " - &weather.dieyuan.attributes.forecast." + id + ".temperature";
                  forecast += "℃";
                  //   var datetime = "&weather.dieyuan.attributes.forecast." + id + ".datetime";
                  var probable_precipitation = "&weather.dieyuan.attributes.forecast." + id + ".probable_precipitation";
                  probable_precipitation += "%";

                  return {
                        date: function() {
                            var d = new Date(Date.now() + id * 24 * 60 * 60 * 1000);
                            //var d = new Date(Date.parse(datetime.replace(/-/g, '/')));
                            return d.toLocaleDateString('zh-Hans', {
                              weekday: 'short'
                            });
                        },
                        icon: "&weather.dieyuan.attributes.forecast." + id + ".condition",
                        //iconImage: null, replace icon with image
                        primary: forecast,
                        secondary: probable_precipitation
                  }
                })
            }

            ]
      },
      {
            title: '基础信息',
            width: 3,
            height: 4,
            items: [{
                position: ,
                width: 1,
                type: TYPES.DEVICE_TRACKER,
                id: 'device_tracker.xxx',
                // using empty object for an unknown id
                states: {
                  home: "在家",
                  not_home: "离开",
                },
                // bg: '/local/images/xxx.png'
            },{
                position: ,
                width: 1,
                type: TYPES.DEVICE_TRACKER,
                id: 'device_tracker.xxx',
                // using empty object for an unknown id
                states: {
                  home: "在家",
                  not_home: "离开",
                },
                // bg: '/local/images/xxx.png'
            },{
                position: ,
                width: 1,
                type: TYPES.DEVICE_TRACKER,
                id: 'device_tracker.xxx',
                // using empty object for an unknown id
                states: {
                  home: "在家",
                  not_home: "离开",
                },
                // bg: '/local/images/xxx.png'
            },
            {
                position: ,
                type: TYPES.DEVICE_TRACKER,
                title: '洗衣机',
                id: 'switch.plug_158d0002836ad3',
                // unit: '℃',
                // override default entity unit
                state: function (item, entity) {
                  var load_power = parseFloat(entity.attributes.load_power);
                  if (load_power > 1)
                      return "运行";
                  else
                      return "关闭";
                },
                // hidding state
                filter: function(value, item, entity) { // optional
                  return "";
                },
                bg: "/local/images/washer.png",
            },
            {
                position: ,
                type: TYPES.DEVICE_TRACKER,
                title: '烘干机',
                id: 'switch.plug_158d0002ecece4',
                state: function (item, entity) {
                  var load_power = parseFloat(entity.attributes.load_power);
                  if (load_power > 1)
                      return "运行";
                  else
                      return "关闭";
                },
                filter: function(value, item, entity) { // optional
                  return "";
                },
                bg: "/local/images/dryer.png",
            },
            {
                position: ,
                type: TYPES.DEVICE_TRACKER,
                title: '电视机',
                id: 'device_tracker.letv_2',
                states: {
                  home: "打开",
                  not_home: "关闭",
                },
                bg: "/local/images/tv.png",
            },
            {
                position: ,
                type: TYPES.SENSOR,
                title: '主卧温湿度',
                id: 'sensor.mithermometer_master_room_temperature',
                state: '湿度 ' + "&sensor.mithermometer_master_room_humidity.state" + '%',
                filter: function(value, item, entity) { // optional
                  var num = parseFloat(value);
                  return num && !isNaN(num) ? num.toFixed(1) : value;
                }
            },
            {
                position: ,
                type: TYPES.SENSOR,
                title: '机柜温湿度',
                id: 'sensor.temperature_158d00033e78c1',
                state: '湿度 ' + "&sensor.humidity_158d00033e78c1.state" + '%',
                filter: function(value, item, entity) { // optional
                  var num = parseFloat(value);
                  return num && !isNaN(num) ? num.toFixed(1) : value;
                }
            },
            {
                position: ,
                type: TYPES.SENSOR,
                title: '主卫温湿度',
                id: 'sensor.temperature_158d00036311c9',
                state: '湿度 ' + "&sensor.humidity_158d00036311c9.state" + '%',
                filter: function(value, item, entity) { // optional
                  var num = parseFloat(value);
                  return num && !isNaN(num) ? num.toFixed(1) : value;
                }
            },
            {
                position: ,
                type: TYPES.SENSOR,
                title: '父母房温湿度',
                id: 'sensor.temperature_158d0003a404db',
                state: '湿度 ' + "&sensor.humidity_158d0003a404db.state" + '%',
                filter: function(value, item, entity) { // optional
                  var num = parseFloat(value);
                  return num && !isNaN(num) ? num.toFixed(1) : value;
                }
            },
            {
                position: ,
                type: TYPES.SENSOR,
                title: '儿童房温湿度',
                id: 'sensor.temperature_158d00034f6314',
                state: '湿度 ' + "&sensor.humidity_158d00034f6314.state" + '%',
                filter: function(value, item, entity) { // optional
                  var num = parseFloat(value);
                  return num && !isNaN(num) ? num.toFixed(1) : value;
                }
            },
            {
                position: ,
                type: TYPES.SENSOR,
                title: '厨房温湿度',
                id: 'sensor.temperature_158d0003a404c1',
                state: '湿度 ' + "&sensor.humidity_158d0003a404c1.state" + '%',
                filter: function(value, item, entity) { // optional
                  var num = parseFloat(value);
                  return num && !isNaN(num) ? num.toFixed(1) : value;
                }
            },
            {
                position: ,
                type: TYPES.SENSOR,
                title: '客厅温湿度',
                id: 'sensor.siements_dock_temperature',
                state: '湿度 ' + "&sensor.siements_dock_humidity.state" + '%',
                filter: function(value, item, entity) { // optional
                  var num = parseFloat(value);
                  return num && !isNaN(num) ? num.toFixed(1) : value;
                }
            },
            {
                position: ,
                type: TYPES.SENSOR,
                title: '客厅PM2.5',
                id: 'sensor.siements_dock_pm2_5',
                state: 'PM10 ' + "&sensor.siements_dock_pm10.state" +
                   "&sensor.siements_dock_pm10.attributes.unit_of_measurement",
                filter: function(value, item, entity) { // optional
                  var num = parseFloat(value);
                  return num && !isNaN(num) ? num.toFixed(1) : value;
                }
            },
            {
                position: ,
                type: TYPES.SENSOR,
                title: '客厅甲醛',
                id: 'sensor.siements_dock_hcho',
                // state: '湿度 ' + "&sensor.siements_dock_humidity.state" + '%',
                filter: function(value, item, entity) { // optional
                  var num = parseFloat(value);
                  return num && !isNaN(num) ? num.toFixed(1) : value;
                }
            }]
      },

      {
            title: '设备控制',
            width: 2,
            height: 4,
            items: [{
                position: ,
                width: 1,
                type: TYPES.FAN,
                id: "fan.airx",
                // replace it with real string id
                state: false,
                title: '空气净化器',
            },
            {
                position: ,
                width: 1,
                type: TYPES.SWITCH,
                id: "switch.switch_door",
                // replace it with real string id (e.g. "switch.lights")
                state: true,
                title: '衣柜灯',
                subtitle: '主卧',
                states: {
                  on: "On",
                  off: "Off"
                },
                icons: {
                  on: "mdi-lightbulb-on",
                  off: "mdi-lightbulb",
                },
            },
            {
                position: ,
                type: TYPES.ALARM,
                //id: "alarm_control_panel.home_alarm",
                id: {
                  state: 'disarmed'
                },
                // replace it with real string id
                title: 'Home Alarm',
                icons: {
                  disarmed: 'mdi-bell-off',
                  pending: 'mdi-bell',
                  armed_home: 'mdi-bell-plus',
                  armed_away: 'mdi-bell',
                  triggered: 'mdi-bell-ring'
                },
                states: {
                  disarmed: 'Disarmed',
                  pending: 'Pending',
                  armed_home: 'Armed home',
                  armed_away: 'Armed away',
                  triggered: 'Triggered'
                }
            },
            {
                position: ,
                type: TYPES.SENSOR,
                title: '主卧温度',
                id: 'sensor.mithermometer_master_room_temperature',
                // unit: '℃',
                // override default entity unit
                state: true,
                // hidding state
                filter: function(value) { // optional
                  var num = parseFloat(value);
                  return num && !isNaN(num) ? num.toFixed(1) : value;
                }
            }]
      },

      ]
    },
    {
      title: 'Second page',
      bg: 'images/bg2.png',
      icon: 'mdi-numeric-2-box-outline',
      groups: [{
            title: '',
            width: 2,
            height: 3,
            items: [{
                position: ,
                width: 2,
                title: 'Short instruction',
                type: TYPES.TEXT_LIST,
                id: {},
                // using empty object for an unknown id
                state: false,
                // disable state element
                list: [{
                  title: 'Read',
                  icon: 'mdi-numeric-1-box-outline',
                  value: 'README.md'
                },
                {
                  title: 'Ask on forum',
                  icon: 'mdi-numeric-2-box-outline',
                  value: 'home-assistant.io'
                },
                {
                  title: 'Open an issue',
                  icon: 'mdi-numeric-3-box-outline',
                  value: 'github.com'
                }]
            }]
      },
      ]
    }],
}
```

如果了解js那写起来轻松愉快。

这里有一个注意点:

- state、filter这两个即可以返回一个function也可以是一个值,只有是值的时候才处理&符号数据替换
- 不要照抄我每一行,这个不复杂一行一行看一下配置,既然我是测试所以几种常见的情况我都配置了。

由于没找到合适的PAD所以这三种我都是实验,都不太深入,主要是没使用场景,设备太少了。



602293544 发表于 2019-8-26 23:37:31

抢楼时间到了学习学习

ghostist 发表于 2019-8-27 08:43:52

个人感觉...默认的界面就挺好了配合lovelace做一些小美化
floorplan目前没看到我心仪的风格我个人也没那个审美能自己画出来
说实话lianjia的那种结构图就蛮不错的,HA要是能提供个生成工具就好了主页就放一个这个 也算是特色

netsnake 发表于 2019-8-27 08:55:11

好内容,仔细学习!谢谢分享!

hanwei0708 发表于 2019-8-27 10:19:05


謝謝大大的分享

cc18253597863 发表于 2019-8-27 16:11:21

很不错的教程

telanx 发表于 2019-8-27 18:07:08

求大佬的configuration.yaml文件,里边带各种注释,很有用。谢谢大佬

wsq0387 发表于 2019-8-27 20:32:45

同求大佬的configuration.yaml文件,里边带各种注释,很有用。谢谢大佬

zoujian019 发表于 2019-8-27 21:35:01

非常好,粗略看了下,你说的用流程软件画的那个图,假设我用自己用3d渲染的效果图(假3d),可以适用吗?按我的理解,只要分好图层就一样能用你写的脚本?

新新人类 发表于 2019-8-29 00:32:00

谢谢,学习中
页: [1] 2 3 4 5
查看完整版本: 篇五:几个界面优化插件