first commit
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
import datetime
|
||||
from automation import Automation, Base # type: ignore
|
||||
|
||||
#
|
||||
# App to send email report for low balance
|
||||
#
|
||||
# Args:
|
||||
#
|
||||
# threshold = value below which battery levels are reported and email is sent
|
||||
# always_send = set to 1 to override threshold and force send
|
||||
#
|
||||
# None
|
||||
#
|
||||
# Release Notes
|
||||
#
|
||||
# Version 1.0:
|
||||
# Initial Version
|
||||
|
||||
class Balance(Base):
|
||||
def initialize(self):
|
||||
super().initialize()
|
||||
self.check_balance({"force": 1})
|
||||
self.run_daily(self.check_balance, datetime.time(10, 0, 0))
|
||||
|
||||
def check_balance(self, kwargs):
|
||||
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
|
||||
return
|
||||
|
||||
values = {}
|
||||
low = []
|
||||
for key in self.entity_ids:
|
||||
device = self.entity_ids[key]
|
||||
balance = self.get_state(device)
|
||||
if balance != None and self.is_number(balance):
|
||||
if float(balance) < self.args["threshold"]:
|
||||
low.append(device)
|
||||
values[device] = balance
|
||||
|
||||
message=""
|
||||
name = "Алтуфьево"
|
||||
if 'name' in self.args:
|
||||
name = self.args['name']
|
||||
if low:
|
||||
message += "Пожалуйста пополните баланс ({}): (< {}) \n".format(name, self.args["threshold"])
|
||||
for device in low:
|
||||
message += " - {}: {}\n".format(self.friendly_name(device), values[device])
|
||||
message += "\n\n"
|
||||
|
||||
if low or ("always_send" in self.args and self.args["always_send"] == 1) or ("force" in kwargs and kwargs["force"] == 1):
|
||||
if message != "":
|
||||
self.notify(message, name = "telegram") #name = "telegram_monster"
|
||||
|
||||
def is_number(self, s):
|
||||
try:
|
||||
float(s)
|
||||
return True
|
||||
except ValueError:
|
||||
return False
|
||||
@@ -0,0 +1,30 @@
|
||||
#################################
|
||||
# SENSOR BATTERY LOW REMINDER #
|
||||
#################################
|
||||
balance_low_report:
|
||||
class: Balance
|
||||
module: balance
|
||||
constraint: input_boolean.balance_report
|
||||
name: Алтуфьево
|
||||
entity_ids:
|
||||
mosenergosbyt_balance: sensor.power_mosenergosbyt_balance
|
||||
epd_balance: sensor.epd_balance
|
||||
always_send: 0
|
||||
threshold: -100
|
||||
notify: telegram
|
||||
global_dependencies:
|
||||
- globals
|
||||
|
||||
balance_low_report_belorechenskaya:
|
||||
class: Balance
|
||||
module: balance
|
||||
constraint: input_boolean.balance_report
|
||||
name: Белореченская
|
||||
entity_ids:
|
||||
mosenergosbyt_balance: sensor.power_mosenergosbyt_belorechenskaya_balance
|
||||
epd_balance: sensor.epd_balance_belorechenskaya
|
||||
always_send: 0
|
||||
threshold: -100
|
||||
notify: telegram
|
||||
global_dependencies:
|
||||
- globals
|
||||
@@ -0,0 +1,58 @@
|
||||
import appdaemon.plugins.hass.hassapi as hass
|
||||
import datetime
|
||||
|
||||
#
|
||||
# App to send email report for devices running low on battery
|
||||
#
|
||||
# Args:
|
||||
#
|
||||
# threshold = value below which battery levels are reported and email is sent
|
||||
# always_send = set to 1 to override threshold and force send
|
||||
#
|
||||
# None
|
||||
#
|
||||
# Release Notes
|
||||
#
|
||||
# Version 1.0:
|
||||
# Initial Version
|
||||
|
||||
class Battery(hass.Hass):
|
||||
|
||||
def initialize(self):
|
||||
#self.check_batteries({"force": 1})
|
||||
time = datetime.time(10, 0, 0)
|
||||
self.run_daily(self.check_batteries, time)
|
||||
# self.check_batteries(None)
|
||||
|
||||
def check_batteries(self, kwargs):
|
||||
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
|
||||
return
|
||||
|
||||
devices = self.get_state()
|
||||
values = {}
|
||||
low = []
|
||||
for deviceName in devices:
|
||||
device = devices[deviceName]
|
||||
if device == None:
|
||||
continue
|
||||
battery = None
|
||||
if "attributes" in device:
|
||||
if "battery" in device["attributes"]:
|
||||
battery = device["attributes"]["battery"]
|
||||
if "battery_level" in device["attributes"]:
|
||||
battery = device["attributes"]["battery_level"]
|
||||
if battery != None:
|
||||
if battery < self.args["threshold"] and battery != 0:
|
||||
low.append(deviceName)
|
||||
values[deviceName] = battery
|
||||
|
||||
message=""
|
||||
if low:
|
||||
message += "У следующих датчиков садится батарея: (< {}) \n".format(self.args["threshold"])
|
||||
for device in low:
|
||||
message += "{}: {}%\n".format(self.friendly_name(device), values[device])
|
||||
message += "\n\n"
|
||||
|
||||
if low or ("always_send" in self.args and self.args["always_send"] == 1) or ("force" in kwargs and kwargs["force"] == 1):
|
||||
if message != "":
|
||||
self.notify(message, name = "telegram")
|
||||
@@ -0,0 +1,12 @@
|
||||
#################################
|
||||
# SENSOR BATTERY LOW REMINDER #
|
||||
#################################
|
||||
sensor_battery_low_report:
|
||||
class: Battery
|
||||
module: battery
|
||||
constraint: input_boolean.battery_report
|
||||
always_send: 0
|
||||
threshold: 7
|
||||
notify: telegram
|
||||
global_dependencies:
|
||||
- globals
|
||||
@@ -0,0 +1,59 @@
|
||||
import appdaemon.plugins.hass.hassapi as hass
|
||||
import datetime
|
||||
|
||||
#
|
||||
# App to send email report for devices running low on battery
|
||||
#
|
||||
# Args:
|
||||
#
|
||||
# threshold = value below which battery levels are reported and email is sent
|
||||
# always_send = set to 1 to override threshold and force send
|
||||
#
|
||||
# None
|
||||
#
|
||||
# Release Notes
|
||||
#
|
||||
# Version 1.0:
|
||||
# Initial Version
|
||||
|
||||
class Flower(hass.Hass):
|
||||
|
||||
def initialize(self):
|
||||
#self.check_batteries({"force": 1})
|
||||
time = datetime.time(21, 0, 0)
|
||||
self.run_daily(self.check_flowers, time)
|
||||
# self.log('---------------------')
|
||||
# self.check_flowers([])
|
||||
|
||||
def check_flowers(self, kwargs):
|
||||
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
|
||||
return
|
||||
|
||||
devices = self.get_state()
|
||||
values = {}
|
||||
low = []
|
||||
for deviceName in devices:
|
||||
device = devices[deviceName]
|
||||
if device == None:
|
||||
continue
|
||||
if '_soil_moisture' not in deviceName or 'avocado' not in deviceName:
|
||||
continue
|
||||
# self.log('found: {}'.format(device))
|
||||
|
||||
moisture = int(device['state'])
|
||||
if moisture != None:
|
||||
if moisture < self.args["threshold"] and moisture != 0:
|
||||
low.append(deviceName)
|
||||
values[deviceName] = moisture
|
||||
|
||||
message=""
|
||||
if low:
|
||||
message += "Пора полить цветочки: (< {}) \n".format(self.args["threshold"])
|
||||
for device in low:
|
||||
message += "{}: {}%\n".format(self.friendly_name(device), values[device])
|
||||
message += "\n\n"
|
||||
|
||||
if low or ("always_send" in self.args and self.args["always_send"] == 1) or ("force" in kwargs and kwargs["force"] == 1):
|
||||
if message != "":
|
||||
self.notify(message, name = "telegram")
|
||||
self.call_service('media_player/play_media', entity_id=self.args['alice'], media_content_type='text', media_content_id="Пора полить цветочки.")
|
||||
@@ -0,0 +1,13 @@
|
||||
#################################
|
||||
# SENSOR BATTERY LOW REMINDER #
|
||||
#################################
|
||||
sensor_flower_moisture_low_report:
|
||||
class: Flower
|
||||
module: flower
|
||||
constraint: input_boolean.flower_report
|
||||
alice: media_player.yandex_station
|
||||
always_send: 0
|
||||
threshold: 60
|
||||
notify: telegram
|
||||
global_dependencies:
|
||||
- globals
|
||||
@@ -0,0 +1,28 @@
|
||||
import appdaemon.plugins.hass.hassapi as hass
|
||||
import datetime
|
||||
|
||||
#
|
||||
# App to send reports about unsuccessfull auths
|
||||
#
|
||||
# Args:
|
||||
#
|
||||
# threshold = value below which battery levels are reported and email is sent
|
||||
# always_send = set to 1 to override threshold and force send
|
||||
#
|
||||
# None
|
||||
#
|
||||
# Release Notes
|
||||
#
|
||||
# Version 1.0:
|
||||
# Initial Version
|
||||
|
||||
class Security(hass.Hass):
|
||||
def initialize(self):
|
||||
self.log('---------------------')
|
||||
self.listen_event_handle_list = []
|
||||
self.listen_event_handle_list.append(self.listen_state(self.state_change, 'persistent_notification.http_login', attribute='message'))
|
||||
|
||||
def state_change(self, entity, attribute, old, new, kwargs):
|
||||
notifier = self.args.get('notify', 'telegram')
|
||||
self.notify(new, name = notifier)
|
||||
self.log(new)
|
||||
@@ -0,0 +1,10 @@
|
||||
#################################
|
||||
# INVALID AUTH REPORT #
|
||||
#################################
|
||||
invalid_auth_report:
|
||||
class: Security
|
||||
module: security
|
||||
alice: media_player.yandex_station
|
||||
notify: telegram
|
||||
global_dependencies:
|
||||
- globals
|
||||
@@ -0,0 +1,57 @@
|
||||
import appdaemon.plugins.hass.hassapi as hass
|
||||
from datetime import timedelta
|
||||
import datetime
|
||||
import globals
|
||||
import requests
|
||||
|
||||
#
|
||||
# App to monitor entity update time.
|
||||
#
|
||||
# Args:
|
||||
#
|
||||
#
|
||||
# None
|
||||
#
|
||||
# Release Notes
|
||||
#
|
||||
# Version 1.0:
|
||||
# Initial Version
|
||||
|
||||
class Watchdog(hass.Hass):
|
||||
listen_event_handle_list = []
|
||||
timezone = 0
|
||||
def initialize(self):
|
||||
if not globals.check_args(self, ['check_interval', 'timeout']):
|
||||
return
|
||||
self.timer = self.run_every(self.watchdog_check, self.datetime()+timedelta(seconds=1), self.args['check_interval'])
|
||||
|
||||
def watchdog_check(self, kwargs):
|
||||
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
|
||||
self.log('disabled by constraint')
|
||||
return
|
||||
|
||||
entities = []
|
||||
if 'entity' in self.args:
|
||||
entities.append(self.args['entity'])
|
||||
if 'entities' in self.args:
|
||||
for entity in self.args['entities']:
|
||||
entities.append(entity)
|
||||
|
||||
# self.log(entities)
|
||||
for entity in entities:
|
||||
# entity = self.args['entity']
|
||||
attributes = self.get_state(entity, attribute='all')
|
||||
if not 'last_changed' in attributes:
|
||||
continue
|
||||
now = datetime.datetime.now()
|
||||
last_changed = attributes['last_changed']
|
||||
last_changed_date = datetime.datetime.strptime(last_changed, '%Y-%m-%dT%H:%M:%S.%f+00:00') + timedelta(hours=self.timezone)
|
||||
time_diff = now - last_changed_date
|
||||
|
||||
# self.log('{}: {}, {}, {} (now: {})'.format(entity, last_changed, last_changed_date, time_diff, now))
|
||||
if time_diff.seconds > self.args['timeout']:
|
||||
self.log('Entity {} was changed {} seconds ago.'.format(entity, time_diff.seconds))
|
||||
|
||||
friendly_name = self.friendly_name(entity)
|
||||
message = "Датчик {} ({}) не обновлялся в течении {} секунд.".format(friendly_name, entity, self.args['timeout'])
|
||||
self.notify(message, name = self.args.get('notify', "telegram"))
|
||||
@@ -0,0 +1,13 @@
|
||||
# uptime_watchdog:
|
||||
# class: Watchdog
|
||||
# module: watchdog
|
||||
# constraint: input_boolean.watchdog_report
|
||||
# entities:
|
||||
# - sensor.uptime_drink_filter
|
||||
# - sensor.uptime_sls
|
||||
# - sensor.uptime_watercontrol
|
||||
# check_interval: 60
|
||||
# timeout: 900
|
||||
# notify: telegram_monster
|
||||
# global_dependencies:
|
||||
# - globals
|
||||
@@ -0,0 +1,109 @@
|
||||
import appdaemon.plugins.hass.hassapi as hass
|
||||
import datetime
|
||||
import globals
|
||||
|
||||
#
|
||||
# App to send notifications when counters state needs attention
|
||||
#
|
||||
# Args:
|
||||
#
|
||||
#
|
||||
# None
|
||||
#
|
||||
# Release Notes
|
||||
#
|
||||
# Version 1.0:
|
||||
# Initial Version
|
||||
|
||||
class WaterCountersAlarm(hass.Hass):
|
||||
checkup_threasold = 31
|
||||
send_threasold = 31
|
||||
|
||||
def initialize(self):
|
||||
if not globals.check_args(self, ['checkup_threasold', 'send_threasold']):
|
||||
return
|
||||
self.checkup_threasold = self.args['checkup_threasold']
|
||||
self.send_threasold = self.args['send_threasold']
|
||||
|
||||
self.check_send_dates({"force": 1})
|
||||
self.run_daily(self.check_checkup_dates, datetime.time(10, 0, 0))
|
||||
self.run_daily(self.check_send_dates, datetime.time(10, 1, 0))
|
||||
#self.check_checkup_dates([])
|
||||
|
||||
def check_send_dates(self, kwargs):
|
||||
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
|
||||
return
|
||||
devices = self.get_state()
|
||||
if devices == None:
|
||||
return
|
||||
values = {}
|
||||
send_devices = []
|
||||
for deviceName in devices:
|
||||
device = devices[deviceName]
|
||||
if (device == None):
|
||||
continue
|
||||
send_date = None
|
||||
if "attributes" in device:
|
||||
if "date" in device["attributes"]:
|
||||
send_date = device["attributes"]["date"]
|
||||
if send_date != None:
|
||||
self.log('found device {} with send date {}'.format(deviceName, send_date))
|
||||
if send_date == "":
|
||||
send_devices.append(deviceName)
|
||||
else:
|
||||
send_date_date = None
|
||||
if '-' in send_date:
|
||||
send_date_date = datetime.datetime.strptime(send_date, '%Y-%m-%d')
|
||||
else:
|
||||
send_date_date = datetime.datetime.strptime(send_date, '%d.%m.%Y')
|
||||
if send_date_date < (datetime.datetime.now() - datetime.timedelta(days=self.send_threasold)):
|
||||
send_devices.append(deviceName)
|
||||
values[deviceName] = send_date
|
||||
|
||||
message=""
|
||||
if send_devices:
|
||||
message += "ВНИМАНИЕ! У вас есть счетчики, показания по которым давно не передавались:\n"
|
||||
for device in send_devices:
|
||||
message += "- {}: {}\n".format(self.friendly_name(device), values[device])
|
||||
message += "\n\n"
|
||||
|
||||
if send_devices or ("always_send" in self.args and self.args["always_send"] == 1) or ("force" in kwargs and kwargs["force"] == 1):
|
||||
if message != "":
|
||||
self.notify(message, name = "telegram")
|
||||
|
||||
def check_checkup_dates(self, kwargs):
|
||||
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
|
||||
return
|
||||
|
||||
entities = self.get_state()
|
||||
if entities == None:
|
||||
return
|
||||
|
||||
values = {}
|
||||
checkup_devices = []
|
||||
for entity_id in entities:
|
||||
entity = entities[entity_id]
|
||||
if entity == None:
|
||||
# self.log('not found {} in entities list.'.format(entity_id))
|
||||
continue
|
||||
checkup = None
|
||||
if "attributes" in entity:
|
||||
if "checkup" in entity["attributes"]:
|
||||
checkup = entity["attributes"]["checkup"]
|
||||
if checkup != None:
|
||||
self.log('found device {} with checkup date {}'.format(entity_id, checkup))
|
||||
checkup_date = datetime.datetime.strptime(checkup, '%Y-%m-%d')
|
||||
if (checkup_date - datetime.timedelta(days=self.checkup_threasold)) < datetime.datetime.now():
|
||||
checkup_devices.append(entity_id)
|
||||
values[entity_id] = checkup
|
||||
|
||||
message=""
|
||||
if checkup_devices:
|
||||
message += "ВНИМАНИЕ! У вас есть счетчик, нуждающийся в поверке:\n"
|
||||
for device in checkup_devices:
|
||||
message += "- {}: {}\n".format(self.friendly_name(device), values[device])
|
||||
message += "\n\n"
|
||||
|
||||
if checkup_devices or ("always_send" in self.args and self.args["always_send"] == 1) or ("force" in kwargs and kwargs["force"] == 1):
|
||||
if message != "":
|
||||
self.notify(message, name = "telegram")
|
||||
@@ -0,0 +1,11 @@
|
||||
#################################
|
||||
# WATER COUNTERS ALARM #
|
||||
#################################
|
||||
water_counters:
|
||||
class: WaterCountersAlarm
|
||||
module: water_counters
|
||||
constraint: input_boolean.water_counters_report
|
||||
checkup_threasold: 31
|
||||
send_threasold: 31
|
||||
global_dependencies:
|
||||
- globals
|
||||
Reference in New Issue
Block a user