def time_zone(value):
    """Validate timezone."""
    if dt_util.get_time_zone(value) is not None:
        return value
    raise vol.Invalid(
        'Invalid time zone passed in. Valid options can be found here: '
        'http://en.wikipedia.org/wiki/List_of_tz_database_time_zones')
Example #2
0
    def test_periodic_task_leaving_dst(self):
        """Test periodic task behavior when leaving dst."""
        tz = dt_util.get_time_zone('Europe/Vienna')
        dt_util.set_default_time_zone(tz)
        specific_runs = []

        unsub = track_time_change(
            self.hass, lambda x: specific_runs.append(1), hour=2, minute=30,
            second=0)

        self._send_time_changed(
            tz.localize(datetime(2018, 10, 28, 2, 5, 0), is_dst=False))
        self.hass.block_till_done()
        assert 0 == len(specific_runs)

        self._send_time_changed(
            tz.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=False))
        self.hass.block_till_done()
        assert 1 == len(specific_runs)

        self._send_time_changed(
            tz.localize(datetime(2018, 10, 28, 2, 5, 0), is_dst=True))
        self.hass.block_till_done()
        assert 1 == len(specific_runs)

        self._send_time_changed(
            tz.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=True))
        self.hass.block_till_done()
        assert 2 == len(specific_runs)

        unsub()
Example #3
0
def get_test_home_assistant(num_threads=None):
    """Return a Home Assistant object pointing at test config dir."""
    loop = asyncio.new_event_loop()

    if num_threads:
        orig_num_threads = ha.MIN_WORKER_THREAD
        ha.MIN_WORKER_THREAD = num_threads

    hass = ha.HomeAssistant(loop)

    if num_threads:
        ha.MIN_WORKER_THREAD = orig_num_threads

    hass.config.location_name = 'test home'
    hass.config.config_dir = get_test_config_dir()
    hass.config.latitude = 32.87336
    hass.config.longitude = -117.22743
    hass.config.elevation = 0
    hass.config.time_zone = date_util.get_time_zone('US/Pacific')
    hass.config.units = METRIC_SYSTEM
    hass.config.skip_pip = True

    if 'custom_components.test' not in loader.AVAILABLE_COMPONENTS:
        loader.prepare(hass)

    # FIXME should not be a daemon. Means hass.stop() not called in teardown
    stop_event = threading.Event()

    def run_loop():
        loop.run_forever()
        loop.close()
        stop_event.set()

    threading.Thread(name="LoopThread", target=run_loop, daemon=True).start()

    orig_start = hass.start
    orig_stop = hass.stop

    @asyncio.coroutine
    def fake_stop():
        yield None

    def start_hass():
        """Helper to start hass."""
        with patch.object(hass.loop, 'run_forever', return_value=None):
            with patch.object(hass, 'async_stop', return_value=fake_stop()):
                with patch.object(ha, 'async_create_timer', return_value=None):
                    with patch.object(ha, 'async_monitor_worker_pool',
                                      return_value=None):
                        orig_start()
                        hass.block_till_done()

    def stop_hass():
        orig_stop()
        stop_event.wait()

    hass.start = start_hass
    hass.stop = stop_hass

    return hass
Example #4
0
def async_test_home_assistant(loop):
    """Return a Home Assistant object pointing at test config dir."""
    loop._thread_ident = threading.get_ident()

    hass = ha.HomeAssistant(loop)
    hass.async_track_tasks()

    hass.config.location_name = 'test home'
    hass.config.config_dir = get_test_config_dir()
    hass.config.latitude = 32.87336
    hass.config.longitude = -117.22743
    hass.config.elevation = 0
    hass.config.time_zone = date_util.get_time_zone('US/Pacific')
    hass.config.units = METRIC_SYSTEM
    hass.config.skip_pip = True

    if 'custom_components.test' not in loader.AVAILABLE_COMPONENTS:
        yield from loop.run_in_executor(None, loader.prepare, hass)

    hass.state = ha.CoreState.running

    # Mock async_start
    orig_start = hass.async_start

    @asyncio.coroutine
    def mock_async_start():
        """Start the mocking."""
        with patch('homeassistant.core._async_create_timer'):
            yield from orig_start()

    hass.async_start = mock_async_start

    return hass
async def async_setup_platform(
        hass, config, async_add_entities, discovery_info=None):
    """Set up the World clock sensor."""
    name = config.get(CONF_NAME)
    time_zone = dt_util.get_time_zone(config.get(CONF_TIME_ZONE))

    async_add_entities([WorldClockSensor(time_zone, name)], True)
    def setUp(self):
        """Setup things to be run when tests are started."""
        self.hass = get_test_home_assistant()

        # Set our timezone to CST/Regina so we can check calculations
        # This keeps UTC-6 all year round
        dt_util.set_default_time_zone(dt_util.get_time_zone('America/Regina'))
Example #7
0
    def test_now(self):
        """Test the now method."""
        dt_util.set_default_time_zone(dt_util.get_time_zone(TEST_TIME_ZONE))

        self.assertAlmostEqual(
            dt_util.as_utc(dt_util.now()).replace(tzinfo=None),
            datetime.utcnow(),
            delta=timedelta(seconds=1))
Example #8
0
    def test_set_default_time_zone(self):
        """Test setting default time zone."""
        time_zone = dt_util.get_time_zone(TEST_TIME_ZONE)

        dt_util.set_default_time_zone(time_zone)

        # We cannot compare the timezones directly because of DST
        assert time_zone.zone == dt_util.now().tzinfo.zone
Example #9
0
    def test_as_utc_with_local_object(self):
        """Test the UTC time with local object."""
        dt_util.set_default_time_zone(dt_util.get_time_zone(TEST_TIME_ZONE))
        localnow = dt_util.now()
        utcnow = dt_util.as_utc(localnow)

        assert localnow == utcnow
        assert localnow.tzinfo != utcnow.tzinfo
Example #10
0
    def setUp(self):
        """Set up things to be run when tests are started."""
        self.hass = get_test_home_assistant()
        self.time_zone = dt_util.get_time_zone("America/New_York")

        config = {"sensor": {"platform": "worldclock", "time_zone": "America/New_York"}}

        self.assertTrue(setup_component(self.hass, "sensor", config))
Example #11
0
    def test_as_local_with_utc_object(self):
        dt_util.set_default_time_zone(dt_util.get_time_zone(TEST_TIME_ZONE))

        utcnow = dt_util.utcnow()
        localnow = dt_util.as_local(utcnow)

        self.assertEqual(localnow, utcnow)
        self.assertNotEqual(localnow.tzinfo, utcnow.tzinfo)
 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'))
Example #13
0
    def test_as_local_with_utc_object(self):
        """Test local time with UTC object."""
        dt_util.set_default_time_zone(dt_util.get_time_zone(TEST_TIME_ZONE))

        utcnow = dt_util.utcnow()
        localnow = dt_util.as_local(utcnow)

        assert localnow == utcnow
        assert localnow.tzinfo != utcnow.tzinfo
Example #14
0
    def test_now(self):
        """Test the now method."""
        dt_util.set_default_time_zone(dt_util.get_time_zone(TEST_TIME_ZONE))

        assert abs(
            dt_util.as_utc(dt_util.now()).replace(
                tzinfo=None
            ) - datetime.utcnow()
        ) < timedelta(seconds=1)
Example #15
0
def async_test_home_assistant(loop):
    """Return a Home Assistant object pointing at test config dir."""
    global INST_COUNT
    INST_COUNT += 1
    loop._thread_ident = threading.get_ident()

    hass = ha.HomeAssistant(loop)

    orig_async_add_job = hass.async_add_job

    def async_add_job(target, *args):
        """Add a magic mock."""
        if isinstance(target, Mock):
            return mock_coro(target())
        return orig_async_add_job(target, *args)

    hass.async_add_job = async_add_job

    hass.config.location_name = 'test home'
    hass.config.config_dir = get_test_config_dir()
    hass.config.latitude = 32.87336
    hass.config.longitude = -117.22743
    hass.config.elevation = 0
    hass.config.time_zone = date_util.get_time_zone('US/Pacific')
    hass.config.units = METRIC_SYSTEM
    hass.config.skip_pip = True

    if 'custom_components.test' not in loader.AVAILABLE_COMPONENTS:
        yield from loop.run_in_executor(None, loader.prepare, hass)

    hass.state = ha.CoreState.running

    # Mock async_start
    orig_start = hass.async_start

    @asyncio.coroutine
    def mock_async_start():
        """Start the mocking."""
        # 1. We only mock time during tests
        # 2. We want block_till_done that is called inside stop_track_tasks
        with patch('homeassistant.core._async_create_timer'), \
                patch.object(hass, 'async_stop_track_tasks'):
            yield from orig_start()

    hass.async_start = mock_async_start

    @ha.callback
    def clear_instance(event):
        """Clear global instance."""
        global INST_COUNT
        INST_COUNT -= 1

    hass.bus.async_listen_once(EVENT_HOMEASSISTANT_CLOSE, clear_instance)

    return hass
Example #16
0
def async_test_home_assistant(loop):
    """Return a Home Assistant object pointing at test config dir."""
    hass = ha.HomeAssistant(loop)
    hass.config.async_load = Mock()
    store = auth.AuthStore(hass)
    hass.auth = auth.AuthManager(hass, store, {})
    ensure_auth_manager_loaded(hass.auth)
    INSTANCES.append(hass)

    orig_async_add_job = hass.async_add_job

    def async_add_job(target, *args):
        """Add a magic mock."""
        if isinstance(target, Mock):
            return mock_coro(target(*args))
        return orig_async_add_job(target, *args)

    hass.async_add_job = async_add_job

    hass.config.location_name = 'test home'
    hass.config.config_dir = get_test_config_dir()
    hass.config.latitude = 32.87336
    hass.config.longitude = -117.22743
    hass.config.elevation = 0
    hass.config.time_zone = date_util.get_time_zone('US/Pacific')
    hass.config.units = METRIC_SYSTEM
    hass.config.skip_pip = True

    hass.config_entries = config_entries.ConfigEntries(hass, {})
    hass.config_entries._entries = []
    hass.config_entries._store._async_ensure_stop_listener = lambda: None

    hass.state = ha.CoreState.running

    # Mock async_start
    orig_start = hass.async_start

    @asyncio.coroutine
    def mock_async_start():
        """Start the mocking."""
        # We only mock time during tests and we want to track tasks
        with patch('homeassistant.core._async_create_timer'), \
                patch.object(hass, 'async_stop_track_tasks'):
            yield from orig_start()

    hass.async_start = mock_async_start

    @ha.callback
    def clear_instance(event):
        """Clear global instance."""
        INSTANCES.remove(hass)

    hass.bus.async_listen_once(EVENT_HOMEASSISTANT_CLOSE, clear_instance)

    return hass
Example #17
0
    def set_time_zone(time_zone_str):
        """ Helper method to set time zone in HA. """
        if time_zone_str is None:
            return

        time_zone = date_util.get_time_zone(time_zone_str)

        if time_zone:
            hac.time_zone = time_zone
            date_util.set_default_time_zone(time_zone)
        else:
            _LOGGER.error("Received invalid time zone %s", time_zone_str)
    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'))
Example #19
0
    def set_time_zone(time_zone_str: Optional[str]) -> None:
        """Help to set the time zone."""
        if time_zone_str is None:
            return

        time_zone = date_util.get_time_zone(time_zone_str)

        if time_zone:
            hac.time_zone = time_zone
            date_util.set_default_time_zone(time_zone)
        else:
            _LOGGER.error("Received invalid time zone %s", time_zone_str)
    def setUp(self):
        """Set up things to be run when tests are started."""
        self.hass = get_test_home_assistant()
        self.time_zone = dt_util.get_time_zone('America/New_York')

        config = {
            'sensor': {
                'platform': 'worldclock',
                'time_zone': 'America/New_York',
            }
        }

        assert setup_component(self.hass, 'sensor', config)
Example #21
0
def setup_platform(hass, config, add_devices, discovery_info=None):
    """Setup the Worldclock sensor."""
    try:
        time_zone = dt_util.get_time_zone(config.get('time_zone'))
    except AttributeError:
        _LOGGER.error("time_zone in platform configuration is missing.")
        return False

    if time_zone is None:
        _LOGGER.error("Timezone '%s' is not valid.", config.get('time_zone'))
        return False

    add_devices([WorldClockSensor(
        time_zone,
        config.get('name', DEFAULT_NAME)
    )])
 def test_jewish_calendar_sensor(self, time, tzname, latitude, longitude,
                                 language, sensor, diaspora, result):
     """Test Jewish calendar sensor output."""
     tz = get_time_zone(tzname)
     set_default_time_zone(tz)
     test_time = tz.localize(time)
     self.hass.config.latitude = latitude
     self.hass.config.longitude = longitude
     sensor = JewishCalSensor(
         name='test', language=language, sensor_type=sensor,
         latitude=latitude, longitude=longitude,
         timezone=tz, diaspora=diaspora)
     sensor.hass = self.hass
     with patch('homeassistant.util.dt.now', return_value=test_time):
         run_coroutine_threadsafe(
             sensor.async_update(),
             self.hass.loop).result()
         assert sensor.state == result
Example #23
0
    def test_find_next_time_expression_time_dst(self):
        """Test daylight saving time for find_next_time_expression_time."""
        tz = dt_util.get_time_zone('Europe/Vienna')
        dt_util.set_default_time_zone(tz)

        def find(dt, hour, minute, second):
            """Call test_find_next_time_expression_time."""
            seconds = dt_util.parse_time_expression(second, 0, 59)
            minutes = dt_util.parse_time_expression(minute, 0, 59)
            hours = dt_util.parse_time_expression(hour, 0, 23)

            return dt_util.find_next_time_expression_time(
                dt, seconds, minutes, hours)

        # Entering DST, clocks are rolled forward
        assert tz.localize(datetime(2018, 3, 26, 2, 30, 0)) == \
            find(tz.localize(datetime(2018, 3, 25, 1, 50, 0)), 2, 30, 0)

        assert tz.localize(datetime(2018, 3, 26, 2, 30, 0)) == \
            find(tz.localize(datetime(2018, 3, 25, 3, 50, 0)), 2, 30, 0)

        assert tz.localize(datetime(2018, 3, 26, 2, 30, 0)) == \
            find(tz.localize(datetime(2018, 3, 26, 1, 50, 0)), 2, 30, 0)

        # Leaving DST, clocks are rolled back
        assert tz.localize(datetime(2018, 10, 28, 2, 30, 0), is_dst=False) == \
            find(tz.localize(datetime(2018, 10, 28, 2, 5, 0), is_dst=False),
                 2, 30, 0)

        assert tz.localize(datetime(2018, 10, 28, 2, 30, 0), is_dst=False) == \
            find(tz.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=True),
                 2, 30, 0)

        assert tz.localize(datetime(2018, 10, 28, 4, 30, 0), is_dst=False) == \
            find(tz.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=True),
                 4, 30, 0)

        assert tz.localize(datetime(2018, 10, 28, 2, 30, 0), is_dst=True) == \
            find(tz.localize(datetime(2018, 10, 28, 2, 5, 0), is_dst=True),
                 2, 30, 0)

        assert tz.localize(datetime(2018, 10, 29, 2, 30, 0)) == \
            find(tz.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=False),
                 2, 30, 0)
Example #24
0
 def test_issur_melacha_sensor(self, now, candle_lighting, havdalah,
                               diaspora, tzname, latitude, longitude,
                               result):
     """Test Issur Melacha sensor output."""
     time_zone = get_time_zone(tzname)
     set_default_time_zone(time_zone)
     test_time = time_zone.localize(now)
     self.hass.config.latitude = latitude
     self.hass.config.longitude = longitude
     sensor = JewishCalSensor(
         name='test', language='english',
         sensor_type='issur_melacha_in_effect',
         latitude=latitude, longitude=longitude,
         timezone=time_zone, diaspora=diaspora, havdalah_offset=havdalah,
         candle_lighting_offset=candle_lighting)
     sensor.hass = self.hass
     with patch('homeassistant.util.dt.now', return_value=test_time):
         run_coroutine_threadsafe(
             sensor.async_update(),
             self.hass.loop).result()
         assert sensor.state == result
Example #25
0
def get_test_home_assistant(num_threads=None):
    """Return a Home Assistant object pointing at test config dir."""
    if num_threads:
        orig_num_threads = ha.MIN_WORKER_THREAD
        ha.MIN_WORKER_THREAD = num_threads

    hass = ha.HomeAssistant()

    if num_threads:
        ha.MIN_WORKER_THREAD = orig_num_threads

    hass.config.config_dir = get_test_config_dir()
    hass.config.latitude = 32.87336
    hass.config.longitude = -117.22743
    hass.config.time_zone = date_util.get_time_zone('US/Pacific')
    hass.config.temperature_unit = TEMP_CELCIUS

    if 'custom_components.test' not in loader.AVAILABLE_COMPONENTS:
        loader.prepare(hass)

    return hass
def test_find_next_time_expression_time_leave_dst_chicago_into_the_fold_same_time():
    """Test leaving daylight saving time for find_next_time_expression_time."""
    tz = dt_util.get_time_zone("America/Chicago")
    dt_util.set_default_time_zone(tz)

    # Leaving DST, clocks are rolled back

    # Find the same time inside the fold
    hour_minute_second = (1, 30, 1)
    test_time = datetime(2021, 11, 7, *hour_minute_second, tzinfo=tz, fold=0)
    matching_hours, matching_minutes, matching_seconds = _get_matches(
        *hour_minute_second
    )

    next_time = dt_util.find_next_time_expression_time(
        test_time, matching_seconds, matching_minutes, matching_hours
    )
    assert next_time == datetime(2021, 11, 7, *hour_minute_second, tzinfo=tz, fold=1)
    assert next_time.fold == 0
    assert dt_util.as_utc(next_time) == datetime(
        2021, 11, 7, 6, 30, 1, tzinfo=dt_util.UTC
    )
Example #27
0
def test_auto_purge(hass_recorder):
    """Test saving and restoring a state."""
    hass = hass_recorder()

    original_tz = dt_util.DEFAULT_TIME_ZONE

    tz = dt_util.get_time_zone("Europe/Copenhagen")
    dt_util.set_default_time_zone(tz)

    test_time = tz.localize(datetime(2020, 1, 1, 4, 12, 0))

    with patch("homeassistant.components.recorder.purge.purge_old_data"
               ) as purge_old_data:
        for delta in (-1, 0, 1):
            hass.bus.fire(EVENT_TIME_CHANGED,
                          {ATTR_NOW: test_time + timedelta(seconds=delta)})
            hass.block_till_done()
            hass.data[DATA_INSTANCE].block_till_done()

        assert len(purge_old_data.mock_calls) == 1

    dt_util.set_default_time_zone(original_tz)
Example #28
0
def get_test_home_assistant(num_threads=None):
    """Return a Home Assistant object pointing at test config dir."""
    if num_threads:
        orig_num_threads = ha.MIN_WORKER_THREAD
        ha.MIN_WORKER_THREAD = num_threads

    hass = ha.HomeAssistant()

    if num_threads:
        ha.MIN_WORKER_THREAD = orig_num_threads

    hass.config.config_dir = get_test_config_dir()
    hass.config.latitude = 32.87336
    hass.config.longitude = -117.22743
    hass.config.elevation = 0
    hass.config.time_zone = date_util.get_time_zone('US/Pacific')
    hass.config.units = METRIC_SYSTEM

    if 'custom_components.test' not in loader.AVAILABLE_COMPONENTS:
        loader.prepare(hass)

    return hass
Example #29
0
def test_find_next_time_expression_time_dst():
    """Test daylight saving time for find_next_time_expression_time."""
    tz = dt_util.get_time_zone("Europe/Vienna")
    dt_util.set_default_time_zone(tz)

    def find(dt, hour, minute, second):
        """Call test_find_next_time_expression_time."""
        seconds = dt_util.parse_time_expression(second, 0, 59)
        minutes = dt_util.parse_time_expression(minute, 0, 59)
        hours = dt_util.parse_time_expression(hour, 0, 23)

        return dt_util.find_next_time_expression_time(dt, seconds, minutes,
                                                      hours)

    # Entering DST, clocks are rolled forward
    assert tz.localize(datetime(2018, 3, 26, 2, 30, 0)) == find(
        tz.localize(datetime(2018, 3, 25, 1, 50, 0)), 2, 30, 0)

    assert tz.localize(datetime(2018, 3, 26, 2, 30, 0)) == find(
        tz.localize(datetime(2018, 3, 25, 3, 50, 0)), 2, 30, 0)

    assert tz.localize(datetime(2018, 3, 26, 2, 30, 0)) == find(
        tz.localize(datetime(2018, 3, 26, 1, 50, 0)), 2, 30, 0)

    # Leaving DST, clocks are rolled back
    assert tz.localize(datetime(2018, 10, 28, 2, 30, 0), is_dst=False) == find(
        tz.localize(datetime(2018, 10, 28, 2, 5, 0), is_dst=False), 2, 30, 0)

    assert tz.localize(datetime(2018, 10, 28, 2, 30, 0), is_dst=False) == find(
        tz.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=True), 2, 30, 0)

    assert tz.localize(datetime(2018, 10, 28, 4, 30, 0), is_dst=False) == find(
        tz.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=True), 4, 30, 0)

    assert tz.localize(datetime(2018, 10, 28, 2, 30, 0), is_dst=True) == find(
        tz.localize(datetime(2018, 10, 28, 2, 5, 0), is_dst=True), 2, 30, 0)

    assert tz.localize(datetime(2018, 10, 29, 2, 30, 0)) == find(
        tz.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=False), 2, 30, 0)
Example #30
0
    def test_shabbat_times_sensor(self, now, candle_lighting, havdalah,
                                  diaspora, tzname, latitude, longitude,
                                  result):
        """Test sensor output for upcoming shabbat/yomtov times."""
        time_zone = get_time_zone(tzname)
        set_default_time_zone(time_zone)
        test_time = time_zone.localize(now)
        for sensor_type, value in result.items():
            if isinstance(value, dt):
                result[sensor_type] = time_zone.localize(value)
        self.hass.config.latitude = latitude
        self.hass.config.longitude = longitude

        if ('upcoming_shabbat_candle_lighting' in result
                and 'upcoming_candle_lighting' not in result):
            result['upcoming_candle_lighting'] = \
                result['upcoming_shabbat_candle_lighting']
        if ('upcoming_shabbat_havdalah' in result
                and 'upcoming_havdalah' not in result):
            result['upcoming_havdalah'] = result['upcoming_shabbat_havdalah']

        for sensor_type, result_value in result.items():
            language = 'english'
            if sensor_type.startswith('hebrew_'):
                language = 'hebrew'
                sensor_type = sensor_type.replace('hebrew_', '')
            sensor = JewishCalSensor(
                name='test', language=language, sensor_type=sensor_type,
                latitude=latitude, longitude=longitude,
                timezone=time_zone, diaspora=diaspora,
                havdalah_offset=havdalah,
                candle_lighting_offset=candle_lighting)
            sensor.hass = self.hass
            with patch('homeassistant.util.dt.now', return_value=test_time):
                run_coroutine_threadsafe(
                    sensor.async_update(),
                    self.hass.loop).result()
                assert sensor.state == result_value, "Value for {}".format(
                    sensor_type)
Example #31
0
    async def async_update(self) -> None:
        """Retrieve latest state."""
        when = dt.now()
        _state: TrainStop | None = None
        if self._time:
            departure_day = next_departuredate(self._weekday)
            when = datetime.combine(
                departure_day, self._time,
                dt.get_time_zone(self.hass.config.time_zone))
        try:
            if self._time:
                _state = await self._train_api.async_get_train_stop(
                    self._from_station, self._to_station, when)
            else:

                _state = await self._train_api.async_get_next_train_stop(
                    self._from_station, self._to_station, when)
        except ValueError as output_error:
            _LOGGER.error("Departure %s encountered a problem: %s", when,
                          output_error)

        if not _state:
            self._attr_available = False
            self._attr_native_value = None
            self._attr_extra_state_attributes = {}
            return

        self._attr_available = True

        # The original datetime doesn't provide a timezone so therefore attaching it here.
        self._attr_native_value = dt.as_utc(_state.advertised_time_at_location)
        if _state.time_at_location:
            self._attr_native_value = dt.as_utc(_state.time_at_location)
        if _state.estimated_time_at_location:
            self._attr_native_value = dt.as_utc(
                _state.estimated_time_at_location)

        self._update_attributes(_state)
Example #32
0
    def update(self):
        """Update the data for the sensor."""
        time_zone = dt_util.get_time_zone(self.hass.config.time_zone)
        start = get_date(time_zone)
        end = get_date(time_zone, self.days)
        try:
            res = requests.get(
                ENDPOINTS[self.type].format(self.ssl, self.host, self.port,
                                            self.urlbase, start, end),
                headers={"X-Api-Key": self.apikey},
                timeout=10,
            )
        except OSError:
            _LOGGER.warning("Host %s is not available", self.host)
            self._available = False
            self._state = None
            return

        if res.status_code == HTTP_OK:
            if self.type in ["upcoming", "movies", "commands"]:
                self.data = res.json()
                self._state = len(self.data)
            elif self.type == "diskspace":
                # If included paths are not provided, use all data
                if self.included == []:
                    self.data = res.json()
                else:
                    # Filter to only show lists that are included
                    self.data = list(
                        filter(lambda x: x["path"] in self.included,
                               res.json()))
                self._state = "{:.2f}".format(
                    to_unit(sum(data["freeSpace"] for data in self.data),
                            self._unit))
            elif self.type == "status":
                self.data = res.json()
                self._state = self.data["version"]
            self._available = True
Example #33
0
async def test_jewish_calendar_sensor(hass, now, tzname, latitude, longitude,
                                      language, sensor, diaspora, result):
    """Test Jewish calendar sensor output."""
    time_zone = dt_util.get_time_zone(tzname)
    test_time = time_zone.localize(now)

    hass.config.time_zone = time_zone
    hass.config.latitude = latitude
    hass.config.longitude = longitude

    with alter_time(test_time):
        assert await async_setup_component(
            hass,
            jewish_calendar.DOMAIN,
            {
                "jewish_calendar": {
                    "name": "test",
                    "language": language,
                    "diaspora": diaspora,
                }
            },
        )
        await hass.async_block_till_done()

        future = dt_util.utcnow() + timedelta(seconds=30)
        async_fire_time_changed(hass, future)
        await hass.async_block_till_done()

    result = (dt_util.as_utc(time_zone.localize(result)) if isinstance(
        result, dt) else result)

    sensor_object = hass.states.get(f"sensor.test_{sensor}")
    assert sensor_object.state == str(result)

    if sensor == "holiday":
        assert sensor_object.attributes.get("id") == "rosh_hashana_i"
        assert sensor_object.attributes.get("type") == "YOM_TOV"
        assert sensor_object.attributes.get("type_id") == 1
    def __init__(self,
                 latitude=None,
                 longitude=None,
                 mode=FORECAST_MODE_HOURLY,
                 params=None):
        """Initialize the data object."""
        params = params or {}

        _LOGGER.debug('Place coordinates: %s, %s', latitude, longitude)
        _LOGGER.debug('Forecast mode: %s', mode)

        self._mode = mode
        self._cache = Cache(params) if params.get(
            'cache_dir') is not None else None

        self._city_id = self._get_city_id(latitude, longitude)
        _LOGGER.debug('Nearest city ID: %s', self._city_id)

        self._current = {}
        self._forecast = []
        self._timezone = dt_util.get_time_zone(
            params.get('timezone')) if params.get(
                'timezone') is not None else dt_util.DEFAULT_TIME_ZONE
Example #35
0
 def test_issur_melacha_sensor(self, now, candle_lighting, havdalah,
                               diaspora, tzname, latitude, longitude,
                               result):
     """Test Issur Melacha sensor output."""
     time_zone = get_time_zone(tzname)
     set_default_time_zone(time_zone)
     test_time = time_zone.localize(now)
     self.hass.config.latitude = latitude
     self.hass.config.longitude = longitude
     sensor = JewishCalSensor(name='test',
                              language='english',
                              sensor_type='issur_melacha_in_effect',
                              latitude=latitude,
                              longitude=longitude,
                              timezone=time_zone,
                              diaspora=diaspora,
                              havdalah_offset=havdalah,
                              candle_lighting_offset=candle_lighting)
     sensor.hass = self.hass
     with patch('homeassistant.util.dt.now', return_value=test_time):
         run_coroutine_threadsafe(sensor.async_update(),
                                  self.hass.loop).result()
         assert sensor.state == result
Example #36
0
async def test_data_manager_update_sleep_date_range(
    data_manager: WithingsDataManager, ) -> None:
    """Test method."""
    patch_time_zone = patch(
        "homeassistant.util.dt.DEFAULT_TIME_ZONE",
        new=dt.get_time_zone("America/Belize"),
    )

    with patch_time_zone:
        update_start_time = dt.now()
        await data_manager.update_sleep()

        call_args = data_manager.api.sleep_get.call_args_list[0][1]
        startdate = call_args.get("startdate")
        enddate = call_args.get("enddate")

        assert startdate.tzname() == "CST"

        assert enddate.tzname() == "CST"
        assert startdate.tzname() == "CST"
        assert update_start_time < enddate
        assert enddate < update_start_time + timedelta(seconds=1)
        assert enddate > startdate
Example #37
0
def test_auto_purge(hass_recorder):
    """Test saving and restoring a state."""
    hass = hass_recorder()

    original_tz = dt_util.DEFAULT_TIME_ZONE

    tz = dt_util.get_time_zone("Europe/Copenhagen")
    dt_util.set_default_time_zone(tz)

    now = dt_util.utcnow()
    test_time = tz.localize(datetime(now.year + 1, 1, 1, 4, 12, 0))
    async_fire_time_changed(hass, test_time)

    with patch("homeassistant.components.recorder.purge.purge_old_data",
               return_value=True) as purge_old_data:
        for delta in (-1, 0, 1):
            async_fire_time_changed(hass, test_time + timedelta(seconds=delta))
            hass.block_till_done()
            hass.data[DATA_INSTANCE].block_till_done()

        assert len(purge_old_data.mock_calls) == 1

    dt_util.set_default_time_zone(original_tz)
Example #38
0
 def test_jewish_calendar_sensor(self, cur_time, tzname, latitude,
                                 longitude, language, sensor, diaspora,
                                 result):
     """Test Jewish calendar sensor output."""
     time_zone = get_time_zone(tzname)
     set_default_time_zone(time_zone)
     test_time = time_zone.localize(cur_time)
     self.hass.config.latitude = latitude
     self.hass.config.longitude = longitude
     sensor = JewishCalSensor(
         name="test",
         language=language,
         sensor_type=sensor,
         latitude=latitude,
         longitude=longitude,
         timezone=time_zone,
         diaspora=diaspora,
     )
     sensor.hass = self.hass
     with patch("homeassistant.util.dt.now", return_value=test_time):
         run_coroutine_threadsafe(sensor.async_update(),
                                  self.hass.loop).result()
         assert sensor.state == result
Example #39
0
async def test_set_datetime_3(hass):
    """Test set_datetime method using timestamp."""
    await async_setup_component(
        hass, DOMAIN,
        {DOMAIN: {
            "test_datetime": {
                "has_time": True,
                "has_date": True
            }
        }})

    entity_id = "input_datetime.test_datetime"

    dt_obj = datetime.datetime(2017,
                               9,
                               7,
                               19,
                               46,
                               30,
                               tzinfo=dt_util.get_time_zone(
                                   hass.config.time_zone))

    await async_set_timestamp(hass, entity_id,
                              dt_util.as_utc(dt_obj).timestamp())

    state = hass.states.get(entity_id)
    assert state.state == dt_obj.strftime(FMT_DATETIME)
    assert state.attributes["has_time"]
    assert state.attributes["has_date"]

    assert state.attributes["year"] == 2017
    assert state.attributes["month"] == 9
    assert state.attributes["day"] == 7
    assert state.attributes["hour"] == 19
    assert state.attributes["minute"] == 46
    assert state.attributes["second"] == 30
    assert state.attributes["timestamp"] == dt_obj.timestamp()
Example #40
0
async def test_dst(hass, freezer, hass_tz_info):
    """Test sun event with offset."""
    hass.config.time_zone = "CET"
    dt_util.set_default_time_zone(dt_util.get_time_zone("CET"))
    test_time = datetime(2019, 3, 30, 3, 0, 0, tzinfo=hass_tz_info)
    config = {
        "binary_sensor": [
            {"platform": "tod", "name": "Day", "after": "2:30", "before": "2:40"}
        ]
    }
    # Test DST:
    # after 2019-03-30 03:00 CET the next update should ge scheduled
    # at 3:30 not 2:30 local time
    entity_id = "binary_sensor.day"
    freezer.move_to(test_time)
    await async_setup_component(hass, "binary_sensor", config)
    await hass.async_block_till_done()

    await hass.async_block_till_done()
    state = hass.states.get(entity_id)
    assert state.attributes["after"] == "2019-03-31T03:30:00+02:00"
    assert state.attributes["before"] == "2019-03-31T03:40:00+02:00"
    assert state.attributes["next_update"] == "2019-03-31T03:30:00+02:00"
    assert state.state == STATE_OFF
Example #41
0
    def __init__(self,
                 latitude=None,
                 longitude=None,
                 mode=FORECAST_MODE_HOURLY,
                 params=None):
        """Initialize the data object."""
        params = params or {}
        params["domain"] = DOMAIN

        _LOGGER.debug("Place coordinates: %s, %s", latitude, longitude)
        _LOGGER.debug("Forecast mode: %s", mode)

        self._mode = mode
        self._cache = Cache(params) if params.get(
            "cache_dir") is not None else None

        self._city_id = self._get_city_id(latitude, longitude)
        _LOGGER.debug("Nearest city ID: %s", self._city_id)

        self._current = {}
        self._forecast = []
        self._timezone = (dt_util.get_time_zone(params.get("timezone"))
                          if params.get("timezone") is not None else
                          dt_util.DEFAULT_TIME_ZONE)
Example #42
0
def test_find_next_time_expression_time_leave_dst_chicago_inside_the_fold_ahead_10_min():
    """Test leaving daylight saving time for find_next_time_expression_time."""
    tz = dt_util.get_time_zone("America/Chicago")
    dt_util.set_default_time_zone(tz)

    # Leaving DST, clocks are rolled back

    # Find 10m later while we are in the fold
    # Start at 01:30:01 fold=0
    # Reach to 01:40:01 fold=1
    hour_minute_second = (1, 40, 1)
    test_time = datetime(2021, 11, 7, 1, 30, 1, tzinfo=tz, fold=1)
    matching_hours, matching_minutes, matching_seconds = _get_matches(
        *hour_minute_second
    )

    next_time = dt_util.find_next_time_expression_time(
        test_time, matching_seconds, matching_minutes, matching_hours
    )
    assert next_time == datetime(2021, 11, 7, *hour_minute_second, tzinfo=tz, fold=1)
    assert next_time.fold == 1  # time is ambiguous
    assert dt_util.as_utc(next_time) == datetime(
        2021, 11, 7, 7, 40, 1, tzinfo=dt_util.UTC
    )
Example #43
0
def test_find_next_time_expression_time_leave_dst_chicago_past_the_fold_ahead_2_hour_10_min():
    """Test leaving daylight saving time for find_next_time_expression_time."""
    tz = dt_util.get_time_zone("America/Chicago")
    dt_util.set_default_time_zone(tz)

    # Leaving DST, clocks are rolled back

    # Find 1h 10m after into the fold
    # Start at 01:30:01 fold=0
    # Reach to 02:20:01 past the fold
    hour_minute_second = (2, 20, 1)
    test_time = datetime(2021, 11, 7, 1, 30, 1, tzinfo=tz, fold=0)
    matching_hours, matching_minutes, matching_seconds = _get_matches(
        *hour_minute_second
    )

    next_time = dt_util.find_next_time_expression_time(
        test_time, matching_seconds, matching_minutes, matching_hours
    )
    assert next_time == datetime(2021, 11, 7, *hour_minute_second, tzinfo=tz, fold=1)
    assert next_time.fold == 0  # Time is no longer ambiguous
    assert dt_util.as_utc(next_time) == datetime(
        2021, 11, 7, 8, 20, 1, tzinfo=dt_util.UTC
    )
Example #44
0
    def test_get_time_zone_retrieves_valid_time_zone(self):
        """Test getting a time zone."""
        time_zone = dt_util.get_time_zone(TEST_TIME_ZONE)

        self.assertIsNotNone(time_zone)
        self.assertEqual(TEST_TIME_ZONE, time_zone.zone)
Example #45
0
    def test_get_time_zone_returns_none_for_garbage_time_zone(self):
        """Test getting a non existing time zone."""
        time_zone = dt_util.get_time_zone("Non existing time zone")

        self.assertIsNone(time_zone)
    def tearDown(self):
        """Stop everything that was started."""
        dt_util.set_default_time_zone(dt_util.get_time_zone('UTC'))

        self.hass.stop()
Example #47
0
async def test_multi_sensor_migration(
        hass, caplog, legacy_patchable_time,
        pvpc_aioclient_mock: AiohttpClientMocker):
    """Test tariff migration when there are >1 old sensors."""
    entity_reg = mock_registry(hass)
    hass.config.time_zone = dt_util.get_time_zone("Europe/Madrid")
    uid_1 = "discrimination"
    uid_2 = "normal"
    old_conf_1 = {CONF_NAME: "test_pvpc_1", ATTR_TARIFF: uid_1}
    old_conf_2 = {CONF_NAME: "test_pvpc_2", ATTR_TARIFF: uid_2}

    config_entry_1 = MockConfigEntry(domain=DOMAIN,
                                     data=old_conf_1,
                                     unique_id=uid_1)
    config_entry_1.add_to_hass(hass)
    entity1 = entity_reg.async_get_or_create(
        domain="sensor",
        platform=DOMAIN,
        unique_id=uid_1,
        config_entry=config_entry_1,
        suggested_object_id="test_pvpc_1",
    )

    config_entry_2 = MockConfigEntry(domain=DOMAIN,
                                     data=old_conf_2,
                                     unique_id=uid_2)
    config_entry_2.add_to_hass(hass)
    entity2 = entity_reg.async_get_or_create(
        domain="sensor",
        platform=DOMAIN,
        unique_id=uid_2,
        config_entry=config_entry_2,
        suggested_object_id="test_pvpc_2",
    )

    assert len(hass.config_entries.async_entries(DOMAIN)) == 2
    assert len(entity_reg.entities) == 2

    mock_data = {
        "return_time": datetime(2019, 10, 27, 20, tzinfo=date_util.UTC)
    }

    def mock_now():
        return mock_data["return_time"]

    caplog.clear()
    with caplog.at_level(logging.WARNING):
        with patch("homeassistant.util.dt.utcnow", new=mock_now):
            assert await hass.config_entries.async_setup(
                config_entry_1.entry_id)
            assert len(caplog.messages) == 2

            # check migration with removal of extra sensors
            assert len(entity_reg.entities) == 1
            assert entity1.entity_id in entity_reg.entities
            assert entity2.entity_id not in entity_reg.entities

            current_entries = hass.config_entries.async_entries(DOMAIN)
            assert len(current_entries) == 1
            migrated_entry = current_entries[0]
            assert migrated_entry.version == 1
            assert migrated_entry.data[ATTR_POWER] == migrated_entry.data[
                ATTR_POWER_P3]
            assert migrated_entry.data[ATTR_TARIFF] == TARIFFS[0]

            await hass.async_block_till_done()
            assert pvpc_aioclient_mock.call_count == 2
Example #48
0
 def setUp(self):
     """Set up things to be run when tests are started."""
     self.hass = get_test_home_assistant()
     self.time_zone = dt_util.get_time_zone("America/New_York")
Example #49
0
)
import homeassistant.helpers.config_validation as cv
from homeassistant.util import Throttle, dt as dt_util

_LOGGER = logging.getLogger(__name__)

ATTR_STATION = "station"
ATTR_UPDATED = "updated"
ATTRIBUTION = "Data provided by ZAMG"

CONF_STATION_ID = "station_id"

DEFAULT_NAME = "zamg"

MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=10)
VIENNA_TIME_ZONE = dt_util.get_time_zone("Europe/Vienna")

DTypeT = Union[Type[int], Type[float], Type[str]]


@dataclass
class ZamgRequiredKeysMixin:
    """Mixin for required keys."""

    col_heading: str
    dtype: DTypeT


@dataclass
class ZamgSensorEntityDescription(SensorEntityDescription,
                                  ZamgRequiredKeysMixin):
    def tearDown(self):
        """Stop everything that was started."""
        dt_util.set_default_time_zone(dt_util.get_time_zone('UTC'))

        self.hass.stop()
Example #51
0
    def test_get_time_zone_returns_none_for_garbage_time_zone(self):
        """Test getting a non existing time zone."""
        time_zone = dt_util.get_time_zone("Non existing time zone")

        assert time_zone is None
Example #52
0
def setup_platform(hass, config, add_devices, discovery_info=None):
    """Setup the Worldclock sensor."""
    name = config.get(CONF_NAME)
    time_zone = dt_util.get_time_zone(config.get(CONF_TIME_ZONE))

    add_devices([WorldClockSensor(time_zone, name)])
Example #53
0
async def test_sensor_availability(hass, caplog, legacy_patchable_time,
                                   pvpc_aioclient_mock: AiohttpClientMocker):
    """Test sensor availability and handling of cloud access."""
    hass.config.time_zone = dt_util.get_time_zone("Europe/Madrid")
    config_entry = MockConfigEntry(domain=DOMAIN,
                                   data={
                                       CONF_NAME: "test_dst",
                                       ATTR_TARIFF: "discrimination"
                                   })
    config_entry.add_to_hass(hass)
    assert len(hass.config_entries.async_entries(DOMAIN)) == 1
    mock_data = {
        "return_time": datetime(2019, 10, 27, 20, 0, 0, tzinfo=date_util.UTC)
    }

    def mock_now():
        return mock_data["return_time"]

    with patch("homeassistant.util.dt.utcnow", new=mock_now):
        assert await hass.config_entries.async_setup(config_entry.entry_id)

        # check migration
        current_entries = hass.config_entries.async_entries(DOMAIN)
        assert len(current_entries) == 1
        migrated_entry = current_entries[0]
        assert migrated_entry.version == 1
        assert migrated_entry.data[ATTR_POWER] == migrated_entry.data[
            ATTR_POWER_P3]
        assert migrated_entry.data[ATTR_TARIFF] == TARIFFS[0]

        await hass.async_block_till_done()
        caplog.clear()
        assert pvpc_aioclient_mock.call_count == 2

        await _process_time_step(hass, mock_data, "price_21h", 0.13896)
        await _process_time_step(hass, mock_data, "price_22h", 0.06893)
        assert pvpc_aioclient_mock.call_count == 4
        await _process_time_step(hass, mock_data, "price_23h", 0.06935)
        assert pvpc_aioclient_mock.call_count == 5

        # sensor has no more prices, state is "unavailable" from now on
        await _process_time_step(hass, mock_data, value="unavailable")
        await _process_time_step(hass, mock_data, value="unavailable")
        num_errors = sum(1 for x in caplog.records
                         if x.levelno == logging.ERROR
                         and "unknown job listener" not in x.msg)
        num_warnings = sum(1 for x in caplog.records
                           if x.levelno == logging.WARNING)
        assert num_warnings == 1
        assert num_errors == 0
        assert pvpc_aioclient_mock.call_count == 9

        # check that it is silent until it becomes available again
        caplog.clear()
        with caplog.at_level(logging.WARNING):
            # silent mode
            for _ in range(21):
                await _process_time_step(hass, mock_data, value="unavailable")
            assert pvpc_aioclient_mock.call_count == 30
            assert len(caplog.messages) == 0

            # warning about data access recovered
            await _process_time_step(hass, mock_data, value="unavailable")
            assert pvpc_aioclient_mock.call_count == 31
            assert len(caplog.messages) == 1
            assert caplog.records[0].levelno == logging.WARNING

            # working ok again
            await _process_time_step(hass,
                                     mock_data,
                                     "price_00h",
                                     value=0.06821)
            assert pvpc_aioclient_mock.call_count == 32
            await _process_time_step(hass,
                                     mock_data,
                                     "price_01h",
                                     value=0.06627)
            assert pvpc_aioclient_mock.call_count == 33
            assert len(caplog.messages) == 1
            assert caplog.records[0].levelno == logging.WARNING
 def teardown_method(self, method):
     """Stop everything that was started."""
     self.hass.stop()
     # Reset the default timezone, so we don't affect other tests
     set_default_time_zone(get_time_zone('UTC'))
Example #55
0
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=1)
MAX_LIST = 20
MAX_TIME_OFFSET = 360
ICON = "mdi:bus"

ATTR_DEPARTURE = "departure"
ATTR_LINE = "line"
ATTR_ORIGIN = "origin"
ATTR_DIRECTION = "direction"
ATTR_TYPE = "type"
ATTR_DELAY = "delay"
ATTR_NEXT = "next"

PARALLEL_UPDATES = 0
BERLIN_TIME_ZONE = get_time_zone("Europe/Berlin")

_LOGGER = logging.getLogger(__name__)


async def async_setup_entry(hass, config_entry, async_add_devices):
    """Set up the sensor platform."""
    hub = hass.data[DOMAIN][config_entry.entry_id]

    session = aiohttp_client.async_get_clientsession(hass)

    sensor = HVVDepartureSensor(hass, config_entry, session, hub)
    async_add_devices([sensor], True)


class HVVDepartureSensor(SensorEntity):
Example #56
0
async def async_test_home_assistant(loop):
    """Return a Home Assistant object pointing at test config dir."""
    hass = ha.HomeAssistant(loop)
    store = auth_store.AuthStore(hass)
    hass.auth = auth.AuthManager(hass, store, {}, {})
    ensure_auth_manager_loaded(hass.auth)
    INSTANCES.append(hass)

    orig_async_add_job = hass.async_add_job
    orig_async_add_executor_job = hass.async_add_executor_job
    orig_async_create_task = hass.async_create_task

    def async_add_job(target, *args):
        """Add job."""
        if isinstance(target, Mock):
            return mock_coro(target(*args))
        return orig_async_add_job(target, *args)

    def async_add_executor_job(target, *args):
        """Add executor job."""
        if isinstance(target, Mock):
            return mock_coro(target(*args))
        return orig_async_add_executor_job(target, *args)

    def async_create_task(coroutine):
        """Create task."""
        if isinstance(coroutine, Mock):
            return mock_coro()
        return orig_async_create_task(coroutine)

    hass.async_add_job = async_add_job
    hass.async_add_executor_job = async_add_executor_job
    hass.async_create_task = async_create_task

    hass.config.location_name = 'test home'
    hass.config.config_dir = get_test_config_dir()
    hass.config.latitude = 32.87336
    hass.config.longitude = -117.22743
    hass.config.elevation = 0
    hass.config.time_zone = date_util.get_time_zone('US/Pacific')
    hass.config.units = METRIC_SYSTEM
    hass.config.skip_pip = True

    hass.config_entries = config_entries.ConfigEntries(hass, {})
    hass.config_entries._entries = []
    hass.config_entries._store._async_ensure_stop_listener = lambda: None

    hass.state = ha.CoreState.running

    # Mock async_start
    orig_start = hass.async_start

    async def mock_async_start():
        """Start the mocking."""
        # We only mock time during tests and we want to track tasks
        with patch('homeassistant.core._async_create_timer'), \
                patch.object(hass, 'async_stop_track_tasks'):
            await orig_start()

    hass.async_start = mock_async_start

    @ha.callback
    def clear_instance(event):
        """Clear global instance."""
        INSTANCES.remove(hass)

    hass.bus.async_listen_once(EVENT_HOMEASSISTANT_CLOSE, clear_instance)

    return hass
Example #57
0
    MATCH_ALL,
    __version__,
)
import homeassistant.core as ha
from homeassistant.exceptions import (
    InvalidEntityFormatError,
    InvalidStateError,
    MaxLengthExceeded,
    ServiceNotFound,
)
import homeassistant.util.dt as dt_util
from homeassistant.util.unit_system import METRIC_SYSTEM

from tests.common import async_capture_events, async_mock_service

PST = dt_util.get_time_zone("America/Los_Angeles")


def test_split_entity_id():
    """Test split_entity_id."""
    assert ha.split_entity_id("domain.object_id") == ["domain", "object_id"]


def test_async_add_hass_job_schedule_callback():
    """Test that we schedule coroutines and add jobs to the job pool."""
    hass = MagicMock()
    job = MagicMock()

    ha.HomeAssistant.async_add_hass_job(hass, ha.HassJob(ha.callback(job)))
    assert len(hass.loop.call_soon.mock_calls) == 1
    assert len(hass.loop.create_task.mock_calls) == 0
Example #58
0
    async def async_check_date_and_time(self):
        """Warns if camera and system date not synced."""
        _LOGGER.debug("Setting up the ONVIF device management service")
        devicemgmt = self._camera.create_devicemgmt_service()

        _LOGGER.debug("Retrieving current camera date/time")
        try:
            system_date = dt_util.utcnow()
            device_time = await devicemgmt.GetSystemDateAndTime()
            if not device_time:
                _LOGGER.debug(
                    """Couldn't get camera '%s' date/time.
                    GetSystemDateAndTime() return null/empty""",
                    self._name,
                )
                return

            if device_time.UTCDateTime:
                tzone = dt_util.UTC
                cdate = device_time.UTCDateTime
            else:
                tzone = (dt_util.get_time_zone(device_time.TimeZone)
                         or dt_util.DEFAULT_TIME_ZONE)
                cdate = device_time.LocalDateTime

            if cdate is None:
                _LOGGER.warning("Could not retrieve date/time on this camera")
            else:
                cam_date = dt.datetime(
                    cdate.Date.Year,
                    cdate.Date.Month,
                    cdate.Date.Day,
                    cdate.Time.Hour,
                    cdate.Time.Minute,
                    cdate.Time.Second,
                    0,
                    tzone,
                )

                cam_date_utc = cam_date.astimezone(dt_util.UTC)

                _LOGGER.debug("TimeZone for date/time: %s", tzone)

                _LOGGER.debug("Camera date/time: %s", cam_date)

                _LOGGER.debug("Camera date/time in UTC: %s", cam_date_utc)

                _LOGGER.debug("System date/time: %s", system_date)

                dt_diff = cam_date - system_date
                dt_diff_seconds = dt_diff.total_seconds()

                if dt_diff_seconds > 5:
                    _LOGGER.warning(
                        "The date/time on the camera (UTC) is '%s', "
                        "which is different from the system '%s', "
                        "this could lead to authentication issues",
                        cam_date_utc,
                        system_date,
                    )
        except ServerDisconnectedError as err:
            _LOGGER.warning("Couldn't get camera '%s' date/time. Error: %s",
                            self._name, err)
Example #59
0
    def _update_member(self, m, name):
        name = name.replace(',', '_').replace('-', '_')

        dev_id = slugify(self._prefix + name)
        prev_seen, reported = self._dev_data.get(dev_id, (None, False))

        loc = m.get('location')
        try:
            last_seen = utc_from_ts(loc.get('timestamp'))
        except AttributeError:
            last_seen = None

        if self._max_update_wait:
            update = last_seen or prev_seen or self._started
            overdue = dt_util.utcnow() - update > self._max_update_wait
            if overdue and not reported:
                self._hass.bus.fire(
                    'life360_update_overdue',
                    {'entity_id': DT_ENTITY_ID_FORMAT.format(dev_id)})
                reported = True
            elif not overdue and reported:
                self._hass.bus.fire(
                    'life360_update_restored', {
                        'entity_id':
                        DT_ENTITY_ID_FORMAT.format(dev_id),
                        'wait':
                        str(last_seen -
                            (prev_seen or self._started)).split('.')[0]
                    })
                reported = False

        self._dev_data[dev_id] = last_seen or prev_seen, reported

        if not loc:
            err_msg = m['issues']['title']
            if err_msg:
                if m['issues']['dialog']:
                    err_msg += ': ' + m['issues']['dialog']
            else:
                err_msg = 'Location information missing'
            self._err(dev_id, err_msg)
            return

        if last_seen and (not prev_seen or last_seen > prev_seen):
            lat = loc.get('latitude')
            lon = loc.get('longitude')
            gps_accuracy = loc.get('accuracy')
            try:
                lat = float(lat)
                lon = float(lon)
                # Life360 reports accuracy in feet, but Device Tracker expects
                # gps_accuracy in meters.
                gps_accuracy = round(
                    convert(float(gps_accuracy), LENGTH_FEET, LENGTH_METERS))
            except (TypeError, ValueError):
                self._err(
                    dev_id, 'GPS data invalid: {}, {}, {}'.format(
                        lat, lon, gps_accuracy))
                return

            self._ok(dev_id)

            msg = 'Updating {}'.format(dev_id)
            if prev_seen:
                msg += '; Time since last update: {}'.format(last_seen -
                                                             prev_seen)
            _LOGGER.debug(msg)

            if (self._max_gps_accuracy is not None
                    and gps_accuracy > self._max_gps_accuracy):
                _LOGGER.info('{}: Ignoring update because expected GPS '
                             'accuracy {} is not met: {}'.format(
                                 dev_id, gps_accuracy, self._max_gps_accuracy))
                return

            place_name = loc.get('name') or None

            # Does user want location name to be shown as state?
            if SHOW_PLACES in self._show_as_state:
                loc_name = place_name
                # Make sure Home Place is always seen exactly as home,
                # which is the special device_tracker state for home.
                if loc_name and loc_name.lower() == self._home_place:
                    loc_name = STATE_HOME
            else:
                loc_name = None

            # If a place name is given, then address will just be a copy of
            # it, so don't bother with address. Otherwise, piece address
            # lines together, depending on which are present.
            if place_name:
                address = None
            else:
                address1 = loc.get('address1') or None
                address2 = loc.get('address2') or None
                if address1 and address2:
                    address = ', '.join([address1, address2])
                else:
                    address = address1 or address2

            raw_speed = loc.get('speed')
            try:
                speed = float(raw_speed) * SPEED_FACTOR_MPH
                if self._hass.config.units.is_metric:
                    speed = convert(speed, LENGTH_MILES, LENGTH_KILOMETERS)
                speed = max(0, round(speed))
            except (TypeError, ValueError):
                speed = STATE_UNKNOWN
            driving = bool_attr_from_int(loc.get('isDriving'))
            if (driving in (STATE_UNKNOWN, False)
                    and self._driving_speed is not None
                    and speed != STATE_UNKNOWN):
                driving = speed >= self._driving_speed
            moving = bool_attr_from_int(loc.get('inTransit'))

            if self._time_as in [TZ_DEVICE_UTC, TZ_DEVICE_LOCAL]:
                # timezone_at will return a string or None.
                tzname = self._tf.timezone_at(lng=lon, lat=lat)
                # get_time_zone will return a tzinfo or None.
                tz = dt_util.get_time_zone(tzname)
                attrs = {ATTR_TIME_ZONE: tzname or STATE_UNKNOWN}
            else:
                tz = None
                attrs = {}

            attrs.update({
                ATTR_ADDRESS:
                address,
                ATTR_AT_LOC_SINCE:
                self._dt_attr_from_ts(loc.get('since'), tz),
                ATTR_BATTERY_CHARGING:
                bool_attr_from_int(loc.get('charge')),
                ATTR_DRIVING:
                driving,
                ATTR_LAST_SEEN:
                self._dt_attr_from_utc(last_seen, tz),
                ATTR_MOVING:
                moving,
                ATTR_RAW_SPEED:
                raw_speed,
                ATTR_SPEED:
                speed,
                ATTR_WIFI_ON:
                bool_attr_from_int(loc.get('wifiState')),
            })

            # If we don't have a location name yet and user wants driving or moving
            # to be shown as state, and current location is not in a HA zone,
            # then update location name accordingly.
            if not loc_name and not active_zone(self._hass, lat, lon,
                                                gps_accuracy):
                if SHOW_DRIVING in self._show_as_state and driving is True:
                    loc_name = SHOW_DRIVING.capitalize()
                elif SHOW_MOVING in self._show_as_state and moving is True:
                    loc_name = SHOW_MOVING.capitalize()

            try:
                battery = int(float(loc.get('battery')))
            except (TypeError, ValueError):
                battery = None

            self._see(dev_id=dev_id,
                      location_name=loc_name,
                      gps=(lat, lon),
                      gps_accuracy=gps_accuracy,
                      battery=battery,
                      attributes=attrs,
                      picture=m.get('avatar'))