LINUX.ORG.RU

Как правильно логировать срабатывания датчика?

 , ,


1

1

Доброго дня!

Есть датчик табачного дыма. Когда дым есть, он замыкает контакт. Когда нету - размыкает. При первом замыкании, и до размыкания - мне нужно генерировать один e-mail. Есть малинка, в общем то, мне понятно как на python считать состояние GPIO пина и сделать некую команду.

Одна сложность, в которую не вкуриваю пока:

Я должен через GPIO считать информацию, положим, раз в 5 секунд (в моём случае это адекватное время). Состояние GPIO изменилось. Послали e-mail. Через пять секунд - состояние датчика по-прежнему замкнутое (ну дым от табака, положим не рассеился). - Как добиться того, чтобы не слало оно e-mail каждые пять секунд, а дождалось когда датчик перейдет снова в дежурный режим, и только в случае, повторной сработки, снова выслать e-mail? - В моём случае, это важно, так-как в туалетах могут ночью покурить несколько раз. И важно понимать в какое время были «перекуры», что бы потом поднять запись с камер.

P.S. в программировании я ноль без палочки. Но подозреваю, что мне нужен, некий аналог RS триггера программного. :)

★★★★★

Поставь флаг состояния программы (в случае питона и твоей задачи хватит переменной normal_mode и хранить в ней True или False), главное чтобы оно глобальное было, на предыдущей итерации и шли e-mail только когда оно меняется. Разумеется, после опроса своей железяки начинай с проверки этого условия и меняй его в соответствии с текущим состоянием.

peregrine ★★★★★
()
Последнее исправление: peregrine (всего исправлений: 3)
Ответ на: комментарий от peregrine

То есть, писать состояние в некий файл (мне хочется, чтобы после перезагрузки малины, оно не чудило, а понимало предыдущее состояние), потом, после каждого опроса, оно вычитывало gpio, сравнивало это состояние с предыдущим, и если оно изменилось, слать на почту? Примерно так? Если бросите код, буду очень рад.

DALDON ★★★★★
() автор топика
Ответ на: комментарий от Andreezy

Да. Я понимаю, но пока не очень понимаю как правильней написать код. Пишу с помощью гугла сейчас.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Подключаем необходимые библиотеки (для задержки по времени и GPIO)
import time
import RPi.GPIO as GPIO

# Установим номера пинов GPIO, с которыми будем работать
SMOKE = 17

# Делаем сброс состояний портов (все конфигурируются на вход - INPUT)
GPIO.cleanup()

# Режим нумерации пинов - по названию (не по порядковому номеру на разъеме)
GPIO.setmode(GPIO.BCM)

# Сконфигурируем пин SMOKE на ввод (INPUT)
GPIO.setup(SMOKE, GPIO.IN)

# Проверка на прерывание программы с клавиатуры (CTRL+C)
try:
    # Вечный цикл
    while True:
	    # Устанавливаем задержку 2 сек.
        timeout = 2
        # Если кнопка нажата (на пине SMOKE низкий уровень 0V)
        if GPIO.input(SMOKE) == False:

            print 'SMOKE pressed.'
        else:
            # в противном случае задержка - 0,5 сек.
            timeout = 0.5
        # Засветим светодиод, подключенный к пину LED
        GPIO.output(LED, GPIO.HIGH)
        # Подождем (выполним заданную выше задержку)
        time.sleep(timeout)
        # Погасим светодиод, подключенный к пину LED
        GPIO.output(LED, GPIO.LOW)
        time.sleep(timeout)
# Если комбинация клавиш CTRL+C была нажата - сброс пинов и завершение
except SMOKEboardInterrupt:
    GPIO.cleanup()

Думаю, как оптимальней сделать кусок кода. Не программировал никогда. Но что-то мне подсказывает, что я должен из файла вычитать значение переменной. Вычитать состояние gpio, сравнить. Если одинаковое - то снова запускаем цикл. Если разное - пишем в файл новое значение и отправляем письмо…

DALDON ★★★★★
() автор топика

Тебе надо ловить фронт.

Типа: [code] def my_callback(channel): print(‘Callback’)

GPIO.add_event_detect(channel, GPIO.RISING) GPIO.add_event_callback(channel, my_callback)

[/code]

Uncle_Bobby
()
Ответ на: комментарий от DALDON

Надо чтобы оно после перезагрузки работало, включая нештатные? Всё равно надо понимать, что гарантий в 100% не будет, но скорее всего будет работать большую часть времени.

#! /usr/bin/env python3
# -*- coding: utf-8 -*-

import json
import os.path


class State(object):  # Паттерн Singleton (Одиночка)
    def __new__(cls):
        if not hasattr(cls, 'instance'):
            cls.instance = super(State, cls).__new__(cls)
        return cls.instance

    def __init__(self):
        self._data = {}  # словарь со всеми базовыми глобальными состояниями
        self._settings_path = 'state.json'  # мне просто нравится json
        if os.path.exists(self._settings_path):
            try:
                with open(self._settings_path, "r") as read_file:
                self._data = json.load(read_file)
            except Exception:
                # посылай e-mail, у тебя какая-то шляпа с чтением сохранения
                # на самом деле, этого недостаточно, может такое быть, что файл
                # получился нормальный с точки зрения формата json, но не полный
                # так что, возможно, требуются ещё проверки. Это может произойти
                # как из-за ошибок где-то в программе, так и из-за внезапного
                # отключения питания в самый неподходящий момент
                print('Фигня случается...')
                self._data['normal_mode'] = True  # а вот тут ты должен получать
                # состояние датчика при создании своей программы, True просто
                # для примера стоит, да и вообще все глобальные состояния,
                # которые у тебя есть, если такие имеются
        else:
            self._data['normal_mode'] = True  # а вот тут ты должен получать
            # состояние датчика при создании своей программы, True просто для
            # примера стоит, да и вообще все глобальные состояния, которые у
            # тебя есть, если такие имеются
        with open(self._settings_path, 'w') as outfile:
            json.dump(self._data, outfile)

    def change_normal_mode(self):  # функция для смены состояния датчика
        self._data["normal_mode"] = not self._data["normal_mode"]
        with open(self._settings_path, 'w') as outfile:
            json.dump(self._data, outfile)

    def get_normal_mode(self):
        return self._data["normal_mode"]


state = State()
print(state.get_normal_mode())
state.change_normal_mode()
print(state.get_normal_mode())

peregrine ★★★★★
()
Ответ на: комментарий от Uncle_Bobby

Итить колотить, как сложно выглядит… Ничего не понял из написанного) Но, насколько я понимаю, мне оптимальней не только в файл писать но и в память, чтобы не вычитывать каждые две секунды файл…

DALDON ★★★★★
() автор топика
Последнее исправление: DALDON (всего исправлений: 1)
Ответ на: комментарий от Uncle_Bobby

Когда у тебя сигнал на ножке сменится с 1 на 0 вызовется callback.

Uncle_Bobby
()
Ответ на: комментарий от DALDON

Да, так дешевле. Т.е. оборачивай ещё логику, если скорость важна

peregrine ★★★★★
()
Последнее исправление: peregrine (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.