Skip to content

Commit

Permalink
Add delivery start and delivery end sensors
Browse files Browse the repository at this point in the history
Exposes the timeslot as selected by the user when the order
was placed.
  • Loading branch information
NLthijs48 committed May 19, 2024
1 parent a1336a8 commit e056deb
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 14 deletions.
20 changes: 12 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,23 @@ An account is represented as a device.

## Account sensors

Name | Description
-- | --
`Order count total` | Total number of orders in your Crisp account (includes completed, cancelled and pending orders).
`Order count open` | Count of open orders in your Crisp account (out for delivery, or planned in the future).
Name | Type | Description
-- | -- | --
`Order count total` | int | Total number of orders in your Crisp account (includes completed, cancelled and pending orders).
`Order count open` | int | Count of open orders in your Crisp account (out for delivery, or planned in the future).

## Next order sensors

If there are orders planned for delivery, the following sensors are available for the order that is closest to delivery.

Name | Description
-- | --
`Next order delivery on` | Delivery date
`Next order product count` | Number of order lines (count of different products, not a sum of counts)
Name | Type | Description
-- | -- | --
`Next order delivery on` | date | Delivery date
`Next order delivery start` | datetime | Start of the delivery window (as selected by the user)
`Next order delivery start time` | time | Start time of the delivery window (as selected by the user)
`Next order delivery end` | datetime | End of the delivery window (as selected by the user)
`Next order delivery end time` | time | End time of the delivery window (as selected by the user)
`Next order product count` | int | Number of order lines (count of different products, not a sum of counts)

## Installation

Expand Down
4 changes: 4 additions & 0 deletions custom_components/crisp/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@
SENSOR_ORDER_COUNT_OPEN = "order_count_open"
SENSOR_NEXT_ORDER_PRODUCT_COUNT = "next_order_product_count"
SENSOR_NEXT_ORDER_DELIVERY_ON = "next_order_delivery_on"
SENSOR_NEXT_ORDER_DELIVERY_START = "next_order_delivery_start"
SENSOR_NEXT_ORDER_DELIVERY_START_TIME = "next_order_delivery_start_time"
SENSOR_NEXT_ORDER_DELIVERY_END = "next_order_delivery_end"
SENSOR_NEXT_ORDER_DELIVERY_END_TIME = "next_order_delivery_end_time"
33 changes: 28 additions & 5 deletions custom_components/crisp/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from __future__ import annotations

from datetime import timedelta, date
from datetime import timedelta, date, datetime, time
from typing import TypedDict

from homeassistant.config_entries import ConfigEntry
Expand All @@ -12,6 +12,7 @@
UpdateFailed,
)
from homeassistant.exceptions import ConfigEntryAuthFailed
from homeassistant.util import dt as dt_util

from .api import (
CrispApiClient,
Expand All @@ -32,7 +33,14 @@ class CrispUpcomingOrderData(TypedDict):

id: int
product_count: int
delivery_on: date
# None for the case it cannot get parsed
delivery_on: None | date
# None for the case it cannot get parsed
delivery_start: None | datetime
delivery_start_time: None | time
# None for the case it cannot get parsed
delivery_end: None | datetime
delivery_end_time: None | time

# https://developers.home-assistant.io/docs/integration_fetching_data#coordinated-single-api-poll-for-data-for-all-entities
class CrispDataUpdateCoordinator(DataUpdateCoordinator[CrispData]):
Expand Down Expand Up @@ -66,20 +74,35 @@ async def _async_update_data(self):
next_order: None | CrispUpcomingOrderData = None
if (len(open_order_ids) >= 1):
next_order_id = open_order_ids[0]
# LOGGER.debug("next order id: %s", next_order_id)
next_open_order = await self.client.get_order_details(next_order_id)
# LOGGER.debug(json.dumps(next_open_order.keys(), indent=4))
next_open_order_data = next_open_order.get('data', {})

product_count = len(next_open_order_data.get('products'))

delivery_slot = next_open_order_data.get('deliverySlot', {})
delivery_on = date.fromisoformat(delivery_slot.get('date'))

delivery_on_raw = delivery_slot.get('date')
delivery_on = dt_util.parse_date(delivery_on_raw) if delivery_on_raw is not None else None

# Is it best practice to store in UTC or using as_local in the state?
delivery_start_raw = delivery_slot.get('tsStart')
delivery_start = dt_util.as_local(dt_util.parse_datetime(delivery_start_raw)) if delivery_start_raw is not None else None
delivery_start_time_raw = delivery_slot.get('start')
delivery_start_time = dt_util.parse_time(delivery_start_time_raw) if delivery_start_time_raw is not None else None

delivery_end_raw = delivery_slot.get('tsEnd')
delivery_end = dt_util.as_local(dt_util.parse_datetime(delivery_end_raw)) if delivery_end_raw is not None else None
delivery_end_time_raw = delivery_slot.get('end')
delivery_end_time = dt_util.parse_time(delivery_end_time_raw) if delivery_end_time_raw is not None else None

next_order = {
'id': next_order_id,
'product_count': product_count,
'delivery_on': delivery_on,
'delivery_start': delivery_start,
'delivery_start_time': delivery_start_time,
'delivery_end': delivery_end,
'delivery_end_time': delivery_end_time
}

result: CrispData = {
Expand Down
26 changes: 25 additions & 1 deletion custom_components/crisp/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from homeassistant.components.sensor import SensorEntity, SensorEntityDescription
from homeassistant.helpers.typing import StateType

from .const import DOMAIN, SENSOR_NEXT_ORDER_PRODUCT_COUNT, SENSOR_ORDER_COUNT_OPEN, SENSOR_ORDER_COUNT_TOTAL, SENSOR_NEXT_ORDER_DELIVERY_ON
from .const import DOMAIN, SENSOR_NEXT_ORDER_DELIVERY_END, SENSOR_NEXT_ORDER_DELIVERY_END_TIME, SENSOR_NEXT_ORDER_DELIVERY_START, SENSOR_NEXT_ORDER_DELIVERY_START_TIME, SENSOR_NEXT_ORDER_PRODUCT_COUNT, SENSOR_ORDER_COUNT_OPEN, SENSOR_ORDER_COUNT_TOTAL, SENSOR_NEXT_ORDER_DELIVERY_ON
from .coordinator import CrispData, CrispDataUpdateCoordinator
from .entity import CrispEntity
from dataclasses import dataclass
Expand Down Expand Up @@ -45,6 +45,30 @@ class CrispSensorEntityDescription(SensorEntityDescription):
icon="mdi:calendar",
get_value=lambda data: data['next_order'].get('delivery_on'),
),
CrispSensorEntityDescription(
key=SENSOR_NEXT_ORDER_DELIVERY_START,
name="Next order delivery start",
icon="mdi:clock-start",
get_value=lambda data: data['next_order'].get('delivery_start'),
),
CrispSensorEntityDescription(
key=SENSOR_NEXT_ORDER_DELIVERY_START_TIME,
name="Next order delivery start time",
icon="mdi:clock-start",
get_value=lambda data: data['next_order'].get('delivery_start_time'),
),
CrispSensorEntityDescription(
key=SENSOR_NEXT_ORDER_DELIVERY_END,
name="Next order delivery end",
icon="mdi:clock-end",
get_value=lambda data: data['next_order'].get('delivery_end'),
),
CrispSensorEntityDescription(
key=SENSOR_NEXT_ORDER_DELIVERY_END_TIME,
name="Next order delivery end time",
icon="mdi:clock-end",
get_value=lambda data: data['next_order'].get('delivery_end_time'),
),
)

async def async_setup_entry(hass, entry, async_add_devices):
Expand Down

0 comments on commit e056deb

Please sign in to comment.