-
-
Notifications
You must be signed in to change notification settings - Fork 33.8k
Move uptime from relative time to absolute time #43623
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,80 +1,59 @@ | ||
"""Platform to retrieve uptime for Home Assistant.""" | ||
import logging | ||
|
||
import voluptuous as vol | ||
|
||
from homeassistant.components.sensor import PLATFORM_SCHEMA | ||
from homeassistant.components.sensor import DEVICE_CLASS_TIMESTAMP, PLATFORM_SCHEMA | ||
from homeassistant.const import CONF_NAME, CONF_UNIT_OF_MEASUREMENT | ||
import homeassistant.helpers.config_validation as cv | ||
from homeassistant.helpers.entity import Entity | ||
import homeassistant.util.dt as dt_util | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
DEFAULT_NAME = "Uptime" | ||
|
||
ICON = "mdi:clock" | ||
|
||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( | ||
{ | ||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, | ||
vol.Optional(CONF_UNIT_OF_MEASUREMENT, default="days"): vol.All( | ||
cv.string, vol.In(["minutes", "hours", "days", "seconds"]) | ||
), | ||
} | ||
PLATFORM_SCHEMA = vol.All( | ||
cv.deprecated(CONF_UNIT_OF_MEASUREMENT), | ||
PLATFORM_SCHEMA.extend( | ||
{ | ||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, | ||
vol.Optional(CONF_UNIT_OF_MEASUREMENT, default="days"): vol.All( | ||
cv.string, vol.In(["minutes", "hours", "days", "seconds"]) | ||
), | ||
} | ||
), | ||
) | ||
|
||
|
||
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): | ||
"""Set up the uptime sensor platform.""" | ||
name = config.get(CONF_NAME) | ||
units = config.get(CONF_UNIT_OF_MEASUREMENT) | ||
|
||
async_add_entities([UptimeSensor(name, units)], True) | ||
async_add_entities([UptimeSensor(name)], True) | ||
|
||
|
||
class UptimeSensor(Entity): | ||
"""Representation of an uptime sensor.""" | ||
|
||
def __init__(self, name, unit): | ||
def __init__(self, name): | ||
"""Initialize the uptime sensor.""" | ||
self._name = name | ||
self._unit = unit | ||
self.initial = dt_util.now() | ||
self._state = None | ||
self._state = dt_util.now().isoformat() | ||
|
||
@property | ||
def name(self): | ||
"""Return the name of the sensor.""" | ||
return self._name | ||
|
||
@property | ||
def icon(self): | ||
"""Icon to display in the front end.""" | ||
return ICON | ||
|
||
@property | ||
def unit_of_measurement(self): | ||
"""Return the unit of measurement the value is expressed in.""" | ||
return self._unit | ||
def device_class(self): | ||
"""Return device class.""" | ||
return DEVICE_CLASS_TIMESTAMP | ||
|
||
@property | ||
def state(self): | ||
"""Return the state of the sensor.""" | ||
return self._state | ||
|
||
async def async_update(self): | ||
"""Update the state of the sensor.""" | ||
delta = dt_util.now() - self.initial | ||
div_factor = 3600 | ||
|
||
if self.unit_of_measurement == "days": | ||
div_factor *= 24 | ||
elif self.unit_of_measurement == "minutes": | ||
div_factor /= 60 | ||
elif self.unit_of_measurement == "seconds": | ||
div_factor /= 3600 | ||
|
||
delta = delta.total_seconds() / div_factor | ||
self._state = round(delta, 2) | ||
_LOGGER.debug("New value: %s", delta) | ||
@property | ||
def should_poll(self) -> bool: | ||
"""Disable polling for this entity.""" | ||
return False |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,85 +1,11 @@ | ||
"""The tests for the uptime sensor platform.""" | ||
from datetime import timedelta | ||
|
||
from homeassistant.components.uptime.sensor import UptimeSensor | ||
from homeassistant.setup import async_setup_component | ||
|
||
from tests.async_mock import patch | ||
|
||
|
||
async def test_uptime_min_config(hass): | ||
"""Test minimum uptime configuration.""" | ||
config = {"sensor": {"platform": "uptime"}} | ||
assert await async_setup_component(hass, "sensor", config) | ||
await hass.async_block_till_done() | ||
state = hass.states.get("sensor.uptime") | ||
assert state.attributes.get("unit_of_measurement") == "days" | ||
|
||
|
||
async def test_uptime_sensor_name_change(hass): | ||
"""Test uptime sensor with different name.""" | ||
config = {"sensor": {"platform": "uptime", "name": "foobar"}} | ||
assert await async_setup_component(hass, "sensor", config) | ||
await hass.async_block_till_done() | ||
state = hass.states.get("sensor.foobar") | ||
assert state.attributes.get("unit_of_measurement") == "days" | ||
|
||
|
||
async def test_uptime_sensor_config_hours(hass): | ||
"""Test uptime sensor with hours defined in config.""" | ||
config = {"sensor": {"platform": "uptime", "unit_of_measurement": "hours"}} | ||
assert await async_setup_component(hass, "sensor", config) | ||
await hass.async_block_till_done() | ||
state = hass.states.get("sensor.uptime") | ||
assert state.attributes.get("unit_of_measurement") == "hours" | ||
|
||
|
||
async def test_uptime_sensor_config_minutes(hass): | ||
"""Test uptime sensor with minutes defined in config.""" | ||
config = {"sensor": {"platform": "uptime", "unit_of_measurement": "minutes"}} | ||
assert await async_setup_component(hass, "sensor", config) | ||
await hass.async_block_till_done() | ||
state = hass.states.get("sensor.uptime") | ||
assert state.attributes.get("unit_of_measurement") == "minutes" | ||
|
||
|
||
async def test_uptime_sensor_days_output(hass): | ||
"""Test uptime sensor output data.""" | ||
sensor = UptimeSensor("test", "days") | ||
assert sensor.unit_of_measurement == "days" | ||
new_time = sensor.initial + timedelta(days=1) | ||
with patch("homeassistant.util.dt.now", return_value=new_time): | ||
await sensor.async_update() | ||
assert sensor.state == 1.00 | ||
new_time = sensor.initial + timedelta(days=111.499) | ||
with patch("homeassistant.util.dt.now", return_value=new_time): | ||
await sensor.async_update() | ||
assert sensor.state == 111.50 | ||
|
||
|
||
async def test_uptime_sensor_hours_output(hass): | ||
"""Test uptime sensor output data.""" | ||
sensor = UptimeSensor("test", "hours") | ||
assert sensor.unit_of_measurement == "hours" | ||
new_time = sensor.initial + timedelta(hours=16) | ||
with patch("homeassistant.util.dt.now", return_value=new_time): | ||
await sensor.async_update() | ||
assert sensor.state == 16.00 | ||
new_time = sensor.initial + timedelta(hours=72.499) | ||
with patch("homeassistant.util.dt.now", return_value=new_time): | ||
await sensor.async_update() | ||
assert sensor.state == 72.50 | ||
|
||
581C td> |
|
|
async def test_uptime_sensor_minutes_output(hass): | ||
"""Test uptime sensor output data.""" | ||
sensor = UptimeSensor("test", "minutes") | ||
assert sensor.unit_of_measurement == "minutes" | ||
new_time = sensor.initial + timedelta(minutes=16) | ||
with patch("homeassistant.util.dt.now", return_value=new_time): | ||
await sensor.async_update() | ||
assert sensor.state == 16.00 | ||
new_time = sensor.initial + timedelta(minutes=12.499) | ||
with patch("homeassistant.util.dt.now", return_value=new_time): | ||
await sensor.async_update() | ||
assert sensor.state == 12.50 | ||
assert hass.states.get("sensor.foobar") |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.