From 7a32cb74dae31b8cad723f1229a5e1065fe83692 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 6 Nov 2019 09:20:11 +0300 Subject: [PATCH] water action fixes --- appdaemon/docker/Dockerfile | 9 ++-- appdaemon/settings/appdaemon.yaml | 16 ++++--- .../apps/alarm_clock/alarm_clock_action.py | 3 +- .../apps/alarm_clock/alarm_clock_prealarm.py | 3 +- appdaemon/settings/apps/doorbells/doorbell.py | 4 +- appdaemon/settings/apps/light/lightcontrol.py | 11 +++++ .../settings/apps/light/lightcontrol.yaml | 6 +++ appdaemon/settings/apps/notifiers/watchdog.py | 2 +- .../apps/presence/home/water_action.py | 29 +++++++++---- .../settings/apps/sensors/mosenergosbyt.py | 2 +- appdaemon/settings/apps/sensors/mosru.py | 2 +- .../settings/apps/sensors/toilet_presence.py | 2 +- appdaemon/settings/apps/test.py | 9 +++- appdaemon/settings/apps/test.py.save | 39 ++++++++++++++++++ docker-compose.yml | 4 +- hass/settings/configuration.yaml | 15 +++---- hass/settings/configuration/fan/purifier.yaml | 4 ++ .../configuration/light/livingroom.yaml | 10 ++--- .../configuration/sensor/purifier.yaml | 7 ++++ .../template/xiaomi_socket_money_cost.yaml | 12 ++++++ .../xiaomi_socket_power_consumed.yaml | 5 ++- .../configuration/utility_meter/server.yaml | 9 ++++ hass/settings/custom_components/noolite.tgz | Bin 0 -> 10676 bytes hass/settings/ui-lovelace.yaml | 19 +++++++++ 24 files changed, 178 insertions(+), 44 deletions(-) create mode 100644 appdaemon/settings/apps/test.py.save create mode 100644 hass/settings/configuration/fan/purifier.yaml create mode 100644 hass/settings/configuration/sensor/purifier.yaml create mode 100644 hass/settings/configuration/utility_meter/server.yaml create mode 100644 hass/settings/custom_components/noolite.tgz diff --git a/appdaemon/docker/Dockerfile b/appdaemon/docker/Dockerfile index 1bd411d..106d2bf 100644 --- a/appdaemon/docker/Dockerfile +++ b/appdaemon/docker/Dockerfile @@ -1,5 +1,6 @@ -ARG VERSION -FROM acockburn/appdaemon:${VERSION} +ARG BASE_IMAGE +#FROM acockburn/appdaemon:${BASE_IMAGE} +FROM ${BASE_IMAGE} RUN pip3 install \ attrs==19.1.0 \ @@ -7,4 +8,6 @@ RUN pip3 install \ packaging==16.8 \ python-Levenshtein==0.12.0 \ voluptuous==0.11.5 \ - noolite==1.4.0 && apt-get update -y && apt-get install -y libusb-1.0-0-dev && apt-get clean + noolite==1.4.0 && \ + apk add --no-cache libusb-dev + #apt-get update && apt-get install -y libusb-1.0.0-dev && apt-get clean diff --git a/appdaemon/settings/appdaemon.yaml b/appdaemon/settings/appdaemon.yaml index 683d474..75f4609 100644 --- a/appdaemon/settings/appdaemon.yaml +++ b/appdaemon/settings/appdaemon.yaml @@ -1,17 +1,23 @@ -log: - logfile: STDOUT - errorfile: STDERR +logs: + main_log: + filename: STDOUT appdaemon: threads: 10 + latitude: !secret home_latitude + longitude: !secret home_longitude + elevation: 0 + timezone: !secret timezone api_port: 5000 api_key: !secret ha_password time_zone: !secret timezone narodmon_key: !secret narodmon_key - + + api: + plugins: HASS: type: hass ha_url: !secret ha_url #ha_key: !secret ha_password - token: !secret ha_token \ No newline at end of file + token: !secret ha_token diff --git a/appdaemon/settings/apps/alarm_clock/alarm_clock_action.py b/appdaemon/settings/apps/alarm_clock/alarm_clock_action.py index b7ad124..9087ac6 100644 --- a/appdaemon/settings/apps/alarm_clock/alarm_clock_action.py +++ b/appdaemon/settings/apps/alarm_clock/alarm_clock_action.py @@ -1,5 +1,6 @@ import appdaemon.plugins.hass.hassapi as hass import globals +import datetime # # Very special case, this will run sound 'alarm' on xiaomi gateway based on alarm clock event (alarmclock_trigger) # and stop it when sensor became active. @@ -41,7 +42,7 @@ class AlarmclockAction(hass.Hass): def alarmclock_alarm(self, event_id, event_args, kwargs): self.log('Alarm triggered!') self.volume = 10 - self.timer = self.run_every(self.timer_tick, self.datetime(), 17) + self.timer = self.run_every(self.timer_tick, self.datetime()+datetime.timedelta(seconds=15), 17) def timer_tick(self, kwargs): self.call_service("xiaomi_aqara/play_ringtone", gw_mac=self.gw_mac, ringtone_id=self.ringtone, ringtone_vol=self.volume) diff --git a/appdaemon/settings/apps/alarm_clock/alarm_clock_prealarm.py b/appdaemon/settings/apps/alarm_clock/alarm_clock_prealarm.py index 15ebb69..fc86aca 100644 --- a/appdaemon/settings/apps/alarm_clock/alarm_clock_prealarm.py +++ b/appdaemon/settings/apps/alarm_clock/alarm_clock_prealarm.py @@ -1,4 +1,5 @@ import appdaemon.plugins.hass.hassapi as hass +import datetime # # Pre alarm event. @@ -51,7 +52,7 @@ class AlarmclockPrealarm(hass.Hass): self.log('Prealarm triggered!') self.brightness = 1 self.color_temp = 588 - self.timer = self.run_every(self.timer_tick, self.datetime(), 10) + self.timer = self.run_every(self.timer_tick, self.datetime()+datetime.timedelta(seconds=15), 10) def timer_tick(self, kwargs): attributes = self.get_state(self.args['entity'], attribute = "all") diff --git a/appdaemon/settings/apps/doorbells/doorbell.py b/appdaemon/settings/apps/doorbells/doorbell.py index dbc6fbf..f454da9 100644 --- a/appdaemon/settings/apps/doorbells/doorbell.py +++ b/appdaemon/settings/apps/doorbells/doorbell.py @@ -39,11 +39,11 @@ class Doorbell(hass.Hass): self.notify("Звонок в дверь!!!", name = self.args['notify']) result = self.send_video() - def send_video(self): + def send_video(self): file = '/config/www/doorbell_video.mp4' if os.path.exists(file): os.remove(file) - + self.call_service("stream/record", stream_source=self.args['rtsp'], filename=file, duration=10) self.timer = self.run_in(self.run_in_send_video, 20, file=file) diff --git a/appdaemon/settings/apps/light/lightcontrol.py b/appdaemon/settings/apps/light/lightcontrol.py index 44232c3..77021dd 100644 --- a/appdaemon/settings/apps/light/lightcontrol.py +++ b/appdaemon/settings/apps/light/lightcontrol.py @@ -34,6 +34,17 @@ class LightControl(hass.Hass): # self.log('Sun is up, and we will turn it only after sundown.') return + vacuum_state = "docked" + ha_panel_state = "" + if "vacuum" in self.args: + vacuum_state = self.get_state(self.args["vacuum"]) + if "ha_panel" in self.args: + ha_panel_state = self.get_state(self.args["ha_panel"]) + #Если работает пылесос и сработал датчик движения + if ha_panel_state == "armed_away" and vacuum_state == 'cleaning': + self.log('Motion sensor is triggered, but vacuum is cleaning.') + return + #sensor is off if new == 'off' and old == 'on': self.log('Sensor is off - running timer for {}s.'.format(self.args['timeout'])) diff --git a/appdaemon/settings/apps/light/lightcontrol.yaml b/appdaemon/settings/apps/light/lightcontrol.yaml index d0a586e..b4d4568 100644 --- a/appdaemon/settings/apps/light/lightcontrol.yaml +++ b/appdaemon/settings/apps/light/lightcontrol.yaml @@ -8,6 +8,8 @@ light_control_mainroom: control_entity: group.mainroom_light timeout: 60 constraint: input_boolean.mainroom_light_control + ha_panel: alarm_control_panel.ha_alarm + vacuum: vacuum.xiaomi_vacuum_cleaner global_dependencies: - globals @@ -18,6 +20,8 @@ light_control_kitchen: control_entity: group.kitchen_light timeout: 300 constraint: input_boolean.kitchen_light_control + ha_panel: alarm_control_panel.ha_alarm + vacuum: vacuum.xiaomi_vacuum_cleaner global_dependencies: - globals @@ -28,6 +32,8 @@ light_control_hall: control_entity: group.hall_light timeout: 120 constraint: input_boolean.hall_light_control + ha_panel: alarm_control_panel.ha_alarm + vacuum: vacuum.xiaomi_vacuum_cleaner global_dependencies: - globals diff --git a/appdaemon/settings/apps/notifiers/watchdog.py b/appdaemon/settings/apps/notifiers/watchdog.py index 7243027..564e51b 100644 --- a/appdaemon/settings/apps/notifiers/watchdog.py +++ b/appdaemon/settings/apps/notifiers/watchdog.py @@ -23,7 +23,7 @@ class Watchdog(hass.Hass): def initialize(self): if not globals.check_args(self, ['entity','update_interval', 'timeout']): return - self.timer = self.run_every(self.watchdog_check, self.datetime(), self.args['update_interval']) + self.timer = self.run_every(self.watchdog_check, self.datetime()+timedelta(seconds=10), self.args['update_interval']) def watchdog_check(self, kwargs): if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']): diff --git a/appdaemon/settings/apps/presence/home/water_action.py b/appdaemon/settings/apps/presence/home/water_action.py index da81131..e69088d 100644 --- a/appdaemon/settings/apps/presence/home/water_action.py +++ b/appdaemon/settings/apps/presence/home/water_action.py @@ -1,4 +1,5 @@ import appdaemon.plugins.hass.hassapi as hass +import datetime # # Water control application. @@ -16,6 +17,8 @@ import appdaemon.plugins.hass.hassapi as hass class WaterValveControl(hass.Hass): standby_power_limit = 15 + current_wait_cycle = 0 + wait_cycles = 3 timer = None listen_event_handle_list = [] timers = [] @@ -51,7 +54,7 @@ class WaterValveControl(hass.Hass): device_names += self.friendly_name(device) self.notify('В доме остались требующие воды устройства ({}), подача воды не будет отключена.'.format(device_names), name = self.args['notify']) self.cancel_current_timer() - self.timers.append(self.run_every(self.wait_when_device_is_done, self.datetime(), 5*60)) + self.timers.append(self.run_every(self.wait_when_device_is_done, self.datetime()+datetime.timedelta(seconds=5), 5*60)) else: self.turn_off(self.args['water_valve']) for device in self.args['water_devices']: @@ -62,13 +65,23 @@ class WaterValveControl(hass.Hass): return powered_on = self.get_turned_on_devices() self.log('still powered on: {}'.format(powered_on)) - if (len(powered_on) == 0): - # self.turn_off(self.args['water_valve']) - # for device in self.args['water_devices']: - # self.turn_off(device) - self.notify('Устройства требующие воды закончили свою работу.', name = self.args['notify']) + if len(powered_on) == 1: + self.current_wait_cycle = 0 + elif len(powered_on) == 0 and self.current_wait_cycle=self.wait_cycles: + self.current_wait_cycle = 0 + self.notify('Устройства требующие воды закончили свою работу, отключаю подачу воды.', name = self.args['notify']) + self.turn_off_water_devices() self.cancel_current_timer() + def turn_off_water_devices(): + self.log("Turning off water devices.") + self.turn_off(self.args['water_valve']) + for device in self.args['water_devices']: + self.turn_off(device) + def get_turned_on_devices(self): powered_on_devices = [] devices = self.args['water_devices'] @@ -80,8 +93,8 @@ class WaterValveControl(hass.Hass): if 'load_power' not in attributes: continue load_power = attributes['load_power'] - self.log('{} load power is: {}'.format(device, load_power)) - if state == 'on' and load_power < self.standby_power_limit: + self.log('{} state: {}, load power is: {}'.format(device, state, load_power)) + if state == 'off' or load_power < self.standby_power_limit: continue powered_on_devices.append(device) return powered_on_devices diff --git a/appdaemon/settings/apps/sensors/mosenergosbyt.py b/appdaemon/settings/apps/sensors/mosenergosbyt.py index 0692dac..dbae8df 100644 --- a/appdaemon/settings/apps/sensors/mosenergosbyt.py +++ b/appdaemon/settings/apps/sensors/mosenergosbyt.py @@ -24,7 +24,7 @@ class MosEnergoSbytSender(Automation): class MosEnergoSbytUpdater(Automation): def initialize(self): super().initialize() - self.timer = self.run_every(self.update_sensors, self.datetime(), 1*60*60) + self.timer = self.run_every(self.update_sensors, self.datetime()+timedelta(seconds=10), 1*60*60) # self.send_mosenergosbyt_counters({}) def update_sensors(self, args) -> None: diff --git a/appdaemon/settings/apps/sensors/mosru.py b/appdaemon/settings/apps/sensors/mosru.py index 32c1e8a..7d67c2c 100644 --- a/appdaemon/settings/apps/sensors/mosru.py +++ b/appdaemon/settings/apps/sensors/mosru.py @@ -161,7 +161,7 @@ class PowerCounterSensor(Automation): class EpdBalanceSensor(Automation): def initialize(self): super().initialize() - self.timer = self.run_every(self.update_sensors, self.datetime(), 1*60*60) + self.timer = self.run_every(self.update_sensors, self.datetime()+timedelta(seconds=40), 1*60*60) def update_sensors(self, args) -> None: if 'epd_balance' in self.entity_ids: diff --git a/appdaemon/settings/apps/sensors/toilet_presence.py b/appdaemon/settings/apps/sensors/toilet_presence.py index be4d709..fd08267 100644 --- a/appdaemon/settings/apps/sensors/toilet_presence.py +++ b/appdaemon/settings/apps/sensors/toilet_presence.py @@ -32,7 +32,7 @@ class ToiletPresence(hass.Hass): def distance_changed(self, entity, attribute, old, new, kwargs): distance = int(new) state = "" - if (distance > 1000 or distance < 850): + if (distance > 1100 or distance < 750): self.timers_off() self.timers.append(self.run_in(self.run_in_presense_off, self.presence_timeout)) self.log('re-setting timer for {}s.'.format(self.presence_timeout)) diff --git a/appdaemon/settings/apps/test.py b/appdaemon/settings/apps/test.py index 207a745..c37ebd3 100644 --- a/appdaemon/settings/apps/test.py +++ b/appdaemon/settings/apps/test.py @@ -1,6 +1,10 @@ +# -*- coding: utf-8 -*- import appdaemon.plugins.hass.hassapi as hass from notification import send_notification import datetime +import sys, locale +import logging, codecs +#import unicode # from automation import Automation # type: ignore """ @@ -10,7 +14,8 @@ Arguments: """ class Test(hass.Hass): def initialize(self) -> None: - self.log('test') + self.log(u"Привет") + self.log(str(u'ô')) # id = send_notification( # self, targets="telegram_monster", message="Repeated message", title="title", when=datetime.datetime.now(), interval=10, iterations=2 # ) @@ -23,4 +28,4 @@ class Test(hass.Hass): self.log('terminate') # for listen_event_handle in self.listen_event_handle_list: # self.cancel_listen_event(listen_event_handle) - \ No newline at end of file + diff --git a/appdaemon/settings/apps/test.py.save b/appdaemon/settings/apps/test.py.save new file mode 100644 index 0000000..6df9d26 --- /dev/null +++ b/appdaemon/settings/apps/test.py.save @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +import appdaemon.plugins.hass.hassapi as hass +from notification import send_notification +import datetime +import sys, locale +import logging +#import unicode +# from automation import Automation # type: ignore + +""" +Monitor events and output changes to the verbose_log. Nice for debugging purposes. +Arguments: + - events: List of events to monitor +""" +class Test(hass.Hass): + def initialize(self) -> None: + root_logger= logging.getLogger() + root_logger.setLevel(logging.DEBUG) # or whatever + handler = logging.FileHandler('test.log', 'w', 'utf-8') # or whatever + formatter = logging.Formatter('%(name)s %(message)s') # or whatever + handler.setFormatter(formatter) # Pass handler as a parameter, not assign + root_logger.addHandler(handler) + UTF8Writer = codecs.getwriter('utf8') + sys.stdout = UTF8Writer(sys.stdout.buffer) + self.log(u"Привет") + self.log(str(u'ô')) + # id = send_notification( + # self, targets="telegram_monster", message="Repeated message", title="title", when=datetime.datetime.now(), interval=10, iterations=2 + # ) + # self.log("id:{}".format(id)) + # id = send_notification( + # self, targets="telegram_monster", message="Dummy", title="title" + # ) + + def terminate(self): + self.log('terminate') + # for listen_event_handle in self.listen_event_handle_list: + # self.cancel_listen_event(listen_event_handle) + diff --git a/docker-compose.yml b/docker-compose.yml index ff82df7..e61d9c7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,7 +19,7 @@ services: - /srv/mysql:/var/lib/mysql hass: - image: homeassistant/home-assistant + image: homeassistant/home-assistant:0.100.2 container_name: hass volumes: - ./hass/settings:/config @@ -46,7 +46,7 @@ services: build: context: ./appdaemon/docker args: - VERSION: 3.0.5 + BASE_IMAGE: dlashua/appdaemon:dev #acockburn/appdaemon:3.0.5 container_name: appdaemon depends_on: - hass diff --git a/hass/settings/configuration.yaml b/hass/settings/configuration.yaml index 9d29b1f..6ab1c1b 100644 --- a/hass/settings/configuration.yaml +++ b/hass/settings/configuration.yaml @@ -23,6 +23,8 @@ http: trusted_proxies: - 172.19.0.0/24 +# noolite: + # Enables the frontend frontend: lovelace: @@ -44,11 +46,12 @@ logbook: # Components automation: !include_dir_merge_list configuration/automation -apple_tv: !include_dir_merge_list configuration/appletv -alexa: !include configuration/amazon/alexa.yaml +#apple_tv: !include_dir_merge_list configuration/appletv +#alexa: !include configuration/amazon/alexa.yaml alarm_control_panel: !include_dir_merge_list configuration/alarm_control_panel binary_sensor: !include_dir_merge_list configuration/binary_sensor camera: !include_dir_merge_list configuration/camera +fan: !include_dir_merge_list configuration/fan #climate: !include_dir_merge_list configuration/climate group: !include_dir_merge_named configuration/group input_boolean: !include_dir_merge_named configuration/input/input_boolean @@ -78,10 +81,4 @@ modbus: !include configuration/modbus.yaml utility_meter: !include_dir_merge_named configuration/utility_meter speedtestdotnet: !include configuration/speedtest.yaml -yandex_smart_home: !include configuration/alice.yaml - -# fan: -# - platform: xiaomi_miio -# host: 192.168.1.14 -# token: '411cf70bb69052c0121813388f30e193' -# model: zhimi.airpurifier.mc1 +yandex_smart_home: !include configuration/alice.yaml \ No newline at end of file diff --git a/hass/settings/configuration/fan/purifier.yaml b/hass/settings/configuration/fan/purifier.yaml new file mode 100644 index 0000000..1b49963 --- /dev/null +++ b/hass/settings/configuration/fan/purifier.yaml @@ -0,0 +1,4 @@ +- platform: xiaomi_miio + model: zhimi.airpurifier.mc1 + host: !secret purifier_ip + token: !secret purifier_key diff --git a/hass/settings/configuration/light/livingroom.yaml b/hass/settings/configuration/light/livingroom.yaml index ee8becc..6ef0c69 100644 --- a/hass/settings/configuration/light/livingroom.yaml +++ b/hass/settings/configuration/light/livingroom.yaml @@ -1,6 +1,4 @@ -# - platform: noolite -# channel: 0 -# name: "salt_lamp" -# scan_interval: 60 -# type: dimmer -# mode: noolite \ No newline at end of file +# - platform: noolite +# tx_channel: 1 +# friendly_name: "salt_lamp" +# dimmable: true \ No newline at end of file diff --git a/hass/settings/configuration/sensor/purifier.yaml b/hass/settings/configuration/sensor/purifier.yaml new file mode 100644 index 0000000..4488159 --- /dev/null +++ b/hass/settings/configuration/sensor/purifier.yaml @@ -0,0 +1,7 @@ + - platform: template + sensors: + xiaomi_airpurifier_air_quality_pm25: + friendly_name: "Air quality" + value_template: "{{ state_attr('fan.xiaomi_miio_device', 'aqi') }}" + unit_of_measurement: "μg/m³" + icon_template: "mdi:weather-fog" \ No newline at end of file diff --git a/hass/settings/configuration/sensor/template/xiaomi_socket_money_cost.yaml b/hass/settings/configuration/sensor/template/xiaomi_socket_money_cost.yaml index e5ffa90..09ad36a 100644 --- a/hass/settings/configuration/sensor/template/xiaomi_socket_money_cost.yaml +++ b/hass/settings/configuration/sensor/template/xiaomi_socket_money_cost.yaml @@ -40,6 +40,10 @@ friendly_name: "Фитолампа в мес." unit_of_measurement: '₽' value_template: "{{ (states('sensor.fitolamp_monthly') | float * (states('sensor.power_cost') | float)) | round(2) }}" + server_money_monthly: + friendly_name: "Сервер в мес." + unit_of_measurement: '₽' + value_template: "{{ (states('sensor.server_monthly') | float * (states('sensor.power_cost') | float)) | round(2) }}" power_money_t1_monthly: friendly_name: "Т1 в мес." unit_of_measurement: '₽' @@ -98,6 +102,10 @@ friendly_name: "Фитолампа в день" unit_of_measurement: '₽' value_template: "{{ (states('sensor.fitolamp_daily') | float * (states('sensor.power_cost') | float)) | round(2) }}" + server_money_daily: + friendly_name: "Сервер в день" + unit_of_measurement: '₽' + value_template: "{{ (states('sensor.server_daily') | float * (states('sensor.power_cost') | float)) | round(2) }}" counter_hot_money_hourly: friendly_name: "Горячая в час" @@ -139,3 +147,7 @@ friendly_name: "Фитолампа в час" unit_of_measurement: '₽' value_template: "{{ (states('sensor.fitolamp_hourly') | float * (states('sensor.power_cost') | float)) | round(2) }}" + server_money_hourly: + friendly_name: "Сервер в час" + unit_of_measurement: '₽' + value_template: "{{ (states('sensor.server_hourly') | float * (states('sensor.power_cost') | float)) | round(2) }}" diff --git a/hass/settings/configuration/sensor/template/xiaomi_socket_power_consumed.yaml b/hass/settings/configuration/sensor/template/xiaomi_socket_power_consumed.yaml index 8e06ac2..14de93e 100644 --- a/hass/settings/configuration/sensor/template/xiaomi_socket_power_consumed.yaml +++ b/hass/settings/configuration/sensor/template/xiaomi_socket_power_consumed.yaml @@ -28,4 +28,7 @@ friendly_name: "Фитолампа потреблено" unit_of_measurement: 'kWh' value_template: "{{ state_attr('switch.plug_158d0002924779', 'power_consumed') / 1000 }}" - \ No newline at end of file + server_consumed: + friendly_name: "Сервер потреблено" + unit_of_measurement: 'kWh' + value_template: "{{ state_attr('switch.plug_158d00026ea017', 'power_consumed') / 1000 }}" \ No newline at end of file diff --git a/hass/settings/configuration/utility_meter/server.yaml b/hass/settings/configuration/utility_meter/server.yaml new file mode 100644 index 0000000..5370849 --- /dev/null +++ b/hass/settings/configuration/utility_meter/server.yaml @@ -0,0 +1,9 @@ +server_hourly: + source: sensor.server_consumed + cycle: hourly +server_daily: + source: sensor.server_consumed + cycle: daily +server_monthly: + source: sensor.server_consumed + cycle: monthly diff --git a/hass/settings/custom_components/noolite.tgz b/hass/settings/custom_components/noolite.tgz new file mode 100644 index 0000000000000000000000000000000000000000..a27fde1de0c17c1c00fc47344b82e4baee998ff8 GIT binary patch literal 10676 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 a_!&RrXZ(zx@iTs2{P`!+Rg5|Spa1~nJHJi< literal 0 HcmV?d00001 diff --git a/hass/settings/ui-lovelace.yaml b/hass/settings/ui-lovelace.yaml index d39888e..46f7c99 100644 --- a/hass/settings/ui-lovelace.yaml +++ b/hass/settings/ui-lovelace.yaml @@ -22,14 +22,17 @@ views: entities: - sensor.temperature_158d0001149b3c - sensor.humidity_158d0001149b3c + - sensor.xiaomi_airpurifier_air_quality_pm25 - light.yeelight_color1_34ce008fe328 - light.yeelight_color1_286c071065c7 - light.yeelight_mono1_34ce0087ff33 - light.yeelight_mono1_f0b4290e5444 - light.yeelight_mono1_f0b429a8f6df + # - light.salt_lamp - cover.curtain_158d0002b0c46a - switch.plug_158d0001104a0c - switch.plug_158d00010dd98d + - fan.xiaomi_miio_device - climate.living_room - type: entities title: "Кухня" @@ -285,6 +288,16 @@ views: - sensor.fitolamp_money_hourly - sensor.fitolamp_money_daily - sensor.fitolamp_money_monthly + - type: entities + title: "Сервер" + show_header_toggle: false + entities: + - sensor.server_hourly + - sensor.server_daily + - sensor.server_monthly + - sensor.server_money_hourly + - sensor.server_money_daily + - sensor.server_money_monthly - type: entities title: "Теория трехтарифника" show_header_toggle: false @@ -296,6 +309,12 @@ views: - sensor.power_money_t2_monthly - sensor.power_money_t3_monthly - sensor.power_theory_money_monthly + - type: history-graph + title: Качество воздуха + hours_to_show: 80 + refresh_interval: 60 + entities: + - sensor.xiaomi_airpurifier_air_quality_pm25 - title: "Настройки" icon: mdi:settings cards: