From 3bedcbdc20a2b2f2415f97c77af3157b0b6568c2 Mon Sep 17 00:00:00 2001 From: Mahasri Kalavala Date: Tue, 29 Nov 2022 19:50:52 -0500 Subject: [PATCH] cleaned up, and updated to latest version. --- .gitignore | 15 +- CONTRIBUTING.md | 1 - configuration.yaml | 45 +- .../image_processing/__init__.py | 0 custom_components/image_processing/tagbox.pyx | 179 -- .../image_processing/tensorflow.pyx | 347 ---- custom_components/life365/__init__.py | 0 custom_components/life365/sensor.py | 267 --- custom_components/paloalto/__init__.py | 0 custom_components/paloalto/sensor.py | 269 --- custom_components/telegram_bot/__init__.py | 988 ++++++++++ custom_components/telegram_bot/broadcast.py | 17 + custom_components/telegram_bot/manifest.json | 11 + custom_components/telegram_bot/polling.py | 99 + custom_components/telegram_bot/services.yaml | 840 +++++++++ custom_components/telegram_bot/webhooks.py | 107 ++ custom_components/udp/__init__.py | 0 custom_components/udp/udp.py | 141 -- logging.yaml | 7 +- lovelace/00_myhome_view.yaml | 245 ++- lovelace/01_lights_view.yaml | 122 +- lovelace/03_camera_view.yaml | 162 +- lovelace/05_tensorflow_view.yaml | 14 +- lovelace/06_tesla_view.yaml | 2 +- lovelace/07_system_view.yaml | 18 +- lovelace/08_multimedia_view.yaml | 42 +- lovelace/09_settings_view.yaml | 82 +- lovelace/10_raspberrypi_view.yaml | 94 - lovelace/11_scripts_view.yaml | 28 - lovelace/12_automations_view.yaml | 36 - lovelace/13_qnap_view.yaml | 16 +- lovelace/15_3d_printer.yaml | 10 +- mos_sub.py | 82 - motion_mqtt.py | 31 - packages/3dprinting.yaml | 506 +++--- packages/aroma.yaml | 113 -- packages/batteries.yaml | 890 ++++----- packages/cameras.yaml | 130 +- packages/cameras_machinebox.yaml | 409 ----- packages/daily_routines.yaml | 25 +- packages/door_sensors.yaml | 64 +- packages/hdmi_cec.yaaml | 39 - packages/homeassistant.yaml | 46 - packages/homesecurity.yaml | 63 +- packages/led_notify.yaml | 20 +- packages/lights_switches.yaml | 62 +- packages/motion_counts.yaml | 27 - packages/motion_timers.yaml | 14 +- packages/notify.yaml | 3 - packages/paloalto.yaml | 218 --- packages/pi_admin.yaml | 552 ------ packages/pill_reminder.yaml | 21 +- packages/recycle_trash.yaml | 2 +- packages/rfswitches.yaml | 186 -- packages/scripts.yaml | 53 +- packages/season.yaml | 4 - packages/settings.yaml | 70 +- packages/tesla.yaml | 57 - packages/tv.yaml | 46 +- packages/usps.yaml | 105 -- packages/watchdog.yaml | 291 ++- packages/weather.yaml | 1 + packages/wfh.yaml | 87 - packages/xiaomi_magic_cubes.yaml | 56 +- packages/zones.yaml | 90 +- packages/zwave_batteries.yaml | 222 --- packages/zwave_sensors.yaml | 318 ---- readme.md | 298 --- secrets.example | 4 - templates/away_status.yaml | 7 +- templates/goodnight.yaml | 10 +- templates/home_status.yaml | 2 +- ui-lovelace.yaml | 14 +- wb_client.py | 24 - wb_server.py | 49 - zwcfg_0xd89c4f0c.xml | 1615 ----------------- zwscene.xml | 2 - 77 files changed, 3853 insertions(+), 7279 deletions(-) delete mode 100644 CONTRIBUTING.md delete mode 100644 custom_components/image_processing/__init__.py delete mode 100644 custom_components/image_processing/tagbox.pyx delete mode 100644 custom_components/image_processing/tensorflow.pyx delete mode 100644 custom_components/life365/__init__.py delete mode 100644 custom_components/life365/sensor.py delete mode 100644 custom_components/paloalto/__init__.py delete mode 100644 custom_components/paloalto/sensor.py create mode 100644 custom_components/telegram_bot/__init__.py create mode 100644 custom_components/telegram_bot/broadcast.py create mode 100644 custom_components/telegram_bot/manifest.json create mode 100644 custom_components/telegram_bot/polling.py create mode 100644 custom_components/telegram_bot/services.yaml create mode 100644 custom_components/telegram_bot/webhooks.py delete mode 100644 custom_components/udp/__init__.py delete mode 100644 custom_components/udp/udp.py delete mode 100644 lovelace/10_raspberrypi_view.yaml delete mode 100644 mos_sub.py delete mode 100644 motion_mqtt.py delete mode 100644 packages/aroma.yaml delete mode 100644 packages/cameras_machinebox.yaml delete mode 100644 packages/hdmi_cec.yaaml delete mode 100644 packages/paloalto.yaml delete mode 100644 packages/pi_admin.yaml delete mode 100644 packages/rfswitches.yaml delete mode 100644 packages/tesla.yaml delete mode 100644 packages/usps.yaml delete mode 100644 packages/wfh.yaml delete mode 100644 packages/zwave_batteries.yaml delete mode 100644 packages/zwave_sensors.yaml delete mode 100644 wb_client.py delete mode 100644 wb_server.py delete mode 100644 zwcfg_0xd89c4f0c.xml delete mode 100644 zwscene.xml diff --git a/.gitignore b/.gitignore index 997200c..59cb4d0 100644 --- a/.gitignore +++ b/.gitignore @@ -56,7 +56,14 @@ apps/__pycache__/*.pyc docker/streamer docker-compose.yml packages/telegram_commands.yaml -custom_components/input_label/input_labelpy -custom_components/input_label/services.yaml -custom_components/input_label/__init__.py -custom_components/input_label/manifest.json +config.yml +example.yaml +home-assistant.log.1 +home-assistant.log.fault +custom_components/input_label/* +custom_components/hacs/* +etc-pihole/* +models/* +packages/tesla.zamlx +packages/tesla.yaml +packages/zwave_sensors.yaml diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index a860077..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1 +0,0 @@ -Please contact me if you found any issues. Thank you! diff --git a/configuration.yaml b/configuration.yaml index 0c2cbc3..98dec53 100644 --- a/configuration.yaml +++ b/configuration.yaml @@ -22,8 +22,6 @@ homeassistant: - /config/www/downloads/camera/playarea/ - /config/www/downloads/camera/driveway/ - /config/www/downloads/camera/frontdoor/ - - /config/www/downloads/camera/kitchen/ - - /config/www/downloads/camera/frontroom/ - /config/www/downloads/camera/3d/ sun: @@ -35,9 +33,7 @@ discovery: frontend: -octoprint: - host: !secret octoprint_ip - api_key: !secret octoprint_key +media_source: homekit: autostart: true @@ -63,47 +59,14 @@ logger: !include logging.yaml zeroconf: system_health: -life360: - accounts: - - username: !secret life360_username - password: !secret life360_password - circles: - include: [Family] - -mqtt: - broker: !secret mqtt_server - port: !secret mqtt_port - username: !secret mqtt_username - password: !secret mqtt_password - keepalive: 60 - client_id: HA_SERVER - -sonos: - media_player: - hosts: - - !secret sonos_living_room_ip - - !secret sonos_front_room_ip - binary_sensor: - platform: workday country: US lovelace: mode: yaml - resources: - - url: /local/button-card.js - type: module # Google Calendar -google: - client_id: !secret google_client_id - client_secret: !secret google_client_secret -#emulated_hue: -# expose_by_default: false -# host_ip: !secret ha_ip_address -# listen_port: 8300 -# exposed_domains: -# - light -# - switch -# - input_boolean -# - group +# google: +# client_id: !secret google_client_id +# client_secret: !secret google_client_secret diff --git a/custom_components/image_processing/__init__.py b/custom_components/image_processing/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/custom_components/image_processing/tagbox.pyx b/custom_components/image_processing/tagbox.pyx deleted file mode 100644 index 54cc367..0000000 --- a/custom_components/image_processing/tagbox.pyx +++ /dev/null @@ -1,179 +0,0 @@ -# """ -# Search images for tagged objects via a local Tagbox instance. - -# For more details about this platform, please refer to the documentation at -# https://home-assistant.io/components/image_processing.tagbox - -# This file is stolen from @robmarkcole's repo -# """ -# import base64 -# import requests -# import logging -# import voluptuous as vol - -# from homeassistant.core import ( -# callback, split_entity_id) -# import homeassistant.helpers.config_validation as cv -# from homeassistant.components.image_processing import ( -# PLATFORM_SCHEMA, ImageProcessingEntity, ATTR_CONFIDENCE, CONF_CONFIDENCE, -# CONF_SOURCE, CONF_ENTITY_ID, CONF_NAME) -# from homeassistant.const import ( -# ATTR_ENTITY_ID, ATTR_NAME, CONF_IP_ADDRESS, CONF_PORT) -# from homeassistant.util.async_ import run_callback_threadsafe - -# _LOGGER = logging.getLogger(__name__) - -# CLASSIFIER = 'tagbox' -# EVENT_DETECT_TAG = 'image_processing.detect_tag' -# TIMEOUT = 9 - -# PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ -# vol.Required(CONF_IP_ADDRESS): cv.string, -# vol.Required(CONF_PORT): cv.port, -# }) - - -# def encode_image(image): -# """base64 encode an image stream.""" -# base64_img = base64.b64encode(image).decode('ascii') -# return base64_img - - -# def get_matched_tags(tags, confidence): -# """Return the name and rounded confidence of matched tags.""" -# return {tag['name']: tag['confidence'] -# for tag in tags if tag['confidence'] > confidence} - - -# def parse_tags(api_tags): -# """Parse the API tag data into the format required.""" -# parsed_tags = [] -# for entry in api_tags: -# tag = {} -# tag[ATTR_NAME] = entry['tag'] -# tag[ATTR_CONFIDENCE] = round(100.0*entry['confidence'], 2) -# parsed_tags.append(tag) -# return parsed_tags - - -# def post_image(url, image): -# """Post an image to the classifier.""" -# try: -# response = requests.post( -# url, -# json={"base64": encode_image(image)}, -# timeout=TIMEOUT -# ) -# return response -# except requests.exceptions.ConnectionError: -# _LOGGER.error("ConnectionError: Is %s running?", CLASSIFIER) - - -# def setup_platform(hass, config, add_devices, discovery_info=None): -# """Set up the classifier.""" -# entities = [] -# for camera in config[CONF_SOURCE]: -# entities.append(ImageProcessingTagEntity( -# config[CONF_IP_ADDRESS], -# config[CONF_PORT], -# camera[CONF_ENTITY_ID], -# camera.get(CONF_NAME), -# config[CONF_CONFIDENCE], -# )) -# add_devices(entities) - - -# class ImageProcessingTagEntity(ImageProcessingEntity): -# """Perform a tag search via a Tagbox.""" - -# def __init__(self, ip, port, camera_entity, name, confidence): -# """Init with the IP and PORT""" -# super().__init__() -# self._url_check = "http://{}:{}/{}/check".format(ip, port, CLASSIFIER) -# self._camera = camera_entity -# if name: -# self._name = name -# else: -# camera_name = split_entity_id(camera_entity)[1] -# self._name = "{} {}".format( -# CLASSIFIER, camera_name) -# self._confidence = confidence -# self.tags = [] -# self._matched = {} - -# def process_image(self, image): -# """Process an image.""" -# response = post_image(self._url_check, image) -# if response is not None: -# response_json = response.json() -# if response_json['success']: -# api_tags = response_json['tags'] + response_json['custom_tags'] -# tags = parse_tags(api_tags) -# self.process_tags(tags) -# self._matched = get_matched_tags(tags, self.confidence) -# else: -# self.tags = [] -# self._matched = {} - -# @property -# def confidence(self): -# """Return minimum confidence for send events.""" -# return self._confidence - -# @property -# def state(self): -# """Return the state of the entity.""" -# state = None - -# if len(self._matched) > 0: -# return self.tags[0][ATTR_NAME] - -# return state - -# def process_tags(self, tags): -# """Send event with detected tags and store data.""" -# run_callback_threadsafe( -# self.hass.loop, self.async_process_tags, tags).result() - -# @callback -# def async_process_tags(self, tags): -# """Send event with detected tags and store data. -# Tags are a dict in follow format: -# [ -# { -# ATTR_CONFIDENCE: 80, -# ATTR_NAME: 'people', -# }, -# ] -# This method must be run in the event loop. -# """ -# # Send events -# for tag in tags: -# tag.update({ATTR_ENTITY_ID: self.entity_id}) -# if tag[ATTR_CONFIDENCE] > self.confidence: -# self.hass.async_add_job( -# self.hass.bus.async_fire, EVENT_DETECT_TAG, tag -# ) - -# # Update entity store -# self.tags = tags - -# @property -# def camera_entity(self): -# """Return camera entity id from process pictures.""" -# return self._camera - -# @property -# def name(self): -# """Return the name of the sensor.""" -# return self._name - -# @property -# def device_state_attributes(self): -# """Return other details about the sensor state.""" -# return { -# 'tags': self.tags, -# 'total_tags': len(self.tags), -# 'matched_tags': self._matched, -# 'total_matched_tags': len(self._matched), -# } \ No newline at end of file diff --git a/custom_components/image_processing/tensorflow.pyx b/custom_components/image_processing/tensorflow.pyx deleted file mode 100644 index 41c7296..0000000 --- a/custom_components/image_processing/tensorflow.pyx +++ /dev/null @@ -1,347 +0,0 @@ -# """ -# Component that performs TensorFlow classification on images. - -# For a quick start, pick a pre-trained COCO model from: -# https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md - -# For more details about this platform, please refer to the documentation at -# https://home-assistant.io/components/image_processing.tensorflow/ -# """ -# import logging -# import sys -# import os - -# import voluptuous as vol - -# from homeassistant.components.image_processing import ( -# CONF_CONFIDENCE, CONF_ENTITY_ID, CONF_NAME, CONF_SOURCE, PLATFORM_SCHEMA, -# ImageProcessingEntity) -# from homeassistant.core import split_entity_id -# from homeassistant.helpers import template -# import homeassistant.helpers.config_validation as cv - -# REQUIREMENTS = ['numpy==1.15.3', 'pillow==5.2.0', 'protobuf==3.6.1'] - -# _LOGGER = logging.getLogger(__name__) - -# ATTR_MATCHES = 'matches' -# ATTR_SUMMARY = 'summary' -# ATTR_TOTAL_MATCHES = 'total_matches' - -# CONF_FILE_OUT = 'file_out' -# CONF_MODEL = 'model' -# CONF_GRAPH = 'graph' -# CONF_LABELS = 'labels' -# CONF_MODEL_DIR = 'model_dir' -# CONF_CATEGORIES = 'categories' -# CONF_CATEGORY = 'category' -# CONF_AREA = 'area' -# CONF_TOP = 'top' -# CONF_LEFT = 'left' -# CONF_BOTTOM = 'bottom' -# CONF_RIGHT = 'right' - -# AREA_SCHEMA = vol.Schema({ -# vol.Optional(CONF_TOP, default=0): cv.small_float, -# vol.Optional(CONF_LEFT, default=0): cv.small_float, -# vol.Optional(CONF_BOTTOM, default=1): cv.small_float, -# vol.Optional(CONF_RIGHT, default=1): cv.small_float -# }) - -# CATEGORY_SCHEMA = vol.Schema({ -# vol.Required(CONF_CATEGORY): cv.string, -# vol.Optional(CONF_AREA): AREA_SCHEMA -# }) - -# PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ -# vol.Optional(CONF_FILE_OUT, default=[]): -# vol.All(cv.ensure_list, [cv.template]), -# vol.Required(CONF_MODEL): vol.Schema({ -# vol.Required(CONF_GRAPH): cv.isfile, -# vol.Optional(CONF_LABELS): cv.isfile, -# vol.Optional(CONF_MODEL_DIR): cv.isdir, -# vol.Optional(CONF_AREA): AREA_SCHEMA, -# vol.Optional(CONF_CATEGORIES, default=[]): -# vol.All(cv.ensure_list, [vol.Any( -# cv.string, -# CATEGORY_SCHEMA -# )]) -# }) -# }) - - -# def draw_box(draw, box, img_width, -# img_height, text='', color=(255, 255, 0)): -# """Draw bounding box on image.""" -# ymin, xmin, ymax, xmax = box -# (left, right, top, bottom) = (xmin * img_width, xmax * img_width, -# ymin * img_height, ymax * img_height) -# draw.line([(left, top), (left, bottom), (right, bottom), -# (right, top), (left, top)], width=5, fill=color) -# if text: -# draw.text((left, abs(top-15)), text, fill=color) - - -# def setup_platform(hass, config, add_entities, discovery_info=None): -# """Set up the TensorFlow image processing platform.""" -# model_config = config.get(CONF_MODEL) -# model_dir = model_config.get(CONF_MODEL_DIR) \ -# or hass.config.path('tensorflow') -# labels = model_config.get(CONF_LABELS) \ -# or hass.config.path('tensorflow', 'object_detection', -# 'data', 'mscoco_label_map.pbtxt') - -# # Make sure locations exist -# if not os.path.isdir(model_dir) or not os.path.exists(labels): -# _LOGGER.error("Unable to locate tensorflow models or label map.") -# return - -# # append custom model path to sys.path -# sys.path.append(model_dir) - -# try: -# # Verify that the TensorFlow Object Detection API is pre-installed -# # pylint: disable=unused-import,unused-variable -# os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' -# import tensorflow as tf # noqa -# from object_detection.utils import label_map_util # noqa -# except ImportError: -# # pylint: disable=line-too-long -# _LOGGER.error( -# "No TensorFlow Object Detection library found! Install or compile " -# "for your system following instructions here: " -# "https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/installation.md") # noqa -# return - -# try: -# # Display warning that PIL will be used if no OpenCV is found. -# # pylint: disable=unused-import,unused-variable -# import cv2 # noqa -# except ImportError: -# _LOGGER.warning("No OpenCV library found. " -# "TensorFlow will process image with " -# "PIL at reduced resolution.") - -# # setup tensorflow graph, session, and label map to pass to processor -# # pylint: disable=no-member -# detection_graph = tf.Graph() -# with detection_graph.as_default(): -# od_graph_def = tf.GraphDef() -# with tf.gfile.GFile(model_config.get(CONF_GRAPH), 'rb') as fid: -# serialized_graph = fid.read() -# od_graph_def.ParseFromString(serialized_graph) -# tf.import_graph_def(od_graph_def, name='') - -# session = tf.Session(graph=detection_graph) -# label_map = label_map_util.load_labelmap(labels) -# categories = label_map_util.convert_label_map_to_categories( -# label_map, max_num_classes=90, use_display_name=True) -# category_index = label_map_util.create_category_index(categories) - -# entities = [] - -# for camera in config[CONF_SOURCE]: -# entities.append(TensorFlowImageProcessor( -# hass, camera[CONF_ENTITY_ID], camera.get(CONF_NAME), -# session, detection_graph, category_index, config)) - -# add_entities(entities) - - -# class TensorFlowImageProcessor(ImageProcessingEntity): -# """Representation of an TensorFlow image processor.""" - -# def __init__(self, hass, camera_entity, name, session, detection_graph, -# category_index, config): -# """Initialize the TensorFlow entity.""" -# model_config = config.get(CONF_MODEL) -# self.hass = hass -# self._camera_entity = camera_entity -# if name: -# self._name = name -# else: -# self._name = "TensorFlow {0}".format( -# split_entity_id(camera_entity)[1]) -# self._session = session -# self._graph = detection_graph -# self._category_index = category_index -# self._min_confidence = config.get(CONF_CONFIDENCE) -# self._file_out = config.get(CONF_FILE_OUT) - -# # handle categories and specific detection areas -# categories = model_config.get(CONF_CATEGORIES) -# self._include_categories = [] -# self._category_areas = {} -# for category in categories: -# if isinstance(category, dict): -# category_name = category.get(CONF_CATEGORY) -# category_area = category.get(CONF_AREA) -# self._include_categories.append(category_name) -# self._category_areas[category_name] = [0, 0, 1, 1] -# if category_area: -# self._category_areas[category_name] = [ -# category_area.get(CONF_TOP), -# category_area.get(CONF_LEFT), -# category_area.get(CONF_BOTTOM), -# category_area.get(CONF_RIGHT) -# ] -# else: -# self._include_categories.append(category) -# self._category_areas[category] = [0, 0, 1, 1] - -# # Handle global detection area -# self._area = [0, 0, 1, 1] -# area_config = model_config.get(CONF_AREA) -# if area_config: -# self._area = [ -# area_config.get(CONF_TOP), -# area_config.get(CONF_LEFT), -# area_config.get(CONF_BOTTOM), -# area_config.get(CONF_RIGHT) -# ] - -# template.attach(hass, self._file_out) - -# self._matches = {} -# self._total_matches = 0 -# self._last_image = None - -# @property -# def camera_entity(self): -# """Return camera entity id from process pictures.""" -# return self._camera_entity - -# @property -# def name(self): -# """Return the name of the image processor.""" -# return self._name - -# @property -# def state(self): -# """Return the state of the entity.""" -# return self._total_matches - -# @property -# def device_state_attributes(self): -# """Return device specific state attributes.""" -# return { -# ATTR_MATCHES: self._matches, -# ATTR_SUMMARY: {category: len(values) -# for category, values in self._matches.items()}, -# ATTR_TOTAL_MATCHES: self._total_matches -# } - -# def _save_image(self, image, matches, paths): -# from PIL import Image, ImageDraw -# import io -# img = Image.open(io.BytesIO(bytearray(image))).convert('RGB') -# img_width, img_height = img.size -# draw = ImageDraw.Draw(img) - -# # Draw custom global region/area -# if self._area != [0, 0, 1, 1]: -# draw_box(draw, self._area, -# img_width, img_height, -# "Detection Area", (0, 255, 255)) - -# for category, values in matches.items(): -# # Draw custom category regions/areas -# if (category in self._category_areas -# and self._category_areas[category] != [0, 0, 1, 1]): -# label = "{} Detection Area".format(category.capitalize()) -# draw_box(draw, self._category_areas[category], img_width, -# img_height, label, (0, 255, 0)) - -# # Draw detected objects -# for instance in values: -# label = "{0} {1:.1f}%".format(category, instance['score']) -# draw_box(draw, instance['box'], -# img_width, img_height, -# label, (255, 255, 0)) - -# for path in paths: -# _LOGGER.info("Saving results image to %s", path) -# img.save(path) - -# def process_image(self, image): -# """Process the image.""" -# import numpy as np - -# try: -# import cv2 # pylint: disable=import-error -# img = cv2.imdecode( -# np.asarray(bytearray(image)), cv2.IMREAD_UNCHANGED) -# inp = img[:, :, [2, 1, 0]] # BGR->RGB -# inp_expanded = inp.reshape(1, inp.shape[0], inp.shape[1], 3) -# except ImportError: -# from PIL import Image -# import io -# img = Image.open(io.BytesIO(bytearray(image))).convert('RGB') -# img.thumbnail((460, 460), Image.ANTIALIAS) -# img_width, img_height = img.size -# inp = np.array(img.getdata()).reshape( -# (img_height, img_width, 3)).astype(np.uint8) -# inp_expanded = np.expand_dims(inp, axis=0) - -# image_tensor = self._graph.get_tensor_by_name('image_tensor:0') -# boxes = self._graph.get_tensor_by_name('detection_boxes:0') -# scores = self._graph.get_tensor_by_name('detection_scores:0') -# classes = self._graph.get_tensor_by_name('detection_classes:0') -# boxes, scores, classes = self._session.run( -# [boxes, scores, classes], -# feed_dict={image_tensor: inp_expanded}) -# boxes, scores, classes = map(np.squeeze, [boxes, scores, classes]) -# classes = classes.astype(int) - -# matches = {} -# total_matches = 0 -# for box, score, obj_class in zip(boxes, scores, classes): -# score = score * 100 -# boxes = box.tolist() - -# # Exclude matches below min confidence value -# if score < self._min_confidence: -# continue - -# # Exclude matches outside global area definition -# if (boxes[0] < self._area[0] or boxes[1] < self._area[1] -# or boxes[2] > self._area[2] or boxes[3] > self._area[3]): -# continue - -# category = self._category_index[obj_class]['name'] - -# # Exclude unlisted categories -# if (self._include_categories -# and category not in self._include_categories): -# continue - -# # Exclude matches outside category specific area definition -# if (self._category_areas -# and (boxes[0] < self._category_areas[category][0] -# or boxes[1] < self._category_areas[category][1] -# or boxes[2] > self._category_areas[category][2] -# or boxes[3] > self._category_areas[category][3])): -# continue - -# # If we got here, we should include it -# if category not in matches.keys(): -# matches[category] = [] -# matches[category].append({ -# 'score': float(score), -# 'box': boxes -# }) -# total_matches += 1 - -# # Save Images -# if total_matches and self._file_out: -# paths = [] -# for path_template in self._file_out: -# if isinstance(path_template, template.Template): -# paths.append(path_template.render( -# camera_entity=self._camera_entity)) -# else: -# paths.append(path_template) -# self._save_image(image, matches, paths) - -# self._matches = matches -# self._total_matches = total_matches \ No newline at end of file diff --git a/custom_components/life365/__init__.py b/custom_components/life365/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/custom_components/life365/sensor.py b/custom_components/life365/sensor.py deleted file mode 100644 index 1b8c689..0000000 --- a/custom_components/life365/sensor.py +++ /dev/null @@ -1,267 +0,0 @@ -""" -@ Author : Suresh Kalavala -@ Date : 05/24/2017 -@ Description : Life365 Sensor - It queries Life360 API and retrieves - data at a specified interval and dumps into MQTT - -@ Notes: Copy this file and place it in your - "Home Assistant Config folder\custom_components\sensor\" folder - Copy corresponding Life365 Package frommy repo, - and make sure you have MQTT installed and Configured - Make sure the life365 password doesn't contain '#' or '$' symbols -""" - -from datetime import timedelta -import logging -import subprocess -import json - -import voluptuous as vol -import homeassistant.components.mqtt as mqtt - -from io import StringIO -from homeassistant.components.mqtt import (CONF_STATE_TOPIC, CONF_COMMAND_TOPIC, CONF_QOS, CONF_RETAIN) -from homeassistant.helpers import template -from homeassistant.exceptions import TemplateError -from homeassistant.components.sensor import PLATFORM_SCHEMA -from homeassistant.const import ( - CONF_NAME, CONF_VALUE_TEMPLATE, CONF_UNIT_OF_MEASUREMENT, - STATE_UNKNOWN) -from homeassistant.helpers.entity import Entity -import homeassistant.helpers.config_validation as cv - -_LOGGER = logging.getLogger(__name__) - -DEPENDENCIES = ['mqtt'] - -DEFAULT_NAME = 'Life365 Sensor' -CONST_MQTT_TOPIC = "mqtt_topic" -CONST_STATE_ERROR = "error" -CONST_STATE_RUNNING = "running" -CONST_USERNAME = "username" -CONST_PASSWORD = "password" - -COMMAND1 = "curl -s -X POST -H \"Authorization: Basic cFJFcXVnYWJSZXRyZTRFc3RldGhlcnVmcmVQdW1hbUV4dWNyRUh1YzptM2ZydXBSZXRSZXN3ZXJFQ2hBUHJFOTZxYWtFZHI0Vg==\" -F \"grant_type=password\" -F \"username=USERNAME360\" -F \"password=PASSWORD360\" https://api.life360.com/v3/oauth2/token.json | grep -Po '(?<=\"access_token\":\")\\w*'" -COMMAND2 = "curl -s -X GET -H \"Authorization: Bearer ACCESS_TOKEN\" https://api.life360.com/v3/circles.json | grep -Po '(?<=\"id\":\")[\\w-]*'" -COMMAND3 = "curl -s -X GET -H \"Authorization: Bearer ACCESS_TOKEN\" https://api.life360.com/v3/circles/ID" - -SCAN_INTERVAL = timedelta(seconds=60) - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONST_USERNAME): cv.string, - vol.Required(CONST_PASSWORD): cv.string, - vol.Required(CONST_MQTT_TOPIC): cv.string, - vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string, - vol.Optional(CONF_VALUE_TEMPLATE): cv.template, -}) - -# pylint: disable=unused-argument -def setup_platform(hass, config, add_devices, discovery_info=None): - """Set up the Life365 Sensor.""" - name = config.get(CONF_NAME) - username = config.get(CONST_USERNAME) - password = config.get(CONST_PASSWORD) - mqtt_topic = config.get(CONST_MQTT_TOPIC) - - unit = config.get(CONF_UNIT_OF_MEASUREMENT) - value_template = config.get(CONF_VALUE_TEMPLATE) - if value_template is not None: - value_template.hass = hass - - data = Life365SensorData(username, password, COMMAND1, COMMAND2, COMMAND3, mqtt_topic, hass) - - add_devices([Life365Sensor(hass, data, name, unit, value_template)]) - - -class Life365Sensor(Entity): - """Representation of a sensor.""" - - def __init__(self, hass, data, name, unit_of_measurement, value_template): - """Initialize the sensor.""" - self._hass = hass - self.data = data - self._name = name - self._state = STATE_UNKNOWN - self._unit_of_measurement = unit_of_measurement - self._value_template = value_template - self.update() - - @property - def name(self): - """Return the name of the sensor.""" - return self._name - - @property - def unit_of_measurement(self): - """Return the unit the value is expressed in.""" - return self._unit_of_measurement - - @property - def state(self): - """Return the state of the device.""" - return self._state - - def update(self): - """Get the latest data and updates the state.""" - self.data.update() - value = self.data.value - - if value is None: - value = STATE_UNKNOWN - elif self._value_template is not None: - self._state = self._value_template.render_with_possible_json_value( - value, STATE_UNKNOWN) - else: - self._state = value - - -class Life365SensorData(object): - """The class for handling the data retrieval.""" - - def __init__(self, username, password, command1, command2, command3, mqtt_topic, hass): - """Initialize the data object.""" - self.username = username - self.password = password - self.COMMAND_ACCESS_TOKEN = command1 - self.COMMAND_ID = command2 - self.COMMAND_MEMBERS = command3 - self.hass = hass - self.value = None - self.mqtt_topic = mqtt_topic - self.mqtt_retain = True - self.mqtt_qos = 0 - - def update(self): - - try: - """ Prepare and Execute Commands """ - self.COMMAND_ACCESS_TOKEN = self.COMMAND_ACCESS_TOKEN.replace("USERNAME360", self.username) - self.COMMAND_ACCESS_TOKEN = self.COMMAND_ACCESS_TOKEN.replace("PASSWORD360", self.password) - access_token = self.exec_shell_command( self.COMMAND_ACCESS_TOKEN ) - - if access_token == None: - self.value = CONST_STATE_ERROR - return None - - self.COMMAND_ID = self.COMMAND_ID.replace("ACCESS_TOKEN", access_token) - id = self.exec_shell_command( self.COMMAND_ID ) - - if id == None: - self.value = CONST_STATE_ERROR - return None - - self.COMMAND_MEMBERS = self.COMMAND_MEMBERS.replace("ACCESS_TOKEN", access_token) - self.COMMAND_MEMBERS = self.COMMAND_MEMBERS.replace("ID", id) - payload = self.exec_shell_command( self.COMMAND_MEMBERS ) - - if payload != None: - self.save_payload_to_mqtt ( self.mqtt_topic, payload ) - data = json.loads ( payload ) - for member in data["members"]: - topic = StringBuilder() - topic.Append("owntracks/") - topic.Append(member["firstName"].lower()) - topic.Append("/") - topic.Append(member["firstName"].lower()) - topic = topic - - msgPayload = StringBuilder() - msgPayload.Append("{") - msgPayload.Append("\"t\":\"p\"") - msgPayload.Append(",") - - msgPayload.Append("\"tst\":") - msgPayload.Append(member['location']['timestamp']) - msgPayload.Append(",") - - msgPayload.Append("\"acc\":") - msgPayload.Append(member['location']['accuracy']) - msgPayload.Append(",") - - msgPayload.Append("\"_type\":\"location\"") - msgPayload.Append(",") - - msgPayload.Append("\"alt\":\"0\"") - msgPayload.Append(",") - - msgPayload.Append("\"_cp\":\"false\"") - msgPayload.Append(",") - - msgPayload.Append("\"lon\":") - msgPayload.Append(member['location']['longitude']) - msgPayload.Append(",") - - msgPayload.Append("\"lat\":") - msgPayload.Append(member['location']['latitude']) - msgPayload.Append(",") - - msgPayload.Append("\"batt\":") - msgPayload.Append(member['location']['battery']) - msgPayload.Append(",") - - if str(member['location']['wifiState']) == "1": - msgPayload.Append("\"conn\":\"w\"") - msgPayload.Append(",") - - msgPayload.Append("\"vel\":") - msgPayload.Append(str(member['location']['speed'])) - msgPayload.Append(",") - - msgPayload.Append("\"charging\":") - msgPayload.Append(member['location']['charge']) - msgPayload.Append("}") - - self.save_payload_to_mqtt ( str(topic), str(msgPayload) ) - self.value = CONST_STATE_RUNNING - else: - self.value = CONST_STATE_ERROR - - except Exception as e: - self.value = CONST_STATE_ERROR - - def exec_shell_command( self, command ): - - output = None - try: - output = subprocess.check_output( command, shell=True, timeout=50 ) - output = output.strip().decode('utf-8') - - except subprocess.CalledProcessError: - """ _LOGGER.error("Command failed: %s", command)""" - self.value = CONST_STATE_ERROR - output = None - except subprocess.TimeoutExpired: - """ _LOGGER.error("Timeout for command: %s", command)""" - self.value = CONST_STATE_ERROR - output = None - - if output == None: - _LOGGER.error( "Life365 has not responsed well. Nothing to worry, will try again!" ) - self.value = CONST_STATE_ERROR - return None - else: - return output - - def save_payload_to_mqtt( self, topic, payload ): - - try: - """mqtt.async_publish ( self.hass, topic, payload, self.mqtt_qos, self.mqtt_retain )""" - _LOGGER.info("topic: %s", topic) - _LOGGER.info("payload: %s", payload) - mqtt.publish ( self.hass, topic, payload, self.mqtt_qos, self.mqtt_retain ) - - except: - _LOGGER.error( "Error saving Life365 data to mqtt." ) - -class StringBuilder: - _file_str = None - - def __init__(self): - self._file_str = StringIO() - - def Append(self, str): - self._file_str.write(str) - - def __str__(self): - return self._file_str.getvalue() \ No newline at end of file diff --git a/custom_components/paloalto/__init__.py b/custom_components/paloalto/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/custom_components/paloalto/sensor.py b/custom_components/paloalto/sensor.py deleted file mode 100644 index c3902b9..0000000 --- a/custom_components/paloalto/sensor.py +++ /dev/null @@ -1,269 +0,0 @@ -""" -@Author: Suresh Kalavala -@Date: 03/03/2018 - -Custom Sensor: Palo Alto device integration with Home Assistant. - -For more details about this platform, please refer to the documentation at -https://home-assistant.io/components/sensor.paloalto/ -""" -import ssl -import logging -import urllib.request -import voluptuous as vol -import homeassistant.helpers.config_validation as cv -import xml.etree.ElementTree as ET - -from enum import Enum -from datetime import timedelta -from homeassistant.helpers.entity import Entity -from homeassistant.components.sensor import PLATFORM_SCHEMA -from homeassistant.const import (CONF_NAME, CONF_API_KEY, CONF_IP_ADDRESS, - CONF_SSL, CONF_VERIFY_SSL, - CONF_MONITORED_CONDITIONS) - -_LOGGER = logging.getLogger(__name__) - -DEFAULT_NAME = 'PaloAlto' -DEFAULT_SSL = False -DEFAULT_VERIFY_SSL = True - -CONST_COMMAND = "COMMAND" -CONST_OPS_ENDPOINT = '/api/?type=op&cmd=COMMAND' -CONST_CONFIG_ENDPOINT = '/api/?type=config&action=get&xpath=COMMAND' - -PA_OPS_ACTIVE_USERS = "" -PA_CONF_SYS_INFO = "" -PA_CONF_GP_USERS = "" \ - "" -PA_CONF_TEMPERATURE = "" \ - "" - -SCAN_INTERVAL = timedelta(seconds=120) - -MONITORED_CONDITIONS = { - 'host_name': ['Host Name', 'x', 'mdi:fire'], - 'up_time': ['Up Time', 'x', 'mdi:clock'], - 'serial_no': ['Serial Number', 'x', 'mdi:counter'], - 'sw_version': ['Software Version', 'x', 'mdi:counter'], - 'gp_version': ['Global protect Version', 'x', 'mdi:counter'], - 'logdb_version': ['LogDB Version', 'x', 'mdi:book-open'], - 'operation_mode': ['Operation Mode', 'x', 'mdi:book-open'], - 'core_temp': ['Core Temperature', 'x', 'mdi:oil-temperature'], - 'sys_temp': ['System Temperature', 'x', 'mdi:oil-temperature'], - 'gp_user_count': ['Global Protect User Count', 'vpn users', 'mdi:counter'], - 'gp_users': ['Global Protect Users', 'vpn users', 'mdi:account-multiple'], - 'loggedin_user_count': ['Loggedin User Count', 'users', 'mdi:counter'], - 'loggedin_users': ['Loggedin Users', 'users', 'mdi:account-multiple'], -} - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - vol.Required(CONF_API_KEY): cv.string, - vol.Required(CONF_IP_ADDRESS): cv.string, - vol.Optional(CONF_SSL, default=DEFAULT_SSL): cv.boolean, - vol.Optional(CONF_MONITORED_CONDITIONS, - default=list(MONITORED_CONDITIONS)): - vol.All(cv.ensure_list, [vol.In(MONITORED_CONDITIONS)]), - vol.Optional(CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL): cv.boolean, -}) - - -# pylint: disable=unused-argument -def setup_platform(hass, config, add_devices, discovery_info=None): - """Set up the Palo Alto VPN User Sensor.""" - name = config.get(CONF_NAME) - host = config.get(CONF_IP_ADDRESS) - use_ssl = config.get(CONF_SSL) - verify_ssl = config.get(CONF_VERIFY_SSL) - api_key = config.get(CONF_API_KEY) - sensors = [] - - try: - api = PaloAltoApi(host, use_ssl, verify_ssl, api_key) - for condition in config[CONF_MONITORED_CONDITIONS]: - sensor = PaloAltoSensor(hass, api, name, condition) - sensors.append(sensor) - add_devices(sensors, True) - except Exception as err: - _LOGGER.error("Failed to setup Palo Alto Sensor. Error: " + str(err)) - - -class PaloAltoSensor(Entity): - """Representation of a sensor.""" - - def __init__(self, hass, api, name, variable): - """Initialize the sensor.""" - self._hass = hass - self._api = api - self._name = name - self._var_id = variable - - variable_info = MONITORED_CONDITIONS[variable] - self._var_name = variable_info[0] - self._var_units = variable_info[1] - self._var_icon = variable_info[2] - - @property - def name(self): - """Return the name of the sensor.""" - return "{} {}".format(self._name, self._var_name) - - @property - def icon(self): - """Icon to use in the frontend, if any.""" - return self._var_icon - - @property - def state(self): - """Return the state of the device.""" - return self._api.data[self._var_id] - - @property - def available(self): - """Could the device be accessed during the last update call.""" - return self._api.available - - def update(self): - """Get the latest data and updates the state.""" - self._api.update() - - -class PaloAltoApi(object): - """The class for handling the data retrieval from Palo Alto Device.""" - - def __init__(self, host, use_ssl, verify_ssl, api_key): - """Initialize the Palo Alto API.""" - self._host = host - self._use_ssl = use_ssl - self._verify_ssl = verify_ssl - self._api_key = api_key - self._usersdata = None - self._sysinfo = None - self._gp_users = None - self._temperature = None - self.available = True - self._sensors = {} - - @property - def data(self): - """Return data.""" - return self._sensors - - def get_uri_scheme(self, use_ssl): - """Return proper uril scheme based on config setting.""" - return 'https://' if use_ssl else 'http://' - - def get_resource(self, use_ssl, host, api_key, endpoint): - """Prepare the URL.""" - uri_scheme = self.get_uri_scheme(use_ssl) - if endpoint == EndPointType.Operational: - return "{}{}{}&key={}".format(uri_scheme, self._host, - CONST_OPS_ENDPOINT, self._api_key) - else: - return "{}{}{}&key={}".format(uri_scheme, self._host, - CONST_CONFIG_ENDPOINT, self._api_key) - - def http_request(self, url): - """HTTP request to the Palo Alto device.""" - content = None - context = None - try: - if self._use_ssl and not self._verify_ssl: - context = ssl._create_unverified_context() - response = urllib.request.urlopen(url, context=context) - content = response.read() - except Exception as ex: - _LOGGER.error(str(ex)) - content = None - - return content - - def update(self): - """Get Operational and Configuration urls.""" - ops_url = self.get_resource(self._use_ssl, self._host, - self._api_key, EndPointType.Operational) - - users_url = ops_url.replace(CONST_COMMAND, PA_OPS_ACTIVE_USERS) - self._usersdata = self.http_request(users_url) - - sysinfo_url = ops_url.replace(CONST_COMMAND, PA_CONF_SYS_INFO) - self._sysinfo = self.http_request(sysinfo_url) - - gp_users_url = ops_url.replace(CONST_COMMAND, PA_CONF_GP_USERS) - self._gp_users = self.http_request(gp_users_url) - - temperature_url = ops_url.replace(CONST_COMMAND, PA_CONF_TEMPERATURE) - self._temperature = self.http_request(temperature_url) - - """parse the xml data""" - self.parse_data() - - def parse_globalprotect_users(self): - """Parses global protect users xml.""" - user_count = 0 - vpn_users = [] - root = ET.fromstring(self._gp_users) - nodes = root.findall('result/gp-portal-users/user') - for user in nodes: - user_count += 1 - vpn_users.append(user.find('username').text) - - if user_count != 0: - self._sensors["gp_users"] = ', '.join(vpn_users) - else: - self._sensors["gp_users"] = "None" - self._sensors["gp_user_count"] = user_count - - def parse_temperature(self): - """Parses environment/temperature values.""" - root = ET.fromstring(self._temperature) - nodes = root.findall('result/thermal/Slot1/entry/DegreesC') - self._sensors["core_temp"] = round(float(nodes[0].text), 2) - self._sensors["sys_temp"] = round(float(nodes[1].text), 2) - - def parse_system_info(self): - """Parses System Information.""" - root = ET.fromstring(self._sysinfo) - sys_node = root.findall('result/system') - self._sensors["up_time"] = sys_node[0].find('uptime').text - self._sensors["serial_no"] = sys_node[0].find('serial').text - self._sensors["host_name"] = sys_node[0].find('hostname').text - self._sensors["sw_version"] = sys_node[0].find('sw-version').text - self._sensors["logdb_version"] = sys_node[0].find( - 'logdb-version').text - self._sensors["operation_mode"] = sys_node[0].find( - 'operational-mode').text - self._sensors["gp_version"] = sys_node[0].find( - 'global-protect-client-package-version').text - - def parse_active_users(self): - """Parses Active Users XML.""" - root = ET.fromstring(self._usersdata) - nodes = root.findall('result/admins/entry') - count = 0 - users = [] - for item in nodes: - count += 1 - users.append(item.find('admin').text) - - if count > 0: - self._sensors["loggedin_users"] = ', '.join(users) - else: - self._sensors["loggedin_users"] = "None" - - self._sensors["loggedin_user_count"] = count - - def parse_data(self): - """Parses data and populates sensors.""" - self.parse_globalprotect_users() - self.parse_temperature() - self.parse_system_info() - self.parse_active_users() - - -class EndPointType(Enum): - """Enum that indicates that type of endpoint that is.""" - - Operational = "operational" - Configuration = "configuration" \ No newline at end of file diff --git a/custom_components/telegram_bot/__init__.py b/custom_components/telegram_bot/__init__.py new file mode 100644 index 0000000..5924291 --- /dev/null +++ b/custom_components/telegram_bot/__init__.py @@ -0,0 +1,988 @@ +"""Support to send and receive Telegram messages.""" +from functools import partial +import importlib +import io +from ipaddress import ip_network +import logging + +import requests +from requests.auth import HTTPBasicAuth, HTTPDigestAuth +from telegram import ( + Bot, + InlineKeyboardButton, + InlineKeyboardMarkup, + ReplyKeyboardMarkup, + ReplyKeyboardRemove, +) +from telegram.error import TelegramError +from telegram.parsemode import ParseMode +from telegram.utils.request import Request +import voluptuous as vol + +from homeassistant.const import ( + ATTR_COMMAND, + ATTR_LATITUDE, + ATTR_LONGITUDE, + CONF_API_KEY, + CONF_PLATFORM, + CONF_URL, + HTTP_BEARER_AUTHENTICATION, + HTTP_DIGEST_AUTHENTICATION, +) +from homeassistant.core import HomeAssistant, ServiceCall +from homeassistant.exceptions import TemplateError +import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.typing import ConfigType + +_LOGGER = logging.getLogger(__name__) + +ATTR_DATA = "data" +ATTR_MESSAGE = "message" +ATTR_TITLE = "title" + +ATTR_ARGS = "args" +ATTR_AUTHENTICATION = "authentication" +ATTR_CALLBACK_QUERY = "callback_query" +ATTR_CALLBACK_QUERY_ID = "callback_query_id" +ATTR_CAPTION = "caption" +ATTR_CHAT_ID = "chat_id" +ATTR_CHAT_INSTANCE = "chat_instance" +ATTR_DISABLE_NOTIF = "disable_notification" +ATTR_DISABLE_WEB_PREV = "disable_web_page_preview" +ATTR_EDITED_MSG = "edited_message" +ATTR_FILE = "file" +ATTR_FROM_FIRST = "from_first" +ATTR_FROM_LAST = "from_last" +ATTR_KEYBOARD = "keyboard" +ATTR_KEYBOARD_INLINE = "inline_keyboard" +ATTR_MESSAGEID = "message_id" +ATTR_MSG = "message" +ATTR_MSGID = "id" +ATTR_PARSER = "parse_mode" +ATTR_PASSWORD = "password" +ATTR_REPLY_TO_MSGID = "reply_to_message_id" +ATTR_REPLYMARKUP = "reply_markup" +ATTR_SHOW_ALERT = "show_alert" +ATTR_STICKER_ID = "sticker_id" +ATTR_TARGET = "target" +ATTR_TEXT = "text" +ATTR_URL = "url" +ATTR_USER_ID = "user_id" +ATTR_USERNAME = "username" +ATTR_VERIFY_SSL = "verify_ssl" +ATTR_TIMEOUT = "timeout" +ATTR_MESSAGE_TAG = "message_tag" +ATTR_CHANNEL_POST = "channel_post" + +CONF_ALLOWED_CHAT_IDS = "allowed_chat_ids" +CONF_PROXY_URL = "proxy_url" +CONF_PROXY_PARAMS = "proxy_params" +CONF_TRUSTED_NETWORKS = "trusted_networks" + +DOMAIN = "telegram_bot" + +SERVICE_SEND_MESSAGE = "send_message" +SERVICE_SEND_PHOTO = "send_photo" +SERVICE_SEND_STICKER = "send_sticker" +SERVICE_SEND_ANIMATION = "send_animation" +SERVICE_SEND_VIDEO = "send_video" +SERVICE_SEND_VOICE = "send_voice" +SERVICE_SEND_DOCUMENT = "send_document" +SERVICE_SEND_LOCATION = "send_location" +SERVICE_EDIT_MESSAGE = "edit_message" +SERVICE_EDIT_CAPTION = "edit_caption" +SERVICE_EDIT_REPLYMARKUP = "edit_replymarkup" +SERVICE_ANSWER_CALLBACK_QUERY = "answer_callback_query" +SERVICE_DELETE_MESSAGE = "delete_message" +SERVICE_LEAVE_CHAT = "leave_chat" + +EVENT_TELEGRAM_CALLBACK = "telegram_callback" +EVENT_TELEGRAM_COMMAND = "telegram_command" +EVENT_TELEGRAM_TEXT = "telegram_text" +EVENT_TELEGRAM_SENT = "telegram_sent" + +PARSER_HTML = "html" +PARSER_MD = "markdown" + +DEFAULT_TRUSTED_NETWORKS = [ip_network("149.154.160.0/20"), ip_network("91.108.4.0/22")] + +CONFIG_SCHEMA = vol.Schema( + { + DOMAIN: vol.All( + cv.ensure_list, + [ + vol.Schema( + { + vol.Required(CONF_PLATFORM): vol.In( + ("broadcast", "polling", "webhooks") + ), + vol.Required(CONF_API_KEY): cv.string, + vol.Required(CONF_ALLOWED_CHAT_IDS): vol.All( + cv.ensure_list, [vol.Coerce(int)] + ), + vol.Optional(ATTR_PARSER, default=PARSER_MD): cv.string, + vol.Optional(CONF_PROXY_URL): cv.string, + vol.Optional(CONF_PROXY_PARAMS): dict, + # webhooks + vol.Optional(CONF_URL): cv.url, + vol.Optional( + CONF_TRUSTED_NETWORKS, default=DEFAULT_TRUSTED_NETWORKS + ): vol.All(cv.ensure_list, [ip_network]), + } + ) + ], + ) + }, + extra=vol.ALLOW_EXTRA, +) + +BASE_SERVICE_SCHEMA = vol.Schema( + { + vol.Optional(ATTR_TARGET): vol.All(cv.ensure_list, [vol.Coerce(int)]), + vol.Optional(ATTR_PARSER): cv.string, + vol.Optional(ATTR_DISABLE_NOTIF): cv.boolean, + vol.Optional(ATTR_DISABLE_WEB_PREV): cv.boolean, + vol.Optional(ATTR_KEYBOARD): vol.All(cv.ensure_list, [cv.string]), + vol.Optional(ATTR_KEYBOARD_INLINE): cv.ensure_list, + vol.Optional(ATTR_TIMEOUT): cv.positive_int, + vol.Optional(ATTR_MESSAGE_TAG): cv.string, + }, + extra=vol.ALLOW_EXTRA, +) + +SERVICE_SCHEMA_SEND_MESSAGE = BASE_SERVICE_SCHEMA.extend( + {vol.Required(ATTR_MESSAGE): cv.template, vol.Optional(ATTR_TITLE): cv.template} +) + +SERVICE_SCHEMA_SEND_FILE = BASE_SERVICE_SCHEMA.extend( + { + vol.Optional(ATTR_URL): cv.template, + vol.Optional(ATTR_FILE): cv.template, + vol.Optional(ATTR_CAPTION): cv.template, + vol.Optional(ATTR_USERNAME): cv.string, + vol.Optional(ATTR_PASSWORD): cv.string, + vol.Optional(ATTR_AUTHENTICATION): cv.string, + vol.Optional(ATTR_VERIFY_SSL): cv.boolean, + } +) + +SERVICE_SCHEMA_SEND_STICKER = SERVICE_SCHEMA_SEND_FILE.extend( + {vol.Optional(ATTR_STICKER_ID): cv.string} +) + +SERVICE_SCHEMA_SEND_LOCATION = BASE_SERVICE_SCHEMA.extend( + { + vol.Required(ATTR_LONGITUDE): cv.template, + vol.Required(ATTR_LATITUDE): cv.template, + } +) + +SERVICE_SCHEMA_EDIT_MESSAGE = SERVICE_SCHEMA_SEND_MESSAGE.extend( + { + vol.Required(ATTR_MESSAGEID): vol.Any( + cv.positive_int, vol.All(cv.string, "last") + ), + vol.Required(ATTR_CHAT_ID): vol.Coerce(int), + } +) + +SERVICE_SCHEMA_EDIT_CAPTION = vol.Schema( + { + vol.Required(ATTR_MESSAGEID): vol.Any( + cv.positive_int, vol.All(cv.string, "last") + ), + vol.Required(ATTR_CHAT_ID): vol.Coerce(int), + vol.Required(ATTR_CAPTION): cv.template, + vol.Optional(ATTR_KEYBOARD_INLINE): cv.ensure_list, + }, + extra=vol.ALLOW_EXTRA, +) + +SERVICE_SCHEMA_EDIT_REPLYMARKUP = vol.Schema( + { + vol.Required(ATTR_MESSAGEID): vol.Any( + cv.positive_int, vol.All(cv.string, "last") + ), + vol.Required(ATTR_CHAT_ID): vol.Coerce(int), + vol.Required(ATTR_KEYBOARD_INLINE): cv.ensure_list, + }, + extra=vol.ALLOW_EXTRA, +) + +SERVICE_SCHEMA_ANSWER_CALLBACK_QUERY = vol.Schema( + { + vol.Required(ATTR_MESSAGE): cv.template, + vol.Required(ATTR_CALLBACK_QUERY_ID): vol.Coerce(int), + vol.Optional(ATTR_SHOW_ALERT): cv.boolean, + }, + extra=vol.ALLOW_EXTRA, +) + +SERVICE_SCHEMA_DELETE_MESSAGE = vol.Schema( + { + vol.Required(ATTR_CHAT_ID): vol.Coerce(int), + vol.Required(ATTR_MESSAGEID): vol.Any( + cv.positive_int, vol.All(cv.string, "last") + ), + }, + extra=vol.ALLOW_EXTRA, +) + +SERVICE_SCHEMA_LEAVE_CHAT = vol.Schema({vol.Required(ATTR_CHAT_ID): vol.Coerce(int)}) + +SERVICE_MAP = { + SERVICE_SEND_MESSAGE: SERVICE_SCHEMA_SEND_MESSAGE, + SERVICE_SEND_PHOTO: SERVICE_SCHEMA_SEND_FILE, + SERVICE_SEND_STICKER: SERVICE_SCHEMA_SEND_STICKER, + SERVICE_SEND_ANIMATION: SERVICE_SCHEMA_SEND_FILE, + SERVICE_SEND_VIDEO: SERVICE_SCHEMA_SEND_FILE, + SERVICE_SEND_VOICE: SERVICE_SCHEMA_SEND_FILE, + SERVICE_SEND_DOCUMENT: SERVICE_SCHEMA_SEND_FILE, + SERVICE_SEND_LOCATION: SERVICE_SCHEMA_SEND_LOCATION, + SERVICE_EDIT_MESSAGE: SERVICE_SCHEMA_EDIT_MESSAGE, + SERVICE_EDIT_CAPTION: SERVICE_SCHEMA_EDIT_CAPTION, + SERVICE_EDIT_REPLYMARKUP: SERVICE_SCHEMA_EDIT_REPLYMARKUP, + SERVICE_ANSWER_CALLBACK_QUERY: SERVICE_SCHEMA_ANSWER_CALLBACK_QUERY, + SERVICE_DELETE_MESSAGE: SERVICE_SCHEMA_DELETE_MESSAGE, + SERVICE_LEAVE_CHAT: SERVICE_SCHEMA_LEAVE_CHAT, +} + + +def load_data( + hass, + url=None, + filepath=None, + username=None, + password=None, + authentication=None, + num_retries=5, + verify_ssl=None, +): + """Load data into ByteIO/File container from a source.""" + try: + if url is not None: + # Load data from URL + params = {"timeout": 15} + if authentication == HTTP_BEARER_AUTHENTICATION and password is not None: + params["headers"] = {"Authorization": f"Bearer {password}"} + elif username is not None and password is not None: + if authentication == HTTP_DIGEST_AUTHENTICATION: + params["auth"] = HTTPDigestAuth(username, password) + else: + params["auth"] = HTTPBasicAuth(username, password) + if verify_ssl is not None: + params["verify"] = verify_ssl + retry_num = 0 + while retry_num < num_retries: + req = requests.get(url, **params) + if not req.ok: + _LOGGER.warning( + "Status code %s (retry #%s) loading %s", + req.status_code, + retry_num + 1, + url, + ) + else: + data = io.BytesIO(req.content) + if data.read(): + data.seek(0) + data.name = url + return data + _LOGGER.warning("Empty data (retry #%s) in %s)", retry_num + 1, url) + retry_num += 1 + _LOGGER.warning("Can't load data in %s after %s retries", url, retry_num) + elif filepath is not None: + if hass.config.is_allowed_path(filepath): + return open(filepath, "rb") + + _LOGGER.warning("'%s' are not secure to load data from!", filepath) + else: + _LOGGER.warning("Can't load data. No data found in params!") + + except (OSError, TypeError) as error: + _LOGGER.error("Can't load data into ByteIO: %s", error) + + return None + + +async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: + """Set up the Telegram bot component.""" + if not config[DOMAIN]: + return False + + for p_config in config[DOMAIN]: + + p_type = p_config.get(CONF_PLATFORM) + + platform = importlib.import_module(f".{p_config[CONF_PLATFORM]}", __name__) + + _LOGGER.info("Setting up %s.%s", DOMAIN, p_type) + try: + receiver_service = await platform.async_setup_platform(hass, p_config) + if receiver_service is False: + _LOGGER.error("Failed to initialize Telegram bot %s", p_type) + return False + + except Exception: # pylint: disable=broad-except + _LOGGER.exception("Error setting up platform %s", p_type) + return False + + bot = initialize_bot(p_config) + notify_service = TelegramNotificationService( + hass, bot, p_config.get(CONF_ALLOWED_CHAT_IDS), p_config.get(ATTR_PARSER) + ) + + async def async_send_telegram_message(service: ServiceCall) -> None: + """Handle sending Telegram Bot message service calls.""" + + def _render_template_attr(data, attribute): + if attribute_templ := data.get(attribute): + if any( + isinstance(attribute_templ, vtype) for vtype in (float, int, str) + ): + data[attribute] = attribute_templ + else: + attribute_templ.hass = hass + try: + data[attribute] = attribute_templ.async_render( + parse_result=False + ) + except TemplateError as exc: + _LOGGER.error( + "TemplateError in %s: %s -> %s", + attribute, + attribute_templ.template, + exc, + ) + data[attribute] = attribute_templ.template + + msgtype = service.service + kwargs = dict(service.data) + for attribute in ( + ATTR_MESSAGE, + ATTR_TITLE, + ATTR_URL, + ATTR_FILE, + ATTR_CAPTION, + ATTR_LONGITUDE, + ATTR_LATITUDE, + ): + _render_template_attr(kwargs, attribute) + _LOGGER.debug("New telegram message %s: %s", msgtype, kwargs) + + if msgtype == SERVICE_SEND_MESSAGE: + await hass.async_add_executor_job( + partial(notify_service.send_message, **kwargs) + ) + elif msgtype in [ + SERVICE_SEND_PHOTO, + SERVICE_SEND_ANIMATION, + SERVICE_SEND_VIDEO, + SERVICE_SEND_VOICE, + SERVICE_SEND_DOCUMENT, + ]: + await hass.async_add_executor_job( + partial(notify_service.send_file, msgtype, **kwargs) + ) + elif msgtype == SERVICE_SEND_STICKER: + await hass.async_add_executor_job( + partial(notify_service.send_sticker, **kwargs) + ) + elif msgtype == SERVICE_SEND_LOCATION: + await hass.async_add_executor_job( + partial(notify_service.send_location, **kwargs) + ) + elif msgtype == SERVICE_ANSWER_CALLBACK_QUERY: + await hass.async_add_executor_job( + partial(notify_service.answer_callback_query, **kwargs) + ) + elif msgtype == SERVICE_DELETE_MESSAGE: + await hass.async_add_executor_job( + partial(notify_service.delete_message, **kwargs) + ) + else: + await hass.async_add_executor_job( + partial(notify_service.edit_message, msgtype, **kwargs) + ) + + # Register notification services + for service_notif, schema in SERVICE_MAP.items(): + hass.services.async_register( + DOMAIN, service_notif, async_send_telegram_message, schema=schema + ) + + return True + + +def initialize_bot(p_config): + """Initialize telegram bot with proxy support.""" + + api_key = p_config.get(CONF_API_KEY) + proxy_url = p_config.get(CONF_PROXY_URL) + proxy_params = p_config.get(CONF_PROXY_PARAMS) + + if proxy_url is not None: + request = Request( + con_pool_size=8, proxy_url=proxy_url, urllib3_proxy_kwargs=proxy_params + ) + else: + request = Request(con_pool_size=8) + return Bot(token=api_key, request=request) + + +class TelegramNotificationService: + """Implement the notification services for the Telegram Bot domain.""" + + def __init__(self, hass, bot, allowed_chat_ids, parser): + """Initialize the service.""" + + self.allowed_chat_ids = allowed_chat_ids + self._default_user = self.allowed_chat_ids[0] + self._last_message_id = {user: None for user in self.allowed_chat_ids} + self._parsers = {PARSER_HTML: ParseMode.HTML, PARSER_MD: ParseMode.MARKDOWN} + self._parse_mode = self._parsers.get(parser) + self.bot = bot + self.hass = hass + + def _get_msg_ids(self, msg_data, chat_id): + """Get the message id to edit. + + This can be one of (message_id, inline_message_id) from a msg dict, + returning a tuple. + **You can use 'last' as message_id** to edit + the message last sent in the chat_id. + """ + message_id = inline_message_id = None + if ATTR_MESSAGEID in msg_data: + message_id = msg_data[ATTR_MESSAGEID] + if ( + isinstance(message_id, str) + and (message_id == "last") + and (self._last_message_id[chat_id] is not None) + ): + message_id = self._last_message_id[chat_id] + else: + inline_message_id = msg_data["inline_message_id"] + return message_id, inline_message_id + + def _get_target_chat_ids(self, target): + """Validate chat_id targets or return default target (first). + + :param target: optional list of integers ([12234, -12345]) + :return list of chat_id targets (integers) + """ + if target is not None: + if isinstance(target, int): + target = [target] + chat_ids = [t for t in target if t in self.allowed_chat_ids] + if chat_ids: + return chat_ids + _LOGGER.warning( + "Disallowed targets: %s, using default: %s", target, self._default_user + ) + return [self._default_user] + + def _get_msg_kwargs(self, data): + """Get parameters in message data kwargs.""" + + def _make_row_inline_keyboard(row_keyboard): + """Make a list of InlineKeyboardButtons. + + It can accept: + - a list of tuples like: + `[(text_b1, data_callback_b1), + (text_b2, data_callback_b2), ...] + - a string like: `/cmd1, /cmd2, /cmd3` + - or a string like: `text_b1:/cmd1, text_b2:/cmd2` + """ + + buttons = [] + if isinstance(row_keyboard, str): + for key in row_keyboard.split(","): + if ":/" in key: + # commands like: 'Label:/cmd' become ('Label', '/cmd') + label = key.split(":/")[0] + command = key[len(label) + 1 :] + buttons.append( + InlineKeyboardButton(label, callback_data=command) + ) + else: + # commands like: '/cmd' become ('CMD', '/cmd') + label = key.strip()[1:].upper() + buttons.append(InlineKeyboardButton(label, callback_data=key)) + elif isinstance(row_keyboard, list): + for entry in row_keyboard: + text_btn, data_btn = entry + buttons.append( + InlineKeyboardButton(text_btn, callback_data=data_btn) + ) + else: + raise ValueError(str(row_keyboard)) + return buttons + + # Defaults + params = { + ATTR_PARSER: self._parse_mode, + ATTR_DISABLE_NOTIF: False, + ATTR_DISABLE_WEB_PREV: None, + ATTR_REPLY_TO_MSGID: None, + ATTR_REPLYMARKUP: None, + ATTR_TIMEOUT: None, + ATTR_MESSAGE_TAG: None, + } + if data is not None: + if ATTR_PARSER in data: + params[ATTR_PARSER] = self._parsers.get( + data[ATTR_PARSER], self._parse_mode + ) + if ATTR_TIMEOUT in data: + params[ATTR_TIMEOUT] = data[ATTR_TIMEOUT] + if ATTR_DISABLE_NOTIF in data: + params[ATTR_DISABLE_NOTIF] = data[ATTR_DISABLE_NOTIF] + if ATTR_DISABLE_WEB_PREV in data: + params[ATTR_DISABLE_WEB_PREV] = data[ATTR_DISABLE_WEB_PREV] + if ATTR_REPLY_TO_MSGID in data: + params[ATTR_REPLY_TO_MSGID] = data[ATTR_REPLY_TO_MSGID] + if ATTR_MESSAGE_TAG in data: + params[ATTR_MESSAGE_TAG] = data[ATTR_MESSAGE_TAG] + # Keyboards: + if ATTR_KEYBOARD in data: + keys = data.get(ATTR_KEYBOARD) + keys = keys if isinstance(keys, list) else [keys] + if keys: + params[ATTR_REPLYMARKUP] = ReplyKeyboardMarkup( + [[key.strip() for key in row.split(",")] for row in keys] + ) + else: + params[ATTR_REPLYMARKUP] = ReplyKeyboardRemove(True) + + elif ATTR_KEYBOARD_INLINE in data: + keys = data.get(ATTR_KEYBOARD_INLINE) + keys = keys if isinstance(keys, list) else [keys] + params[ATTR_REPLYMARKUP] = InlineKeyboardMarkup( + [_make_row_inline_keyboard(row) for row in keys] + ) + return params + + def _send_msg(self, func_send, msg_error, message_tag, *args_msg, **kwargs_msg): + """Send one message.""" + + try: + out = func_send(*args_msg, **kwargs_msg) + if not isinstance(out, bool) and hasattr(out, ATTR_MESSAGEID): + chat_id = out.chat_id + message_id = out[ATTR_MESSAGEID] + self._last_message_id[chat_id] = message_id + _LOGGER.debug( + "Last message ID: %s (from chat_id %s)", + self._last_message_id, + chat_id, + ) + + event_data = { + ATTR_CHAT_ID: chat_id, + ATTR_MESSAGEID: message_id, + } + if message_tag is not None: + event_data[ATTR_MESSAGE_TAG] = message_tag + self.hass.bus.fire(EVENT_TELEGRAM_SENT, event_data) + elif not isinstance(out, bool): + _LOGGER.warning( + "Update last message: out_type:%s, out=%s", type(out), out + ) + return out + except TelegramError as exc: + _LOGGER.error( + "%s: %s. Args: %s, kwargs: %s", msg_error, exc, args_msg, kwargs_msg + ) + + def send_message(self, message="", target=None, **kwargs): + """Send a message to one or multiple pre-allowed chat IDs.""" + title = kwargs.get(ATTR_TITLE) + text = f"{title}\n{message}" if title else message + params = self._get_msg_kwargs(kwargs) + for chat_id in self._get_target_chat_ids(target): + _LOGGER.debug("Send message in chat ID %s with params: %s", chat_id, params) + self._send_msg( + self.bot.send_message, + "Error sending message", + params[ATTR_MESSAGE_TAG], + chat_id, + text, + parse_mode=params[ATTR_PARSER], + disable_web_page_preview=params[ATTR_DISABLE_WEB_PREV], + disable_notification=params[ATTR_DISABLE_NOTIF], + reply_to_message_id=params[ATTR_REPLY_TO_MSGID], + reply_markup=params[ATTR_REPLYMARKUP], + timeout=params[ATTR_TIMEOUT], + ) + + def delete_message(self, chat_id=None, **kwargs): + """Delete a previously sent message.""" + chat_id = self._get_target_chat_ids(chat_id)[0] + message_id, _ = self._get_msg_ids(kwargs, chat_id) + _LOGGER.debug("Delete message %s in chat ID %s", message_id, chat_id) + deleted = self._send_msg( + self.bot.delete_message, "Error deleting message", None, chat_id, message_id + ) + # reduce message_id anyway: + if self._last_message_id[chat_id] is not None: + # change last msg_id for deque(n_msgs)? + self._last_message_id[chat_id] -= 1 + return deleted + + def edit_message(self, type_edit, chat_id=None, **kwargs): + """Edit a previously sent message.""" + chat_id = self._get_target_chat_ids(chat_id)[0] + message_id, inline_message_id = self._get_msg_ids(kwargs, chat_id) + params = self._get_msg_kwargs(kwargs) + _LOGGER.debug( + "Edit message %s in chat ID %s with params: %s", + message_id or inline_message_id, + chat_id, + params, + ) + if type_edit == SERVICE_EDIT_MESSAGE: + message = kwargs.get(ATTR_MESSAGE) + title = kwargs.get(ATTR_TITLE) + text = f"{title}\n{message}" if title else message + _LOGGER.debug("Editing message with ID %s", message_id or inline_message_id) + return self._send_msg( + self.bot.edit_message_text, + "Error editing text message", + params[ATTR_MESSAGE_TAG], + text, + chat_id=chat_id, + message_id=message_id, + inline_message_id=inline_message_id, + parse_mode=params[ATTR_PARSER], + disable_web_page_preview=params[ATTR_DISABLE_WEB_PREV], + reply_markup=params[ATTR_REPLYMARKUP], + timeout=params[ATTR_TIMEOUT], + ) + if type_edit == SERVICE_EDIT_CAPTION: + return self._send_msg( + self.bot.edit_message_caption, + "Error editing message attributes", + params[ATTR_MESSAGE_TAG], + chat_id=chat_id, + message_id=message_id, + inline_message_id=inline_message_id, + caption=kwargs.get(ATTR_CAPTION), + reply_markup=params[ATTR_REPLYMARKUP], + timeout=params[ATTR_TIMEOUT], + parse_mode=params[ATTR_PARSER], + ) + + return self._send_msg( + self.bot.edit_message_reply_markup, + "Error editing message attributes", + params[ATTR_MESSAGE_TAG], + chat_id=chat_id, + message_id=message_id, + inline_message_id=inline_message_id, + reply_markup=params[ATTR_REPLYMARKUP], + timeout=params[ATTR_TIMEOUT], + ) + + def answer_callback_query( + self, message, callback_query_id, show_alert=False, **kwargs + ): + """Answer a callback originated with a press in an inline keyboard.""" + params = self._get_msg_kwargs(kwargs) + _LOGGER.debug( + "Answer callback query with callback ID %s: %s, alert: %s", + callback_query_id, + message, + show_alert, + ) + self._send_msg( + self.bot.answer_callback_query, + "Error sending answer callback query", + params[ATTR_MESSAGE_TAG], + callback_query_id, + text=message, + show_alert=show_alert, + timeout=params[ATTR_TIMEOUT], + ) + + def send_file(self, file_type=SERVICE_SEND_PHOTO, target=None, **kwargs): + """Send a photo, sticker, video, or document.""" + params = self._get_msg_kwargs(kwargs) + file_content = load_data( + self.hass, + url=kwargs.get(ATTR_URL), + filepath=kwargs.get(ATTR_FILE), + username=kwargs.get(ATTR_USERNAME), + password=kwargs.get(ATTR_PASSWORD), + authentication=kwargs.get(ATTR_AUTHENTICATION), + verify_ssl=kwargs.get(ATTR_VERIFY_SSL), + ) + + if file_content: + for chat_id in self._get_target_chat_ids(target): + _LOGGER.debug("Sending file to chat ID %s", chat_id) + + if file_type == SERVICE_SEND_PHOTO: + self._send_msg( + self.bot.send_photo, + "Error sending photo", + params[ATTR_MESSAGE_TAG], + chat_id=chat_id, + photo=file_content, + caption=kwargs.get(ATTR_CAPTION), + disable_notification=params[ATTR_DISABLE_NOTIF], + reply_markup=params[ATTR_REPLYMARKUP], + timeout=params[ATTR_TIMEOUT], + parse_mode=params[ATTR_PARSER], + ) + + elif file_type == SERVICE_SEND_STICKER: + self._send_msg( + self.bot.send_sticker, + "Error sending sticker", + params[ATTR_MESSAGE_TAG], + chat_id=chat_id, + sticker=file_content, + disable_notification=params[ATTR_DISABLE_NOTIF], + reply_markup=params[ATTR_REPLYMARKUP], + timeout=params[ATTR_TIMEOUT], + ) + + elif file_type == SERVICE_SEND_VIDEO: + self._send_msg( + self.bot.send_video, + "Error sending video", + params[ATTR_MESSAGE_TAG], + chat_id=chat_id, + video=file_content, + caption=kwargs.get(ATTR_CAPTION), + disable_notification=params[ATTR_DISABLE_NOTIF], + reply_markup=params[ATTR_REPLYMARKUP], + timeout=params[ATTR_TIMEOUT], + parse_mode=params[ATTR_PARSER], + ) + elif file_type == SERVICE_SEND_DOCUMENT: + self._send_msg( + self.bot.send_document, + "Error sending document", + params[ATTR_MESSAGE_TAG], + chat_id=chat_id, + document=file_content, + caption=kwargs.get(ATTR_CAPTION), + disable_notification=params[ATTR_DISABLE_NOTIF], + reply_markup=params[ATTR_REPLYMARKUP], + timeout=params[ATTR_TIMEOUT], + parse_mode=params[ATTR_PARSER], + ) + elif file_type == SERVICE_SEND_VOICE: + self._send_msg( + self.bot.send_voice, + "Error sending voice", + params[ATTR_MESSAGE_TAG], + chat_id=chat_id, + voice=file_content, + caption=kwargs.get(ATTR_CAPTION), + disable_notification=params[ATTR_DISABLE_NOTIF], + reply_markup=params[ATTR_REPLYMARKUP], + timeout=params[ATTR_TIMEOUT], + ) + elif file_type == SERVICE_SEND_ANIMATION: + self._send_msg( + self.bot.send_animation, + "Error sending animation", + params[ATTR_MESSAGE_TAG], + chat_id=chat_id, + animation=file_content, + caption=kwargs.get(ATTR_CAPTION), + disable_notification=params[ATTR_DISABLE_NOTIF], + reply_markup=params[ATTR_REPLYMARKUP], + timeout=params[ATTR_TIMEOUT], + parse_mode=params[ATTR_PARSER], + ) + + file_content.seek(0) + else: + _LOGGER.error("Can't send file with kwargs: %s", kwargs) + + def send_sticker(self, target=None, **kwargs): + """Send a sticker from a telegram sticker pack.""" + params = self._get_msg_kwargs(kwargs) + stickerid = kwargs.get(ATTR_STICKER_ID) + if stickerid: + for chat_id in self._get_target_chat_ids(target): + self._send_msg( + self.bot.send_sticker, + "Error sending sticker", + params[ATTR_MESSAGE_TAG], + chat_id=chat_id, + sticker=stickerid, + disable_notification=params[ATTR_DISABLE_NOTIF], + reply_markup=params[ATTR_REPLYMARKUP], + timeout=params[ATTR_TIMEOUT], + ) + else: + self.send_file(SERVICE_SEND_STICKER, target, **kwargs) + + def send_location(self, latitude, longitude, target=None, **kwargs): + """Send a location.""" + latitude = float(latitude) + longitude = float(longitude) + params = self._get_msg_kwargs(kwargs) + for chat_id in self._get_target_chat_ids(target): + _LOGGER.debug( + "Send location %s/%s to chat ID %s", latitude, longitude, chat_id + ) + self._send_msg( + self.bot.send_location, + "Error sending location", + params[ATTR_MESSAGE_TAG], + chat_id=chat_id, + latitude=latitude, + longitude=longitude, + disable_notification=params[ATTR_DISABLE_NOTIF], + timeout=params[ATTR_TIMEOUT], + ) + + def leave_chat(self, chat_id=None): + """Remove bot from chat.""" + chat_id = self._get_target_chat_ids(chat_id)[0] + _LOGGER.debug("Leave from chat ID %s", chat_id) + leaved = self._send_msg( + self.bot.leave_chat, "Error leaving chat", None, chat_id + ) + return leaved + + +class BaseTelegramBotEntity: + """The base class for the telegram bot.""" + + def __init__(self, hass, allowed_chat_ids): + """Initialize the bot base class.""" + self.allowed_chat_ids = allowed_chat_ids + self.hass = hass + + def _get_message_data(self, msg_data): + """Return boolean msg_data_is_ok and dict msg_data.""" + if not msg_data: + return False, None + bad_fields = ( + "text" not in msg_data and "data" not in msg_data and "chat" not in msg_data + ) + if bad_fields or "from" not in msg_data: + # Message is not correct. + _LOGGER.error("Incoming message does not have required data (%s)", msg_data) + return False, None + + if ( + msg_data["from"].get("id") not in self.allowed_chat_ids + and msg_data["chat"].get("id") not in self.allowed_chat_ids + # and msg_data["message"]["chat"].get("id") not in self.allowed_chat_ids + ): + # Neither from id nor chat id was in allowed_chat_ids, + # origin is not allowed. + _LOGGER.error("Incoming message is not allowed (%s)", msg_data) + return True, None + + data = { + ATTR_USER_ID: msg_data["from"]["id"], + ATTR_FROM_FIRST: msg_data["from"]["first_name"], + } + if "message_id" in msg_data: + data[ATTR_MSGID] = msg_data["message_id"] + if "last_name" in msg_data["from"]: + data[ATTR_FROM_LAST] = msg_data["from"]["last_name"] + if "chat" in msg_data: + data[ATTR_CHAT_ID] = msg_data["chat"]["id"] + elif ATTR_MESSAGE in msg_data and "chat" in msg_data[ATTR_MESSAGE]: + data[ATTR_CHAT_ID] = msg_data[ATTR_MESSAGE]["chat"]["id"] + + return True, data + + def _get_channel_post_data(self, msg_data): + """Return boolean msg_data_is_ok and dict msg_data.""" + if not msg_data: + return False, None + + if "sender_chat" in msg_data and "chat" in msg_data and "text" in msg_data: + if ( + msg_data["sender_chat"].get("id") not in self.allowed_chat_ids + and msg_data["chat"].get("id") not in self.allowed_chat_ids + ): + # Neither sender_chat id nor chat id was in allowed_chat_ids, + # origin is not allowed. + _LOGGER.error("Incoming message is not allowed (%s)", msg_data) + return True, None + + data = { + ATTR_MSGID: msg_data["message_id"], + ATTR_CHAT_ID: msg_data["chat"]["id"], + ATTR_TEXT: msg_data["text"], + } + return True, data + + _LOGGER.error("Incoming message does not have required data (%s)", msg_data) + return False, None + + def process_message(self, data): + """Check for basic message rules and fire an event if message is ok.""" + if ATTR_MSG in data or ATTR_EDITED_MSG in data: + event = EVENT_TELEGRAM_COMMAND + if ATTR_MSG in data: + data = data.get(ATTR_MSG) + else: + data = data.get(ATTR_EDITED_MSG) + message_ok, event_data = self._get_message_data(data) + if event_data is None: + return message_ok + + if ATTR_MSGID in data: + event_data[ATTR_MSGID] = data[ATTR_MSGID] + + if "text" in data: + if data["text"][0] == "/": + pieces = data["text"].split(" ") + event_data[ATTR_COMMAND] = pieces[0] + event_data[ATTR_ARGS] = pieces[1:] + else: + event_data[ATTR_TEXT] = data["text"] + event = EVENT_TELEGRAM_TEXT + else: + _LOGGER.warning("Message without text data received: %s", data) + event_data[ATTR_TEXT] = str(data) + event = EVENT_TELEGRAM_TEXT + + self.hass.bus.async_fire(event, event_data) + return True + if ATTR_CALLBACK_QUERY in data: + event = EVENT_TELEGRAM_CALLBACK + data = data.get(ATTR_CALLBACK_QUERY) + message_ok, event_data = self._get_message_data(data) + if event_data is None: + return message_ok + + query_data = event_data[ATTR_DATA] = data[ATTR_DATA] + + if query_data[0] == "/": + pieces = query_data.split(" ") + event_data[ATTR_COMMAND] = pieces[0] + event_data[ATTR_ARGS] = pieces[1:] + + event_data[ATTR_MSG] = data[ATTR_MSG] + event_data[ATTR_CHAT_INSTANCE] = data[ATTR_CHAT_INSTANCE] + event_data[ATTR_MSGID] = data[ATTR_MSGID] + + self.hass.bus.async_fire(event, event_data) + return True + if ATTR_CHANNEL_POST in data: + event = EVENT_TELEGRAM_TEXT + data = data.get(ATTR_CHANNEL_POST) + message_ok, event_data = self._get_channel_post_data(data) + if event_data is None: + return message_ok + + self.hass.bus.async_fire(event, event_data) + return True + + _LOGGER.warning("Message with unknown data received: %s", data) + return True \ No newline at end of file diff --git a/custom_components/telegram_bot/broadcast.py b/custom_components/telegram_bot/broadcast.py new file mode 100644 index 0000000..cca8017 --- /dev/null +++ b/custom_components/telegram_bot/broadcast.py @@ -0,0 +1,17 @@ +"""Support for Telegram bot to send messages only.""" +import logging + +from . import initialize_bot + +_LOGGER = logging.getLogger(__name__) + + +async def async_setup_platform(hass, config): + """Set up the Telegram broadcast platform.""" + bot = initialize_bot(config) + + bot_config = await hass.async_add_executor_job(bot.getMe) + _LOGGER.debug( + "Telegram broadcast platform setup with bot %s", bot_config["username"] + ) + return True \ No newline at end of file diff --git a/custom_components/telegram_bot/manifest.json b/custom_components/telegram_bot/manifest.json new file mode 100644 index 0000000..844c09e --- /dev/null +++ b/custom_components/telegram_bot/manifest.json @@ -0,0 +1,11 @@ +{ + "domain": "telegram_bot", + "name": "Telegram bot", + "version": "1.0", + "documentation": "https://www.home-assistant.io/integrations/telegram_bot", + "requirements": ["python-telegram-bot==13.1", "PySocks==1.7.1"], + "dependencies": ["http"], + "codeowners": [], + "iot_class": "cloud_push", + "loggers": ["telegram"] + } \ No newline at end of file diff --git a/custom_components/telegram_bot/polling.py b/custom_components/telegram_bot/polling.py new file mode 100644 index 0000000..82e4621 --- /dev/null +++ b/custom_components/telegram_bot/polling.py @@ -0,0 +1,99 @@ +"""Support for Telegram bot using polling.""" +import logging + +from telegram import Update +from telegram.error import NetworkError, RetryAfter, TelegramError, TimedOut +from telegram.ext import CallbackContext, Dispatcher, Handler, Updater +from telegram.utils.types import HandlerArg + +from homeassistant.const import EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP + +from . import CONF_ALLOWED_CHAT_IDS, BaseTelegramBotEntity, initialize_bot + +_LOGGER = logging.getLogger(__name__) + + +async def async_setup_platform(hass, config): + """Set up the Telegram polling platform.""" + bot = initialize_bot(config) + pol = TelegramPoll(bot, hass, config[CONF_ALLOWED_CHAT_IDS]) + + def _start_bot(_event): + """Start the bot.""" + pol.start_polling() + + def _stop_bot(_event): + """Stop the bot.""" + pol.stop_polling() + + hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START, _start_bot) + hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, _stop_bot) + + return True + + +def process_error(update: Update, context: CallbackContext): + """Telegram bot error handler.""" + try: + raise context.error + except (TimedOut, NetworkError, RetryAfter): + # Long polling timeout or connection problem. Nothing serious. + pass + except TelegramError: + _LOGGER.error('Update "%s" caused error: "%s"', update, context.error) + + +def message_handler(handler): + """Create messages handler.""" + + class MessageHandler(Handler): + """Telegram bot message handler.""" + + def __init__(self): + """Initialize the messages handler instance.""" + super().__init__(handler) + + def check_update(self, update): + """Check is update valid.""" + return isinstance(update, Update) + + def handle_update( + self, + update: HandlerArg, + dispatcher: Dispatcher, + check_result: object, + context: CallbackContext = None, + ): + """Handle update.""" + optional_args = self.collect_optional_args(dispatcher, update) + context.args = optional_args + return self.callback(update, context) + + return MessageHandler() + + +class TelegramPoll(BaseTelegramBotEntity): + """Asyncio telegram incoming message handler.""" + + def __init__(self, bot, hass, allowed_chat_ids): + """Initialize the polling instance.""" + + BaseTelegramBotEntity.__init__(self, hass, allowed_chat_ids) + + self.updater = Updater(bot=bot, workers=4) + self.dispatcher = self.updater.dispatcher + + self.dispatcher.add_handler(message_handler(self.process_update)) + self.dispatcher.add_error_handler(process_error) + + def start_polling(self): + """Start the polling task.""" + self.updater.start_polling() + + def stop_polling(self): + """Stop the polling task.""" + self.updater.stop() + + def process_update(self, update: HandlerArg, context: CallbackContext): + """Process incoming message.""" + self.process_message(update.to_dict()) \ No newline at end of file diff --git a/custom_components/telegram_bot/services.yaml b/custom_components/telegram_bot/services.yaml new file mode 100644 index 0000000..9cf5fa6 --- /dev/null +++ b/custom_components/telegram_bot/services.yaml @@ -0,0 +1,840 @@ +# Describes the format for available Telegram bot services + +send_message: + name: Send message + description: Send a notification. + fields: + message: + name: Message + description: Message body of the notification. + required: true + example: The garage door has been open for 10 minutes. + selector: + text: + title: + name: Title + description: Optional title for your notification. Will be composed as '%title\n%message' + example: "Your Garage Door Friend" + selector: + text: + target: + name: Target + description: An array of pre-authorized chat_ids to send the notification to. If not present, first allowed chat_id is the default. + example: "[12345, 67890] or 12345" + selector: + object: + parse_mode: + name: Parse mode + description: "Parser for the message text." + selector: + select: + options: + - "html" + - "markdown" + - "markdown2" + disable_notification: + name: Disable notification + description: Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound. + selector: + boolean: + disable_web_page_preview: + name: Disable web page preview + description: Disables link previews for links in the message. + selector: + boolean: + timeout: + name: Timeout + description: Timeout for send message. Will help with timeout errors (poor internet connection, etc)s + selector: + number: + min: 1 + max: 3600 + unit_of_measurement: seconds + + keyboard: + name: Keyboard + description: List of rows of commands, comma-separated, to make a custom keyboard. Empty list clears a previously set keyboard. + example: '["/command1, /command2", "/command3"]' + selector: + object: + inline_keyboard: + name: Inline keyboard + description: List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data. + example: '["/button1, /button2", "/button3"] or ["Text button1:/button1, Text button2:/button2", "Text button3:/button3"] or [[["Text button1", "/button1"], ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' + selector: + object: + message_tag: + name: Message tag + description: "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}" + example: "msg_to_edit" + selector: + text: + +send_photo: + name: Send photo + description: Send a photo. + fields: + url: + name: URL + description: Remote path to an image. + example: "http://example.org/path/to/the/image.png" + selector: + text: + file: + name: File + description: Local path to an image. + example: "/path/to/the/image.png" + selector: + text: + caption: + name: Caption + description: The title of the image. + example: "My image" + selector: + text: + username: + name: Username + description: Username for a URL which require HTTP authentication. + example: myuser + selector: + text: + password: + name: Password + description: Password (or bearer token) for a URL which require HTTP authentication. + example: myuser_pwd + selector: + text: + authentication: + name: Authentication method + description: Define which authentication method to use. Set to `digest` to use HTTP digest authentication, or `bearer_token` for OAuth 2.0 bearer token authentication. Defaults to `basic`. + default: digest + selector: + select: + options: + - "digest" + - "bearer_token" + target: + name: Target + description: An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default. + example: "[12345, 67890] or 12345" + selector: + object: + parse_mode: + name: Parse mode + description: "Parser for the message text." + selector: + select: + options: + - "html" + - "markdown" + - "markdown2" + disable_notification: + name: Disable notification + description: Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound. + selector: + boolean: + verify_ssl: + name: Verify SSL + description: Enable or disable SSL certificate verification. Set to false if you're downloading the file from a URL and you don't want to validate the SSL certificate of the server. + selector: + boolean: + timeout: + name: Timeout + description: Timeout for send photo. Will help with timeout errors (poor internet connection, etc) + selector: + number: + min: 1 + max: 3600 + unit_of_measurement: seconds + keyboard: + name: Keyboard + description: List of rows of commands, comma-separated, to make a custom keyboard. + example: '["/command1, /command2", "/command3"]' + selector: + object: + inline_keyboard: + name: Inline keyboard + description: List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data. + example: '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' + selector: + object: + message_tag: + name: Message tag + description: "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}" + example: "msg_to_edit" + selector: + text: + +send_sticker: + name: Send sticker + description: Send a sticker. + fields: + url: + name: URL + description: Remote path to a static .webp or animated .tgs sticker. + example: "http://example.org/path/to/the/sticker.webp" + selector: + text: + file: + name: File + description: Local path to a static .webp or animated .tgs sticker. + example: "/path/to/the/sticker.webp" + selector: + text: + sticker_id: + name: Sticker ID + description: ID of a sticker that exists on telegram servers + example: CAACAgIAAxkBAAEDDldhZD-hqWclr6krLq-FWSfCrGNmOQAC9gAD9HsZAAFeYY-ltPYnrCEE + selector: + text: + username: + name: Username + description: Username for a URL which require HTTP authentication. + example: myuser + selector: + text: + password: + name: Password + description: Password (or bearer token) for a URL which require HTTP authentication. + example: myuser_pwd + selector: + text: + authentication: + name: Authentication method + description: Define which authentication method to use. Set to `digest` to use HTTP digest authentication, or `bearer_token` for OAuth 2.0 bearer token authentication. Defaults to `basic`. + default: digest + selector: + select: + options: + - "digest" + - "bearer_token" + target: + name: Target + description: An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default. + example: "[12345, 67890] or 12345" + selector: + object: + disable_notification: + name: Disable notification + description: Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound. + selector: + boolean: + verify_ssl: + name: Verify SSL + description: Enable or disable SSL certificate verification. Set to false if you're downloading the file from a URL and you don't want to validate the SSL certificate of the server. + selector: + boolean: + timeout: + name: Timeout + description: Timeout for send sticker. Will help with timeout errors (poor internet connection, etc) + selector: + number: + min: 1 + max: 3600 + unit_of_measurement: seconds + keyboard: + name: Keyboard + description: List of rows of commands, comma-separated, to make a custom keyboard. + example: '["/command1, /command2", "/command3"]' + selector: + object: + inline_keyboard: + name: Inline keyboard + description: List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data. + example: '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' + selector: + object: + message_tag: + name: Message tag + description: "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}" + example: "msg_to_edit" + selector: + text: + +send_animation: + name: Send animation + description: Send an anmiation. + fields: + url: + name: URL + description: Remote path to a GIF or H.264/MPEG-4 AVC video without sound. + example: "http://example.org/path/to/the/animation.gif" + selector: + text: + file: + name: File + description: Local path to a GIF or H.264/MPEG-4 AVC video without sound. + example: "/path/to/the/animation.gif" + selector: + text: + caption: + name: Caption + description: The title of the animation. + example: "My animation" + selector: + text: + username: + name: Username + description: Username for a URL which require HTTP authentication. + example: myuser + selector: + text: + password: + name: Password + description: Password (or bearer token) for a URL which require HTTP authentication. + example: myuser_pwd + selector: + text: + authentication: + name: Authentication method + description: Define which authentication method to use. Set to `digest` to use HTTP digest authentication, or `bearer_token` for OAuth 2.0 bearer token authentication. Defaults to `basic`. + default: digest + selector: + select: + options: + - "digest" + - "bearer_token" + target: + name: Target + description: An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default. + example: "[12345, 67890] or 12345" + selector: + object: + parse_mode: + name: Parse Mode + description: "Parser for the message text." + selector: + select: + options: + - "html" + - "markdown" + - "markdown2" + disable_notification: + name: Disable notification + description: Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound. + selector: + boolean: + verify_ssl: + name: Verify SSL + description: Enable or disable SSL certificate verification. Set to false if you're downloading the file from a URL and you don't want to validate the SSL certificate of the server. + selector: + boolean: + timeout: + name: Timeout + description: Timeout for send sticker. Will help with timeout errors (poor internet connection, etc) + selector: + number: + min: 1 + max: 3600 + unit_of_measurement: seconds + keyboard: + name: Keyboard + description: List of rows of commands, comma-separated, to make a custom keyboard. + example: '["/command1, /command2", "/command3"]' + selector: + object: + inline_keyboard: + name: Inline keyboard + description: List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data. + example: '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' + selector: + object: + +send_video: + name: Send video + description: Send a video. + fields: + url: + name: URL + description: Remote path to a video. + example: "http://example.org/path/to/the/video.mp4" + selector: + text: + file: + name: File + description: Local path to a video. + example: "/path/to/the/video.mp4" + selector: + text: + caption: + name: Caption + description: The title of the video. + example: "My video" + selector: + text: + username: + name: Username + description: Username for a URL which require HTTP authentication. + example: myuser + selector: + text: + password: + name: Password + description: Password (or bearer token) for a URL which require HTTP authentication. + example: myuser_pwd + selector: + text: + authentication: + name: Authentication method + description: Define which authentication method to use. Set to `digest` to use HTTP digest authentication, or `bearer_token` for OAuth 2.0 bearer token authentication. Defaults to `basic`. + default: digest + selector: + select: + options: + - "digest" + - "bearer_token" + target: + name: Target + description: An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default. + example: "[12345, 67890] or 12345" + selector: + object: + parse_mode: + name: Parse mode + description: "Parser for the message text." + selector: + select: + options: + - "html" + - "markdown" + - "markdown2" + disable_notification: + name: Disable notification + description: Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound. + selector: + boolean: + verify_ssl: + name: Verify SSL + description: Enable or disable SSL certificate verification. Set to false if you're downloading the file from a URL and you don't want to validate the SSL certificate of the server. + selector: + boolean: + timeout: + name: Timeout + description: Timeout for send video. Will help with timeout errors (poor internet connection, etc) + selector: + number: + min: 1 + max: 3600 + unit_of_measurement: seconds + keyboard: + name: Keyboard + description: List of rows of commands, comma-separated, to make a custom keyboard. + example: '["/command1, /command2", "/command3"]' + selector: + object: + inline_keyboard: + name: Inline keyboard + description: List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data. + example: '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' + selector: + object: + message_tag: + name: Message tag + description: "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}" + example: "msg_to_edit" + selector: + text: + +send_voice: + name: Send voice + description: Send a voice message. + fields: + url: + name: URL + description: Remote path to a voice message. + example: "http://example.org/path/to/the/voice.opus" + selector: + text: + file: + name: File + description: Local path to a voice message. + example: "/path/to/the/voice.opus" + selector: + text: + caption: + name: Caption + description: The title of the voice message. + example: "My microphone recording" + selector: + text: + username: + name: Username + description: Username for a URL which require HTTP authentication. + example: myuser + selector: + text: + password: + name: Password + description: Password (or bearer token) for a URL which require HTTP authentication. + example: myuser_pwd + selector: + text: + authentication: + name: Authentication method + description: Define which authentication method to use. Set to `digest` to use HTTP digest authentication, or `bearer_token` for OAuth 2.0 bearer token authentication. Defaults to `basic`. + default: digest + selector: + select: + options: + - "digest" + - "bearer_token" + target: + name: Target + description: An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default. + example: "[12345, 67890] or 12345" + selector: + object: + disable_notification: + name: Disable notification + description: Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound. + selector: + boolean: + verify_ssl: + name: Verify SSL + description: Enable or disable SSL certificate verification. Set to false if you're downloading the file from a URL and you don't want to validate the SSL certificate of the server. + selector: + boolean: + timeout: + name: Timeout + description: Timeout for send voice. Will help with timeout errors (poor internet connection, etc) + selector: + number: + min: 1 + max: 3600 + unit_of_measurement: seconds + keyboard: + name: Keyboard + description: List of rows of commands, comma-separated, to make a custom keyboard. + example: '["/command1, /command2", "/command3"]' + selector: + object: + inline_keyboard: + name: Inline keyboard + description: List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data. + example: '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' + selector: + object: + message_tag: + name: Message tag + description: "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}" + example: "msg_to_edit" + selector: + text: + +send_document: + name: Send document + description: Send a document. + fields: + url: + name: URL + description: Remote path to a document. + example: "http://example.org/path/to/the/document.odf" + selector: + text: + file: + name: File + description: Local path to a document. + example: "/tmp/whatever.odf" + selector: + text: + caption: + name: Caption + description: The title of the document. + example: Document Title xy + selector: + text: + username: + name: Username + description: Username for a URL which require HTTP authentication. + example: myuser + selector: + text: + password: + name: Password + description: Password (or bearer token) for a URL which require HTTP authentication. + example: myuser_pwd + selector: + text: + authentication: + name: Authentication method + description: Define which authentication method to use. Set to `digest` to use HTTP digest authentication, or `bearer_token` for OAuth 2.0 bearer token authentication. Defaults to `basic`. + default: digest + selector: + select: + options: + - "digest" + - "bearer_token" + target: + name: Target + description: An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default. + example: "[12345, 67890] or 12345" + selector: + object: + parse_mode: + name: Parse mode + description: "Parser for the message text." + selector: + select: + options: + - "html" + - "markdown" + - "markdown2" + disable_notification: + name: Disable notification + description: Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound. + selector: + boolean: + verify_ssl: + name: Verify SSL + description: Enable or disable SSL certificate verification. Set to false if you're downloading the file from a URL and you don't want to validate the SSL certificate of the server. + selector: + boolean: + timeout: + name: Timeout + description: Timeout for send document. Will help with timeout errors (poor internet connection, etc) + selector: + number: + min: 1 + max: 3600 + unit_of_measurement: seconds + keyboard: + name: Keyboard + description: List of rows of commands, comma-separated, to make a custom keyboard. + example: '["/command1, /command2", "/command3"]' + selector: + object: + inline_keyboard: + name: Inline keyboard + description: List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data. + example: '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' + selector: + object: + message_tag: + name: Message tag + description: "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}" + example: "msg_to_edit" + selector: + text: + +send_location: + name: Send location + description: Send a location. + fields: + latitude: + name: Latitude + description: The latitude to send. + required: true + selector: + number: + min: -90 + max: 90 + step: 0.001 + unit_of_measurement: "°" + longitude: + name: Longitude + description: The longitude to send. + required: true + selector: + number: + min: -180 + max: 180 + step: 0.001 + unit_of_measurement: "°" + target: + name: Target + description: An array of pre-authorized chat_ids to send the location to. If not present, first allowed chat_id is the default. + example: "[12345, 67890] or 12345" + selector: + object: + disable_notification: + name: Disable notification + description: Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound. + selector: + boolean: + timeout: + name: Timeout + description: Timeout for send photo. Will help with timeout errors (poor internet connection, etc) + selector: + number: + min: 1 + max: 3600 + unit_of_measurement: seconds + keyboard: + name: Keyboard + description: List of rows of commands, comma-separated, to make a custom keyboard. + example: '["/command1, /command2", "/command3"]' + selector: + object: + inline_keyboard: + name: Inline keyboard + description: List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data. + example: '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' + selector: + object: + message_tag: + name: Message tag + description: "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}" + example: "msg_to_edit" + selector: + text: + +edit_message: + name: Edit message + description: Edit a previously sent message. + fields: + message_id: + name: Message ID + description: id of the message to edit. + required: true + example: "{{ trigger.event.data.message.message_id }}" + selector: + text: + chat_id: + name: Chat ID + description: The chat_id where to edit the message. + required: true + example: 12345 + selector: + text: + message: + name: Message + description: Message body of the notification. + example: The garage door has been open for 10 minutes. + selector: + text: + title: + name: Title + description: Optional title for your notification. Will be composed as '%title\n%message' + example: "Your Garage Door Friend" + selector: + text: + parse_mode: + name: Parse mode + description: "Parser for the message text." + selector: + select: + options: + - "html" + - "markdown" + - "markdown2" + disable_web_page_preview: + name: Disable web page preview + description: Disables link previews for links in the message. + selector: + boolean: + inline_keyboard: + name: Inline keyboard + description: List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data. + example: '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' + selector: + object: + +edit_caption: + name: Edit caption + description: Edit the caption of a previously sent message. + fields: + message_id: + name: Message ID + description: id of the message to edit. + required: true + example: "{{ trigger.event.data.message.message_id }}" + selector: + text: + chat_id: + name: Chat ID + description: The chat_id where to edit the caption. + required: true + example: 12345 + selector: + text: + caption: + name: Caption + description: Message body of the notification. + required: true + example: The garage door has been open for 10 minutes. + selector: + text: + inline_keyboard: + name: Inline keyboard + description: List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data. + example: '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' + selector: + object: + +edit_replymarkup: + name: Edit reply markup + description: Edit the inline keyboard of a previously sent message. + fields: + message_id: + name: Message ID + description: id of the message to edit. + required: true + example: "{{ trigger.event.data.message.message_id }}" + selector: + text: + chat_id: + name: Chat ID + description: The chat_id where to edit the reply_markup. + required: true + example: 12345 + selector: + text: + inline_keyboard: + name: Inline keyboard + description: List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data. + required: true + example: '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' + selector: + object: + +answer_callback_query: + name: Answer callback query + description: Respond to a callback query originated by clicking on an online keyboard button. The answer will be displayed to the user as a notification at the top of the chat screen or as an alert. + fields: + message: + name: Message + description: Unformatted text message body of the notification. + required: true + example: "OK, I'm listening" + selector: + text: + callback_query_id: + name: Callback query ID + description: Unique id of the callback response. + required: true + example: "{{ trigger.event.data.id }}" + selector: + text: + show_alert: + name: Show alert + description: Show a permanent notification. + required: true + selector: + boolean: + timeout: + name: Timeout + description: Timeout for sending the answer. Will help with timeout errors (poor internet connection, etc) + selector: + number: + min: 1 + max: 3600 + unit_of_measurement: seconds + +delete_message: + name: Delete message + description: Delete a previously sent message. + fields: + message_id: + name: Message ID + description: id of the message to delete. + required: true + example: "{{ trigger.event.data.message.message_id }}" + selector: + text: + chat_id: + name: Chat ID + description: The chat_id where to delete the message. + required: true + example: 12345 + selector: + text: \ No newline at end of file diff --git a/custom_components/telegram_bot/webhooks.py b/custom_components/telegram_bot/webhooks.py new file mode 100644 index 0000000..222e205 --- /dev/null +++ b/custom_components/telegram_bot/webhooks.py @@ -0,0 +1,107 @@ +"""Support for Telegram bots using webhooks.""" +import datetime as dt +from http import HTTPStatus +from ipaddress import ip_address +import logging + +from telegram.error import TimedOut + +from homeassistant.components.http import HomeAssistantView +from homeassistant.const import EVENT_HOMEASSISTANT_STOP +from homeassistant.helpers.network import get_url + +from . import ( + CONF_ALLOWED_CHAT_IDS, + CONF_TRUSTED_NETWORKS, + CONF_URL, + BaseTelegramBotEntity, + initialize_bot, +) + +_LOGGER = logging.getLogger(__name__) + +TELEGRAM_HANDLER_URL = "/api/telegram_webhooks" +REMOVE_HANDLER_URL = "" + + +async def async_setup_platform(hass, config): + """Set up the Telegram webhooks platform.""" + + bot = initialize_bot(config) + + current_status = await hass.async_add_executor_job(bot.getWebhookInfo) + if not (base_url := config.get(CONF_URL)): + base_url = get_url(hass, require_ssl=True, allow_internal=False) + + # Some logging of Bot current status: + last_error_date = getattr(current_status, "last_error_date", None) + if (last_error_date is not None) and (isinstance(last_error_date, int)): + last_error_date = dt.datetime.fromtimestamp(last_error_date) + _LOGGER.info( + "Telegram webhook last_error_date: %s. Status: %s", + last_error_date, + current_status, + ) + else: + _LOGGER.debug("telegram webhook Status: %s", current_status) + + handler_url = f"{base_url}{TELEGRAM_HANDLER_URL}" + if not handler_url.startswith("https"): + _LOGGER.error("Invalid telegram webhook %s must be https", handler_url) + return False + + def _try_to_set_webhook(): + retry_num = 0 + while retry_num < 3: + try: + return bot.setWebhook(handler_url, timeout=5) + except TimedOut: + retry_num += 1 + _LOGGER.warning("Timeout trying to set webhook (retry #%d)", retry_num) + + if current_status and current_status["url"] != handler_url: + result = await hass.async_add_executor_job(_try_to_set_webhook) + if result: + _LOGGER.info("Set new telegram webhook %s", handler_url) + else: + _LOGGER.error("Set telegram webhook failed %s", handler_url) + return False + + hass.bus.async_listen_once( + EVENT_HOMEASSISTANT_STOP, lambda event: bot.setWebhook(REMOVE_HANDLER_URL) + ) + hass.http.register_view( + BotPushReceiver( + hass, config[CONF_ALLOWED_CHAT_IDS], config[CONF_TRUSTED_NETWORKS] + ) + ) + return True + + +class BotPushReceiver(HomeAssistantView, BaseTelegramBotEntity): + """Handle pushes from Telegram.""" + + requires_auth = False + url = TELEGRAM_HANDLER_URL + name = "telegram_webhooks" + + def __init__(self, hass, allowed_chat_ids, trusted_networks): + """Initialize the class.""" + BaseTelegramBotEntity.__init__(self, hass, allowed_chat_ids) + self.trusted_networks = trusted_networks + + async def post(self, request): + """Accept the POST from telegram.""" + real_ip = ip_address(request.remote) + if not any(real_ip in net for net in self.trusted_networks): + _LOGGER.warning("Access denied from %s", real_ip) + return self.json_message("Access denied", HTTPStatus.UNAUTHORIZED) + + try: + data = await request.json() + except ValueError: + return self.json_message("Invalid JSON", HTTPStatus.BAD_REQUEST) + + if not self.process_message(data): + return self.json_message("Invalid message", HTTPStatus.BAD_REQUEST) + return None \ No newline at end of file diff --git a/custom_components/udp/__init__.py b/custom_components/udp/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/custom_components/udp/udp.py b/custom_components/udp/udp.py deleted file mode 100644 index fb6d755..0000000 --- a/custom_components/udp/udp.py +++ /dev/null @@ -1,141 +0,0 @@ -""" -Custom Component, written by @skalavala - based on the existing TCP component. - -Support for UDP socket based sensors. - -For more details about this platform, please refer to the documentation at -https://home-assistant.io/components/sensor.udp/ -""" -import logging -import socket -import select - -import voluptuous as vol - -from homeassistant.components.sensor import PLATFORM_SCHEMA -from homeassistant.const import ( - CONF_NAME, CONF_HOST, CONF_PORT, CONF_PAYLOAD, CONF_TIMEOUT, - CONF_UNIT_OF_MEASUREMENT, CONF_VALUE_TEMPLATE) -from homeassistant.exceptions import TemplateError -from homeassistant.helpers.entity import Entity -import homeassistant.helpers.config_validation as cv - -_LOGGER = logging.getLogger(__name__) - -CONF_BUFFER_SIZE = 'buffer_size' -CONF_VALUE_ON = 'value_on' - -DEFAULT_BUFFER_SIZE = 1024 -DEFAULT_NAME = 'UDP Sensor' -DEFAULT_TIMEOUT = 10 - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_HOST): cv.string, - vol.Required(CONF_PORT): cv.port, - vol.Required(CONF_PAYLOAD): cv.string, - vol.Optional(CONF_BUFFER_SIZE, default=DEFAULT_BUFFER_SIZE): - cv.positive_int, - vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int, - vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string, - vol.Optional(CONF_VALUE_ON): cv.string, - vol.Optional(CONF_VALUE_TEMPLATE): cv.template, -}) - - -def setup_platform(hass, config, add_entities, discovery_info=None): - """Set up the UDP Sensor.""" - add_entities([UdpSensor(hass, config)]) - - -class UdpSensor(Entity): - """Implementation of a UDP socket based sensor.""" - - required = tuple() - - def __init__(self, hass, config): - """Set all the config values if they exist and get initial state.""" - value_template = config.get(CONF_VALUE_TEMPLATE) - - if value_template is not None: - value_template.hass = hass - - self._hass = hass - self._config = { - CONF_NAME: config.get(CONF_NAME), - CONF_HOST: config.get(CONF_HOST), - CONF_PORT: config.get(CONF_PORT), - CONF_TIMEOUT: config.get(CONF_TIMEOUT), - CONF_PAYLOAD: config.get(CONF_PAYLOAD), - CONF_UNIT_OF_MEASUREMENT: config.get(CONF_UNIT_OF_MEASUREMENT), - CONF_VALUE_TEMPLATE: value_template, - CONF_VALUE_ON: config.get(CONF_VALUE_ON), - CONF_BUFFER_SIZE: config.get(CONF_BUFFER_SIZE), - } - self._state = None - self.update() - - @property - def name(self): - """Return the name of this sensor.""" - name = self._config[CONF_NAME] - if name is not None: - return name - return super(UdpSensor, self).name - - @property - def state(self): - """Return the state of the device.""" - return self._state - - @property - def unit_of_measurement(self): - """Return the unit of measurement of this entity.""" - return self._config[CONF_UNIT_OF_MEASUREMENT] - - def update(self): - """Get the latest value for this sensor.""" - with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock: - sock.settimeout(self._config[CONF_TIMEOUT]) - try: - sock.connect( - (self._config[CONF_HOST], self._config[CONF_PORT])) - except socket.error as err: - _LOGGER.error( - "Unable to connect to %s on port %s: %s", - self._config[CONF_HOST], self._config[CONF_PORT], err) - return - - try: - sock.send(self._config[CONF_PAYLOAD].encode()) - except socket.error as err: - _LOGGER.error( - "Unable to send payload %r to %s on port %s: %s", - self._config[CONF_PAYLOAD], self._config[CONF_HOST], - self._config[CONF_PORT], err) - return - - readable, _, _ = select.select( - [sock], [], [], self._config[CONF_TIMEOUT]) - if not readable: - _LOGGER.warning( - "Timeout (%s second(s)) waiting for a response after " - "sending %r to %s on port %s.", - self._config[CONF_TIMEOUT], self._config[CONF_PAYLOAD], - self._config[CONF_HOST], self._config[CONF_PORT]) - return - - value = sock.recv(self._config[CONF_BUFFER_SIZE]).decode() - - if self._config[CONF_VALUE_TEMPLATE] is not None: - try: - self._state = self._config[CONF_VALUE_TEMPLATE].render( - value=value) - return - except TemplateError: - _LOGGER.error( - "Unable to render template of %r with value: %r", - self._config[CONF_VALUE_TEMPLATE], value) - return - - self._state = value diff --git a/logging.yaml b/logging.yaml index 7428f32..8cf70ca 100644 --- a/logging.yaml +++ b/logging.yaml @@ -1,16 +1,14 @@ default: warning logs: - gsp: critical root: warning pyhap: warning - openzwave: warning py.warnings: warning pywemo.ssdp: warning - libopenzwave: warning simplipy.api: warning netdisco.ssdp: warning aiohttp.server: warning aiohttp.websocket: error + pywemo.subscribe: error homeassistant.core: critical homeassistant.setup: warning homeassistant.loader: warning # hide custom_component warnings @@ -19,9 +17,9 @@ logs: homeassistant.helpers.entity: warning homeassistant.helpers.template: critical homeassistant.components.wemo: critical + homeassistant.components.light: error homeassistant.components.sensor: critical homeassistant.components.cloud.iot: warning - # homeassistant.components.http: warning homeassistant.components.camera: warning homeassistant.components.zwave: critical homeassistant.components.image_processing: warning @@ -39,4 +37,3 @@ logs: homeassistant.components.emulated_hue: warning homeassistant.components.device_tracker: warning homeassistant.components.camera.generic: warning - homeassistant.components.automation.update_zwave_battery_levels: critical diff --git a/lovelace/00_myhome_view.yaml b/lovelace/00_myhome_view.yaml index f911173..74f7a9f 100644 --- a/lovelace/00_myhome_view.yaml +++ b/lovelace/00_myhome_view.yaml @@ -1,31 +1,37 @@ title: My Home icon: mdi:home cards: + - type: alarm-panel + entity: alarm_control_panel.home + icon: mdi:security + color_type: card + show_state: true + name: Security + size: 20% + style: + - height: 75px + - font-weight: bold + - color: rgb(255, 255, 255) + state: + - value: "disarmed" + color: rgb(255,0,0) + - value: "armed_home" + color: rgb(0, 128, 0) + - value: "armed_away" + color: rgb(0, 0, 255) + action: more_info + - type: horizontal-stack cards: - - type: "custom:button-card" - entity: alarm_control_panel.home - icon: mdi:security - color_type: card - show_state: true - style: - - font-weight: bold - - color: rgb(255, 255, 255) - state: - - value: "disarmed" - color: rgb(255,0,0) - - value: "armed_home" - color: rgb(0, 128, 0) - - value: "armed_away" - color: rgb(0, 0, 255) - action: more_info - - - type: "custom:button-card" + - type: button entity: climate.dining_room icon: mdi:thermometer-lines + name: Nest color_type: card - show_state: true + show_state: "on" + size: 20% style: + - height: 75px - font-weight: bold - color: rgb(255, 255, 255) state: @@ -40,67 +46,58 @@ cards: domain: script action: toggle_climate + - type: button + entity: binary_sensor.door_window_sensor_158d000424a6d6 + icon: mdi:door + name: Front Door + color_type: card + show_state: "on" + size: 20% + style: + - height: 75px + - font-weight: bold + - color: rgb(255, 255, 255) + state: + - value: "on" + color: rgb(255,0,0) + - value: "off" + color: rgb(0, 128, 0) + + - type: button + entity: binary_sensor.door_window_sensor_158d00040ad8fc + icon: mdi:door + name: Back Door + color_type: card + show_state: "on" + size: 20% + style: + - height: 75px + - font-weight: bold + - color: rgb(255, 255, 255) + state: + - value: "on" + color: rgb(255,0,0) + - value: "off" + color: rgb(0, 128, 0) + - type: entities title: Kalavala Family show_header_toggle: false entities: - - entity: device_tracker.life360_suresh - name: Suresh - - entity: device_tracker.life360_mallika - name: Mallika - - entity: device_tracker.life360_srinika - name: Srinika - - entity: device_tracker.life360_hasika - name: Hasika - - entity: sensor.yo_mama_geocoded_location - name: Suresh - - entity: sensor.mallika_geocoded_location - name: Mallika + - entity: device_tracker.mallika + name: Mallika's Location + - entity: device_tracker.suresh + name: Suresh's Location + - entity: device_tracker.srinika + name: Srinika's Location + - entity: device_tracker.hasika + name: Hasika's Location + - entity: input_boolean.home_mode_away + name: Home Away Status card: type: glance title: Kalavala Family - - type: entities - title: Pill Reminder - show_header_toggle: false - entities: - - input_datetime.pill_reminder_time - - input_boolean.pill_on_vacation - - input_boolean.pill_taken - - input_boolean.pill_voice_notification - - binary_sensor.door_window_sensor_158d00040ad8ec - - input_label.pill_taken_at - - - type: entities - title: 3D Printer - show_header_toggle: false - entities: - - binary_sensor.octoprint_printing - - binary_sensor.octoprint_printing_error - - sensor.octoprint_current_state - - sensor.octoprint_job_percentage - - sensor.octoprint_time_elapsed - - sensor.octoprint_time_remaining - - - type: glance - show_icon: true - show_name: true - show_state: true - title: Fitness - entities: - - entity: sensor.yo_mama_steps - icon: "mdi:run" - name: Suresh Steps - - entity: sensor.yo_mama_floors_ascended - icon: "mdi:run" - name: Suresh Floors Ascended - - entity: sensor.mallika_steps - icon: "mdi:run" - name: Mallika Steps - - entity: sensor.mallika_floors_ascended - icon: "mdi:run" - name: Mallika Floors Ascended - - type: entity-filter title: For Your Information show_empty: false @@ -135,6 +132,35 @@ cards: type: glance title: FYI + - type: entities + title: Pill Reminder + show_header_toggle: false + entities: + - input_datetime.pill_reminder_time + - input_boolean.pill_taken + - input_boolean.pill_voice_notification + - binary_sensor.door_window_sensor_158d00040ad8ec + - input_label.pill_taken_at + + - type: glance + show_icon: true + show_name: true + show_state: true + title: Fitness + entities: + - entity: sensor.yo_mama_steps + icon: "mdi:run" + name: Suresh Steps + - entity: sensor.yo_mama_floors_ascended + icon: "mdi:run" + name: Suresh Floors Ascended + - entity: sensor.mallika_steps + icon: "mdi:run" + name: Mallika Steps + - entity: sensor.mallika_floors_ascended + icon: "mdi:run" + name: Mallika Floors Ascended + - type: conditional conditions: - entity: input_boolean.emergency_mode @@ -180,6 +206,10 @@ cards: name: Single Car Garage Door - entity: binary_sensor.two_car_garage_door_tilt_sensor_sensor name: Double Car Garage Door + - entity: binary_sensor.door_window_sensor_158d00044e5cb3 + name: Master Bathroom Toilet Door Sensor + - entity: binary_sensor.door_window_sensor_158d00045ab168 + name: Guest Bathroom Door Sensor state_filter: - "on" - "opened" @@ -188,22 +218,9 @@ cards: type: glance title: Doors - - type: weather-forecast + - type: tile entity: weather.dark_sky - - type: conditional - conditions: - - entity: sensor.usps_mail - state_not: "0" - card: - type: picture-entity - id: camera_usps_mail_pictures - title: USPS Mail Pictures - entity: camera.usps_mail_pictures - camera_image: camera.usps_mail_pictures - show_info: true - tap_action: - action: more-info - type: entities title: Xiaomi Motion Sensors @@ -240,13 +257,17 @@ cards: name: Two Car Garage Door - entity: binary_sensor.door_window_sensor_158d0004248d5b name: Single Car Garage Door + - entity: binary_sensor.door_window_sensor_158d00044e5cb3 + name: Master Bathroom Toilet Door Sensor + - entity: binary_sensor.door_window_sensor_158d00045ab168 + name: Guest Bathroom Door Sensor - type: entities title: Plex show_header_toggle: false entities: - sensor.plex_mahasri_nas - + - type: entities title: Luminance show_header_toggle: false @@ -312,18 +333,14 @@ cards: - binary_sensor.driveway_camera_motion - binary_sensor.audio_detector_sensor - binary_sensor.basement_door_sensor_sensor - - binary_sensor.downstairs_multi_sensor_sensor - - binary_sensor.front_room_multi_sensor_sensor - binary_sensor.door_window_sensor_158d000424a6d6 - binary_sensor.garage_door_sensor_sensor - binary_sensor.kitchen_motion_sensor_sensor - binary_sensor.door_window_sensor_158d00040ad8fc # back door - binary_sensor.door_window_sensor_158d0004880f30 # Garage Entry Door - binary_sensor.stairs_motion_sensor_sensor - - binary_sensor.tv_multi_sensor_sensor - binary_sensor.door_window_sensor_158d0004248d5b - binary_sensor.two_car_garage_door_tilt_sensor_sensor - - binary_sensor.upstairs_multi_sensor_sensor state_filter: - "on" - "detected" @@ -334,52 +351,6 @@ cards: title: Motion Sensors show_header_toggle: false - - type: conditional - conditions: - - entity: sensor.season - state: "spring" - card: - type: vertical-stack - cards: - - type: horizontal-stack - cards: - - type: gauge - name: Pollen Today - unit: "%" - entity: sensor.allergy_index_today - max: 12.0 - severity: - green: 0 - yellow: 4 - red: 7 - - type: gauge - name: Pollen Tomorrow - unit: "%" - entity: sensor.allergy_index_tomorrow - max: 12.0 - severity: - green: 0 - yellow: 4 - red: 7 - - type: horizontal-stack - cards: - - type: gauge - name: Asthma Today - unit: "%" - entity: sensor.asthma_index_forecasted_average - severity: - green: 0 - yellow: 4 - red: 7 - - type: gauge - name: Asthma Tomorrow - unit: "%" - entity: sensor.asthma_index_tomorrow - severity: - green: 0 - yellow: 4 - red: 7 - - type: entities title: Motion Counters show_header_toggle: false diff --git a/lovelace/01_lights_view.yaml b/lovelace/01_lights_view.yaml index 6269948..de78769 100644 --- a/lovelace/01_lights_view.yaml +++ b/lovelace/01_lights_view.yaml @@ -2,25 +2,31 @@ title: Lights icon: mdi:lightbulb-on cards: - type: entities - title: Upstairs + title: Master Bedroom show_header_toggle: true entities: - - light.master_bedroom_lights + # - light.master_bedroom_lights + - switch.master_bedroom_fan + - switch.master_bedroom_lights - entity: light.master_bedroom_1 name: Suresh's Bedside Light - entity: light.master_bedroom_2 name: Mallika's Bedside Light - - entity: switch.kids_bedroom - name: Hasika's Bedroom - - entity: switch.kids_bed_accent - name: Hasika's Bed Accent Lights - - entity: switch.guest_bedroom - name: Srinika's Bedroom - - entity: switch.prayer_room - name: Study Room + + # header: + # type: picture + # image: "https://www.home-assistant.io/images/lovelace/header-footer/balloons-header.png" + + - type: entities + title: Master Bathroom + show_header_toggle: true + entities: + - switch.master_bathroom_toilet_light + - switch.master_bathroom_toilet_exhaust + - switch.master_bathroom_shower_exhaust - entity: light.master_bathroom_lights name: Master Bathroom Lights - + - type: entities title: Office Room show_header_toggle: true @@ -29,11 +35,49 @@ cards: - entity: switch.wemoswitch1 name: Office Room Accent Lights + - type: entities + title: Srinika Room + show_header_toggle: true + entities: + - switch.srinika_bedroom + - switch.srinika_bedroom_fan + - switch.srinika_bedroom_fan_light + - light.srinika_led_dimmer_switch + - switch.srinika_bedroom_closet + - switch.srinika_bedroom_accent_lights + + - type: entities + title: Hasika Room + show_header_toggle: true + entities: + - switch.hasika_bedroom + - switch.hasika_bedroom_fan + - switch.hasika_bedroom_fan_light + - light.hasika_led_dimmer_switch + - switch.hasika_bedroom_closet + - switch.hasika_bed_accent + + - type: entities + title: Guest Room + show_header_toggle: true + entities: + - switch.guest_room + - switch.guest_bedroom_fan + - switch.guest_bedroom_fan_light + - light.guest_bedroom_led_dimmer_switch + + - type: entities + title: Guest/Kids Bathroom + show_header_toggle: true + entities: + - switch.guest_bathroom_exhaust + - switch.guest_bathroom_lights + - type: entities title: Family Room show_header_toggle: true entities: - - switch.kitchen + - switch.kitchen_switch - light.family_room_lights - light.hue_color_lamp_1 - light.hue_color_lamp_2 @@ -57,11 +101,11 @@ cards: title: TV Power Strip show_header_toggle: true entities: - - entity: switch.plug_1 + - entity: switch.chromecast_monitor name: Monitor - - entity: switch.plug_2 + - entity: switch.sharp_tv name: Sharp TV - - entity: switch.plug_3 + - entity: switch.bose_audio name: Bose Audio - type: entities @@ -82,13 +126,6 @@ cards: - entity: switch.tasmota_outlet_2 name: Tasmota Outlet 2 - - type: entities - title: Fragrance Outlets - show_header_toggle: true - entities: - - switch.downstairs_fragrance - - switch.upstairs_fragrance - - type: entities title: Garage show_header_toggle: false @@ -102,3 +139,44 @@ cards: entities: - switch.frontyard_light - switch.backyard_light + + # - type: entities + # title: LED Indicators + # show_header_toggle: false + # entities: + # - switch.3d_printer_led + # - switch.basement_left_led + # - switch.basement_right_led + # - switch.front_room_led + # - switch.garage_led + # - switch.garage_shop_lights_led + # - switch.guest_bathroom_exhaust_led + # - switch.guest_bathroom_lights_led + # - switch.guest_bedroom_fan_led + # - switch.guest_bedroom_fan_light_led + # - switch.guest_bedroom_lamp_led + # - switch.guest_bedroom_led_dimmer_switch_led + # - switch.hasika_bed_accent_lights_led + # - switch.hasika_bedroom_closet_led + # - switch.hasika_bedroom_fan_led + # - switch.hasika_bedroom_fan_light_led + # - switch.hasika_bedroom_lamp_led + # - switch.hasika_led_dimmer_switch_led + # - switch.kitchen_switch_led + # - switch.master_bathroom_lights + # - switch.master_bathroom_shower_exhaust_led + # - switch.master_bathroom_toilet_exhaust_led + # - switch.master_bathroom_toilet_light_led + # - switch.master_bedroom_accent_lights_led + # - switch.master_bedroom_fan_led + # - switch.master_bedroom_lights_led + # - switch.office_room_led + # - switch.srinika_bed_accent_lights_led + # - switch.srinika_bedroom_closet_led + # - switch.srinika_bedroom_fan_led + # - switch.srinika_bedroom_fan_light_led + # - switch.srinika_bedroom_lamp_led + # - switch.srinika_led_dimmer_switch_led + # - switch.tp_link_power_strip_b5e2_led + # - switch.tp_link_smart_plug_25ba_led + # - switch.upstairs_fragrance_led \ No newline at end of file diff --git a/lovelace/03_camera_view.yaml b/lovelace/03_camera_view.yaml index 55032ed..febf769 100644 --- a/lovelace/03_camera_view.yaml +++ b/lovelace/03_camera_view.yaml @@ -1,110 +1,95 @@ title: Camera Live icon: mdi:cctv cards: - - type: horizontal-stack + - type: vertical-stack cards: - - type: "custom:button-card" - name: Porch + - type: button + name: RESET CAMERA entity: input_label.current_stream icon: mdi:cctv color_type: card + show_state: false + size: 5% style: - font-weight: bold - color: rgb(0, 0, 5) state: - value: "frontyard" color: var(--primary-color) - action: service - service: - domain: script - action: stream_frontdoor_camera_to_chromecast - - - type: "custom:button-card" - name: Driveway - entity: input_label.current_stream - icon: mdi:cctv - color_type: card - style: - - font-weight: bold - - color: rgb(0, 0, 5) - state: - - value: "driveway" - color: var(--primary-color) - action: service - service: - domain: script - action: stream_driveway_camera_to_chromecast - - - type: "custom:button-card" - name: Patio - entity: input_label.current_stream - icon: mdi:cctv - color_type: card - style: - - font-weight: bold - - color: rgb(0, 0, 5) - state: - - value: "patio" - color: var(--primary-color) - action: service - service: - domain: script - action: stream_patio_camera_to_chromecast - - - type: "custom:button-card" + tap_action: + action: call-service + service: script.reset_camera_stream + - type: horizontal-stack + cards: + - type: button name: Porch entity: input_label.current_stream icon: mdi:cctv color_type: card + show_state: false style: - font-weight: bold - color: rgb(0, 0, 5) state: - value: "porch" color: var(--primary-color) - action: service - service: - domain: script - action: stream_porch_camera_to_chromecast + tap_action: + action: service + service: script.stream_porch_camera_to_chromecast - - type: "custom:button-card" + - type: button + name: Driveway + entity: input_label.current_stream + icon: mdi:cctv + color_type: card + show_state: false + style: + - font-weight: bold + - color: rgb(0, 0, 5) + state: + - value: "driveway" + color: var(--primary-color) + tap_action: + action: call-service + service: script.stream_driveway_camera_to_chromecast + + - type: button + name: Patio + entity: input_label.current_stream + icon: mdi:cctv + color_type: card + show_state: false + style: + - font-weight: bold + - color: rgb(0, 0, 5) + state: + - value: "patio" + color: var(--primary-color) + tap_action: + action: call-service + service: script.stream_patio_camera_to_chromecast + + - type: button name: Playarea entity: input_label.current_stream icon: mdi:cctv color_type: card + show_state: false style: - font-weight: bold - color: rgb(0, 0, 5) state: - value: "playarea" color: var(--primary-color) - action: service - service: - domain: script - action: stream_playarea_camera_to_chromecast - - - type: "custom:button-card" - name: RESET CAMERA - entity: input_label.current_stream - icon: mdi:cctv - color_type: card - style: - - font-weight: bold - - color: rgb(0, 0, 5) - state: - - value: "frontyard" - color: var(--primary-color) - action: service - service: - domain: script - action: reset_camera_stream + tap_action: + action: call-service + service: script.stream_playarea_camera_to_chromecast - type: picture-glance id: camera_frontdoor_camera title: Frontdoor Camera entity: camera.frontdoor_camera camera_image: camera.frontdoor_camera - # camera_view: live show_info: true tap_action: action: more-info @@ -148,28 +133,27 @@ cards: - switch.backyard_light - binary_sensor.playarea_camera_motion - - type: picture-glance - id: camera_garage_camera - title: Garage Camera - entity: camera.garage_camera - camera_image: camera.garage_camera - show_info: true - tap_action: - action: more-info - entities: - - switch.garage + # - type: picture-glance + # id: camera_garage_camera + # title: Garage Camera + # entity: camera.garage_camera + # camera_image: camera.garage_camera + # show_info: true + # tap_action: + # action: more-info + # entities: + # - switch.garage - type: picture-glance - id: camera_3dprinter_camera - title: 3D Printer Camera - entity: camera.3d_printer_camera - camera_image: camera.3d_printer_camera + id: camera_front_camera + title: Front Camera + entity: camera.amcrest_camera + camera_image: camera.amcrest_camera show_info: true tap_action: action: more-info entities: - - binary_sensor.motion_sensor_158d00016c2d0e - - binary_sensor.octoprint_printing + - switch.basement_left - type: picture-glance id: porch_camera @@ -182,3 +166,15 @@ cards: entities: - binary_sensor.porch_motion - switch.frontyard_light + + - type: picture-glance + id: garage_camera + title: Garage Camera + entity: camera.garage + camera_image: camera.garage + show_info: true + tap_action: + action: more-info + entities: + - switch.garage + - switch.garage_shop_lights diff --git a/lovelace/05_tensorflow_view.yaml b/lovelace/05_tensorflow_view.yaml index cf730e2..bef7ca9 100644 --- a/lovelace/05_tensorflow_view.yaml +++ b/lovelace/05_tensorflow_view.yaml @@ -68,17 +68,17 @@ cards: title: Image Processing show_header_toggle: false entities: - - entity: image_processing.tensorflow_frontdoor_camera + - entity: image_processing.doods_frontdoor_camera name: Front Door Camera - - entity: image_processing.tensorflow_driveway_camera + - entity: image_processing.doods_driveway_camera name: Driveway Camera - - entity: image_processing.tensorflow_garage_camera + - entity: image_processing.doods_garage name: Garage Camera - - entity: image_processing.tensorflow_patio_camera + - entity: image_processing.doods_patio_camera name: Patio Camera - - entity: image_processing.tensorflow_playarea_camera + - entity: image_processing.doods_playarea_camera name: Playarea Camera - - entity: image_processing.tensorflow_3d_printer_camera + - entity: image_processing.doods_3d_printer_camera name: 3D Printer Camera - - entity: image_processing.tensorflow_porch_camera + - entity: image_processing.doods_porch_camera name: Porch Camera diff --git a/lovelace/06_tesla_view.yaml b/lovelace/06_tesla_view.yaml index afaaf70..46d1d45 100644 --- a/lovelace/06_tesla_view.yaml +++ b/lovelace/06_tesla_view.yaml @@ -40,7 +40,7 @@ cards: title: Tesla Car show_header_toggle: false entities: - - device_tracker.mahasri_tesla_location_tracker + # - device_tracker.mahasri_tesla_location_tracker - binary_sensor.mahasri_tesla_online_sensor - binary_sensor.mahasri_tesla_parking_brake_sensor - lock.mahasri_tesla_door_lock diff --git a/lovelace/07_system_view.yaml b/lovelace/07_system_view.yaml index e7c139d..628e60a 100644 --- a/lovelace/07_system_view.yaml +++ b/lovelace/07_system_view.yaml @@ -63,12 +63,12 @@ cards: - sensor.esxi_total_ram - sensor.esxi_used_ram - - type: entities - title: Windows Server - show_header_toggle: false - entities: - - sensor.windows_server - - sensor.windows_server_cpu_usage - - sensor.windows_server_idle_time - - sensor.windows_server_memory_available - - sensor.windows_server_memory_used + # - type: entities + # title: Windows Server + # show_header_toggle: false + # entities: + # - sensor.windows_server + # - sensor.windows_server_cpu_usage + # - sensor.windows_server_idle_time + # - sensor.windows_server_memory_available + # - sensor.windows_server_memory_used diff --git a/lovelace/08_multimedia_view.yaml b/lovelace/08_multimedia_view.yaml index f76ff6b..a50a1df 100644 --- a/lovelace/08_multimedia_view.yaml +++ b/lovelace/08_multimedia_view.yaml @@ -1,21 +1,6 @@ title: Multi Room Audio & TTS icon: mdi:television cards: - # - type: entities - # title: Snapcast Server Commands - # show_header_toggle: false - # entities: - # - entity: input_select.snapcast_server - # name: Snapcast Server Command - - - type: entities - title: Raspberry Pi Commands - show_header_toggle: false - entities: - - entity: input_select.raspberry_pis - name: Select a Raspberry Pi - - entity: input_select.rpi_commands - name: Select Command To Execute - type: entities title: Raspberry Pi Scripts @@ -42,13 +27,10 @@ cards: title: Media Players show_header_toggle: false entities: - # - media_player.denon_avr_x2400h - # - media_player.gstreamer - # - media_player.mpd - media_player.attic_tv - - media_player.living_room - - media_player.upstairs - # - media_player.my_denon_receiver + - media_player.living_room # sonos + - media_player.upstairs # sonos + - media_player.smart_tv - type: vertical-stack cards: @@ -56,26 +38,8 @@ cards: entity: media_player.living_room - type: media-control entity: media_player.upstairs - - # - type: media-control - # entity: media_player.denon_avr_x2400h - - # - type: media-control - # entity: media_player.gstreamer - - type: media-control entity: media_player.attic_tv - type: media-control entity: media_player.chromecastultra7021 - # - type: media-control - # entity: media_player.my_denon_receiver - # - type: entities - # title: Snapcast Clients - # show_header_toggle: false - # entities: - # - media_player.snapcast_client_b827eb011e00 - # - media_player.snapcast_client_b827eb4445b1 - # - media_player.snapcast_client_b827eb505e2d - # - media_player.snapcast_client_b827eba8e7ef - # - media_player.snapcast_client_b827ebaa08f7 diff --git a/lovelace/09_settings_view.yaml b/lovelace/09_settings_view.yaml index 9348c82..6c75e27 100644 --- a/lovelace/09_settings_view.yaml +++ b/lovelace/09_settings_view.yaml @@ -5,11 +5,13 @@ cards: cards: - type: horizontal-stack cards: - - type: "custom:button-card" + - type: button name: Automatic Lights entity: input_boolean.light_automations icon: mdi:lightbulb-on color_type: card + show_state: "on" + size: 10% style: - font-weight: bold - color: rgb(0, 0, 5) @@ -21,11 +23,13 @@ cards: domain: input_boolean action: light_automations - - type: "custom:button-card" + - type: button name: Do Not Disturb entity: input_boolean.do_not_disturb - icon: mdi:do-not-disturb + icon: mdi:minus-circle color_type: card + show_state: "on" + size: 10% style: - font-weight: bold - color: rgb(0, 0, 5) @@ -37,11 +41,15 @@ cards: domain: input_boolean action: do_not_disturb - - type: "custom:button-card" + - type: horizontal-stack + cards: + - type: button name: Home Sounds entity: input_boolean.voice_notifications icon: mdi:volume-high color_type: card + show_state: "on" + size: 10% style: - font-weight: bold - color: rgb(0, 0, 5) @@ -53,11 +61,13 @@ cards: domain: input_boolean action: voice_notifications - - type: "custom:button-card" + - type: button name: Location Alerts entity: input_boolean.zone_alerts icon: mdi:map-marker color_type: card + show_state: "on" + size: 10% style: - font-weight: bold - color: rgb(0, 0, 5) @@ -71,11 +81,13 @@ cards: - type: horizontal-stack cards: - - type: "custom:button-card" + - type: button name: Family Movie entity: input_boolean.movie_time icon: mdi:filmstrip color_type: card + show_state: "on" + size: 10% style: - font-weight: bold - color: rgb(0, 0, 5) @@ -87,11 +99,13 @@ cards: domain: input_boolean action: movie_time - - type: "custom:button-card" + - type: button name: Hourly Report entity: input_boolean.hourly_report icon: mdi:timer-sand color_type: card + show_state: "on" + size: 10% style: - font-weight: bold - color: rgb(0, 0, 5) @@ -103,11 +117,15 @@ cards: domain: input_boolean action: hourly_report - - type: "custom:button-card" + - type: horizontal-stack + cards: + - type: button name: Nightly Report entity: input_boolean.nightly_report icon: mdi:weather-night color_type: card + show_state: "on" + size: 10% style: - font-weight: bold - color: rgb(0, 0, 5) @@ -119,11 +137,13 @@ cards: domain: input_boolean action: nightly_report - - type: "custom:button-card" - name: Good Weather + - type: button + name: Go Outside entity: input_boolean.enjoyable_weather_reminders icon: mdi:weather-windy-variant color_type: card + show_state: "on" + size: 10% style: - font-weight: bold - color: rgb(0, 0, 5) @@ -137,11 +157,13 @@ cards: - type: horizontal-stack cards: - - type: "custom:button-card" + - type: button name: Working in Office entity: input_boolean.working_in_office_room icon: mdi:office-building color_type: card + show_state: "on" + size: 10% style: - font-weight: bold - color: rgb(0, 0, 5) @@ -153,11 +175,13 @@ cards: domain: input_boolean action: working_in_office_room - - type: "custom:button-card" + - type: button name: Working in Garage entity: input_boolean.working_in_garage icon: mdi:garage-alert color_type: card + show_state: "on" + size: 10% style: - font-weight: bold - color: rgb(0, 0, 5) @@ -171,11 +195,13 @@ cards: - type: horizontal-stack cards: - - type: "custom:button-card" + - type: button name: Stream Cameras To Chromecast entity: input_boolean.stream_camera2chromecast icon: mdi:cctv color_type: card + show_state: "on" + size: 5% style: - font-weight: bold - color: rgb(0, 0, 5) @@ -194,6 +220,36 @@ cards: - input_number.calendar_remind_before_days - input_number.battery_alert_threshold + - type: entities + title: Garage Timers + show_header_toggle: false + entities: + - input_number.garage_lights + - input_number.garage_shop_lights + + - type: entities + title: Master Suite Timers + show_header_toggle: false + entities: + - input_number.master_bathroom_lights + - input_number.master_bathroom_toilet_lights + - input_number.master_bathroom_shower_exhaust_timer_duration + - input_number.master_bathroom_toilet_exhaust_timer_duration + + - type: entities + title: Kids Bathroom Timers + show_header_toggle: false + entities: + - input_number.guest_bathroom_lights + - input_number.guest_bathroom_exhaust_timer_duration + + - type: entities + title: Kids Bedroom Closet Timers + show_header_toggle: false + entities: + - input_number.srinika_bedroom_closet_lights + - input_number.hasika_bedroom_closet_lights + - type: entities title: Alerts & Notifications show_header_toggle: false diff --git a/lovelace/10_raspberrypi_view.yaml b/lovelace/10_raspberrypi_view.yaml deleted file mode 100644 index 9d1d14a..0000000 --- a/lovelace/10_raspberrypi_view.yaml +++ /dev/null @@ -1,94 +0,0 @@ -title: Raspberry PI -icon: mdi:pig -cards: - - type: horizontal-stack - cards: - - type: "custom:button-card" - name: Query Wifi - entity: inout_boolean.dummy - icon: mdi:wifi - color_type: card - style: - - font-weight: bold - - color: var(--primary-color) - action: service - service: - domain: script - action: query_wifi_info - - type: "custom:button-card" - name: Query Disk - entity: inout_boolean.dummy - icon: mdi:harddisk - color_type: card - style: - - font-weight: bold - - color: var(--primary-color) - action: service - service: - domain: script - action: query_disk_info - - - type: entities - title: Raspberry Pi Commands - show_header_toggle: false - entities: - - input_select.raspberry_pis - - input_select.rpi_commands - - - type: entities - title: WiFi Signal Strength - show_header_toggle: false - entities: - - sensor.kitchen_pi_signal_level - - sensor.family_room_pi_signal_level - - sensor.front_room_pi_signal_level - - sensor.garage_pi_signal_level - - sensor.guest_1_pi_signal_level - - sensor.guest_2_pi_signal_level - - sensor.master_bedroom_pi_signal_level - - - type: entities - title: WiFi Link Quality - show_header_toggle: false - entities: - - sensor.kitchen_pi_link_quality - - sensor.family_room_pi_link_quality - - sensor.front_room_pi_link_quality - - sensor.garage_pi_link_quality - - sensor.guest_1_pi_link_quality - - sensor.guest_2_pi_link_quality - - sensor.master_bedroom_pi_link_quality - - - type: entities - title: RPi Disk Available - show_header_toggle: false - entities: - - sensor.kitchen_pi_available_disk - - sensor.family_room_pi_available_disk - - sensor.front_room_pi_available_disk - - sensor.garage_pi_available_disk - - sensor.guest_1_pi_available_disk - - sensor.guest_2_pi_available_disk - - sensor.master_bedroom_pi_available_disk - - - type: entities - title: RPi Disk Used - show_header_toggle: false - entities: - - sensor.kitchen_pi_disk_used - - sensor.family_room_pi_disk_used - - sensor.front_room_pi_disk_used - - sensor.garage_pi_disk_used - - sensor.guest_1_pi_disk_used - - sensor.guest_2_pi_disk_used - - sensor.master_bedroom_pi_disk_used - - - type: entities - title: RPi Scripts - show_header_toggle: false - entities: - - script.query_disk_info - - script.query_wifi_info - - script.restart_all_raspberrypis - - script.restart_all_snapclients - - script.shutdown_all_raspberrypis diff --git a/lovelace/11_scripts_view.yaml b/lovelace/11_scripts_view.yaml index 5dddfce..5837992 100644 --- a/lovelace/11_scripts_view.yaml +++ b/lovelace/11_scripts_view.yaml @@ -1,34 +1,6 @@ title: Scripts icon: mdi:script cards: - - type: horizontal-stack - cards: - - type: "custom:button-card" - name: Update HASS - entity: inout_boolean.dummy - icon: mdi:home-assistant - color_type: card - style: - - font-weight: bold - - color: var(--primary-color) - action: service - service: - domain: script - action: update_hass - - - type: "custom:button-card" - name: Restart HASS - entity: inout_boolean.dummy - icon: mdi:home-assistant - color_type: card - style: - - font-weight: bold - - color: var(--primary-color) - action: service - service: - domain: script - action: restart_hass - - type: entities title: Notification Scripts show_header_toggle: false diff --git a/lovelace/12_automations_view.yaml b/lovelace/12_automations_view.yaml index d703372..1f00c15 100644 --- a/lovelace/12_automations_view.yaml +++ b/lovelace/12_automations_view.yaml @@ -27,10 +27,7 @@ cards: title: Zone Based Alerts show_header_toggle: false entities: - - automation.alert_private_zone_enter - - automation.alert_private_zone_leaves - automation.alert_when_everyone_is_away - - automation.alert_when_moving - automation.alert_when_someone_enters_a_zone - automation.alert_when_someone_leaves_a_zone - automation.send_a_message_as_i_get_closer_to_home @@ -40,21 +37,14 @@ cards: title: Misc. Notifications show_header_toggle: false entities: - - automation.notify_charger_switch_state - - automation.notify_charging_status - - automation.notify_door_status - automation.notify_holiday_state_change - automation.notify_indian_holidays - - automation.notify_low_battery - automation.notify_thermostat_state_change - - automation.notify_usps_mail - - automation.notify_usps_packages - type: entities title: Timer Automations show_header_toggle: false entities: - - automation.cancel_wfh_timer_when_suresh_leaves_home - automation.family_room_motion_timer - automation.family_room_timer_elapsed - automation.frontroom_motion_timer @@ -64,22 +54,6 @@ cards: - automation.master_bedroom_timer_elapsed - automation.officeroom_motion_timer - automation.officeroom_timer_elapsed - - automation.timer_elapsed_take_a_walk - - automation.upstairs_aroma_timer_elapsed - - automation.upstairs_aroma_timer_finish - - automation.upstairs_aroma_timer_start - - automation.wfh_timer_start - - - type: entities - title: 3D Printer Automations - show_header_toggle: false - entities: - - automation.3d_print_send_telegram_pictures - - automation.3d_print_job_finished - - automation.3d_print_progress_update - - automation.3d_print_state_changed - - automation.3d_print_notify_printer_state - - automation.3d_print_notify_printer_error - type: entities title: Garage Automations @@ -121,7 +95,6 @@ cards: title: Light Automations show_header_toggle: false entities: - - automation.restore_familyroom_lights - automation.evening_indoor_lights_on_before_sunset - automation.evening_outdoor_lights_on_at_sunset - automation.garage_lights_on_when_door_is_opened @@ -197,17 +170,8 @@ cards: - automation.notify_home_status_when_away - automation.home_mode_away_on - automation.hourly_report_during_day_time - - automation.check_wi_fi_status_of_iphones_at_home - automation.night_bedtime_report - - type: entities - title: Raspberry Pi Automations - show_header_toggle: false - entities: - - automation.query_rpi_disk_data - - automation.query_rpi_wifi_data - - automation.raspberry_pi_command - - type: entities title: Media Player Automations show_header_toggle: false diff --git a/lovelace/13_qnap_view.yaml b/lovelace/13_qnap_view.yaml index 12f8fa4..2641649 100644 --- a/lovelace/13_qnap_view.yaml +++ b/lovelace/13_qnap_view.yaml @@ -6,7 +6,7 @@ cards: cards: - type: horizontal-stack cards: - - type: "custom:button-card" + - type: button entity: sensor.kalavala_nas_smart_status_drive_0_1 name: Drive 1 color_type: card @@ -20,7 +20,7 @@ cards: - value: "FAIL" color: rgb(255, 0, 0) action: more_info - - type: "custom:button-card" + - type: button entity: sensor.kalavala_nas_smart_status_drive_0_2 name: Drive 2 color_type: card @@ -34,7 +34,7 @@ cards: - value: "FAIL" color: rgb(255, 0, 0) action: more_info - - type: "custom:button-card" + - type: button entity: sensor.kalavala_nas_smart_status_drive_0_3 name: Drive 3 color_type: card @@ -48,7 +48,7 @@ cards: - value: "FAIL" color: rgb(255, 0, 0) action: more_info - - type: "custom:button-card" + - type: button entity: sensor.kalavala_nas_smart_status_drive_0_4 name: Drive 4 color_type: card @@ -115,7 +115,7 @@ cards: cards: - type: horizontal-stack cards: - - type: "custom:button-card" + - type: button entity: sensor.mahasri_nas_smart_status_drive_0_1 name: Drive 1 color_type: card @@ -129,7 +129,7 @@ cards: - value: "FAIL" color: rgb(255, 0, 0) action: more_info - - type: "custom:button-card" + - type: button entity: sensor.mahasri_nas_smart_status_drive_0_2 name: Drive 2 color_type: card @@ -143,7 +143,7 @@ cards: - value: "FAIL" color: rgb(255, 0, 0) action: more_info - - type: "custom:button-card" + - type: button entity: sensor.mahasri_nas_smart_status_drive_0_3 name: Drive 3 color_type: card @@ -157,7 +157,7 @@ cards: - value: "FAIL" color: rgb(255, 0, 0) action: more_info - - type: "custom:button-card" + - type: button entity: sensor.mahasri_nas_smart_status_drive_0_4 name: Drive 4 color_type: card diff --git a/lovelace/15_3d_printer.yaml b/lovelace/15_3d_printer.yaml index 100b53b..5384f5b 100644 --- a/lovelace/15_3d_printer.yaml +++ b/lovelace/15_3d_printer.yaml @@ -42,12 +42,10 @@ cards: title: Print Times show_header_toggle: false entities: - - entity: sensor.time_elapsed - name: Elapsed - - entity: sensor.time_estimated - name: Estimated - - entity: sensor.print_completion - name: Print Completion + - entity: sensor.octoprint_print_start + name: Print Started + - entity: sensor.octoprint_print_end_eta + name: Completed ETA - type: entities title: 3D Printer Settings diff --git a/mos_sub.py b/mos_sub.py deleted file mode 100644 index c70ae3a..0000000 --- a/mos_sub.py +++ /dev/null @@ -1,82 +0,0 @@ -import mosquitto -import os -import urlparse - -# External module imports -import RPi.GPIO as GPIO -import time - -led = 12 -MQTT_SERVER = "x.x.x.xxx" -MQTT_SERVER_PORT = xxx -MQTT_TOPIC = "/home/tv/backlight" -MQTT_USERNAME = "mosquitto" -MQTT_PASSWORD = "xxx" - -# Pin Setup: -GPIO.setmode(GPIO.BOARD) -GPIO.setwarnings(False) -GPIO.setup(led, GPIO.OUT) - -# Define event callbacks -def on_connect(mosq, obj, rc): - print("Return Code On Connect: " + str(rc)) - -def on_message(mosq, obj, msg): - print(msg.topic + " " + str(msg.qos) + " " + str(msg.payload)) - if (str(msg.payload) == "on" or str(msg.payload) == "ON"): - #os.system('python on.py') - GPIO.output(led, GPIO.LOW) - time.sleep(1) - else: - if (str(msg.payload) == "off" or str(msg.payload) == "OFF"): - #os.system('python off.py') - GPIO.output(led, GPIO.HIGH) - time.sleep(1) - else: - if (str(msg.payload) == "FLICKER_TV_OFF"): - for x in range(0, 3): - GPIO.output(led, GPIO.HIGH) - time.sleep(0.25) - GPIO.output(led, GPIO.LOW) - time.sleep(0.25) - else: - if (str(msg.payload) == "FLICKER"): - for x in range(0, 3): - GPIO.output(led, GPIO.LOW) - time.sleep(0.25) - GPIO.output(led, GPIO.HIGH) - time.sleep(0.25) - time.sleep(1.00) - else: - print("Unknown command") - - -def on_subscribe(mosq, obj, mid, granted_qos): - print("Subscribed: " + str(mid) + " " + str(granted_qos)) - -def on_log(mosq, obj, level, string): - print(string) - -mqttc = mosquitto.Mosquitto() - -# Assign event callbacks -mqttc.on_message = on_message -mqttc.on_connect = on_connect -mqttc.on_subscribe = on_subscribe - -# Uncomment to enable debug messages -#mqttc.on_log = on_log - -# Connect -mqttc.username_pw_set(MQTT_USERNAME, MQTT_PASSWORD) -mqttc.connect(MQTT_SERVER, MQTT_SERVER_PORT) - -# Start subscribe, with QoS level 0 -mqttc.subscribe(MQTT_TOPIC, 0) - -# Continue the network loop, exit when an error occurs -rc = 0 -while rc == 0: - rc = mqttc.loop() -print("MQTT Return Code: " + str(rc)) diff --git a/motion_mqtt.py b/motion_mqtt.py deleted file mode 100644 index 5d0b2f7..0000000 --- a/motion_mqtt.py +++ /dev/null @@ -1,31 +0,0 @@ -import os -import time -import paho.mqtt.client as mqtt - -MQTT_SERVER = "192.168.xxx.xxx" -MQTT_SERVER_PORT = 1883 -MQTT_TOPIC = "/garage/motion" -MQTT_USERNAME = "xxx" -MQTT_PASSWORD = "xxx" - -# Define event callbacks -def on_connect(mosq, obj, rc): - print("Return Code On Connect: " + str(rc)) - -def on_log(mosq, obj, level, string): - print(string) - -mqttc = mqtt.Mosquitto() - -# Assign event callbacks -mqttc.on_connect = on_connect - -# Uncomment to enable debug messages -#mqttc.on_log = on_log - -# Connect -mqttc.username_pw_set(MQTT_USERNAME, MQTT_PASSWORD) -mqttc.connect(MQTT_SERVER, MQTT_SERVER_PORT) - -# publish the message -mqttc.publish(MQTT_TOPIC, 'on') \ No newline at end of file diff --git a/packages/3dprinting.yaml b/packages/3dprinting.yaml index 033139b..24b7e8c 100644 --- a/packages/3dprinting.yaml +++ b/packages/3dprinting.yaml @@ -1,274 +1,274 @@ -############################################################################### -# @author : Mahasri Kalavala -# @date : 09/04/2020 -# @package : 3D Printer -# @description : 3D Printer Automations -############################################################################### -homeassistant: - customize: - automation.3d_print: - icon: mdi:printer +# ############################################################################### +# # @author : Mahasri Kalavala +# # @date : 09/04/2020 +# # @package : 3D Printer +# # @description : 3D Printer Automations +# ############################################################################### +# homeassistant: +# customize: +# automation.3d_print: +# icon: mdi:printer -input_boolean: - twenty_five_percent: - name: "25%" - icon: mdi:radiobox-blank +# input_boolean: +# twenty_five_percent: +# name: "25%" +# icon: mdi:radiobox-blank - fifty_percent: - name: "50%" - icon: mdi:brightness-3 +# fifty_percent: +# name: "50%" +# icon: mdi:brightness-3 - seventy_five_percent: - name: "75%" - icon: mdi:brightness-2 +# seventy_five_percent: +# name: "75%" +# icon: mdi:brightness-2 - hundred_percent: - name: "100%" - icon: mdi:brightness-1 +# hundred_percent: +# name: "100%" +# icon: mdi:brightness-1 - power_off_when_complete: - name: Auto Shutoff When Done - icon: mdi:toggle-switch-off +# power_off_when_complete: +# name: Auto Shutoff When Done +# icon: mdi:toggle-switch-off - send_progress_pictures: - name: Send Telegram Pictures - icon: mdi:toggle-switch-off +# send_progress_pictures: +# name: Send Telegram Pictures +# icon: mdi:toggle-switch-off -# -# Octoprint Camera URL in the format -# still_image_url: "http://192.xxx.xxx.xxx/webcam/?action=snapshot" -# mjpeg_url: "http://192.xxx.xxx.xxx/webcam/?action=stream" -# -camera: - - platform: mjpeg - name: 3D Printer Camera - still_image_url: !secret octoprint_cam_snapshot - mjpeg_url: !secret octoprint_cam_stream +# # +# # Octoprint Camera URL in the format +# # still_image_url: "http://192.xxx.xxx.xxx/webcam/?action=snapshot" +# # mjpeg_url: "http://192.xxx.xxx.xxx/webcam/?action=stream" +# # +# camera: +# - platform: mjpeg +# name: 3D Printer Camera +# still_image_url: !secret octoprint_cam_snapshot +# mjpeg_url: !secret octoprint_cam_stream -# -# A couple of template sensors to show the elapsed and estimated time in readable format -# instead of # of seconds (default) -# -sensor: - - platform: template - sensors: - time_elapsed: - value_template: > - {%- macro secondsToReadableString(seconds) %} - {%- set map = {'week': (seconds / 604800) % 604800, - 'day': (seconds / 86400) % 7, 'hour': (seconds / 3600) % 24, - 'minute': (seconds / 60) % 60} -%} - {%- for item in map if map[item] | int > 0 -%} - {%- if loop.first %}{% elif loop.last %}, and {% else %}, {% endif -%} - {{- map[item]|int }} {{ item -}} {{- 's' if map[item]|int > 1 -}} - {%- endfor -%} - {% endmacro %} - {{ secondsToReadableString(states('sensor.octoprint_time_elapsed') |int) }} +# # +# # A couple of template sensors to show the elapsed and estimated time in readable format +# # instead of # of seconds (default) +# # +# sensor: +# # - platform: template +# # sensors: +# # time_elapsed: +# # value_template: > +# # {%- macro secondsToReadableString(seconds) %} +# # {%- set map = {'week': (seconds / 604800) % 604800, +# # 'day': (seconds / 86400) % 7, 'hour': (seconds / 3600) % 24, +# # 'minute': (seconds / 60) % 60} -%} +# # {%- for item in map if map[item] | int > 0 -%} +# # {%- if loop.first %}{% elif loop.last %}, and {% else %}, {% endif -%} +# # {{- map[item]|int }} {{ item -}} {{- 's' if map[item]|int > 1 -}} +# # {%- endfor -%} +# # {% endmacro %} +# # {{ secondsToReadableString(states('sensor.octoprint_time_elapsed') |int) }} - - platform: template - sensors: - time_estimated: - value_template: > - {%- macro secondsToReadableString(seconds) %} - {%- set map = {'week': (seconds / 604800) % 604800, - 'day': (seconds / 86400) % 7, 'hour': (seconds / 3600) % 24, - 'minute': (seconds / 60) % 60 } -%} - {%- for item in map if map[item] | int > 0 -%} - {%- if loop.first %}{% elif loop.last %}, and {% else %}, {% endif -%} - {{- map[item]|int }} {{ item -}} {{- 's' if map[item]|int > 1 -}} - {%- endfor -%} - {% endmacro %} - {{ secondsToReadableString(states('sensor.octoprint_time_remaining') |int) }} +# # - platform: template +# # sensors: +# # time_estimated: +# # value_template: > +# # {%- macro secondsToReadableString(seconds) %} +# # {%- set map = {'week': (seconds / 604800) % 604800, +# # 'day': (seconds / 86400) % 7, 'hour': (seconds / 3600) % 24, +# # 'minute': (seconds / 60) % 60 } -%} +# # {%- for item in map if map[item] | int > 0 -%} +# # {%- if loop.first %}{% elif loop.last %}, and {% else %}, {% endif -%} +# # {{- map[item]|int }} {{ item -}} {{- 's' if map[item]|int > 1 -}} +# # {%- endfor -%} +# # {% endmacro %} +# # {{ secondsToReadableString(states('sensor.octoprint_time_remaining') |int) }} - - platform: template - sensors: - print_completion: - value_template: > - {% set seconds = states('sensor.octoprint_time_remaining')|int %} - {% if utcnow().strftime('%s')|int | timestamp_custom("%A %D") == (utcnow().strftime('%s') |int + seconds) | timestamp_custom("%A %D") %} - Today at {{ (utcnow().strftime('%s')|int + seconds) | timestamp_custom("%I:%M %p") }} - {% else %} - {{ (utcnow().strftime('%s') |int + seconds) | timestamp_custom("%A %D %I:%M %p") }} - {% endif %} +# # - platform: template +# # sensors: +# # print_completion: +# # value_template: > +# # {% set seconds = states('sensor.octoprint_time_remaining')|int %} +# # {% if utcnow().strftime('%s')|int | timestamp_custom("%A %D") == (utcnow().strftime('%s') |int + seconds) | timestamp_custom("%A %D") %} +# # Today at {{ (utcnow().strftime('%s')|int + seconds) | timestamp_custom("%I:%M %p") }} +# # {% else %} +# # {{ (utcnow().strftime('%s') |int + seconds) | timestamp_custom("%A %D %I:%M %p") }} +# # {% endif %} - - platform: template - sensors: - octoprint_actual_bed_temp_c: - unit_of_measurement: "C" - value_template: > - {%- macro F2C(temperature) -%} - {% set tmp = (((temperature - 32) *5)/9) %} - {{- " %0.2f" % tmp }} - {%- endmacro -%} - {{ F2C(states('sensor.octoprint_actual_bed_temp') |int ) |int }} +# - platform: template +# sensors: +# octoprint_actual_bed_temp_c: +# unit_of_measurement: "C" +# value_template: > +# {%- macro F2C(temperature) -%} +# {% set tmp = (((temperature - 32) *5)/9) %} +# {{- " %0.2f" % tmp }} +# {%- endmacro -%} +# {{ F2C(states('sensor.octoprint_actual_bed_temp') |int ) |int }} - - platform: template - sensors: - octoprint_actual_tool0_temp_c: - unit_of_measurement: "C" - value_template: > - {%- macro F2C(temperature) -%} - {% set tmp = (((temperature - 32) *5)/9) %} - {{- " %0.2f" % tmp }} - {%- endmacro -%} - {{ F2C(states('sensor.octoprint_actual_tool0_temp') |int ) |int }} +# - platform: template +# sensors: +# octoprint_actual_tool0_temp_c: +# unit_of_measurement: "C" +# value_template: > +# {%- macro F2C(temperature) -%} +# {% set tmp = (((temperature - 32) *5)/9) %} +# {{- " %0.2f" % tmp }} +# {%- endmacro -%} +# {{ F2C(states('sensor.octoprint_actual_tool0_temp') |int ) |int }} - - platform: template - sensors: - octoprint_target_bed_temp_c: - unit_of_measurement: "C" - value_template: > - {%- macro F2C(temperature) -%} - {% set tmp = (((temperature - 32) *5)/9) %} - {{- " %0.2f" % tmp }} - {%- endmacro -%} - {{ F2C(states('sensor.octoprint_target_bed_temp') |int ) |int }} +# - platform: template +# sensors: +# octoprint_target_bed_temp_c: +# unit_of_measurement: "C" +# value_template: > +# {%- macro F2C(temperature) -%} +# {% set tmp = (((temperature - 32) *5)/9) %} +# {{- " %0.2f" % tmp }} +# {%- endmacro -%} +# {{ F2C(states('sensor.octoprint_target_bed_temp') |int ) |int }} - - platform: template - sensors: - octoprint_target_tool0_temp_c: - unit_of_measurement: "C" - value_template: > - {%- macro F2C(temperature) -%} - {% set tmp = (((temperature - 32) *5)/9) %} - {{- " %0.2f" % tmp }} - {%- endmacro -%} - {{ F2C(states('sensor.octoprint_target_tool0_temp') |int ) |int }} +# - platform: template +# sensors: +# octoprint_target_tool0_temp_c: +# unit_of_measurement: "C" +# value_template: > +# {%- macro F2C(temperature) -%} +# {% set tmp = (((temperature - 32) *5)/9) %} +# {{- " %0.2f" % tmp }} +# {%- endmacro -%} +# {{ F2C(states('sensor.octoprint_target_tool0_temp') |int ) |int }} -automation: - # - # Notify when the printer status changed from "Prnting" to anything. - # Use this later to determine if you want to turn off printer or not - # - - alias: "3D Print State Changed" - trigger: - platform: state - entity_id: "sensor.octoprint_current_state" - from: "Printing" - action: - - service: script.notify_me - data_template: - message: "3D Printer Status Changed from 'Printing' to '{{ trigger.to_state.state }}'." +# - platform: template +# sensors: +# octoprint_print_start: +# value_template: "{{ as_timestamp(states('sensor.octoprint_start_time'))| timestamp_custom('%m/%d/%Y, %H:%M:%S %p') }}" - # - # Updates on the Printer Status - # - - alias: "3D Print Notify Printer State" - trigger: - platform: state - entity_id: "binary_sensor.octoprint_printing" - action: - - service: script.notify_me - data_template: - message: "3D Printer Status changed from '{{ trigger.from_state.state }}' to '{{ trigger.to_state.state }}'." +# - platform: template +# sensors: +# octoprint_print_end_eta: +# value_template: "{{ as_timestamp(states('sensor.octoprint_estimated_finish_time'))| timestamp_custom('%m/%d/%Y, %H:%M:%S %p') }}" - # - # Notifies when the printer errors out - # - - alias: "3D Print Notify Printer Error" - trigger: - platform: state - entity_id: binary_sensor.octoprint_printing_error - to: "on" - action: - - service: script.notify_me - data_template: - message: "3D Printer Status changed to 'ERROR'. Please check the printer!" +# automation: +# # +# # Notify when the printer status changed from "Prnting" to anything. +# # Use this later to determine if you want to turn off printer or not +# # +# - alias: "3D Print State Changed" +# trigger: +# platform: state +# entity_id: "sensor.octoprint_current_state" +# from: "Printing" +# action: +# - service: script.notify_me +# data_template: +# message: "3D Printer Status Changed from 'Printing' to '{{ trigger.to_state.state }}'." - # - # Updates appropriate input booleans based on percentage complete - # - - alias: "3D Print Update Percentage Booleans" - trigger: - platform: state - entity_id: sensor.octoprint_job_percentage - action: - - service_template: "input_boolean.turn_{{- 'on' if states('sensor.octoprint_job_percentage') | int >= 25 else 'off' }}" - entity_id: input_boolean.twenty_five_percent - - service_template: "input_boolean.turn_{{- 'on' if states('sensor.octoprint_job_percentage') | int >= 50 else 'off' }}" - entity_id: input_boolean.fifty_percent - - service_template: "input_boolean.turn_{{- 'on' if states('sensor.octoprint_job_percentage') | int >= 75 else 'off' }}" - entity_id: input_boolean.seventy_five_percent - - service_template: "input_boolean.turn_{{- 'on' if states('sensor.octoprint_job_percentage') | int == 100 else 'off' }}" - entity_id: input_boolean.hundred_percent +# # +# # Updates on the Printer Status +# # +# - alias: "3D Print Notify Printer State" +# trigger: +# platform: state +# entity_id: "binary_sensor.octoprint_printing" +# action: +# - service: script.notify_me +# data_template: +# message: "3D Printer Status changed from '{{ trigger.from_state.state }}' to '{{ trigger.to_state.state }}'." - # - # Provides update at frequent intervals - 25%, 50%, 75%, and 100%! - # - - alias: "3D Print Progress Update" - trigger: - platform: state - entity_id: input_boolean.twenty_five_percent, input_boolean.fifty_percent, input_boolean.seventy_five_percent, input_boolean.hundred_percent - to: "on" - from: "off" - action: - - service: script.notify_me - data_template: - message: >- - {%- macro secondsToReadableString(seconds) %} - {%- set map = {'week': (seconds / 604800) % 604800, - 'day': (seconds / 86400) % 7, 'hour': (seconds / 3600) % 24, - 'minute': (seconds / 60) % 60 } -%} - {%- for item in map if map[item] | int > 0 -%} - {%- if loop.first %}{% elif loop.last %}, and {% else %}, {% endif -%} - {{- map[item]|int }} {{ item -}} {{- 's' if map[item]|int > 1 -}} - {%- endfor -%} - {% endmacro %} - 3D Printer job is now {{ trigger.to_state.attributes.friendly_name }} complete. {% if trigger.entity_id != 'input_boolean.hundred_percent' %} Will be done in {{ secondsToReadableString(states('sensor.octoprint_time_remaining') |int) }}. - {%- endif -%} +# # +# # Notifies when the printer errors out +# # +# - alias: "3D Print Notify Printer Error" +# trigger: +# platform: state +# entity_id: binary_sensor.octoprint_printing_error +# to: "on" +# action: +# - service: script.notify_me +# data_template: +# message: "3D Printer Status changed to 'ERROR'. Please check the printer!" - # - # When the printing is complete (100%), it waits for 2 minutes and turns off the printer. - # It also resets all the input booleans, so that it starts fresh next time. - # Resetting input boleans is not necessary as they get updated automatically when - # octoprint job percentage value chaanges... but why not? - # - - alias: "3d Print Job Finished" - trigger: - platform: state - entity_id: input_boolean.hundred_percent - to: "on" - action: - - condition: template - value_template: "{{ states('input_boolean.power_off_when_complete') == 'on' }}" - - delay: "00:02:00" - - service: switch.turn_off - entity_id: switch.3d_printer - - service: script.notify_me - data_template: - message: "3D Printer is now switched off!" - - service_template: input_boolean.turn_off - entity_id: input_boolean.twenty_five_percent - - service_template: input_boolean.turn_off - entity_id: input_boolean.fifty_percent - - service_template: input_boolean.turn_off - entity_id: input_boolean.seventy_five_percent - - service_template: input_boolean.turn_off - entity_id: input_boolean.hundred_percent +# # +# # Updates appropriate input booleans based on percentage complete +# # +# - alias: "3D Print Update Percentage Booleans" +# trigger: +# platform: state +# entity_id: sensor.octoprint_job_percentage +# action: +# - service_template: "input_boolean.turn_{{- 'on' if states('sensor.octoprint_job_percentage') | int >= 25 else 'off' }}" +# entity_id: input_boolean.twenty_five_percent +# - service_template: "input_boolean.turn_{{- 'on' if states('sensor.octoprint_job_percentage') | int >= 50 else 'off' }}" +# entity_id: input_boolean.fifty_percent +# - service_template: "input_boolean.turn_{{- 'on' if states('sensor.octoprint_job_percentage') | int >= 75 else 'off' }}" +# entity_id: input_boolean.seventy_five_percent +# - service_template: "input_boolean.turn_{{- 'on' if states('sensor.octoprint_job_percentage') | int == 100 else 'off' }}" +# entity_id: input_boolean.hundred_percent - # - # If the printer is ON and is "Printing", it will send a snapshot/picture every 30 minutes - # - - alias: "3D Print Send Telegram Pictures" - trigger: - platform: time_pattern - minutes: "/30" - seconds: 00 - condition: - - condition: template - value_template: "{{ states('input_boolean.send_progress_pictures') == 'on' }}" - - condition: template - value_template: "{{ states('sensor.octoprint_current_state') | lower == 'printing' }}" - action: - - service: camera.snapshot - data: - entity_id: camera.3d_printer_camera - filename: "/config/www/downloads/camera/3dprinter/print_latest.jpg" - - service: notify.telegram - data_template: - title: "3D Printer" - message: "Print Progress" - data: - photo: - - file: "/config/www/downloads/camera/3dprinter/print_latest.jpg" - caption: "3D Print Progress at {{ states('sensor.octoprint_job_percentage') }}%" +# # +# # Provides update at frequent intervals - 25%, 50%, 75%, and 100%! +# # +# - alias: "3D Print Progress Update" +# trigger: +# platform: state +# entity_id: input_boolean.twenty_five_percent, input_boolean.fifty_percent, input_boolean.seventy_five_percent, input_boolean.hundred_percent +# to: "on" +# from: "off" +# action: +# - service: script.notify_me +# data_template: +# message: >- +# 3D Printer job is now {{ trigger.to_state.attributes.friendly_name }} complete. + +# # +# # When the printing is complete (100%), it waits for 2 minutes and turns off the printer. +# # It also resets all the input booleans, so that it starts fresh next time. +# # Resetting input boleans is not necessary as they get updated automatically when +# # octoprint job percentage value chaanges... but why not? +# # +# - alias: "3d Print Job Finished" +# trigger: +# platform: state +# entity_id: input_boolean.hundred_percent +# to: "on" +# action: +# - condition: template +# value_template: "{{ states('input_boolean.power_off_when_complete') == 'on' }}" +# - delay: "00:02:00" +# - service: switch.turn_off +# entity_id: switch.3d_printer +# - service: script.notify_me +# data_template: +# message: "3D Printer is now switched off!" +# - service_template: input_boolean.turn_off +# entity_id: input_boolean.twenty_five_percent +# - service_template: input_boolean.turn_off +# entity_id: input_boolean.fifty_percent +# - service_template: input_boolean.turn_off +# entity_id: input_boolean.seventy_five_percent +# - service_template: input_boolean.turn_off +# entity_id: input_boolean.hundred_percent + +# # +# # If the printer is ON and is "Printing", it will send a snapshot/picture every 30 minutes +# # +# - alias: "3D Print Send Telegram Pictures" +# trigger: +# platform: time_pattern +# minutes: "/30" +# seconds: 00 +# condition: +# - condition: template +# value_template: "{{ states('input_boolean.send_progress_pictures') == 'on' }}" +# - condition: template +# value_template: "{{ states('sensor.octoprint_current_state') | lower == 'printing' }}" +# action: +# - service: camera.snapshot +# data: +# entity_id: camera.3d_printer_camera +# filename: "/config/www/downloads/camera/3dprinter/print_latest.jpg" +# - service: notify.telegram +# data_template: +# title: "3D Printer" +# message: "Print Progress" +# data: +# photo: +# - file: "/config/www/downloads/camera/3dprinter/print_latest.jpg" +# caption: "3D Print Progress at {{ states('sensor.octoprint_job_percentage') }}%" diff --git a/packages/aroma.yaml b/packages/aroma.yaml deleted file mode 100644 index 04e3735..0000000 --- a/packages/aroma.yaml +++ /dev/null @@ -1,113 +0,0 @@ -homeassistant: - customize: - timer.timer_downstairs_aroma: - hidden: true - timer.timer_upstairs_aroma: - hidden: true - -timer: - timer_downstairs_aroma: - duration: "01:00:00" - timer_upstairs_aroma: - duration: "01:00:00" - -############################################################################### -# _ _ _ -# /\ | | | | (_) -# / \ _ _| |_ ___ _ __ ___ __ _| |_ _ ___ _ __ ___ -# / /\ \| | | | __/ _ \| '_ ` _ \ / _` | __| |/ _ \| '_ \/ __| -# / ____ \ |_| | || (_) | | | | | | (_| | |_| | (_) | | | \__ \ -# /_/ \_\__,_|\__\___/|_| |_| |_|\__,_|\__|_|\___/|_| |_|___/ -# -############################################################################### - -automation: - - alias: Downstairs Aroma Timer Start - initial_state: true - trigger: - - platform: state - entity_id: switch.downstairs_fragrance - from: "off" - to: "on" - action: - - service: timer.start - entity_id: timer.timer_downstairs_aroma - - - alias: Downstairs Aroma Timer Finish - initial_state: true - trigger: - - platform: state - entity_id: switch.downstairs_fragrance - from: "on" - to: "off" - action: - - service: timer.finish - entity_id: timer.timer_downstairs_aroma - - - alias: Upstairs Aroma Timer Start - initial_state: true - trigger: - - platform: state - entity_id: switch.upstairs_fragrance - from: "off" - to: "on" - action: - - service: timer.start - entity_id: timer.timer_upstairs_aroma - - - alias: Upstairs Aroma Timer Finish - initial_state: true - trigger: - - platform: state - entity_id: switch.upstairs_fragrance - from: "on" - to: "off" - action: - - service: timer.finish - entity_id: timer.timer_upstairs_aroma - - # - # Timer Elapsed Events - # - - alias: Downstairs Aroma Timer Elapsed - initial_state: true - trigger: - - platform: event - event_type: timer.finished - event_data: - entity_id: timer.timer_downstairs_aroma - action: - - service: switch.turn_off - entity_id: switch.downstairs_fragrance - - - alias: Upstairs Aroma Timer Elapsed - initial_state: true - trigger: - - platform: event - event_type: timer.finished - event_data: - entity_id: timer.timer_upstairs_aroma - action: - - service: switch.turn_off - entity_id: switch.upstairs_fragrance - - # - # Turn ON fragrance outlets automatically at specific times of the day - # - - alias: Turn On Upstairs Aroma - trigger: - - platform: time - at: "08:00:00" - - platform: time - at: "20:00:00" - action: - - service: switch.turn_on - entity_id: switch.upstairs_fragrance - - - alias: Turn On Downstairs Aroma - trigger: - - platform: time - at: "17:00:00" - action: - - service: switch.turn_on - entity_id: switch.downstairs_fragrance diff --git a/packages/batteries.yaml b/packages/batteries.yaml index 40b04e4..fd3bcc9 100644 --- a/packages/batteries.yaml +++ b/packages/batteries.yaml @@ -1,473 +1,473 @@ -############################################################################### -# @author : Mahasri Kalavala -# @date : 04/15/2017 -# @package : Batteries -# @description : Status about various baterries (iphones, sensors...etc) -############################################################################### -homeassistant: - customize: - group.batteries: - order: 2 +# ############################################################################### +# # @author : Mahasri Kalavala +# # @date : 04/15/2017 +# # @package : Batteries +# # @description : Status about various baterries (iphones, sensors...etc) +# ############################################################################### +# homeassistant: +# customize: +# group.batteries: +# order: 2 - sensor.suresh_iphone_battery_state: - hidden: true - sensor.mallika_iphone_battery_state: - hidden: true - sensor.srinika_iphone_battery_state: - hidden: true - sensor.hasika_iphone_battery_state: - hidden: true +# sensor.suresh_iphone_battery_state: +# hidden: true +# sensor.mallika_iphone_battery_state: +# hidden: true +# sensor.srinika_iphone_battery_state: +# hidden: true +# sensor.hasika_iphone_battery_state: +# hidden: true - sensor.suresh_iphone_battery_ot: - hidden: true - sensor.mallika_iphone_battery_ot: - hidden: true - sensor.srinika_iphone_battery_ot: - hidden: true - sensor.hasika_iphone_battery_ot: - hidden: true +# sensor.suresh_iphone_battery_ot: +# hidden: true +# sensor.mallika_iphone_battery_ot: +# hidden: true +# sensor.srinika_iphone_battery_ot: +# hidden: true +# sensor.hasika_iphone_battery_ot: +# hidden: true - sensor.hasika_iphone_wifi_state: - friendly_name: Hasika Phone Wi-Fi Status - sensor.mallika_iphone_wifi_state: - friendly_name: Mallika Phone Wi-Fi Status - sensor.srinika_iphone_wifi_state: - friendly_name: Srinika Phone Wi-Fi Status - sensor.suresh_iphone_wifi_state: - friendly_name: Suresh Phone Wi-Fi Status +# sensor.hasika_iphone_wifi_state: +# friendly_name: Hasika Phone Wi-Fi Status +# sensor.mallika_iphone_wifi_state: +# friendly_name: Mallika Phone Wi-Fi Status +# sensor.srinika_iphone_wifi_state: +# friendly_name: Srinika Phone Wi-Fi Status +# sensor.suresh_iphone_wifi_state: +# friendly_name: Suresh Phone Wi-Fi Status -sensor: - - platform: mqtt - state_topic: "owntracks/mallika/mallika" - name: "Mallika iPhone Battery (OT)" - unit_of_measurement: "%" - value_template: "{{ value_json.batt }}" +# sensor: +# - platform: mqtt +# state_topic: "owntracks/mallika/mallika" +# name: "Mallika iPhone Battery (OT)" +# unit_of_measurement: "%" +# value_template: "{{ value_json.batt }}" - - platform: mqtt - state_topic: "owntracks/suresh/suresh" - name: "Suresh iPhone Battery (OT)" - unit_of_measurement: "%" - value_template: "{{ value_json.batt }}" +# - platform: mqtt +# state_topic: "owntracks/suresh/suresh" +# name: "Suresh iPhone Battery (OT)" +# unit_of_measurement: "%" +# value_template: "{{ value_json.batt }}" - - platform: mqtt - state_topic: "owntracks/srinika/srinika" - name: "Srinika iPhone Battery (OT)" - unit_of_measurement: "%" - value_template: "{{ value_json.batt }}" +# - platform: mqtt +# state_topic: "owntracks/srinika/srinika" +# name: "Srinika iPhone Battery (OT)" +# unit_of_measurement: "%" +# value_template: "{{ value_json.batt }}" - - platform: mqtt - state_topic: "owntracks/hasika/hasika" - name: "Hasika iPhone Battery (OT)" - unit_of_measurement: "%" - value_template: "{{ value_json.batt }}" +# - platform: mqtt +# state_topic: "owntracks/hasika/hasika" +# name: "Hasika iPhone Battery (OT)" +# unit_of_measurement: "%" +# value_template: "{{ value_json.batt }}" - - platform: mqtt - state_topic: "owntracks/mallika/mallika" - name: "Mallika iPhone Battery State" - value_template: > - {% if value_json.charging == 1 %} - Charging - {% else %} - Not Charging - {% endif %} - icon: "mdi:battery-charging" +# - platform: mqtt +# state_topic: "owntracks/mallika/mallika" +# name: "Mallika iPhone Battery State" +# value_template: > +# {% if value_json.charging == 1 %} +# Charging +# {% else %} +# Not Charging +# {% endif %} +# icon: "mdi:battery-charging" - - platform: mqtt - state_topic: "owntracks/suresh/suresh" - name: "Suresh iPhone Battery State" - value_template: > - {% if value_json.charging == 1 %} - Charging - {% else %} - Not Charging - {% endif %} - icon: "mdi:battery-charging" +# - platform: mqtt +# state_topic: "owntracks/suresh/suresh" +# name: "Suresh iPhone Battery State" +# value_template: > +# {% if value_json.charging == 1 %} +# Charging +# {% else %} +# Not Charging +# {% endif %} +# icon: "mdi:battery-charging" - - platform: mqtt - state_topic: "owntracks/srinika/srinika" - name: "Srinika iPhone Battery State" - value_template: > - {% if value_json.charging == 1 %} - Charging - {% else %} - Not Charging - {% endif %} - icon: "mdi:battery-charging" +# - platform: mqtt +# state_topic: "owntracks/srinika/srinika" +# name: "Srinika iPhone Battery State" +# value_template: > +# {% if value_json.charging == 1 %} +# Charging +# {% else %} +# Not Charging +# {% endif %} +# icon: "mdi:battery-charging" - - platform: mqtt - state_topic: "owntracks/hasika/hasika" - name: "Hasika iPhone Battery State" - value_template: > - {% if value_json.charging == 1 %} - Charging - {% else %} - Not Charging - {% endif %} - icon: "mdi:battery-charging" +# - platform: mqtt +# state_topic: "owntracks/hasika/hasika" +# name: "Hasika iPhone Battery State" +# value_template: > +# {% if value_json.charging == 1 %} +# Charging +# {% else %} +# Not Charging +# {% endif %} +# icon: "mdi:battery-charging" - - platform: mqtt - state_topic: "owntracks/mallika/mallika" - name: "Mallika iPhone Wifi State" - value_template: > - {% if value_json.conn == "w" %} - Connected - {% else %} - Not Connected - {% endif %} - icon: "mdi:wifi" +# - platform: mqtt +# state_topic: "owntracks/mallika/mallika" +# name: "Mallika iPhone Wifi State" +# value_template: > +# {% if value_json.conn == "w" %} +# Connected +# {% else %} +# Not Connected +# {% endif %} +# icon: "mdi:wifi" - - platform: mqtt - state_topic: "owntracks/suresh/suresh" - name: "Suresh iPhone Wifi State" - value_template: > - {% if value_json.conn == "w" %} - Connected - {% else %} - Not Connected - {% endif %} - icon: "mdi:wifi" +# - platform: mqtt +# state_topic: "owntracks/suresh/suresh" +# name: "Suresh iPhone Wifi State" +# value_template: > +# {% if value_json.conn == "w" %} +# Connected +# {% else %} +# Not Connected +# {% endif %} +# icon: "mdi:wifi" - - platform: mqtt - state_topic: "owntracks/srinika/srinika" - name: "Srinika iPhone Wifi State" - value_template: > - {% if value_json.conn == "w" %} - Connected - {% else %} - Not Connected - {% endif %} - icon: "mdi:wifi" +# - platform: mqtt +# state_topic: "owntracks/srinika/srinika" +# name: "Srinika iPhone Wifi State" +# value_template: > +# {% if value_json.conn == "w" %} +# Connected +# {% else %} +# Not Connected +# {% endif %} +# icon: "mdi:wifi" - - platform: mqtt - state_topic: "owntracks/hasika/hasika" - name: "Hasika iPhone Wifi State" - value_template: > - {% if value_json.conn == "w" %} - Connected - {% else %} - Not Connected - {% endif %} - icon: "mdi:wifi" +# - platform: mqtt +# state_topic: "owntracks/hasika/hasika" +# name: "Hasika iPhone Wifi State" +# value_template: > +# {% if value_json.conn == "w" %} +# Connected +# {% else %} +# Not Connected +# {% endif %} +# icon: "mdi:wifi" - - platform: mqtt - state_topic: "owntracks/mallika/mallika" - name: "Mallika Driving Speed" - value_template: "{{ value_json.vel |int|round}}" - unit_of_measurement: miles +# - platform: mqtt +# state_topic: "owntracks/mallika/mallika" +# name: "Mallika Driving Speed" +# value_template: "{{ value_json.vel |int|round}}" +# unit_of_measurement: miles - - platform: mqtt - state_topic: "owntracks/suresh/suresh" - name: "Suresh Driving Speed" - value_template: "{{ value_json.vel |int|round}}" - unit_of_measurement: miles +# - platform: mqtt +# state_topic: "owntracks/suresh/suresh" +# name: "Suresh Driving Speed" +# value_template: "{{ value_json.vel |int|round}}" +# unit_of_measurement: miles - - platform: mqtt - state_topic: "owntracks/srinika/srinika" - name: "Srinika Driving Speed" - value_template: "{{ value_json.vel |int|round}}" - unit_of_measurement: miles +# - platform: mqtt +# state_topic: "owntracks/srinika/srinika" +# name: "Srinika Driving Speed" +# value_template: "{{ value_json.vel |int|round}}" +# unit_of_measurement: miles - - platform: mqtt - state_topic: "owntracks/hasika/hasika" - name: "Hasika Driving Speed" - value_template: "{{ value_json.vel |int|round}}" - unit_of_measurement: miles +# - platform: mqtt +# state_topic: "owntracks/hasika/hasika" +# name: "Hasika Driving Speed" +# value_template: "{{ value_json.vel |int|round}}" +# unit_of_measurement: miles - - platform: template - sensors: - suresh_iphone_battery_ot: - unit_of_measurement: "%" - value_template: > - {% if states('sensor.suresh_iphone_battery_ot') != "unknown" %} - {{ states('sensor.suresh_iphone_battery_ot')| int }} - {% else %} - 0 - {% endif %} - icon_template: >- - {% if states('sensor.suresh_iphone_battery_ot') != "unknown" %} - {% set battery_level = states('sensor.suresh_iphone_battery_ot')|int (-1)%} - {% set battery_round = (battery_level|int / 10)|int * 10 %} - {% if states('sensor.suresh_iphone_battery_state') | lower == "charging" %} - {% if battery_level == -1 %} - mdi:battery-unknown - {% else %} - {% if battery_round >= 100 %} - mdi:battery-charging-100 - {% elif battery_round > 0 %} - mdi:battery-charging-{{ battery_round }} - {% else %} - mdi:battery-alert - {% endif %} - {% endif %} - {% else %} - {% if battery_level == -1 %} - mdi:battery-unknown - {% else %} - {% if battery_round >= 100 %} - mdi:battery - {% elif battery_round > 0 %} - mdi:battery-{{ battery_round }} - {% else %} - mdi:battery-alert - {% endif %} - {% endif %} - {% endif %} - {% else %} - mdi:battery-alert - {% endif %} +# - platform: template +# sensors: +# suresh_iphone_battery_ot: +# unit_of_measurement: "%" +# value_template: > +# {% if states('sensor.suresh_iphone_battery_ot') != "unknown" %} +# {{ states('sensor.suresh_iphone_battery_ot')| int }} +# {% else %} +# 0 +# {% endif %} +# icon_template: >- +# {% if states('sensor.suresh_iphone_battery_ot') != "unknown" %} +# {% set battery_level = states('sensor.suresh_iphone_battery_ot')|int (-1)%} +# {% set battery_round = (battery_level|int / 10)|int * 10 %} +# {% if states('sensor.suresh_iphone_battery_state') | lower == "charging" %} +# {% if battery_level == -1 %} +# mdi:battery-unknown +# {% else %} +# {% if battery_round >= 100 %} +# mdi:battery-charging-100 +# {% elif battery_round > 0 %} +# mdi:battery-charging-{{ battery_round }} +# {% else %} +# mdi:battery-alert +# {% endif %} +# {% endif %} +# {% else %} +# {% if battery_level == -1 %} +# mdi:battery-unknown +# {% else %} +# {% if battery_round >= 100 %} +# mdi:battery +# {% elif battery_round > 0 %} +# mdi:battery-{{ battery_round }} +# {% else %} +# mdi:battery-alert +# {% endif %} +# {% endif %} +# {% endif %} +# {% else %} +# mdi:battery-alert +# {% endif %} - - platform: template - sensors: - mallika_iphone_battery_ot: - unit_of_measurement: "%" - value_template: "{{ states('sensor.mallika_iphone_battery_ot')|int(-1) }}" - icon_template: >- - {% if states('sensor.mallika_iphone_battery_ot') != "unknown" %} - {% set battery_level = states('sensor.mallika_iphone_battery_ot')|int (-1)%} - {% set battery_round = (battery_level|int / 10)|int * 10 %} - {% if states('sensor.mallika_iphone_battery_state') | lower == "charging" %} - {% if battery_level == -1 %} - mdi:battery-unknown - {% else %} - {% if battery_round >= 100 %} - mdi:battery-charging-100 - {% elif battery_round > 0 %} - mdi:battery-charging-{{ battery_round }} - {% else %} - mdi:battery-alert - {% endif %} - {% endif %} - {% else %} - {% if battery_level == -1 %} - mdi:battery-unknown - {% else %} - {% if battery_round >= 100 %} - mdi:battery - {% elif battery_round > 0 %} - mdi:battery-{{ battery_round }} - {% else %} - mdi:battery-alert - {% endif %} - {% endif %} - {% endif %} - {% else %} - mdi:battery-alert - {% endif %} +# - platform: template +# sensors: +# mallika_iphone_battery_ot: +# unit_of_measurement: "%" +# value_template: "{{ states('sensor.mallika_iphone_battery_ot')|int(-1) }}" +# icon_template: >- +# {% if states('sensor.mallika_iphone_battery_ot') != "unknown" %} +# {% set battery_level = states('sensor.mallika_iphone_battery_ot')|int (-1)%} +# {% set battery_round = (battery_level|int / 10)|int * 10 %} +# {% if states('sensor.mallika_iphone_battery_state') | lower == "charging" %} +# {% if battery_level == -1 %} +# mdi:battery-unknown +# {% else %} +# {% if battery_round >= 100 %} +# mdi:battery-charging-100 +# {% elif battery_round > 0 %} +# mdi:battery-charging-{{ battery_round }} +# {% else %} +# mdi:battery-alert +# {% endif %} +# {% endif %} +# {% else %} +# {% if battery_level == -1 %} +# mdi:battery-unknown +# {% else %} +# {% if battery_round >= 100 %} +# mdi:battery +# {% elif battery_round > 0 %} +# mdi:battery-{{ battery_round }} +# {% else %} +# mdi:battery-alert +# {% endif %} +# {% endif %} +# {% endif %} +# {% else %} +# mdi:battery-alert +# {% endif %} - - platform: template - sensors: - srinika_iphone_battery_ot: - unit_of_measurement: "%" - value_template: "{{ states('sensor.srinika_iphone_battery_ot')|int(-1) }}" - icon_template: >- - {% if states('sensor.srinika_iphone_battery_ot') != "unknown" %} - {% set battery_level = states('sensor.srinika_iphone_battery_ot')|int (-1)%} - {% set battery_round = (battery_level|int / 10)|int * 10 %} - {% if states('sensor.srinika_iphone_battery_state') | lower == "charging" %} - {% if battery_level == -1 %} - mdi:battery-unknown - {% else %} - {% if battery_round >= 100 %} - mdi:battery-charging-100 - {% elif battery_round > 0 %} - mdi:battery-charging-{{ battery_round }} - {% else %} - mdi:battery-alert - {% endif %} - {% endif %} - {% else %} - {% if battery_level == -1 %} - mdi:battery-unknown - {% else %} - {% if battery_round >= 100 %} - mdi:battery - {% elif battery_round > 0 %} - mdi:battery-{{ battery_round }} - {% else %} - mdi:battery-alert - {% endif %} - {% endif %} - {% endif %} - {% else %} - mdi:battery-alert - {% endif %} +# - platform: template +# sensors: +# srinika_iphone_battery_ot: +# unit_of_measurement: "%" +# value_template: "{{ states('sensor.srinika_iphone_battery_ot')|int(-1) }}" +# icon_template: >- +# {% if states('sensor.srinika_iphone_battery_ot') != "unknown" %} +# {% set battery_level = states('sensor.srinika_iphone_battery_ot')|int (-1)%} +# {% set battery_round = (battery_level|int / 10)|int * 10 %} +# {% if states('sensor.srinika_iphone_battery_state') | lower == "charging" %} +# {% if battery_level == -1 %} +# mdi:battery-unknown +# {% else %} +# {% if battery_round >= 100 %} +# mdi:battery-charging-100 +# {% elif battery_round > 0 %} +# mdi:battery-charging-{{ battery_round }} +# {% else %} +# mdi:battery-alert +# {% endif %} +# {% endif %} +# {% else %} +# {% if battery_level == -1 %} +# mdi:battery-unknown +# {% else %} +# {% if battery_round >= 100 %} +# mdi:battery +# {% elif battery_round > 0 %} +# mdi:battery-{{ battery_round }} +# {% else %} +# mdi:battery-alert +# {% endif %} +# {% endif %} +# {% endif %} +# {% else %} +# mdi:battery-alert +# {% endif %} - - platform: template - sensors: - hasika_iphone_battery_ot: - unit_of_measurement: "%" - value_template: "{{ states('sensor.hasika_iphone_battery_ot')|int(-1) }}" - icon_template: >- - {% if states('sensor.hasika_iphone_battery_ot') != "unknown" %} - {% set battery_level = states('sensor.hasika_iphone_battery_ot')|int (-1)%} - {% set battery_round = (battery_level|int / 10)|int * 10 %} - {% if states('sensor.hasika_iphone_battery_state') | lower == "charging" %} - {% if battery_level == -1 %} - mdi:battery-unknown - {% else %} - {% if battery_round >= 100 %} - mdi:battery-charging-100 - {% elif battery_round > 0 %} - mdi:battery-charging-{{ battery_round }} - {% else %} - mdi:battery-alert - {% endif %} - {% endif %} - {% else %} - {% if battery_level == -1 %} - mdi:battery-unknown - {% else %} - {% if battery_round >= 100 %} - mdi:battery - {% elif battery_round > 0 %} - mdi:battery-{{ battery_round }} - {% else %} - mdi:battery-alert - {% endif %} - {% endif %} - {% endif %} - {% else %} - mdi:battery-alert - {% endif %} +# - platform: template +# sensors: +# hasika_iphone_battery_ot: +# unit_of_measurement: "%" +# value_template: "{{ states('sensor.hasika_iphone_battery_ot')|int(-1) }}" +# icon_template: >- +# {% if states('sensor.hasika_iphone_battery_ot') != "unknown" %} +# {% set battery_level = states('sensor.hasika_iphone_battery_ot')|int (-1)%} +# {% set battery_round = (battery_level|int / 10)|int * 10 %} +# {% if states('sensor.hasika_iphone_battery_state') | lower == "charging" %} +# {% if battery_level == -1 %} +# mdi:battery-unknown +# {% else %} +# {% if battery_round >= 100 %} +# mdi:battery-charging-100 +# {% elif battery_round > 0 %} +# mdi:battery-charging-{{ battery_round }} +# {% else %} +# mdi:battery-alert +# {% endif %} +# {% endif %} +# {% else %} +# {% if battery_level == -1 %} +# mdi:battery-unknown +# {% else %} +# {% if battery_round >= 100 %} +# mdi:battery +# {% elif battery_round > 0 %} +# mdi:battery-{{ battery_round }} +# {% else %} +# mdi:battery-alert +# {% endif %} +# {% endif %} +# {% endif %} +# {% else %} +# mdi:battery-alert +# {% endif %} -############################################################################### -# _ _ _ -# /\ | | | | (_) -# / \ _ _| |_ ___ _ __ ___ __ _| |_ _ ___ _ __ ___ -# / /\ \| | | | __/ _ \| '_ ` _ \ / _` | __| |/ _ \| '_ \/ __| -# / ____ \ |_| | || (_) | | | | | | (_| | |_| | (_) | | | \__ \ -# /_/ \_\__,_|\__\___/|_| |_| |_|\__,_|\__|_|\___/|_| |_|___/ -# -############################################################################### +# ############################################################################### +# # _ _ _ +# # /\ | | | | (_) +# # / \ _ _| |_ ___ _ __ ___ __ _| |_ _ ___ _ __ ___ +# # / /\ \| | | | __/ _ \| '_ ` _ \ / _` | __| |/ _ \| '_ \/ __| +# # / ____ \ |_| | || (_) | | | | | | (_| | |_| | (_) | | | \__ \ +# # /_/ \_\__,_|\__\___/|_| |_| |_|\__,_|\__|_|\___/|_| |_|___/ +# # +# ############################################################################### -automation: - # - # This automation alerts family members when they are "moving" - meaning either in driving from work, - # kids got on the school bus, and bus is moving...etc - # This will only announces/ alert when someone is at home. - # - - alias: Alert When Moving - trigger: - platform: numeric_state - entity_id: - - sensor.suresh_driving_speed - - sensor.mallika_driving_speed - - sensor.srinika_driving_speed - - sensor.hasika_driving_speed - above: 8 - condition: - - condition: template - value_template: > - {%- if state_attr('automation.alert_when_moving', 'last_triggered') -%} - {{ (as_timestamp(now()) - as_timestamp(state_attr('automation.alert_when_moving', 'last_triggered'))) > 300 }} - {%- else -%} - true - {%- endif -%} - - condition: template - value_template: "{{ states('input_boolean.home_mode_away') == 'off' }}" - - condition: template - value_template: "{{ states('alarm_control_panel.home') | lower != 'armed_away' }}" - action: - - service: script.voice_notify - data_template: - message: >- - {% set apostrophe = "\'" %} - {{ trigger.entity_id.split('.')[1].split('_')[0] |title ~ apostrophe ~ 's' }} vehicle is in motion. - - service: script.notify_me - data_template: - message: >- - {% set apostrophe = "\'" %} - {{ trigger.entity_id.split('.')[1].split('_')[0] |title ~ apostrophe ~ 's' }} vehicle is going at {{ trigger.to_state.state |round *2 }} mph. +# automation: +# # +# # This automation alerts family members when they are "moving" - meaning either in driving from work, +# # kids got on the school bus, and bus is moving...etc +# # This will only announces/ alert when someone is at home. +# # +# - alias: Alert When Moving +# trigger: +# platform: numeric_state +# entity_id: +# - sensor.suresh_driving_speed +# - sensor.mallika_driving_speed +# - sensor.srinika_driving_speed +# - sensor.hasika_driving_speed +# above: 8 +# condition: +# - condition: template +# value_template: > +# {%- if state_attr('automation.alert_when_moving', 'last_triggered') -%} +# {{ (as_timestamp(now()) - as_timestamp(state_attr('automation.alert_when_moving', 'last_triggered'))) > 300 }} +# {%- else -%} +# true +# {%- endif -%} +# - condition: template +# value_template: "{{ states('input_boolean.home_mode_away') == 'off' }}" +# - condition: template +# value_template: "{{ states('alarm_control_panel.home') | lower != 'armed_away' }}" +# action: +# - service: script.voice_notify +# data_template: +# message: >- +# {% set apostrophe = "\'" %} +# {{ trigger.entity_id.split('.')[1].split('_')[0] |title ~ apostrophe ~ 's' }} vehicle is in motion. +# - service: script.notify_me +# data_template: +# message: >- +# {% set apostrophe = "\'" %} +# {{ trigger.entity_id.split('.')[1].split('_')[0] |title ~ apostrophe ~ 's' }} vehicle is going at {{ trigger.to_state.state |round *2 }} mph. - ############################################################################### - # Automation: Notify of iPhone Low Battery - ############################################################################### - - alias: Notify Low battery - initial_state: true - trigger: - platform: numeric_state - entity_id: - - device_tracker.life360_suresh - - device_tracker.life360_mallika - - device_tracker.life360_srinika - - device_tracker.life360_hasika - value_template: "{{ state.attributes.battery }}" - below: 25 - condition: - - condition: template - value_template: "{{ states('input_boolean.battery_notifications') == 'on' }}" - action: - - service: script.notify_me - data_template: - message: "{{ trigger.to_state.attributes.friendly_name.split(' ')[1] | title }}'s phone battery is : {{ trigger.to_state.attributes.battery }}%." - - service: script.voice_notify - data_template: - message: "{{ trigger.to_state.attributes.friendly_name.split(' ')[1] }}'s phone battery is : {{ trigger.to_state.attributes.battery }}%." - - service: script.led_message - data_template: - message: "{{ trigger.to_state.attributes.friendly_name.split(' ')[1] }}'s phone battery is : {{ trigger.to_state.attributes.battery }}%." +# ############################################################################### +# # Automation: Notify of iPhone Low Battery +# ############################################################################### +# - alias: Notify Low battery +# initial_state: true +# trigger: +# platform: numeric_state +# entity_id: +# - device_tracker.suresh +# - device_tracker.mallika +# - device_tracker.srinika +# - device_tracker.hasika +# value_template: "{{ state.attributes.battery }}" +# below: 25 +# condition: +# - condition: template +# value_template: "{{ states('input_boolean.battery_notifications') == 'on' }}" +# action: +# - service: script.notify_me +# data_template: +# message: "{{ trigger.to_state.attributes.friendly_name.split(' ')[1] | title }}'s phone battery is : {{ trigger.to_state.attributes.battery }}%." +# - service: script.voice_notify +# data_template: +# message: "{{ trigger.to_state.attributes.friendly_name.split(' ')[1] }}'s phone battery is : {{ trigger.to_state.attributes.battery }}%." +# - service: script.led_message +# data_template: +# message: "{{ trigger.to_state.attributes.friendly_name.split(' ')[1] }}'s phone battery is : {{ trigger.to_state.attributes.battery }}%." - # - alias: Alert Low Battery - # trigger: - # - platform: template - # value_template: > - # {% set ns = namespace(lowBattery=false) %} - # {%- for x in states if x.attributes and x.attributes.battery_level and x.attributes.battery_level |int <= 24 %} - # {% set ns.lowBattery = true %}{% endfor %} - # {{ ns.lowBattery }} - # condition: - # - condition: template - # value_template: "{{ ((trigger.to_state.state | int) < states('sensor.battery_alert_threshold') | int) }}" - # action: - # - service: script.voice_notify - # data_template: - # message: > - # {% set ns = namespace(lowBattery="") %} - # {%- for x in states if x.attributes and x.attributes.battery_level and x.attributes.battery_level |int <= 24 %} - # {%- if loop.first %}The {% elif loop.last %} and the {% else %}, the {% endif -%} - # {% set ns.lowBattery = ns.lowBattery ~ ',' ~ x.name %} - # {%- endfor %} - # {{ ns.lowBattery -}} - # {{- ' battery is ' if ns.lowBattery.split(',')|count == 2 else ' batteries are ' -}} less than 25 percent. - # - service: script.led_message - # data_template: - # message: "{{ trigger.to_state.attributes.friendly_name.split(' ')[1] }}'s phone battery is : {{ trigger.to_state.attributes.battery }}%." +# # - alias: Alert Low Battery +# # trigger: +# # - platform: template +# # value_template: > +# # {% set ns = namespace(lowBattery=false) %} +# # {%- for x in states if x.attributes and x.attributes.battery_level and x.attributes.battery_level |int <= 24 %} +# # {% set ns.lowBattery = true %}{% endfor %} +# # {{ ns.lowBattery }} +# # condition: +# # - condition: template +# # value_template: "{{ ((trigger.to_state.state | int) < states('sensor.battery_alert_threshold') | int) }}" +# # action: +# # - service: script.voice_notify +# # data_template: +# # message: > +# # {% set ns = namespace(lowBattery="") %} +# # {%- for x in states if x.attributes and x.attributes.battery_level and x.attributes.battery_level |int <= 24 %} +# # {%- if loop.first %}The {% elif loop.last %} and the {% else %}, the {% endif -%} +# # {% set ns.lowBattery = ns.lowBattery ~ ',' ~ x.name %} +# # {%- endfor %} +# # {{ ns.lowBattery -}} +# # {{- ' battery is ' if ns.lowBattery.split(',')|count == 2 else ' batteries are ' -}} less than 25 percent. +# # - service: script.led_message +# # data_template: +# # message: "{{ trigger.to_state.attributes.friendly_name.split(' ')[1] }}'s phone battery is : {{ trigger.to_state.attributes.battery }}%." - - alias: Check Wi-Fi Status of iPhones At Home - initial_state: true - trigger: - - platform: state - entity_id: - - device_tracker.life360_mallika - - device_tracker.life360_suresh - - device_tracker.life360_srinika - - device_tracker.life360_hasika - from: "not_home" - to: "home" - for: "00:05:00" - condition: - condition: or - conditions: - - condition: state - entity_id: sensor.hasika_iphone_wifi_state - state: "Not Connected" - - condition: state - entity_id: sensor.mallika_iphone_wifi_state - state: "Not Connected" - - condition: state - entity_id: sensor.srinika_iphone_wifi_state - state: "Not Connected" - - condition: state - entity_id: sensor.suresh_iphone_wifi_state - state: "Not Connected" - action: - - service: script.notify_me - data_template: - message: > - {% set member = trigger.entity_id.split('.')[1].split('_')[0] %} - {{ member | title }}'s iPhone is not connected to Wi-Fi at home! - - service: script.voice_notify - data_template: - message: > - {% set member = trigger.entity_id.split('.')[1].split('_')[0] %} - {{ member | title }}'s iPhone is not connected to Wi-Fi at home! +# - alias: Check Wi-Fi Status of iPhones At Home +# initial_state: true +# trigger: +# - platform: state +# entity_id: +# - device_tracker.mallika +# - device_tracker.suresh +# - device_tracker.srinika +# - device_tracker.hasika +# from: "not_home" +# to: "home" +# for: "00:05:00" +# condition: +# condition: or +# conditions: +# - condition: state +# entity_id: sensor.hasika_iphone_wifi_state +# state: "Not Connected" +# - condition: state +# entity_id: sensor.mallika_iphone_wifi_state +# state: "Not Connected" +# - condition: state +# entity_id: sensor.srinika_iphone_wifi_state +# state: "Not Connected" +# - condition: state +# entity_id: sensor.suresh_iphone_wifi_state +# state: "Not Connected" +# action: +# - service: script.notify_me +# data_template: +# message: > +# {% set member = trigger.entity_id.split('.')[1].split('_')[0] %} +# {{ member | title }}'s iPhone is not connected to Wi-Fi at home! +# - service: script.voice_notify +# data_template: +# message: > +# {% set member = trigger.entity_id.split('.')[1].split('_')[0] %} +# {{ member | title }}'s iPhone is not connected to Wi-Fi at home! diff --git a/packages/cameras.yaml b/packages/cameras.yaml index e82ce7b..9bbf27b 100644 --- a/packages/cameras.yaml +++ b/packages/cameras.yaml @@ -13,6 +13,7 @@ homeassistant: # frontdoor_camera_url: http://username:password@192.168.xxx.xxx/ISAPI/Streaming/channels/101/picture # camera: + - platform: generic name: Frontdoor Camera still_image_url: !secret frontdoor_camera_url @@ -58,9 +59,12 @@ camera: # input: porch_camera_rtsp_url # name: Porch Camera - - platform: mjpeg - mjpeg_url: !secret garage_camera_url - name: Garage Camera + # - platform: mjpeg + # mjpeg_url: !secret garage_camera_url + # name: Garage Camera + +# add amcrest cameras + - platform: amcrest - platform: local_file name: Frontdoor Latest Scan @@ -87,6 +91,16 @@ camera: shell_command: reset_camera_stream: !secret camera_stream_restart_docker_url +# Amcrest Camera Model IP8M-T2669EW-AI +amcrest: + - host: !secret amcrest_front_camera_ip + username: !secret amcrest_front_camera_username + password: !secret amcrest_front_camera_password + binary_sensors: + - motion_detected + - crossline_detected + - online + switch: - platform: rest resource: !secret camera_stream_docker_url @@ -132,22 +146,46 @@ binary_sensor: payload_off: "OFF" value_template: "{{ value }}" +# image_processing: +# - platform: tensorflow +# scan_interval: 10000 +# source: +# - entity_id: camera.frontdoor_camera +# - entity_id: camera.driveway_camera +# - entity_id: camera.patio_camera +# - entity_id: camera.playarea_camera +# - entity_id: camera.garage_camera +# - entity_id: camera.3d_printer_camera +# - entity_id: camera.porch_camera +# file_out: +# - "/config/www/downloads/camera/{{- camera_entity.split('.')[1].split('_')[0] -}}/{{ camera_entity.split('.')[1].split('_')[0] }}_latest.jpg" +# - "/config/www/downloads/camera/{{- camera_entity.split('.')[1].split('_')[0] -}}/{{ camera_entity.split('.')[1].split('_')[0] }}_{{ now().strftime('%Y%m%d_%H%M%S') }}.jpg" +# model: +# graph: /config/tensorflow/models/efficientdet_d0_coco17_tpu-32/ + image_processing: - - platform: tensorflow + - platform: doods scan_interval: 10000 + url: !secret doods_server_url + detector: tensorflow source: - entity_id: camera.frontdoor_camera - entity_id: camera.driveway_camera - entity_id: camera.patio_camera - entity_id: camera.playarea_camera - - entity_id: camera.garage_camera + - entity_id: camera.garage - entity_id: camera.3d_printer_camera - entity_id: camera.porch_camera file_out: - "/config/www/downloads/camera/{{- camera_entity.split('.')[1].split('_')[0] -}}/{{ camera_entity.split('.')[1].split('_')[0] }}_latest.jpg" - "/config/www/downloads/camera/{{- camera_entity.split('.')[1].split('_')[0] -}}/{{ camera_entity.split('.')[1].split('_')[0] }}_{{ now().strftime('%Y%m%d_%H%M%S') }}.jpg" - model: - graph: /config/tensorflow/models/efficientdet_d0_coco17_tpu-32/ + labels: + - name: person + confidence: 75 + - name: car + confidence: 90 + - name: truck + confidence: 90 input_label: current_stream: @@ -240,7 +278,7 @@ automation: .replace(' ', '_').replace(':','_').replace('.','_').replace('+','_') ~ '.jpg' }}" - service: image_processing.scan data_template: - entity_id: image_processing.tensorflow_porch_camera + entity_id: image_processing.doods_porch_camera # # Scan front door and driveway cameras when motion detected @@ -261,14 +299,14 @@ automation: value_template: "{{ states('alarm_control_panel.home') == 'armed_home' or states('alarm_control_panel.home') == 'armed_away' }}" - service: image_processing.scan data_template: - entity_id: image_processing.tensorflow_frontdoor_camera + entity_id: image_processing.doods_frontdoor_camera - service: image_processing.scan data_template: - entity_id: image_processing.tensorflow_driveway_camera + entity_id: image_processing.doods_driveway_camera - condition: template value_template: >- - {% if state_attr('image_processing.tensorflow_frontdoor_camera', 'summary') != None %} - {% if state_attr('image_processing.tensorflow_frontdoor_camera', 'summary') |count > 0 %} + {% if state_attr('image_processing.doods_frontdoor_camera', 'summary') != None %} + {% if state_attr('image_processing.doods_frontdoor_camera', 'summary') |count > 0 %} true {% else %} false @@ -280,7 +318,7 @@ automation: - service: script.voice_notify data_template: message: >- - {%- set e_id = "image_processing.tensorflow_frontdoor_camera" -%} + {%- set e_id = "image_processing.doods_frontdoor_camera" -%} {%- if state_attr(e_id, 'summary') -%} {%- set count = state_attr(e_id, 'summary') | count -%} {%- for x in state_attr(e_id, 'summary') | list -%} @@ -295,7 +333,7 @@ automation: data_template: title: 'Front door motion {{ now().strftime("%d %h %Y, %I:%M:%S %p") }}' message: > - {%- set e_id = "image_processing.tensorflow_frontdoor_camera" -%} + {%- set e_id = "image_processing.doods_frontdoor_camera" -%} {%- if state_attr(e_id, 'summary') -%} {%- set count = state_attr(e_id, 'summary') | count -%} {%- for x in state_attr(e_id, 'summary') | list -%} @@ -314,7 +352,7 @@ automation: data_template: title: "Front Door Motion" message: > - {%- set e_id = "image_processing.tensorflow_frontdoor_camera" -%} + {%- set e_id = "image_processing.doods_frontdoor_camera" -%} {%- if state_attr(e_id, 'summary') -%} {%- set count = state_attr(e_id, 'summary') | count -%} {%- for x in state_attr(e_id, 'summary') | list -%} @@ -338,7 +376,7 @@ automation: {% endif %} - service: image_processing.scan data_template: - entity_id: image_processing.tensorflow_garage_camera + entity_id: image_processing.doods_garage # # Scan driveway and frontdoor cameras when motion detected # if the garage doors are open, scan garage cameras as well @@ -361,14 +399,14 @@ automation: value_template: "{{ states('alarm_control_panel.home') == 'armed_home' or states('alarm_control_panel.home') == 'armed_away' }}" - service: image_processing.scan data_template: - entity_id: image_processing.tensorflow_driveway_camera + entity_id: image_processing.doods_driveway_camera - service: image_processing.scan data_template: - entity_id: image_processing.tensorflow_frontdoor_camera + entity_id: image_processing.doods_frontdoor_camera - condition: template value_template: >- - {% if state_attr('image_processing.tensorflow_driveway_camera', 'summary') != None %} - {% if state_attr('image_processing.tensorflow_driveway_camera', 'summary') |count > 0 %} + {% if state_attr('image_processing.doods_driveway_camera', 'summary') != None %} + {% if state_attr('image_processing.doods_driveway_camera', 'summary') |count > 0 %} true {% else %} false @@ -380,7 +418,7 @@ automation: - service: script.voice_notify data_template: message: >- - {%- set e_id = "image_processing.tensorflow_driveway_camera" -%} + {%- set e_id = "image_processing.doods_driveway_camera" -%} {%- if state_attr(e_id, 'summary') -%} {%- set count = state_attr(e_id, 'summary') | count -%} {%- for x in state_attr(e_id, 'summary') | list -%} @@ -394,7 +432,7 @@ automation: data_template: title: "Driveway Motion" message: > - {%- set e_id = "image_processing.tensorflow_driveway_camera" -%} + {%- set e_id = "image_processing.doods_driveway_camera" -%} {%- if state_attr(e_id, 'summary') -%} {%- set count = state_attr(e_id, 'summary') | count -%} {%- for x in state_attr(e_id, 'summary') | list -%} @@ -412,7 +450,7 @@ automation: data_template: title: 'Driveway motion {{ now().strftime("%d %h %Y, %I:%M:%S %p") }}' message: > - {%- set e_id = "image_processing.tensorflow_driveway_camera" -%} + {%- set e_id = "image_processing.doods_driveway_camera" -%} {%- if state_attr(e_id, 'summary') -%} {%- set count = state_attr(e_id, 'summary') | count -%} {%- for x in state_attr(e_id, 'summary') | list -%} @@ -438,7 +476,7 @@ automation: - service: image_processing.scan data_template: - entity_id: image_processing.tensorflow_garage_camera + entity_id: image_processing.doods_garage # # When motion detected in garage, scan garage camera @@ -459,7 +497,7 @@ automation: action: - service: image_processing.scan data_template: - entity_id: image_processing.tensorflow_garage_camera + entity_id: image_processing.doods_garage - condition: template value_template: > {% if states('binary_sensor.door_window_sensor_158d0004248d5b') == "on" or @@ -470,14 +508,14 @@ automation: {% endif %} - service: image_processing.scan data_template: - entity_id: image_processing.tensorflow_driveway_camera + entity_id: image_processing.doods_driveway_camera - service: image_processing.scan data_template: - entity_id: image_processing.tensorflow_frontdoor_camera + entity_id: image_processing.doods_frontdoor_camera - condition: template value_template: >- - {% if state_attr('image_processing.tensorflow_garage_camera', 'summary') != None %} - {% if state_attr('image_processing.tensorflow_garage_camera', 'summary') |count > 0 %} + {% if state_attr('image_processing.doods_garage', 'summary') != None %} + {% if state_attr('image_processing.doods_garage', 'summary') |count > 0 %} true {% else %} false @@ -489,7 +527,7 @@ automation: - service: script.voice_notify data_template: message: >- - {%- set e_id = "image_processing.tensorflow_garage_camera" -%} + {%- set e_id = "image_processing.doods_garage" -%} {%- if state_attr(e_id, 'summary') -%} {%- set count = state_attr(e_id, 'summary') | count -%} {%- for x in state_attr(e_id, 'summary') | list -%} @@ -503,7 +541,7 @@ automation: data_template: title: "Garage Motion" message: > - {%- set e_id = "image_processing.tensorflow_garage_camera" -%} + {%- set e_id = "image_processing.doods_garage" -%} {%- if state_attr(e_id, 'summary') -%} {%- set count = state_attr(e_id, 'summary') | count -%} {%- for x in state_attr(e_id, 'summary') | list -%} @@ -521,7 +559,7 @@ automation: data_template: title: 'Garage motion {{ now().strftime("%d %h %Y, %I:%M:%S %p") }}' message: > - {%- set e_id = "image_processing.tensorflow_garage_camera" -%} + {%- set e_id = "image_processing.doods_garage" -%} {%- if state_attr(e_id, 'summary') -%} {%- set count = state_attr(e_id, 'summary') | count -%} {%- for x in state_attr(e_id, 'summary') | list -%} @@ -556,14 +594,14 @@ automation: value_template: "{{ states('alarm_control_panel.home') == 'armed_home' or states('alarm_control_panel.home') == 'armed_away' }}" - service: image_processing.scan data_template: - entity_id: image_processing.tensorflow_patio_camera + entity_id: image_processing.doods_patio_camera - service: image_processing.scan data_template: - entity_id: image_processing.tensorflow_playarea_camera + entity_id: image_processing.doods_playarea_camera - condition: template value_template: >- - {% if state_attr('image_processing.tensorflow_patio_camera', 'summary') != None %} - {% if state_attr('image_processing.tensorflow_patio_camera', 'summary') |count > 0 %} + {% if state_attr('image_processing.doods_patio_camera', 'summary') != None %} + {% if state_attr('image_processing.doods_patio_camera', 'summary') |count > 0 %} true {% else %} false @@ -575,7 +613,7 @@ automation: - service: script.voice_notify data_template: message: >- - {%- set e_id = "image_processing.tensorflow_patio_camera" -%} + {%- set e_id = "image_processing.doods_patio_camera" -%} {%- if state_attr(e_id, 'summary') -%} {%- set count = state_attr(e_id, 'summary') | count -%} {%- for x in state_attr(e_id, 'summary') | list -%} @@ -589,7 +627,7 @@ automation: data_template: title: "Backyardge Motion" message: > - {%- set e_id = "image_processing.tensorflow_patio_camera" -%} + {%- set e_id = "image_processing.doods_patio_camera" -%} {%- if state_attr(e_id, 'summary') -%} {%- set count = state_attr(e_id, 'summary') | count -%} {%- for x in state_attr(e_id, 'summary') | list -%} @@ -607,7 +645,7 @@ automation: data_template: title: 'Backyard motion {{ now().strftime("%d %h %Y, %I:%M:%S %p") }}' message: > - {%- set e_id = "image_processing.tensorflow_patio_camera" -%} + {%- set e_id = "image_processing.doods_patio_camera" -%} {%- if state_attr(e_id, 'summary') -%} {%- set count = state_attr(e_id, 'summary') | count -%} {%- for x in state_attr(e_id, 'summary') | list -%} @@ -693,7 +731,7 @@ automation: .replace(' ', '_').replace(':','_').replace('.','_').replace('+','_') ~ '.jpg' }}" - service: camera.snapshot data_template: - entity_id: "camera.garage_camera" + entity_id: "camera.garage" filename: "{{ '/config/www/downloads/camera/garage/garage_' ~ (states.binary_sensor.motion_sensor_158d00024ee084.last_updated ~ '').replace('-','_') @@ -742,7 +780,7 @@ automation: .replace(' ', '_').replace(':','_').replace('.','_').replace('+','_') ~ '.jpg' }}" - condition: template - value_template: "{{ states('device_tracker.life360_suresh') == 'home' }}" + value_template: "{{ states('device_tracker.suresh') == 'home' }}" - service: notify.ios_devices data_template: @@ -792,7 +830,7 @@ automation: .replace(' ', '_').replace(':','_').replace('.','_').replace('+','_') ~ '.jpg' }}" - service: camera.snapshot data_template: - entity_id: "camera.garage_camera" + entity_id: "camera.garage" filename: "{{ '/config/www/downloads/camera/garage/garage_' ~ (states.binary_sensor.motion_sensor_158d00024e57fb.last_updated ~ '').replace('-','_') @@ -834,7 +872,7 @@ automation: .replace(' ', '_').replace(':','_').replace('.','_').replace('+','_') ~ '.jpg' }}" - condition: template - value_template: "{{ states('device_tracker.life360_suresh') == 'home' }}" + value_template: "{{ states('device_tracker.suresh') == 'home' }}" - service: notify.ios_devices data_template: message: "Check Driveway camera!" @@ -869,8 +907,8 @@ automation: action: - condition: template value_template: >- - {% if state_attr('image_processing.tensorflow_frontdoor_camera', 'summary') != None %} - {% if state_attr('image_processing.tensorflow_frontdoor_camera', 'summary') |count > 0 %} + {% if state_attr('image_processing.doods_frontdoor_camera', 'summary') != None %} + {% if state_attr('image_processing.doods_frontdoor_camera', 'summary') |count > 0 %} true {% else %} false @@ -924,7 +962,7 @@ automation: .replace(' ', '_').replace(':','_').replace('.','_').replace('+','_') ~ '.jpg' }}" - condition: template - value_template: "{{ states('device_tracker.life360_suresh') == 'home' }}" + value_template: "{{ states('device_tracker.suresh') == 'home' }}" - service: notify.ios_devices data_template: message: "Check Patio camera!" diff --git a/packages/cameras_machinebox.yaml b/packages/cameras_machinebox.yaml deleted file mode 100644 index b622dfb..0000000 --- a/packages/cameras_machinebox.yaml +++ /dev/null @@ -1,409 +0,0 @@ -# # -# # I COMMENTED OUT ALL THE TAGBOX RELATED STUFF AS I USE TENSORFLOW COMPONENT FOR IT. -# # -# homeassistant: -# customize: -# image_processing.facebox_frontdoor_camera: -# friendly_name: People @ Front Door -# image_processing.facebox_driveway_camera: -# friendly_name: People @ Driveway -# image_processing.facebox_patio_camera: -# friendly_name: People @ Patio -# image_processing.facebox_playarea_camera: -# friendly_name: People @ Playarea -# image_processing.facebox_garage_camera: -# friendly_name: People @ Garage - -# image_processing.tagbox_frontdoor_camera: -# friendly_name: Frontdoor Tag -# image_processing.tagbox_driveway_camera: -# friendly_name: Driveway Tag -# image_processing.tagbox_playarea_camera: -# friendly_name: Playarea Tag -# image_processing.tagbox_patio_camera: -# friendly_name: Patio Tag -# image_processing.tagbox_garage_camera: -# friendly_name: Garage Tag - -# sensor.frontdoor_camera_objects: -# friendly_name: Things At Front Door -# sensor.driveway_camera_objects: -# friendly_name: Things At Driveway -# sensor.playarea_camera_objects: -# friendly_name: Things At Playarea -# sensor.patio_camera_objects: -# friendly_name: Things At Patio -# sensor.garage_camera_objects: -# friendly_name: Things in Garage -# sensor.frontdoor_camera_people: -# friendly_name: People At Front Door -# sensor.driveway_camera_people: -# friendly_name: People Driveway -# sensor.playarea_camera_people: -# friendly_name: People Playarea -# sensor.patio_camera_people: -# friendly_name: People Patio -# sensor.garage_camera_people: -# friendly_name: Garage Patio - -# image_processing: -# - platform: facebox -# ip_address: !secret ha_ip_address -# scan_interval: 360 -# port: 8080 -# source: -# - entity_id: camera.frontdoor_camera -# - entity_id: camera.driveway_camera -# - entity_id: camera.patio_camera -# - entity_id: camera.playarea_camera -# - entity_id: camera.garage_camera -# # - platform: tagbox -# # scan_interval: 10000 # Default 10 -# # ip_address: !secret ha_ip_address -# # port: 8081 -# # source: -# # - entity_id: camera.frontdoor_camera -# # - entity_id: camera.driveway_camera -# # - entity_id: camera.patio_camera -# # - entity_id: camera.playarea_camera -# # - entity_id: camera.garage_camera - -# sensor: - -# ## -# #Facebox related sensors -# ## -# - platform: template -# sensors: -# frontdoor_camera_people: -# value_template: >- -# {% set faces = state_attr('image_processing.facebox_frontdoor_camera', 'matched_faces') %} -# {% if None != faces %} -# {% if faces | list | count == 0 %} -# Clear -# {% else %} -# {%- for face in faces | list %}{%- if loop.first %}{% elif loop.last %} and {% else %}, {% endif -%}{{ face }}{%- endfor %} -# {% endif %} -# {% endif %} -# icon_template: mdi:cctv - -# - platform: template -# sensors: -# driveway_camera_people: -# value_template: >- -# {% set faces = state_attr('image_processing.facebox_driveway_camera', 'matched_faces') %} -# {% if None != faces %} -# {% if faces | list | count == 0 %} -# Clear -# {% else %} -# {%- for face in faces | list %}{%- if loop.first %}{% elif loop.last %} and {% else %}, {% endif -%}{{ face }}{%- endfor %} -# {% endif %} -# {% endif %} -# icon_template: mdi:cctv - -# - platform: template -# sensors: -# patio_camera_people: -# value_template: >- -# {% set faces = state_attr('image_processing.facebox_patio_camera', 'matched_faces') %} -# {% if None != faces %} -# {% if faces | list | count == 0 %} -# Clear -# {% else %} -# {%- for face in faces | list %}{%- if loop.first %}{% elif loop.last %} and {% else %}, {% endif -%}{{ face }}{%- endfor %} -# {% endif %} -# {% endif %} -# icon_template: mdi:cctv - -# - platform: template -# sensors: -# playarea_camera_people: -# value_template: >- -# {% set faces = state_attr('image_processing.facebox_playarea_camera', 'matched_faces') %} -# {% if None != faces %} -# {% if faces | list | count == 0 %} -# Clear -# {% else %} -# {%- for face in faces | list %}{%- if loop.first %}{% elif loop.last %} and {% else %}, {% endif -%}{{ face }}{%- endfor %} -# {% endif %} -# {% endif %} -# icon_template: mdi:cctv - -# - platform: template -# sensors: -# garage_camera_people: -# value_template: >- -# {% set faces = state_attr('image_processing.facebox_garage_camera', 'matched_faces') %} -# {% if None != faces %} -# {% if faces | list | count == 0 %} -# Clear -# {% else %} -# {%- for face in faces | list %}{%- if loop.first %}{% elif loop.last %} and {% else %}, {% endif -%}{{ face }}{%- endfor %} -# {% endif %} -# {% endif %} -# icon_template: mdi:cctv - -# # ########################################################################################################################### -# # # Tagbox related Sensors; Please don't go crazy looking at the code. Here is the simple explanation. -# # # The tagbox gives a bunch of tags for each picture, and I eliminate a bunch of unwanted tags by filtering them out -# # # The unwanted tags are something that I really don't care - like a Tree in the front yard. -# # # Then I do custom mapping of the tags that fits my needs. That way I can display what I want rather than what I was given. -# # # I have no control over what tagbox gives, I want to pick and choose tags irrespective of confidence level. -# # ########################################################################################################################### - -# # - platform: template -# # sensors: -# # frontdoor_camera_objects: -# # value_template: >- -# # {% set attribs = state_attr('image_processing.tagbox_frontdoor_camera', 'tags') %} -# # {%- if None != attribs -%} -# # {%- set tag_map = {'Vehicle':'Car', 'Sedan':'Car', 'Luxury vehicle':'Car', 'Driving':'Car', -# # 'Wheel':'Car', 'Automotive design':'Car', 'Automotive exterior':'Car', -# # 'Transport':'Car', 'Sports car':'Car', 'Land vehicle':'Car', 'Supercar':'Car', -# # 'Waterway':'Rain', 'Super car': 'Car' -# # } -%} -# # {%- set unwanted_tags = ['Asphalt', 'Backyard', 'City', 'Estate', 'Flower', 'Garden', 'Grass', 'Tree', 'Car', 'Vehicle', 'Suburb', 'Street', -# # 'Highway', 'Infrastructure', 'Lane', 'Lawn', 'Neighbourhood', 'Public space', 'Super car', 'Snow', 'Winter', 'Supercar', -# # 'Residential area', 'Road', 'Road surface', 'Sidewalk', 'Tarmac', 'Race track', 'Sport venue', 'Soil', 'Outdoor structure', 'Cartoon', 'Poster', 'Illustration', -# # 'Transport', 'Walkway', 'Yard', 'Screenshot', 'Night', 'Lighting and Light', 'Drawing', 'Sketch', 'Stadium', -# # 'Black-and-white', 'Monochrome', 'Monochrome photography', 'Black and White', 'Parking lot', 'Parking', -# # 'Black', 'White', 'Darkness', 'Light', 'Text'] -%} -# # {%- macro filter_unwanted(tags) -%} -# # {%- set comma = joiner(',') -%} -# # {%- for item in tags if item not in unwanted_tags -%}{{- comma() -}}{{- item -}}{% endfor %}{%- endmacro -%} -# # {%- macro mapped_items(tags) -%} -# # {%- set comma = joiner(',') -%} -# # {%- for item in tags if item not in tag_map -%}{{- comma() -}}{{- item -}} -# # {%- endfor -%} -# # {%- for item in tags if item in tag_map -%}{{- comma() -}}{{- tag_map[item] -}}{%- endfor -%} -# # {%- endmacro -%} -# # {% macro get_final_output(output_list) %} -# # {%- for x in output_list if x != "" -%} -# # {%- if loop.first %}{% elif loop.last %},{% else %},{% endif -%}{{- x -}} -# # {%- endfor -%} -# # {% endmacro %} -# # {%- set result = filter_unwanted(attribs| map(attribute='name')|list).split(',') -%} -# # {%- set output = get_final_output(mapped_items(result).split(',') | unique|list) -%} -# # {{- "Clear" if output |trim == "" else output -}} -# # {% endif %} -# # icon_template: mdi:cctv - -# # - platform: template -# # sensors: -# # driveway_camera_objects: -# # value_template: >- -# # {%- set attribs = state_attr('image_processing.tagbox_driveway_camera', 'tags') -%} -# # {%- if None != attribs -%} -# # {%- set tag_map = {'Vehicle':'Car', 'Sedan':'Car', 'Luxury vehicle':'Car', 'Driving':'Car', -# # 'Wheel':'Car', 'Automotive design':'Car', 'Automotive exterior':'Car', -# # 'Transport':'Car', 'Sports car':'Car', 'Land vehicle':'Car','Supercar':'Car', -# # 'Waterway':'Rain', 'Super car': 'Car' -# # } -%} -# # {%- set unwanted_tags = ['Asphalt', 'Backyard', 'City', 'Estate', 'Flower', 'Garden', 'Grass', 'Tree', 'Car', 'Vehicle', 'Suburb', 'Street', -# # 'Highway', 'Infrastructure', 'Lane', 'Lawn', 'Neighbourhood', 'Public space', 'Super car', 'Sport venue', 'Supercar', -# # 'Residential area', 'Road', 'Road surface', 'Sidewalk', 'Tarmac', 'Race track', 'Snow', 'Winter', 'Soil', 'Outdoor structure', 'Cartoon', 'Poster', 'Illustration', -# # 'Transport', 'Walkway', 'Yard', 'Screenshot', 'Night', 'Lighting and Light', 'Drawing', 'Sketch', 'Stadium', -# # 'Black-and-white', 'Monochrome', 'Monochrome photography', 'Black and White', -# # 'Black', 'White', 'Darkness', 'Light', 'Text'] -%} -# # {%- macro filter_unwanted(tags) -%} -# # {%- set comma = joiner(',') -%} -# # {%- for item in tags if item not in unwanted_tags -%}{{- comma() -}}{{- item -}}{% endfor %}{%- endmacro -%} -# # {%- macro mapped_items(tags) -%} -# # {%- set comma = joiner(',') -%} -# # {%- for item in tags if item not in tag_map -%}{{- comma() -}}{{- item -}} -# # {%- endfor -%} -# # {%- for item in tags if item in tag_map -%}{{- comma() -}}{{- tag_map[item] -}}{%- endfor -%} -# # {%- endmacro -%} -# # {% macro get_final_output(output_list) %} -# # {%- for x in output_list if x != "" -%} -# # {%- if loop.first %}{% elif loop.last %},{% else %},{% endif -%}{{- x -}} -# # {%- endfor -%} -# # {% endmacro %} -# # {%- set result = filter_unwanted(attribs| map(attribute='name')|list).split(',') -%} -# # {%- set output = get_final_output(mapped_items(result).split(',') | unique|list) -%} -# # {{- "Clear" if output |trim == "" else output -}} -# # {% endif %} -# # icon_template: mdi:cctv - -# # - platform: template -# # sensors: -# # patio_camera_objects: -# # value_template: >- -# # {% set attribs = state_attr('image_processing.tagbox_patio_camera', 'tags') %} -# # {%- if None != attribs -%} -# # {%- set tag_map = {'Waterway':'Rain'} -%} -# # {%- set unwanted_tags = ['Asphalt', 'Backyard', 'City', 'Estate', 'Flower', 'Garden', 'Grass', 'Tree', 'Vehicle','Driving', 'Transport', 'Car', 'Vehicle', 'Suburb', 'Street', -# # 'Highway', 'Infrastructure', 'Lane', 'Lawn', 'Neighbourhood', 'Public space', 'Car', 'Wheel', 'Sports car','Super car', 'Sport venue', 'Outdoor structure', 'Cartoon', 'Poster', 'Illustration', -# # 'Residential area', 'Road', 'Road surface', 'Sidewalk', 'Tarmac', 'Race track', 'Sedan', 'Automotive design', 'Snow', 'Winter', 'Soil', 'Stadium', -# # 'Transport', 'Walkway', 'Yard', 'Screenshot', 'Night', 'Lighting and Light', 'Luxury vehicle', 'Automotive exterior', 'Drawing', 'Sketch', -# # 'Black-and-white', 'Monochrome', 'Monochrome photography', 'Black and White', 'Black', 'White', 'Light', 'Text'] -%} -# # {%- macro filter_unwanted(tags) -%} -# # {%- set comma = joiner(',') -%} -# # {%- for item in tags if item not in unwanted_tags -%}{{- comma() -}}{{- item -}}{% endfor %}{%- endmacro -%} -# # {%- macro mapped_items(tags) -%} -# # {%- set comma = joiner(',') -%} -# # {%- for item in tags if item not in tag_map -%}{{- comma() -}}{{- item -}} -# # {%- endfor -%} -# # {%- for item in tags if item in tag_map -%}{{- comma() -}}{{- tag_map[item] -}}{%- endfor -%} -# # {%- endmacro -%} -# # {% macro get_final_output(output_list) %} -# # {%- for x in output_list if x != "" -%} -# # {%- if loop.first %}{% elif loop.last %},{% else %},{% endif -%}{{- x -}} -# # {%- endfor -%} -# # {% endmacro %} -# # {%- set result = filter_unwanted(attribs| map(attribute='name')|list).split(',') -%} -# # {%- set output = get_final_output(mapped_items(result).split(',') | unique|list) -%} -# # {{- "Clear" if output |trim == "" else output -}} -# # {% endif %} -# # icon_template: mdi:cctv - -# # - platform: template -# # sensors: -# # playarea_camera_objects: -# # value_template: >- -# # {% set attribs = state_attr('image_processing.tagbox_playarea_camera', 'tags') %} -# # {%- if None != attribs -%} -# # {%- set tag_map = {'Waterway':'Rain'} -%} -# # {%- set unwanted_tags = ['Asphalt', 'Backyard', 'City', 'Estate', 'Flower', 'Garden', 'Grass', 'Tree', 'Vehicle','Driving', 'Transport', 'Car', 'Vehicle', 'Suburb', 'Street', -# # 'Highway', 'Infrastructure', 'Lane', 'Lawn', 'Neighbourhood', 'Public space', 'Car', 'Wheel', 'Sports car', 'Super car', 'Winter', 'Soil', 'Stadium', -# # 'Residential area', 'Road', 'Road surface', 'Sidewalk', 'Tarmac', 'Race track', 'Sedan', 'Automotive design', 'Snow', 'Sport venue', 'Outdoor structure', 'Cartoon', 'Poster', 'Illustration', -# # 'Transport', 'Walkway', 'Yard', 'Screenshot', 'Night', 'Lighting and Light', 'Luxury vehicle', 'Automotive exterior', 'Drawing', 'Sketch', -# # 'Black-and-white', 'Monochrome', 'Monochrome photography', 'Black and White', 'Black', 'White', 'Light', 'Text'] -%} -# # {%- macro filter_unwanted(tags) -%} -# # {%- set comma = joiner(',') -%} -# # {%- for item in tags if item not in unwanted_tags -%}{{- comma() -}}{{- item -}}{% endfor %}{%- endmacro -%} -# # {%- macro mapped_items(tags) -%} -# # {%- set comma = joiner(',') -%} -# # {%- for item in tags if item not in tag_map -%}{{- comma() -}}{{- item -}}{%- endfor -%} -# # {%- for item in tags if item in tag_map -%}{{- comma() -}}{{- tag_map[item] -}}{%- endfor -%} -# # {%- endmacro -%} -# # {% macro get_final_output(output_list) %} -# # {%- for x in output_list if x != "" -%} -# # {%- if loop.first %}{% elif loop.last %},{% else %},{% endif -%}{{- x -}} -# # {%- endfor -%} -# # {% endmacro %} -# # {%- set result = filter_unwanted(attribs| map(attribute='name')|list).split(',') -%} -# # {%- set output = get_final_output(mapped_items(result).split(',') | unique|list) -%} -# # {{- "Clear" if output |trim == "" else output -}} -# # {% endif %} -# # icon_template: mdi:cctv - -# # - platform: template -# # sensors: -# # garage_camera_objects: -# # value_template: >- -# # {% set attribs = state_attr('image_processing.tagbox_garage_camera', 'tags') %} -# # {%- if None != attribs -%} -# # {%- set tag_map = {'Waterway':'Rain'} -%} -# # {%- set unwanted_tags = ['Asphalt', 'Backyard', 'City', 'Estate', 'Flower', 'Garden', 'Grass', 'Tree', 'Driving', 'Transport', 'Suburb', 'Street', -# # 'Highway', 'Infrastructure', 'Lane', 'Lawn', 'Neighbourhood', 'Public space', 'Winter', 'Soil', 'Stadium', -# # 'Residential area', 'Road', 'Road surface', 'Sidewalk', 'Tarmac', 'Race track', 'Sedan', 'Automotive design', 'Snow', 'Sport venue', 'Outdoor structure', 'Cartoon', 'Poster', 'Illustration', -# # 'Transport', 'Walkway', 'Yard', 'Screenshot', 'Night', 'Lighting and Light', 'Luxury vehicle', 'Automotive exterior', 'Drawing', 'Sketch', -# # 'Black-and-white', 'Monochrome', 'Monochrome photography', 'Black and White', 'Black', 'White', 'Light', 'Text'] -%} -# # {%- macro filter_unwanted(tags) -%} -# # {%- set comma = joiner(',') -%} -# # {%- for item in tags if item not in unwanted_tags -%}{{- comma() -}}{{- item -}}{% endfor %}{%- endmacro -%} -# # {%- macro mapped_items(tags) -%} -# # {%- set comma = joiner(',') -%} -# # {%- for item in tags if item not in tag_map -%}{{- comma() -}}{{- item -}}{%- endfor -%} -# # {%- for item in tags if item in tag_map -%}{{- comma() -}}{{- tag_map[item] -}}{%- endfor -%} -# # {%- endmacro -%} -# # {% macro get_final_output(output_list) %} -# # {%- for x in output_list if x != "" -%} -# # {%- if loop.first %}{% elif loop.last %},{% else %},{% endif -%}{{- x -}} -# # {%- endfor -%} -# # {% endmacro %} -# # {%- set result = filter_unwanted(attribs| map(attribute='name')|list).split(',') -%} -# # {%- set output = get_final_output(mapped_items(result).split(',') | unique|list) -%} -# # {{- "Clear" if output |trim == "" else output -}} -# # {% endif %} -# # icon_template: mdi:cctv - -# automation: - -# - alias: Alert Family Member Activity -# trigger: -# - platform: state -# entity_id: -# - sensor.frontdoor_camera_people -# - sensor.driveway_camera_people -# - sensor.patio_camera_people -# - sensor.playarea_camera_people -# - sensor.garage_camera_people -# condition: -# - condition: template -# value_template: "{{ states('input_boolean.notify_camera_alerts') == 'on' }}" -# - condition: template -# value_template: '{{ trigger.to_state.state | trim != "" and -# trigger.to_state.state | lower | trim != "unknown" and -# trigger.to_state.state | lower | trim != "clear" }}' -# action: -# - service: script.notify_me -# data_template: -# message: >- -# {% set camera_name = states['camera'][trigger.entity_id.split('.')[1].split('_')[0] ~ '_camera'].attributes.friendly_name %} -# {{ trigger.to_state.state }} is at the {{ camera_name }}. - -# # - alias: Alert Object Activity -# # trigger: -# # - platform: state -# # entity_id: -# # - sensor.frontdoor_camera_objects -# # - sensor.driveway_camera_objects -# # - sensor.patio_camera_objects -# # - sensor.playarea_camera_objects -# # - sensor.garage_camera_objects -# # condition: -# # - condition: template -# # value_template: "{{ states('input_boolean.notify_camera_alerts') == 'on' }}" -# # - condition: template -# # value_template: '{{ trigger.to_state.state | trim != "" and -# # trigger.to_state.state | lower | trim != "unknown" and -# # trigger.to_state.state | lower | trim != "clear" }}' -# # action: -# # - service: script.notify_me -# # data_template: -# # message: >- -# # {% set camera_name = states['camera'][trigger.entity_id.split('.')[1].split('_')[0] ~ '_camera'].attributes.friendly_name %} -# # {{ trigger.to_state.state }} detected at the {{ camera_name }}. - -# # -# # This automation basically scans image and keeps a count of people from each camera view and notifies using iOS notification -# # There is another automation that alerts in the house (using TTS) based on the data -# # -# - alias: Scan People and Objects -# initial_state: true -# trigger: -# - platform: state -# entity_id: -# - binary_sensor.frontdoor_camera_motion -# - binary_sensor.driveway_camera_motion -# - binary_sensor.patio_camera_motion -# - binary_sensor.playarea_camera_motion -# - binary_sensor.frontdoor_camera_field_detection -# - binary_sensor.driveway_camera_field_detection -# - binary_sensor.patio_camera_field_detection -# - binary_sensor.playarea_camera_field_detection -# - binary_sensor.frontdoor_camera_line_crossing -# - binary_sensor.driveway_camera_line_crossing -# - binary_sensor.patio_camera_line_crossing -# - binary_sensor.playarea_camera_line_crossing -# - binary_sensor.garage_motion -# to: 'on' -# condition: -# - condition: template -# value_template: "{{ states('input_boolean.notify_camera_alerts') == 'on' }}" -# - condition: template -# value_template: > -# {% macro last_triggered(entity) %} -# {% set time_in_seconds = 30 %} -# {{ ( (as_timestamp(now()) - as_timestamp(states["binary_sensor"][entity].attributes.last_tripped_time)))|round|abs < time_in_seconds }} -# {% endmacro %} -# {{ last_triggered(trigger.entity_id.split('.')[1].split('_')[0] ~ '_camera_motion')}} -# action: -# - service: image_processing.scan -# data_template: -# entity_id: "image_processing.facebox_{{- trigger.entity_id.split('.')[1].split('_')[0] -}}_camera" -# # - service: image_processing.scan -# # data_template: -# # entity_id: "image_processing.tagbox_{{- trigger.entity_id.split('.')[1].split('_')[0] -}}_camera" diff --git a/packages/daily_routines.yaml b/packages/daily_routines.yaml index 02a2ca5..a08d44b 100644 --- a/packages/daily_routines.yaml +++ b/packages/daily_routines.yaml @@ -40,7 +40,7 @@ automation: action: - service: switch.turn_on data: - entity_id: switch.kitchen + entity_id: switch.kitchen_switch ############################################################################### # Turn ON Master Bedroom lights ON in the morning @@ -70,6 +70,9 @@ automation: transition: 15 brightness: 25 color_temp: 154 + - service: switch.turn_on + data: + entity_id: switch.chromecast_monitor - alias: Morning Master Bedroom Lights OFF (Mallika) initial_state: true @@ -134,7 +137,7 @@ automation: state: "on" action: - service: switch.turn_off - entity_id: switch.kitchen + entity_id: switch.kitchen_switch - service: switch.turn_off entity_id: switch.front_room @@ -153,7 +156,7 @@ automation: # Turn outdoor lights on 15 minutes before sunset ############################################################################### - alias: Evening Outdoor Lights ON (At Sunset) - initial_state: true +# initial_state: true trigger: platform: sun event: sunset @@ -187,23 +190,23 @@ automation: action: - service: switch.turn_on data: - entity_id: switch.kitchen + entity_id: switch.kitchen_switch - service: light.turn_on data: entity_id: light.hue_color_lamp_1 - transition: 15 + transition: 3000 brightness: 255 color_temp: 154 - service: light.turn_on data: entity_id: light.hue_color_lamp_2 - transition: 15 + transition: 3000 brightness: 255 color_temp: 154 - service: light.turn_on data: entity_id: light.hue_color_lamp_3 - transition: 15 + transition: 3000 brightness: 255 color_temp: 154 - service: light.turn_on @@ -217,7 +220,7 @@ automation: brightness: 25 color_temp: 366 - service: switch.turn_on - entity_id: switch.kids_bed_accent + entity_id: switch.hasika_bed_accent - service: switch.turn_on entity_id: switch.front_room - service: switch.turn_on @@ -281,9 +284,9 @@ automation: state: "on" action: - service: script.all_indoor_lights_off - - service: script.notify_me - data: - message: "It is bed time, turned lights off!" + # - service: script.notify_me + # data: + # message: "It is bed time, turned lights off!" ############################################################################### # Provide Bed time Report via TTS diff --git a/packages/door_sensors.yaml b/packages/door_sensors.yaml index 7abee78..858d933 100644 --- a/packages/door_sensors.yaml +++ b/packages/door_sensors.yaml @@ -157,7 +157,7 @@ automation: - delay: "00:00:05" - service: camera.snapshot data_template: - entity_id: "camera.garage_camera" + entity_id: "camera.garage" filename: "{{ '/config/www/downloads/camera/garage/garage_' ~ ((state_attr('automation.notify_garage_door_status', 'last_triggered') |string).replace('-','_') @@ -290,7 +290,7 @@ automation: - condition: template value_template: "{{ states('sun.sun') == 'below_horizon' }}" - service: switch.turn_on - entity_id: switch.kitchen + entity_id: switch.kitchen_switch ################################################################################ # When I open the garage door @@ -324,6 +324,9 @@ automation: - service: timer.start entity_id: timer.timer_garage +############################################################################### +# MASTER BATHROOM AUTOMATIONS +############################################################################### # # Only turn ON lights at 25% at night # @@ -335,7 +338,7 @@ automation: to: "on" condition: - condition: template - value_template: '{{states.sun.sun.state == "below_horizon"}}' + value_template: '{{states("sun.sun") == "below_horizon"}}' - condition: state entity_id: input_boolean.light_automations state: "on" @@ -354,7 +357,7 @@ automation: to: "on" condition: - condition: template - value_template: '{{states.sun.sun.state == "above_horizon"}}' + value_template: '{{states("sun.sun") == "above_horizon"}}' - condition: state entity_id: input_boolean.light_automations state: "on" @@ -362,5 +365,54 @@ automation: - service: light.turn_on entity_id: light.master_bathroom_lights data: - brightness: 255 # 100% of brightness - transition: 10 + brightness: 254 # 100% of brightness + transition: 5 + + - alias: Master Bathroom Toilet Door Opened + initial_state: true + trigger: + platform: state + entity_id: binary_sensor.door_window_sensor_158d00044e5cb3 + to: "on" + condition: + - condition: state + entity_id: input_boolean.light_automations + state: "on" + action: + - service: switch.turn_on + entity_id: switch.master_bathroom_toilet_light + + - alias: Turn off Master Bathroom Toilet if the door is open for too long + initial_state: true + trigger: + - platform: state + entity_id: binary_sensor.door_window_sensor_158d00044e5cb3 + to: "on" + for: + minutes: 3 + condition: + - condition: state + entity_id: input_boolean.light_automations + state: "on" + action: + - service: switch.turn_off + data_template: + entity_id: switch.master_bathroom_toilet_light + +############################################################################### +# GUEST BATHROOM AUTOMATIONS +############################################################################### + + - alias: Guest Bathroom Door Opened + initial_state: true + trigger: + platform: state + entity_id: binary_sensor.door_window_sensor_158d00045ab168 + to: "on" + condition: + - condition: state + entity_id: input_boolean.light_automations + state: "on" + action: + - service: switch.turn_on + entity_id: switch.guest_bathroom_lights \ No newline at end of file diff --git a/packages/hdmi_cec.yaaml b/packages/hdmi_cec.yaaml deleted file mode 100644 index 8473552..0000000 --- a/packages/hdmi_cec.yaaml +++ /dev/null @@ -1,39 +0,0 @@ -# sudo usermod -a -G video homeassistant -# ln -s /usr/local/lib/python3.4/dist-packages/cec /srv/homeassistant/lib/python3.4/site-packages - -# echo scan | cec-client -s -d 1 - -# opening a connection to the CEC adapter... -# requesting CEC bus information ... -# CEC bus information -# =================== -# device #0: TV -# address: 0.0.0.0 -# active source: no -# vendor: Vizio -# osd string: TV -# CEC version: 1.4 -# power status: on -# language: eng -# -# -# device #1: Recorder 1 -# address: 2.0.0.0 -# active source: no -# vendor: Pulse Eight -# osd string: CECTester -# CEC version: 1.4 -# power status: on -# language: eng - -# currently active source: unknown (-1) - - -# Edit /boot/config.txt and include the line to prevent turning TV on when you restart Raspberry Pi -# hdmi_ignore_cec_init=1 - - -hdmi_cec: - devices: - TV: 0.0.0.0 - PI: 2.0.0.0 \ No newline at end of file diff --git a/packages/homeassistant.yaml b/packages/homeassistant.yaml index dbc7f99..d218f96 100644 --- a/packages/homeassistant.yaml +++ b/packages/homeassistant.yaml @@ -6,28 +6,7 @@ ############################################################################### homeassistant: -shell_command: - stop_hass: >- - hassctl stop - - restart_hass: >- - hassctl restart - - update_hass: >- - hassctl update-hass && hassctl config && hassctl restart - -speedtestdotnet: - scan_interval: - hours: 1 - monitored_conditions: - - ping - - download - - upload - sensor: - - platform: uptime - name: Home Assistant Up Time - - platform: rest resource: http://icanhazip.com name: external_ip @@ -43,28 +22,3 @@ sensor: - type: ipv4_address arg: ens160 - type: last_boot - - - platform: mqtt - state_topic: "iotlink/domain/winsvr2016/lwt" - name: "Windows Server" - value_template: "{{ value }}" - - - platform: mqtt - state_topic: "iotlink/domain/winsvr2016/windows-monitor/stats/cpu/usage" - name: "Windows Server CPU Usage" - value_template: "{{ value }}" - - - platform: mqtt - state_topic: "iotlink/domain/winsvr2016/windows-monitor/stats/memory/used" - name: "Windows Server Memory Used" - value_template: "{{ value }}" - - - platform: mqtt - state_topic: "iotlink/domain/winsvr2016/windows-monitor/stats/memory/available" - name: "Windows Server Memory Available" - value_template: "{{ value }}" - - - platform: mqtt - state_topic: "iotlink/domain/winsvr2016/windows-monitor/stats/system/idle-time" - name: "Windows Server Idle Time" - value_template: "{{ value }}" diff --git a/packages/homesecurity.yaml b/packages/homesecurity.yaml index bcfea65..8eafbd4 100644 --- a/packages/homesecurity.yaml +++ b/packages/homesecurity.yaml @@ -16,11 +16,6 @@ homeassistant: friendly_name: Home Security System icon: mdi:security -# simplisafe: -# accounts: -# - username: !secret simplisafe_username -# password: !secret simplisafe_password - ############################################################################### # _ _ _ # /\ | | | | (_) @@ -111,7 +106,7 @@ automation: .replace(' ', '_').replace(':','_').replace('.','_').replace('+','_') ~ '.jpg' }}" - service: camera.snapshot data_template: - entity_id: "camera.garage_camera" + entity_id: "camera.garage" filename: "{{ '/config/www/downloads/camera/garage/garage_' ~ (states.binary_sensor.motion_sensor_158d00024ee084.last_updated ~ '').replace('-','_') @@ -265,33 +260,33 @@ automation: entity_id: climate.dining_room away_mode: "false" - # ############################################################################### - # # TURN HOME SECURITY SYSTEM ON AT BED TIME - # ############################################################################### - # - alias: Night HomeSecurity On - # initial_state: true - # trigger: - # platform: time_pattern - # minutes: "/5" - # seconds: 00 - # condition: - # - condition: template - # value_template: "{{ states('sensor.bedtime_hour')|int == now().hour|int }}" - # - condition: template - # value_template: "{{ states('sensor.bedtime_minute')|int == now().minute|int }}" - # - condition: template - # value_template: "{{ states('alarm_control_panel.home') != 'away' }}" - # - condition: template - # value_template: "{{ states('alarm_control_panel.home') == 'disarmed' }}" - # - condition: template - # value_template: "{{ states('input_boolean.security_system_alerts') == 'on' }}" - # action: - # - service: alarm_control_panel.alarm_arm_home - # data: - # entity_id: alarm_control_panel.home - # - service: script.notify_me - # data: - # message: "It's bedtime, you forgot to turn ON Home Security System. Turned it ON for you." + ############################################################################### + # TURN HOME SECURITY SYSTEM ON AT BED TIME + ############################################################################### + - alias: Night HomeSecurity On + initial_state: true + trigger: + platform: time_pattern + minutes: "/5" + seconds: 00 + condition: + - condition: template + value_template: "{{ states('sensor.bedtime_hour')|int == now().hour|int }}" + - condition: template + value_template: "{{ states('sensor.bedtime_minute')|int == now().minute|int }}" + - condition: template + value_template: "{{ states('alarm_control_panel.home') != 'away' }}" + - condition: template + value_template: "{{ states('alarm_control_panel.home') == 'disarmed' }}" + - condition: template + value_template: "{{ states('input_boolean.security_system_alerts') == 'on' }}" + action: + - service: alarm_control_panel.alarm_arm_home + data: + entity_id: alarm_control_panel.home + - service: script.notify_me + data: + message: "It's bedtime, you forgot to turn ON Home Security System. Turned it ON for you." ############################################################################### # Check for Garage Door Status when Home Security System State changes @@ -324,7 +319,7 @@ automation: - service: camera.snapshot data_template: - entity_id: "camera.garage_camera" + entity_id: "camera.garage" filename: "{{ '/config/www/downloads/camera/garage/garage_' ~ (state_attr('automation.home_security_system_and_garage_door_check','last_updated') ~ '').replace('-','_').replace(' ', '_').replace(':','_').replace('.','_').replace('+','_') ~ '.jpg' }}" - service: notify.telegram diff --git a/packages/led_notify.yaml b/packages/led_notify.yaml index 6b02e2b..0428bbf 100644 --- a/packages/led_notify.yaml +++ b/packages/led_notify.yaml @@ -60,10 +60,10 @@ automation: trigger: - platform: state entity_id: - - device_tracker.life360_mallika - - device_tracker.life360_suresh - - device_tracker.life360_srinika - - device_tracker.life360_hasika + - device_tracker.mallika + - device_tracker.suresh + - device_tracker.srinika + - device_tracker.hasika from: "not_home" to: "home" for: "00:02:00" @@ -77,16 +77,12 @@ automation: trigger: - platform: zone entity_id: - - device_tracker.life360_hasika - - device_tracker.life360_mallika - - device_tracker.life360_srinika - - device_tracker.life360_suresh + - device_tracker.hasika + - device_tracker.mallika + - device_tracker.srinika + - device_tracker.suresh zone: zone.home event: enter - - platform: zone - entity_id: device_tracker.life360_suresh - zone: zone.work - event: enter condition: - condition: template value_template: "{{ states('input_boolean.zone_alerts') == 'on' }}" diff --git a/packages/lights_switches.yaml b/packages/lights_switches.yaml index b79dbbe..8bd7ae6 100644 --- a/packages/lights_switches.yaml +++ b/packages/lights_switches.yaml @@ -24,22 +24,6 @@ homeassistant: emulated_hue_name: Backyard Lights homebridge_name: Backyard Lights - switch.guest_bedroom: - icon: mdi:lightbulb - friendly_name: Guest Bedroom 1 - emulated_hue_name: Guest Bedroom 1 - homebridge_name: Guest Bedroom 1 - - switch.prayer_room: - icon: mdi:lightbulb - friendly_name: Guest Bedroom 2 - emulated_hue_name: Guest Bedroom 2 - homebridge_name: Guest Bedroom 2 - - switch.kids_bed_accent: - friendly_name: Hasika's Bed Accent Lights - assumed_state: false - icon: mdi:lightbulb switch.front_room: friendly_name: Front Room Light assumed_state: false @@ -52,7 +36,7 @@ homeassistant: friendly_name: Basement Right Side Lights assumed_state: false icon: mdi:lightbulb - switch.kitchen: + switch.kitchen_switch: friendly_name: Kitchen Light assumed_state: false icon: mdi:lightbulb @@ -60,9 +44,6 @@ homeassistant: friendly_name: Office Room Lights assumed_state: false icon: mdi:lightbulb - switch.kids_bedroom: - friendly_name: Kids Bedroom - icon: mdi:lightbulb switch.garage: friendly_name: Garage Lights icon: mdi:lightbulb @@ -82,55 +63,14 @@ homeassistant: input_boolean.long_flash: icon: mdi:flash friendly_name: Long Flash - input_boolean.animate_downstairs_lights: - icon: mdi:flash-outline - friendly_name: Animate Family Room Lights input_boolean.animate_upstairs_lights: icon: mdi:flash-outline friendly_name: Animate Master Bedroom Lights -tplink: - discovery: false - switch: - # In-wall switches - - host: !secret tplink_hasika_bedroom - - host: !secret tplink_srinika_bedroom - - host: !secret tplink_guest_bedroom - - host: !secret tplink_garage - - host: !secret tplink_garage_shoplights - - host: !secret tplink_basement_left - - host: !secret tplink_basement_right - - host: !secret tplink_kitchen - - host: !secret tplink_office_room - - host: !secret tplink_front_room - # Smart Outlets - - host: !secret tplink_smart_outlet1 - #name: Downstairs Fragrance Outlet - - host: !secret tplink_smart_outlet3 - #name: Upstairs Fragrance Outlet - - host: !secret tplink_kids_bed_accent_light - #name: Kids Bed Accent Light - - host: !secret tplink_3d_printer - dimmer: - - host: !secret tplink_bathroom_lights - strip: - - host: !secret tplink_smart_strip - - host: !secret tplink_outdoor_plug - -wemo: - discovery: false - static: - - !secret wemo_switch_1 - - !secret wemo_switch_2 - - !secret wemo_switch_3 - input_boolean: animate_upstairs_lights: name: Animate Master Bedroom Lights initial: off - animate_downstairs_lights: - name: Animate Family Room Lights - initial: off long_flash: name: Long Flash Lights initial: off diff --git a/packages/motion_counts.yaml b/packages/motion_counts.yaml index cd93106..f4067da 100644 --- a/packages/motion_counts.yaml +++ b/packages/motion_counts.yaml @@ -6,18 +6,12 @@ homeassistant: unit_of_measurement: "count" input_label.basement_door_sensor_sensor: unit_of_measurement: "count" - input_label.downstairs_multi_sensor_sensor: - unit_of_measurement: "count" - input_label.front_room_multi_sensor_sensor: - unit_of_measurement: "count" input_label.front_room_window_sensor_sensor: unit_of_measurement: "count" input_label.garage_door_sensor_sensor: unit_of_measurement: "count" input_label.garage_motion: unit_of_measurement: "count" - input_label.guest_bedroom_multi_sensor_sensor: - unit_of_measurement: "count" input_label.kitchen_motion_sensor_sensor: unit_of_measurement: "count" input_label.motion_sensor_158d00016c2d0e: @@ -50,8 +44,6 @@ homeassistant: unit_of_measurement: "count" input_label.two_car_garage_door_tilt_sensor_sensor: unit_of_measurement: "count" - input_label.upstairs_multi_sensor_sensor: - unit_of_measurement: "count" input_label.door_window_sensor_158d0004231f7b: unit_of_measurement: "count" input_label.door_window_sensor_158d0004248d5b: @@ -80,21 +72,12 @@ input_label: name: Garage Door icon: mdi:run-fast - downstairs_multi_sensor_sensor: - name: TV Room Multi Sensor - icon: mdi:run-fast - front_room_multi_sensor_sensor: - name: Front Room Multi Sensor - icon: mdi:run-fast front_room_window_sensor_sensor: name: Front Room Sensor icon: mdi:run-fast garage_motion: name: Garage Motion icon: mdi:run-fast - guest_bedroom_multi_sensor_sensor: - name: Guest Bedroom Motion - icon: mdi:run-fast kitchen_motion_sensor_sensor: name: Kitchen Motion icon: mdi:run-fast @@ -145,9 +128,6 @@ input_label: stairs_motion_sensor_sensor: name: Stairs Motion icon: mdi:run-fast - upstairs_multi_sensor_sensor: - name: Upstairs Motion Sensor - icon: mdi:run-fast automation: - alias: Count Motions @@ -159,12 +139,9 @@ automation: - binary_sensor.door_window_sensor_158d00040ad8fc - binary_sensor.door_window_sensor_158d0004880f30 # garage entry door - binary_sensor.basement_door_sensor_sensor - - binary_sensor.downstairs_multi_sensor_sensor - - binary_sensor.front_room_multi_sensor_sensor - binary_sensor.front_room_window_sensor_sensor - binary_sensor.garage_door_sensor_sensor - binary_sensor.garage_motion - - binary_sensor.guest_bedroom_multi_sensor_sensor - binary_sensor.kitchen_motion_sensor_sensor - binary_sensor.motion_sensor_158d00016c2d0e - binary_sensor.motion_sensor_158d00016db6d2 @@ -181,7 +158,6 @@ automation: - binary_sensor.stairs_motion_sensor_sensor - binary_sensor.door_window_sensor_158d0004248d5b # Single Car Garage - binary_sensor.door_window_sensor_158d0004231f7b # Double Car Garage - - binary_sensor.upstairs_multi_sensor_sensor action: - service: input_label.set_value data_template: @@ -200,12 +176,9 @@ automation: value: 0 entity_id: - input_label.basement_door_sensor_sensor - - input_label.downstairs_multi_sensor_sensor - - input_label.front_room_multi_sensor_sensor - input_label.front_room_window_sensor_sensor - input_label.garage_door_sensor_sensor - input_label.garage_motion - - input_label.guest_bedroom_multi_sensor_sensor - input_label.kitchen_motion_sensor_sensor - input_label.motion_sensor_158d00016c2d0e - input_label.motion_sensor_158d00016db6d2 diff --git a/packages/motion_timers.yaml b/packages/motion_timers.yaml index b2486e4..934e900 100644 --- a/packages/motion_timers.yaml +++ b/packages/motion_timers.yaml @@ -70,6 +70,16 @@ automation: entity_id: timer.timer_masterbathroom - service: light.turn_on entity_id: light.master_bathroom_lights + data: + brightness: 64 # 25% of brightness + transition: 5 + - condition: template + value_template: '{{states("sun.sun") == "above_horizon"}}' + - service: light.turn_on + entity_id: light.master_bathroom_lights + data: + brightness: 254 # 100% of brightness + transition: 5 - alias: Master Bathroom Timer Elapsed initial_state: true @@ -171,7 +181,7 @@ automation: state: "on" action: - service: switch.turn_on - entity_id: switch.kitchen + entity_id: switch.kitchen_switch - service: timer.start entity_id: timer.timer_kitchen # Kitchen: @@ -199,7 +209,7 @@ automation: {% else %} switch.turn_on {% endif %} - entity_id: switch.kitchen + entity_id: switch.kitchen_switch # Family Room: # Motion Detected - When TV is OFF, turn ON the light 100% and extend timer ############################################################################### diff --git a/packages/notify.yaml b/packages/notify.yaml index f48e732..81c538d 100644 --- a/packages/notify.yaml +++ b/packages/notify.yaml @@ -6,9 +6,6 @@ ############################################################################### homeassistant: -ifttt: - key: !secret ifttt_key - notify: - name: ios_devices platform: group diff --git a/packages/paloalto.yaml b/packages/paloalto.yaml deleted file mode 100644 index b0277a1..0000000 --- a/packages/paloalto.yaml +++ /dev/null @@ -1,218 +0,0 @@ -# ############################################################################### -# # AUTHOR : Suresh Kalavala -# # DATE : 03/04/2018 -# # PACKAGE : PALO ALTO APPLANCE/DEVICE SENSOR -# # Description : Package to monitor PaloAlto device, logged-in users, vpn users -# # and other system information -# ############################################################################### -# homeassistant: -# customize: - -# # Sensors from custom component -# sensor.paloalto_host_name: -# friendly_name: Palo Alto Host Name -# sensor.paloalto_operation_mode: -# friendly_name: Device Operation Mode -# sensor.paloalto_serial_number: -# friendly_name: Device Serial Number -# sensor.paloalto_global_protect_user_count: -# friendly_name: VPN Loggedin User Count -# sensor.paloalto_global_protect_users: -# friendly_name: VPN Loggedin Users -# sensor.paloalto_global_protect_version: -# friendly_name: VPN Software Version -# sensor.paloalto_logdb_version: -# friendly_name: Log Db Version -# sensor.paloalto_software_version: -# friendly_name: Device Software Version -# sensor.paloalto_core_temperature: -# friendly_name: Core Temperature -# sensor.paloalto_system_temperature: -# friendly_name: System Temperature -# sensor.paloalto_up_time: -# friendly_name: Up Time - -# # Scripts -# script.paloalto_clear_traffic_logs: -# friendly_name: Clear Traffic Logs -# script.paloalto_clear_threat_logs: -# friendly_name: Clear Threat Logs -# script.paloalto_clear_alarm_logs: -# friendly_name: Clear Alarm Logs -# script.paloalto_clear_authentication_logs: -# friendly_name: Clear Authentication Logs -# script.paloalto_clear_config_logs: -# friendly_name: Clear Configuration Logs -# script.paloalto_clear_system_logs: -# friendly_name: Clear System Logs -# script.paloalto_shutdown: -# friendly_name: Shutdown Palo Alto Device -# icon: mdi:power -# script.paloalto_restart: -# friendly_name: Restart Palo Alto Device -# icon: mdi:restart - -# sensor: -# - platform: paloalto -# api_key: !secret paloalto_authkey -# ip_address: !secret paloalto_hostip -# ssl: True -# verify_ssl: False -# scan_interval: 60 -# monitored_conditions: -# - host_name -# - up_time -# - serial_no -# - sw_version -# - gp_version -# - logdb_version -# - operation_mode -# - core_temp -# - sys_temp -# - gp_users -# - gp_user_count -# - loggedin_user_count -# - loggedin_users - -# # -# # All the URLs below use the following format -# # For ex: paloalto_clear_traffic_logs: "curl -k 'https://192.xxx.xxx.xxx/api/?type=op&cmd=&key=YOUR_API_KEY'" -# # Check out secrets.example file for additional details about the commands -# # https://github.com/skalavala/mysmarthome/blob/master/secrets.example -# # -# shell_command: -# paloalto_clear_traffic_logs: !secret paloalto_clear_traffic_logs -# paloalto_clear_threat_logs: !secret paloalto_clear_threat_logs -# paloalto_clear_alarm_logs: !secret paloalto_clear_alarm_logs -# paloalto_clear_authentication_logs: !secret paloalto_clear_authentication_logs -# paloalto_clear_config_logs: !secret paloalto_clear_config_logs -# paloalto_clear_system_logs: !secret paloalto_clear_system_logs -# paloalto_shutdown: !secret paloalto_shutdown -# paloalto_restart: !secret paloalto_restart - -# script: -# paloalto_clear_traffic_logs: -# sequence: -# - service: shell_command.paloalto_clear_traffic_logs -# paloalto_clear_threat_logs: -# sequence: -# - service: shell_command.paloalto_clear_threat_logs -# paloalto_clear_alarm_logs: -# sequence: -# - service: shell_command.paloalto_clear_alarm_logs -# paloalto_clear_authentication_logs: -# sequence: -# - service: shell_command.paloalto_clear_authentication_logs -# paloalto_clear_config_logs: -# sequence: -# - service: shell_command.paloalto_clear_config_logs -# paloalto_clear_system_logs: -# sequence: -# - service: shell_command.paloalto_clear_system_logs -# paloalto_shutdown: -# sequence: -# - service: shell_command.paloalto_shutdown -# paloalto_restart: -# sequence: -# - service: shell_command.paloalto_restart - -# automation: -# # -# # Alerts me when someone logs into my VPN network -# # This automation compares before and after state changes -# # and alerts when someone logged in/out of VPN -# # -# - alias: Alert When Someone Logged into VPN -# initial_state: true -# trigger: -# - platform: state -# entity_id: sensor.paloalto_global_protect_users -# condition: -# - condition: template -# value_template: '{{ trigger.from_state.state | lower != trigger.to_state.state | lower }}' -# action: -# - service: script.notify_me -# data_template: -# message: >- -# {% set before = trigger.from_state.state %} -# {% set after = trigger.to_state.state %} -# {% macro loggedIn(beforeList, afterList) %} -# {%- for user in afterList if user != 'None' and user not in beforeList%} -# {%- if loop.first %}{% elif loop.last %} and{% else %},{% endif -%} -# {{- user }} -# {%- endfor %} -# {%- endmacro %} -# {% macro loggedOut(beforeList, afterList) %} -# {%- for user in beforeList if user != 'None' and user not in afterList %} -# {%- if loop.first %}{% elif loop.last %} and{% else %},{% endif -%} -# {{- user }} -# {%- endfor %} -# {%- endmacro %} -# {%- macro checkUsers(beforeList, afterList) -%} -# {%- set loggedInUsers = loggedIn(beforeList, afterList) -%} -# {%- set loggedOutUsers = loggedOut(beforeList, afterList) -%} -# {%- if loggedInUsers | trim != "" -%} -# Alert! {{- loggedInUsers | title }} just logged into your Web VPN. -# {%- endif -%} -# {%- if loggedOutUsers | trim != "" %} -# {{- loggedOutUsers |title }} just logged out of your Web VPN. -# {% endif %} -# {%- endmacro -%} -# {{ checkUsers(before.split(','), after.split(',')) }} - -# # -# # Alerts me when someone logs into my firewall. -# # This automation compares before and after state changes -# # and alerts when someone logged in/out of Firewall -# # -# - alias: Alert When Someone Logged into Firewall -# initial_state: true -# trigger: -# - platform: state -# entity_id: sensor.paloalto_loggedin_users -# condition: -# - condition: template -# value_template: '{{ trigger.from_state.state | lower != trigger.to_state.state | lower }}' -# action: -# - service: script.notify_me -# data_template: -# message: >- -# {% set before = trigger.from_state.state %} -# {% set after = trigger.to_state.state %} -# {% macro loggedIn(beforeList, afterList) %} -# {%- for user in afterList if user != 'None' and user not in beforeList%} -# {%- if loop.first %}{% elif loop.last %} and{% else %},{% endif -%} -# {{- user }} -# {%- endfor %} -# {%- endmacro %} -# {% macro loggedOut(beforeList, afterList) %} -# {%- for user in beforeList if user != 'None' and user not in afterList %} -# {%- if loop.first %}{% elif loop.last %} and{% else %},{% endif -%} -# {{- user }} -# {%- endfor %} -# {%- endmacro %} -# {%- macro checkUsers(beforeList, afterList) -%} -# {%- set loggedInUsers = loggedIn(beforeList, afterList) -%} -# {%- set loggedOutUsers = loggedOut(beforeList, afterList) -%} -# {%- if loggedInUsers | trim != "" -%} -# Alert! {{- loggedInUsers | title }} just logged into your Palo Alto Firewall. -# {%- endif -%} -# {%- if loggedOutUsers | trim != "" %} -# {{- loggedOutUsers |title }} just logged out of your Palo Alto Firewall. -# {% endif %} -# {%- endmacro -%} -# {{ checkUsers(before.split(','), after.split(',')) }} - -# # -# # Palo Alto PA-200 device sucks ass in terms of its disk space! -# # A work around would be to clear traffic logs periodically -# # This automation runs every hour and clears traffic log/log files -# # -# - alias: Clear Traffic Logs -# initial_state: True -# trigger: -# - platform: time_pattern -# hours: '/1' -# minutes: 00 -# action: -# - service: script.paloalto_clear_traffic_logs diff --git a/packages/pi_admin.yaml b/packages/pi_admin.yaml deleted file mode 100644 index aa7ccb5..0000000 --- a/packages/pi_admin.yaml +++ /dev/null @@ -1,552 +0,0 @@ -############################################################################### -# @author : Mahasri Kalavala -# @date : 12/27/2017 -# @package : Pi Admin Package -# @description : Got way too many Raspberry Pi's and this package is to -# help me with managing them via Home Assistant. -# -# How Does It Work? -# -# Each Raspberry Pi runs a service (a python program) locally that listens for -# commands via MQTT on a pre-defined topic. This package publishes commands -# to MQTT requesting each Raspberry Pi to respond and or return data. -# When the responses are received (on a differet topic), the sensors gets -# updated automatically and are displayed. -# -################################################################################ - -homeassistant: - customize: - script.restart_all_raspberrypis: - friendly_name: Restart All Raspberry Pis - script.restart_all_snapclients: - friendly_name: Restart All Snapserver Clients - script.shutdown_all_raspberrypis: - friendly_name: Shutdown All Raspberry Pis - script.query_wifi_info: - friendly_name: Query WiFi Info - script.query_disk_info: - friendly_name: Query Disk Info - -input_select: - raspberry_pis: - name: All Raspberry Pis - options: - - Select One - - pi_basement - - pi_theater - - pi_kitchen - - pi_familyroom - - pi_frontroom - - pi_garage - - pi_guest1 - - pi_guest2 - - pi_masterbedroom - initial: Select One - icon: mdi:pig - - rpi_commands: - name: RPi Commands - options: - - Select One - - Restart Server - - Shutdown - - Restart Snapcast - initial: Select One - icon: mdi:pig - -sensor: - ## WiFi Information related sensors - - platform: mqtt - state_topic: "/wifi/pi_basement" - name: Basement Pi Signal Level - value_template: '{{ value_json["Signal Level"]}}' - unit_of_measurement: dBm - - platform: mqtt - state_topic: "/wifi/pi_basement" - name: Basement Pi Link Quality - value_template: '{{ value_json["Link Quality"]}}' - - - platform: mqtt - state_topic: "/wifi/pi_theater" - name: Theater Pi Signal Level - value_template: '{{ value_json["Signal Level"]}}' - unit_of_measurement: dBm - - platform: mqtt - state_topic: "/wifi/pi_theater" - name: Theater Pi Link Quality - value_template: '{{ value_json["Link Quality"]}}' - - - platform: mqtt - state_topic: "/wifi/pi_kitchen" - name: Kitchen Pi Signal Level - value_template: '{{ value_json["Signal Level"]}}' - unit_of_measurement: dBm - - platform: mqtt - state_topic: "/wifi/pi_kitchen" - name: Kitchen Pi Link Quality - value_template: '{{ value_json["Link Quality"]}}' - - - platform: mqtt - state_topic: "/wifi/pi_familyroom" - name: Family Room Pi Signal Level - value_template: '{{ value_json["Signal Level"]}}' - unit_of_measurement: dBm - - platform: mqtt - state_topic: "/wifi/pi_familyroom" - name: Family Room Pi Link Quality - value_template: '{{ value_json["Link Quality"]}}' - - - platform: mqtt - state_topic: "/wifi/pi_frontroom" - name: Front Room Pi Signal Level - value_template: '{{ value_json["Signal Level"]}}' - unit_of_measurement: dBm - - platform: mqtt - state_topic: "/wifi/pi_frontroom" - name: Front Room Pi Link Quality - value_template: '{{ value_json["Link Quality"]}}' - - - platform: mqtt - state_topic: "/wifi/pi_garage" - name: Garage Pi Signal Level - value_template: '{{ value_json["Signal Level"]}}' - unit_of_measurement: dBm - - platform: mqtt - state_topic: "/wifi/pi_garage" - name: Garage Pi Link Quality - value_template: '{{ value_json["Link Quality"]}}' - - - platform: mqtt - state_topic: "/wifi/pi_guest1" - name: Guest 1 Pi Signal Level - value_template: '{{ value_json["Signal Level"]}}' - unit_of_measurement: dBm - - platform: mqtt - state_topic: "/wifi/pi_guest1" - name: Guest 1 Pi Link Quality - value_template: '{{ value_json["Link Quality"]}}' - - - platform: mqtt - state_topic: "/wifi/pi_guest2" - name: Guest 2 Pi Signal Level - value_template: '{{ value_json["Signal Level"]}}' - unit_of_measurement: dBm - - platform: mqtt - state_topic: "/wifi/pi_guest2" - name: Guest 2 Pi Link Quality - value_template: '{{ value_json["Link Quality"]}}' - - - platform: mqtt - state_topic: "/wifi/pi_masterbedroom" - name: master Bedroom Pi Signal Level - value_template: '{{ value_json["Signal Level"]}}' - unit_of_measurement: dBm - - platform: mqtt - state_topic: "/wifi/pi_masterbedroom" - name: Master Bedroom Pi Link Quality - value_template: '{{ value_json["Link Quality"]}}' - - ## Disk Information related Sensors - - platform: mqtt - state_topic: "/disk/pi_basement" - name: Basement Pi Available Disk - value_template: '{{ value_json["Available"]}}' - - platform: mqtt - state_topic: "/disk/pi_basement" - name: Basement Pi Disk Used - value_template: '{{ value_json["% Used"]}}' - - - platform: mqtt - state_topic: "/disk/pi_theater" - name: Theater Pi Available Disk - value_template: '{{ value_json["Available"]}}' - - platform: mqtt - state_topic: "/disk/pi_theater" - name: Theater Pi Disk Used - value_template: '{{ value_json["% Used"]}}' - - - platform: mqtt - state_topic: "/disk/pi_kitchen" - name: Kitchen Pi Available Disk - value_template: '{{ value_json["Available"]}}' - - platform: mqtt - state_topic: "/disk/pi_kitchen" - name: Kitchen Pi Disk Used - value_template: '{{ value_json["% Used"]}}' - - - platform: mqtt - state_topic: "/disk/pi_familyroom" - name: Family Room Pi Available Disk - value_template: '{{ value_json["Available"]}}' - - platform: mqtt - state_topic: "/disk/pi_familyroom" - name: Family Room Pi Disk Used - value_template: '{{ value_json["% Used"]}}' - - - platform: mqtt - state_topic: "/disk/pi_frontroom" - name: Front Room Pi Available Disk - value_template: '{{ value_json["Available"]}}' - - platform: mqtt - state_topic: "/disk/pi_frontroom" - name: Front Room Pi Disk Used - value_template: '{{ value_json["% Used"]}}' - - - platform: mqtt - state_topic: "/disk/pi_garage" - name: Garage Pi Available Disk - value_template: '{{ value_json["Available"]}}' - - platform: mqtt - state_topic: "/disk/pi_garage" - name: Garage Pi Disk Used - value_template: '{{ value_json["% Used"]}}' - - - platform: mqtt - state_topic: "/disk/pi_guest1" - name: Guest 1 Pi Available Disk - value_template: '{{ value_json["Available"]}}' - - platform: mqtt - state_topic: "/disk/pi_guest1" - name: Guest 1 Pi Disk Used - value_template: '{{ value_json["% Used"]}}' - - - platform: mqtt - state_topic: "/disk/pi_guest2" - name: Guest 2 Pi Available Disk - value_template: '{{ value_json["Available"]}}' - - platform: mqtt - state_topic: "/disk/pi_guest2" - name: Guest 2 Pi Disk Used - value_template: '{{ value_json["% Used"]}}' - - - platform: mqtt - state_topic: "/disk/pi_masterbedroom" - name: Master Bedroom Pi Available Disk - value_template: '{{ value_json["Available"]}}' - - platform: mqtt - state_topic: "/disk/pi_masterbedroom" - name: Master Bedroom Pi Disk Used - value_template: '{{ value_json["% Used"]}}' - -script: - restart_all_raspberrypis: - sequence: - - service: mqtt.publish - data_template: - topic: "/server/pi_basement" - payload: CMD_REBOOT_PI - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_theater" - payload: CMD_REBOOT_PI - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_kitchen" - payload: CMD_REBOOT_PI - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_familyroom" - payload: CMD_REBOOT_PI - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_frontroom" - payload: CMD_REBOOT_PI - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_garage" - payload: CMD_REBOOT_PI - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_guest1" - payload: CMD_REBOOT_PI - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_guest2" - payload: CMD_REBOOT_PI - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_masterbedroom" - payload: CMD_REBOOT_PI - retain: false - - restart_all_snapclients: - sequence: - - service: mqtt.publish - data_template: - topic: "/server/pi_basement" - payload: CMD_RESTART_SNAPCLIENT - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_theater" - payload: CMD_RESTART_SNAPCLIENT - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_kitchen" - payload: CMD_RESTART_SNAPCLIENT - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_familyroom" - payload: CMD_RESTART_SNAPCLIENT - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_frontroom" - payload: CMD_RESTART_SNAPCLIENT - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_garage" - payload: CMD_RESTART_SNAPCLIENT - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_guest1" - payload: CMD_RESTART_SNAPCLIENT - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_guest2" - payload: CMD_RESTART_SNAPCLIENT - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_masterbedroom" - payload: CMD_RESTART_SNAPCLIENT - retain: false - - shutdown_all_raspberrypis: - sequence: - - service: mqtt.publish - data_template: - topic: "/server/pi_basement" - payload: CMD_SHUTDOWN_PI - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_theater" - payload: CMD_SHUTDOWN_PI - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_kitchen" - payload: CMD_SHUTDOWN_PI - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_familyroom" - payload: CMD_SHUTDOWN_PI - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_frontroom" - payload: CMD_SHUTDOWN_PI - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_garage" - payload: CMD_SHUTDOWN_PI - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_guest1" - payload: CMD_SHUTDOWN_PI - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_guest2" - payload: CMD_SHUTDOWN_PI - retain: false - - service: mqtt.publish - data_template: - topic: "/server/pi_masterbedroom" - payload: CMD_SHUTDOWN_PI - retain: false - - # Script to Query Disk Information - Publishes message 'CMD_REPORT_WIFI_DETAILS' - # to MQTT, so that the message gets received by individual Raspberry Pi - ############################################################################### - query_wifi_info: - sequence: - - service: mqtt.publish - data: - topic: /server/pi_basement - payload: "CMD_REPORT_WIFI_DETAILS" - retain: false - - service: mqtt.publish - data: - topic: /server/pi_theater - payload: "CMD_REPORT_WIFI_DETAILS" - retain: false - - service: mqtt.publish - data: - topic: /server/pi_kitchen - payload: "CMD_REPORT_WIFI_DETAILS" - retain: false - - service: mqtt.publish - data: - topic: /server/pi_familyroom - payload: "CMD_REPORT_WIFI_DETAILS" - retain: false - - service: mqtt.publish - data: - topic: /server/pi_frontroom - payload: "CMD_REPORT_WIFI_DETAILS" - retain: false - - service: mqtt.publish - data: - topic: /server/pi_garage - payload: "CMD_REPORT_WIFI_DETAILS" - retain: false - - service: mqtt.publish - data: - topic: /server/pi_guest1 - payload: "CMD_REPORT_WIFI_DETAILS" - retain: false - - service: mqtt.publish - data: - topic: /server/pi_guest2 - payload: "CMD_REPORT_WIFI_DETAILS" - retain: false - - service: mqtt.publish - data: - topic: /server/pi_masterbedroom - payload: "CMD_REPORT_WIFI_DETAILS" - retain: false - - service: mqtt.publish - data: - topic: /server/pizero_green - payload: "CMD_REPORT_WIFI_DETAILS" - retain: false - - # Script to Query Disk Information - Publishes message 'CMD_REPORT_DISK_DETAILS' - # to MQTT, so that the message gets received by individual Raspberry Pi - ############################################################################### - query_disk_info: - sequence: - - service: mqtt.publish - data: - topic: /server/pi_basement - payload: "CMD_REPORT_DISK_DETAILS" - retain: false - - service: mqtt.publish - data: - topic: /server/pi_theater - payload: "CMD_REPORT_DISK_DETAILS" - retain: false - - service: mqtt.publish - data: - topic: /server/pi_kitchen - payload: "CMD_REPORT_DISK_DETAILS" - retain: false - - service: mqtt.publish - data: - topic: /server/pi_familyroom - payload: "CMD_REPORT_DISK_DETAILS" - retain: false - - service: mqtt.publish - data: - topic: /server/pi_frontroom - payload: "CMD_REPORT_DISK_DETAILS" - retain: false - - service: mqtt.publish - data: - topic: /server/pi_garage - payload: "CMD_REPORT_DISK_DETAILS" - retain: false - - service: mqtt.publish - data: - topic: /server/pi_guest1 - payload: "CMD_REPORT_DISK_DETAILS" - retain: false - - service: mqtt.publish - data: - topic: /server/pi_guest2 - payload: "CMD_REPORT_DISK_DETAILS" - retain: false - - service: mqtt.publish - data: - topic: /server/pi_masterbedroom - payload: "CMD_REPORT_DISK_DETAILS" - retain: false - - service: mqtt.publish - data: - topic: /server/pizero_green - payload: "CMD_REPORT_DISK_DETAILS" - retain: false - -############################################################################### -# _ _ _ -# /\ | | | | (_) -# / \ _ _| |_ ___ _ __ ___ __ _| |_ _ ___ _ __ ___ -# / /\ \| | | | __/ _ \| '_ ` _ \ / _` | __| |/ _ \| '_ \/ __| -# / ____ \ |_| | || (_) | | | | | | (_| | |_| | (_) | | | \__ \ -# /_/ \_\__,_|\__\___/|_| |_| |_|\__,_|\__|_|\___/|_| |_|___/ -# -############################################################################### - -# Automations: Various automations to query and issue commands to Raspberry Pis -############################################################################### -automation: - # Queries WiFi Signal Level and Link Quality - it loads during startup, and - # updates once every 30 minutes - ############################################################################### - - alias: Query RPi Wifi Data - initial_state: true - trigger: - - platform: time_pattern - minutes: "/30" - - platform: homeassistant - event: start - action: - - service: script.query_wifi_info - - # Queries Disk Available and % Used - it loads during startup, and - # updates once every 30 minutes - ############################################################################### - - alias: Query RPi Disk Data - initial_state: true - trigger: - - platform: time_pattern - minutes: "/30" - - platform: homeassistant - event: start - action: - - service: script.query_disk_info - - # Issues commands to Raspberry Pi via MQTT - On Demand - ############################################################################### - - alias: Raspberry Pi Command - initial_state: true - trigger: - - platform: state - entity_id: input_select.rpi_commands - condition: - - condition: template - value_template: "{{ states('input_select.raspberry_pis') | lower != 'select one' }}" - - condition: template - value_template: "{{ states('input_select.rpi_commands') | lower != 'select one' }}" - action: - service: mqtt.publish - data_template: - retain: false - topic: "{{ '/server/' ~ states('input_select.raspberry_pis') }}" - payload: >- - {% if states('input_select.rpi_commands') | lower == "restart server" %} - CMD_REBOOT_PI - {% elif states('input_select.rpi_commands') | lower == "restart snapcast" %} - CMD_RESTART_SNAPCLIENT - {% else %} - CMD_SHUTDOWN_PI - {% endif %} diff --git a/packages/pill_reminder.yaml b/packages/pill_reminder.yaml index 976b2de..437876e 100644 --- a/packages/pill_reminder.yaml +++ b/packages/pill_reminder.yaml @@ -27,11 +27,6 @@ input_boolean: name: Pill Taken icon: mdi:pill - pill_on_vacation: - name: On Vacation - initial: off - icon: mdi:beach - pill_voice_notification: name: Pill Voice Notification icon: mdi:speaker @@ -90,20 +85,6 @@ automation: - service: input_boolean.turn_off entity_id: input_boolean.pill_taken - ############################################################################### - # Set the vacation mode automatically based on home security system state - # When travelling, make sure you add a reminder on your mobile phone - ############################################################################### - - alias: Set Vacation Mode For Pills - initial_state: true - trigger: - platform: state - entity_id: alarm_control_panel.home - action: - - service_template: "input_boolean.turn_{{- 'on' if - states('alarm_control_panel.home') == 'armed_away' else 'off' }}" - entity_id: input_boolean.pill_on_vacation - ############################################################################### # Checks if the pills were taken - trigger on the pill reminder time # Also, only remind if not on vacation or away from home @@ -120,7 +101,7 @@ automation: - condition: template value_template: "{{ states('input_boolean.pill_taken') == 'off' }}" - condition: template - value_template: "{{ states('input_boolean.pill_on_vacation') == 'off' }}" + value_template: "{{ states('input_boolean.home_mode_away') == 'off' }}" action: - service: script.remind_pill diff --git a/packages/recycle_trash.yaml b/packages/recycle_trash.yaml index 805805b..e0d5233 100644 --- a/packages/recycle_trash.yaml +++ b/packages/recycle_trash.yaml @@ -282,7 +282,7 @@ automation: condition: and conditions: - condition: template - value_template: '{{ states.input_boolean.trash_reminders.state == "on" }}' + value_template: "{{ states('input_boolean.trash_reminders') == 'on' }}" - condition: or conditions: - condition: state diff --git a/packages/rfswitches.yaml b/packages/rfswitches.yaml deleted file mode 100644 index a234fb2..0000000 --- a/packages/rfswitches.yaml +++ /dev/null @@ -1,186 +0,0 @@ -# NOTE: THIS CODE WORKS! I NO LONGER USE RPI FOR MY HA ANYMORE. HENCE THE CODE IS COMMENTED. -# PLEASE FEEL FREE TO COPY THE CODE AND UNCOMMENT IT, AND SHOULD WORK OUT OF THE BOX - -# ############################################################################### -# # @author : Mahasri Kalavala -# # @date : 04/15/2017 -# # @package : RF Outlets -# # @description : Etekcity RF Outlet Sensors and Automations -# ############################################################################### -# homeassistant: -# customize: - -# group.etekcity_rf_switches: -# order: 13 - -# switch.switch_one: -# friendly_name: Switch One -# switch.switch_two: -# friendly_name: Switch Two -# switch.switch_three: -# friendly_name: Switch Three -# switch.switch_four: -# friendly_name: Switch Four -# switch.switch_five: -# friendly_name: Switch Five - -# sensor.rf_switch_one: -# hidden: true -# sensor.rf_switch_two: -# hidden: true -# sensor.rf_switch_three: -# hidden: true -# sensor.rf_switch_four: -# hidden: true -# sensor.rf_switch_five: -# hidden: true - -# ############################################################################### -# # RF Switches -# ############################################################################### -# switch: -# - platform: rpi_rf -# gpio: 17 -# switches: -# switch_one: -# code_on: !secret rf_switch_1_code_on -# code_off: !secret rf_switch_1_code_off -# pulselength: !secret rf_switch_1_pulselength -# switch_two: -# code_on: !secret rf_switch_2_code_on -# code_off: !secret rf_switch_2_code_off -# pulselength: !secret rf_switch_2_pulselength -# switch_three: -# code_on: !secret rf_switch_3_code_on -# code_off: !secret rf_switch_3_code_off -# pulselength: !secret rf_switch_3_pulselength -# switch_four: -# code_on: !secret rf_switch_4_code_on -# code_off: !secret rf_switch_4_code_off -# pulselength: !secret rf_switch_4_pulselength -# switch_five: -# code_on: !secret rf_switch_5_code_on -# code_off: !secret rf_switch_5_code_off -# pulselength: !secret rf_switch_5_pulselength - -# ############################################################################### -# # Sensor Definitions -# ############################################################################### -# sensor: -# - platform: mqtt -# state_topic: "/home/rfswitches/switch_one" -# name: "RF Switch One" -# value_template: "{{ value }}" - -# - platform: mqtt -# state_topic: "/home/rfswitches/switch_two" -# name: "RF Switch Two" -# value_template: "{{ value }}" - -# - platform: mqtt -# state_topic: "/home/rfswitches/switch_three" -# name: "RF Switch Three" -# value_template: "{{ value }}" - -# - platform: mqtt -# state_topic: "/home/rfswitches/switch_four" -# name: "RF Switch Four" -# value_template: "{{ value }}" - -# - platform: mqtt -# state_topic: "/home/rfswitches/switch_five" -# name: "RF Switch Five" -# value_template: "{{ value }}" - -# ############################################################################### -# # Automation - Saves Switch State to MQTT -# ############################################################################### -# automation: - -# # When the switch state changes (programatically or by UI), save the state to MQTT -# - alias: Save RF Switch State -# initial_state: true -# trigger: -# platform: state -# entity_id: -# - switch.switch_one -# - switch.switch_two -# - switch.switch_three -# - switch.switch_four -# - switch.switch_five -# action: -# service: mqtt.publish -# data_template: -# topic: "/home/rfswitches/{{ trigger.entity_id.split('.')[1] }}" -# retain: true -# qos: 1 -# payload: '{{ trigger.to_state.state }}' - -# # When the switch state is updated in MQTT (for remove integration), reload the Switch to that state -# - alias: Sync MQTT and Switch States -# initial_state: true -# trigger: -# platform: state -# entity_id: -# - sensor.rf_switch_one -# - sensor.rf_switch_two -# - sensor.rf_switch_three -# - sensor.rf_switch_four -# - sensor.rf_switch_five -# action: -# - service_template: > -# {%- if trigger.to_state.state | lower == "on" -%} -# homeassistant.turn_on -# {%- else -%} -# homeassistant.turn_off -# {%- endif -%} -# data_template: -# entity_id: 'switch.switch_{{ trigger.entity_id.split(".")[1].split("_")[2]}}' - -# ############################################################################### -# # Startup event - restores states of dropdowns, and RF Switches...etc -# ############################################################################### -# - alias: Restore RF Switch Status on Startup -# initial_state: true -# trigger: -# platform: homeassistant -# event: start -# action: -# - delay: -# minutes: 1 -# - service_template: > -# {%- if states('sensor.rf_switch_one') | lower == "on" -%} -# homeassistant.turn_on -# {%- else -%} -# homeassistant.turn_off -# {%- endif -%} -# entity_id: switch.switch_one -# - service_template: > -# {%- if states('sensor.rf_switch_two') | lower == "on" -%} -# homeassistant.turn_on -# {%- else -%} -# homeassistant.turn_off -# {%- endif -%} -# entity_id: switch.switch_two -# - service_template: > -# {%- if states('sensor.rf_switch_three') | lower == "on" -%} -# homeassistant.turn_on -# {%- else -%} -# homeassistant.turn_off -# {%- endif -%} -# entity_id: switch.switch_three -# - service_template: > -# {%- if states('sensor.rf_switch_four') | lower == "on" -%} -# homeassistant.turn_on -# {%- else -%} -# homeassistant.turn_off -# {%- endif -%} -# entity_id: switch.switch_four -# - service_template: > -# {%- if states('sensor.rf_switch_five') | lower == "on" -%} -# homeassistant.turn_on -# {%- else -%} -# homeassistant.turn_off -# {%- endif -%} -# data: -# entity_id: switch.switch_five diff --git a/packages/scripts.yaml b/packages/scripts.yaml index a4dac2e..7b5bf2a 100644 --- a/packages/scripts.yaml +++ b/packages/scripts.yaml @@ -80,14 +80,13 @@ script: - service: script.all_indoor_lights_off - service: input_boolean.turn_on entity_id: input_boolean.notify_camera_alerts - - service: climate.set_away_mode + - service: alarm_control_panel.alarm_arm_away data: - entity_id: climate.dining_room - away_mode: "true" + entity_id: alarm_control_panel.home - service: script.notify_me data: message: > - No one is at home. Cameras rolling, Indoor lights OFF, Thermostat is set to 'away' and your home is secured! + No one is at home. Cameras rolling, Indoor lights are OFF. Your home security system is turned ON! ############################################################################### # The following script runs when no one is home. It excludes some lights @@ -111,28 +110,18 @@ script: entity_id: - switch.basement_left - switch.basement_right - - switch.downstairs_fragrance - switch.front_room - switch.garage - switch.garage_shop_lights - - switch.guest_bedroom - - switch.kids_bed_accent - - switch.kids_bedroom - - switch.kitchen + - switch.srinika_bedroom + - switch.hasika_bed_accent + - switch.hasika_bedroom + - switch.kitchen_switch - switch.office_room - - switch.prayer_room - - switch.upstairs_fragrance + - switch.guest_room - switch.officeroom_accent_lights - - stop_hass: - sequence: - - service: shell_command.stop_hass - update_hass: - sequence: - - service: shell_command.update_hass - restart_hass: - sequence: - - service: shell_command.restart_hass + - switch.chromecast_monitor + - switch.master_bathroom_lights xiaomi_red: sequence: @@ -186,8 +175,8 @@ script: state: "on" - condition: template value_template: '{{- message | trim != "" -}}' - - service: notify.telegram - data_template: + - service: telegram_bot.send_message + data: title: "{{- title -}}" message: "{{- message -}}" data: @@ -202,9 +191,15 @@ script: state: "on" - condition: template value_template: '{{ message | trim != "" }}' - - service: notify.telegram - data_template: + - service: telegram_bot.send_message + data: message: "{{ message }}" + - service: notify.android_tv_fire_tv + data: + message: "{{ message }}" + title: "Hello!" + data: + color: red good_night_tts: sequence: @@ -363,8 +358,12 @@ script: - service: input_boolean.turn_on entity_id: input_boolean.pill_taken - service: script.notify_me - data: - message: "Thank you for taking tablets on time!" + data_template: + message: > + Thank you for taking tablets. + {%- if state_attr('sensor.allergy_index_today', 'rating') != None %} + {{- " Today's pollen level is : " ~ state_attr('sensor.allergy_index_today', 'rating') }}. + {%- endif -%} - condition: template value_template: "{{ states('input_boolean.pill_voice_notification') == 'on' }}" - service: script.voice_notify diff --git a/packages/season.yaml b/packages/season.yaml index adc7f33..846dcc2 100644 --- a/packages/season.yaml +++ b/packages/season.yaml @@ -10,10 +10,6 @@ homeassistant: -sensor: - - platform: season - type: astronomical - ############################################################################### # _ _ _ # /\ | | | | (_) diff --git a/packages/settings.yaml b/packages/settings.yaml index 140b5fd..5a8f389 100644 --- a/packages/settings.yaml +++ b/packages/settings.yaml @@ -56,18 +56,79 @@ input_datetime: input_number: calendar_remind_before_days: name: Calendar Remind Before Days - initial: 2 min: 1 max: 15 step: 1 mode: box battery_alert_threshold: name: Notify Low Battery if goes below - initial: 4 min: 1 max: 100 step: 1 mode: box + guest_bathroom_exhaust_timer_duration: + name: Guest Bathroom Shower Exhaust Timer Duration + min: 5 + max: 240 + step: 5 + mode: box + master_bathroom_shower_exhaust_timer_duration: + name: Master Bathroom Shower Exhaust Timer Duration + min: 5 + max: 240 + step: 5 + mode: box + master_bathroom_toilet_exhaust_timer_duration: + name: Master Bathroom Toilet Exhaust Timer Duration + min: 5 + max: 240 + step: 5 + mode: box + master_bathroom_toilet_lights: + name: Master Bathroom Toilet Lights Duration + min: 5 + max: 240 + step: 5 + mode: box + + guest_bathroom_lights: + name: Guest Bathroom Lights Duration + min: 5 + max: 240 + step: 5 + mode: box + master_bathroom_lights: + name: Master Bathroom Lights Duration + min: 5 + max: 240 + step: 5 + mode: box + garage_lights: + name: Garage Lights Duration + min: 5 + max: 240 + step: 5 + mode: box + garage_shop_lights: + name: Garage Shop Lights Duration + min: 5 + max: 240 + step: 5 + mode: box + +######################### CLOSET LIGHTS + hasika_bedroom_closet_lights: + name: Hasika Closet Lights Duration + min: 5 + max: 120 + step: 5 + mode: box + srinika_bedroom_closet_lights: + name: Srinika Closet Lights Duration + min: 5 + max: 120 + step: 5 + mode: box sensor: - platform: template @@ -202,11 +263,6 @@ input_boolean: name: Battery Notifications icon: mdi:battery - sharp_tv: - name: TV - initial: on - icon: mdi:television-classic - dummy: name: "Dummy Input Boolean!" icon: mdi:sticker-emoji diff --git a/packages/tesla.yaml b/packages/tesla.yaml deleted file mode 100644 index ce752b4..0000000 --- a/packages/tesla.yaml +++ /dev/null @@ -1,57 +0,0 @@ -homeassistant: -# customize: - -# The scan_interval is now set to 6 hours -# Leaving it to the default (which is 5 minutes, or 300 seconds) will drain battery at a rate of -# 10 miles per day (or 3% battery use) on an average. Use this setting carefully! - -tesla: - username: !secret tesla_username - password: !secret tesla_password - scan_interval: 21600 -############################################################################### -# _ _ _ -# /\ | | | | (_) -# / \ _ _| |_ ___ _ __ ___ __ _| |_ _ ___ _ __ ___ -# / /\ \| | | | __/ _ \| '_ ` _ \ / _` | __| |/ _ \| '_ \/ __| -# / ____ \ |_| | || (_) | | | | | | (_| | |_| | (_) | | | \__ \ -# /_/ \_\__,_|\__\___/|_| |_| |_|\__,_|\__|_|\___/|_| |_|___/ -# -############################################################################### - -automation: - - alias: Notify Charging Status - initial_state: true - trigger: - - platform: state - entity_id: binary_sensor.tesla_model_3_charger_sensor - action: - - service: script.notify_me - data_template: - message: "Tesla Car Charge Status changed to: {{ trigger.to_state.state| upper }}" - - - alias: Notify Door Status - initial_state: true - trigger: - - platform: state - entity_id: lock.tesla_model_3_door_lock - condition: - - condition: template - value_template: '{{ trigger.from_state.state | lower != "unknown" }}' - action: - - service: script.notify_me - data_template: - message: "Tesla Door is now: {{ trigger.to_state.state | upper }}" - - - alias: Notify Charger Switch State - initial_state: true - trigger: - - platform: state - entity_id: switch.tesla_model_3_charger_switch - condition: - - condition: template - value_template: '{{ trigger.from_state.state | lower != "unknown" }}' - action: - - service: script.notify_me - data_template: - message: "Tesla Door is now: {{ trigger.to_state.state| upper }}" diff --git a/packages/tv.yaml b/packages/tv.yaml index ecdfe66..a28bfcf 100644 --- a/packages/tv.yaml +++ b/packages/tv.yaml @@ -12,13 +12,6 @@ binary_sensor: payload_off: "off" value_template: "{{ value }}" - - platform: mqtt - name: Sharp TV Command State - state_topic: "/home/sharp_tv_cmd" - payload_on: "on" - payload_off: "off" - value_template: "{{ value }}" - ############################################################################### # _ _ _ # /\ | | | | (_) @@ -29,26 +22,33 @@ binary_sensor: # ############################################################################### automation: - # Restore Familyroom Lights - ############################################################################### - - alias: Restore Familyroom Lights + + - alias: TV Status ON initial_state: true trigger: platform: state - entity_id: input_boolean.animate_downstairs_lights - to: "off" - condition: - - condition: state - entity_id: input_boolean.light_automations - state: "on" + entity_id: remote.streaming_stick_4k + to: "on" action: - - service: light.turn_on - data: - entity_id: group.family_room_lights - transition: 5 - rgb_color: [255, 251, 245] - brightness: 255 - color_temp: 162 + - service: mqtt.publish + data_template: + topic: "/home/sharptv" + payload: "on" + retain: true + + - alias: TV Status OFF + initial_state: true + trigger: + platform: state + entity_id: remote.streaming_stick_4k + to: "unavailable" + action: + - service: mqtt.publish + data_template: + topic: "/home/sharptv" + payload: "off" + retain: true + # Dim Family Room Lights When TV is Turned ON ############################################################################### diff --git a/packages/usps.yaml b/packages/usps.yaml deleted file mode 100644 index 335c388..0000000 --- a/packages/usps.yaml +++ /dev/null @@ -1,105 +0,0 @@ -############################################################################### -# @Author : Mahasri Kalavala -# @Date : 01/27/2018 -# @Package : USPS Package - notifies me of mails and packages. -############################################################################### -homeassistant: - customize: - sensor.usps_mail: - friendly_name: USPS Mail - icon: mdi:email-outline - sensor.usps_packages: - friendly_name: USPS Packages - icon: mdi:package-variant - -sensor: - - platform: mqtt - name: "USPS Mail" - state_topic: "/usps/mails" - value_template: "{{ value }}" - - - platform: mqtt - name: USPS Packages - state_topic: "/usps/packages" - value_template: "{{ value }}" - -camera: - - platform: generic - name: USPS Mail Pictures - still_image_url: !secret usps_camera_url - -############################################################################### -# _ _ _ -# /\ | | | | (_) -# / \ _ _| |_ ___ _ __ ___ __ _| |_ _ ___ _ __ ___ -# / /\ \| | | | __/ _ \| '_ ` _ \ / _` | __| |/ _ \| '_ \/ __| -# / ____ \ |_| | || (_) | | | | | | (_| | |_| | (_) | | | \__ \ -# /_/ \_\__,_|\__\___/|_| |_| |_|\__,_|\__|_|\___/|_| |_|___/ -# -############################################################################### -automation: - # Notify USPS mails via TTS, and iOS notification with attachment - ############################################################################### - - alias: Notify USPS Mail - initial_state: true - trigger: - - platform: state - entity_id: sensor.usps_mail - condition: - - condition: template - value_template: "{{ states('sensor.usps_mail') != 'unknown' }}" - - condition: template - value_template: "{{ states('sensor.usps_mail') | int > 0 }}" - - condition: template - value_template: "{{ ((now().hour | int) > 7) and ((now().hour | int) < 16) }}" - action: - - service: script.voice_notify - data_template: - message: > - {%- if states('sensor.usps_mail') | int == 1 -%} - Attention: USPS is delivering {{ states('sensor.usps_mail') }} mail today. - {%- else -%} - Attention: USPS is delivering {{ states('sensor.usps_mail') }} mails today. - {%- endif -%} - - service: script.led_message - data_template: - message: > - {%- if states('sensor.usps_mail') | int == 1 -%} - USPS is delivering {{ states('sensor.usps_mail') }} mail today. - {%- else -%} - USPS is delivering {{ states('sensor.usps_mail') }} mails today. - {%- endif -%} - - service: notify.ios_devices - data_template: - message: "USPS will be delivering {{ states('sensor.usps_mail') }} mail(s) today." - data: - push: - category: camera - entity_id: "camera.usps_mail_pictures" - attachment: - url: "{{ state_attr('camera.usps_mail_pictures', 'entity_picture') }}" - content-type: jpg - - # Notify USPS packages via TTS. Usually there are no pictures for packages - ############################################################################### - - alias: Notify USPS Packages - initial_state: true - trigger: - - platform: state - entity_id: sensor.usps_packages - condition: - - condition: template - value_template: "{{ states('sensor.usps_packages') != 'unknown' }}" - - condition: template - value_template: "{{ states('sensor.usps_packages') | int > 0 }}" - - condition: template - value_template: "{{ ((now().hour | int) > 7) and ((now().hour | int) < 16) }}" - action: - - service: script.voice_notify - data_template: - message: > - {%- if states('sensor.usps_packages') | int == 1 -%} - Attention: USPS is delivering {{ states('sensor.usps_packages') }} package today. - {%- else -%} - Attention: USPS is delivering {{ states('sensor.usps_packages') }} packages today. - {%- endif -%} diff --git a/packages/watchdog.yaml b/packages/watchdog.yaml index fdd5dde..9f61734 100644 --- a/packages/watchdog.yaml +++ b/packages/watchdog.yaml @@ -106,7 +106,7 @@ automation: # General Watch Dog automation: # Keeps and eye on the lights & switches, turns off after 10 PM if they are on. ############################################################################### - - alias: Lights And Switches WatchDog + - alias: Lights And Switches WatchDog 10 Min initial_state: true trigger: - platform: state @@ -114,12 +114,11 @@ automation: - switch.basement_left - switch.basement_right - switch.front_room - - switch.guest_bedroom - - switch.kids_bed_accent - - switch.kids_bedroom - - switch.kitchen - - switch.prayer_room - - switch.upstairs_fragrance + - switch.srinika_bedroom + - switch.hasika_bed_accent + - switch.hasika_bedroom + - switch.kitchen_switch + - switch.study_room - light.hue_color_lamp_1 - light.hue_color_lamp_2 - light.hue_color_lamp_3 @@ -139,3 +138,281 @@ automation: - service: homeassistant.turn_off data_template: entity_id: "{{ trigger.entity_id }}" + + - alias: Guest Bathroom Lights WatchDog + initial_state: true + trigger: + - platform: state + entity_id: + - switch.guest_bathroom_lights + to: "on" + for: + minutes: "{{ states('input_number.guest_bathroom_lights')|int }}" + condition: + - condition: state + entity_id: input_boolean.light_automations + state: "on" + action: + - service: homeassistant.turn_off + data_template: + entity_id: "{{ trigger.entity_id }}" + + - alias: Master Bathroom Lights WatchDog + initial_state: true + trigger: + - platform: state + entity_id: + - light.master_bathroom_lights + to: "on" + for: + minutes: "{{ states('input_number.master_bathroom_lights')|int }}" + condition: + - condition: state + entity_id: input_boolean.light_automations + state: "on" + action: + - service: homeassistant.turn_off + data_template: + entity_id: "{{ trigger.entity_id }}" + + - alias: Garage Lights WatchDog + initial_state: true + trigger: + - platform: state + entity_id: + - switch.garage + to: "on" + for: + minutes: "{{ states('input_number.garage_lights')|int }}" + condition: + - condition: state + entity_id: input_boolean.light_automations + state: "on" + action: + - service: homeassistant.turn_off + data_template: + entity_id: "{{ trigger.entity_id }}" + + - alias: Garage Shop Lights WatchDog + initial_state: true + trigger: + - platform: state + entity_id: + - switch.garage_shop_lights + to: "on" + for: + minutes: "{{ states('input_number.garage_shop_lights')|int }}" + condition: + - condition: state + entity_id: input_boolean.light_automations + state: "on" + action: + - service: homeassistant.turn_off + data_template: + entity_id: "{{ trigger.entity_id }}" + + - alias: Guest Bathroom Exhaust WatchDog + initial_state: true + trigger: + - platform: state + entity_id: + - switch.guest_bathroom_exhaust + to: "on" + for: + minutes: "{{ states('input_number.guest_bathroom_exhaust_timer_duration')|int }}" + condition: + - condition: state + entity_id: input_boolean.light_automations + state: "on" + action: + - service: homeassistant.turn_off + data_template: + entity_id: "{{ trigger.entity_id }}" + + - alias: Master Bathroom Shower Exhaust WatchDog + initial_state: true + trigger: + - platform: state + entity_id: + - switch.master_bathroom_shower_exhaust + to: "on" + for: + minutes: "{{ states('input_number.master_bathroom_shower_exhaust_timer_duration')|int }}" + condition: + - condition: state + entity_id: input_boolean.light_automations + state: "on" + action: + - service: homeassistant.turn_off + data_template: + entity_id: "{{ trigger.entity_id }}" + + - alias: Master Bathroom Toilet Exhaust WatchDog + initial_state: true + trigger: + - platform: state + entity_id: + - switch.master_bathroom_toilet_exhaust + to: "on" + for: + minutes: "{{ states('input_number.master_bathroom_toilet_exhaust_timer_duration')|int }}" + condition: + - condition: state + entity_id: input_boolean.light_automations + state: "on" + action: + - service: homeassistant.turn_off + data_template: + entity_id: "{{ trigger.entity_id }}" + + +############################################################################# +# CLOSET LIGHTS WATCH DOG +############################################################################# + + - alias: Srinika Bedroom Closet WatchDog + initial_state: true + trigger: + - platform: state + entity_id: + - switch.srinika_bedroom_closet + to: "on" + for: + minutes: "{{ states('input_number.srinika_bedroom_closet_lights')|int }}" + condition: + - condition: state + entity_id: input_boolean.light_automations + state: "on" + action: + - service: homeassistant.turn_off + data_template: + entity_id: "{{ trigger.entity_id }}" + + - alias: Hasika Bedroom Closet WatchDog + initial_state: true + trigger: + - platform: state + entity_id: + - switch.hasika_bedroom_closet + to: "on" + for: + minutes: "{{ states('input_number.hasika_bedroom_closet_lights')|int }}" + condition: + - condition: state + entity_id: input_boolean.light_automations + state: "on" + action: + - service: homeassistant.turn_off + data_template: + entity_id: "{{ trigger.entity_id }}" + + - alias: Notify Plex User Status + initial_state: true + trigger: + # - platform: numeric_state + # entity_id: sensor.plex_mahasri_nas + # above: 0 + # for: + # minutes: 2 + - platform: state + entity_id: + - media_player.plex_adi_bh_plex_for_roku_roku3 + - media_player.plex_adi_bh_plex_for_roku_rokuultra + - media_player.plex_prade5_plex_for_roku_roku_express + to: 'playing' + for: + minutes: 2 + action: + - service: script.notify_me + data_template: + message: >- + {%- set tag_map = {'adi.bh':'Adi', 'prade5':'Pradeep'} -%} + {% for item in states.media_player if item.state == 'playing' and state_attr(item.entity_id, 'media_title') != None + and state_attr(item.entity_id, 'username') != 'kalavala' + and tag_map[state_attr(item.entity_id, 'username')] |trim != '' %} + + {{ tag_map[state_attr(item.entity_id, 'username')] }} is watching {% if state_attr(item.entity_id, 'media_content_type') == "movie" -%} + {{ "a movie, " + state_attr(item.entity_id, 'media_title') |title }} + {% endif %} + {%- if state_attr(item.entity_id, 'media_content_type') == "tvshow" %} + TV Show - {{ state_attr(item.entity_id, 'media_series_title') }} + Season: {{ state_attr(item.entity_id, 'media_season') }}, Episode: {{ state_attr(item.entity_id, 'media_episode') }} ({{ state_attr(item.entity_id, 'media_title') }}) + {% endif %} + {% endfor %} + + # - alias: Lights And Switches WatchDog 10 Min + # initial_state: true + # trigger: + # - platform: state + # entity_id: + # - switch.guest_bathroom_exhaust + # - switch.master_bathroom_toilet_exhaust + # to: "on" + # for: + # minutes: 10 + # condition: + # - condition: state + # entity_id: input_boolean.light_automations + # state: "on" + # action: + # - service: homeassistant.turn_off + # data_template: + # entity_id: "{{ trigger.entity_id }}" + +# +# Main master Bathoom has more CFM to vent out... keep it for 20 minutes +# + # - alias: Lights And Switches WatchDog 20 Min + # initial_state: true + # trigger: + # - platform: state + # entity_id: + # - switch.master_bathroom_shower_exhaust + # to: "on" + # for: + # minutes: 20 + # condition: + # - condition: state + # entity_id: input_boolean.light_automations + # state: "on" + # action: + # - service: homeassistant.turn_off + # data_template: + # entity_id: "{{ trigger.entity_id }}" + + # - alias: Lights And Switches WatchDog 30 Min + # initial_state: true + # trigger: + # - platform: state + # entity_id: + # - switch.guest_bathroom_lights + # - switch.master_bathroom_toilet_light + # to: "on" + # for: + # minutes: 30 + # condition: + # - condition: state + # entity_id: input_boolean.light_automations + # state: "on" + # action: + # - service: homeassistant.turn_off + # data_template: + # entity_id: "{{ trigger.entity_id }}" + + # - alias: Lights And Switches WatchDog 45 Min + # initial_state: true + # trigger: + # - platform: state + # entity_id: + # - switch.garage_shop_lights + # to: "on" + # for: + # minutes: 45 + # condition: + # - condition: state + # entity_id: input_boolean.light_automations + # state: "on" + # action: + # - service: homeassistant.turn_off + # data_template: + # entity_id: "{{ trigger.entity_id }}" \ No newline at end of file diff --git a/packages/weather.yaml b/packages/weather.yaml index c60e62b..cb40ac3 100644 --- a/packages/weather.yaml +++ b/packages/weather.yaml @@ -115,6 +115,7 @@ binary_sensor: weather: - platform: darksky api_key: !secret darksky_api_key + mode: daily sensor: - platform: darksky diff --git a/packages/wfh.yaml b/packages/wfh.yaml deleted file mode 100644 index bf1fec1..0000000 --- a/packages/wfh.yaml +++ /dev/null @@ -1,87 +0,0 @@ -############################################################################### -# @author : Mahasri Kalavala -# @date : 11/07/2017 -# @package : Work From Home (wfh) -# @description : Reminds me to Get Up and Walk around the house once -# every 30 minutes during Work From Home days -############################################################################### -homeassistant: - customize: - timer.wfh_timer: - hidden: true - -timer: - wfh_timer: - duration: "00:30:00" - -############################################################################### -# _ _ _ -# /\ | | | | (_) -# / \ _ _| |_ ___ _ __ ___ __ _| |_ _ ___ _ __ ___ -# / /\ \| | | | __/ _ \| '_ ` _ \ / _` | __| |/ _ \| '_ \/ __| -# / ____ \ |_| | || (_) | | | | | | (_| | |_| | (_) | | | \__ \ -# /_/ \_\__,_|\__\___/|_| |_| |_|\__,_|\__|_|\___/|_| |_|___/ -# -############################################################################### - -automation: - # Start WFH timer if Suresh is HOME during weekdays between 10 AM and 5 PM - ############################################################################### - - alias: WFH Timer Start - initial_state: false - trigger: - - platform: time_pattern - minutes: "/5" - seconds: 00 - condition: - - condition: template - value_template: "{{ states('binary_sensor.workday_sensor') == 'on' }}" - - condition: template - value_template: "{{ now().hour|int >= 10 and now().hour|int < 17 }}" - - condition: template - value_template: "{{ states('timer.wfh_timer') == 'idle' }}" - - condition: template - value_template: "{{ states('device_tracker.life360_suresh') == 'home' }}" - action: - - service: timer.start - entity_id: timer.wfh_timer - - # Timer elapsed... Remind Suresh to take a quick walk - # Restart the timer ONLY if the time is betwen office hours (10 AM and 5 PM) - ############################################################################### - - alias: Timer Elapsed - Take a walk - initial_state: false - trigger: - - platform: event - event_type: timer.finished - event_data: - entity_id: timer.wfh_timer - action: - - service_template: > - {% if now().hour | int >= 10 and now().hour | int < 17 %} - timer.start - {% else %} - timer.cancel - {% endif %} - entity_id: timer.wfh_timer - - condition: template - value_template: "{{ now().hour|int >= 10 and now().hour|int < 17 }}" - - service: script.voice_notify - data_template: - message: "It is time to stand up and walk around!" - - # Cancel timer (if active) When Suresh left home - ############################################################################### - - alias: Cancel WFH Timer When Suresh Leaves Home - initial_state: false - trigger: - - platform: zone - entity_id: device_tracker.life360_suresh - zone: zone.home - event: leave - condition: - - condition: template - value_template: "{{ states('timer.wfh_timer') == 'active' }}" - action: - - service: timer.cancel - entity_id: timer.wfh_timer diff --git a/packages/xiaomi_magic_cubes.yaml b/packages/xiaomi_magic_cubes.yaml index d0aea2b..beef560 100644 --- a/packages/xiaomi_magic_cubes.yaml +++ b/packages/xiaomi_magic_cubes.yaml @@ -75,7 +75,7 @@ automation: state: "on" action: - service: switch.toggle - entity_id: switch.kitchen + entity_id: switch.kitchen_switch # Double Tap: Turn OFF Downstairs Lights - alias: Family Room Cube Event Tap Twice @@ -186,7 +186,7 @@ automation: state: "on" action: - service_template: switch.toggle - entity_id: switch.guest_bedroom + entity_id: switch.srinika_bedroom # Shake: Toggle Do Not Disturb Mode - alias: Srinika Room Cube Event Shake @@ -227,7 +227,7 @@ automation: state: "on" action: - service_template: switch.toggle - entity_id: switch.kids_bedroom + entity_id: switch.hasika_bedroom # Shake: Toggle Do Not Disturb Mode - alias: Hasika Room Cube Event Shake @@ -270,7 +270,7 @@ automation: state: "on" action: - service: switch.toggle - entity_id: switch.prayer_room + entity_id: switch.study_room # Shake: Toggle Do Not Disturb Mode - alias: Study Room Cube Event Shake @@ -311,9 +311,11 @@ automation: state: "on" action: - service: homeassistant.turn_off - entity_id: group.downstairs_lights + data: + entity_id: group.downstairs_lights - service: homeassistant.turn_off - entity_id: group.upstairs_lights + data: + entity_id: group.upstairs_lights # Flip 180: Toggle Lights - alias: Master Bedroom Cube Event Flip180 @@ -428,6 +430,7 @@ automation: {% else %} script.play_dog_sounds {% endif %} + - service: script.doorbell_camera_pics - alias: Doorbell Double Press initial_state: true @@ -444,6 +447,7 @@ automation: {% else %} script.play_dog_sounds {% endif %} + - service: script.doorbell_camera_pics - alias: Doorbell Long Press initial_state: true @@ -460,3 +464,43 @@ automation: {% else %} script.play_dog_sounds {% endif %} + - service: script.doorbell_camera_pics + +################################################################################ +# Script for sending camera snapshots when doorbell is pressed +################################################################################ +script: + + doorbell_camera_pics: + sequence: + - service: script.notify_me + data: + message: "ALERT! Someone is at the front door!" + - service: camera.snapshot + data_template: + entity_id: "camera.frontdoor_camera" + filename: + "{{ '/config/www/downloads/camera/frontdoor/frontdoor_' ~ + (state_attr('script.doorbell_camera_pics', 'last_triggered') ~ '').replace('-','_') + .replace(' ', '_').replace(':','_').replace('.','_').replace('+','_') ~ '.jpg' }}" + - service: camera.snapshot + data_template: + entity_id: "camera.driveway_camera" + filename: + "{{ '/config/www/downloads/camera/driveway/driveway_' ~ + (state_attr('script.doorbell_camera_pics', 'last_triggered') ~ '').replace('-','_') + .replace(' ', '_').replace(':','_').replace('.','_').replace('+','_') ~ '.jpg' }}" + - service: notify.telegram + data_template: + title: "Door Bell" + message: "Someone rang door bell!" + data: + photo: + - file: "{{ '/config/www/downloads/camera/frontdoor/frontdoor_' ~ + (state_attr('script.doorbell_camera_pics', 'last_triggered') ~ '').replace('-','_') + .replace(' ', '_').replace(':','_').replace('.','_').replace('+','_') ~ '.jpg' }}" + caption: "Someone rang door bell!" + - file: "{{ '/config/www/downloads/camera/driveway/driveway_' ~ + (state_attr('script.doorbell_camera_pics', 'last_triggered') ~ '').replace('-','_') + .replace(' ', '_').replace(':','_').replace('.','_').replace('+','_') ~ '.jpg' }}" + caption: "Someone rang door bell!" \ No newline at end of file diff --git a/packages/zones.yaml b/packages/zones.yaml index e56a437..a796c2e 100644 --- a/packages/zones.yaml +++ b/packages/zones.yaml @@ -10,18 +10,9 @@ homeassistant: friendly_name: Away Mode zone.home: friendly_name: Home - zone.work: - friendly_name: Office group.zone_alerts: order: 40 -zone: - - name: work - latitude: !secret work_latitude - longitude: !secret work_longitude - radius: 200 - icon: mdi:briefcase - input_boolean: home_mode_away: name: Away @@ -29,11 +20,7 @@ input_boolean: proximity: home: - devices: device_tracker.life360_suresh - tolerance: 50 - unit_of_measurement: mi - work: - devices: device_tracker.life360_suresh + devices: device_tracker.suresh tolerance: 50 unit_of_measurement: mi @@ -56,16 +43,12 @@ automation: trigger: - platform: zone entity_id: - - device_tracker.life360_hasika - - device_tracker.life360_mallika - - device_tracker.life360_srinika - - device_tracker.life360_suresh + - device_tracker.hasika + - device_tracker.mallika + - device_tracker.srinika + - device_tracker.suresh zone: zone.home event: enter - - platform: zone - entity_id: device_tracker.life360_suresh - zone: zone.work - event: enter condition: - condition: template value_template: "{{ states('input_boolean.zone_alerts') == 'on' }}" @@ -85,16 +68,12 @@ automation: trigger: - platform: zone entity_id: - - device_tracker.life360_hasika - - device_tracker.life360_mallika - - device_tracker.life360_srinika - - device_tracker.life360_suresh + - device_tracker.hasika + - device_tracker.mallika + - device_tracker.srinika + - device_tracker.suresh zone: zone.home event: leave - - platform: zone - entity_id: device_tracker.life360_suresh - zone: zone.work - event: leave condition: - condition: template value_template: "{{ states('input_boolean.zone_alerts') == 'on' }}" @@ -119,10 +98,10 @@ automation: trigger: - platform: state entity_id: - - device_tracker.life360_mallika - - device_tracker.life360_suresh - - device_tracker.life360_srinika - - device_tracker.life360_hasika + - device_tracker.mallika + - device_tracker.suresh + - device_tracker.srinika + - device_tracker.hasika from: "not_home" to: "home" for: "00:02:00" @@ -142,32 +121,25 @@ automation: greeting: "no" - service: input_boolean.turn_off entity_id: input_boolean.home_mode_away + - service: switch.turn_on + entity_id: switch.chromecast_monitor ############################################################################## # Alert when every one is away ############################################################################## - - alias: Alert when everyone is AWAY + - alias: Poll Home Away Mode initial_state: true trigger: platform: time_pattern minutes: 00 seconds: "/30" - condition: - - condition: template - value_template: "{{ states('input_boolean.home_mode_away') == 'off' }}" - - condition: template - value_template: > - {% set suresh = states('device_tracker.life360_suresh') %} - {% set mallika = states('device_tracker.life360_mallika') %} - {% set srinika = states('device_tracker.life360_srinika') %} - {% set hasika = states('device_tracker.life360_hasika') %} - {% if suresh != "home" and mallika != "home" and srinika != "home" and hasika != "home" %} - True - {% else %} - False - {% endif %} action: - - service: input_boolean.turn_on + - service_template: >- + {%- set suresh = states('device_tracker.suresh') -%} + {%- set mallika = states('device_tracker.mallika') -%} + {%- set srinika = states('device_tracker.srinika') -%} + {%- set hasika = states('device_tracker.hasika') -%} + {{ 'input_boolean.turn_on' if suresh != "home" and mallika != "home" and srinika != "home" and hasika != "home" else 'input_boolean.turn_off' }} entity_id: input_boolean.home_mode_away - alias: Home Mode Away ON @@ -196,21 +168,3 @@ automation: - service: script.notify_me data_template: message: "Suresh is on his way home, he is within the 5 miles range. Should be home soon!" - - condition: template - value_template: > - {% set suresh = states('device_tracker.life360_suresh') %} - {% set mallika = states('device_tracker.life360_mallika') %} - {% set srinika = states('device_tracker.life360_srinika') %} - {% set hasika = states('device_tracker.life360_hasika') %} - {% if suresh != "home" and mallika != "home" and srinika != "home" and hasika != "home" %} - True - {% else %} - False - {% endif %} - - service: climate.set_away_mode - data: - entity_id: climate.dining_room - away_mode: "false" - - service: script.notify_me - data_template: - message: "Your Nest thermostat is set to HOME mode. Thank you!" diff --git a/packages/zwave_batteries.yaml b/packages/zwave_batteries.yaml deleted file mode 100644 index f149bcd..0000000 --- a/packages/zwave_batteries.yaml +++ /dev/null @@ -1,222 +0,0 @@ -# ############################################################################### -# # @author : Mahasri Kalavala -# # @date : 04/20/2018 -# # @package : zwave batteries -# # @description : Zwave batteries using input_label & MQTT -# ############################################################################### - -# input_label: -# audio_detector: -# back_door_sensor: -# basement_door_sensor: -# downstairs_multi_sensor: -# zwave_front_door_sensor: -# front_room_multi_sensor: -# garage_door_sensor: -# guest_bedroom_multi_sensor: -# kitchen_motion_sensor: -# single_car_garage_door_tilt_sensor: -# stairs_motion_sensor: -# tv_multi_sensor: -# two_car_garage_door_tilt_sensor: -# upstairs_multi_sensor: -# wallmote: -# ecolink_motion_detector: -# ecolink_firefighter: -# ecolink_door_window_sensor_2: -# aeon_labs_zw100_multisensor_6_2: -# aeon_labs_zw100_multisensor_6: -# ecolink_door_window_sensor: -# ecolink_garage_door_tilt_sensor: - -# suresh_battery: -# mallika_battery: -# srinika_battery: -# hasika_battery: - -# suresh_charging: -# mallika_charging: -# srinika_charging: -# hasika_charging: - -# suresh_wifi: -# mallika_wifi: -# srinika_wifi: -# hasika_wifi: - -# ############################################################################### -# # _ _ _ -# # /\ | | | | (_) -# # / \ _ _| |_ ___ _ __ ___ __ _| |_ _ ___ _ __ ___ -# # / /\ \| | | | __/ _ \| '_ ` _ \ / _` | __| |/ _ \| '_ \/ __| -# # / ____ \ |_| | || (_) | | | | | | (_| | |_| | (_) | | | \__ \ -# # /_/ \_\__,_|\__\___/|_| |_| |_|\__,_|\__|_|\___/|_| |_|___/ -# # -# ############################################################################### - -# automation: -# - alias: Update ZWave Battery Levels -# initial_state: true -# trigger: -# - platform: event -# event_type: state_changed -# condition: -# - condition: template -# value_template: "{{ trigger.event.data.entity_id is not none }}" -# - condition: template -# value_template: "{{ trigger.event.data.entity_id.split('.')[0] == 'zwave' }}" -# - condition: template -# value_template: "{{ trigger.event.data.new_state.attributes is not none }}" -# - condition: template -# value_template: "{{ trigger.event.data.new_state.attributes.battery_level | trim != '' }}" -# - condition: template -# value_template: "{{ trigger.event.data.new_state.attributes.battery_level | default(999) | int != 999 }}" -# action: -# - service: input_label.set_value -# data_template: -# entity_id: "input_label.{{- trigger.event.data.entity_id.split('.')[1] -}}" -# value: "{{ trigger.event.data.new_state.attributes.battery_level }}" -# - service: input_label.set_name -# data_template: -# entity_id: "input_label.{{- trigger.event.data.entity_id.split('.')[1] -}}" -# value: "{{ trigger.event.data.new_state.attributes.friendly_name }}'s Battery" -# - service: input_label.set_icon -# data_template: -# entity_id: "input_label.{{- trigger.event.data.entity_id.split('.')[1] -}}" -# value: > -# {% set battery_level = trigger.event.data.new_state.attributes.battery_level | int %} -# {% set battery_round = (battery_level / 10)|int * 10 %} -# {% if battery_round >= 100 %} -# mdi:battery -# {% elif battery_round > 0 %} -# mdi:battery-{{ battery_round }} -# {% else %} -# mdi:battery-alert -# {% endif %} - -# # - alias: Update Phone Battery Levels -# # initial_state: true -# # trigger: -# # platform: mqtt -# # topic: "owntracks/+/+" -# # action: -# # - service: input_label.set_value -# # data_template: -# # entity_id: "input_label.{{trigger.topic.split('/')[-1]}}_wifi" -# # value: "{{ 'Yes' if trigger.payload_json.conn == 'w' else 'No' }}" -# # - service: input_label.set_icon -# # data_template: -# # entity_id: "input_label.{{trigger.topic.split('/')[-1]}}_wifi" -# # value: "{{ 'mdi:wifi' if trigger.payload_json.conn == 'w' else 'mdi:wifi-off' }}" -# # - service: input_label.set_name -# # data_template: -# # entity_id: "input_label.{{trigger.topic.split('/')[-1]}}_wifi" -# # value: "{{trigger.topic.split('/')[-1] | title }}'s phone wifi enabled?" - -# # - service: input_label.set_value -# # data_template: -# # entity_id: "input_label.{{trigger.topic.split('/')[-1]}}_battery" -# # value: "{{ trigger.payload_json.batt | int }}" -# # - service: input_label.set_name -# # data_template: -# # entity_id: "input_label.{{trigger.topic.split('/')[-1]}}_battery" -# # value: "{{trigger.topic.split('/')[-1] | title }}'s Battery" -# # - service: input_label.set_icon -# # data_template: -# # entity_id: "input_label.{{trigger.topic.split('/')[-1]}}_battery" -# # value: > -# # {% set battery_level = trigger.payload_json.batt | int %} -# # {% set battery_round = (battery_level / 10)|int * 10 %} -# # {% if trigger.payload_json.charging == 1 %} -# # {% if battery_round >= 100 %} -# # mdi:battery-charging-100 -# # {% elif battery_round > 0 %} -# # mdi:battery-charging-{{ battery_round }} -# # {% else %} -# # mdi:battery-alert -# # {% endif %} -# # {% else %} -# # {% if battery_round >= 100 %} -# # mdi:battery -# # {% elif battery_round > 0 %} -# # mdi:battery-{{ battery_round }} -# # {% else %} -# # mdi:battery-alert -# # {% endif %} -# # {% endif %} - -# - alias: Update Phone Battery Levels From Life360 -# initial_state: true -# trigger: -# - platform: event -# event_type: state_changed -# condition: -# - condition: template -# value_template: "{{ trigger.event.data.entity_id is not none }}" -# - condition: template -# value_template: "{{ 'life360_' in trigger.event.data.entity_id }}" -# - condition: template -# value_template: "{{ trigger.event.data.new_state.attributes is not none }}" -# action: -# - service: input_label.set_name -# data_template: -# entity_id: "input_label.{{- trigger.event.data.entity_id.split('.')[1].split('_')[1] -}}_battery" -# value: "{{- trigger.event.data.entity_id.split('.')[1].split('_')[1] |title -}}'s Battery" -# - service: input_label.set_value -# data_template: -# entity_id: "input_label.{{- trigger.event.data.entity_id.split('.')[1].split('_')[1] -}}_battery" -# value: "{{ trigger.event.data.new_state.attributes.battery }}" -# - service: input_label.set_icon -# data_template: -# entity_id: "input_label.{{- trigger.event.data.entity_id.split('.')[1].split('_')[1] -}}_battery" -# value: > -# {% set battery_level = trigger.event.data.new_state.attributes.battery | int %} -# {% set battery_round = (battery_level / 10)|int * 10 %} -# {% if trigger.event.data.new_state.attributes.battery_charging == "true" %} -# {% if battery_round >= 100 %} -# mdi:battery-charging-100 -# {% elif battery_round > 0 %} -# mdi:battery-charging-{{ battery_round }} -# {% else %} -# mdi:battery-alert -# {% endif %} -# {% else %} -# {% if battery_round >= 100 %} -# mdi:battery -# {% elif battery_round > 0 %} -# mdi:battery-{{ battery_round }} -# {% else %} -# mdi:battery-alert -# {% endif %} -# {% endif %} -# - service: input_label.set_value -# data_template: -# entity_id: "input_label.{{- trigger.event.data.entity_id.split('.')[1].split('_')[1] -}}_wifi" -# value: "{{ 'WiFi' if trigger.event.data.new_state.attributes.wifi_on |string |lower == 'true' else 'LTE' }}" -# - service: input_label.set_value -# data_template: -# entity_id: "input_label.{{- trigger.event.data.entity_id.split('.')[1].split('_')[1] -}}_charging" -# value: "{{ 'Charging' if trigger.event.data.new_state.attributes.battery_charging |string |lower == 'true' else 'Not Charging' }}" -# - service: input_label.set_icon -# data_template: -# entity_id: "input_label.{{- trigger.event.data.entity_id.split('.')[1].split('_')[1] -}}_charging" -# value: > -# {% set battery_level = trigger.event.data.new_state.attributes.battery | int %} -# {% set battery_round = (battery_level / 10)|int * 10 %} -# {% if trigger.event.data.new_state.attributes.battery_charging == "true" %} -# {% if battery_round >= 100 %} -# mdi:battery-charging-100 -# {% elif battery_round > 0 %} -# mdi:battery-charging-{{ battery_round }} -# {% else %} -# mdi:battery-alert -# {% endif %} -# {% else %} -# {% if battery_round >= 100 %} -# mdi:battery -# {% elif battery_round > 0 %} -# mdi:battery-{{ battery_round }} -# {% else %} -# mdi:battery-alert -# {% endif %} -# {% endif %} diff --git a/packages/zwave_sensors.yaml b/packages/zwave_sensors.yaml deleted file mode 100644 index e389e6c..0000000 --- a/packages/zwave_sensors.yaml +++ /dev/null @@ -1,318 +0,0 @@ -# ################################################################# -# # @author : Mahasri Kalavala -# # @date : 09/18/17 -# # @package : Z-Wave package -# # @description : Z-Wave Still and it's configuration stuff -# # -# # This entire page is auto generated by the script (link below): -# # https://github.com/skalavala/mysmarthome/blob/master/jinja_helpers/zwave_auto_gen.md -# ################################################################# - -# homeassistant: -# customize: -# # ZWave Binary Sensors -# binary_sensor.audio_detector_sensor: -# friendly_name: Audio Detector Sensor -# binary_sensor.basement_door_sensor_sensor: -# friendly_name: Basement Door Sensor -# binary_sensor.downstairs_multi_sensor_sensor: -# friendly_name: Downstairs Multi Sensor -# binary_sensor.front_door_sensor_sensor: -# friendly_name: Front Door Sensor -# binary_sensor.front_room_multi_sensor_sensor: -# friendly_name: Front Room Multi Sensor -# binary_sensor.garage_door_sensor_sensor: -# friendly_name: Garage Door Sensor -# binary_sensor.guest_bedroom_multi_sensor_sensor: -# friendly_name: Guest Bedroom Multi Sensor -# binary_sensor.kitchen_motion_sensor_sensor: -# friendly_name: Kitchen Motion Sensor -# binary_sensor.door_window_sensor_158d0004248d5b: -# friendly_name: Single Car Garage Door -# binary_sensor.stairs_motion_sensor_sensor: -# friendly_name: Stairs Motion Sensor -# binary_sensor.tv_multi_sensor_sensor: -# friendly_name: TV Multi Sensor -# binary_sensor.door_window_sensor_158d0004231f7b: -# friendly_name: Double Car Garage Door -# binary_sensor.upstairs_multi_sensor_sensor: -# friendly_name: Upstairs Multi Sensor - -# # ZWave Sensors -# sensor.audio_detector_alarm_level: -# friendly_name: Audio Detector Alarm Level -# sensor.audio_detector_alarm_type: -# friendly_name: Audio Detector Alarm Type -# sensor.audio_detector_burglar: -# friendly_name: Audio Detector Burglar -# sensor.audio_detector_carbon_monoxide: -# friendly_name: Audio Detector Carbon Monoxide -# sensor.audio_detector_power_management: -# friendly_name: Audio Detector Power Management -# sensor.audio_detector_smoke: -# friendly_name: Audio Detector Smoke -# sensor.audio_detector_sourcenodeid: -# friendly_name: Audio Detector SourceNodeId -# sensor.audio_detector_temperature: -# friendly_name: Audio Detector Temperature -# sensor.back_door_sensor_access_control: -# friendly_name: Back Door Sensor Access Control -# sensor.back_door_sensor_alarm_level: -# friendly_name: Back Door Sensor Alarm Level -# sensor.back_door_sensor_alarm_type: -# friendly_name: Back Door Sensor Alarm Type -# sensor.back_door_sensor_burglar: -# friendly_name: Back Door Sensor Burglar -# sensor.back_door_sensor_power_management: -# friendly_name: Back Door Sensor Power Management -# sensor.back_door_sensor_sourcenodeid: -# friendly_name: Back Door Sensor SourceNodeId -# sensor.basement_door_sensor_access_control: -# friendly_name: Basement Door Sensor Access Control -# sensor.basement_door_sensor_alarm_level: -# friendly_name: Basement Door Sensor Alarm Level -# sensor.basement_door_sensor_alarm_type: -# friendly_name: Basement Door Sensor Alarm Type -# sensor.basement_door_sensor_burglar: -# friendly_name: Basement Door Sensor Burglar -# sensor.basement_door_sensor_power_management: -# friendly_name: Basement Door Sensor Power Management -# sensor.basement_door_sensor_sourcenodeid: -# friendly_name: Basement Door Sensor SourceNodeId -# sensor.downstairs_multi_sensor_alarm_level: -# friendly_name: Downstairs Multi Sensor Alarm Level -# sensor.downstairs_multi_sensor_alarm_type: -# friendly_name: Downstairs Multi Sensor Alarm Type -# sensor.downstairs_multi_sensor_burglar: -# friendly_name: Downstairs Multi Sensor Burglar -# sensor.downstairs_multi_sensor_luminance: -# friendly_name: Downstairs Multi Sensor Luminance -# sensor.downstairs_multi_sensor_power: -# friendly_name: Downstairs Multi Sensor Power -# sensor.downstairs_multi_sensor_relative_humidity: -# friendly_name: Downstairs Multi Sensor Relative Humidity -# sensor.downstairs_multi_sensor_sourcenodeid: -# friendly_name: Downstairs Multi Sensor SourceNodeId -# sensor.downstairs_multi_sensor_temperature: -# friendly_name: Downstairs Multi Sensor Temperature -# sensor.front_room_multi_sensor_alarm_level: -# friendly_name: Front Room Multi Sensor Alarm Level -# sensor.front_room_multi_sensor_alarm_type: -# friendly_name: Front Room Multi Sensor Alarm Type -# sensor.front_room_multi_sensor_burglar: -# friendly_name: Front Room Multi Sensor Burglar -# sensor.front_room_multi_sensor_luminance: -# friendly_name: Front Room Multi Sensor Luminance -# sensor.front_room_multi_sensor_relative_humidity: -# friendly_name: Front Room Multi Sensor Relative Humidity -# sensor.front_room_multi_sensor_sourcenodeid: -# friendly_name: Front Room Multi Sensor SourceNodeId -# sensor.front_room_multi_sensor_temperature: -# friendly_name: Front Room Multi Sensor Temperature -# sensor.front_room_multi_sensor_ultraviolet: -# friendly_name: Front Room Multi Sensor Ultraviolet -# sensor.garage_door_sensor_access_control: -# friendly_name: Garage Door Sensor Access Control -# sensor.garage_door_sensor_alarm_level: -# friendly_name: Garage Door Sensor Alarm Level -# sensor.garage_door_sensor_alarm_type: -# friendly_name: Garage Door Sensor Alarm Type -# sensor.garage_door_sensor_burglar: -# friendly_name: Garage Door Sensor Burglar -# sensor.garage_door_sensor_power_management: -# friendly_name: Garage Door Sensor Power Management -# sensor.garage_door_sensor_sourcenodeid: -# friendly_name: Garage Door Sensor SourceNodeId -# sensor.single_car_garage_door_sensor_status: -# friendly_name: Single Car Garage Door Sensor Status -# sensor.two_car_garage_door_sensor_status: -# friendly_name: Double Car Garage Door Sensor Status -# sensor.guest_bedroom_multi_sensor_alarm_level: -# friendly_name: Guest Bedroom Multi Sensor Alarm Level -# sensor.guest_bedroom_multi_sensor_alarm_type: -# friendly_name: Guest Bedroom Multi Sensor Alarm Type -# sensor.guest_bedroom_multi_sensor_burglar: -# friendly_name: Guest Bedroom Multi Sensor Burglar -# sensor.guest_bedroom_multi_sensor_luminance: -# friendly_name: Guest Bedroom Multi Sensor Luminance -# sensor.guest_bedroom_multi_sensor_relative_humidity: -# friendly_name: Guest Bedroom Multi Sensor Relative Humidity -# sensor.guest_bedroom_multi_sensor_sourcenodeid: -# friendly_name: Guest Bedroom Multi Sensor SourceNodeId -# sensor.guest_bedroom_multi_sensor_temperature: -# friendly_name: Guest Bedroom Multi Sensor Temperature -# sensor.guest_bedroom_multi_sensor_ultraviolet: -# friendly_name: Guest Bedroom Multi Sensor Ultraviolet -# sensor.kitchen_motion_sensor_alarm_level: -# friendly_name: Kitchen Motion Sensor Alarm Level -# sensor.kitchen_motion_sensor_alarm_type: -# friendly_name: Kitchen Motion Sensor Alarm Type -# sensor.kitchen_motion_sensor_burglar: -# friendly_name: Kitchen Motion Sensor Burglar -# sensor.kitchen_motion_sensor_power_management: -# friendly_name: Kitchen Motion Sensor Power Management -# sensor.kitchen_motion_sensor_sourcenodeid: -# friendly_name: Kitchen Motion Sensor SourceNodeId -# sensor.single_car_garage_door_tilt_sensor_access_control: -# friendly_name: Single Car Garage Door Tilt Sensor Access Control -# sensor.single_car_garage_door_tilt_sensor_alarm_level: -# friendly_name: Single Car Garage Door Tilt Sensor Alarm Level -# sensor.single_car_garage_door_tilt_sensor_alarm_type: -# friendly_name: Single Car Garage Door Tilt Sensor Alarm Type -# sensor.single_car_garage_door_tilt_sensor_burglar: -# friendly_name: Single Car Garage Door Tilt Sensor Burglar -# sensor.single_car_garage_door_tilt_sensor_power_management: -# friendly_name: Single Car Garage Door Tilt Sensor Power Management -# sensor.single_car_garage_door_tilt_sensor_sourcenodeid: -# friendly_name: Single Car Garage Door Tilt Sensor SourceNodeId -# sensor.stairs_motion_sensor_alarm_level: -# friendly_name: Stairs Motion Sensor Alarm Level -# sensor.stairs_motion_sensor_alarm_type: -# friendly_name: Stairs Motion Sensor Alarm Type -# sensor.stairs_motion_sensor_burglar: -# friendly_name: Stairs Motion Sensor Burglar -# sensor.stairs_motion_sensor_power_management: -# friendly_name: Stairs Motion Sensor Power Management -# sensor.stairs_motion_sensor_sourcenodeid: -# friendly_name: Stairs Motion Sensor SourceNodeId -# sensor.tv_multi_sensor_alarm_level: -# friendly_name: TV Multi Sensor Alarm Level -# sensor.tv_multi_sensor_alarm_type: -# friendly_name: TV Multi Sensor Alarm Type -# sensor.tv_multi_sensor_burglar: -# friendly_name: TV Multi Sensor Burglar -# sensor.tv_multi_sensor_luminance: -# friendly_name: TV Multi Sensor Luminance -# sensor.tv_multi_sensor_relative_humidity: -# friendly_name: TV Multi Sensor Relative Humidity -# sensor.tv_multi_sensor_sourcenodeid: -# friendly_name: TV Multi Sensor SourceNodeId -# sensor.tv_multi_sensor_temperature: -# friendly_name: TV Multi Sensor Temperature -# sensor.tv_multi_sensor_ultraviolet: -# friendly_name: TV Multi Sensor Ultraviolet -# sensor.two_car_garage_door_tilt_sensor_access_control: -# friendly_name: Two Car Garage Door Tilt Sensor Access Control -# sensor.two_car_garage_door_tilt_sensor_alarm_level: -# friendly_name: Two Car Garage Door Tilt Sensor Alarm Level -# sensor.two_car_garage_door_tilt_sensor_alarm_type: -# friendly_name: Two Car Garage Door Tilt Sensor Alarm Type -# sensor.two_car_garage_door_tilt_sensor_burglar: -# friendly_name: Two Car Garage Door Tilt Sensor Burglar -# sensor.two_car_garage_door_tilt_sensor_power_management: -# friendly_name: Two Car Garage Door Tilt Sensor Power Management -# sensor.two_car_garage_door_tilt_sensor_sourcenodeid: -# friendly_name: Two Car Garage Door Tilt Sensor SourceNodeId -# sensor.upstairs_multi_sensor_alarm_level: -# friendly_name: Upstairs Multi Sensor Alarm Level -# sensor.upstairs_multi_sensor_alarm_type: -# friendly_name: Upstairs Multi Sensor Alarm Type -# sensor.upstairs_multi_sensor_burglar: -# friendly_name: Upstairs Multi Sensor Burglar -# sensor.upstairs_multi_sensor_luminance: -# friendly_name: Upstairs Multi Sensor Luminance -# sensor.upstairs_multi_sensor_relative_humidity: -# friendly_name: Upstairs Multi Sensor Relative Humidity -# sensor.upstairs_multi_sensor_sourcenodeid: -# friendly_name: Upstairs Multi Sensor SourceNodeId -# sensor.upstairs_multi_sensor_temperature: -# friendly_name: Upstairs Multi Sensor Temperature -# sensor.upstairs_multi_sensor_ultraviolet: -# friendly_name: Upstairs Multi Sensor Ultraviolet -# sensor.wallmote_alarm_level: -# friendly_name: Wallmote Alarm Level -# sensor.wallmote_alarm_type: -# friendly_name: Wallmote Alarm Type -# sensor.wallmote_power_management: -# friendly_name: Wallmote Power Management -# sensor.wallmote_sourcenodeid: -# friendly_name: Wallmote SourceNodeId -# sensor.zwave_smart_switch_current: -# friendly_name: ZWave Smart Switch Current -# sensor.zwave_smart_switch_energy: -# friendly_name: ZWave Smart Switch Energy -# sensor.zwave_smart_switch_power: -# friendly_name: ZWave Smart Switch Power -# sensor.zwave_smart_switch_previous_reading: -# friendly_name: ZWave Smart Switch Previous Reading -# sensor.zwave_smart_switch_voltage: -# friendly_name: ZWave Smart Switch Voltage - -# # ZWave Switches - -# switch.kitchen_siren_switch: -# friendly_name: Kitchen Siren Switch 1 -# switch.kitchen_siren_switch_2: -# friendly_name: Kitchen Siren Switch 2 -# switch.kitchen_siren_switch_3: -# friendly_name: Kitchen Siren Switch 3 -# switch.kitchen_siren_switch_4: -# friendly_name: Kitchen Siren Switch 4 -# switch.kitchen_siren_switch_5: -# friendly_name: Kitchen Siren Switch 5 -# switch.wallmote_switch: -# friendly_name: Wallmote Switch - -# zwave: -# usb_path: /dev/ttyACM0 -# network_key: !secret zwave_network_key - -# ############################################################################### -# # _ _ _ -# # /\ | | | | (_) -# # / \ _ _| |_ ___ _ __ ___ __ _| |_ _ ___ _ __ ___ -# # / /\ \| | | | __/ _ \| '_ ` _ \ / _` | __| |/ _ \| '_ \/ __| -# # / ____ \ |_| | || (_) | | | | | | (_| | |_| | (_) | | | \__ \ -# # /_/ \_\__,_|\__\___/|_| |_| |_|\__,_|\__|_|\___/|_| |_|___/ -# # -# ############################################################################### -# automation: -# - alias: WallMote Button 1 Pressed -# trigger: -# - platform: event -# event_type: zwave.scene_activated -# event_data: -# entity_id: zwave.wallmote -# scene_id: 1 -# action: -# - service: light.toggle -# entity_id: light.master_bedroom_1 -# - service: light.toggle -# entity_id: light.master_bedroom_2 - -# - alias: WallMote Button 2 Pressed -# trigger: -# - platform: event -# event_type: zwave.scene_activated -# event_data: -# entity_id: zwave.wallmote -# scene_id: 2 -# action: -# - service: homeassistant.turn_off -# entity_id: group.upstairs_lights - -# - alias: WallMote Button 3 Pressed -# trigger: -# - platform: event -# event_type: zwave.scene_activated -# event_data: -# entity_id: zwave.wallmote -# scene_id: 3 -# action: -# - service: climate.set_away_mode -# data_template: -# entity_id: climate.dining_room -# away_mode: "false" - -# - alias: WallMote Button 4 Pressed -# trigger: -# - platform: event -# event_type: zwave.scene_activated -# event_data: -# entity_id: zwave.wallmote -# scene_id: 4 -# action: -# - service: climate.set_away_mode -# data_template: -# entity_id: climate.dining_room -# away_mode: "true" diff --git a/readme.md b/readme.md index f7d4c04..75073f5 100644 --- a/readme.md +++ b/readme.md @@ -1,301 +1,3 @@ ## skalavala's Home Automation/Smart Home skalavala's Home Automation - - diff --git a/secrets.example b/secrets.example index 1a6f255..c099bfa 100644 --- a/secrets.example +++ b/secrets.example @@ -103,10 +103,6 @@ google_maps_geocoding_api: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx #Ecobee Credentials ecobee_api_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -# Life 360 Credentials -life360_username: xxxx.xxxx@xxxx.com -life360_password: xxxxxxxxxxxxxxxxxxxx - # Google Calendar google_client_id: xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com google_client_secret: xxxxxxxxxxxxxxxxxxxxxxxx diff --git a/templates/away_status.yaml b/templates/away_status.yaml index dc7e602..ea9c419 100644 --- a/templates/away_status.yaml +++ b/templates/away_status.yaml @@ -39,7 +39,8 @@ {%- endmacro -%} {%- macro alarm_status() -%} - Your home is {{ "SECURED!" if states('alarm_control_panel.home') == "armed_away" or states('alarm_control_panel.home') == "armed_home" else "UNSECURED!" }} + Your home is {{ "SECURED!" if states('alarm_control_panel.home') == "armed_away" or states('alarm_control_panel.home') == "armed_home" else "UNSECURED!" -}} + . Your Home Away Status is set to {{ states('input_boolean.home_mode_away') |upper }} {%- endmacro -%} {%- macro single_car_garage_door_status() -%} @@ -79,9 +80,9 @@ {%- macro light_switch_status() -%} {% for item in states if item.domain =="light" or item.domain == "switch" -%} - {%- if item.state == "on" -%} + {%- if item.state == "on" and not item.entity_id.endswith('led') and not item.attributes.friendly_name.endswith('LED') -%} {%- set friendly_name = item.attributes.friendly_name -%} - {{ friendly_name }} {{ 'are' if plural(friendly_name) == "true" else 'is' }} ON. + {{ item.domain }} {{ friendly_name }} {{ 'are' if plural(friendly_name) == "true" else 'is' }} ON. {% endif %} {%- endfor -%} {%- endmacro -%} diff --git a/templates/goodnight.yaml b/templates/goodnight.yaml index 2b68515..10c16d6 100644 --- a/templates/goodnight.yaml +++ b/templates/goodnight.yaml @@ -22,11 +22,11 @@ "switch.basement_right", "switch.frontyard_light", "switch.garage", - "switch.guest_bedroom", - "switch.prayer_room", - "switch.kids_bed_accent", - "switch.kids_bedroom", - "switch.kitchen", + "switch.srinika_bedroom", + "switch.guest_room", + "switch.hasika_bed_accent", + "switch.hasika_bedroom", + "switch.kitchen_switch", "switch.office_room", "switch.backyard_light"] %} {%- for item in lights_switches -%} diff --git a/templates/home_status.yaml b/templates/home_status.yaml index e7bef4f..cf7bbeb 100644 --- a/templates/home_status.yaml +++ b/templates/home_status.yaml @@ -164,7 +164,7 @@ {# Drone Flying Weather #} {%- macro drone_weather() -%} {% if states('binary_sensor.good_weather_to_fly_drones')| lower == "on" and - states('device_tracker.life360_suresh') == "home" and + states('device_tracker.suresh') == "home" and states('sun.sun') == "above_horizon" %} It is now a great weather to fly drone outside. {% endif %} diff --git a/ui-lovelace.yaml b/ui-lovelace.yaml index e87810e..1c80b0e 100644 --- a/ui-lovelace.yaml +++ b/ui-lovelace.yaml @@ -1,27 +1,15 @@ -# This code is auto-generated using my Jinja lovelace migration script -# visit: https://github.com/skalavala/mysmarthome/blob/master/jinja_helpers/jinja_lovelace.md -# Or visit https://sharethelove.io/tools/jinja-magic-scripts -# -# I use custom:button card, for two button, credits to https://github.com/kuuji/button-card -# title: Kalavala's Home -# resources: -# - url: /local/button-card.js -# type: module views: - !include lovelace/00_myhome_view.yaml - - !include lovelace/15_3d_printer.yaml - !include lovelace/01_lights_view.yaml - !include lovelace/02_climate_view.yaml - !include lovelace/03_camera_view.yaml - !include lovelace/04_trash_view.yaml - !include lovelace/05_tensorflow_view.yaml - - !include lovelace/06_tesla_view.yaml - !include lovelace/07_system_view.yaml - !include lovelace/08_multimedia_view.yaml - !include lovelace/09_settings_view.yaml - - !include lovelace/10_raspberrypi_view.yaml - !include lovelace/11_scripts_view.yaml - !include lovelace/12_automations_view.yaml - - !include lovelace/13_qnap_view.yaml + - !include lovelace/13_qnap_view.yaml \ No newline at end of file diff --git a/wb_client.py b/wb_client.py deleted file mode 100644 index 7620e12..0000000 --- a/wb_client.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/python - -import sys -import socket - -UDP_SERVER_HOST = "192.168.xxx.xxx" -UDP_SERVER_PORT = 7090 - -def print_usage(): - print("This program requires arguments to be passed. Possible arguments are: ") - print("['i', 'failsafe', 'curr', 'report 1', 'ena 1']") - print("\nUsage: python " + sys.argv[0] + " i\n") - exit() - -args = len(sys.argv) -if args == 1: - print_usage() - -serverAddressPort = (UDP_SERVER_HOST, UDP_SERVER_PORT) -UDPClientSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - -bytesSent = UDPClientSock.sendto(str.encode(sys.argv[1]), serverAddressPort) - -print ("Successfully sent '{}' ({} bytes) to the server!".format(sys.argv[1], str(bytesSent))) diff --git a/wb_server.py b/wb_server.py deleted file mode 100644 index 44d4274..0000000 --- a/wb_server.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/python - -import socket -import asyncore -import paho.mqtt.client as mqtt -import paho.mqtt.publish as publish - -MQTT_SERVER_HOST = "192.168.xxx.xxx" -MQTT_SERVER_PORT = 1883 -MQTT_USERNAME = "username" -MQTT_PASSWORD = "letmein" -MQTT_TOPIC = "/wallbox/data" - -UDP_SERVER_PORT = 7090 -DEFAULT_RECV_BYTES = 2048 - -client = mqtt.Client("udp-server") -#client.tls_set('/home/pi/certs/ca-certificates.crt') -client.username_pw_set(MQTT_USERNAME, MQTT_PASSWORD) -client.connect(MQTT_SERVER_HOST, MQTT_SERVER_PORT) -client.loop_start() - -class AsyncoreServerUDP(asyncore.dispatcher): - def __init__(self): - asyncore.dispatcher.__init__(self) - - # Bind to port 7090 on all interfaces - self.create_socket(socket.AF_INET, socket.SOCK_DGRAM) - self.bind(('', UDP_SERVER_PORT)) - - # Even though UDP is connectionless this is called when it binds to a port - def handle_connect(self): - print("Server Started...") - - # This is called everytime there is something to read - def handle_read(self): - data, addr = self.recvfrom(DEFAULT_RECV_BYTES) - client.publish(MQTT_TOPIC, data, retain=False) - print(str(addr) + " >> " + data) - - - # This is called all the time and causes errors if you leave it out. - def handle_write(self): - pass - -AsyncoreServerUDP() -asyncore.loop() - -print("continue") diff --git a/zwcfg_0xd89c4f0c.xml b/zwcfg_0xd89c4f0c.xml deleted file mode 100644 index ce7a771..0000000 --- a/zwcfg_0xd89c4f0c.xml +++ /dev/null @@ -1,1615 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Enable/Disable Basic Sets of 0x00 on a fault restore to nodes in Group 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Enable/Disable waking up for 10 minutes when re-power on (battery mode) the MultiSensor - - - - - Duration that the motion sensor must observe no motion before it will return to the no-motion state. If value greater than 255, effective value is rounded up to the nearest minute (255 -> 255 seconds, 256 -> 300 seconds) - - - Enable Motion Sensor, (1 minimum, 5 maximum sensitivity level) - - - - - - - - - Which commands to send when PIR motion sensor triggered OZW Ideal Value is Binary Sensor Report - - - - - Set the timeout of awake after the Wake Up CC is sent out. Available rang: 8 to 255 seconds. - - - Report the current power mode and the product state for battery power mode - - - - - - - Configure low battery value Value=10 to 50. - - - Enable/disable the selective reporting only when measurements reach a certain threshold or percentage set in the threshold settings. This is used to reduce network traffic. - - - - - Threshold change in temperature to induce an automatic report. Note: 1. The unit is Fahrenheit for US version, Celsius for EU/AU version. 2. The value contains one decimal point. E.g. if the value is set to 20, the threshold value = 2.0 C (EU/AU) or 2.0 F (US). When the temperature has changed by 2.0 (of the appropriate unit), a temperature report will be sent. - - - Threshold change in humidity to induce an automatic report. Note: 1. The unit is %. 2. The default value is 10, which means that a 10% change in humidity will trigger a report. - - - Threshold change in luminance to induce an automatic report. - - - Threshold change in battery level to induce an automatic report. Note: 1. The unit is %. 2. The default value is 10, which means that a 10% change in battery will trigger a report. - - - Threshold change in ultraviolet to induce an automatic report. - - - Enable/disable to send the alarm report of low temperature(Less than 15 Degress C) - - - - - Enable/disable to send a report when the measurement is more than the upper limit value or less than the lower limit value. Bit mask = 0, disable. Bit mask = 1, enable. Bit 0 = temperature. Bit 1 = humidity. Bit 2 = luminance. Bit 3 = ultraviolet. The above bit masks are used to enable/disable to send out a report when the measurement is less than the lower limit value. The below bit masks are used to enable/disable to send out a report when the measurement is more than the upper limit value. Bit 4 = temperature. Bit 5 = humidity. Bit 6 = luminance. Bit 7 = ultraviolet. Note: If USB power, the Sensor will check the limit every 10 seconds. If battery power, the Sensor will check the limit when it is waken up. - - - When the measurement is more than this upper limit, which will trigger to sent out a sensor report. High byte is the upper limit value. Low byte is the unit (0x01=Celsius, 0x02=Fahrenheit). 1. When unit is Celsius. Upper limit range: -40.0 to 100.0 C (0xFE70 to 0x03E8). E.g. The default upper limit of EU/AU version is 28.0 C (0x0118), when the measurement is more than 28.0C, it will be triggered to send out a temperature sensor report. 2. When unit is Fahrenheit. Upper limit range: -40.0 to 212.0 F (0xFE70 to 0x0848). E.g. The default upper limit of US version is 82.4F (0X0338), when the measurement is more than 82.4F, it will be triggered to send out a temperature sensor report. - - - When the measurement is less than this lower limit, which will trigger to sent out a sensor report. High byte is the lower limit value. Low byte is the unit (0x01=Celsius, 0x02=Fahrenheit). 1. When unit is Celsius. Lower limit range: -40.0 to 100.0 C (0xFE70 to 0x03E8). E.g. The default lower limit of EU/AU version is 0 C (0x0000), when the measurement is less than 0C, it will be triggered to send out a temperature sensor report. 2. When unit is Fahrenheit. Upper limit range: -40.0 to 212.0 F (0xFE70 to 0x0848). E.g. The default lower limit of US version is 32.0F (0x0140), when the measurement is less than 32.0F, it will be triggered to send out a temperature sensor report. - - - When the measurement is more than this upper limit, which will trigger to sent out a sensor report. Upper limit range: 0 to 100%. E.g. The default upper limit is 60%, when the measurement is more than 60%, it will be triggered to send out a humidity sensor report. - - - When the measurement is less than this lower limit, which will trigger to sent out a sensor report. Lower limit range: 0 to 100%. E.g. The default lower limit is 50%, when the measurement is less than 50%, it will be triggered to send out a humidity sensor report. - - - When the measurement is more than this upper limit, which will trigger to sent out a sensor report. Upper limit range: 0 to 30000 Lux. E.g. The default upper limit is 1000Lux, when the measurement is more than 1000Lux, it will be triggered to send out a Lighting sensor report. - - - When the measurement is less than this lower limit, which will trigger to sent out a sensor report. Lower limit range: 0 to 30000 Lux. E.g. The default lower limit is 100Lux, when the measurement is less than 100Lux, it will be triggered to send out a Lighting sensor report. - - - When the measurement is more than this upper limit, which will trigger to sent out a sensor report. Upper limit range: 1 to 11. E.g. The default upper limit is 8, when the measurement is more than 8, it will be triggered to send out a ultraviolet sensor report. - - - When the measurement is less than this upper limit, which will trigger to sent out a sensor report. Lower limit range: 1 to 11. E.g. The default lower limit is 4, when the measurement is less than 8, it will be triggered to send out a ultraviolet sensor report. - - - Note: 1. When the current measurement lower or equal (Upper limit - Recover limit), the upper limit report is enabled and then it would send out a sensor report when the next measurement is more than the upper limit. After that, the upper limit report would be disabled again until the measurement lower or equal (Upper limit - Recover limit). 2. When the current measurement greater or equal (Lower limit + Recover limit), the lower limit report is enabled and then it would send out a sensor report when the next measurement is less than the lower limit. After that, the lower limit report would be disabled again until the measurement greater or equal (Lower limit + Recover limit). 3. High byte is the recover limit value. Low byte is the unit (0x01=Celsius, 0x02=Fahrenheit). 4. Recover limit range: 1.0 to 25.5 C/ F (0x0101 to 0xFF01 or 0x0102 to 0xFF02). E.g. The default recover limit value is 2.0 C/F (0x1401/0x1402), when the measurement is less than (Upper limit - 2), the upper limit report would be enabled one time or when the measurement is more than (Lower limit + 2), the lower limit report would be enabled one time. - - - Note: 1. When the current measurement lower or equal (Upper limit - Recover limit), the upper limit report is enabled and then it would send out a sensor report when the next measurement is more than the upper limit. After that the upper limit report would be disabled again until the measurement lower or equal (Upper limit - Recover limit). 2. When the current measurement greater or equal (Lower limit + Recover limit), the lower limit report is enabled and then it would send out a sensor report when the next measurement is less than the lower limit. After that the lower limit report would be disabled again until the measurement greater or equal(Lower limit + Recover limit). 3. Recover limit range: 1 to 50% (0x01 to 0x32). E.g. The default recover limit value is 5%, when the measurement is less than (Upper limit - 5), the upper limit report would be enabled one time or when the measurement is more than (Lower limit + 5), the lower limit report would be enabled one time. - - - Note: 1. When the current measurement lower or equal (Upper limit - Recover limit), the upper limit report is enabled and then it would send out a sensor report when the next measurement is more than the upper limit. After that the upper limit report would be disabled again until the measurement lower or equal (Upper limit - Recover limit). 2. When the current measurement greater or equal (Lower limit + Recover limit), the lower limit report is enabled and then it would send out a sensor report when the next measurement is less than the lower limit. After that the lower limit report would be disabled again until the measurement greater or equal (Lower limit + Recover limit). 3. Unit = 10*Recover limit (Lux) 4. Recover limit range: 10 to 2550Lux (0x01 to 0xFF). E.g. The default recover limit value is 100 Lux, when the measurement is less than (Upper limit - 100), the upper limit report would be enabled one time or when the measurement is more than (Lower limit + 100), the lower limit report would be enabled one time. - - - Note: 1. When the current measurement lower or equal (Upper limit - Recover limit), the upper limit report is enabled and then it would send out a sensor report when the next measurement is more than the upper limit. After that the upper limit report would be disabled again until the measurement lower or equal (Upper limit - Recover limit). 2. When the current measurement greater or equal (Lower limit + Recover limit), the lower limit report is enabled and then it would send out a sensor report when the next measurement is less than the lower limit. After that the lower limit report would be disabled again until the measurement greater or equal(Lower limit + Recover limit). 3. Recover limit range: 1 to 50% (0x01 to 0x32). E.g. The default recover limit value is 5%, when the measurement is less than (Upper limit - 5), the upper limit report would be enabled one time or when the measurement is more than (Lower limit + 5), the lower limit report would be enabled one time. - - - Get the out-of-limit state of the Sensors. Bit mask = 0, within the limit. Bit mask = 1, out of the limit. Bit 0 = temperature. Bit 1 = humidity. Bit 2 = luminance. Bit 3 = ultraviolet. The above bit masks are used to indicate whether the current measurements of the Sensors are out of the lower limit. The below bit masks are used to indicate whether the current measurements of the Sensors are out of the upper limit. Bit 4 = temperature. Bit 5 = humidity. Bit 6 = luminance. Bit 7 = ultraviolet. - - - Default value: Celsius for EU/AU version, Fahrenheit for US version. - - - - - Enable/disable the LED blinking for motion, wakeup, and sensor report. - - - - - - Reset The Reporting Group Configuration (101 to 103) to default - - - Which reports need to send automatically in timing intervals for group 1. Bitmask: 10000000 - 128 - Luminance 01000000 - 64 - Humidity 00100000 - 32 - Temperature 00010000 - 16 - Ultraviolet 00000001 - 1 - Battery 10100000 - 160 - Luminance and Temperature (32+128) 11110001 - 241 - All (1+16+32+64+128) - - - Which reports need to send automatically in timing intervals for group 2. Bitmask: 10000000 - 128 - Luminance 01000000 - 64 - Humidity 00100000 - 32 - Temperature 00010000 - 16 - Ultraviolet 00000001 - 1 - Battery 10100000 - 160 - Luminance and Temperature (32+128) 11110001 - 241 - All (1+16+32+64+128) - - - Which reports need to send automatically in timing intervals for group 3. Bitmask: 10000000 - 128 - Luminance 01000000 - 64 - Humidity 00100000 - 32 - Temperature 00010000 - 16 - Ultraviolet 00000001 - 1 - Battery 10100000 - 160 - Luminance and Temperature (32+128) 11110001 - 241 - All (1+16+32+64+128) - - - Reset The Reporting Group Interval Configuration (111 to 113) to default - - - The interval for sending reports for group 1. The effective behavior of this setting depends on the device's power source: - If the device is on USB power, it will send the reports at the configured interval; set it to something low (~15-60 seconds) to get frequent updates from a powered device. - If the device is on battery, the sensor will never report in more often than its configured wake interval, regardless of what this setting is configured to; setting this to 3601 when the wake interval is 3600 would make this group report in every 7200 seconds. 240 seconds is the minimum wake interval, but will quickly use battery. - - - The interval for sending reports for group 2. The effective behavior of this setting depends on the device's power source: - If the device is on USB power, it will send the reports at the configured interval; set it to something low (~15-60 seconds) to get frequent updates from a powered device. - If the device is on battery, the sensor will never report in more often than its configured wake interval, regardless of what this setting is configured to; setting this to 3601 when the wake interval is 3600 would make this group report in every 7200 seconds. 240 seconds is the minimum wake interval, but will quickly use battery. - - - The interval for sending reports for group 3. The effective behavior of this setting depends on the device's power source: - If the device is on USB power, it will send the reports at the configured interval; set it to something low (~15-60 seconds) to get frequent updates from a powered device. - If the device is on battery, the sensor will never report in more often than its configured wake interval, regardless of what this setting is configured to; setting this to 3601 when the wake interval is 3600 would make this group report in every 7200 seconds. 240 seconds is the minimum wake interval, but will quickly use battery. - - - Temperature calibration (the available value range is [-128,127] or [-12.8C,12.7C]). Note: 1. High byte is the calibration value. Low byte is the unit (0x01=Celsius,0x02=Fahrenheit) 2. The calibration value (high byte) contains one decimal point. E.g. if the value is set to 20 (0x1401), the calibration value is 2.0C (EU/AU version) or if the value is set to 20 (0x1402), the calibration value is 2.0F (US version) 3. The calibration value (high byte) = standard value - measure value. E.g. If measure value =25.3C and the standard value = 23.2C, so the calibration value= 23.2C - 25.3C= -2.1C (0xEB). If the measure value =30.1C and the standard value = 33.2C, so the calibration value= 33.2C - 30.1C=3.1C (0x1F). Default value: 1 for EU/AU version, 2 for US version. - - - The calibration value = standard value - measure value. (the available value range is [-50, 50]). If measure value =80RH and the standard value = 75RH, so the calibration value= 75RH-80RH = -5RH (0xFB). If the measure value =85RH and the standard value = 90RH, so the calibration value= 90RH-85RH = 5RH (0x05). - - - The calibration value = standard value - measure value. (the available value range is [-1000, 1000]). If measure value =800Lux and the standard value = 750Lux, so the calibration value= 750-800 = -50 (0xFFCE). If the measure value =850Lux and the standard value = 900Lux, so the calibration value= 900-850 = 50 (0x0032). - - - The calibration value = standard value measure value. (the available value range is [-10, 10]). If measure value =9 and the standard value = 8, so the calibration value= 8-9 = -1 (0xFE). If the measure value =7 and the standard value = 9, so the calibration value= 9-7 = 2 (0x02). - - - Enable/disable Lock Configuration - - - - - Reset to factory defaults - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Load will be closed when the Current overruns (US 15.5A, Others 16.2) for more than 2 minutes - - - - - Configure the output load status after re-power on. - - - - - - Configure the RGB Led Color for Testing - - - - - - - Defines the automated status notification of an associated device when status changes - - - - - - - - - - - Configure the RGB Value when in Night Light Mode. Byte 1: Red Color Byte 2: Green Color Byte 3: Blue Color - - - Configure the brightness level of RGB LED (0%-100%) when it is in Energy Mode/momentary indicate mode. Byte 1: Red Color Byte 2: Green Color Byte 3: Blue Color - - - Enable/disable Wattage threshold and percent. - - - The value represents the minimum change in wattage for a Report to be sent (default 25 W) - - - The value represents the minimum percentage change in wattage for a Report to be sent (Default 5) - - - Set report types for groups 1, 2 and 3 to default. - - - Defines the type of report sent for reporting group 1. 2 is multisensor report. 4 is meter report for watts. 8 is meter report for kilowatts. Value 1 (msb) Reserved Value 2 Reserved Value 3 Reserved Value 4 (lsb) bits 7-4 reserved bit 3 KWH bit 2 Watt bit 1 Current bit 0 Voltage - - - Defines the type of report sent for reporting group 1. 2 is multisensor report. 4 is meter report for watts. 8 is meter report for kilowatts. Value 1 (msb) Reserved Value 2 Reserved Value 3 Reserved Value 4 (lsb) bits 7-4 reserved bit 3 KWH bit 2 Watt bit 1 Current bit 0 Voltage - - - Defines the type of report sent for reporting group 1. 2 is multisensor report. 4 is meter report for watts. 8 is meter report for kilowatts. Value 1 (msb) Reserved Value 2 Reserved Value 3 Reserved Value 4 (lsb) bits 7-4 reserved bit 3 KWH bit 2 Watt bit 1 Current bit 0 Voltage - - - Set time interval for sending reports for groups 1, 2 and 3 to default. - - - Defines the time interval when the defined report for group 1 is sent. - - - Defines the time interval when the defined report for group 2 is sent. - - - Defines the time interval when the defined report for group 3 is sent. - - - Partner ID - - - - - Enable/disable Configuration Locked - - - - - Device tag. - - - Reset to the default configuration. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Configures the sensor to send or not send Basic Set commands of 0x00 to nodes in Association group 2 turning the devices off when the sensor is in a restored state (i.e. motion not detected). By default the sensor does NOT send Basic Set commands of 0x00. - - - - - Configures the sensor to either to send or not to send Sensor Binary Report commands to Association Group 1 when the sensor is faulted and restored. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Set the default status of the LED when the Range Extender relays Z-Wave message. - - - - - Partner ID - - - - - Enable/disable Configuration Locked - - - - - Device tag. - - - Reset to factory defaults - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Enable/Disable waking up for 10 minutes when re-power on (battery mode) the MultiSensor - - - - - Duration that the motion sensor must observe no motion before it will return to the no-motion state. If value greater than 255, effective value is rounded up to the nearest minute (255 -> 255 seconds, 256 -> 300 seconds) - - - Enable Motion Sensor, (1 minimum, 5 maximum sensitivity level) - - - - - - - - - Which commands to send when PIR motion sensor triggered OZW Ideal Value is Binary Sensor Report - - - - - Set the timeout of awake after the Wake Up CC is sent out. Available rang: 8 to 255 seconds. - - - Report the current power mode and the product state for battery power mode - - - - - - - Configure low battery value Value=10 to 50. - - - Enable/disable the selective reporting only when measurements reach a certain threshold or percentage set in the threshold settings. This is used to reduce network traffic. - - - - - Threshold change in temperature to induce an automatic report. Note: 1. The unit is Fahrenheit for US version, Celsius for EU/AU version. 2. The value contains one decimal point. E.g. if the value is set to 20, the threshold value = 2.0 C (EU/AU) or 2.0 F (US). When the temperature has changed by 2.0 (of the appropriate unit), a temperature report will be sent. - - - Threshold change in humidity to induce an automatic report. Note: 1. The unit is %. 2. The default value is 10, which means that a 10% change in humidity will trigger a report. - - - Threshold change in luminance to induce an automatic report. - - - Threshold change in battery level to induce an automatic report. Note: 1. The unit is %. 2. The default value is 10, which means that a 10% change in battery will trigger a report. - - - Threshold change in ultraviolet to induce an automatic report. - - - Enable/disable to send the alarm report of low temperature(Less than 15 Degress C) - - - - - Enable/disable to send a report when the measurement is more than the upper limit value or less than the lower limit value. Bit mask = 0, disable. Bit mask = 1, enable. Bit 0 = temperature. Bit 1 = humidity. Bit 2 = luminance. Bit 3 = ultraviolet. The above bit masks are used to enable/disable to send out a report when the measurement is less than the lower limit value. The below bit masks are used to enable/disable to send out a report when the measurement is more than the upper limit value. Bit 4 = temperature. Bit 5 = humidity. Bit 6 = luminance. Bit 7 = ultraviolet. Note: If USB power, the Sensor will check the limit every 10 seconds. If battery power, the Sensor will check the limit when it is waken up. - - - When the measurement is more than this upper limit, which will trigger to sent out a sensor report. High byte is the upper limit value. Low byte is the unit (0x01=Celsius, 0x02=Fahrenheit). 1. When unit is Celsius. Upper limit range: -40.0 to 100.0 C (0xFE70 to 0x03E8). E.g. The default upper limit of EU/AU version is 28.0 C (0x0118), when the measurement is more than 28.0C, it will be triggered to send out a temperature sensor report. 2. When unit is Fahrenheit. Upper limit range: -40.0 to 212.0 F (0xFE70 to 0x0848). E.g. The default upper limit of US version is 82.4F (0X0338), when the measurement is more than 82.4F, it will be triggered to send out a temperature sensor report. - - - When the measurement is less than this lower limit, which will trigger to sent out a sensor report. High byte is the lower limit value. Low byte is the unit (0x01=Celsius, 0x02=Fahrenheit). 1. When unit is Celsius. Lower limit range: -40.0 to 100.0 C (0xFE70 to 0x03E8). E.g. The default lower limit of EU/AU version is 0 C (0x0000), when the measurement is less than 0C, it will be triggered to send out a temperature sensor report. 2. When unit is Fahrenheit. Upper limit range: -40.0 to 212.0 F (0xFE70 to 0x0848). E.g. The default lower limit of US version is 32.0F (0x0140), when the measurement is less than 32.0F, it will be triggered to send out a temperature sensor report. - - - When the measurement is more than this upper limit, which will trigger to sent out a sensor report. Upper limit range: 0 to 100%. E.g. The default upper limit is 60%, when the measurement is more than 60%, it will be triggered to send out a humidity sensor report. - - - When the measurement is less than this lower limit, which will trigger to sent out a sensor report. Lower limit range: 0 to 100%. E.g. The default lower limit is 50%, when the measurement is less than 50%, it will be triggered to send out a humidity sensor report. - - - When the measurement is more than this upper limit, which will trigger to sent out a sensor report. Upper limit range: 0 to 30000 Lux. E.g. The default upper limit is 1000Lux, when the measurement is more than 1000Lux, it will be triggered to send out a Lighting sensor report. - - - When the measurement is less than this lower limit, which will trigger to sent out a sensor report. Lower limit range: 0 to 30000 Lux. E.g. The default lower limit is 100Lux, when the measurement is less than 100Lux, it will be triggered to send out a Lighting sensor report. - - - When the measurement is more than this upper limit, which will trigger to sent out a sensor report. Upper limit range: 1 to 11. E.g. The default upper limit is 8, when the measurement is more than 8, it will be triggered to send out a ultraviolet sensor report. - - - When the measurement is less than this upper limit, which will trigger to sent out a sensor report. Lower limit range: 1 to 11. E.g. The default lower limit is 4, when the measurement is less than 8, it will be triggered to send out a ultraviolet sensor report. - - - Note: 1. When the current measurement lower or equal (Upper limit - Recover limit), the upper limit report is enabled and then it would send out a sensor report when the next measurement is more than the upper limit. After that, the upper limit report would be disabled again until the measurement lower or equal (Upper limit - Recover limit). 2. When the current measurement greater or equal (Lower limit + Recover limit), the lower limit report is enabled and then it would send out a sensor report when the next measurement is less than the lower limit. After that, the lower limit report would be disabled again until the measurement greater or equal (Lower limit + Recover limit). 3. High byte is the recover limit value. Low byte is the unit (0x01=Celsius, 0x02=Fahrenheit). 4. Recover limit range: 1.0 to 25.5 C/ F (0x0101 to 0xFF01 or 0x0102 to 0xFF02). E.g. The default recover limit value is 2.0 C/F (0x1401/0x1402), when the measurement is less than (Upper limit - 2), the upper limit report would be enabled one time or when the measurement is more than (Lower limit + 2), the lower limit report would be enabled one time. - - - Note: 1. When the current measurement lower or equal (Upper limit - Recover limit), the upper limit report is enabled and then it would send out a sensor report when the next measurement is more than the upper limit. After that the upper limit report would be disabled again until the measurement lower or equal (Upper limit - Recover limit). 2. When the current measurement greater or equal (Lower limit + Recover limit), the lower limit report is enabled and then it would send out a sensor report when the next measurement is less than the lower limit. After that the lower limit report would be disabled again until the measurement greater or equal(Lower limit + Recover limit). 3. Recover limit range: 1 to 50% (0x01 to 0x32). E.g. The default recover limit value is 5%, when the measurement is less than (Upper limit - 5), the upper limit report would be enabled one time or when the measurement is more than (Lower limit + 5), the lower limit report would be enabled one time. - - - Note: 1. When the current measurement lower or equal (Upper limit - Recover limit), the upper limit report is enabled and then it would send out a sensor report when the next measurement is more than the upper limit. After that the upper limit report would be disabled again until the measurement lower or equal (Upper limit - Recover limit). 2. When the current measurement greater or equal (Lower limit + Recover limit), the lower limit report is enabled and then it would send out a sensor report when the next measurement is less than the lower limit. After that the lower limit report would be disabled again until the measurement greater or equal (Lower limit + Recover limit). 3. Unit = 10*Recover limit (Lux) 4. Recover limit range: 10 to 2550Lux (0x01 to 0xFF). E.g. The default recover limit value is 100 Lux, when the measurement is less than (Upper limit - 100), the upper limit report would be enabled one time or when the measurement is more than (Lower limit + 100), the lower limit report would be enabled one time. - - - Note: 1. When the current measurement lower or equal (Upper limit - Recover limit), the upper limit report is enabled and then it would send out a sensor report when the next measurement is more than the upper limit. After that the upper limit report would be disabled again until the measurement lower or equal (Upper limit - Recover limit). 2. When the current measurement greater or equal (Lower limit + Recover limit), the lower limit report is enabled and then it would send out a sensor report when the next measurement is less than the lower limit. After that the lower limit report would be disabled again until the measurement greater or equal(Lower limit + Recover limit). 3. Recover limit range: 1 to 50% (0x01 to 0x32). E.g. The default recover limit value is 5%, when the measurement is less than (Upper limit - 5), the upper limit report would be enabled one time or when the measurement is more than (Lower limit + 5), the lower limit report would be enabled one time. - - - Get the out-of-limit state of the Sensors. Bit mask = 0, within the limit. Bit mask = 1, out of the limit. Bit 0 = temperature. Bit 1 = humidity. Bit 2 = luminance. Bit 3 = ultraviolet. The above bit masks are used to indicate whether the current measurements of the Sensors are out of the lower limit. The below bit masks are used to indicate whether the current measurements of the Sensors are out of the upper limit. Bit 4 = temperature. Bit 5 = humidity. Bit 6 = luminance. Bit 7 = ultraviolet. - - - Default value: Celsius for EU/AU version, Fahrenheit for US version. - - - - - Enable/disable the LED blinking for motion, wakeup, and sensor report. - - - - - - Reset The Reporting Group Configuration (101 to 103) to default - - - Which reports need to send automatically in timing intervals for group 1. Bitmask: 10000000 - 128 - Luminance 01000000 - 64 - Humidity 00100000 - 32 - Temperature 00010000 - 16 - Ultraviolet 00000001 - 1 - Battery 10100000 - 160 - Luminance and Temperature (32+128) 11110001 - 241 - All (1+16+32+64+128) - - - Which reports need to send automatically in timing intervals for group 2. Bitmask: 10000000 - 128 - Luminance 01000000 - 64 - Humidity 00100000 - 32 - Temperature 00010000 - 16 - Ultraviolet 00000001 - 1 - Battery 10100000 - 160 - Luminance and Temperature (32+128) 11110001 - 241 - All (1+16+32+64+128) - - - Which reports need to send automatically in timing intervals for group 3. Bitmask: 10000000 - 128 - Luminance 01000000 - 64 - Humidity 00100000 - 32 - Temperature 00010000 - 16 - Ultraviolet 00000001 - 1 - Battery 10100000 - 160 - Luminance and Temperature (32+128) 11110001 - 241 - All (1+16+32+64+128) - - - Reset The Reporting Group Interval Configuration (111 to 113) to default - - - The interval for sending reports for group 1. The effective behavior of this setting depends on the device's power source: - If the device is on USB power, it will send the reports at the configured interval; set it to something low (~15-60 seconds) to get frequent updates from a powered device. - If the device is on battery, the sensor will never report in more often than its configured wake interval, regardless of what this setting is configured to; setting this to 3601 when the wake interval is 3600 would make this group report in every 7200 seconds. 240 seconds is the minimum wake interval, but will quickly use battery. - - - The interval for sending reports for group 2. The effective behavior of this setting depends on the device's power source: - If the device is on USB power, it will send the reports at the configured interval; set it to something low (~15-60 seconds) to get frequent updates from a powered device. - If the device is on battery, the sensor will never report in more often than its configured wake interval, regardless of what this setting is configured to; setting this to 3601 when the wake interval is 3600 would make this group report in every 7200 seconds. 240 seconds is the minimum wake interval, but will quickly use battery. - - - The interval for sending reports for group 3. The effective behavior of this setting depends on the device's power source: - If the device is on USB power, it will send the reports at the configured interval; set it to something low (~15-60 seconds) to get frequent updates from a powered device. - If the device is on battery, the sensor will never report in more often than its configured wake interval, regardless of what this setting is configured to; setting this to 3601 when the wake interval is 3600 would make this group report in every 7200 seconds. 240 seconds is the minimum wake interval, but will quickly use battery. - - - Temperature calibration (the available value range is [-128,127] or [-12.8C,12.7C]). Note: 1. High byte is the calibration value. Low byte is the unit (0x01=Celsius,0x02=Fahrenheit) 2. The calibration value (high byte) contains one decimal point. E.g. if the value is set to 20 (0x1401), the calibration value is 2.0C (EU/AU version) or if the value is set to 20 (0x1402), the calibration value is 2.0F (US version) 3. The calibration value (high byte) = standard value - measure value. E.g. If measure value =25.3C and the standard value = 23.2C, so the calibration value= 23.2C - 25.3C= -2.1C (0xEB). If the measure value =30.1C and the standard value = 33.2C, so the calibration value= 33.2C - 30.1C=3.1C (0x1F). Default value: 1 for EU/AU version, 2 for US version. - - - The calibration value = standard value - measure value. (the available value range is [-50, 50]). If measure value =80RH and the standard value = 75RH, so the calibration value= 75RH-80RH = -5RH (0xFB). If the measure value =85RH and the standard value = 90RH, so the calibration value= 90RH-85RH = 5RH (0x05). - - - The calibration value = standard value - measure value. (the available value range is [-1000, 1000]). If measure value =800Lux and the standard value = 750Lux, so the calibration value= 750-800 = -50 (0xFFCE). If the measure value =850Lux and the standard value = 900Lux, so the calibration value= 900-850 = 50 (0x0032). - - - The calibration value = standard value measure value. (the available value range is [-10, 10]). If measure value =9 and the standard value = 8, so the calibration value= 8-9 = -1 (0xFE). If the measure value =7 and the standard value = 9, so the calibration value= 9-7 = 2 (0x02). - - - Enable/disable Lock Configuration - - - - - Reset to factory defaults - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/zwscene.xml b/zwscene.xml deleted file mode 100644 index bdc9dca..0000000 --- a/zwscene.xml +++ /dev/null @@ -1,2 +0,0 @@ - -