Add SetSystemDateandTime Button (#66419)

* add SetSystemDateandTime

* fix

* address review

* follow recommendation to set date and time on start

* add set date and time button test
This commit is contained in:
Diogo Gomes 2022-07-07 15:25:44 +01:00 committed by GitHub
parent 29cbd9d469
commit 4e2de2479a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 79 additions and 2 deletions

View File

@ -1,5 +1,4 @@
"""ONVIF Buttons."""
from homeassistant.components.button import ButtonDeviceClass, ButtonEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
@ -18,7 +17,7 @@ async def async_setup_entry(
) -> None:
"""Set up ONVIF button based on a config entry."""
device = hass.data[DOMAIN][config_entry.unique_id]
async_add_entities([RebootButton(device)])
async_add_entities([RebootButton(device), SetSystemDateAndTimeButton(device)])
class RebootButton(ONVIFBaseEntity, ButtonEntity):
@ -39,3 +38,19 @@ class RebootButton(ONVIFBaseEntity, ButtonEntity):
"""Send out a SystemReboot command."""
device_mgmt = self.device.device.create_devicemgmt_service()
await device_mgmt.SystemReboot()
class SetSystemDateAndTimeButton(ONVIFBaseEntity, ButtonEntity):
"""Defines a ONVIF SetSystemDateAndTime button."""
_attr_entity_category = EntityCategory.CONFIG
def __init__(self, device: ONVIFDevice) -> None:
"""Initialize the button entity."""
super().__init__(device)
self._attr_name = f"{self.device.name} Set System Date and Time"
self._attr_unique_id = f"{self.device.info.mac or self.device.info.serial_number}_setsystemdatetime"
async def async_press(self) -> None:
"""Send out a SetSystemDateAndTime command."""
await self.device.async_manually_set_date_and_time()

View File

@ -5,6 +5,7 @@ import asyncio
from contextlib import suppress
import datetime as dt
import os
import time
from httpx import RequestError
import onvif
@ -148,6 +149,32 @@ class ONVIFDevice:
await self.events.async_stop()
await self.device.close()
async def async_manually_set_date_and_time(self) -> None:
"""Set Date and Time Manually using SetSystemDateAndTime command."""
device_mgmt = self.device.create_devicemgmt_service()
# Retrieve DateTime object from camera to use as template for Set operation
device_time = await device_mgmt.GetSystemDateAndTime()
system_date = dt_util.utcnow()
LOGGER.debug("System date (UTC): %s", system_date)
dt_param = device_mgmt.create_type("SetSystemDateAndTime")
dt_param.DateTimeType = "Manual"
# Retrieve DST setting from system
dt_param.DaylightSavings = bool(time.localtime().tm_isdst)
dt_param.UTCDateTime = device_time.UTCDateTime
# Retrieve timezone from system
dt_param.TimeZone = str(system_date.astimezone().tzinfo)
dt_param.UTCDateTime.Date.Year = system_date.year
dt_param.UTCDateTime.Date.Month = system_date.month
dt_param.UTCDateTime.Date.Day = system_date.day
dt_param.UTCDateTime.Time.Hour = system_date.hour
dt_param.UTCDateTime.Time.Minute = system_date.minute
dt_param.UTCDateTime.Time.Second = system_date.second
LOGGER.debug("SetSystemDateAndTime: %s", dt_param)
await device_mgmt.SetSystemDateAndTime(dt_param)
async def async_check_date_and_time(self) -> None:
"""Warns if device and system date not synced."""
LOGGER.debug("Setting up the ONVIF device management service")
@ -165,6 +192,8 @@ class ONVIFDevice:
)
return
LOGGER.debug("Device time: %s", device_time)
tzone = dt_util.DEFAULT_TIME_ZONE
cdate = device_time.LocalDateTime
if device_time.UTCDateTime:
@ -207,6 +236,9 @@ class ONVIFDevice:
cam_date_utc,
system_date,
)
if device_time.DateTimeType == "Manual":
# Set Date and Time ourselves if Date and Time is set manually in the camera.
await self.async_manually_set_date_and_time()
except RequestError as err:
LOGGER.warning(
"Couldn't get device '%s' date/time. Error: %s", self.name, err

View File

@ -38,3 +38,33 @@ async def test_reboot_button_press(hass):
await hass.async_block_till_done()
devicemgmt.SystemReboot.assert_called_once()
async def test_set_dateandtime_button(hass):
"""Test states of the SetDateAndTime button."""
await setup_onvif_integration(hass)
state = hass.states.get("button.testcamera_set_system_date_and_time")
assert state
assert state.state == STATE_UNKNOWN
registry = er.async_get(hass)
entry = registry.async_get("button.testcamera_set_system_date_and_time")
assert entry
assert entry.unique_id == f"{MAC}_setsystemdatetime"
async def test_set_dateandtime_button_press(hass):
"""Test SetDateAndTime button press."""
_, camera, device = await setup_onvif_integration(hass)
device.async_manually_set_date_and_time = AsyncMock(return_value=True)
await hass.services.async_call(
BUTTON_DOMAIN,
"press",
{ATTR_ENTITY_ID: "button.testcamera_set_system_date_and_time"},
blocking=True,
)
await hass.async_block_till_done()
device.async_manually_set_date_and_time.assert_called_once()