Ejemplo n.º 1
0
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'])
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
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
Ejemplo n.º 7
0
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'])
Ejemplo n.º 8
0
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"
Ejemplo n.º 9
0
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()
Ejemplo n.º 10
0
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
Ejemplo n.º 11
0
    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)
Ejemplo n.º 12
0
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")
Ejemplo n.º 13
0
    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
Ejemplo n.º 14
0
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'])
Ejemplo n.º 15
0
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
Ejemplo n.º 17
0
    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
Ejemplo n.º 19
0
    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
Ejemplo n.º 20
0
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")
Ejemplo n.º 21
0
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)
Ejemplo n.º 22
0
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"
Ejemplo n.º 23
0
    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),
            }
Ejemplo n.º 24
0
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)
Ejemplo n.º 25
0
 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
Ejemplo n.º 26
0
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"
Ejemplo n.º 27
0
 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)
Ejemplo n.º 28
0
    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
Ejemplo n.º 29
0
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
Ejemplo n.º 31
0
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")
Ejemplo n.º 32
0
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
Ejemplo n.º 33
0
    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 }'
Ejemplo n.º 34
0
 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'))
Ejemplo n.º 35
0
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'])
Ejemplo n.º 36
0
 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)
Ejemplo n.º 37
0
 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'))
Ejemplo n.º 38
0
    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())
Ejemplo n.º 39
0
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
Ejemplo n.º 40
0
    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()
Ejemplo n.º 41
0
    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))
Ejemplo n.º 42
0
 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)
Ejemplo n.º 43
0
 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
Ejemplo n.º 44
0
    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())
Ejemplo n.º 45
0
    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'))
Ejemplo n.º 46
0
 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
Ejemplo n.º 47
0
    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()
Ejemplo n.º 48
0
    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
Ejemplo n.º 49
0
    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)
Ejemplo n.º 50
0
def forgiving_as_timestamp(value):
    """Try to convert value to timestamp."""
    try:
        return dt_util.as_timestamp(value)
    except (ValueError, TypeError):
        return None
Ejemplo n.º 51
0
    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