-
Notifications
You must be signed in to change notification settings - Fork 9
Умная кофеварка
Alex X edited this page Sep 18, 2023
·
2 revisions
Интеграции
Дополнительное ПО
http:
use_x_forwarded_for: true
trusted_proxies:
- 127.0.0.1
yandex_dialogs:
file: dialogs.py
from homeassistant.core import HomeAssistant
from custom_components.morph_numbers import MORPH
def make_response(event: dict, text: str, end_session=False) -> dict:
return {
"version": event["version"],
"session": event["session"],
"response": {"text": text, "end_session": end_session},
}
def get_slots(intent: dict) -> dict:
return {k: v["value"] for k, v in intent["slots"].items()}
def morph(value: str, text: str) -> str:
return (
MORPH.number_with_text(value, text, as_text=False)
if value != "unavailable"
else ""
)
def state_response(event: dict, context: dict, end_session=False) -> dict:
hass: HomeAssistant = context["hass"]
product = hass.states.get("select.jura_product").state
if product == "unknown":
return intent_list(event)
stren = hass.states.get("select.jura_coffee_strength").state
temp = hass.states.get("select.jura_temperature").state
coffee = hass.states.get("number.jura_water_amount").state
milk = hass.states.get("number.jura_milk_foam_amount").state
water = hass.states.get("number.jura_bypass").state
pause = hass.states.get("number.jura_milk_break").state
text = morph(coffee, "миллилитр")
if temp == "High":
text += " горячего"
elif temp == "Low":
text += " холодного"
text += " кофе крепости " + stren
if value := morph(milk, "секунда"):
text += f" и {value} молока"
if value := morph(water, "миллилитр"):
text += f" и {value} воды"
if pause != "unavailable":
text += " с паузой " + pause
return make_response(event, text, end_session)
def set_state(hass: HomeAssistant, entity_id: str, value: int | str):
state = hass.states.get(entity_id)
if state.state == "unavailable":
return
if entity_id.startswith("select"):
if isinstance(value, int):
# important! options from 1 to len
options: list[str] = state.attributes["options"]
if value > len(options):
value = len(options)
elif value < 1:
value = 1
value = options[value - 1]
hass.services.call(
"select",
"select_option",
service_data={"option": value},
blocking=True,
target={"entity_id": entity_id},
)
elif entity_id.startswith("number"):
if value < state.attributes["min"]:
value = state.attributes["min"]
if value > state.attributes["max"]:
value = state.attributes["max"]
hass.services.call(
"number",
"set_value",
service_data={"value": value},
blocking=True,
target={"entity_id": entity_id},
)
PRODUCTS = {
"coffee": "Coffee",
"cappuccino": "Cappuccino",
"espresso": "Espresso",
"latte": "Latte Macchiato",
"barista": "Cafe Barista",
"lungo_barista": "Barista Lungo",
"flat_white": "1 Flat White",
"cortado": "Cortado",
"macchiato": "Espresso Macchiato",
"doppio": "Espresso Doppio",
}
TEMPERATURES = {"low": "Low", "normal": "Normal", "high": "High"}
def intent_product(event: dict, context: dict, slots: dict) -> dict:
hass: HomeAssistant = context["hass"]
if option := PRODUCTS.get(slots.get("product")):
set_state(hass, "select.jura_product", option)
if option := TEMPERATURES.get(slots.get("temperature")):
set_state(hass, "select.jura_temperature", option)
if value := slots.get("coffee"):
set_state(hass, "number.jura_water_amount", value)
if value := slots.get("milk"):
set_state(hass, "number.jura_milk_foam_amount", value)
if value := slots.get("water"):
set_state(hass, "number.jura_bypass", value)
if value := slots.get("strength"):
set_state(hass, "select.jura_coffee_strength", value)
# check for instant make
command: str = event["request"]["command"]
if command.startswith("make "):
intent_make(event, context)
return state_response(event, context, end_session=True)
return state_response(event, context)
PARAM_ENTITIES = {
"coffee": "number.jura_water_amount",
"milk": "number.jura_milk_foam_amount",
"water": "number.jura_bypass",
"strength": "select.jura_coffee_strength",
"temperature": "select.jura_temperature",
}
def intent_param(event: dict, context: dict, slots: dict) -> dict:
param: str = slots["param"]
if "-" in param:
# temperature-inc, strength-dec
param, direction = param.split("-")
else:
direction = slots.get("direction") # inc, dec
entity_id: str = PARAM_ENTITIES[param]
hass: HomeAssistant = context["hass"]
state = hass.states.get(entity_id)
if state.state == "unavailable":
return make_response(event, "Нельзя изменить для этого напитка")
if entity_id.startswith("select"):
# important! options from 1 to len
options: list = state.attributes["options"]
value_max = len(options)
value_min = 1
value_old = 1 + options.index(state.state)
else:
value_max = state.attributes["max"]
value_min = state.attributes["min"]
value_old = int(state.state)
value = slots.get("value", 1)
if direction == "inc":
value = value_old + value
elif direction == "dec":
value = value_old - value
if value > value_max:
value = value_max
elif value < value_min:
value = value_min
set_state(hass, entity_id, value)
return state_response(event, context)
def intent_make(event: dict, context: dict) -> dict:
# return make_response(event, "Блокировка")
hass: HomeAssistant = context["hass"]
hass.services.call(
"button",
"press",
target={"entity_id": "button.jura_make"},
)
return make_response(event, "Поехали!", end_session=True)
def intent_list(event: dict):
return make_response(
event, "Обычный, эспрессо, капучино, латте, бариста, flat white"
)
def default(event: dict, context: dict) -> dict:
hass: HomeAssistant = context["hass"]
hass.services.call(
# "persistent_notification", "create",
"telegram_bot",
"send_message",
service_data={"message": event["request"]["command"]},
)
return make_response(event, "я не понимаю")
def handler(event: dict, context: dict) -> dict:
intents: dict = event["request"].get("nlu", {}).get("intents")
if intent := intents.get("coffee.product"):
return intent_product(event, context, get_slots(intent))
if intent := intents.get("coffee.param"):
return intent_param(event, context, get_slots(intent))
if "coffee.make" in intents:
return intent_make(event, context)
if "coffee.list" in intents:
return intent_list(event)
if "coffee.settings" in intents:
return state_response(event, context)
if event["request"]["command"] == "":
return make_response(event, "Какой кофе желаете?")
return default(event, context)
Сущности
entity product:
values:
coffee:
кофе
обычный
простой
cappuccino:
капучино
espresso:
эспрессо
latte:
латте
barista:
бариста
баристу
по листу
lungo_barista:
лунго бариста
лонго бариста
лунка бариста
лунга бариста
гунга бариста
flat_white:
flat white
led white
red white
red light
left right
лэд вайт
cortado:
кортадо
кортана
macchiato:
маккиато
макиато
мотиватор
котята
гладиатор
эспрессо маккиато
doppio:
доппио
дай пиво
крапива
да пио
тапио
эспрессо доппио
entity param:
lemma: true
values:
coffee:
кофе
milk:
молоко
water:
вода
strength:
крепость
temperature:
температура
strength-inc:
крепче
strength-dec:
слабее
temperature-inc:
горячее
погорячее
temperature-dec:
холоднее
entity temperature:
lemma: true
values:
low:
холодный
прохладный
normal:
телпый
нормальный
high:
горячий
entity direction:
lemma: true
values:
inc:
увеличить
повысить
поднять
добавить
прибавить
больше
побольше
dec:
уменьшить
опустить
отнять
снизить
меньше
поменьше
coffee.product
root:
%lemma
[(($temperature)? $product)? ($coffee)? ($milk молока)? ($water воды)? (крепости $strength)?]
slots:
temperature:
type: temperature
source: $temperature
product:
type: product
source: $product
coffee:
type: YANDEX.NUMBER
source: $coffee
milk:
type: YANDEX.NUMBER
source: $milk
water:
type: YANDEX.NUMBER
source: $water
strength:
type: YANDEX.NUMBER
source: $strength
$coffee: $YANDEX.NUMBER
$milk: $YANDEX.NUMBER
$water: $YANDEX.NUMBER
$strength: $YANDEX.NUMBER
filler:
%lemma
make
сделать|приготовить|налить|установить|хочу|давай
количество|единиц|кофе
а|и|с|на
миллилитров|секунд
coffee.param
root:
[$direction? $param $value?]
slots:
direction:
type: direction
source: $direction
param:
type: param
source: $param
value:
type: YANDEX.NUMBER
source: $value
$value: $YANDEX.NUMBER
filler:
%lemma
сделать|приготовить|налить|изобразить|установить|хочу|давай
количество|миллилитров|секунд|единиц|кофе|а
кофе|чуточку|немного|капельку
на
coffee.make
root:
%lemma
приготовь|сделать|запустить|готовь|давай|поехали|пойдёт|хорошо|наливай|вари
coffee.list
root:
%lemma
есть|умеешь|список
filler:
%lemma
какие|что|огласи|расскажи|весь|про|напитки|ты|еще
make
coffee.settings
root:
%lemma
повтори
ещё раз
что (там|выбрано)
какие (настройки|параметры)
version: '3'
services:
caddy:
image: caddy:latest
network_mode: host
restart: unless-stopped
volumes:
- ~/docker/caddy/Caddyfile:/etc/caddy/Caddyfile
- ~/docker/caddy/data:/data
- ~/docker/caddy/config:/config
{
email mymail@gmail.com
ocsp_stapling off
}
myhome.duckdns.org {
reverse_proxy 127.0.0.1:8123
}