Skip to content

Commit

Permalink
Christmas
Browse files Browse the repository at this point in the history
  • Loading branch information
aneisch committed Jan 12, 2025
1 parent fb6ef35 commit b1a0847
Show file tree
Hide file tree
Showing 331 changed files with 10,651 additions and 235 deletions.
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[![Build Status](https://github.com/aneisch/home-assistant-config/actions/workflows/check-ha-release-compatibility.yml/badge.svg)](https://github.com/aneisch/home-assistant-config/actions)
[![GitHub last commit](https://img.shields.io/github/last-commit/aneisch/home-assistant-config)](https://github.com/aneisch/home-assistant-config/commits/master)
[![GitHub commit activity](https://img.shields.io/github/commit-activity/y/aneisch/home-assistant-config)](https://github.com/aneisch/home-assistant-config/graphs/commit-activity)
[![HA Version](https://img.shields.io/badge/Running%20Home%20Assistant%20-2025.1.0b9%20(Out%20of%20Date)-Red)](https://github.com/home-assistant/home-assistant/releases/latest)
[![HA Version](https://img.shields.io/badge/Running%20Home%20Assistant-2025.1.2%20(Latest)-brightgreen)](https://github.com/home-assistant/home-assistant/releases/latest)
<br><a href="https://www.buymeacoffee.com/aneisch" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-black.png" width="150px" height="35px" alt="Buy Me A Coffee" style="height: 35px !important;width: 150px !important;" ></a>

I do my best to keep [Home Assistant](https://github.com/home-assistant/home-assistant) on the [latest release](https://github.com/home-assistant/home-assistant/releases/latest). I'm heavily utilizing [AppDaemon](http://appdaemon.readthedocs.io/en/latest/) and [NodeRed](https://flows.nodered.org/node/node-red-contrib-home-assistant-websocket) for advanced/templated automations. See [Appdaemon config](https://github.com/aneisch/home-assistant-config/tree/master/extras/appdaemon) and my NodeRed screenshots below for details. Most of my setup is run as Docker containers (see [docker-compose](https://github.com/aneisch/home-assistant-config/tree/master/extras/docker-compose) for container list).
Expand Down Expand Up @@ -59,17 +59,17 @@ Home Assistant and other containers have ingress handled automatically by [Traef
Description | value
-- | --
Lines of ESPHome YAML | 3301
Lines of Home Assistant YAML | 11025
Lines of Home Assistant YAML | 11067
[Integrations](https://www.home-assistant.io/integrations/) in use | 68
Zigbee devices in [`zha`](https://www.home-assistant.io/integrations/zha/) | 26
Z-Wave devices in [`zwave_js`](https://www.home-assistant.io/integrations/zwave_js/) | 37

Description | value
-- | --
Entities in the [`automation`](https://www.home-assistant.io/components/automation) domain | 140
Entities in the [`binary_sensor`](https://www.home-assistant.io/components/binary_sensor) domain | 183
Entities in the [`button`](https://www.home-assistant.io/components/button) domain | 68
Entities in the [`camera`](https://www.home-assistant.io/components/camera) domain | 15
Entities in the [`automation`](https://www.home-assistant.io/components/automation) domain | 141
Entities in the [`binary_sensor`](https://www.home-assistant.io/components/binary_sensor) domain | 192
Entities in the [`button`](https://www.home-assistant.io/components/button) domain | 67
Entities in the [`camera`](https://www.home-assistant.io/components/camera) domain | 16
Entities in the [`climate`](https://www.home-assistant.io/components/climate) domain | 1
Entities in the [`conversation`](https://www.home-assistant.io/components/conversation) domain | 3
Entities in the [`counter`](https://www.home-assistant.io/components/counter) domain | 1
Expand All @@ -94,8 +94,8 @@ Entities in the [`person`](https://www.home-assistant.io/components/person) doma
Entities in the [`plant`](https://www.home-assistant.io/components/plant) domain | 1
Entities in the [`remote`](https://www.home-assistant.io/components/remote) domain | 4
Entities in the [`script`](https://www.home-assistant.io/components/script) domain | 54
Entities in the [`select`](https://www.home-assistant.io/components/select) domain | 6
Entities in the [`sensor`](https://www.home-assistant.io/components/sensor) domain | 617
Entities in the [`select`](https://www.home-assistant.io/components/select) domain | 8
Entities in the [`sensor`](https://www.home-assistant.io/components/sensor) domain | 622
Entities in the [`setter`](https://www.home-assistant.io/components/setter) domain | 1
Entities in the [`siren`](https://www.home-assistant.io/components/siren) domain | 1
Entities in the [`stt`](https://www.home-assistant.io/components/stt) domain | 1
Expand All @@ -108,7 +108,7 @@ Entities in the [`vacuum`](https://www.home-assistant.io/components/vacuum) doma
Entities in the [`wake_word`](https://www.home-assistant.io/components/wake_word) domain | 1
Entities in the [`weather`](https://www.home-assistant.io/components/weather) domain | 1
Entities in the [`zone`](https://www.home-assistant.io/components/zone) domain | 8
**Total state objects** | **1678**
**Total state objects** | **1695**
## The HACS integrations/plugins that I use:

**Appdaemon**:<br>
Expand Down
4 changes: 3 additions & 1 deletion configuration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ homeassistant:
alexa: !include packages/alexa.yaml
#aarlo: !include packages/aarlo.yaml
aquarium: !include packages/aquarium.yaml
christmas: !include packages/christmas.yaml
# Start Christmas
#christmas: !include packages/christmas.yaml
# End Christmas
# covid: !include packages/covid.yaml
frigate: !include packages/frigate.yaml
door_otp: !include packages/door_otp.yaml
Expand Down
2 changes: 1 addition & 1 deletion custom_components/bhyve/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ async def async_update_callback(data):
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
entry.async_on_unload(entry.add_update_listener(update_listener))

hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, client.stop())
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, client.stop)

return True

Expand Down
2 changes: 1 addition & 1 deletion custom_components/bhyve/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"documentation": "https://github.com/sebr/bhyve-home-assistant/blob/main/README.md",
"iot_class": "cloud_push",
"requirements": [],
"version": "3.2.4"
"version": "3.2.5"
}
32 changes: 21 additions & 11 deletions custom_components/bhyve/sensor.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
"""Support for Orbit BHyve sensors."""

import logging
from datetime import timedelta
import logging

from homeassistant.components.sensor import SensorDeviceClass, SensorStateClass
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_BATTERY_LEVEL
from homeassistant.const import ATTR_BATTERY_LEVEL, UnitOfTemperature
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.icon import icon_for_battery_level

from homeassistant.components.sensor import SensorDeviceClass

from . import BHyveDeviceEntity
from .const import (
CONF_CLIENT,
Expand Down Expand Up @@ -54,8 +53,17 @@ async def async_setup_entry(
for device in devices:
if device.get("type") == DEVICE_SPRINKLER:
sensors.append(BHyveStateSensor(hass, bhyve, device))
for zone in device.get("zones"):
sensors.append(BHyveZoneHistorySensor(hass, bhyve, device, zone))
all_zones = device.get("zones")
for zone in all_zones:
# if the zone doesn't have a name, set it to the device's name if there is only one (eg a hose timer)
zone_name = zone.get("name", None)
if zone_name is None:
zone_name = (
device.get("name") if len(all_zones) == 1 else "Unnamed Zone"
)
sensors.append(
BHyveZoneHistorySensor(hass, bhyve, device, zone, zone_name)
)

if device.get("battery", None) is not None:
sensors.append(BHyveBatterySensor(hass, bhyve, device))
Expand Down Expand Up @@ -165,7 +173,7 @@ def parse_battery_level(battery_data):
Otherwise, if the 'mv' attribute is present, the battery level is calculated as a percentage
based on the millivolts, assuming that 2x1.5V AA batteries are used. Note that AA batteries can
range from 1.2V to 1.7V depending on their chemistry, so the calculation may not be accurate
for all types of batteries. YMMV ¯\_(ツ)_/¯
for all types of batteries. YMMV
Args:
battery_data (dict): A dictionary containing the battery data.
Expand All @@ -187,13 +195,13 @@ def parse_battery_level(battery_data):
class BHyveZoneHistorySensor(BHyveDeviceEntity):
"""Define a BHyve sensor."""

def __init__(self, hass, bhyve, device, zone):
def __init__(self, hass, bhyve, device, zone, zone_name):
"""Initialize the sensor."""
self._history = None
self._zone = zone
self._zone_id = zone.get("station")

name = "{} zone history".format(zone.get("name", "Unknown"))
name = "{} zone history".format(zone_name)
_LOGGER.info("Creating history sensor: %s", name)

super().__init__(
Expand Down Expand Up @@ -335,9 +343,11 @@ def __init__(self, hass, bhyve, device):
)

def _setup(self, device):
self._state = device.get("status", {}).get("temp_f")
self._available = device.get("is_connected", False)
self._unit = "°F"
self._native_value = device.get("status", {}).get("temp_f")
self._native_unit_of_measurement = UnitOfTemperature.FAHRENHEIT
self._state_class = SensorStateClass.MEASUREMENT

self._attrs = {
"location": device.get("location_name"),
"rssi": device.get("status", {}).get("rssi"),
Expand Down
1 change: 1 addition & 0 deletions custom_components/frigate/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
# Unit of measurement
FPS = "fps"
MS = "ms"
S = "s"

# Attributes
ATTR_CLIENT = "client"
Expand Down
1 change: 1 addition & 0 deletions custom_components/frigate/icons.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
ICON_SERVER = "mdi:server"
ICON_SPEEDOMETER = "mdi:speedometer"
ICON_WAVEFORM = "mdi:waveform"
ICON_UPTIME = "mdi:clock-time-five"

ICON_DEFAULT_ON = "mdi:home"

Expand Down
2 changes: 1 addition & 1 deletion custom_components/frigate/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@
"iot_class": "local_push",
"issue_tracker": "https://github.com/blakeblackshear/frigate-hass-integration/issues",
"requirements": ["hass-web-proxy-lib==0.0.7"],
"version": "5.6.0"
"version": "5.7.0"
}
60 changes: 59 additions & 1 deletion custom_components/frigate/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@
get_frigate_entity_unique_id,
get_zones,
)
from .const import ATTR_CONFIG, ATTR_COORDINATOR, DOMAIN, FPS, MS, NAME
from .const import ATTR_CONFIG, ATTR_COORDINATOR, DOMAIN, FPS, MS, NAME, S
from .icons import (
ICON_CORAL,
ICON_SERVER,
ICON_SPEEDOMETER,
ICON_UPTIME,
ICON_WAVEFORM,
get_icon_from_type,
)
Expand Down Expand Up @@ -104,6 +105,7 @@ async def async_setup_entry(
]
)
entities.append(FrigateStatusSensor(coordinator, entry))
entities.append(FrigateUptimeSensor(coordinator, entry))
async_add_entities(entities)


Expand Down Expand Up @@ -207,6 +209,62 @@ def icon(self) -> str:
return ICON_SERVER


class FrigateUptimeSensor(
FrigateEntity, CoordinatorEntity[FrigateDataUpdateCoordinator]
):
"""Frigate Uptime Sensor class."""

_attr_entity_category = EntityCategory.DIAGNOSTIC
_attr_name = "Uptime"

def __init__(
self, coordinator: FrigateDataUpdateCoordinator, config_entry: ConfigEntry
) -> None:
"""Construct a FrigateUptimeSensor."""
FrigateEntity.__init__(self, config_entry)
CoordinatorEntity.__init__(self, coordinator)
self._attr_entity_registry_enabled_default = False

@property
def unique_id(self) -> str:
"""Return a unique ID to use for this entity."""
return get_frigate_entity_unique_id(
self._config_entry.entry_id, "uptime", "frigate"
)

@property
def device_info(self) -> DeviceInfo:
"""Get device information."""
return {
"identifiers": {get_frigate_device_identifier(self._config_entry)},
"name": NAME,
"model": self._get_model(),
"configuration_url": self._config_entry.data.get(CONF_URL),
"manufacturer": NAME,
}

@property
def state(self) -> int | None:
"""Return the state of the sensor."""
if self.coordinator.data:
data = self.coordinator.data.get("service", {}).get("uptime", 0)
try:
return int(data)
except (TypeError, ValueError):
pass
return None

@property
def unit_of_measurement(self) -> str:
"""Return the unit of measurement of the sensor."""
return S

@property
def icon(self) -> str:
"""Return the icon of the sensor."""
return ICON_UPTIME


class DetectorSpeedSensor(
FrigateEntity, CoordinatorEntity[FrigateDataUpdateCoordinator]
):
Expand Down
7 changes: 5 additions & 2 deletions custom_components/frigate/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from collections.abc import Mapping
import datetime
import logging
import os
from typing import Any, Optional, cast

from aiohttp import web
Expand Down Expand Up @@ -245,12 +246,14 @@ def _get_proxied_url(
url_path = f"api/events/{event_id}/snapshot.jpg"
elif path.endswith("clip.mp4"):
url_path = f"api/events/{event_id}/clip.mp4"
elif path.endswith("master.m3u8"):
url_path = f"vod/events/{event_id}/master.m3u8"
elif path.endswith("event_preview.gif"):
url_path = f"api/events/{event_id}/preview.gif"
elif path.endswith("review_preview.gif"):
url_path = f"api/review/{event_id}/preview"
elif path.endswith(".m3u8") or path.endswith(".ts"):
# Proxy event HLS requests to the vod module
file_name = os.path.basename(path)
url_path = f"vod/event/{event_id}/{file_name}"

if not url_path:
raise HASSWebProxyLibNotFoundRequestError
Expand Down
3 changes: 2 additions & 1 deletion custom_components/hacs/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,8 @@ class HacsOptionsFlowHandler(OptionsFlow):

def __init__(self, config_entry):
"""Initialize HACS options flow."""
self.config_entry = config_entry
if AwesomeVersion(HAVERSION) < "2024.11.99":
self.config_entry = config_entry

async def async_step_init(self, _user_input=None):
"""Manage the options."""
Expand Down
4 changes: 2 additions & 2 deletions custom_components/hacs/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
"lovelace",
"repairs"
],
"documentation": "https://hacs.xyz/docs/configuration/start",
"documentation": "https://hacs.xyz/docs/use/",
"iot_class": "cloud_polling",
"issue_tracker": "https://github.com/hacs/integration/issues",
"requirements": [
"aiogithubapi>=22.10.1"
],
"version": "2.0.1"
"version": "2.0.2"
}
2 changes: 1 addition & 1 deletion custom_components/hacs/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
}
},
"progress": {
"wait_for_device": "1. Open {url} \n2. Paste the following key to authorize HACS: \n```\n{code}\n```\n"
"wait_for_device": "1. Open {url} \n2. Paste the following key to authorize HACS: \n```\n{code}\n```"
}
},
"options": {
Expand Down
7 changes: 6 additions & 1 deletion custom_components/hacs/utils/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,13 @@ def async_restore_repository(self, entry: str, repository_data: dict[str, Any]):
if not repository:
return

try:
self.hacs.repositories.set_repository_id(repository, entry)
except ValueError as exception:
self.logger.warning("<HacsData async_restore_repository> duplicate IDs %s", exception)
return

# Restore repository attributes
self.hacs.repositories.set_repository_id(repository, entry)
repository.data.authors = repository_data.get("authors", [])
repository.data.description = repository_data.get("description", "")
repository.data.downloads = repository_data.get("downloads", 0)
Expand Down
Loading

0 comments on commit b1a0847

Please sign in to comment.