Skip to content

Commit

Permalink
Auto reboot feature
Browse files Browse the repository at this point in the history
  • Loading branch information
ldotlopez committed Mar 15, 2023
1 parent e2b1682 commit d17797e
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 37 deletions.
7 changes: 7 additions & 0 deletions config/configuration.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
default_config:

logger:
default: warning
logs:
hnap: debug
custom_components.hnap_device: debug
1 change: 1 addition & 0 deletions config/custom_components
10 changes: 8 additions & 2 deletions custom_components/hnap_device/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,21 @@
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
hass.data[DOMAIN] = hass.data.get(DOMAIN, {})

def get_api():
def get_device():
client = hnap.soapclient.SoapClient(
hostname=entry.data[CONF_HOST],
password=entry.data[CONF_PASSWORD],
username=entry.data[CONF_USERNAME],
)
return hnap.DeviceFactory(client=client)

hass.data[DOMAIN][entry.entry_id] = await hass.async_add_executor_job(get_api)
def get_device_info(device):
return device.client.device_info()

device = await hass.async_add_executor_job(get_device)
device_info = await hass.async_add_executor_job(get_device_info, device)

hass.data[DOMAIN][entry.entry_id] = device, device_info

await hass.config_entries.async_forward_entry_setups(
entry, entry.data[CONF_PLATFORMS]
Expand Down
15 changes: 7 additions & 8 deletions custom_components/hnap_device/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,24 +33,23 @@
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import DiscoveryInfoType


from .const import DOMAIN, PLATFORM_BINARY_SENSOR
from .const import CONF_AUTO_REBOOT, DOMAIN, PLATFORM_BINARY_SENSOR
from .entity import HNapEntity

PLATFORM = PLATFORM_BINARY_SENSOR

SENSOR_DOMAIN = "sensor"
_LOGGER = logging.getLogger(__name__)


class HNAPMotion(HNapEntity, BinarySensorEntity):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs, name="motion")
super().__init__(*args, **kwargs, name="motion", domain=SENSOR_DOMAIN)

self._attr_device_class = BinarySensorDeviceClass.MOTION

def update(self):
try:
self._attr_is_on = self._api.is_active()
self._attr_is_on = self.device.is_active()
self.hnap_update_success()

except (
Expand All @@ -68,15 +67,15 @@ async def async_setup_entry(
add_entities: AddEntitiesCallback,
discovery_info: Optional[DiscoveryInfoType] = None, # noqa DiscoveryInfoType | None
):
api = hass.data[DOMAIN][config_entry.entry_id]
device_info = await hass.async_add_executor_job(api.client.device_info)
device, device_info = hass.data[DOMAIN][config_entry.entry_id]

add_entities(
[
HNAPMotion(
unique_id=f"{config_entry.entry_id}-{PLATFORM}",
device_info=device_info,
api=api,
device=device,
auto_reboot=config_entry.data[CONF_AUTO_REBOOT],
)
],
update_before_add=True,
Expand Down
4 changes: 4 additions & 0 deletions custom_components/hnap_device/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
PLATFORM_CAMERA,
PLATFORM_SIREN,
DEFAULT_USERNAME,
CONF_AUTO_REBOOT,
DEFAULT_AUTO_REBOOT,
)

_LOGGER = logging.getLogger(__name__)
Expand All @@ -49,6 +51,7 @@
vol.Required(CONF_HOST): str,
vol.Required(CONF_USERNAME, default=DEFAULT_USERNAME): str,
vol.Required(CONF_PASSWORD): str,
vol.Required(CONF_AUTO_REBOOT, default=DEFAULT_AUTO_REBOOT): bool,
}
)

Expand Down Expand Up @@ -94,6 +97,7 @@ async def validate_input(hass: HomeAssistant, data: dict[str, Any]) -> dict[str,
CONF_PASSWORD: data[CONF_PASSWORD],
CONF_USERNAME: data[CONF_USERNAME],
CONF_PLATFORMS: platforms,
CONF_AUTO_REBOOT: data[CONF_AUTO_REBOOT],
}


Expand Down
2 changes: 2 additions & 0 deletions custom_components/hnap_device/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,5 @@
MAX_FAILURES_BEFORE_UNAVAILABLE = 3
MAX_UPTIME_BEFORE_REBOOT = 60 * 60 * 12 # 12 hours
DEFAULT_USERNAME = "admin"
DEFAULT_AUTO_REBOOT = False
CONF_AUTO_REBOOT = "auto_reboot"
36 changes: 22 additions & 14 deletions custom_components/hnap_device/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,32 +18,38 @@
# USA.


from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity import DeviceInfo, Entity

from hnap import Device as HNapDevice
import time

from homeassistant.helpers.entity_registry import slugify

from .const import MAX_FAILURES_BEFORE_UNAVAILABLE, MAX_UPTIME_BEFORE_REBOOT
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC
import logging

_LOGGER = logging.getLogger(__name__)


class HNapEntity:
class HNapEntity(Entity):
def __init__(
self,
*args,
domain: str,
unique_id: str,
device_info: dict[str, str],
api: HNapDevice,
device: HNapDevice,
name: str,
**kwargs
auto_reboot=True,
**kwargs,
):
super().__init__(*args, **kwargs)

self._attr_unique_id = unique_id

part = slugify(f"{device_info['DeviceName']}_{name}")
self._attr_entity_id = f"{domain}.{part}"

self._attr_device_info = DeviceInfo(
identifiers={
("mac", device_info["DeviceMacId"]),
Expand All @@ -59,23 +65,25 @@ def __init__(
self._attr_entity_registry_visible_default = True
self._attr_entity_registry_enabled_default = True

self._api = api
self.device = device

self._consecutive_failures = 0
self._boot_ts = time.monotonic()
self._auto_reboot = auto_reboot

def hnap_update_success(self):
self._consecutive_failures = 0

# Automatic reboot is still experimental
#
# uptime = time.monotonic() - self._boot_ts
# _LOGGER.debug(f"Device uptime: {uptime:.2f}/{MAX_UPTIME_BEFORE_REBOOT}")
if self._auto_reboot:
uptime = time.monotonic() - self._boot_ts
_LOGGER.debug(
f"{self.entity_id}: device uptime {uptime:.2f}s / {MAX_UPTIME_BEFORE_REBOOT}s"
)

# if self.available and uptime > MAX_UPTIME_BEFORE_REBOOT:
# _LOGGER.debug("Device must be rebooted")
# self.device.client.call("Reboot")
# self._boot_ts = time.monotonic()
if self.available and uptime > MAX_UPTIME_BEFORE_REBOOT:
_LOGGER.debug("Device must be rebooted")
self.device.client.call("Reboot")
self._boot_ts = time.monotonic()

def hnap_update_failure(self):
self._consecutive_failures = self._consecutive_failures + 1
Expand Down
4 changes: 0 additions & 4 deletions custom_components/hnap_device/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@
"config_flow" : true,
"dependencies" : [],
"dhcp" : [
{
"hostname" : "c200_*",
"macaddress" : "000AEB*"
}
],
"documentation" : "https://github.com/ldotlopez/ha-hnap-device",
"homekit" : {},
Expand Down
18 changes: 10 additions & 8 deletions custom_components/hnap_device/siren.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,17 @@
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import DiscoveryInfoType

from .const import DOMAIN, PLATFORM_SIREN
from .const import CONF_AUTO_REBOOT, DOMAIN, PLATFORM_SIREN
from .entity import HNapEntity

PLATFORM = PLATFORM_SIREN
SIREN_DOMAIN = "siren"
_LOGGER = logging.getLogger(__name__)


class HNAPSiren(HNapEntity, SirenEntity):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs, name="siren")
super().__init__(*args, **kwargs, name="siren", domain=SIREN_DOMAIN)
self._attr_is_on = False
self._attr_supported_features = (
SUPPORT_TURN_ON
Expand All @@ -62,7 +63,7 @@ def __init__(self, *args, **kwargs):

def update(self):
try:
self._attr_is_on = self._api.is_playing()
self._attr_is_on = self.device.is_playing()

except requests.exceptions.ConnectionError as e:
_LOGGER.error(e)
Expand All @@ -73,14 +74,14 @@ def update(self):
self.hnap_update_success()

def turn_on(self, volume_level=1, duration=15, tone="police") -> None:
self._api.play(
self.device.play(
sound=hnap.SirenSound.fromstring(tone),
volume=int(volume_level * 100),
duration=duration,
)

def turn_off(self) -> None:
self._api.stop()
self.device.stop()


async def async_setup_entry(
Expand All @@ -89,15 +90,16 @@ async def async_setup_entry(
add_entities: AddEntitiesCallback,
discovery_info: Optional[DiscoveryInfoType] = None, # noqa DiscoveryInfoType | None
):
api = hass.data[DOMAIN][config_entry.entry_id]
device_info = await hass.async_add_executor_job(api.client.device_info)
device = hass.data[DOMAIN][config_entry.entry_id]
device, device_info = hass.data[DOMAIN][config_entry.entry_id]

add_entities(
[
HNAPSiren(
unique_id=f"{config_entry.entry_id}-{PLATFORM}",
device_info=device_info,
api=api,
device=device,
auto_reboot=config_entry.data[CONF_AUTO_REBOOT],
)
],
update_before_add=True,
Expand Down
3 changes: 2 additions & 1 deletion custom_components/hnap_device/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"data": {
"host": "Host",
"password": "Password",
"username": "Username"
"username": "Username",
"auto_reboot": "Reboot device each 12 hours"
}
}
}
Expand Down

0 comments on commit d17797e

Please sign in to comment.