def test_scan_devices_filtered(): """Test the scanning for devices based on SSID.""" ctrl = mock.MagicMock() fake_clients = [ { 'mac': '123', 'essid': 'foonet', 'last_seen': dt_util.as_timestamp(dt_util.utcnow()) }, { 'mac': '234', 'essid': 'foonet', 'last_seen': dt_util.as_timestamp(dt_util.utcnow()) }, { 'mac': '567', 'essid': 'notnet', 'last_seen': dt_util.as_timestamp(dt_util.utcnow()) }, { 'mac': '890', 'essid': 'barnet', 'last_seen': dt_util.as_timestamp(dt_util.utcnow()) }, ] ssid_filter = ['foonet', 'barnet'] ctrl.get_clients.return_value = fake_clients scanner = unifi.UnifiScanner(ctrl, DEFAULT_DETECTION_TIME, ssid_filter, None) assert set(scanner.scan_devices()) == set(['123', '234', '890'])
def test_get_device_name(): """Test the getting of device names.""" ctrl = mock.MagicMock() fake_clients = [ { 'mac': '123', 'hostname': 'foobar', 'last_seen': dt_util.as_timestamp(dt_util.utcnow()) }, { 'mac': '234', 'name': 'Nice Name', 'last_seen': dt_util.as_timestamp(dt_util.utcnow()) }, { 'mac': '456', 'last_seen': '1504786810' }, ] ctrl.get_clients.return_value = fake_clients scanner = unifi.UnifiScanner(ctrl, DEFAULT_DETECTION_TIME) assert scanner.get_device_name('123') == 'foobar' assert scanner.get_device_name('234') == 'Nice Name' assert scanner.get_device_name('456') is None assert scanner.get_device_name('unknown') is None
async def test_option_ignore_wired_bug(hass): """Test option to ignore wired bug.""" client_1_client = copy(CLIENT_1) client_1_client["last_seen"] = dt_util.as_timestamp(dt_util.utcnow()) controller = await setup_unifi_integration( hass, options={CONF_IGNORE_WIRED_BUG: True}, clients_response=[client_1_client] ) assert len(hass.states.async_entity_ids("device_tracker")) == 1 client_1 = hass.states.get("device_tracker.client_1") assert client_1 is not None assert client_1.state == "home" assert client_1.attributes["is_wired"] is False client_1_client["is_wired"] = True client_1_client["last_seen"] = dt_util.as_timestamp(dt_util.utcnow()) event = {"meta": {"message": "sta:sync"}, "data": [client_1_client]} controller.api.message_handler(event) await hass.async_block_till_done() client_1 = hass.states.get("device_tracker.client_1") assert client_1.state == "home" assert client_1.attributes["is_wired"] is True client_1_client["is_wired"] = False client_1_client["last_seen"] = dt_util.as_timestamp(dt_util.utcnow()) event = {"meta": {"message": "sta:sync"}, "data": [client_1_client]} controller.api.message_handler(event) await hass.async_block_till_done() client_1 = hass.states.get("device_tracker.client_1") assert client_1.state == "home" assert client_1.attributes["is_wired"] is False
async def async_update(self): """Get the latest data and updates the states.""" # Get previous values of start and end p_start, p_end = self._period # Parse templates self.update_period() start, end = self._period # Convert times to UTC start = dt_util.as_utc(start) end = dt_util.as_utc(end) p_start = dt_util.as_utc(p_start) p_end = dt_util.as_utc(p_end) now = datetime.datetime.now() # Compute integer timestamps start_timestamp = math.floor(dt_util.as_timestamp(start)) end_timestamp = math.floor(dt_util.as_timestamp(end)) p_start_timestamp = math.floor(dt_util.as_timestamp(p_start)) p_end_timestamp = math.floor(dt_util.as_timestamp(p_end)) now_timestamp = math.floor(dt_util.as_timestamp(now)) # If period has not changed and current time after the period end... if (start_timestamp == p_start_timestamp and end_timestamp == p_end_timestamp and end_timestamp <= now_timestamp): # Don't compute anything as the value cannot have changed return await get_instance(self.hass).async_add_executor_job( self._update, start, end, now_timestamp, start_timestamp, end_timestamp)
def test_monitored_conditions(): """Test the filtering of attributes.""" ctrl = mock.MagicMock() fake_clients = [ {'mac': '123', 'hostname': 'foobar', 'essid': 'barnet', 'signal': -60, 'last_seen': dt_util.as_timestamp(dt_util.utcnow())}, {'mac': '234', 'name': 'Nice Name', 'essid': 'barnet', 'signal': -42, 'last_seen': dt_util.as_timestamp(dt_util.utcnow())}, {'mac': '456', 'hostname': 'wired', 'essid': 'barnet', 'last_seen': dt_util.as_timestamp(dt_util.utcnow())}, ] ctrl.get_clients.return_value = fake_clients scanner = unifi.UnifiScanner(ctrl, DEFAULT_DETECTION_TIME, None, ['essid', 'signal']) assert scanner.get_extra_attributes('123') == {'essid': 'barnet', 'signal': -60} assert scanner.get_extra_attributes('234') == {'essid': 'barnet', 'signal': -42} assert scanner.get_extra_attributes('456') == {'essid': 'barnet'}
async def test_get_device_name(): """Test the getting of device names.""" ctrl = mock.MagicMock() fake_clients = [ { 'mac': '123', 'hostname': 'foobar', 'essid': 'barnet', 'last_seen': dt_util.as_timestamp(dt_util.utcnow()) }, { 'mac': '234', 'name': 'Nice Name', 'essid': 'barnet', 'last_seen': dt_util.as_timestamp(dt_util.utcnow()) }, { 'mac': '456', 'essid': 'barnet', 'last_seen': '1504786810' }, ] ctrl.clients = Clients([], CoroutineMock(return_value=fake_clients)) scnr = unifi.UnifiScanner(ctrl, DEFAULT_DETECTION_TIME, None, None) await scnr.async_update() assert scnr.get_device_name('123') == 'foobar' assert scnr.get_device_name('234') == 'Nice Name' assert scnr.get_device_name('456') is None assert scnr.get_device_name('unknown') is None
def test_scan_devices(): """Test the scanning for devices.""" ctrl = mock.MagicMock() fake_clients = [ {'mac': '123', 'last_seen': dt_util.as_timestamp(dt_util.utcnow())}, {'mac': '234', 'last_seen': dt_util.as_timestamp(dt_util.utcnow())}, ] ctrl.get_clients.return_value = fake_clients scanner = unifi.UnifiScanner(ctrl, DEFAULT_DETECTION_TIME) assert set(scanner.scan_devices()) == set(['123', '234'])
async def test_wireless_client_go_wired_issue(hass): """Test the solution to catch wireless device go wired UniFi issue. UniFi has a known issue that when a wireless device goes away it sometimes gets marked as wired. """ client_1_client = copy(CLIENT_1) client_1_client["last_seen"] = dt_util.as_timestamp(dt_util.utcnow()) controller = await setup_unifi_integration( hass, ENTRY_CONFIG, options={}, sites=SITES, clients_response=[client_1_client], devices_response=[], clients_all_response=[], ) assert len(hass.states.async_all()) == 3 client_1 = hass.states.get("device_tracker.client_1") assert client_1 is not None assert client_1.state == "home" client_1_client["is_wired"] = True client_1_client["last_seen"] = dt_util.as_timestamp(dt_util.utcnow()) controller.mock_client_responses.append([client_1_client]) controller.mock_device_responses.append({}) await controller.async_update() await hass.async_block_till_done() client_1 = hass.states.get("device_tracker.client_1") assert client_1.state == "home" with patch.object( unifi.device_tracker.dt_util, "utcnow", return_value=(dt_util.utcnow() + timedelta(minutes=5)), ): controller.mock_client_responses.append([client_1_client]) controller.mock_device_responses.append({}) await controller.async_update() await hass.async_block_till_done() client_1 = hass.states.get("device_tracker.client_1") assert client_1.state == "not_home" client_1_client["is_wired"] = False client_1_client["last_seen"] = dt_util.as_timestamp(dt_util.utcnow()) controller.mock_client_responses.append([client_1_client]) controller.mock_device_responses.append({}) await controller.async_update() await hass.async_block_till_done() client_1 = hass.states.get("device_tracker.client_1") assert client_1.state == "home"
def test_scanner_update(): """Test the scanner update.""" ctrl = mock.MagicMock() fake_clients = [ {'mac': '123', 'last_seen': dt_util.as_timestamp(dt_util.utcnow())}, {'mac': '234', 'last_seen': dt_util.as_timestamp(dt_util.utcnow())}, ] ctrl.get_clients.return_value = fake_clients unifi.UnifiScanner(ctrl, DEFAULT_DETECTION_TIME) assert ctrl.get_clients.call_count == 1 assert ctrl.get_clients.call_args == mock.call()
def test_as_timestamp(): """Test as_timestamp method.""" ts = 1462401234 utc_dt = dt_util.utc_from_timestamp(ts) assert ts == dt_util.as_timestamp(utc_dt) utc_iso = utc_dt.isoformat() assert ts == dt_util.as_timestamp(utc_iso) # confirm the ability to handle a string passed in delta = dt_util.as_timestamp("2016-01-01 12:12:12") delta -= dt_util.as_timestamp("2016-01-01 12:12:11") assert delta == 1
def test_as_timestamp(self): """Test as_timestamp method.""" ts = 1462401234 utc_dt = dt_util.utc_from_timestamp(ts) self.assertEqual(ts, dt_util.as_timestamp(utc_dt)) utc_iso = utc_dt.isoformat() self.assertEqual(ts, dt_util.as_timestamp(utc_iso)) # confirm the ability to handle a string passed in delta = dt_util.as_timestamp("2016-01-01 12:12:12") delta -= dt_util.as_timestamp("2016-01-01 12:12:11") self.assertEquals(1, delta)
async def test_timezone_intervals(hass): """Test date sensor behavior in a timezone besides UTC.""" new_tz = dt_util.get_time_zone("America/New_York") assert new_tz is not None dt_util.set_default_time_zone(new_tz) device = time_date.TimeDateSensor(hass, "date") now = dt_util.utc_from_timestamp(50000) with patch("homeassistant.util.dt.utcnow", return_value=now): next_time = device.get_next_interval() # start of local day in EST was 18000.0 # so the second day was 18000 + 86400 assert next_time.timestamp() == 104400 new_tz = dt_util.get_time_zone("America/Edmonton") assert new_tz is not None dt_util.set_default_time_zone(new_tz) now = dt_util.parse_datetime("2017-11-13 19:47:19-07:00") device = time_date.TimeDateSensor(hass, "date") with patch("homeassistant.util.dt.utcnow", return_value=now): next_time = device.get_next_interval() assert next_time.timestamp() == dt_util.as_timestamp( "2017-11-14 00:00:00-07:00") # Entering DST new_tz = dt_util.get_time_zone("Europe/Prague") assert new_tz is not None dt_util.set_default_time_zone(new_tz) now = dt_util.parse_datetime("2020-03-29 00:00+01:00") with patch("homeassistant.util.dt.utcnow", return_value=now): next_time = device.get_next_interval() assert next_time.timestamp() == dt_util.as_timestamp( "2020-03-30 00:00+02:00") now = dt_util.parse_datetime("2020-03-29 03:00+02:00") with patch("homeassistant.util.dt.utcnow", return_value=now): next_time = device.get_next_interval() assert next_time.timestamp() == dt_util.as_timestamp( "2020-03-30 00:00+02:00") # Leaving DST now = dt_util.parse_datetime("2020-10-25 00:00+02:00") with patch("homeassistant.util.dt.utcnow", return_value=now): next_time = device.get_next_interval() assert next_time.timestamp() == dt_util.as_timestamp( "2020-10-26 00:00:00+01:00") now = dt_util.parse_datetime("2020-10-25 23:59+01:00") with patch("homeassistant.util.dt.utcnow", return_value=now): next_time = device.get_next_interval() assert next_time.timestamp() == dt_util.as_timestamp( "2020-10-26 00:00:00+01:00")
def test_as_timestamp(self): """Test as_timestamp method.""" ts = 1462401234 utc_dt = dt_util.utc_from_timestamp(ts) assert ts == dt_util.as_timestamp(utc_dt) utc_iso = utc_dt.isoformat() assert ts == dt_util.as_timestamp(utc_iso) # confirm the ability to handle a string passed in delta = dt_util.as_timestamp("2016-01-01 12:12:12") delta -= dt_util.as_timestamp("2016-01-01 12:12:11") assert 1 == delta
def test_scan_devices(): """Test the scanning for devices.""" ctrl = mock.MagicMock() fake_clients = [ {'mac': '123', 'essid': 'barnet', 'last_seen': dt_util.as_timestamp(dt_util.utcnow())}, {'mac': '234', 'essid': 'barnet', 'last_seen': dt_util.as_timestamp(dt_util.utcnow())}, ] ctrl.get_clients.return_value = fake_clients scanner = unifi.UnifiScanner(ctrl, DEFAULT_DETECTION_TIME, None, None) assert set(scanner.scan_devices()) == set(['123', '234'])
def test_scanner_update(): """Test the scanner update.""" ctrl = mock.MagicMock() fake_clients = [ {'mac': '123', 'essid': 'barnet', 'last_seen': dt_util.as_timestamp(dt_util.utcnow())}, {'mac': '234', 'essid': 'barnet', 'last_seen': dt_util.as_timestamp(dt_util.utcnow())}, ] ctrl.get_clients.return_value = fake_clients unifi.UnifiScanner(ctrl, DEFAULT_DETECTION_TIME, None, None) assert ctrl.get_clients.call_count == 1 assert ctrl.get_clients.call_args == mock.call()
async def test_tracked_devices(hass, mock_controller): """Test the update_items function with some clients.""" mock_controller.mock_client_responses.append( [CLIENT_1, CLIENT_2, CLIENT_3]) mock_controller.mock_device_responses.append([DEVICE_1, DEVICE_2]) mock_controller.unifi_config = {unifi_dt.CONF_SSID_FILTER: ["ssid"]} await setup_controller(hass, mock_controller) assert len(mock_controller.mock_requests) == 2 assert len(hass.states.async_all()) == 5 client_1 = hass.states.get("device_tracker.client_1") assert client_1 is not None assert client_1.state == "not_home" client_2 = hass.states.get("device_tracker.wired_client") assert client_2 is not None assert client_2.state == "not_home" client_3 = hass.states.get("device_tracker.client_3") assert client_3 is None device_1 = hass.states.get("device_tracker.device_1") assert device_1 is not None assert device_1.state == "not_home" client_1_copy = copy(CLIENT_1) client_1_copy["last_seen"] = dt_util.as_timestamp(dt_util.utcnow()) device_1_copy = copy(DEVICE_1) device_1_copy["last_seen"] = dt_util.as_timestamp(dt_util.utcnow()) mock_controller.mock_client_responses.append([client_1_copy]) mock_controller.mock_device_responses.append([device_1_copy]) await mock_controller.async_update() await hass.async_block_till_done() client_1 = hass.states.get("device_tracker.client_1") assert client_1.state == "home" device_1 = hass.states.get("device_tracker.device_1") assert device_1.state == "home" device_1_copy = copy(DEVICE_1) device_1_copy["disabled"] = True mock_controller.mock_client_responses.append({}) mock_controller.mock_device_responses.append([device_1_copy]) await mock_controller.async_update() await hass.async_block_till_done() device_1 = hass.states.get("device_tracker.device_1") assert device_1.state == STATE_UNAVAILABLE
def update(self): """Get the latest data and updates the states.""" # Parse templates self.update_period() start, end = self._period # Convert to UTC start = dt_util.as_utc(start) end = dt_util.as_utc(end) # Get history between start and end history_list = history.state_changes_during_period( self.hass, start, end, str(self._entity_id)) if self._entity_id not in history_list.keys(): return # Get the first state last_state = history.get_state(self.hass, start, self._entity_id) last_state = (last_state is not None and last_state == self._entity_state) last_time = dt_util.as_timestamp(start) elapsed = 0 count = 0 # Make calculations for item in history_list.get(self._entity_id): current_state = item.state == self._entity_state current_time = item.last_changed.timestamp() if last_state: elapsed += current_time - last_time if current_state and not last_state: count += 1 last_state = current_state last_time = current_time # Count time elapsed between last history state and end of measure if last_state: measure_end = min(dt_util.as_timestamp(end), dt_util.as_timestamp( datetime.datetime.now())) elapsed += measure_end - last_time # Save value in hours self.value = elapsed / 3600 # Save counter self.count = count
async def test_wireless_client_go_wired_issue(hass): """Test the solution to catch wireless device go wired UniFi issue. UniFi has a known issue that when a wireless device goes away it sometimes gets marked as wired. """ client_1_client = copy(CLIENT_1) client_1_client["last_seen"] = dt_util.as_timestamp(dt_util.utcnow()) controller = await setup_unifi_integration( hass, clients_response=[client_1_client]) assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 1 client_1 = hass.states.get("device_tracker.client_1") assert client_1 is not None assert client_1.state == "home" assert client_1.attributes["is_wired"] is False client_1_client["is_wired"] = True client_1_client["last_seen"] = dt_util.as_timestamp(dt_util.utcnow()) event = {"meta": {"message": "sta:sync"}, "data": [client_1_client]} controller.api.message_handler(event) await hass.async_block_till_done() client_1 = hass.states.get("device_tracker.client_1") assert client_1.state == "home" assert client_1.attributes["is_wired"] is False with patch.object( dt_util, "utcnow", return_value=(dt_util.utcnow() + timedelta(minutes=5)), ): event = {"meta": {"message": "sta:sync"}, "data": [client_1_client]} controller.api.message_handler(event) await hass.async_block_till_done() client_1 = hass.states.get("device_tracker.client_1") assert client_1.state == "not_home" assert client_1.attributes["is_wired"] is False client_1_client["is_wired"] = False client_1_client["last_seen"] = dt_util.as_timestamp(dt_util.utcnow()) event = {"meta": {"message": "sta:sync"}, "data": [client_1_client]} controller.api.message_handler(event) await hass.async_block_till_done() client_1 = hass.states.get("device_tracker.client_1") assert client_1.state == "home" assert client_1.attributes["is_wired"] is False
def update(self): """Get the latest data and updates the states.""" # Parse templates self.update_period() start, end = self._period # Convert to UTC start = dt_util.as_utc(start) end = dt_util.as_utc(end) # Get history between start and end history_list = history.state_changes_during_period( self.hass, start, end, str(self._entity_id)) if self._entity_id not in history_list.keys(): return # Get the first state last_state = history.get_state(self.hass, start, self._entity_id) last_state = (last_state is not None and last_state == self._entity_state) last_time = dt_util.as_timestamp(start) elapsed = 0 count = 0 # Make calculations for item in history_list.get(self._entity_id): current_state = item.state == self._entity_state current_time = item.last_changed.timestamp() if last_state: elapsed += current_time - last_time if current_state and not last_state: count += 1 last_state = current_state last_time = current_time # Count time elapsed between last history state and end of measure if last_state: measure_end = min(dt_util.as_timestamp(end), dt_util.as_timestamp(datetime.datetime.now())) elapsed += measure_end - last_time # Save value in hours self.value = elapsed / 3600 # Save counter self.count = count
async def test_timezone_intervals_empty_parameter(utcnow_mock, hass): """Test get_interval() without parameters.""" hass.config.set_time_zone("America/Edmonton") device = time_date.TimeDateSensor(hass, "date") next_time = device.get_next_interval() assert next_time.timestamp() == dt_util.as_timestamp( "2017-11-14 00:00:00-07:00")
def convert_time_to_utc(timestr): """Take a string like 08:00:00 and convert it to a unix timestamp.""" combined = datetime.combine(dt_util.start_of_local_day(), dt_util.parse_time(timestr)) if combined < datetime.now(): combined = combined + timedelta(days=1) return dt_util.as_timestamp(combined)
async def test_connection_state_signalling(hass, aioclient_mock, mock_unifi_websocket): """Verify connection statesignalling and connection state are working.""" client = { "hostname": "client", "ip": "10.0.0.1", "is_wired": True, "last_seen": dt_util.as_timestamp(dt_util.utcnow()), "mac": "00:00:00:00:00:01", } await setup_unifi_integration(hass, aioclient_mock, clients_response=[client]) # Controller is connected assert hass.states.get("device_tracker.client").state == "home" mock_unifi_websocket(state=STATE_DISCONNECTED) await hass.async_block_till_done() # Controller is disconnected assert hass.states.get("device_tracker.client").state == "unavailable" mock_unifi_websocket(state=STATE_RUNNING) await hass.async_block_till_done() # Controller is once again connected assert hass.states.get("device_tracker.client").state == "home"
def get(self, request): """Get SpaceAPI data.""" hass = request.app["hass"] spaceapi = dict(hass.data[DATA_SPACEAPI]) is_sensors = spaceapi.get("sensors") location = { ATTR_LAT: hass.config.latitude, ATTR_LON: hass.config.longitude } try: location[ATTR_ADDRESS] = spaceapi[ATTR_LOCATION][CONF_ADDRESS] except KeyError: pass except TypeError: pass state_entity = spaceapi["state"][ATTR_ENTITY_ID] if (space_state := hass.states.get(state_entity)) is not None: state = { ATTR_OPEN: space_state.state != "off", ATTR_LASTCHANGE: dt_util.as_timestamp(space_state.last_updated), }
def convert_time_to_utc(timestr): """Take a string like 08:00:00 and convert it to a unix timestamp.""" combined = datetime.combine( dt_util.start_of_local_day(), dt_util.parse_time(timestr)) if combined < datetime.now(): combined = combined + timedelta(days=1) return dt_util.as_timestamp(combined)
def _update_recurring_alarm(self, value): _LOGGER.debug("Sensor value %s", value) alarm = value[1][self._sensor_property] reminder = None if isinstance(value[1][self._sensor_property], (int, float)): reminder = True alarm = dt.as_local( self._round_time( datetime.datetime.fromtimestamp(alarm / 1000, tz=LOCAL_TIMEZONE))) alarm_on = value[1]["status"] == "ON" recurring_pattern = value[1].get("recurringPattern") while (alarm_on and recurring_pattern and RECURRING_PATTERN_ISO_SET[recurring_pattern] and alarm.isoweekday not in RECURRING_PATTERN_ISO_SET[recurring_pattern] and alarm < dt.now()): alarm += datetime.timedelta(days=1) if reminder: alarm = dt.as_timestamp(alarm) * 1000 if alarm != value[1][self._sensor_property]: _LOGGER.debug( "%s with recurrence %s set to %s", value[1]["type"], RECURRING_PATTERN[recurring_pattern], alarm, ) value[1][self._sensor_property] = alarm return value
async def test_option_ssid_filter(hass): """Test the SSID filter works.""" controller = await setup_unifi_integration( hass, options={CONF_SSID_FILTER: ["ssid"]}, clients_response=[CLIENT_3], ) assert len(hass.states.async_all()) == 2 # SSID filter active client_3 = hass.states.get("device_tracker.client_3") assert client_3.state == "not_home" client_3_copy = copy(CLIENT_3) client_3_copy["last_seen"] = dt_util.as_timestamp(dt_util.utcnow()) event = {"meta": {"message": "sta:sync"}, "data": [client_3_copy]} controller.api.message_handler(event) await hass.async_block_till_done() # SSID filter active even though time stamp should mark as home client_3 = hass.states.get("device_tracker.client_3") assert client_3.state == "not_home" # Remove SSID filter hass.config_entries.async_update_entry( controller.config_entry, options={CONF_SSID_FILTER: []}, ) event = {"meta": {"message": "sta:sync"}, "data": [client_3_copy]} controller.api.message_handler(event) await hass.async_block_till_done() # SSID no longer filtered client_3 = hass.states.get("device_tracker.client_3") assert client_3.state == "home"
def _get_utime(source, tzone): local_date = source if len(source) <= 10: local_date += "T00:00:00" tz_h, tz_m = divmod(abs(tzone), 60) local_date += f"+{tz_h:02}:{tz_m:02}" if tzone >= 0 else f"-{tz_h:02}:{tz_m:02}" return dt_util.as_timestamp(local_date)
def update(self): """Get the latest data and updates the states.""" # Get previous values of start and end p_start, p_end = self._period # Parse templates self.update_period() start, end = self._period # Convert times to UTC start = dt_util.as_utc(start) end = dt_util.as_utc(end) p_start = dt_util.as_utc(p_start) p_end = dt_util.as_utc(p_end) now = datetime.datetime.now() # Compute integer timestamps start_timestamp = math.floor(dt_util.as_timestamp(start)) end_timestamp = math.floor(dt_util.as_timestamp(end)) p_start_timestamp = math.floor(dt_util.as_timestamp(p_start)) p_end_timestamp = math.floor(dt_util.as_timestamp(p_end)) now_timestamp = math.floor(dt_util.as_timestamp(now)) # If period has not changed and current time after the period end... if start_timestamp == p_start_timestamp and \ end_timestamp == p_end_timestamp and \ end_timestamp <= now_timestamp: # Don't compute anything as the value cannot have changed _LOGGER.debug("Values for %s have not changed", self._name) return if self._last_updated and (self._last_updated + self._scan_interval.total_seconds()) > now_timestamp: # no need to update yet _LOGGER.debug("No need to update %s yet", self._name) return self._session.sync(self._scan_interval) _LOGGER.debug("Synced %s, updating value", self._name) sensor_series = self._session.tmposession.series(self._sensor, head=start_timestamp, tail=end_timestamp) self.value = sensor_series.diff().sum() _LOGGER.debug("Value for %s updated", self._name) self._last_updated = now_timestamp
async def test_wireless_client_go_wired_issue(hass): """Test the solution to catch wireless device go wired UniFi issue. UniFi has a known issue that when a wireless device goes away it sometimes gets marked as wired. """ client_1_client = copy(CLIENT_1) client_1_client["last_seen"] = dt_util.as_timestamp(dt_util.utcnow()) controller = await setup_unifi_integration(hass, clients_response=[client_1_client]) assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 1 # Client is wireless client_1 = hass.states.get("device_tracker.client_1") assert client_1 is not None assert client_1.state == "home" assert client_1.attributes["is_wired"] is False # Trigger wired bug client_1_client["is_wired"] = True event = {"meta": {"message": MESSAGE_CLIENT}, "data": [client_1_client]} controller.api.message_handler(event) await hass.async_block_till_done() # Wired bug fix keeps client marked as wireless client_1 = hass.states.get("device_tracker.client_1") assert client_1.state == "home" assert client_1.attributes["is_wired"] is False # Pass time new_time = dt_util.utcnow() + controller.option_detection_time with patch("homeassistant.util.dt.utcnow", return_value=new_time): async_fire_time_changed(hass, new_time) await hass.async_block_till_done() # Marked as home according to the timer client_1 = hass.states.get("device_tracker.client_1") assert client_1.state == "not_home" assert client_1.attributes["is_wired"] is False # Try to mark client as connected event = {"meta": {"message": MESSAGE_CLIENT}, "data": [client_1_client]} controller.api.message_handler(event) await hass.async_block_till_done() # Make sure it don't go online again until wired bug disappears client_1 = hass.states.get("device_tracker.client_1") assert client_1.state == "not_home" assert client_1.attributes["is_wired"] is False # Make client wireless client_1_client["is_wired"] = False event = {"meta": {"message": MESSAGE_CLIENT}, "data": [client_1_client]} controller.api.message_handler(event) await hass.async_block_till_done() # Client is no longer affected by wired bug and can be marked online client_1 = hass.states.get("device_tracker.client_1") assert client_1.state == "home" assert client_1.attributes["is_wired"] is False
def next_interval(self): """Determine the next time the sensor should be updated""" interval = self._schedule.interval now = dt_util.utcnow() timestamp = int(dt_util.as_timestamp(now)) delta = interval - (timestamp % interval) self._next_update = now + timedelta(seconds=delta) return self._next_update
async def test_timezone_intervals_empty_parameter(hass): """Test get_interval() without parameters.""" new_tz = dt_util.get_time_zone("America/Edmonton") assert new_tz is not None dt_util.set_default_time_zone(new_tz) device = time_date.TimeDateSensor(hass, "date") next_time = device.get_next_interval() assert next_time.timestamp() == dt_util.as_timestamp("2017-11-14 00:00:00-07:00")
async def test_option_ignore_wired_bug(hass): """Test option to ignore wired bug.""" client_1_client = copy(CLIENT_1) client_1_client["last_seen"] = dt_util.as_timestamp(dt_util.utcnow()) controller = await setup_unifi_integration( hass, options={CONF_IGNORE_WIRED_BUG: True}, clients_response=[client_1_client] ) assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 1 # Client is wireless client_1 = hass.states.get("device_tracker.client_1") assert client_1 is not None assert client_1.state == "home" assert client_1.attributes["is_wired"] is False # Trigger wired bug client_1_client["is_wired"] = True event = {"meta": {"message": MESSAGE_CLIENT}, "data": [client_1_client]} controller.api.message_handler(event) await hass.async_block_till_done() # Wired bug in effect client_1 = hass.states.get("device_tracker.client_1") assert client_1.state == "home" assert client_1.attributes["is_wired"] is True # pass time new_time = dt_util.utcnow() + controller.option_detection_time with patch("homeassistant.util.dt.utcnow", return_value=new_time): async_fire_time_changed(hass, new_time) await hass.async_block_till_done() # Timer marks client as away client_1 = hass.states.get("device_tracker.client_1") assert client_1.state == "not_home" assert client_1.attributes["is_wired"] is True # Mark client as connected again event = {"meta": {"message": MESSAGE_CLIENT}, "data": [client_1_client]} controller.api.message_handler(event) await hass.async_block_till_done() # Ignoring wired bug allows client to go home again even while affected client_1 = hass.states.get("device_tracker.client_1") assert client_1.state == "home" assert client_1.attributes["is_wired"] is True # Make client wireless client_1_client["is_wired"] = False event = {"meta": {"message": MESSAGE_CLIENT}, "data": [client_1_client]} controller.api.message_handler(event) await hass.async_block_till_done() # Client is wireless and still connected client_1 = hass.states.get("device_tracker.client_1") assert client_1.state == "home" assert client_1.attributes["is_wired"] is False
def _update_internal_state(self): self._dateObj = DT.datetime.now() self._ts = self._dateObj.timestamp() self._day = self._dateObj.day self._day_TTS = self._getDay_TTS() sunTs = dt_util.as_timestamp( self.hass.states.get('sun.sun').attributes['next_rising']) sunObj = dt_util.utc_from_timestamp(sunTs) sunObj = dt_util.as_local(sunObj) self._sun_next_rising = sunObj.strftime(TIME_FORMAT) self._sun_next_rising_tts = self._getTime_TTS(self._sun_next_rising) sunTs = dt_util.as_timestamp( self.hass.states.get('sun.sun').attributes['next_setting']) sunObj = dt_util.utc_from_timestamp(sunTs) sunObj = dt_util.as_local(sunObj) self._sun_next_setting = sunObj.strftime(TIME_FORMAT) self._sun_next_setting_tts = self._getTime_TTS(self._sun_next_setting) self._monthNames = [ 'Januar', 'Februar', 'Marts', 'April', 'Maj', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'December' ] self._month = self._dateObj.month self._monthName = self._monthNames[self._month - 1] self._year = self._dateObj.year self._weekNumber = self._dateObj.isocalendar()[1] self._evenWeek = int(self._weekNumber) % 2 == 0 self._weekdaysShort = [ 'Man', 'Tirs', 'Ons', 'Tors', 'Fre', 'Lør', 'Søn' ] self._weekday = self._dateObj.weekday() self._weekdayNameShort = self._weekdaysShort[self._weekday] self._weekdayName = self._weekdayNameShort + 'dag' self._time = self._getTime() self._time_TTS = self._getTime_TTS() self._adventsDates = self._getAdventsDates() self._state = f'{ self._weekdayName} den { self._day }. { self._monthName.lower() } { self._year }'
def test_timezone_intervals_empty_parameter(self, _): """Test get_interval() without parameters.""" new_tz = dt_util.get_time_zone('America/Edmonton') assert new_tz is not None dt_util.set_default_time_zone(new_tz) device = time_date.TimeDateSensor(self.hass, 'date') next_time = device.get_next_interval() assert (next_time.timestamp() == dt_util.as_timestamp( '2017-11-14 00:00:00-07:00'))
def test_scan_devices_filtered(): """Test the scanning for devices based on SSID.""" ctrl = mock.MagicMock() fake_clients = [ {'mac': '123', 'essid': 'foonet', 'last_seen': dt_util.as_timestamp(dt_util.utcnow())}, {'mac': '234', 'essid': 'foonet', 'last_seen': dt_util.as_timestamp(dt_util.utcnow())}, {'mac': '567', 'essid': 'notnet', 'last_seen': dt_util.as_timestamp(dt_util.utcnow())}, {'mac': '890', 'essid': 'barnet', 'last_seen': dt_util.as_timestamp(dt_util.utcnow())}, ] ssid_filter = ['foonet', 'barnet'] ctrl.get_clients.return_value = fake_clients scanner = unifi.UnifiScanner(ctrl, DEFAULT_DETECTION_TIME, ssid_filter) assert set(scanner.scan_devices()) == set(['123', '234', '890'])
async def async_unrestrict_watering(call: ServiceCall) -> None: """Unrestrict watering.""" controller = async_get_controller_for_service_call(hass, call) await controller.restrictions.set_universal( { "rainDelayStartTime": round(as_timestamp(utcnow())), "rainDelayDuration": 0, }, ) await async_update_programs_and_zones(hass, entry)
def test_timezone_intervals_empty_parameter(self, _): """Test get_interval() without parameters.""" new_tz = dt_util.get_time_zone('America/Edmonton') assert new_tz is not None dt_util.set_default_time_zone(new_tz) device = time_date.TimeDateSensor(self.hass, 'date') next_time = device.get_next_interval() assert (next_time.timestamp() == dt_util.as_timestamp('2017-11-14 00:00:00-07:00'))
def test_timestamp_utc(self): """Test the timestamps to local filter.""" tests = { None: "None", 1469119144: "2016-07-21 16:39:04", dt_util.as_timestamp(dt_util.utcnow()): dt_util.now().strftime("%Y-%m-%d %H:%M:%S"), } for inp, out in tests.items(): self.assertEqual(out, template.Template("{{ %s | timestamp_utc }}" % inp, self.hass).render())
def test_get_device_name(): """Test the getting of device names.""" ctrl = mock.MagicMock() fake_clients = [ {'mac': '123', 'hostname': 'foobar', 'last_seen': dt_util.as_timestamp(dt_util.utcnow())}, {'mac': '234', 'name': 'Nice Name', 'last_seen': dt_util.as_timestamp(dt_util.utcnow())}, {'mac': '456', 'last_seen': '1504786810'}, ] ctrl.get_clients.return_value = fake_clients scanner = unifi.UnifiScanner(ctrl, DEFAULT_DETECTION_TIME) assert scanner.get_device_name('123') == 'foobar' assert scanner.get_device_name('234') == 'Nice Name' assert scanner.get_device_name('456') is None assert scanner.get_device_name('unknown') is None
def test_timestamp_utc(self): """Test the timestamps to local filter.""" now = dt_util.utcnow() tests = { None: 'None', 1469119144: '2016-07-21 16:39:04', dt_util.as_timestamp(now): now.strftime('%Y-%m-%d %H:%M:%S') } for inp, out in tests.items(): assert out == \ template.Template('{{ %s | timestamp_utc }}' % inp, self.hass).render()
def test_timestamp_utc(self): """Test the timestamps to local filter.""" tests = { None: 'None', 1469119144: '2016-07-21 16:39:04', dt_util.as_timestamp(dt_util.utcnow()): dt_util.now().strftime('%Y-%m-%d %H:%M:%S') } for inp, out in tests.items(): self.assertEqual( out, template.render(self.hass, '{{ %s | timestamp_utc }}' % inp))
def get_next_interval(self, now=None): """Compute next time an update should occur.""" if now is None: now = dt_util.utcnow() if self.type == 'date': now = dt_util.start_of_local_day(dt_util.as_local(now)) return now + timedelta(seconds=86400) if self.type == 'beat': interval = 86.4 else: interval = 60 timestamp = int(dt_util.as_timestamp(now)) delta = interval - (timestamp % interval) return now + timedelta(seconds=delta)
def __init__(self, hass, name): """Initialize Demo mailbox.""" super().__init__(hass, name) self._messages = {} txt = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " for idx in range(0, 10): msgtime = int(dt.as_timestamp( dt.utcnow()) - 3600 * 24 * (10 - idx)) msgtxt = "Message {}. {}".format( idx + 1, txt * (1 + idx * (idx % 2))) msgsha = sha1(msgtxt.encode('utf-8')).hexdigest() msg = {"info": {"origtime": msgtime, "callerid": "John Doe <212-555-1212>", "duration": "10"}, "text": msgtxt, "sha": msgsha} self._messages[msgsha] = msg
def test_timestamp_custom(self): """Test the timestamps to custom filter.""" tests = [ (None, None, None, "None"), (1469119144, None, True, "2016-07-21 16:39:04"), (1469119144, "%Y", True, "2016"), (1469119144, "invalid", True, "invalid"), (dt_util.as_timestamp(dt_util.utcnow()), None, False, dt_util.now().strftime("%Y-%m-%d %H:%M:%S")), ] for inp, fmt, local, out in tests: if fmt: fil = "timestamp_custom('{}')".format(fmt) elif fmt and local: fil = "timestamp_custom('{0}', {1})".format(fmt, local) else: fil = "timestamp_custom" self.assertEqual(out, template.Template("{{ %s | %s }}" % (inp, fil), self.hass).render())
def test_timezone_intervals(self): """Test date sensor behavior in a timezone besides UTC.""" new_tz = dt_util.get_time_zone('America/New_York') assert new_tz is not None dt_util.set_default_time_zone(new_tz) device = time_date.TimeDateSensor(self.hass, 'date') now = dt_util.utc_from_timestamp(50000) next_time = device.get_next_interval(now) # start of local day in EST was 18000.0 # so the second day was 18000 + 86400 assert next_time.timestamp() == 104400 new_tz = dt_util.get_time_zone('America/Edmonton') assert new_tz is not None dt_util.set_default_time_zone(new_tz) now = dt_util.parse_datetime('2017-11-13 19:47:19-07:00') device = time_date.TimeDateSensor(self.hass, 'date') next_time = device.get_next_interval(now) assert (next_time.timestamp() == dt_util.as_timestamp('2017-11-14 00:00:00-07:00'))
def __init__(self, hass, name): """Initialize Demo mailbox.""" super().__init__(hass, name) self._messages = {} txt = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " for idx in range(0, 10): msgtime = int(dt.as_timestamp( dt.utcnow()) - 3600 * 24 * (10 - idx)) msgtxt = "Message {}. {}".format( idx + 1, txt * (1 + idx * (idx % 2))) msgsha = sha1(msgtxt.encode('utf-8')).hexdigest() msg = { 'info': { 'origtime': msgtime, 'callerid': 'John Doe <212-555-1212>', 'duration': '10', }, 'text': msgtxt, 'sha': msgsha, } self._messages[msgsha] = msg
def test_timestamp_custom(self): """Test the timestamps to custom filter.""" now = dt_util.utcnow() tests = [ (None, None, None, 'None'), (1469119144, None, True, '2016-07-21 16:39:04'), (1469119144, '%Y', True, '2016'), (1469119144, 'invalid', True, 'invalid'), (dt_util.as_timestamp(now), None, False, now.strftime('%Y-%m-%d %H:%M:%S')) ] for inp, fmt, local, out in tests: if fmt: fil = 'timestamp_custom(\'{}\')'.format(fmt) elif fmt and local: fil = 'timestamp_custom(\'{0}\', {1})'.format(fmt, local) else: fil = 'timestamp_custom' assert out == template.Template( '{{ %s | %s }}' % (inp, fil), self.hass).render()
def update(self): """Get the latest data and updates the states.""" # Parse templates self.update_period() start, end = self._period # Convert to UTC start = dt_util.as_utc(start) end = dt_util.as_utc(end) # Get history between start and end history_list = history.state_changes_during_period( start, end, str(self._entity_id)) if self._entity_id not in history_list.keys(): return # Get the first state last_state = history.get_state(start, self._entity_id) last_state = (last_state is not None and last_state == self._entity_state) last_time = dt_util.as_timestamp(start) elapsed = 0 # Make calculations for item in history_list.get(self._entity_id): current_state = item.state == self._entity_state current_time = item.last_changed.timestamp() if last_state: elapsed += current_time - last_time last_state = current_state last_time = current_time # Save value in hours self.value = elapsed / 3600
def get(self, request): """Get SpaceAPI data.""" hass = request.app['hass'] spaceapi = dict(hass.data[DATA_SPACEAPI]) is_sensors = spaceapi.get('sensors') location = { ATTR_ADDRESS: spaceapi[ATTR_LOCATION][CONF_ADDRESS], ATTR_LATITUDE: hass.config.latitude, ATTR_LONGITUDE: hass.config.longitude, } state_entity = spaceapi['state'][ATTR_ENTITY_ID] space_state = hass.states.get(state_entity) if space_state is not None: state = { ATTR_OPEN: False if space_state.state == 'off' else True, ATTR_LASTCHANGE: dt_util.as_timestamp(space_state.last_updated), } else: state = {ATTR_OPEN: 'null', ATTR_LASTCHANGE: 0} try: state[ATTR_ICON] = { ATTR_OPEN: spaceapi['state'][CONF_ICON_OPEN], ATTR_CLOSE: spaceapi['state'][CONF_ICON_CLOSED], } except KeyError: pass data = { ATTR_API: SPACEAPI_VERSION, ATTR_CONTACT: spaceapi[CONF_CONTACT], ATTR_ISSUE_REPORT_CHANNELS: spaceapi[CONF_ISSUE_REPORT_CHANNELS], ATTR_LOCATION: location, ATTR_LOGO: spaceapi[CONF_LOGO], ATTR_SPACE: spaceapi[CONF_SPACE], ATTR_STATE: state, ATTR_URL: spaceapi[CONF_URL], } if is_sensors is not None: sensors = {} for sensor_type in is_sensors: sensors[sensor_type] = [] for sensor in spaceapi['sensors'][sensor_type]: sensor_state = hass.states.get(sensor) unit = sensor_state.attributes[ATTR_UNIT_OF_MEASUREMENT] value = sensor_state.state sensor_data = { ATTR_LOCATION: spaceapi[CONF_SPACE], ATTR_NAME: sensor_state.name, ATTR_UNIT: unit, ATTR_VALUE: value, } sensors[sensor_type].append(sensor_data) data[ATTR_SENSORS] = sensors return self.json(data)
def forgiving_as_timestamp(value): """Try to convert value to timestamp.""" try: return dt_util.as_timestamp(value) except (ValueError, TypeError): return None
def update(self): """Get the latest data and updates the states.""" # Get previous values of start and end p_start, p_end = self._period # Parse templates self.update_period() start, end = self._period # Convert times to UTC start = dt_util.as_utc(start) end = dt_util.as_utc(end) p_start = dt_util.as_utc(p_start) p_end = dt_util.as_utc(p_end) now = datetime.datetime.now() # Compute integer timestamps start_timestamp = math.floor(dt_util.as_timestamp(start)) end_timestamp = math.floor(dt_util.as_timestamp(end)) p_start_timestamp = math.floor(dt_util.as_timestamp(p_start)) p_end_timestamp = math.floor(dt_util.as_timestamp(p_end)) now_timestamp = math.floor(dt_util.as_timestamp(now)) # If period has not changed and current time after the period end... if start_timestamp == p_start_timestamp and \ end_timestamp == p_end_timestamp and \ end_timestamp <= now_timestamp: # Don't compute anything as the value cannot have changed return # Get history between start and end history_list = history.state_changes_during_period( self.hass, start, end, str(self._entity_id)) if self._entity_id not in history_list.keys(): return # Get the first state last_state = history.get_state(self.hass, start, self._entity_id) last_state = (last_state is not None and last_state == self._entity_state) last_time = start_timestamp elapsed = 0 count = 0 # Make calculations for item in history_list.get(self._entity_id): current_state = item.state == self._entity_state current_time = item.last_changed.timestamp() if last_state: elapsed += current_time - last_time if current_state and not last_state: count += 1 last_state = current_state last_time = current_time # Count time elapsed between last history state and end of measure if last_state: measure_end = min(end_timestamp, now_timestamp) elapsed += measure_end - last_time # Save value in hours self.value = elapsed / 3600 # Save counter self.count = count