Skip to content

Commit

Permalink
Merge pull request #44 from theneweinstein/alarm_days
Browse files Browse the repository at this point in the history
Add custom alarm days
  • Loading branch information
theneweinstein authored Sep 30, 2023
2 parents 12efb07 + 2bb9111 commit 31fdddc
Show file tree
Hide file tree
Showing 11 changed files with 310 additions and 83 deletions.
3 changes: 3 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
# github: theneweinstein
ko_fi: theneweinstein
58 changes: 33 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,53 +1,61 @@
# Somneo custom component
Home Assistant custom component for Philips Someo. This integration let's you control the light of the Somneo and reads the following sensors: temperature, humidity, luminance and noise. Furthermore, it provides the alarms set on your Somneo instance as binary sensors and provides a sensor with the first upcoming alarm.
# Somneo custom integration
Home Assistant custom integration to control a Philips Somneo device. This integration let's you control:
- The light and nightlight of the Somneo
- All the 16 available alarms (toggle, time, days, powerwake)
- Media player of the Somneo (FM radio or aux. input)
- Snooze or ignore alarm (buttons)

Furthermore, it provides the following sensors:
- Ambient sensors (temperature, humidity, luminance and noise)
- Alarm status (on, off, snooze, wake-up)
- Next alarm

# Installation
You can install this custom component via HACS as a custom repository (https://hacs.xyz/docs/faq/custom_repositories/). Alternatively you can clone or copy the files into the somneo folder in the custom_components folder of HomeAssistant.

# Configuration
Go to: https://my.home-assistant.io/redirect/config_flow_start/?domain=somneo
The Somneo should be automatically detected via SSDP. If not, you can also manually configure the Somneo: https://my.home-assistant.io/redirect/config_flow_start/?domain=somneo.

# Alarm Configuration
### With slider-entity-row from HACS`
Add a "manual" card into lovelace UI and copy paste the following code. It will create a card for the first Somneo Alarm (alarm0).
# Alarm UI configuration
Add a "manual" card into lovelace UI and copy paste the following code. It will create a card for the first Somneo Alarm (alarm0).
Other cards can be created for other alarms (alarm1, alarm2, etc.)
```
type: entities
entities:
- entity: switch.somneo_alarm0
name: On/Off
- type: custom:slider-entity-row
entity: number.somneo_alarm0_hours
hide_state: false
name: Hours
- type: custom:slider-entity-row
entity: number.somneo_alarm0_minutes
hide_state: false
name: Minutes
- entity: time.somneo_alarm0_time
name: Time
- entity: select.somneo_alarm0_days
name: Days
- entity: switch.somneo_alarm0_powerwake
name: PowerWake
- entity: number.somneo_alarm0_powerwake_delay
name: PowerWake delay
title: Alarm work
show_header_toggle: false
```
<img src="https://github.com/theneweinstein/somneo/blob/master/lovelace1.jpg" alt="Example Lovelace Slider" width="80%"/>
<img src="https://github.com/theneweinstein/somneo/blob/master/lovelace1.jpg" alt="Example Lovelace" width="80%"/>

### Without slider-entity-row from HACS
# Custom alarm days

The select entity for the days only supports a limited set of days, namely weekdays, weekends, everyday and tomorrow. In case you want to select a different day for the alarm, you can use the text entity. The text contains a comma-seperated list (without white-spaces) of abbreviations of the day of the week (i.e. `mon,tue,wed,thu,fri,sat,sun`) or `tomorrow`.
```
type: entities
entities:
- entity: switch.somneo_alarm0
name: On/Off
- entity: number.somneo_alarm0_hours
name: Hours
- entity: number.somneo_alarm0_minutes
name: Minutes
- entity: select.somneo_alarm0_days
- entity: time.somneo_alarm0_time
name: Time
- entity: text.somneo_alarm0_days
name: Days
- entity: switch.somneo_alarm0_powerwake
name: PowerWake
- entity: number.somneo_alarm0_powerwake_delay
name: PowerWake delay
title: Alarm work
show_header_toggle: false
```
<img src="https://github.com/theneweinstein/somneo/blob/master/lovelace2.jpg" alt="Example Lovelace" width="80%"/>
<img src="https://github.com/theneweinstein/somneo/blob/master/lovelace2.jpg" alt="Example Lovelace with custom days" width="80%"/>


# Services
This component includes two services to adjust the wake-up light and sound settings. To adjust the light settings of an alarm you can call the following function:
Expand Down Expand Up @@ -85,4 +93,4 @@ target:
service: somneo.remove_alarm
target:
entity_id: switch.somneo_alarm0
```
```
49 changes: 31 additions & 18 deletions custom_components/somneo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
Platform.TIME,
Platform.BUTTON,
Platform.MEDIA_PLAYER,
Platform.TEXT
]
SCAN_INTERVAL = timedelta(seconds=60)

Expand Down Expand Up @@ -210,26 +211,38 @@ async def async_set_snooze_time(self, time):
async def async_set_alarm_day(self, alarm, day):
"""Set the day of the alarm."""
async with self.state_lock:
if day == WORKDAYS:
if type(day) == list:
await self.hass.async_add_executor_job(
self.somneo.set_alarm_workdays, alarm
)
self.somneo.set_alarm_days,
alarm,
day
)
_LOGGER.debug("Optie is werkday")
elif day == WEEKEND:
await self.hass.async_add_executor_job(
self.somneo.set_alarm_weekend, alarm
)
_LOGGER.debug("Optie is weekend")
elif day == TOMORROW:
await self.hass.async_add_executor_job(
self.somneo.set_alarm_tomorrow, alarm
)
_LOGGER.debug("Optie is morgen")
elif day == EVERYDAY:
await self.hass.async_add_executor_job(
self.somneo.set_alarm_everyday, alarm
)
_LOGGER.debug("Optie is elke dag")
else:
if day == WORKDAYS:
await self.hass.async_add_executor_job(
self.somneo.set_alarm_workdays,
alarm
)
_LOGGER.debug("Optie is werkday")
elif day == WEEKEND:
await self.hass.async_add_executor_job(
self.somneo.set_alarm_weekend,
alarm
)
_LOGGER.debug("Optie is weekend")
elif day == TOMORROW:
await self.hass.async_add_executor_job(
self.somneo.set_alarm_tomorrow,
alarm
)
_LOGGER.debug("Optie is morgen")
elif day == EVERYDAY:
await self.hass.async_add_executor_job(
self.somneo.set_alarm_everyday,
alarm
)
_LOGGER.debug("Optie is elke dag")

await self.async_request_refresh()

Expand Down
2 changes: 1 addition & 1 deletion custom_components/somneo/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
WEEKEND: Final = "weekend"
TOMORROW: Final = "tomorrow"
EVERYDAY: Final = "daily"
UNKNOWN: Final = "unknown"
CUSTOM: Final = "custom"
PW_DELTA: Final = "powerwake_delta"

ALARMS_ICON: Final = "hass:alarm"
Expand Down
8 changes: 4 additions & 4 deletions custom_components/somneo/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
"somneo"
],
"requirements": [
"pysomneo==3.0.1"
"pysomneo==3.1.3"
],
"ssdp": [
{
"nt": "urn:philips-com:device:DiProduct:1",
"modelName": "Wake-up Light"
"modelName": "Wake-up Light"
}
],
"version": "5.0.4"
}
"version": "5.1.0"
}
4 changes: 2 additions & 2 deletions custom_components/somneo/select.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.components.select import SelectEntity

from .const import DOMAIN, WORKDAYS, WEEKEND, TOMORROW, EVERYDAY, UNKNOWN, WORKDAYS_ICON
from .const import DOMAIN, WORKDAYS, WEEKEND, TOMORROW, EVERYDAY, CUSTOM, WORKDAYS_ICON
from .entity import SomneoEntity


Expand Down Expand Up @@ -42,7 +42,7 @@ class SomneoDays(SomneoEntity, SelectEntity):
_attr_icon = WORKDAYS_ICON
_attr_assumed_state = False
_attr_available = True
_attr_options = [WORKDAYS, WEEKEND, TOMORROW, EVERYDAY, UNKNOWN]
_attr_options = [WORKDAYS, WEEKEND, TOMORROW, EVERYDAY, CUSTOM]
_attr_current_option = WORKDAYS

def __init__(self, coordinator, unique_id, name, dev_info, alarm):
Expand Down
71 changes: 71 additions & 0 deletions custom_components/somneo/text.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
"""Text entities for Somneo."""
import logging
from typing import Any
import voluptuous as vol

from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_NAME
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.components.text import TextEntity
from homeassistant.helpers import config_validation as cv, entity_platform

from .const import (
DOMAIN,
WORKDAYS_ICON
)
from .entity import SomneoEntity


_LOGGER = logging.getLogger(__name__)


async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Add Somneo from config_entry."""

coordinator = hass.data[DOMAIN][config_entry.entry_id]
unique_id = config_entry.unique_id
assert unique_id is not None
name = config_entry.data[CONF_NAME]
device_info = config_entry.data["dev_info"]

alarms = []
for alarm in list(coordinator.data["alarms"]):
alarms.append(
SomneoAlarmDays(coordinator, unique_id, name, device_info, alarm)
)

async_add_entities(alarms, update_before_add=True)


class SomneoAlarmDays(SomneoEntity, TextEntity):
"""Representation of a alarm switch."""

_attr_should_poll = True
_attr_assumed_state = False
_attr_available = True
_attr_icon = WORKDAYS_ICON
_attr_native_value = None
_attr_pattern = "^((tomorrow|mon|tue|wed|thu|fri|sat|sun)(,)?)+$"

def __init__(self, coordinator, unique_id, name, device_info, alarm):
"""Initialize the switches."""
super().__init__(coordinator, unique_id, name, device_info, alarm)

self._attr_translation_key = alarm + '_days_str'
self._alarm = alarm

@callback
def _handle_coordinator_update(self) -> None:
days_list = self.coordinator.data["alarm_day_list"][self._alarm]
self._attr_native_value = ",".join([str(item) for item in days_list if item])

self.async_write_ha_state()

async def async_set_value(self, value: str) -> None:
"""Set the text value."""
await self.coordinator.async_set_alarm_day(self._alarm, value.split(','))
Loading

0 comments on commit 31fdddc

Please sign in to comment.