mirror of https://github.com/home-assistant/core
Add Dominos Pizza platform (#10379)
* add dominos service * change require * dump to log * component fixes * clean-up use updated library * remove unnecessary import * fix hound errors * more lint fixes * Coverage rc * update requirements * cleanup as per notes * missing message * linting... * schema validation and reducing requests * fixlint * spacing * unused variable * fix docstrings * update req * notes updates, pypi package, front-end panel * stale import * fix constant name * docstrings * fix library import * lint fixes * pylint bug * remove built-in panel * Make synchronous * unused import and use throttle * Handle exceptions properly and update client * Import exceptions properly * unused import * remove bloat from start-up, readability fixes from notes, retrieve menu on request, not on startup * whitespace on blank line
This commit is contained in:
parent
d0b9f08bf2
commit
1a7522a594
|
@ -53,6 +53,8 @@ omit =
|
|||
homeassistant/components/digital_ocean.py
|
||||
homeassistant/components/*/digital_ocean.py
|
||||
|
||||
homeassistant/components/dominos.py
|
||||
|
||||
homeassistant/components/doorbird.py
|
||||
homeassistant/components/*/doorbird.py
|
||||
|
||||
|
@ -639,7 +641,6 @@ omit =
|
|||
homeassistant/components/zwave/util.py
|
||||
homeassistant/components/vacuum/mqtt.py
|
||||
|
||||
|
||||
[report]
|
||||
# Regexes for lines to exclude from consideration
|
||||
exclude_lines =
|
||||
|
|
|
@ -0,0 +1,240 @@
|
|||
"""
|
||||
Support for Dominos Pizza ordering.
|
||||
|
||||
The Dominos Pizza component ceates a service which can be invoked to order
|
||||
from their menu
|
||||
|
||||
For more details about this platform, please refer to the documentation at
|
||||
https://home-assistant.io/components/dominos/.
|
||||
"""
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.components import http
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.util import Throttle
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
# The domain of your component. Should be equal to the name of your component.
|
||||
DOMAIN = 'dominos'
|
||||
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
||||
|
||||
ATTR_COUNTRY = 'country_code'
|
||||
ATTR_FIRST_NAME = 'first_name'
|
||||
ATTR_LAST_NAME = 'last_name'
|
||||
ATTR_EMAIL = 'email'
|
||||
ATTR_PHONE = 'phone'
|
||||
ATTR_ADDRESS = 'address'
|
||||
ATTR_ORDERS = 'orders'
|
||||
ATTR_SHOW_MENU = 'show_menu'
|
||||
ATTR_ORDER_ENTITY = 'order_entity_id'
|
||||
ATTR_ORDER_NAME = 'name'
|
||||
ATTR_ORDER_CODES = 'codes'
|
||||
|
||||
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=10)
|
||||
MIN_TIME_BETWEEN_STORE_UPDATES = timedelta(minutes=3330)
|
||||
|
||||
REQUIREMENTS = ['pizzapi==0.0.3']
|
||||
|
||||
DEPENDENCIES = ['http']
|
||||
|
||||
_ORDERS_SCHEMA = vol.Schema({
|
||||
vol.Required(ATTR_ORDER_NAME): cv.string,
|
||||
vol.Required(ATTR_ORDER_CODES): vol.All(cv.ensure_list, [cv.string]),
|
||||
})
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
DOMAIN: vol.Schema({
|
||||
vol.Required(ATTR_COUNTRY): cv.string,
|
||||
vol.Required(ATTR_FIRST_NAME): cv.string,
|
||||
vol.Required(ATTR_LAST_NAME): cv.string,
|
||||
vol.Required(ATTR_EMAIL): cv.string,
|
||||
vol.Required(ATTR_PHONE): cv.string,
|
||||
vol.Required(ATTR_ADDRESS): cv.string,
|
||||
vol.Optional(ATTR_SHOW_MENU): cv.boolean,
|
||||
vol.Optional(ATTR_ORDERS): vol.All(cv.ensure_list, [_ORDERS_SCHEMA]),
|
||||
}),
|
||||
}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
|
||||
def setup(hass, config):
|
||||
"""Set up is called when Home Assistant is loading our component."""
|
||||
dominos = Dominos(hass, config)
|
||||
|
||||
component = EntityComponent(_LOGGER, DOMAIN, hass)
|
||||
hass.data[DOMAIN] = {}
|
||||
entities = []
|
||||
conf = config[DOMAIN]
|
||||
|
||||
hass.services.register(DOMAIN, 'order', dominos.handle_order)
|
||||
|
||||
if conf.get(ATTR_SHOW_MENU):
|
||||
hass.http.register_view(DominosProductListView(dominos))
|
||||
|
||||
for order_info in conf.get(ATTR_ORDERS):
|
||||
order = DominosOrder(order_info, dominos)
|
||||
entities.append(order)
|
||||
|
||||
component.add_entities(entities)
|
||||
|
||||
# Return boolean to indicate that initialization was successfully.
|
||||
return True
|
||||
|
||||
|
||||
class Dominos():
|
||||
"""Main Dominos service."""
|
||||
|
||||
def __init__(self, hass, config):
|
||||
"""Set up main service."""
|
||||
conf = config[DOMAIN]
|
||||
from pizzapi import Address, Customer, Store
|
||||
self.hass = hass
|
||||
self.customer = Customer(
|
||||
conf.get(ATTR_FIRST_NAME),
|
||||
conf.get(ATTR_LAST_NAME),
|
||||
conf.get(ATTR_EMAIL),
|
||||
conf.get(ATTR_PHONE),
|
||||
conf.get(ATTR_ADDRESS))
|
||||
self.address = Address(
|
||||
*self.customer.address.split(','),
|
||||
country=conf.get(ATTR_COUNTRY))
|
||||
self.country = conf.get(ATTR_COUNTRY)
|
||||
self.closest_store = Store()
|
||||
|
||||
def handle_order(self, call):
|
||||
"""Handle ordering pizza."""
|
||||
entity_ids = call.data.get(ATTR_ORDER_ENTITY, None)
|
||||
|
||||
target_orders = [order for order in self.hass.data[DOMAIN]['entities']
|
||||
if order.entity_id in entity_ids]
|
||||
|
||||
for order in target_orders:
|
||||
order.place()
|
||||
|
||||
@Throttle(MIN_TIME_BETWEEN_STORE_UPDATES)
|
||||
def update_closest_store(self):
|
||||
"""Update the shared closest store (if open)."""
|
||||
from pizzapi.address import StoreException
|
||||
try:
|
||||
self.closest_store = self.address.closest_store()
|
||||
except StoreException:
|
||||
self.closest_store = False
|
||||
|
||||
def get_menu(self):
|
||||
"""Return the products from the closest stores menu."""
|
||||
if self.closest_store is False:
|
||||
_LOGGER.warning('Cannot get menu. Store may be closed')
|
||||
return
|
||||
|
||||
menu = self.closest_store.get_menu()
|
||||
product_entries = []
|
||||
|
||||
for product in menu.products:
|
||||
item = {}
|
||||
if isinstance(product.menu_data['Variants'], list):
|
||||
variants = ', '.join(product.menu_data['Variants'])
|
||||
else:
|
||||
variants = product.menu_data['Variants']
|
||||
item['name'] = product.name
|
||||
item['variants'] = variants
|
||||
product_entries.append(item)
|
||||
|
||||
return product_entries
|
||||
|
||||
|
||||
class DominosProductListView(http.HomeAssistantView):
|
||||
"""View to retrieve product list content."""
|
||||
|
||||
url = '/api/dominos'
|
||||
name = "api:dominos"
|
||||
|
||||
def __init__(self, dominos):
|
||||
"""Initialize suite view."""
|
||||
self.dominos = dominos
|
||||
|
||||
@callback
|
||||
def get(self, request):
|
||||
"""Retrieve if API is running."""
|
||||
return self.json(self.dominos.get_menu())
|
||||
|
||||
|
||||
class DominosOrder(Entity):
|
||||
"""Represents a Dominos order entity."""
|
||||
|
||||
def __init__(self, order_info, dominos):
|
||||
"""Set up the entity."""
|
||||
self._name = order_info['name']
|
||||
self._product_codes = order_info['codes']
|
||||
self._orderable = False
|
||||
self.dominos = dominos
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the orders name."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def product_codes(self):
|
||||
"""Return the orders product codes."""
|
||||
return self._product_codes
|
||||
|
||||
@property
|
||||
def orderable(self):
|
||||
"""Return the true if orderable."""
|
||||
return self._orderable
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""Return the state either closed, orderable or unorderable."""
|
||||
if self.dominos.closest_store is False:
|
||||
return 'closed'
|
||||
else:
|
||||
return 'orderable' if self._orderable else 'unorderable'
|
||||
|
||||
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
||||
def update(self):
|
||||
"""Update the order state and refreshes the store."""
|
||||
from pizzapi.address import StoreException
|
||||
try:
|
||||
self.dominos.update_closest_store()
|
||||
except StoreException:
|
||||
self._orderable = False
|
||||
return
|
||||
|
||||
try:
|
||||
order = self.order()
|
||||
order.pay_with()
|
||||
self._orderable = True
|
||||
except StoreException:
|
||||
self._orderable = False
|
||||
|
||||
def order(self):
|
||||
"""Create the order object."""
|
||||
from pizzapi import Order
|
||||
order = Order(
|
||||
self.dominos.closest_store,
|
||||
self.dominos.customer,
|
||||
self.dominos.address,
|
||||
self.dominos.country)
|
||||
|
||||
for code in self._product_codes:
|
||||
order.add_item(code)
|
||||
|
||||
return order
|
||||
|
||||
def place(self):
|
||||
"""Place the order."""
|
||||
from pizzapi.address import StoreException
|
||||
try:
|
||||
order = self.order()
|
||||
order.place()
|
||||
except StoreException:
|
||||
self._orderable = False
|
||||
_LOGGER.warning(
|
||||
'Attempted to order Dominos - Order invalid or store closed')
|
|
@ -536,6 +536,9 @@ piglow==1.2.4
|
|||
# homeassistant.components.pilight
|
||||
pilight==0.1.1
|
||||
|
||||
# homeassistant.components.dominos
|
||||
pizzapi==0.0.3
|
||||
|
||||
# homeassistant.components.media_player.plex
|
||||
# homeassistant.components.sensor.plex
|
||||
plexapi==3.0.3
|
||||
|
|
Loading…
Reference in New Issue