Python отправить электронное письмо, когда датчик имеет определенный уровень воды - PullRequest
1 голос
/ 08 мая 2020

Разрабатываю приложение на raspberry pi с сенсором H C -SR01. На данный момент у меня есть сценарий python, который проверяет уровень воды каждую секунду.

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO_TRIGGER = 16
GPIO_ECHO = 18

GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)

def distance():
    # set Trigger High
    GPIO.output(GPIO_TRIGGER, True)

    # set Trigger after 0.1ms low
    time.sleep(0.00001)
    GPIO.output(GPIO_TRIGGER, False)

    startTime = time.time()
    endTime = time.time()

    # store start time
    while GPIO.input(GPIO_ECHO) == 0:
        startTime = time.time()

    # store arrival
    while GPIO.input(GPIO_ECHO) == 1:
        endTime = time.time()

    # elapsed time
    TimeElapsed = endTime - startTime
    # multiply with speed of sound (34300 cm/s)
    # and division by two
    distance = (TimeElapsed * 34300) / 2

    return distance


while True:
    dist = distance()
    print ("Entfernung = %.1f cm" % dist)
    time.sleep(1)

Это работает нормально, и теперь я хочу отправить себе электронное письмо, когда уровень воды превышает определенный предел. Проблема не в отправке электронного письма, а в логике c, когда его отправлять. Если я помещу функцию sendEmail () в while l oop, я буду получать электронную почту каждую секунду, когда будет достигнут уровень воды. Таким образом, следующее не сработает:

#global varaible
alarm_waterlevel = 170

#in while loop
if dist > alarm_waterlevel
  sendMail()

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

Я думал о глобальная переменная и проверьте, упал ли уровень воды ниже определенной точки, прежде чем снова запускать почту. Примерно так:

#global varaible
alarm_waterlevel = 170
mail_sent = false

#in while loop
if dist >= alarm_waterlevel && mail_sent == false
  sendMail()
  mail_sent = true
if dist <= alarm_waterlevel - 10
  mail_sent = false

Как вы думаете, это отказоустойчивое решение? Есть ли какие-нибудь полезные советы, которые помогут мне решить эту проблему?

Ответы [ 2 ]

1 голос
/ 08 мая 2020

Ваш подход кажется мне разумным для решения Raspberry Pi;)

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

L1: send once, 80% full
L2: send every 5 minutes, 90 % full
L3: send every minute, > 100 % 

И вы должны подумать, когда менять состояния. Вы можете добавить что-то вроде гистерезиса. Это может быть элегантно, так что вам не нужно использовать три разных уровня высоты.

Если уровень воды повышается, вы можете переключить состояние, например, на 80%, но вернуться к более низкому состоянию предупреждения можно только тогда, когда он ниже 70%. Идея состоит в том, что ваша система не меняет состояния постоянно, когда уровень воды составляет от 78% до 82%.

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

1 голос
/ 08 мая 2020

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

size_water_container = 200 #Just a estimadet value
if dist < (size_water_container - alarm_waterlevel) and waterlevel_before > (size_water_container - alarm_waterlevel):
    sendMail()

Если я ошибаюсь, игнорируйте его :) Но теперь к вашему вопросу. Если вы постоянно запрашиваете расстояние, вы должны постоянно сохранять свой waterlevel_before, но не в операторе if. Просто сделай это потом

alarm_waterlevel = 170
size_water_container = 200
waterlevel_before = 0
while True:
    dist = distance()
    if dist < (size_water_container - alarm_waterlevel) and waterlevel_before > (size_water_container - alarm_waterlevel):
        sendMail()
    waterlevel_before = dist
    time.sleep(1)
...