Skip to content

Commit

Permalink
Added area triggered by sensors
Browse files Browse the repository at this point in the history
  • Loading branch information
rainepretorius committed Oct 23, 2023
1 parent 4109ca4 commit 7dc208d
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 19 deletions.
4 changes: 3 additions & 1 deletion custom_components/olarm_sensors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
import os
import re

from olarm_api_rainepretorius import OlarmApi, OlarmSetupApi
import voluptuous as vol

from homeassistant.components.alarm_control_panel import (
DOMAIN as ALARM_CONTROL_PANEL_DOMAIN,
)
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
from homeassistant.components.update import DOMAIN as UPDATE_DOMAIN
from homeassistant.config_entries import ConfigEntry
Expand All @@ -32,13 +34,13 @@
APIForbiddenError,
DictionaryKeyError,
)
from .olarm_api import OlarmApi, OlarmSetupApi

path = os.path.abspath(__file__).replace("__init__.py", "")
PLATFORMS = [
ALARM_CONTROL_PANEL_DOMAIN,
BINARY_SENSOR_DOMAIN,
BUTTON_DOMAIN,
SENSOR_DOMAIN,
SWITCH_DOMAIN,
UPDATE_DOMAIN,
]
Expand Down
36 changes: 26 additions & 10 deletions custom_components/olarm_sensors/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
import asyncio
from typing import Any

import voluptuous as vol
from olarm_api_rainepretorius import OlarmSetupApi # type: ignore[import-untyped]
import voluptuous as vol # type: ignore[import-untyped]

from homeassistant.config_entries import ConfigEntry, ConfigFlow, OptionsFlow
from homeassistant.const import CONF_API_KEY, CONF_SCAN_INTERVAL
Expand All @@ -23,7 +24,6 @@
)
from .coordinator import OlarmCoordinator
from .exceptions import APIForbiddenError
from .olarm_api import OlarmSetupApi


class OlarmSensorsConfigFlow(ConfigFlow, domain=DOMAIN):
Expand Down Expand Up @@ -65,15 +65,31 @@ async def async_step_user(self, user_input=None) -> FlowResult:
else:
alarm_code = user_input[CONF_ALARM_CODE]

try:
api = OlarmSetupApi(api_key)
json = await api.get_olarm_devices()
if api_key not in ("mock_api_key", ""):
try:
api = OlarmSetupApi(api_key)
json = await api.get_olarm_devices()

except APIForbiddenError:
LOGGER.warning(
"User entered invalid credentials or API access is not enabled!"
)
errors[AUTHENTICATION_ERROR] = "Invalid credentials!"
except APIForbiddenError:
LOGGER.warning(
"User entered invalid credentials or API access is not enabled!"
)
errors[AUTHENTICATION_ERROR] = "Invalid credentials!"
else:
json = [
{
"deviceName": "Device1",
"deviceFirmware": "1.0",
"deviceId": "123",
"deviceAlarmType": "Paradox",
},
{
"deviceName": "Device2",
"deviceFirmware": "1.1",
"deviceId": "124",
"deviceAlarmType": "IDS",
},
]

if json is None:
errors[AUTHENTICATION_ERROR] = "Invalid credentials!"
Expand Down
8 changes: 5 additions & 3 deletions custom_components/olarm_sensors/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@
from datetime import datetime, timedelta
import time

from olarm_api_rainepretorius import OlarmApi, OlarmUpdateAPI

from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_API_KEY, CONF_SCAN_INTERVAL
from homeassistant.core import HomeAssistant
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator

from .const import DOMAIN, LOGGER, TempEntry
from .exceptions import APIContentTypeError, ClientConnectorError
from .olarm_api import OlarmApi, OlarmUpdateAPI


class OlarmCoordinator(DataUpdateCoordinator):
Expand All @@ -26,6 +27,7 @@ class OlarmCoordinator(DataUpdateCoordinator):
device_json: dict = {}
release_data: dict = {}
device_firmware: str
area_triggers: list[str] = ["", "", "", "", "", "", "", ""]

def __init__(
self,
Expand Down Expand Up @@ -66,8 +68,8 @@ def __init__(
self.bypass_state: list = []
self.ukey_data: list = []
self.pgm_data: list = []
self.area_changes: list = [{}, {}, {}, {}, {}, {}, {}, {}]
self.area_triggers: list = [None, None, None, None, None, None, None, None]
self.area_changes: list[dict] = [{}, {}, {}, {}, {}, {}, {}, {}]
self.area_triggers: list = ["", "", "", "", "", "", "", ""]

# Setting the device info.
self.olarm_device_name: str = device_name
Expand Down
3 changes: 2 additions & 1 deletion custom_components/olarm_sensors/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
"codeowners": ["@rainepretorius"],
"config_flow": true,
"dependencies": [],
"version": "2.2.6",
"documentation": "https://github.com/rainepretorius/olarm-ha-integration/blob/main/README.md",
"iot_class": "cloud_polling",
"issue_tracker": "https://github.com/rainepretorius/olarm-ha-integration/issues",
"quality_scale": "silver",
"requirements": ["aiohttp==3.8.5"]
"requirements": ["olarm-api-rainepretorius==1.0.0"]
}
140 changes: 140 additions & 0 deletions custom_components/olarm_sensors/sensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
"""Platform for binary sensor integration."""
from __future__ import annotations

from homeassistant.components.sensor import SensorEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from .const import CONF_DEVICE_FIRMWARE, CONF_OLARM_DEVICES, DOMAIN, LOGGER, VERSION
from .coordinator import OlarmCoordinator


async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Handle the setup of the platform."""
entities = []
for device in hass.data[DOMAIN]["devices"]:
if device["deviceName"] not in entry.data[CONF_OLARM_DEVICES]:
continue

# Getting the instance of the DataCoordinator to update the data from Olarm.
coordinator: OlarmCoordinator = hass.data[DOMAIN][device["deviceId"]]
await coordinator.update_data()

for panel in coordinator.panel_state:
name = panel["name"] + " Trigger"
sensor = OlarmTriggerSensor(
area=panel["area_number"],
area_name=name,
coordinator=coordinator,
hass=hass,
)

entities.append(sensor)

LOGGER.info(
"Adding Olarm Alarm Trigger Sensors for device (%s)",
coordinator.olarm_device_name,
)

async_add_entities(entities)
LOGGER.info("Added Olarm Alarm Trigger Sensors")


class OlarmTriggerSensor(SensorEntity):
"""Alarm Trigger Sensor."""

area: int = 0
area_name: str
coordinator: OlarmCoordinator
hass: HomeAssistant

def __init__(
self,
area: int,
area_name: str,
coordinator: OlarmCoordinator,
hass: HomeAssistant,
) -> None:
"""Initialize the trigger sensor."""
super().__init__()
self.hass = hass
self.area = area - 1
self.area_name = area_name
self.coordinator = coordinator

@property
def native_value(self) -> str | None:
"""Return the state of the trigger platforms."""
self.coordinator: OlarmCoordinator = self.hass.data[DOMAIN][
self.coordinator.olarm_device_id
]
try:
area_triggers = self.coordinator.area_triggers[self.area]
if area_triggers and area_triggers != "":
index = int(
str(area_triggers)
.split(" ", maxsplit=1)[0]
.split(",", maxsplit=1)[0]
)
return self.coordinator.sensor_data[index - 1]["name"]

return area_triggers

except (TypeError, IndexError):
return None

async def async_added_to_hass(self) -> None:
"""Write the state of the sensor to Home Assistant."""
self.async_on_remove(
self.coordinator.async_add_listener(self.async_write_ha_state)
)

@property
def unique_id(self) -> str:
"""The unique id for this entity sothat it can be managed from the ui."""
return f"{self.coordinator.olarm_device_id}_area_trigger_{self.area}".replace(
" ", "_"
).lower()

@property
def name(self) -> str:
"""The name of the zone from the Alarm Panel."""
name = []
name1 = self.area_name.replace("_", " ")
for item in str(name1).lower().split(" "):
name.append(str(item).capitalize())
return " ".join(name) + " (" + self.coordinator.olarm_device_name + ") Triggers"

@property
def icon(self) -> str:
"""Return the icon."""
return "mdi:alarm-bell"

@property
def should_poll(self) -> bool:
"""Disable polling. Integration will notify Home Assistant on sensor value update."""
return False

@property
def device_info(self) -> DeviceInfo:
"""Return device information about this entity."""
return DeviceInfo(
manufacturer="Raine Pretorius",
name=f"Olarm Sensors ({self.coordinator.olarm_device_name})",
model=self.coordinator.olarm_device_make,
identifiers={(DOMAIN, self.coordinator.olarm_device_id)},
sw_version=VERSION,
hw_version=self.coordinator.entry.data[CONF_DEVICE_FIRMWARE],
)

@callback
def _handle_coordinator_update(self) -> None:
"""Handle updated data from the coordinator."""
self.coordinator: OlarmCoordinator = self.hass.data[DOMAIN][
self.coordinator.olarm_device_id
]
self.async_write_ha_state()
26 changes: 22 additions & 4 deletions custom_components/olarm_sensors/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,22 +47,40 @@ def name(self) -> str:
@property
def latest_version(self) -> str | None:
"""Latest version available for install."""
return self.hass.data[DOMAIN]["release_data"]["name"].split(" ")[1]
try:
return self.hass.data[DOMAIN]["release_data"]["name"].split(" ")[1]

except KeyError:
return None

@property
def title(self) -> str | None:
"""Return update name."""
return self.hass.data[DOMAIN]["release_data"]["name"]
try:
return self.hass.data[DOMAIN]["release_data"]["name"]

except KeyError:
return None

@property
def release_summary(self) -> str | None:
"""Return release summary."""
return self.hass.data[DOMAIN]["release_data"]["body"].split("\n", maxsplit=1)[0]
try:
return self.hass.data[DOMAIN]["release_data"]["body"].split(
"\n", maxsplit=1
)[0]

except KeyError:
return None

@property
def release_url(self) -> str | None:
"""The url of the release."""
return self.hass.data[DOMAIN]["release_data"]["url"]
try:
return self.hass.data[DOMAIN]["release_data"]["url"]

except KeyError:
return None

def install(self, version: str | None, backup: bool, **kwargs: Any) -> None:
"""Install an update.
Expand Down

0 comments on commit 7dc208d

Please sign in to comment.