Skip to content

Commit

Permalink
Combine two sensors into one (#112)
Browse files Browse the repository at this point in the history
  • Loading branch information
KapJI authored Mar 25, 2021
1 parent f7813f8 commit df7fc58
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 143 deletions.
60 changes: 25 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,41 +52,18 @@ tokens and use those tokens making API calls to Google Home devices.

This component will set up the following platforms:

| Platform | Sample sensor | Description |
| -------- | ------------------------------- | --------------------------------------------------------- |
| `sensor` | `sensor.living_room_timers` | Sensor with a list of timers from the device |
| `sensor` | `sensor.living_room_next_timer` | Sensor with next timer from the device |
| `sensor` | `sensor.living_room_alarms` | Sensor with a list of alarms from the device |
| `sensor` | `sensor.living_room_next_alarm` | Sensor with next alarm from the device |
| `sensor` | `sensor.living_room_token` | Sensor with the local authentication token for the device |

### Timers

You can have multiple timers on your Google Home device. The Home Assistant
timers sensor will represent all of them in the state attributes as a list "timers".
Each of timers has the following keys:

| Key | Value type | Description |
| ---------------- | ---------------------------- | ------------------------------------------------------------------------- |
| `id` | Google Home corresponding ID | Used to delete/modify timer |
| `label` | Name | Name of the timer, this can be set when making the timer |
| `fire_time` | Seconds | Raw value coming from Google Home device until the timer goes off |
| `local_time` | Time | Time when the timer goes off, in respect to the Home Assistant's timezone |
| `local_time_iso` | Time in ISO 8601 standard | Useful for automations |
| `duration` | Seconds | Timer duration in seconds |

### Next timer

Will always show the next timer as timestring (ie: `2021-03-07T15:26:17+01:00`) if there is one set, else it will show off.

Has the same attributes as `sensor.living_room_timers`, but only for the first timer.
| Platform | Sample sensor | Description |
| -------- | --------------------------- | --------------------------------------------------------- |
| `sensor` | `sensor.living_room_alarms` | Sensor with a list of alarms from the device |
| `sensor` | `sensor.living_room_timers` | Sensor with a list of timers from the device |
| `sensor` | `sensor.living_room_token` | Sensor with the local authentication token for the device |

### Alarms

You can have multiple alarms on your Google Home device. The Home Assistant
You can have multiple alarms on your Google Home device. Home Assistant
alarms sensor will represent all of them in the state attributes as a list
"alarms".
Each of alarms has the following keys:
`alarms`.
Each of the alarms has the following keys:

| Key | Value type | Description |
| ---------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
Expand All @@ -97,13 +74,26 @@ Each of alarms has the following keys:
| `local_time_iso` | Time in ISO 8601 standard | Useful for automations |
| `recurrence` | List of integers | Days of the week when the alarm will go off. Please note, respecting Google set standard, the week starts from Sunday, therefore is denoted by 0. Correspondingly, Monday is 1, Saturday is 6 and so on |

### Next alarm
The state value shows the next alarm as a timestring (i.e.: `2021-03-07T15:26:17+01:00`) if there is at least one alarm set, otherwise it is set to `off`.

Will always show the next alarm as timestring (ie: `2021-03-07T15:26:17+01:00`) if there is one set, else it will show off.
This sensor is formatted to be compatible with the mobile app sensor, e.g. `sensor.phone_next_alarm`.

### Timers

This sensor is formatted to have compatibly with the sensor that mobile app has `sensor.phone_next_alarm`.
You can have multiple timers on your Google Home device. Home Assistant
timers sensor will represent all of them in the state attributes as a list `timers`.
Each of the timers has the following keys:

| Key | Value type | Description |
| ---------------- | ---------------------------- | ------------------------------------------------------------------------- |
| `id` | Google Home corresponding ID | Used to delete/modify timer |
| `label` | Name | Name of the timer, this can be set when making the timer |
| `fire_time` | Seconds | Raw value coming from Google Home device until the timer goes off |
| `local_time` | Time | Time when the timer goes off, in respect to the Home Assistant's timezone |
| `local_time_iso` | Time in ISO 8601 standard | Useful for automations |
| `duration` | Seconds | Timer duration in seconds |

Has the same attributes as `sensor.living_room_alarms`, but only for the first alarm.
The state value shows the next timer as a timestring (i.e.: `2021-03-07T15:26:17+01:00`) if there is at least one timer set, otherwise it is set to `off`.

## Getting Started

Expand Down
2 changes: 0 additions & 2 deletions custom_components/google_home/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@

LABEL_ALARMS = "alarms"
LABEL_AVAILABLE = "available"
LABEL_NEXT_ALARM = "next_alarm"
LABEL_NEXT_TIMER = "next_timer"
LABEL_TIMERS = "timers"
LABEL_DEVICE = "device"

Expand Down
132 changes: 26 additions & 106 deletions custom_components/google_home/sensor.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
"""Sensor platforms for Google Home"""
import logging
from typing import Any, Dict, Iterable, List
from typing import Any, Dict, Iterable, List, Optional

from typing_extensions import Protocol

from homeassistant.config_entries import ConfigEntry
from homeassistant.const import DEVICE_CLASS_TIMESTAMP, STATE_OFF, STATE_ON
from homeassistant.const import DEVICE_CLASS_TIMESTAMP, STATE_OFF
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import Entity

Expand All @@ -16,8 +16,6 @@
ICON_TOKEN,
LABEL_ALARMS,
LABEL_DEVICE,
LABEL_NEXT_ALARM,
LABEL_NEXT_TIMER,
LABEL_TIMERS,
)
from .entity import GoogleHomeBaseEntity
Expand Down Expand Up @@ -53,18 +51,10 @@ async def async_setup_entry(
coordinator,
device.name,
),
GoogleHomeNextAlarmSensor(
coordinator,
device.name,
),
GoogleHomeTimersSensor(
coordinator,
device.name,
),
GoogleHomeNextTimerSensor(
coordinator,
device.name,
),
]
async_add_devices(sensors)
return True
Expand All @@ -84,7 +74,7 @@ def icon(self) -> str:
return ICON_TOKEN

@property
def state(self) -> str:
def state(self) -> Optional[str]:
device = self.get_device()
return device.auth_token if device else None

Expand All @@ -100,8 +90,7 @@ def device_state_attributes(self):
"available": False,
"integration": DOMAIN,
}
attributes = self.get_device_attributes(device) if device else attributes
return attributes
return self.get_device_attributes(device) if device else attributes

@staticmethod
def get_device_attributes(device):
Expand Down Expand Up @@ -130,10 +119,17 @@ def icon(self) -> str:
return ICON_ALARMS

@property
def state(self) -> str:
alarms = self._get_alarms_data()
state = STATE_ON if len(alarms) else STATE_OFF
return state
def device_class(self) -> str:
"""Return the device class of the sensor."""
return DEVICE_CLASS_TIMESTAMP

@property
def state(self) -> Optional[str]:
device = self.get_device()
if not device:
return None
next_alarm = device.get_next_alarm()
return next_alarm.local_time_iso if next_alarm else STATE_OFF

@property
def device_state_attributes(self):
Expand All @@ -146,68 +142,34 @@ def device_state_attributes(self):
def _get_alarms_data(self) -> List[Dict[Any, Any]]:
"""Update alarms data extracting it from coordinator"""
device = self.get_device()
return self.as_dict(device.get_sorted_alarms())
return self.as_dict(device.get_sorted_alarms()) if device else []


class GoogleHomeNextAlarmSensor(GoogleHomeBaseEntity):
"""Google Home Next Alarm sensor."""
class GoogleHomeTimersSensor(GoogleHomeBaseEntity):
"""Google Home Timers sensor."""

@property
def label(self) -> str:
"""Label to use for name and unique id."""
return LABEL_NEXT_ALARM
return LABEL_TIMERS

@property
def icon(self) -> str:
"""Icon to use in the frontend."""
return ICON_ALARMS
return ICON_TIMERS

@property
def device_class(self) -> str:
"""Return the device class of the sensor."""
return DEVICE_CLASS_TIMESTAMP

@property
def state(self) -> str:
alarm = self._get_next_alarm()
return alarm.local_time_iso if alarm else STATE_OFF

@property
def device_state_attributes(self):
"""Return the state attributes."""
alarm = self._get_next_alarm()
attributes = alarm.__dict__ if alarm else {}
attributes.update(
{
"integration": DOMAIN,
}
)
return attributes

def _get_next_alarm(self):
"""Update alarms data extracting it from coordinator"""
def state(self) -> Optional[str]:
device = self.get_device()
alarm = device.get_next_alarm()
return alarm


class GoogleHomeTimersSensor(GoogleHomeBaseEntity):
"""Google Home Timers sensor."""

@property
def label(self) -> str:
"""Label to use for name and unique id."""
return LABEL_TIMERS

@property
def icon(self) -> str:
"""Icon to use in the frontend."""
return ICON_TIMERS

@property
def state(self) -> str:
timers = self._get_timers_data()
return STATE_ON if len(timers) else STATE_OFF
if not device:
return None
timer = device.get_next_timer()
return timer.local_time_iso if timer else STATE_OFF

@property
def device_state_attributes(self):
Expand All @@ -220,46 +182,4 @@ def device_state_attributes(self):
def _get_timers_data(self) -> List[Dict[Any, Any]]:
"""Update timers data extracting it from coordinator"""
device = self.get_device()
return self.as_dict(device.get_sorted_timers())


class GoogleHomeNextTimerSensor(GoogleHomeBaseEntity):
"""Google Home Next Timer sensor."""

@property
def label(self) -> str:
"""Label to use for name and unique id."""
return LABEL_NEXT_TIMER

@property
def icon(self) -> str:
"""Icon to use in the frontend."""
return ICON_TIMERS

@property
def device_class(self) -> str:
"""Return the device class of the sensor."""
return DEVICE_CLASS_TIMESTAMP

@property
def state(self) -> str:
timer = self._get_next_timer()
return timer.local_time_iso if timer else STATE_OFF

@property
def device_state_attributes(self):
"""Return the state attributes."""
timer = self._get_next_timer()
attributes = timer.__dict__ if timer else {}
attributes.update(
{
"integration": DOMAIN,
}
)
return attributes

def _get_next_timer(self):
"""Update alarms data extracting it from coordinator"""
device = self.get_device()
timer = device.get_next_timer()
return timer
return self.as_dict(device.get_sorted_timers()) if device else []

0 comments on commit df7fc58

Please sign in to comment.