Esempio n. 1
0
    def update(self):
        """Get the latest data from the smart plug."""
        if self._last_tried is not None:
            last_try_s = (dt_util.now() - self._last_tried).total_seconds() / 60
            retry_seconds = min(self._n_tried * 2, 10) - last_try_s
            if self._n_tried > 0 and retry_seconds > 0:
                _LOGGER.warning("Waiting %s s to retry", retry_seconds)
                return

        _state = "unknown"

        try:
            self._last_tried = dt_util.now()
            _state = self.smartplug.state
        except urllib.error.HTTPError:
            _LOGGER.error("D-Link connection problem")
        if _state == "unknown":
            self._n_tried += 1
            self.available = False
            _LOGGER.warning("Failed to connect to D-Link switch")
            return

        self.state = _state
        self.available = True

        self.temperature = self.smartplug.temperature
        self.current_consumption = self.smartplug.current_consumption
        self.total_consumption = self.smartplug.total_consumption
        self._n_tried = 0
Esempio n. 2
0
    def update_period(self):
        """Parse the templates and store a datetime tuple in _period."""
        start = None
        end = None

        # Parse start
        if self._start is not None:
            try:
                start_rendered = self._start.async_render()
            except (TemplateError, TypeError) as ex:
                HistoryStatsHelper.handle_template_exception(ex, "start")
                return
            if isinstance(start_rendered, str):
                start = dt_util.parse_datetime(start_rendered)
            if start is None:
                try:
                    start = dt_util.as_local(
                        dt_util.utc_from_timestamp(
                            math.floor(float(start_rendered))))
                except ValueError:
                    _LOGGER.error(
                        "Parsing error: start must be a datetime or a timestamp"
                    )
                    return

        # Parse end
        if self._end is not None:
            try:
                end_rendered = self._end.async_render()
            except (TemplateError, TypeError) as ex:
                HistoryStatsHelper.handle_template_exception(ex, "end")
                return
            if isinstance(end_rendered, str):
                end = dt_util.parse_datetime(end_rendered)
            if end is None:
                try:
                    end = dt_util.as_local(
                        dt_util.utc_from_timestamp(
                            math.floor(float(end_rendered))))
                except ValueError:
                    _LOGGER.error(
                        "Parsing error: end must be a datetime or a timestamp")
                    return

        # Calculate start or end using the duration
        if start is None:
            start = end - self._duration
        if end is None:
            end = start + self._duration

        if start > dt_util.now():
            # History hasn't been written yet for this period
            return
        if dt_util.now() < end:
            # No point in making stats of the future
            end = dt_util.now()

        self._period = start, end
Esempio n. 3
0
    def _update_info(self):
        """Scan the network for devices.

        Returns boolean if scanning successful.
        """
        _LOGGER.debug("Scanning")

        scanner = PortScanner()

        options = self._options

        if self.home_interval:
            boundary = dt_util.now() - self.home_interval
            last_results = [
                device for device in self.last_results
                if device.last_update > boundary
            ]
            if last_results:
                exclude_hosts = self.exclude + [
                    device.ip for device in last_results
                ]
            else:
                exclude_hosts = self.exclude
        else:
            last_results = []
            exclude_hosts = self.exclude
        if exclude_hosts:
            options += f" --exclude {','.join(exclude_hosts)}"

        try:
            result = scanner.scan(hosts=" ".join(self.hosts),
                                  arguments=options)
        except PortScannerError:
            return False

        now = dt_util.now()
        for ipv4, info in result["scan"].items():
            if info["status"]["state"] != "up":
                continue
            name = info["hostnames"][0]["name"] if info["hostnames"] else ipv4
            # Mac address only returned if nmap ran as root
            mac = info["addresses"].get("mac") or get_mac_address(ip=ipv4)
            if mac is None:
                _LOGGER.info("No MAC address found for %s", ipv4)
                continue
            last_results.append(Device(mac.upper(), name, ipv4, now))

        self.last_results = last_results

        _LOGGER.debug("nmap scan successful")
        return True
Esempio n. 4
0
async def test_if_action_list_weekday(opp, calls):
    """Test for action with a list of weekdays."""
    assert await async_setup_component(
        opp,
        automation.DOMAIN,
        {
            automation.DOMAIN: {
                "trigger": {
                    "platform": "event",
                    "event_type": "test_event"
                },
                "condition": {
                    "condition": "time",
                    "weekday": ["mon", "tue"]
                },
                "action": {
                    "service": "test.automation"
                },
            }
        },
    )
    await opp.async_block_till_done()

    days_past_monday = dt_util.now().weekday()
    monday = dt_util.now() - timedelta(days=days_past_monday)
    tuesday = monday + timedelta(days=1)
    wednesday = tuesday + timedelta(days=1)

    with patch("openpeerpower.helpers.condition.dt_util.now",
               return_value=monday):
        opp.bus.async_fire("test_event")
        await opp.async_block_till_done()

    assert len(calls) == 1

    with patch("openpeerpower.helpers.condition.dt_util.now",
               return_value=tuesday):
        opp.bus.async_fire("test_event")
        await opp.async_block_till_done()

    assert len(calls) == 2

    with patch("openpeerpower.helpers.condition.dt_util.now",
               return_value=wednesday):
        opp.bus.async_fire("test_event")
        await opp.async_block_till_done()

    assert len(calls) == 2
Esempio n. 5
0
    async def async_zone_svc_request(self, service: dict, data: dict) -> None:
        """Process a service request (setpoint override) for a zone."""
        if service == SVC_RESET_ZONE_OVERRIDE:
            await self._evo_broker.call_client_api(
                self._evo_device.cancel_temp_override()
            )
            return

        # otherwise it is SVC_SET_ZONE_OVERRIDE
        temperature = max(min(data[ATTR_ZONE_TEMP], self.max_temp), self.min_temp)

        if ATTR_DURATION_UNTIL in data:
            duration = data[ATTR_DURATION_UNTIL]
            if duration.total_seconds() == 0:
                await self._update_schedule()
                until = dt_util.parse_datetime(self.setpoints.get("next_sp_from", ""))
            else:
                until = dt_util.now() + data[ATTR_DURATION_UNTIL]
        else:
            until = None  # indefinitely

        until = dt_util.as_utc(until) if until else None
        await self._evo_broker.call_client_api(
            self._evo_device.set_temperature(temperature, until=until)
        )
Esempio n. 6
0
    def send_message(self, message="", **kwargs):
        """
        Build and send a message to a user.

        Will send plain text normally, or will build a multipart HTML message
        with inline image attachments if images config is defined, or will
        build a multipart HTML if html config is defined.
        """
        subject = kwargs.get(ATTR_TITLE, ATTR_TITLE_DEFAULT)
        data = kwargs.get(ATTR_DATA)

        if data:
            if ATTR_HTML in data:
                msg = _build_html_msg(
                    message, data[ATTR_HTML], images=data.get(ATTR_IMAGES, [])
                )
            else:
                msg = _build_multipart_msg(message, images=data.get(ATTR_IMAGES, []))
        else:
            msg = _build_text_msg(message)

        msg["Subject"] = subject
        msg["To"] = ",".join(self.recipients)
        if self._sender_name:
            msg["From"] = f"{self._sender_name} <{self._sender}>"
        else:
            msg["From"] = self._sender
        msg["X-Mailer"] = "Open Peer Power"
        msg["Date"] = email.utils.format_datetime(dt_util.now())
        msg["Message-Id"] = email.utils.make_msgid()

        return self._send_email(msg)
Esempio n. 7
0
 def update(self) -> None:
     """Update state."""
     _LOGGER.debug("Updating sensor %s", self._name)
     days_left = self._smarty.filter_timer
     if days_left is not None and days_left != self._days_left:
         self._state = dt_util.now() + dt.timedelta(days=days_left)
         self._days_left = days_left
Esempio n. 8
0
 def state(self) -> datetime:
     """Return the uptime of the client."""
     if self.client.uptime < 1000000000:
         return (dt_util.now() -
                 timedelta(seconds=self.client.uptime)).isoformat()
     return dt_util.utc_from_timestamp(float(
         self.client.uptime)).isoformat()
Esempio n. 9
0
def test_now():
    """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)
Esempio n. 10
0
def test_set_default_time_zone():
    """Test setting default time zone."""
    time_zone = dt_util.get_time_zone(TEST_TIME_ZONE)

    dt_util.set_default_time_zone(time_zone)

    assert dt_util.now().tzinfo is time_zone
Esempio n. 11
0
def get_time_until(departure_time=None):
    """Calculate the time between now and a train's departure time."""
    if departure_time is None:
        return 0

    delta = dt_util.utc_from_timestamp(int(departure_time)) - dt_util.now()
    return round(delta.total_seconds() / 60)
Esempio n. 12
0
def now(opp: OpenPeerPower) -> datetime:
    """Record fetching now."""
    render_info = opp.data.get(_RENDER_INFO)
    if render_info is not None:
        render_info.has_time = True

    return dt_util.now()
Esempio n. 13
0
 async def _schedule_notify(self):
     """Schedule a notification."""
     delay = self._delay[self._next_delay]
     next_msg = now() + delay
     self._cancel = event.async_track_point_in_time(self.opp, self._notify,
                                                    next_msg)
     self._next_delay = min(self._next_delay + 1, len(self._delay) - 1)
Esempio n. 14
0
async def test_offset_in_progress_event(opp, mock_next_event):
    """Test that we can create an event trigger on device."""
    middle_of_event = dt_util.now() + dt_util.dt.timedelta(minutes=14)
    end_event = middle_of_event + dt_util.dt.timedelta(minutes=60)
    start = middle_of_event.isoformat()
    end = end_event.isoformat()
    event_summary = "Test Event in Progress"
    event = copy.deepcopy(TEST_EVENT)
    event["start"]["dateTime"] = start
    event["end"]["dateTime"] = end
    event["summary"] = f"{event_summary} !!-15"
    mock_next_event.return_value.event = event

    assert await async_setup_component(opp, "google",
                                       {"google": GOOGLE_CONFIG})
    await opp.async_block_till_done()

    state = opp.states.get(TEST_ENTITY)
    assert state.name == TEST_ENTITY_NAME
    assert state.state == STATE_OFF
    assert dict(state.attributes) == {
        "friendly_name": TEST_ENTITY_NAME,
        "message": event_summary,
        "all_day": False,
        "offset_reached": True,
        "start_time": middle_of_event.strftime(DATE_STR_FORMAT),
        "end_time": end_event.strftime(DATE_STR_FORMAT),
        "location": event["location"],
        "description": event["description"],
    }
Esempio n. 15
0
async def test_all_day_offset_event(opp, mock_next_event):
    """Test that we can create an event trigger on device."""
    tomorrow = dt_util.dt.date.today() + dt_util.dt.timedelta(days=2)
    end_event = tomorrow + dt_util.dt.timedelta(days=1)
    start = tomorrow.isoformat()
    end = end_event.isoformat()
    offset_hours = 1 + dt_util.now().hour
    event_summary = "Test All Day Event Offset"
    event = copy.deepcopy(TEST_EVENT)
    event["start"]["date"] = start
    event["end"]["date"] = end
    event["summary"] = f"{event_summary} !!-{offset_hours}:0"
    mock_next_event.return_value.event = event

    assert await async_setup_component(opp, "google",
                                       {"google": GOOGLE_CONFIG})
    await opp.async_block_till_done()

    state = opp.states.get(TEST_ENTITY)
    assert state.name == TEST_ENTITY_NAME
    assert state.state == STATE_OFF
    assert dict(state.attributes) == {
        "friendly_name": TEST_ENTITY_NAME,
        "message": event_summary,
        "all_day": True,
        "offset_reached": False,
        "start_time": tomorrow.strftime(DATE_STR_FORMAT),
        "end_time": end_event.strftime(DATE_STR_FORMAT),
        "location": event["location"],
        "description": event["description"],
    }
Esempio n. 16
0
def time(
    before: Optional[dt_util.dt.time] = None,
    after: Optional[dt_util.dt.time] = None,
    weekday: Union[None, str, Container[str]] = None,
) -> bool:
    """Test if local time condition matches.

    Handle the fact that time is continuous and we may be testing for
    a period that crosses midnight. In that case it is easier to test
    for the opposite. "(23:59 <= now < 00:01)" would be the same as
    "not (00:01 <= now < 23:59)".
    """
    now = dt_util.now()
    now_time = now.time()

    if after is None:
        after = dt_util.dt.time(0)
    if before is None:
        before = dt_util.dt.time(23, 59, 59, 999999)

    if after < before:
        if not after <= now_time < before:
            return False
    else:
        if before <= now_time < after:
            return False

    if weekday is not None:
        now_weekday = WEEKDAYS[now.weekday()]

        if (isinstance(weekday, str) and weekday != now_weekday
                or now_weekday not in weekday):
            return False

    return True
Esempio n. 17
0
    def update(self):
        """Update probe data."""
        self.api.login(self.username, self.password)
        _LOGGER.debug("Updating data for %s", self.device_id)
        try:
            if self.growatt_type == "total":
                total_info = self.api.plant_info(self.device_id)
                del total_info["deviceList"]
                # PlantMoneyText comes in as "3.1/€" remove anything that isn't part of the number
                total_info["plantMoneyText"] = re.sub(
                    r"[^\d.,]", "", total_info["plantMoneyText"])
                self.data = total_info
            elif self.growatt_type == "inverter":
                inverter_info = self.api.inverter_detail(self.device_id)
                self.data = inverter_info
            elif self.growatt_type == "storage":
                storage_info_detail = self.api.storage_params(
                    self.device_id)["storageDetailBean"]
                storage_energy_overview = self.api.storage_energy_overview(
                    self.plant_id, self.device_id)
                self.data = {**storage_info_detail, **storage_energy_overview}
            elif self.growatt_type == "mix":
                mix_info = self.api.mix_info(self.device_id)
                mix_totals = self.api.mix_totals(self.device_id, self.plant_id)
                mix_system_status = self.api.mix_system_status(
                    self.device_id, self.plant_id)

                mix_detail = self.api.mix_detail(self.device_id, self.plant_id)
                # Get the chart data and work out the time of the last entry, use this as the last time data was published to the Growatt Server
                mix_chart_entries = mix_detail["chartData"]
                sorted_keys = sorted(mix_chart_entries)

                # Create datetime from the latest entry
                date_now = dt.now().date()
                last_updated_time = dt.parse_time(str(sorted_keys[-1]))
                combined_timestamp = datetime.datetime.combine(
                    date_now, last_updated_time)
                # Convert datetime to UTC
                combined_timestamp_utc = dt.as_utc(combined_timestamp)
                mix_detail[
                    "lastdataupdate"] = combined_timestamp_utc.isoformat()

                # Dashboard data is largely inaccurate for mix system but it is the only call with the ability to return the combined
                # imported from grid value that is the combination of charging AND load consumption
                dashboard_data = self.api.dashboard_data(self.plant_id)
                # Dashboard values have units e.g. "kWh" as part of their returned string, so we remove it
                dashboard_values_for_mix = {
                    # etouser is already used by the results from 'mix_detail' so we rebrand it as 'etouser_combined'
                    "etouser_combined":
                    dashboard_data["etouser"].replace("kWh", "")
                }
                self.data = {
                    **mix_info,
                    **mix_totals,
                    **mix_system_status,
                    **mix_detail,
                    **dashboard_values_for_mix,
                }
        except json.decoder.JSONDecodeError:
            _LOGGER.error("Unable to fetch data from Growatt server")
Esempio n. 18
0
def is_offset_reached(event):
    """Have we reached the offset time specified in the event title."""
    start = get_date(event["start"])
    if start is None or event["offset_time"] == dt.dt.timedelta():
        return False

    return start + event["offset_time"] <= dt.now(start.tzinfo)
Esempio n. 19
0
    async def async_update(self):
        """Get the latest data and updates the states."""
        now = dt_util.now()
        if (
            not self._tibber_home.last_data_timestamp
            or (self._tibber_home.last_data_timestamp - now).total_seconds()
            < 5 * 3600 + self._spread_load_constant
            or not self.available
        ):
            _LOGGER.debug("Asking for new data")
            await self._fetch_data()

        elif (
            self._tibber_home.current_price_total
            and self._last_updated
            and self._last_updated.hour == now.hour
            and self._tibber_home.last_data_timestamp
        ):
            return

        res = self._tibber_home.current_price_data()
        self._attr_state, price_level, self._last_updated = res
        self._attr_extra_state_attributes["price_level"] = price_level

        attrs = self._tibber_home.current_attributes()
        self._attr_extra_state_attributes.update(attrs)
        self._attr_available = self._attr_state is not None
        self._attr_unit_of_measurement = self._tibber_home.price_unit
Esempio n. 20
0
    async def async_update(self) -> None:
        """Get the latest state data."""
        next_sp_from = self._setpoints.get("next_sp_from",
                                           "2000-01-01T00:00:00+00:00")
        if dt_util.now() >= dt_util.parse_datetime(next_sp_from):
            await self._update_schedule()  # no schedule, or it's out-of-date

        self._device_state_attrs = {"setpoints": self.setpoints}
Esempio n. 21
0
def test_as_utc_with_local_object():
    """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
Esempio n. 22
0
 async def _update_consumption_data(self, *_) -> None:
     """Update water consumption data from the API."""
     today = dt_util.now().date()
     start_date = datetime(today.year, today.month, today.day, 0, 0)
     end_date = datetime(today.year, today.month, today.day, 23, 59, 59, 999000)
     self._water_usage = await self.api_client.water.get_consumption_info(
         self._flo_location_id, start_date, end_date
     )
     LOGGER.debug("Updated Flo consumption data: %s", self._water_usage)
Esempio n. 23
0
def due_in_minutes(timestamp):
    """Get the time in minutes from a timestamp.

    The timestamp should be in the format day.month.year hour:minute
    """
    diff = datetime.strptime(
        timestamp, "%d.%m.%y %H:%M") - dt_util.now().replace(tzinfo=None)

    return int(diff.total_seconds() // 60)
Esempio n. 24
0
    def forecast(self):
        """Return the forecast array."""
        if not self._forecast:
            return []

        if self._mode == "hourly":
            forecast_filtered = [
                x for x in self._forecast
                if x.forecasted_hours == 1 and parse_datetime(x.forecast_date)
                > (now().utcnow() - timedelta(hours=1))
            ]

            fcdata_out = [{
                ATTR_FORECAST_TIME:
                data_in.forecast_date,
                ATTR_FORECAST_CONDITION:
                next(
                    (k for k, v in CONDITION_CLASSES.items()
                     if int(data_in.weather_type) in v),
                    None,
                ),
                ATTR_FORECAST_TEMP:
                float(data_in.feels_like_temperature),
                ATTR_FORECAST_PRECIPITATION_PROBABILITY:
                (int(float(data_in.precipitation_probability)) if
                 int(float(data_in.precipitation_probability)) >= 0 else None),
                ATTR_FORECAST_WIND_SPEED:
                data_in.wind_strength,
                ATTR_FORECAST_WIND_BEARING:
                data_in.wind_direction,
            } for data_in in forecast_filtered]
        else:
            forecast_filtered = [
                f for f in self._forecast if f.forecasted_hours == 24
            ]
            fcdata_out = [{
                ATTR_FORECAST_TIME:
                data_in.forecast_date,
                ATTR_FORECAST_CONDITION:
                next(
                    (k for k, v in CONDITION_CLASSES.items()
                     if int(data_in.weather_type) in v),
                    None,
                ),
                ATTR_FORECAST_TEMP_LOW:
                data_in.min_temperature,
                ATTR_FORECAST_TEMP:
                data_in.max_temperature,
                ATTR_FORECAST_PRECIPITATION_PROBABILITY:
                data_in.precipitation_probability,
                ATTR_FORECAST_WIND_SPEED:
                data_in.wind_strength,
                ATTR_FORECAST_WIND_BEARING:
                data_in.wind_direction,
            } for data_in in forecast_filtered]

        return fcdata_out
Esempio n. 25
0
 def set_time(self):
     """Set device time."""
     # Calling this clears any local temperature override and
     # reverts to the scheduled temperature.
     now = dt_util.now()
     self.device.time = {
         "day": now.weekday(),
         "hour": now.hour,
         "minute": now.minute,
     }
Esempio n. 26
0
def setup_platform(opp, config, add_entities, discovery_info=None):
    """Set up the Workday sensor."""
    add_holidays = config.get(CONF_ADD_HOLIDAYS)
    remove_holidays = config.get(CONF_REMOVE_HOLIDAYS)
    country = config[CONF_COUNTRY]
    days_offset = config[CONF_OFFSET]
    excludes = config[CONF_EXCLUDES]
    province = config.get(CONF_PROVINCE)
    sensor_name = config[CONF_NAME]
    workdays = config[CONF_WORKDAYS]

    year = (get_date(dt.now()) + timedelta(days=days_offset)).year
    obj_holidays = getattr(holidays, country)(years=year)

    if province:
        # 'state' and 'prov' are not interchangeable, so need to make
        # sure we use the right one
        if hasattr(obj_holidays,
                   "PROVINCES") and province in obj_holidays.PROVINCES:
            obj_holidays = getattr(holidays, country)(prov=province,
                                                      years=year)
        elif hasattr(obj_holidays,
                     "STATES") and province in obj_holidays.STATES:
            obj_holidays = getattr(holidays, country)(state=province,
                                                      years=year)
        else:
            _LOGGER.error("There is no province/state %s in country %s",
                          province, country)
            return

    # Add custom holidays
    try:
        obj_holidays.append(add_holidays)
    except TypeError:
        _LOGGER.debug("No custom holidays or invalid holidays")

    # Remove holidays
    try:
        for date in remove_holidays:
            obj_holidays.pop(date)
    except TypeError:
        _LOGGER.debug("No holidays to remove or invalid holidays")

    _LOGGER.debug("Found the following holidays for your configuration:")
    for date, name in sorted(obj_holidays.items()):
        _LOGGER.debug("%s %s", date, name)

    add_entities(
        [
            IsWorkdaySensor(obj_holidays, workdays, excludes, days_offset,
                            sensor_name)
        ],
        True,
    )
Esempio n. 27
0
async def test_if_action_after(opp, calls):
    """Test for if action after."""
    assert await async_setup_component(
        opp,
        automation.DOMAIN,
        {
            automation.DOMAIN: {
                "trigger": {
                    "platform": "event",
                    "event_type": "test_event"
                },
                "condition": {
                    "condition": "time",
                    "after": "10:00"
                },
                "action": {
                    "service": "test.automation"
                },
            }
        },
    )
    await opp.async_block_till_done()

    before_10 = dt_util.now().replace(hour=8)
    after_10 = dt_util.now().replace(hour=14)

    with patch("openpeerpower.helpers.condition.dt_util.now",
               return_value=before_10):
        opp.bus.async_fire("test_event")
        await opp.async_block_till_done()

    assert len(calls) == 0

    with patch("openpeerpower.helpers.condition.dt_util.now",
               return_value=after_10):
        opp.bus.async_fire("test_event")
        await opp.async_block_till_done()

    assert len(calls) == 1
Esempio n. 28
0
 def __init__(self):
     """Set the event data."""
     middle_of_event = dt_util.now() - dt_util.dt.timedelta(minutes=30)
     self.event = {
         "start": {
             "dateTime": middle_of_event.isoformat()
         },
         "end": {
             "dateTime": (middle_of_event +
                          dt_util.dt.timedelta(minutes=60)).isoformat()
         },
         "summary": "Current Event",
     }
Esempio n. 29
0
 def __init__(self):
     """Set the event to a future event."""
     one_hour_from_now = dt_util.now() + dt_util.dt.timedelta(minutes=30)
     self.event = {
         "start": {
             "dateTime": one_hour_from_now.isoformat()
         },
         "end": {
             "dateTime": (one_hour_from_now +
                          dt_util.dt.timedelta(minutes=60)).isoformat()
         },
         "summary": "Future Event",
     }
Esempio n. 30
0
 def extra_state_attributes(self):
     """Return the device state attributes."""
     if self._type == 1 and self._state is not None:
         schedule = {
             TIME_FRAME1_BEGIN: None,
             TIME_FRAME1_END: None,
             TIME_FRAME2_BEGIN: None,
             TIME_FRAME2_END: None,
             TIME_FRAME3_BEGIN: None,
             TIME_FRAME3_END: None,
         }
         time_frame = self._state.split(";")
         for index, item in enumerate(sorted(schedule.items())):
             if index < len(time_frame):
                 parsed = datetime.datetime.strptime(
                     time_frame[index], "%H:%M")
                 parsed = parsed.replace(dt_util.now().year,
                                         dt_util.now().month,
                                         dt_util.now().day)
                 schedule[item[0]] = parsed.isoformat()
         return schedule
     return None