minor updates
This commit is contained in:
parent
acb40cdb7a
commit
9a8c586542
|
@ -55,3 +55,8 @@ private/*
|
||||||
apps/__pycache__/*.pyc
|
apps/__pycache__/*.pyc
|
||||||
docker/streamer
|
docker/streamer
|
||||||
docker-compose.yml
|
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
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
blueprint:
|
||||||
|
name: Confirmable Notification
|
||||||
|
description: >-
|
||||||
|
A script that sends an actionable notification with a confirmation before
|
||||||
|
running the specified action.
|
||||||
|
domain: script
|
||||||
|
source_url: https://github.com/home-assistant/core/blob/master/homeassistant/components/script/blueprints/confirmable_notification.yaml
|
||||||
|
input:
|
||||||
|
notify_device:
|
||||||
|
name: Device to notify
|
||||||
|
description: Device needs to run the official Home Assistant app to receive notifications.
|
||||||
|
selector:
|
||||||
|
device:
|
||||||
|
integration: mobile_app
|
||||||
|
title:
|
||||||
|
name: "Title"
|
||||||
|
description: "The title of the button shown in the notification."
|
||||||
|
default: ""
|
||||||
|
selector:
|
||||||
|
text:
|
||||||
|
message:
|
||||||
|
name: "Message"
|
||||||
|
description: "The message body"
|
||||||
|
selector:
|
||||||
|
text:
|
||||||
|
confirm_text:
|
||||||
|
name: "Confirmation Text"
|
||||||
|
description: "Text to show on the confirmation button"
|
||||||
|
default: "Confirm"
|
||||||
|
selector:
|
||||||
|
text:
|
||||||
|
confirm_action:
|
||||||
|
name: "Confirmation Action"
|
||||||
|
description: "Action to run when notification is confirmed"
|
||||||
|
default: []
|
||||||
|
selector:
|
||||||
|
action:
|
||||||
|
dismiss_text:
|
||||||
|
name: "Dismiss Text"
|
||||||
|
description: "Text to show on the dismiss button"
|
||||||
|
default: "Dismiss"
|
||||||
|
selector:
|
||||||
|
text:
|
||||||
|
dismiss_action:
|
||||||
|
name: "Dismiss Action"
|
||||||
|
description: "Action to run when notification is dismissed"
|
||||||
|
default: []
|
||||||
|
selector:
|
||||||
|
action:
|
||||||
|
|
||||||
|
mode: restart
|
||||||
|
|
||||||
|
sequence:
|
||||||
|
- alias: "Send notification"
|
||||||
|
domain: mobile_app
|
||||||
|
type: notify
|
||||||
|
device_id: !input notify_device
|
||||||
|
title: !input title
|
||||||
|
message: !input message
|
||||||
|
data:
|
||||||
|
actions:
|
||||||
|
- action: "CONFIRM"
|
||||||
|
title: !input confirm_text
|
||||||
|
- action: "DISMISS"
|
||||||
|
title: !input dismiss_text
|
||||||
|
- alias: "Awaiting response"
|
||||||
|
wait_for_trigger:
|
||||||
|
- platform: event
|
||||||
|
event_type: mobile_app_notification_action
|
||||||
|
- choose:
|
||||||
|
- conditions: "{{ wait.trigger.event.data.action == 'CONFIRM' }}"
|
||||||
|
sequence: !input confirm_action
|
||||||
|
- conditions: "{{ wait.trigger.event.data.action == 'DISMISS' }}"
|
||||||
|
sequence: !input dismiss_action
|
|
@ -1,161 +0,0 @@
|
||||||
"""
|
|
||||||
@ Author : Suresh Kalavala
|
|
||||||
@ Date : 09/14/2017
|
|
||||||
@ Description : Input Label - A label that holds data
|
|
||||||
|
|
||||||
@ Notes: Copy this file and services.yaml files and place it in your
|
|
||||||
"Home Assistant Config folder\custom_components\" folder
|
|
||||||
|
|
||||||
To use the component, have the following in your .yaml file:
|
|
||||||
The 'value' is optional, by default, it is set to 0
|
|
||||||
|
|
||||||
input_label:
|
|
||||||
some_string1:
|
|
||||||
name: Some String 1
|
|
||||||
icon: mdi:alphabetical
|
|
||||||
|
|
||||||
input_label:
|
|
||||||
name: Some String 2
|
|
||||||
value: 'Hello, Home Assistant!'
|
|
||||||
icon: mdi:alphabetical
|
|
||||||
|
|
||||||
"""
|
|
||||||
"""
|
|
||||||
Component to provide input_label.
|
|
||||||
|
|
||||||
For more details about this component, please contact Suresh Kalavala
|
|
||||||
"""
|
|
||||||
import logging
|
|
||||||
|
|
||||||
import voluptuous as vol
|
|
||||||
|
|
||||||
import homeassistant.helpers.config_validation as cv
|
|
||||||
from homeassistant.const import (ATTR_ENTITY_ID, CONF_ICON, CONF_NAME)
|
|
||||||
from homeassistant.helpers.entity_component import EntityComponent
|
|
||||||
from homeassistant.helpers.restore_state import RestoreEntity
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
DOMAIN = 'input_label'
|
|
||||||
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
|
||||||
|
|
||||||
CONF_INITIAL = 'initial'
|
|
||||||
ATTR_VALUE = "value"
|
|
||||||
DEFAULT_ICON = "mdi:label"
|
|
||||||
|
|
||||||
SERVICE_SETNAME = 'set_name'
|
|
||||||
SERVICE_SETVALUE = 'set_value'
|
|
||||||
SERVICE_SETICON = 'set_icon'
|
|
||||||
|
|
||||||
SERVICE_SCHEMA = vol.Schema({
|
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
|
||||||
vol.Optional(ATTR_VALUE): cv.string,
|
|
||||||
vol.Optional(CONF_NAME): cv.icon,
|
|
||||||
vol.Optional(CONF_ICON): cv.icon,
|
|
||||||
})
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema({
|
|
||||||
DOMAIN: vol.Schema({
|
|
||||||
cv.slug: vol.Any({
|
|
||||||
vol.Optional(CONF_ICON, default=DEFAULT_ICON): cv.icon,
|
|
||||||
vol.Optional(ATTR_VALUE, ''): cv.string,
|
|
||||||
vol.Optional(CONF_NAME): cv.string,
|
|
||||||
}, None)
|
|
||||||
})
|
|
||||||
}, extra=vol.ALLOW_EXTRA)
|
|
||||||
|
|
||||||
async def async_setup(hass, config):
|
|
||||||
"""Set up a input_label."""
|
|
||||||
component = EntityComponent(_LOGGER, DOMAIN, hass)
|
|
||||||
|
|
||||||
entities = []
|
|
||||||
|
|
||||||
for object_id, cfg in config[DOMAIN].items():
|
|
||||||
if not cfg:
|
|
||||||
cfg = {}
|
|
||||||
name = cfg.get(CONF_NAME)
|
|
||||||
initial = cfg.get(ATTR_VALUE)
|
|
||||||
icon = cfg.get(CONF_ICON)
|
|
||||||
|
|
||||||
entities.append(InputLabel(object_id, name, initial, icon))
|
|
||||||
|
|
||||||
if not entities:
|
|
||||||
return False
|
|
||||||
|
|
||||||
component.async_register_entity_service(
|
|
||||||
SERVICE_SETNAME, SERVICE_SCHEMA,
|
|
||||||
'async_set_name'
|
|
||||||
)
|
|
||||||
|
|
||||||
component.async_register_entity_service(
|
|
||||||
SERVICE_SETVALUE, SERVICE_SCHEMA,
|
|
||||||
'async_set_value'
|
|
||||||
)
|
|
||||||
|
|
||||||
component.async_register_entity_service(
|
|
||||||
SERVICE_SETICON, SERVICE_SCHEMA,
|
|
||||||
'async_set_icon'
|
|
||||||
)
|
|
||||||
|
|
||||||
await component.async_add_entities(entities)
|
|
||||||
return True
|
|
||||||
|
|
||||||
class InputLabel(RestoreEntity):
|
|
||||||
"""Representation of a input_label."""
|
|
||||||
|
|
||||||
def __init__(self, object_id, name, initial, icon):
|
|
||||||
"""Initialize a input_label."""
|
|
||||||
self.entity_id = ENTITY_ID_FORMAT.format(object_id)
|
|
||||||
self._name = name
|
|
||||||
self._current_value = initial
|
|
||||||
self._icon = icon
|
|
||||||
|
|
||||||
@property
|
|
||||||
def should_poll(self):
|
|
||||||
"""If entity should be polled."""
|
|
||||||
return False
|
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self):
|
|
||||||
"""Return name of the input_label."""
|
|
||||||
return self._name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def icon(self):
|
|
||||||
"""Return the icon to be used for this entity."""
|
|
||||||
return self._icon
|
|
||||||
|
|
||||||
@property
|
|
||||||
def state(self):
|
|
||||||
"""Return the current value of the input_label."""
|
|
||||||
return self._current_value
|
|
||||||
|
|
||||||
@property
|
|
||||||
def state_attributes(self):
|
|
||||||
"""Return the state attributes."""
|
|
||||||
return {
|
|
||||||
ATTR_VALUE: self._current_value,
|
|
||||||
}
|
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
|
||||||
"""Run when entity about to be added to hass."""
|
|
||||||
|
|
||||||
await super().async_added_to_hass()
|
|
||||||
if self._current_value is not None:
|
|
||||||
return
|
|
||||||
|
|
||||||
state = await self.async_get_last_state()
|
|
||||||
value = state and state.state
|
|
||||||
self._current_value = value
|
|
||||||
|
|
||||||
async def async_set_name(self, value):
|
|
||||||
self._name = value
|
|
||||||
await self.async_update_ha_state()
|
|
||||||
|
|
||||||
async def async_set_icon(self, value):
|
|
||||||
self._icon = value
|
|
||||||
await self.async_update_ha_state()
|
|
||||||
|
|
||||||
async def async_set_value(self, value):
|
|
||||||
self._current_value = value
|
|
||||||
await self.async_update_ha_state()
|
|
|
@ -1,296 +0,0 @@
|
||||||
#
|
|
||||||
# API URLS: http://192.168.xxx.xxx/api/printer and http://192.168.xxx.xxx/api/job
|
|
||||||
#
|
|
||||||
|
|
||||||
"""Support for monitoring OctoPrint 3D printers."""
|
|
||||||
import logging
|
|
||||||
import time
|
|
||||||
|
|
||||||
from aiohttp.hdrs import CONTENT_TYPE
|
|
||||||
import requests
|
|
||||||
import voluptuous as vol
|
|
||||||
|
|
||||||
from homeassistant.components.discovery import SERVICE_OCTOPRINT
|
|
||||||
from homeassistant.const import (
|
|
||||||
CONF_API_KEY,
|
|
||||||
CONF_BINARY_SENSORS,
|
|
||||||
CONF_HOST,
|
|
||||||
CONF_MONITORED_CONDITIONS,
|
|
||||||
CONF_NAME,
|
|
||||||
CONF_PATH,
|
|
||||||
CONF_PORT,
|
|
||||||
CONF_SENSORS,
|
|
||||||
CONF_SSL,
|
|
||||||
CONTENT_TYPE_JSON,
|
|
||||||
PERCENTAGE,
|
|
||||||
TEMP_CELSIUS,
|
|
||||||
TIME_SECONDS,
|
|
||||||
)
|
|
||||||
from homeassistant.helpers import discovery
|
|
||||||
import homeassistant.helpers.config_validation as cv
|
|
||||||
from homeassistant.helpers.discovery import load_platform
|
|
||||||
from homeassistant.util import slugify as util_slugify
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
CONF_BED = "bed"
|
|
||||||
CONF_NUMBER_OF_TOOLS = "number_of_tools"
|
|
||||||
|
|
||||||
DEFAULT_NAME = "OctoPrint"
|
|
||||||
DOMAIN = "octoprint"
|
|
||||||
|
|
||||||
|
|
||||||
def has_all_unique_names(value):
|
|
||||||
"""Validate that printers have an unique name."""
|
|
||||||
names = [util_slugify(printer["name"]) for printer in value]
|
|
||||||
vol.Schema(vol.Unique())(names)
|
|
||||||
return value
|
|
||||||
|
|
||||||
|
|
||||||
def ensure_valid_path(value):
|
|
||||||
"""Validate the path, ensuring it starts and ends with a /."""
|
|
||||||
vol.Schema(cv.string)(value)
|
|
||||||
if value[0] != "/":
|
|
||||||
value = f"/{value}"
|
|
||||||
if value[-1] != "/":
|
|
||||||
value += "/"
|
|
||||||
return value
|
|
||||||
|
|
||||||
|
|
||||||
BINARY_SENSOR_TYPES = {
|
|
||||||
# API Endpoint, Group, Key, unit
|
|
||||||
"Printing": ["printer", "state", "printing", None],
|
|
||||||
"Printing Error": ["printer", "state", "error", None],
|
|
||||||
}
|
|
||||||
|
|
||||||
BINARY_SENSOR_SCHEMA = vol.Schema(
|
|
||||||
{
|
|
||||||
vol.Optional(
|
|
||||||
CONF_MONITORED_CONDITIONS, default=list(BINARY_SENSOR_TYPES)
|
|
||||||
): vol.All(cv.ensure_list, [vol.In(BINARY_SENSOR_TYPES)]),
|
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
SENSOR_TYPES = {
|
|
||||||
# API Endpoint, Group, Key, unit, icon
|
|
||||||
"Temperatures": ["printer", "temperature", "*", TEMP_CELSIUS],
|
|
||||||
"Current State": ["printer", "state", "text", None, "mdi:printer-3d"],
|
|
||||||
"Job Percentage": [
|
|
||||||
"job",
|
|
||||||
"progress",
|
|
||||||
"completion",
|
|
||||||
PERCENTAGE,
|
|
||||||
"mdi:file-percent",
|
|
||||||
],
|
|
||||||
"Time Remaining": [
|
|
||||||
"job",
|
|
||||||
"progress",
|
|
||||||
"printTimeLeft",
|
|
||||||
TIME_SECONDS,
|
|
||||||
"mdi:clock-end",
|
|
||||||
],
|
|
||||||
"Time Elapsed": ["job", "progress", "printTime", TIME_SECONDS, "mdi:clock-start"],
|
|
||||||
"User":["job", "job", "user", None, "mdi:printer-3d"],
|
|
||||||
"File":["job", "job", "file", None, "mdi:printer-3d"],
|
|
||||||
}
|
|
||||||
|
|
||||||
SENSOR_SCHEMA = vol.Schema(
|
|
||||||
{
|
|
||||||
vol.Optional(CONF_MONITORED_CONDITIONS, default=list(SENSOR_TYPES)): vol.All(
|
|
||||||
cv.ensure_list, [vol.In(SENSOR_TYPES)]
|
|
||||||
),
|
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema(
|
|
||||||
{
|
|
||||||
DOMAIN: vol.All(
|
|
||||||
cv.ensure_list,
|
|
||||||
[
|
|
||||||
vol.Schema(
|
|
||||||
{
|
|
||||||
vol.Required(CONF_API_KEY): cv.string,
|
|
||||||
vol.Required(CONF_HOST): cv.string,
|
|
||||||
vol.Optional(CONF_SSL, default=False): cv.boolean,
|
|
||||||
vol.Optional(CONF_PORT, default=80): cv.port,
|
|
||||||
vol.Optional(CONF_PATH, default="/"): ensure_valid_path,
|
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
|
||||||
vol.Optional(CONF_NUMBER_OF_TOOLS, default=0): cv.positive_int,
|
|
||||||
vol.Optional(CONF_BED, default=False): cv.boolean,
|
|
||||||
vol.Optional(CONF_SENSORS, default={}): SENSOR_SCHEMA,
|
|
||||||
vol.Optional(
|
|
||||||
CONF_BINARY_SENSORS, default={}
|
|
||||||
): BINARY_SENSOR_SCHEMA,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
],
|
|
||||||
has_all_unique_names,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
extra=vol.ALLOW_EXTRA,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def setup(hass, config):
|
|
||||||
"""Set up the OctoPrint component."""
|
|
||||||
printers = hass.data[DOMAIN] = {}
|
|
||||||
success = False
|
|
||||||
|
|
||||||
def device_discovered(service, info):
|
|
||||||
"""Get called when an Octoprint server has been discovered."""
|
|
||||||
_LOGGER.debug("Found an Octoprint server: %s", info)
|
|
||||||
|
|
||||||
discovery.listen(hass, SERVICE_OCTOPRINT, device_discovered)
|
|
||||||
|
|
||||||
if DOMAIN not in config:
|
|
||||||
# Skip the setup if there is no configuration present
|
|
||||||
return True
|
|
||||||
|
|
||||||
for printer in config[DOMAIN]:
|
|
||||||
name = printer[CONF_NAME]
|
|
||||||
protocol = "https" if printer[CONF_SSL] else "http"
|
|
||||||
base_url = (
|
|
||||||
f"{protocol}://{printer[CONF_HOST]}:{printer[CONF_PORT]}"
|
|
||||||
f"{printer[CONF_PATH]}api/"
|
|
||||||
)
|
|
||||||
api_key = printer[CONF_API_KEY]
|
|
||||||
number_of_tools = printer[CONF_NUMBER_OF_TOOLS]
|
|
||||||
bed = printer[CONF_BED]
|
|
||||||
try:
|
|
||||||
octoprint_api = OctoPrintAPI(base_url, api_key, bed, number_of_tools)
|
|
||||||
printers[base_url] = octoprint_api
|
|
||||||
octoprint_api.get("printer")
|
|
||||||
octoprint_api.get("job")
|
|
||||||
except requests.exceptions.RequestException as conn_err:
|
|
||||||
_LOGGER.error("Error setting up OctoPrint API: %r", conn_err)
|
|
||||||
continue
|
|
||||||
|
|
||||||
sensors = printer[CONF_SENSORS][CONF_MONITORED_CONDITIONS]
|
|
||||||
load_platform(
|
|
||||||
hass,
|
|
||||||
"sensor",
|
|
||||||
DOMAIN,
|
|
||||||
{"name": name, "base_url": base_url, "sensors": sensors},
|
|
||||||
config,
|
|
||||||
)
|
|
||||||
b_sensors = printer[CONF_BINARY_SENSORS][CONF_MONITORED_CONDITIONS]
|
|
||||||
load_platform(
|
|
||||||
hass,
|
|
||||||
"binary_sensor",
|
|
||||||
DOMAIN,
|
|
||||||
{"name": name, "base_url": base_url, "sensors": b_sensors},
|
|
||||||
config,
|
|
||||||
)
|
|
||||||
success = True
|
|
||||||
|
|
||||||
return success
|
|
||||||
|
|
||||||
|
|
||||||
class OctoPrintAPI:
|
|
||||||
"""Simple JSON wrapper for OctoPrint's API."""
|
|
||||||
|
|
||||||
def __init__(self, api_url, key, bed, number_of_tools):
|
|
||||||
"""Initialize OctoPrint API and set headers needed later."""
|
|
||||||
self.api_url = api_url
|
|
||||||
self.headers = {CONTENT_TYPE: CONTENT_TYPE_JSON, "X-Api-Key": key}
|
|
||||||
self.printer_last_reading = [{}, None]
|
|
||||||
self.job_last_reading = [{}, None]
|
|
||||||
self.job_available = False
|
|
||||||
self.printer_available = False
|
|
||||||
self.available = False
|
|
||||||
self.printer_error_logged = False
|
|
||||||
self.job_error_logged = False
|
|
||||||
self.bed = bed
|
|
||||||
self.number_of_tools = number_of_tools
|
|
||||||
|
|
||||||
def get_tools(self):
|
|
||||||
"""Get the list of tools that temperature is monitored on."""
|
|
||||||
tools = []
|
|
||||||
if self.number_of_tools > 0:
|
|
||||||
for tool_number in range(0, self.number_of_tools):
|
|
||||||
tools.append(f"tool{tool_number!s}")
|
|
||||||
if self.bed:
|
|
||||||
tools.append("bed")
|
|
||||||
if not self.bed and self.number_of_tools == 0:
|
|
||||||
temps = self.printer_last_reading[0].get("temperature")
|
|
||||||
if temps is not None:
|
|
||||||
tools = temps.keys()
|
|
||||||
return tools
|
|
||||||
|
|
||||||
def get(self, endpoint):
|
|
||||||
"""Send a get request, and return the response as a dict."""
|
|
||||||
# Only query the API at most every 30 seconds
|
|
||||||
now = time.time()
|
|
||||||
if endpoint == "job":
|
|
||||||
last_time = self.job_last_reading[1]
|
|
||||||
if last_time is not None:
|
|
||||||
if now - last_time < 30.0:
|
|
||||||
return self.job_last_reading[0]
|
|
||||||
elif endpoint == "printer":
|
|
||||||
last_time = self.printer_last_reading[1]
|
|
||||||
if last_time is not None:
|
|
||||||
if now - last_time < 30.0:
|
|
||||||
return self.printer_last_reading[0]
|
|
||||||
|
|
||||||
url = self.api_url + endpoint
|
|
||||||
try:
|
|
||||||
response = requests.get(url, headers=self.headers, timeout=9)
|
|
||||||
response.raise_for_status()
|
|
||||||
if endpoint == "job":
|
|
||||||
self.job_last_reading[0] = response.json()
|
|
||||||
self.job_last_reading[1] = time.time()
|
|
||||||
self.job_available = True
|
|
||||||
elif endpoint == "printer":
|
|
||||||
self.printer_last_reading[0] = response.json()
|
|
||||||
self.printer_last_reading[1] = time.time()
|
|
||||||
self.printer_available = True
|
|
||||||
self.available = self.printer_available and self.job_available
|
|
||||||
if self.available:
|
|
||||||
self.job_error_logged = False
|
|
||||||
self.printer_error_logged = False
|
|
||||||
return response.json()
|
|
||||||
except Exception as conn_exc: # pylint: disable=broad-except
|
|
||||||
log_string = "Failed to update OctoPrint status. Error: %s" % conn_exc
|
|
||||||
# Only log the first failure
|
|
||||||
if endpoint == "job":
|
|
||||||
log_string = f"Endpoint: job {log_string}"
|
|
||||||
if not self.job_error_logged:
|
|
||||||
_LOGGER.error(log_string)
|
|
||||||
self.job_error_logged = True
|
|
||||||
self.job_available = False
|
|
||||||
elif endpoint == "printer":
|
|
||||||
log_string = f"Endpoint: printer {log_string}"
|
|
||||||
if not self.printer_error_logged:
|
|
||||||
_LOGGER.error(log_string)
|
|
||||||
self.printer_error_logged = True
|
|
||||||
self.printer_available = False
|
|
||||||
self.available = False
|
|
||||||
return None
|
|
||||||
|
|
||||||
def update(self, sensor_type, end_point, group, tool=None):
|
|
||||||
"""Return the value for sensor_type from the provided endpoint."""
|
|
||||||
response = self.get(end_point)
|
|
||||||
if response is not None:
|
|
||||||
return get_value_from_json(response, sensor_type, group, tool)
|
|
||||||
return response
|
|
||||||
|
|
||||||
|
|
||||||
def get_value_from_json(json_dict, sensor_type, group, tool):
|
|
||||||
"""Return the value for sensor_type from the JSON."""
|
|
||||||
if group not in json_dict:
|
|
||||||
return None
|
|
||||||
|
|
||||||
if sensor_type in json_dict[group]:
|
|
||||||
if sensor_type == "target" and json_dict[sensor_type] is None:
|
|
||||||
return 0
|
|
||||||
if sensor_type == "file":
|
|
||||||
return json_dict[group][sensor_type]["name"]
|
|
||||||
return json_dict[group][sensor_type]
|
|
||||||
|
|
||||||
if tool is not None:
|
|
||||||
if sensor_type in json_dict[group][tool]:
|
|
||||||
return json_dict[group][tool][sensor_type]
|
|
||||||
|
|
||||||
return None
|
|
|
@ -1,83 +0,0 @@
|
||||||
"""Support for monitoring OctoPrint binary sensors."""
|
|
||||||
import logging
|
|
||||||
|
|
||||||
import requests
|
|
||||||
|
|
||||||
from homeassistant.components.binary_sensor import BinarySensorEntity
|
|
||||||
|
|
||||||
from . import BINARY_SENSOR_TYPES, DOMAIN as COMPONENT_DOMAIN
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
|
||||||
"""Set up the available OctoPrint binary sensors."""
|
|
||||||
if discovery_info is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
name = discovery_info["name"]
|
|
||||||
base_url = discovery_info["base_url"]
|
|
||||||
monitored_conditions = discovery_info["sensors"]
|
|
||||||
octoprint_api = hass.data[COMPONENT_DOMAIN][base_url]
|
|
||||||
|
|
||||||
devices = []
|
|
||||||
for octo_type in monitored_conditions:
|
|
||||||
new_sensor = OctoPrintBinarySensor(
|
|
||||||
octoprint_api,
|
|
||||||
octo_type,
|
|
||||||
BINARY_SENSOR_TYPES[octo_type][2],
|
|
||||||
name,
|
|
||||||
BINARY_SENSOR_TYPES[octo_type][3],
|
|
||||||
BINARY_SENSOR_TYPES[octo_type][0],
|
|
||||||
BINARY_SENSOR_TYPES[octo_type][1],
|
|
||||||
"flags",
|
|
||||||
)
|
|
||||||
devices.append(new_sensor)
|
|
||||||
add_entities(devices, True)
|
|
||||||
|
|
||||||
|
|
||||||
class OctoPrintBinarySensor(BinarySensorEntity):
|
|
||||||
"""Representation an OctoPrint binary sensor."""
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self, api, condition, sensor_type, sensor_name, unit, endpoint, group, tool=None
|
|
||||||
):
|
|
||||||
"""Initialize a new OctoPrint sensor."""
|
|
||||||
self.sensor_name = sensor_name
|
|
||||||
if tool is None:
|
|
||||||
self._name = f"{sensor_name} {condition}"
|
|
||||||
else:
|
|
||||||
self._name = f"{sensor_name} {condition}"
|
|
||||||
self.sensor_type = sensor_type
|
|
||||||
self.api = api
|
|
||||||
self._state = False
|
|
||||||
self._unit_of_measurement = unit
|
|
||||||
self.api_endpoint = endpoint
|
|
||||||
self.api_group = group
|
|
||||||
self.api_tool = tool
|
|
||||||
_LOGGER.debug("Created OctoPrint binary sensor %r", self)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self):
|
|
||||||
"""Return the name of the sensor."""
|
|
||||||
return self._name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def is_on(self):
|
|
||||||
"""Return true if binary sensor is on."""
|
|
||||||
return bool(self._state)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def device_class(self):
|
|
||||||
"""Return the class of this sensor, from DEVICE_CLASSES."""
|
|
||||||
return None
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
"""Update state of sensor."""
|
|
||||||
try:
|
|
||||||
self._state = self.api.update(
|
|
||||||
self.sensor_type, self.api_endpoint, self.api_group, self.api_tool
|
|
||||||
)
|
|
||||||
except requests.exceptions.ConnectionError:
|
|
||||||
# Error calling the api, already logged in api.update()
|
|
||||||
return
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"domain": "octoprint",
|
|
||||||
"name": "OctoPrint",
|
|
||||||
"documentation": "https://www.home-assistant.io/integrations/octoprint",
|
|
||||||
"after_dependencies": ["discovery"],
|
|
||||||
"codeowners": []
|
|
||||||
}
|
|
|
@ -1,139 +0,0 @@
|
||||||
"""Support for monitoring OctoPrint sensors."""
|
|
||||||
import logging
|
|
||||||
|
|
||||||
import requests
|
|
||||||
|
|
||||||
from homeassistant.const import PERCENTAGE, TEMP_CELSIUS
|
|
||||||
from homeassistant.helpers.entity import Entity
|
|
||||||
|
|
||||||
from . import DOMAIN as COMPONENT_DOMAIN, SENSOR_TYPES
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
NOTIFICATION_ID = "octoprint_notification"
|
|
||||||
NOTIFICATION_TITLE = "OctoPrint sensor setup error"
|
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
|
||||||
"""Set up the available OctoPrint sensors."""
|
|
||||||
if discovery_info is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
name = discovery_info["name"]
|
|
||||||
base_url = discovery_info["base_url"]
|
|
||||||
monitored_conditions = discovery_info["sensors"]
|
|
||||||
octoprint_api = hass.data[COMPONENT_DOMAIN][base_url]
|
|
||||||
tools = octoprint_api.get_tools()
|
|
||||||
|
|
||||||
if "Temperatures" in monitored_conditions:
|
|
||||||
if not tools:
|
|
||||||
hass.components.persistent_notification.create(
|
|
||||||
"Your printer appears to be offline.<br />"
|
|
||||||
"If you do not want to have your printer on <br />"
|
|
||||||
" at all times, and you would like to monitor <br /> "
|
|
||||||
"temperatures, please add <br />"
|
|
||||||
"bed and/or number_of_tools to your configuration <br />"
|
|
||||||
"and restart.",
|
|
||||||
title=NOTIFICATION_TITLE,
|
|
||||||
notification_id=NOTIFICATION_ID,
|
|
||||||
)
|
|
||||||
|
|
||||||
devices = []
|
|
||||||
types = ["actual", "target"]
|
|
||||||
for octo_type in monitored_conditions:
|
|
||||||
if octo_type == "Temperatures":
|
|
||||||
for tool in tools:
|
|
||||||
for temp_type in types:
|
|
||||||
new_sensor = OctoPrintSensor(
|
|
||||||
octoprint_api,
|
|
||||||
temp_type,
|
|
||||||
temp_type,
|
|
||||||
name,
|
|
||||||
SENSOR_TYPES[octo_type][3],
|
|
||||||
SENSOR_TYPES[octo_type][0],
|
|
||||||
SENSOR_TYPES[octo_type][1],
|
|
||||||
tool,
|
|
||||||
)
|
|
||||||
devices.append(new_sensor)
|
|
||||||
else:
|
|
||||||
new_sensor = OctoPrintSensor(
|
|
||||||
octoprint_api,
|
|
||||||
octo_type,
|
|
||||||
SENSOR_TYPES[octo_type][2],
|
|
||||||
name,
|
|
||||||
SENSOR_TYPES[octo_type][3],
|
|
||||||
SENSOR_TYPES[octo_type][0],
|
|
||||||
SENSOR_TYPES[octo_type][1],
|
|
||||||
None,
|
|
||||||
SENSOR_TYPES[octo_type][4],
|
|
||||||
)
|
|
||||||
devices.append(new_sensor)
|
|
||||||
add_entities(devices, True)
|
|
||||||
|
|
||||||
|
|
||||||
class OctoPrintSensor(Entity):
|
|
||||||
"""Representation of an OctoPrint sensor."""
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
api,
|
|
||||||
condition,
|
|
||||||
sensor_type,
|
|
||||||
sensor_name,
|
|
||||||
unit,
|
|
||||||
endpoint,
|
|
||||||
group,
|
|
||||||
tool=None,
|
|
||||||
icon=None,
|
|
||||||
):
|
|
||||||
"""Initialize a new OctoPrint sensor."""
|
|
||||||
self.sensor_name = sensor_name
|
|
||||||
if tool is None:
|
|
||||||
self._name = f"{sensor_name} {condition}"
|
|
||||||
else:
|
|
||||||
self._name = f"{sensor_name} {condition} {tool} temp"
|
|
||||||
self.sensor_type = sensor_type
|
|
||||||
self.api = api
|
|
||||||
self._state = None
|
|
||||||
self._unit_of_measurement = unit
|
|
||||||
self.api_endpoint = endpoint
|
|
||||||
self.api_group = group
|
|
||||||
self.api_tool = tool
|
|
||||||
self._icon = icon
|
|
||||||
_LOGGER.debug("Created OctoPrint sensor %r", self)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self):
|
|
||||||
"""Return the name of the sensor."""
|
|
||||||
return self._name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def state(self):
|
|
||||||
"""Return the state of the sensor."""
|
|
||||||
sensor_unit = self.unit_of_measurement
|
|
||||||
if sensor_unit in (TEMP_CELSIUS, PERCENTAGE):
|
|
||||||
# API sometimes returns null and not 0
|
|
||||||
if self._state is None:
|
|
||||||
self._state = 0
|
|
||||||
return round(self._state, 2)
|
|
||||||
return self._state
|
|
||||||
|
|
||||||
@property
|
|
||||||
def unit_of_measurement(self):
|
|
||||||
"""Return the unit of measurement of this entity, if any."""
|
|
||||||
return self._unit_of_measurement
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
"""Update state of sensor."""
|
|
||||||
try:
|
|
||||||
self._state = self.api.update(
|
|
||||||
self.sensor_type, self.api_endpoint, self.api_group, self.api_tool
|
|
||||||
)
|
|
||||||
except requests.exceptions.ConnectionError:
|
|
||||||
# Error calling the api, already logged in api.update()
|
|
||||||
return
|
|
||||||
|
|
||||||
@property
|
|
||||||
def icon(self):
|
|
||||||
"""Icon to use in the frontend."""
|
|
||||||
return self._icon
|
|
|
@ -17,6 +17,7 @@ logs:
|
||||||
homeassistant.exceptions: warning
|
homeassistant.exceptions: warning
|
||||||
homeassistant.helpers.script: warning
|
homeassistant.helpers.script: warning
|
||||||
homeassistant.helpers.entity: warning
|
homeassistant.helpers.entity: warning
|
||||||
|
homeassistant.helpers.template: critical
|
||||||
homeassistant.components.wemo: critical
|
homeassistant.components.wemo: critical
|
||||||
homeassistant.components.sensor: critical
|
homeassistant.components.sensor: critical
|
||||||
homeassistant.components.cloud.iot: warning
|
homeassistant.components.cloud.iot: warning
|
||||||
|
@ -24,7 +25,7 @@ logs:
|
||||||
homeassistant.components.camera: warning
|
homeassistant.components.camera: warning
|
||||||
homeassistant.components.zwave: critical
|
homeassistant.components.zwave: critical
|
||||||
homeassistant.components.image_processing: warning
|
homeassistant.components.image_processing: warning
|
||||||
homeassistant.components.homekit: warning
|
homeassistant.components.homekit: error
|
||||||
custom_components.sensor.life360: warning
|
custom_components.sensor.life360: warning
|
||||||
custom_components.sensor.paloalto: warning
|
custom_components.sensor.paloalto: warning
|
||||||
homeassistant.components.recorder: warning
|
homeassistant.components.recorder: warning
|
||||||
|
|
|
@ -52,8 +52,6 @@ cards:
|
||||||
name: Srinika
|
name: Srinika
|
||||||
- entity: device_tracker.life360_hasika
|
- entity: device_tracker.life360_hasika
|
||||||
name: Hasika
|
name: Hasika
|
||||||
- entity: device_tracker.mahasri_tesla_location_tracker
|
|
||||||
name: Tesla
|
|
||||||
- entity: sensor.yo_mama_geocoded_location
|
- entity: sensor.yo_mama_geocoded_location
|
||||||
name: Suresh
|
name: Suresh
|
||||||
- entity: sensor.mallika_geocoded_location
|
- entity: sensor.mallika_geocoded_location
|
||||||
|
@ -77,7 +75,6 @@ cards:
|
||||||
title: 3D Printer
|
title: 3D Printer
|
||||||
show_header_toggle: false
|
show_header_toggle: false
|
||||||
entities:
|
entities:
|
||||||
- sensor.octoprint_file
|
|
||||||
- binary_sensor.octoprint_printing
|
- binary_sensor.octoprint_printing
|
||||||
- binary_sensor.octoprint_printing_error
|
- binary_sensor.octoprint_printing_error
|
||||||
- sensor.octoprint_current_state
|
- sensor.octoprint_current_state
|
||||||
|
|
|
@ -25,7 +25,6 @@ cards:
|
||||||
show_header_toggle: false
|
show_header_toggle: false
|
||||||
entities:
|
entities:
|
||||||
- climate.dining_room
|
- climate.dining_room
|
||||||
- climate.tesla_model_3_hvac_climate_system
|
|
||||||
- binary_sensor.dining_room_thermostat_fan
|
- binary_sensor.dining_room_thermostat_fan
|
||||||
- binary_sensor.dining_room_thermostat_has_leaf
|
- binary_sensor.dining_room_thermostat_has_leaf
|
||||||
- binary_sensor.dining_room_thermostat_is_locked
|
- binary_sensor.dining_room_thermostat_is_locked
|
||||||
|
|
|
@ -8,7 +8,7 @@ cards:
|
||||||
- type: gauge
|
- type: gauge
|
||||||
name: Tesla Battery
|
name: Tesla Battery
|
||||||
unit: "%"
|
unit: "%"
|
||||||
entity: sensor.tesla_model_3_battery_sensor
|
entity: sensor.mahasri_tesla_battery_sensor
|
||||||
severity:
|
severity:
|
||||||
green: 75
|
green: 75
|
||||||
yellow: 40
|
yellow: 40
|
||||||
|
@ -16,7 +16,7 @@ cards:
|
||||||
- type: gauge
|
- type: gauge
|
||||||
name: Battery Range
|
name: Battery Range
|
||||||
unit: "miles"
|
unit: "miles"
|
||||||
entity: sensor.tesla_model_3_range_sensor
|
entity: sensor.mahasri_tesla_range_sensor
|
||||||
max: 320
|
max: 320
|
||||||
min: 0
|
min: 0
|
||||||
severity:
|
severity:
|
||||||
|
@ -24,15 +24,15 @@ cards:
|
||||||
yellow: 100
|
yellow: 100
|
||||||
red: 75
|
red: 75
|
||||||
- type: thermostat
|
- type: thermostat
|
||||||
entity: climate.tesla_model_3_hvac_climate_system
|
entity: climate.mahasri_tesla_hvac_climate_system
|
||||||
- type: horizontal-stack
|
- type: horizontal-stack
|
||||||
cards:
|
cards:
|
||||||
- type: sensor
|
- type: sensor
|
||||||
entity: sensor.tesla_model_3_temperature_sensor_inside
|
entity: sensor.mahasri_tesla_temperature_sensor_inside
|
||||||
name: Temperature Inside
|
name: Temperature Inside
|
||||||
graph: line
|
graph: line
|
||||||
- type: sensor
|
- type: sensor
|
||||||
entity: sensor.tesla_model_3_temperature_sensor_outside
|
entity: sensor.mahasri_tesla_temperature_sensor_outside
|
||||||
name: Temperature outside
|
name: Temperature outside
|
||||||
graph: line
|
graph: line
|
||||||
|
|
||||||
|
@ -42,22 +42,31 @@ cards:
|
||||||
entities:
|
entities:
|
||||||
- device_tracker.mahasri_tesla_location_tracker
|
- device_tracker.mahasri_tesla_location_tracker
|
||||||
- binary_sensor.mahasri_tesla_online_sensor
|
- binary_sensor.mahasri_tesla_online_sensor
|
||||||
- binary_sensor.tesla_model_3_parking_brake_sensor
|
- binary_sensor.mahasri_tesla_parking_brake_sensor
|
||||||
- lock.tesla_model_3_door_lock
|
- lock.mahasri_tesla_door_lock
|
||||||
- sensor.tesla_model_3_mileage_sensor
|
- sensor.mahasri_tesla_mileage_sensor
|
||||||
- switch.tesla_model_3_update_switch
|
- switch.mahasri_tesla_update_switch
|
||||||
- lock.tesla_model_3_charger_door_lock
|
- lock.mahasri_tesla_charger_door_lock
|
||||||
- sensor.mahasri_tesla_charging_rate_sensor
|
- sensor.mahasri_tesla_charging_rate_sensor
|
||||||
- sensor.tesla_model_3_battery_sensor
|
- sensor.mahasri_tesla_battery_sensor
|
||||||
- sensor.tesla_model_3_range_sensor
|
- sensor.mahasri_tesla_range_sensor
|
||||||
- sensor.tesla_model_3_temperature_sensor_inside
|
- sensor.mahasri_tesla_temperature_sensor_inside
|
||||||
- sensor.tesla_model_3_temperature_sensor_outside
|
- sensor.mahasri_tesla_temperature_sensor_outside
|
||||||
- switch.mahasri_tesla_sentry_mode_switch
|
- switch.mahasri_tesla_sentry_mode_switch
|
||||||
|
|
||||||
- type: entities
|
- type: entities
|
||||||
title: Charging
|
title: Charging
|
||||||
show_header_toggle: false
|
show_header_toggle: false
|
||||||
entities:
|
entities:
|
||||||
- binary_sensor.tesla_model_3_charger_sensor
|
- binary_sensor.mahasri_tesla_charger_sensor
|
||||||
- switch.tesla_model_3_charger_switch
|
- switch.mahasri_tesla_charger_switch
|
||||||
- switch.tesla_model_3_maxrange_switch
|
- switch.mahasri_tesla_maxrange_switch
|
||||||
|
|
||||||
|
- type: entities
|
||||||
|
title: Locks
|
||||||
|
show_header_toggle: false
|
||||||
|
entities:
|
||||||
|
- lock.mahasri_tesla_trunk_lock
|
||||||
|
- lock.mahasri_tesla_frunk_lock
|
||||||
|
- lock.mahasri_tesla_door_lock
|
||||||
|
- lock.mahasri_tesla_charger_door_lock
|
||||||
|
|
|
@ -26,7 +26,6 @@ cards:
|
||||||
title: Octoprint
|
title: Octoprint
|
||||||
show_header_toggle: false
|
show_header_toggle: false
|
||||||
entities:
|
entities:
|
||||||
- sensor.octoprint_file
|
|
||||||
- binary_sensor.octoprint_printing
|
- binary_sensor.octoprint_printing
|
||||||
- sensor.octoprint_current_state
|
- sensor.octoprint_current_state
|
||||||
- binary_sensor.octoprint_printing_error
|
- binary_sensor.octoprint_printing_error
|
||||||
|
|
|
@ -407,31 +407,31 @@ automation:
|
||||||
data_template:
|
data_template:
|
||||||
message: "{{ trigger.to_state.attributes.friendly_name.split(' ')[1] }}'s phone battery is : {{ trigger.to_state.attributes.battery }}%."
|
message: "{{ trigger.to_state.attributes.friendly_name.split(' ')[1] }}'s phone battery is : {{ trigger.to_state.attributes.battery }}%."
|
||||||
|
|
||||||
- alias: Alert Low Battery
|
# - alias: Alert Low Battery
|
||||||
trigger:
|
# trigger:
|
||||||
- platform: template
|
# - platform: template
|
||||||
value_template: >
|
# value_template: >
|
||||||
{% set ns = namespace(lowBattery=false) %}
|
# {% set ns = namespace(lowBattery=false) %}
|
||||||
{%- for x in states if x.attributes and x.attributes.battery_level and x.attributes.battery_level |int <= 24 %}
|
# {%- for x in states if x.attributes and x.attributes.battery_level and x.attributes.battery_level |int <= 24 %}
|
||||||
{% set ns.lowBattery = true %}{% endfor %}
|
# {% set ns.lowBattery = true %}{% endfor %}
|
||||||
{{ ns.lowBattery }}
|
# {{ ns.lowBattery }}
|
||||||
condition:
|
# condition:
|
||||||
- condition: template
|
# - condition: template
|
||||||
value_template: "{{ ((trigger.to_state.state | int) < states('sensor.battery_alert_threshold') | int) }}"
|
# value_template: "{{ ((trigger.to_state.state | int) < states('sensor.battery_alert_threshold') | int) }}"
|
||||||
action:
|
# action:
|
||||||
- service: script.voice_notify
|
# - service: script.voice_notify
|
||||||
data_template:
|
# data_template:
|
||||||
message: >
|
# message: >
|
||||||
{% set ns = namespace(lowBattery="") %}
|
# {% set ns = namespace(lowBattery="") %}
|
||||||
{%- for x in states if x.attributes and x.attributes.battery_level and x.attributes.battery_level |int <= 24 %}
|
# {%- 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 -%}
|
# {%- if loop.first %}The {% elif loop.last %} and the {% else %}, the {% endif -%}
|
||||||
{% set ns.lowBattery = ns.lowBattery ~ ',' ~ x.name %}
|
# {% set ns.lowBattery = ns.lowBattery ~ ',' ~ x.name %}
|
||||||
{%- endfor %}
|
# {%- endfor %}
|
||||||
{{ ns.lowBattery -}}
|
# {{ ns.lowBattery -}}
|
||||||
{{- ' battery is ' if ns.lowBattery.split(',')|count == 2 else ' batteries are ' -}} less than 25 percent.
|
# {{- ' battery is ' if ns.lowBattery.split(',')|count == 2 else ' batteries are ' -}} less than 25 percent.
|
||||||
- service: script.led_message
|
# - service: script.led_message
|
||||||
data_template:
|
# data_template:
|
||||||
message: "{{ trigger.to_state.attributes.friendly_name.split(' ')[1] }}'s phone battery is : {{ trigger.to_state.attributes.battery }}%."
|
# 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
|
- alias: Check Wi-Fi Status of iPhones At Home
|
||||||
initial_state: true
|
initial_state: true
|
||||||
|
|
|
@ -717,6 +717,10 @@ automation:
|
||||||
(states.binary_sensor.motion_sensor_158d00024ee084.last_updated ~ '').replace('-','_')
|
(states.binary_sensor.motion_sensor_158d00024ee084.last_updated ~ '').replace('-','_')
|
||||||
.replace(' ', '_').replace(':','_').replace('.','_').replace('+','_') ~ '.jpg' }}"
|
.replace(' ', '_').replace(':','_').replace('.','_').replace('+','_') ~ '.jpg' }}"
|
||||||
caption: "Garage"
|
caption: "Garage"
|
||||||
|
- file: "{{ '/config/www/downloads/camera/porch/porch_' ~
|
||||||
|
(states.binary_sensor.motion_sensor_158d00024ee084.last_updated ~ '').replace('-','_')
|
||||||
|
.replace(' ', '_').replace(':','_').replace('.','_').replace('+','_') ~ '.jpg' }}"
|
||||||
|
caption: Porch
|
||||||
|
|
||||||
- service: notify.notify_smtp
|
- service: notify.notify_smtp
|
||||||
data_template:
|
data_template:
|
||||||
|
@ -733,6 +737,9 @@ automation:
|
||||||
- "{{ '/config/www/downloads/camera/garage/garage_' ~
|
- "{{ '/config/www/downloads/camera/garage/garage_' ~
|
||||||
(states.binary_sensor.motion_sensor_158d00024ee084.last_updated ~ '').replace('-','_')
|
(states.binary_sensor.motion_sensor_158d00024ee084.last_updated ~ '').replace('-','_')
|
||||||
.replace(' ', '_').replace(':','_').replace('.','_').replace('+','_') ~ '.jpg' }}"
|
.replace(' ', '_').replace(':','_').replace('.','_').replace('+','_') ~ '.jpg' }}"
|
||||||
|
- "{{ '/config/www/downloads/camera/porch/porch_' ~
|
||||||
|
(states.binary_sensor.motion_sensor_158d00024ee084.last_updated ~ '').replace('-','_')
|
||||||
|
.replace(' ', '_').replace(':','_').replace('.','_').replace('+','_') ~ '.jpg' }}"
|
||||||
|
|
||||||
- condition: template
|
- condition: template
|
||||||
value_template: "{{ states('device_tracker.life360_suresh') == 'home' }}"
|
value_template: "{{ states('device_tracker.life360_suresh') == 'home' }}"
|
||||||
|
|
|
@ -210,7 +210,6 @@ automation:
|
||||||
# A gentle 10 minute reminder that the Home Security system is OFF
|
# A gentle 10 minute reminder that the Home Security system is OFF
|
||||||
###############################################################################
|
###############################################################################
|
||||||
- alias: Home Security System WatchDog 10 minutes
|
- alias: Home Security System WatchDog 10 minutes
|
||||||
initial_state: true
|
|
||||||
trigger:
|
trigger:
|
||||||
- platform: state
|
- platform: state
|
||||||
entity_id:
|
entity_id:
|
||||||
|
@ -227,7 +226,6 @@ automation:
|
||||||
# A gentle reminder that the home security is OFF for more than 30 minutes
|
# A gentle reminder that the home security is OFF for more than 30 minutes
|
||||||
###############################################################################
|
###############################################################################
|
||||||
- alias: Home Security System WatchDog 30 minutes
|
- alias: Home Security System WatchDog 30 minutes
|
||||||
initial_state: true
|
|
||||||
trigger:
|
trigger:
|
||||||
- platform: state
|
- platform: state
|
||||||
entity_id:
|
entity_id:
|
||||||
|
|
|
@ -110,6 +110,7 @@ tplink:
|
||||||
#name: Upstairs Fragrance Outlet
|
#name: Upstairs Fragrance Outlet
|
||||||
- host: !secret tplink_kids_bed_accent_light
|
- host: !secret tplink_kids_bed_accent_light
|
||||||
#name: Kids Bed Accent Light
|
#name: Kids Bed Accent Light
|
||||||
|
- host: !secret tplink_3d_printer
|
||||||
dimmer:
|
dimmer:
|
||||||
- host: !secret tplink_bathroom_lights
|
- host: !secret tplink_bathroom_lights
|
||||||
strip:
|
strip:
|
||||||
|
|
|
@ -65,5 +65,6 @@ telegram_bot:
|
||||||
# Add Polling
|
# Add Polling
|
||||||
- platform: polling
|
- platform: polling
|
||||||
api_key: !secret telegram_apikey
|
api_key: !secret telegram_apikey
|
||||||
|
parse_mode: html
|
||||||
allowed_chat_ids:
|
allowed_chat_ids:
|
||||||
- !secret telegram_chatid
|
- !secret telegram_chatid
|
||||||
|
|
|
@ -148,7 +148,7 @@ sensor:
|
||||||
value_template: "{{value_json.Location.periods[1].Index}}"
|
value_template: "{{value_json.Location.periods[1].Index}}"
|
||||||
scan_interval: 21600
|
scan_interval: 21600
|
||||||
headers:
|
headers:
|
||||||
Referer: "https://www.pollen.com"
|
Referer: !secret weather_pollen_url
|
||||||
|
|
||||||
- platform: rest
|
- platform: rest
|
||||||
name: cold_flu
|
name: cold_flu
|
||||||
|
@ -156,7 +156,7 @@ sensor:
|
||||||
value_template: "{{value_json.Location.periods[0].Index}}"
|
value_template: "{{value_json.Location.periods[0].Index}}"
|
||||||
scan_interval: 21600
|
scan_interval: 21600
|
||||||
headers:
|
headers:
|
||||||
Referer: "https://www.pollen.com"
|
Referer: !secret weather_pollen_url
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# _ _ _
|
# _ _ _
|
||||||
|
|
|
@ -34,12 +34,6 @@
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
{%- endmacro -%}
|
{%- endmacro -%}
|
||||||
|
|
||||||
{%- macro pollen_levels() -%}
|
|
||||||
{% if states('sensor.pollen_level') != 'unknown' %}
|
|
||||||
Pollen level is {{ states('sensor.pollen_level') }}.
|
|
||||||
{% endif %}
|
|
||||||
{%- endmacro -%}
|
|
||||||
|
|
||||||
{%- macro humidity_status() -%}
|
{%- macro humidity_status() -%}
|
||||||
Home humidity is {{ states('sensor.dining_room_thermostat_humidity') }} percent.
|
Home humidity is {{ states('sensor.dining_room_thermostat_humidity') }} percent.
|
||||||
{%- endmacro -%}
|
{%- endmacro -%}
|
||||||
|
@ -83,21 +77,10 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{%- endmacro -%}
|
{%- endmacro -%}
|
||||||
|
|
||||||
{%- macro light_status() -%}
|
{%- macro light_switch_status() -%}
|
||||||
{%- set lights_switches = ["switch.basement_left",
|
{% for item in states if item.domain =="light" or item.domain == "switch" -%}
|
||||||
"switch.basement_right",
|
{%- if item.state == "on" -%}
|
||||||
"switch.frontyard_light",
|
{%- set friendly_name = item.attributes.friendly_name -%}
|
||||||
"switch.garage",
|
|
||||||
"switch.guest_bedroom",
|
|
||||||
"switch.prayer_room",
|
|
||||||
"switch.kids_bed_accent",
|
|
||||||
"switch.kids_bedroom",
|
|
||||||
"switch.kitchen",
|
|
||||||
"switch.office_room",
|
|
||||||
"switch.backyard_light"] %}
|
|
||||||
{% for item in lights_switches -%}
|
|
||||||
{%- if states[item.split('.')[0]][item.split('.')[1]].state == "on" -%}
|
|
||||||
{%- set friendly_name = states[item.split('.')[0]][item.split('.')[1]].attributes.friendly_name -%}
|
|
||||||
{{ friendly_name }} {{ 'are' if plural(friendly_name) == "true" else 'is' }} ON.
|
{{ friendly_name }} {{ 'are' if plural(friendly_name) == "true" else 'is' }} ON.
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{%- endfor -%}
|
{%- endfor -%}
|
||||||
|
@ -106,14 +89,10 @@
|
||||||
{%- macro mother_of_all_macros() -%}
|
{%- macro mother_of_all_macros() -%}
|
||||||
{{ alarm_status() }}
|
{{ alarm_status() }}
|
||||||
{{ garage_status() }}
|
{{ garage_status() }}
|
||||||
{{ USPS() }}
|
|
||||||
{{ tesla_status() }}
|
|
||||||
{{ weather_update() }}
|
{{ weather_update() }}
|
||||||
{{ humidity_status() }}
|
{{ humidity_status() }}
|
||||||
{{ uv_levels() }}
|
{{ uv_levels() }}
|
||||||
{{ pollen_levels() }}
|
{{ light_switch_status() }}
|
||||||
{{ alert_battery_levels() }}
|
|
||||||
{{ light_status() }}
|
|
||||||
{%- endmacro -%}
|
{%- endmacro -%}
|
||||||
|
|
||||||
{{- cleanup(mother_of_all_macros()) -}}
|
{{- cleanup(mother_of_all_macros()) -}}
|
||||||
|
|
Loading…
Reference in New Issue