diff --git a/.gitignore b/.gitignore index 66cb19c..997200c 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,8 @@ private/* 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 diff --git a/blueprints/script/homeassistant/confirmable_notification.yaml b/blueprints/script/homeassistant/confirmable_notification.yaml new file mode 100644 index 0000000..ae170ea --- /dev/null +++ b/blueprints/script/homeassistant/confirmable_notification.yaml @@ -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 diff --git a/custom_components/input_label.py b/custom_components/input_label.py deleted file mode 100644 index befc7ce..0000000 --- a/custom_components/input_label.py +++ /dev/null @@ -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() diff --git a/custom_components/octoprint/__init__.py b/custom_components/octoprint/__init__.py deleted file mode 100644 index 54e1ebe..0000000 --- a/custom_components/octoprint/__init__.py +++ /dev/null @@ -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 \ No newline at end of file diff --git a/custom_components/octoprint/binary_sensor.py b/custom_components/octoprint/binary_sensor.py deleted file mode 100644 index 4c0209b..0000000 --- a/custom_components/octoprint/binary_sensor.py +++ /dev/null @@ -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 \ No newline at end of file diff --git a/custom_components/octoprint/manifest.json b/custom_components/octoprint/manifest.json deleted file mode 100644 index 28e09cc..0000000 --- a/custom_components/octoprint/manifest.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "domain": "octoprint", - "name": "OctoPrint", - "documentation": "https://www.home-assistant.io/integrations/octoprint", - "after_dependencies": ["discovery"], - "codeowners": [] -} diff --git a/custom_components/octoprint/sensor.py b/custom_components/octoprint/sensor.py deleted file mode 100644 index 7b31d70..0000000 --- a/custom_components/octoprint/sensor.py +++ /dev/null @@ -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.
" - "If you do not want to have your printer on
" - " at all times, and you would like to monitor
" - "temperatures, please add
" - "bed and/or number_of_tools to your configuration
" - "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 \ No newline at end of file diff --git a/logging.yaml b/logging.yaml index 56ad88f..7428f32 100644 --- a/logging.yaml +++ b/logging.yaml @@ -17,6 +17,7 @@ logs: homeassistant.exceptions: warning homeassistant.helpers.script: warning homeassistant.helpers.entity: warning + homeassistant.helpers.template: critical homeassistant.components.wemo: critical homeassistant.components.sensor: critical homeassistant.components.cloud.iot: warning @@ -24,7 +25,7 @@ logs: homeassistant.components.camera: warning homeassistant.components.zwave: critical homeassistant.components.image_processing: warning - homeassistant.components.homekit: warning + homeassistant.components.homekit: error custom_components.sensor.life360: warning custom_components.sensor.paloalto: warning homeassistant.components.recorder: warning diff --git a/lovelace/00_myhome_view.yaml b/lovelace/00_myhome_view.yaml index cc9154c..f911173 100644 --- a/lovelace/00_myhome_view.yaml +++ b/lovelace/00_myhome_view.yaml @@ -52,8 +52,6 @@ cards: name: Srinika - entity: device_tracker.life360_hasika name: Hasika - - entity: device_tracker.mahasri_tesla_location_tracker - name: Tesla - entity: sensor.yo_mama_geocoded_location name: Suresh - entity: sensor.mallika_geocoded_location @@ -77,7 +75,6 @@ cards: title: 3D Printer show_header_toggle: false entities: - - sensor.octoprint_file - binary_sensor.octoprint_printing - binary_sensor.octoprint_printing_error - sensor.octoprint_current_state diff --git a/lovelace/02_climate_view.yaml b/lovelace/02_climate_view.yaml index 3e433dd..2f06ee6 100644 --- a/lovelace/02_climate_view.yaml +++ b/lovelace/02_climate_view.yaml @@ -25,7 +25,6 @@ cards: show_header_toggle: false entities: - climate.dining_room - - climate.tesla_model_3_hvac_climate_system - binary_sensor.dining_room_thermostat_fan - binary_sensor.dining_room_thermostat_has_leaf - binary_sensor.dining_room_thermostat_is_locked diff --git a/lovelace/06_tesla_view.yaml b/lovelace/06_tesla_view.yaml index ecba62e..afaaf70 100644 --- a/lovelace/06_tesla_view.yaml +++ b/lovelace/06_tesla_view.yaml @@ -8,7 +8,7 @@ cards: - type: gauge name: Tesla Battery unit: "%" - entity: sensor.tesla_model_3_battery_sensor + entity: sensor.mahasri_tesla_battery_sensor severity: green: 75 yellow: 40 @@ -16,7 +16,7 @@ cards: - type: gauge name: Battery Range unit: "miles" - entity: sensor.tesla_model_3_range_sensor + entity: sensor.mahasri_tesla_range_sensor max: 320 min: 0 severity: @@ -24,15 +24,15 @@ cards: yellow: 100 red: 75 - type: thermostat - entity: climate.tesla_model_3_hvac_climate_system + entity: climate.mahasri_tesla_hvac_climate_system - type: horizontal-stack cards: - type: sensor - entity: sensor.tesla_model_3_temperature_sensor_inside + entity: sensor.mahasri_tesla_temperature_sensor_inside name: Temperature Inside graph: line - type: sensor - entity: sensor.tesla_model_3_temperature_sensor_outside + entity: sensor.mahasri_tesla_temperature_sensor_outside name: Temperature outside graph: line @@ -42,22 +42,31 @@ cards: entities: - device_tracker.mahasri_tesla_location_tracker - binary_sensor.mahasri_tesla_online_sensor - - binary_sensor.tesla_model_3_parking_brake_sensor - - lock.tesla_model_3_door_lock - - sensor.tesla_model_3_mileage_sensor - - switch.tesla_model_3_update_switch - - lock.tesla_model_3_charger_door_lock + - binary_sensor.mahasri_tesla_parking_brake_sensor + - lock.mahasri_tesla_door_lock + - sensor.mahasri_tesla_mileage_sensor + - switch.mahasri_tesla_update_switch + - lock.mahasri_tesla_charger_door_lock - sensor.mahasri_tesla_charging_rate_sensor - - sensor.tesla_model_3_battery_sensor - - sensor.tesla_model_3_range_sensor - - sensor.tesla_model_3_temperature_sensor_inside - - sensor.tesla_model_3_temperature_sensor_outside + - sensor.mahasri_tesla_battery_sensor + - sensor.mahasri_tesla_range_sensor + - sensor.mahasri_tesla_temperature_sensor_inside + - sensor.mahasri_tesla_temperature_sensor_outside - switch.mahasri_tesla_sentry_mode_switch - type: entities title: Charging show_header_toggle: false entities: - - binary_sensor.tesla_model_3_charger_sensor - - switch.tesla_model_3_charger_switch - - switch.tesla_model_3_maxrange_switch + - binary_sensor.mahasri_tesla_charger_sensor + - switch.mahasri_tesla_charger_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 diff --git a/lovelace/15_3d_printer.yaml b/lovelace/15_3d_printer.yaml index 239f36e..100b53b 100644 --- a/lovelace/15_3d_printer.yaml +++ b/lovelace/15_3d_printer.yaml @@ -26,7 +26,6 @@ cards: title: Octoprint show_header_toggle: false entities: - - sensor.octoprint_file - binary_sensor.octoprint_printing - sensor.octoprint_current_state - binary_sensor.octoprint_printing_error diff --git a/packages/batteries.yaml b/packages/batteries.yaml index b7d0656..40b04e4 100644 --- a/packages/batteries.yaml +++ b/packages/batteries.yaml @@ -407,31 +407,31 @@ automation: 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 diff --git a/packages/cameras.yaml b/packages/cameras.yaml index ef1d217..e82ce7b 100644 --- a/packages/cameras.yaml +++ b/packages/cameras.yaml @@ -717,6 +717,10 @@ automation: (states.binary_sensor.motion_sensor_158d00024ee084.last_updated ~ '').replace('-','_') .replace(' ', '_').replace(':','_').replace('.','_').replace('+','_') ~ '.jpg' }}" 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 data_template: @@ -733,6 +737,9 @@ automation: - "{{ '/config/www/downloads/camera/garage/garage_' ~ (states.binary_sensor.motion_sensor_158d00024ee084.last_updated ~ '').replace('-','_') .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 value_template: "{{ states('device_tracker.life360_suresh') == 'home' }}" diff --git a/packages/homesecurity.yaml b/packages/homesecurity.yaml index deded29..bcfea65 100644 --- a/packages/homesecurity.yaml +++ b/packages/homesecurity.yaml @@ -210,7 +210,6 @@ automation: # A gentle 10 minute reminder that the Home Security system is OFF ############################################################################### - alias: Home Security System WatchDog 10 minutes - initial_state: true trigger: - platform: state entity_id: @@ -227,7 +226,6 @@ automation: # A gentle reminder that the home security is OFF for more than 30 minutes ############################################################################### - alias: Home Security System WatchDog 30 minutes - initial_state: true trigger: - platform: state entity_id: diff --git a/packages/lights_switches.yaml b/packages/lights_switches.yaml index c3ea408..b79dbbe 100644 --- a/packages/lights_switches.yaml +++ b/packages/lights_switches.yaml @@ -110,6 +110,7 @@ tplink: #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: diff --git a/packages/notify.yaml b/packages/notify.yaml index 421c3ed..f48e732 100644 --- a/packages/notify.yaml +++ b/packages/notify.yaml @@ -65,5 +65,6 @@ telegram_bot: # Add Polling - platform: polling api_key: !secret telegram_apikey + parse_mode: html allowed_chat_ids: - !secret telegram_chatid diff --git a/packages/weather.yaml b/packages/weather.yaml index 2a8eb0a..c60e62b 100644 --- a/packages/weather.yaml +++ b/packages/weather.yaml @@ -148,7 +148,7 @@ sensor: value_template: "{{value_json.Location.periods[1].Index}}" scan_interval: 21600 headers: - Referer: "https://www.pollen.com" + Referer: !secret weather_pollen_url - platform: rest name: cold_flu @@ -156,7 +156,7 @@ sensor: value_template: "{{value_json.Location.periods[0].Index}}" scan_interval: 21600 headers: - Referer: "https://www.pollen.com" + Referer: !secret weather_pollen_url ############################################################################### # _ _ _ diff --git a/templates/away_status.yaml b/templates/away_status.yaml index 9eeb38f..dc7e602 100644 --- a/templates/away_status.yaml +++ b/templates/away_status.yaml @@ -34,12 +34,6 @@ {%- endif -%} {%- endmacro -%} - {%- macro pollen_levels() -%} - {% if states('sensor.pollen_level') != 'unknown' %} - Pollen level is {{ states('sensor.pollen_level') }}. - {% endif %} - {%- endmacro -%} - {%- macro humidity_status() -%} Home humidity is {{ states('sensor.dining_room_thermostat_humidity') }} percent. {%- endmacro -%} @@ -83,21 +77,10 @@ {% endfor %} {%- endmacro -%} - {%- macro light_status() -%} - {%- set lights_switches = ["switch.basement_left", - "switch.basement_right", - "switch.frontyard_light", - "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 -%} + {%- macro light_switch_status() -%} + {% for item in states if item.domain =="light" or item.domain == "switch" -%} + {%- if item.state == "on" -%} + {%- set friendly_name = item.attributes.friendly_name -%} {{ friendly_name }} {{ 'are' if plural(friendly_name) == "true" else 'is' }} ON. {% endif %} {%- endfor -%} @@ -106,14 +89,10 @@ {%- macro mother_of_all_macros() -%} {{ alarm_status() }} {{ garage_status() }} - {{ USPS() }} - {{ tesla_status() }} {{ weather_update() }} {{ humidity_status() }} {{ uv_levels() }} - {{ pollen_levels() }} - {{ alert_battery_levels() }} - {{ light_status() }} + {{ light_switch_status() }} {%- endmacro -%} {{- cleanup(mother_of_all_macros()) -}}