Как я могу перевести функцию Python в спящий режим, продолжая ее вызывать (IFTTT)

У меня есть функция Python, настроенная на отправку мне сообщения, если в моем доме становится выше 30 градусов по Цельсию. Скрипт также управляет ЖК-дисплеем, на котором отображается различная информация о погоде: температура в доме, влажность, внешние условия и время движения трамвая.

Поскольку сценарий основан на цикле, я получаю текстовое сообщение каждую минуту или около того, пока температура выше 30 C. В идеале я хотел бы найти элегантный способ перевести функцию в спящий режим, продолжая вызывать ее для проверки. температура.

Ниже приведен пример кода, который я использую для запуска IFTTT:

def send_event(api_key, event, value1=None, value2=None, value3=None):
"""Send an event to the IFTTT maker channel"""
url = "https://maker.ifttt.com/trigger/{e}/with/key/{k}/".format(e=event,
                                                                 k=api_key)
payload = {'value1': value1, 'value2': value2, 'value3': value3}
return requests.post(url, data=payload)

Любая помощь приветствуется.

Спасибо!


person Chris Bateman    schedule 24.07.2016    source источник
comment
Я не понимаю, чего ты хочешь. Вы либо хотите, чтобы функция что-то делала, либо ничего не делала. Вы не можете сделать это одновременно, это иррациональное требование. Пожалуйста, уточните, что именно у вас есть и что вам нужно.   -  person freakish    schedule 25.07.2016
comment
Сопрограммы отлично подходят для того, чтобы заставить потоки Python спать. Если вы используете последнюю версию Python, вы также можете попробовать асинхронные методы.   -  person Wolph    schedule 25.07.2016


Ответы (2)


Если я правильно понимаю, проблема в том, что вы получаете слишком много текстов. В этом случае сохраните некоторое состояние о предыдущих событиях и используйте его, чтобы решить, отправлять ли текст.

Например, в качестве простого флага можно использовать простую логическую переменную (True/False). Вы по-прежнему можете использовать цикл, но отправлять событие только в первый раз, когда температура превышает 30 градусов, и сбрасывать, когда она падает ниже:

temp_is_high = False

while True:
    data = weather.get_data()

    if data['temp'] > 30:
        # only send if we are going from "cool" to "hot"
        # not if we were already in "hot" mode
        if not temp_is_high:
            # we are not in "hot" mode: remember for next time
            temp_is_high = True
            send_event(...)
   else: 
       # reset the condition flag
       temp_is_high = False

Есть вариации на эту тему. Например, вы можете добавить гистерезис, чтобы, если ваш термостат установлен на 30 градусов, а температура в доме колеблется около этого значения, измерения [29, 30, 29, 30, 29, 30, ....] не будет отправлять текст каждый раз. Для этого сбрасывайте флаг «горячий режим» только тогда, когда температура, перевалив за 30, упадет ниже (скажем) 26 градусов. Либо 1 час прошел, либо сколько угодно собственных требований.

person Inductiveload    schedule 25.07.2016
comment
Это выглядит ближе всего к тому, что я пытался сделать. Да, вы правы — слишком много текстов. Каждый раз, когда цикл повторяется, я получаю сообщение о том, что в доме более 30 градусов по Цельсию. Это мой первый проект на Python. Можете ли вы предложить, как я мог бы работать в ваших предложениях по этой функции: def home_temp_text_alert(ifttt_api_key, event_1, value1=None, value2=None): home_temp_text_alert_sleep = 0 url = "https://maker.ifttt.com/trigger/{e}/with/key/{k}".format(e=event_1,k=ifttt_api_key) payload = {"value1": value1, "value2": value2} return requests.post(url, data=payload) - person Chris Bateman; 25.07.2016
comment
Вы не используете их в этой функции, эта функция отправляет текст, чего вы не хотите делать в каждом цикле. Вы называете home_temp_text_alert(...) вместо моего заполнителя send_event(...). Вы заменяете строку data = ... тем, что дает вам value1 и value2, что, я полагаю, является тем, как вы получаете температуру? - person Inductiveload; 25.07.2016
comment
Спасибо тебе за это! - person Chris Bateman; 26.07.2016

Вместо того, чтобы пытаться остановить цикл, вы должны записать, когда было отправлено последнее предупреждение, и отправить его повторно только в том случае, если с момента последнего предупреждения прошло достаточно времени.

Всякий раз, когда отправляется предупреждение о температуре, записывайте datetime в переменную. Каждый раз, когда функция вызывается, она сравнивает текущую datetime с переменной, чтобы увидеть, превышает ли разница определенный порог. Если это так, повторно отправьте предупреждение и замените последнее проверенное предупреждение текущим datetime.

from datetime import datetime

alert_interval = 1800 # 30 minutes in seconds
last_alert = datetime(1, 1, 1) # set the initial time to very long ago

def send_event():
    time_diff = datetime.now() - last_alert # get a timedelta
    if time_diff.total_seconds() >= alert_interval:
        last_alert = datetime.now()
        # call the API to send another alert
person Soviut    schedule 25.07.2016