Raspberry Pi, Telegram bot, Python (удаленное управление и мониторинг)

Тема в разделе "Raspberry Pi", создана пользователем urnash, 9 мар 2018.

  1. urnash

    urnash Нерд

    На просторах интернета найдет код, который позволяет удаленно управлять малинкой, включать\выключать пины, опрашивать состояние пинов.
    Может кому интересен будет код.
    Но цель моего визита на форум в том, что я хочу научить малинку следить за пинами в реальном времени и присылать сообщения о состоянии.
    То есть сейчас бот только может реагировать на команды и включать\выключать, присылать состояние 1 или 0...
    Я же хочу чтобы он присылал мне сообщение если на входе поменялся уровень с 1 на 0 или наоборот.
    Кто сможет помочь?:rolleyes:

    Код (Python):
    import time, datetime
    from time import sleep # для импульса в 0,5 сек у светодиода
    import RPi.GPIO as GPIO
    import telepot
    from telepot.loop import MessageLoop

    gpio5_pin29 = 5 #Управление 1
    gpio6_pin31 = 6 #Управление 2
    gpio20_pin38 = 20 #Статус 1
    gpio21_pin40 = 21 #Статус 2

    now = datetime.datetime.now() # получение даты
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)

    GPIO.setup(gpio5_pin29, GPIO.OUT) #gpio5_pin29 выход
    GPIO.output(gpio5_pin29, 0) #Off initially
    GPIO.setup(gpio6_pin31, GPIO.OUT) #gpio6_pin31 выход
    GPIO.output(gpio6_pin31, 0) #Off initially
    GPIO.setup(gpio20_pin38, GPIO.IN, pull_up_down=GPIO.PUD_UP) #gpio20_pin38 вход
    GPIO.setup(gpio21_pin40, GPIO.IN, pull_up_down=GPIO.PUD_UP) #gpio21_pin40 вход

    def action(msg):
        chat_id = msg['chat']['id']
        command = msg['text']

        if command == '/short_imp_rig1':
            GPIO.output(gpio5_pin29, 1)
            #sleep(0.3)
            #GPIO.output(gpio5_pin29, 0)
            telegram_bot.sendMessage (chat_id, str("Подан короткий импульс на 1"))
        elif command == '/long_imp_rig1':
            #GPIO.output(gpio5_pin29, 1)
            #sleep(3)
            GPIO.output(gpio5_pin29, 0)
            telegram_bot.sendMessage (chat_id, str("Подан длинный импульс на 2"))
        elif command == '/short_imp_rig2':
            GPIO.output(gpio6_pin31, 1)
            sleep(0.3)
            GPIO.output(gpio6_pin31, 0)
            telegram_bot.sendMessage (chat_id, str("Подан короткий импульс на 2"))
        elif command == '/long_imp_rig2':
            GPIO.output(gpio6_pin31, 1)
            sleep(3)
            GPIO.output(gpio6_pin31, 0)
            telegram_bot.sendMessage (chat_id, str("Подан длинный импульс на 2"))
        elif command == '/status_rig1':
            value1 = GPIO.input(gpio20_pin38) #В переменную value будет записано состояние пина 20
            telegram_bot.sendMessage (chat_id, str("Статус 1: ")+str(value1))
        elif command == '/status_rig2':
            value2 = GPIO.input(gpio21_pin40) #В переменную value будет записано состояние пина 21
            telegram_bot.sendMessage (chat_id, str("Статус 2: ")+str(value2))

    telegram_bot = telepot.Bot('0000000000:000000000000000000000000000000000000000')
    print (telegram_bot.getMe())
    MessageLoop(telegram_bot, action).run_as_thread()

    while 1:
        time.sleep(10)
     
    Igor68 и arkadyf нравится это.
  2. urnash

    urnash Нерд

    Вот возможные команды телеграм

    short_imp_rig1 - Короткий импульс на 1
    long_imp_rig1 - Длинный импульс на 1
    short_imp_rig2 - Короткий импульс на 2
    long_imp_rig2 - Длинный импульс на 2
    status_rig1 - Статус 1
    status_rig2 - Статус 2
     
    Igor68 и arkadyf нравится это.
  3. Arduino_man

    Arduino_man Гик

    Сейчас попробую набросать код для Вашей задачи.
     
    Igor68 и urnash нравится это.
  4. Arduino_man

    Arduino_man Гик

    Вот код:
    Код (Python):
    import time, datetime
    from time import sleep # для импульса в 0,5 сек у светодиода
    import RPi.GPIO as GPIO
    import telepot
    from telepot.loop import MessageLoop

    gpio5_pin29 = 5 #Управление 1
    gpio6_pin31 = 6 #Управление 2
    gpio20_pin38 = 20 #Статус 1
    gpio21_pin40 = 21 #Статус 2

    now = datetime.datetime.now() # получение даты
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)

    GPIO.setup(gpio5_pin29, GPIO.OUT) #gpio5_pin29 выход
    GPIO.output(gpio5_pin29, 0) #Off initially
    GPIO.setup(gpio6_pin31, GPIO.OUT) #gpio6_pin31 выход
    GPIO.output(gpio6_pin31, 0) #Off initially
    GPIO.setup(gpio20_pin38, GPIO.IN, pull_up_down=GPIO.PUD_UP) #gpio20_pin38 вход
    GPIO.setup(gpio21_pin40, GPIO.IN, pull_up_down=GPIO.PUD_UP) #gpio21_pin40 вход

    #Вот здесь читаете с нужного пина состояние (вместо X)
    value_new=X
    value_old=value_new

    def action(msg):
        chat_id = msg['chat']['id']
        command = msg['text']

        global myChat=chat_id

        if command == '/short_imp_rig1':
            GPIO.output(gpio5_pin29, 1)
            #sleep(0.3)
            #GPIO.output(gpio5_pin29, 0)
            telegram_bot.sendMessage (chat_id, str("Подан короткий импульс на 1"))
        elif command == '/long_imp_rig1':
            #GPIO.output(gpio5_pin29, 1)
            #sleep(3)
            GPIO.output(gpio5_pin29, 0)
            telegram_bot.sendMessage (chat_id, str("Подан длинный импульс на 2"))
        elif command == '/short_imp_rig2':
            GPIO.output(gpio6_pin31, 1)
            sleep(0.3)
            GPIO.output(gpio6_pin31, 0)
            telegram_bot.sendMessage (chat_id, str("Подан короткий импульс на 2"))
        elif command == '/long_imp_rig2':
            GPIO.output(gpio6_pin31, 1)
            sleep(3)
            GPIO.output(gpio6_pin31, 0)
            telegram_bot.sendMessage (chat_id, str("Подан длинный импульс на 2"))
        elif command == '/status_rig1':
            value1 = GPIO.input(gpio20_pin38) #В переменную value будет записано состояние пина 20
            telegram_bot.sendMessage (chat_id, str("Статус 1: ")+str(value1))
        elif command == '/status_rig2':
            value2 = GPIO.input(gpio21_pin40) #В переменную value будет записано состояние пина 21
            telegram_bot.sendMessage (chat_id, str("Статус 2: ")+str(value2))

    telegram_bot = telepot.Bot('0000000000:000000000000000000000000000000000000000')
    print (telegram_bot.getMe())
    MessageLoop(telegram_bot, action).run_as_thread()

    while 1:
        time.sleep(1)
       
        #Читаете с нужного пина состояние
        value_new=Y
       
        #если новое состояние отличается от старого, пишем в старое состояние новое, и отправляем сообщение
        if value_new!=value_old:
            value_old=value_new
           
            telegram_bot.sendMessage (myChat, "Состояние изменено!")
     
  5. urnash

    urnash Нерд

    Код представленный выше взял с https://circuitdigest.com/microcontroller-projects/control-raspberry-pi-gpio-with-telegram
    Есть другие варианты в сети, но я их не смог запустить, кто то говорит что это связано с тем, что телеграм поменял свой API

    Но код представленный выше встречается на нескольких форумах и работает. То ест наиболее свежий и рабочий.
     
    Igor68 и arkadyf нравится это.
  6. Arduino_man

    Arduino_man Гик

    Когда проверите новый код на работоспособность - отпишитесь.
     
  7. Arduino_man

    Arduino_man Гик

    Разберетесь, что подправил?
    Не гарантирую, что будет правильно (на raspberry ботов еще не делал), но может получиться.
     
    Igor68 нравится это.
  8. urnash

    urnash Нерд

    К сожаления выходит ошибка, я нуб и не могу разобраться :(
     

    Вложения:

  9. urnash

    urnash Нерд

    Чат ай ди можно получить с помощью
    Код (Python):
    print(chat_id)
    он имеет вид 123456789
    Далее вставляем его в
    Код (Python):
    telegram_bot.sendMessage (myChat, "Состояние изменено!")
    (вот сюда вставляем 123456789,"Состояние изменено!")

    То есть я закоментировал место где ошибка
    Код (Python):
    global myChat=chat_id
    и вручную прописал ему чат айди.

    Но теперь и ишибок нет и сообщение не присылает об изменении состояния.
    Предполагаю, что блок отправки сообщения
    Код (Python):
    telegram_bot.sendMessage(myChat,"Состояние изменено!")
    работает только если он идет после
    Код (Python):
    def action(msg):
        chat_id = msg['chat']['id']
        command = msg['text']
     
  10. Arduino_man

    Arduino_man Гик

    А Вы с этим местом разобрались?
    Код (Python):
    #Вот здесь читаете с нужного пина состояние (вместо X)
    value_new=X
    value_old=value_new
     
    Igor68 и urnash нравится это.
  11. urnash

    urnash Нерд

    Делал вот так

    Код (Python):
    import time, datetime
    from time import sleep # для импульса в 0,5 сек у светодиода
    import RPi.GPIO as GPIO
    import telepot
    from telepot.loop import MessageLoop

    gpio5_pin29 = 5 #Управление 1
    gpio6_pin31 = 6 #Управление 2
    gpio20_pin38 = 20 #Статус 1
    gpio21_pin40 = 21 #Статус 2

    now = datetime.datetime.now() # получение даты
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)

    GPIO.setup(gpio5_pin29, GPIO.OUT) #gpio5_pin29 выход
    GPIO.output(gpio5_pin29, 0) #Off initially
    GPIO.setup(gpio6_pin31, GPIO.OUT) #gpio6_pin31 выход
    GPIO.output(gpio6_pin31, 0) #Off initially
    GPIO.setup(gpio20_pin38, GPIO.IN, pull_up_down=GPIO.PUD_UP) #gpio20_pin38 вход
    GPIO.setup(gpio21_pin40, GPIO.IN, pull_up_down=GPIO.PUD_UP) #gpio21_pin40 вход

    #Вот здесь читаете с нужного пина состояние (вместо X)
    value_new=gpio20_pin38
    value_old=value_new

    def action(msg):
        chat_id = msg['chat']['id']
        command = msg['text']

        global myChat=chat_id

        if command == '/short_imp_rig1':
            GPIO.output(gpio5_pin29, 1)
            #sleep(0.3)
            #GPIO.output(gpio5_pin29, 0)
            telegram_bot.sendMessage (chat_id, str("Подан короткий импульс на 1"))
        elif command == '/long_imp_rig1':
            #GPIO.output(gpio5_pin29, 1)
            #sleep(3)
            GPIO.output(gpio5_pin29, 0)
            telegram_bot.sendMessage (chat_id, str("Подан длинный импульс на 2"))
        elif command == '/short_imp_rig2':
            GPIO.output(gpio6_pin31, 1)
            sleep(0.3)
            GPIO.output(gpio6_pin31, 0)
            telegram_bot.sendMessage (chat_id, str("Подан короткий импульс на 2"))
        elif command == '/long_imp_rig2':
            GPIO.output(gpio6_pin31, 1)
            sleep(3)
            GPIO.output(gpio6_pin31, 0)
            telegram_bot.sendMessage (chat_id, str("Подан длинный импульс на 2"))
        elif command == '/status_rig1':
            value1 = GPIO.input(gpio20_pin38) #В переменную value будет записано состояние пина 20
            telegram_bot.sendMessage (chat_id, str("Статус 1: ")+str(value1))
        elif command == '/status_rig2':
            value2 = GPIO.input(gpio21_pin40) #В переменную value будет записано состояние пина 21
            telegram_bot.sendMessage (chat_id, str("Статус 2: ")+str(value2))

    telegram_bot = telepot.Bot('0000000000:000000000000000000000000000000000000000')
    print (telegram_bot.getMe())
    MessageLoop(telegram_bot, action).run_as_thread()

    while 1:
        time.sleep(1)
     
        #Читаете с нужного пина состояние
        value_new=gpio20_pin38
     
        #если новое состояние отличается от старого, пишем в старое состояние новое, и отправляем сообщение
        if value_new!=value_old:
            value_old=value_new
         
            telegram_bot.sendMessage (myChat, "Состояние изменено!")
     
  12. urnash

    urnash Нерд

    Я понял свою ошибку, скрипт заработал и теперь следит за состоянием.
    Спасибо большое за помощь :):):)
    Код (Python):
    import time, datetime
    from time import sleep # для импульса в 0,5 сек у светодиода
    import RPi.GPIO as GPIO
    import telepot
    from telepot.loop import MessageLoop

    gpio5_pin29 = 5 #Управление 1
    gpio6_pin31 = 6 #Управление 2
    gpio20_pin38 = 20 #Статус 1
    gpio21_pin40 = 21 #Статус 2

    now = datetime.datetime.now() # получение даты
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)

    GPIO.setup(gpio5_pin29, GPIO.OUT) #gpio5_pin29 выход
    GPIO.output(gpio5_pin29, 0) #Off initially
    GPIO.setup(gpio6_pin31, GPIO.OUT) #gpio6_pin31 выход
    GPIO.output(gpio6_pin31, 0) #Off initially
    GPIO.setup(gpio20_pin38, GPIO.IN, pull_up_down=GPIO.PUD_UP) #gpio20_pin38 вход
    GPIO.setup(gpio21_pin40, GPIO.IN, pull_up_down=GPIO.PUD_UP) #gpio21_pin40 вход

    #Вот здесь читаете с нужного пина состояние (вместо X)
    value_new=GPIO.input(gpio21_pin40)
    value_old=value_new

    def action(msg):
        chat_id = msg['chat']['id']
        command = msg['text']

        global myChat=chat_id

        if command == '/short_imp_rig1':
            GPIO.output(gpio5_pin29, 1)
            #sleep(0.3)
            #GPIO.output(gpio5_pin29, 0)
            telegram_bot.sendMessage (chat_id, str("Подан короткий импульс на 1"))
        elif command == '/long_imp_rig1':
            #GPIO.output(gpio5_pin29, 1)
            #sleep(3)
            GPIO.output(gpio5_pin29, 0)
            telegram_bot.sendMessage (chat_id, str("Подан длинный импульс на 2"))
        elif command == '/short_imp_rig2':
            GPIO.output(gpio6_pin31, 1)
            sleep(0.3)
            GPIO.output(gpio6_pin31, 0)
            telegram_bot.sendMessage (chat_id, str("Подан короткий импульс на 2"))
        elif command == '/long_imp_rig2':
            GPIO.output(gpio6_pin31, 1)
            sleep(3)
            GPIO.output(gpio6_pin31, 0)
            telegram_bot.sendMessage (chat_id, str("Подан длинный импульс на 2"))
        elif command == '/status_rig1':
            value1 = GPIO.input(gpio20_pin38) #В переменную value будет записано состояние пина 20
            telegram_bot.sendMessage (chat_id, str("Статус 1: ")+str(value1))
        elif command == '/status_rig2':
            value2 = GPIO.input(gpio21_pin40) #В переменную value будет записано состояние пина 21
            telegram_bot.sendMessage (chat_id, str("Статус 2: ")+str(value2))

    telegram_bot = telepot.Bot('0000000000:000000000000000000000000000000000000000')
    print (telegram_bot.getMe())
    MessageLoop(telegram_bot, action).run_as_thread()

    while 1:
        time.sleep(1)
     
        #Читаете с нужного пина состояние
        value_new=GPIO.input(gpio21_pin40)
     
        #если новое состояние отличается от старого, пишем в старое состояние новое, и отправляем сообщение
        if value_new!=value_old:
            value_old=value_new
         
            telegram_bot.sendMessage (myChat, "Состояние изменено!")
     
    arkadyf и Securbond нравится это.
  13. gigabelka

    gigabelka Нерд

    Пасибо за код, переделал под свои нужды, может кому пригодится.
    Логика простая в коде. Можно сделать простую оповещалку с датчиков.
    Код (Python):

    import time, datetime
    import RPi.GPIO as GPIO
    import telepot
    from telepot.loop import MessageLoop

    telegram_bot = telepot.Bot('1234567890:5n745yne8yt8eyt8entegtcengtcnegtegtcge')
    chat_id = '1234567890' #Свой ID

    gpio21 = 21 #Статус 1
    gpio22 = 22 #Статус 2

    now = datetime.datetime.now() # получение даты
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)

    GPIO.setup(gpio21, GPIO.IN, pull_up_down=GPIO.PUD_UP) #gpio21 вход
    GPIO.setup(gpio22, GPIO.IN, pull_up_down=GPIO.PUD_UP) #gpio22 вход

    #Вот здесь читаете с нужного пина состояние (вместо X)
    value_new1=GPIO.input(gpio21)
    value_old1=value_new1

    value_new2=GPIO.input(gpio22)
    value_old2=value_new2

    def action(msg):
        chat_id = msg['chat']['id']
        command = msg['text']

        if command == '/stat_21':
            value1 = GPIO.input(gpio21) #В переменную value будет записано состояние пина 21
            telegram_bot.sendMessage (chat_id, str("Статус_21: ")+str(value1))
        elif command == '/stat_22':
            value2 = GPIO.input(gpio22) #В переменную value будет записано состояние пина 22
            telegram_bot.sendMessage (chat_id, str("Статус_22: ")+str(value2))

    print (telegram_bot.getMe())
    MessageLoop(telegram_bot, action).run_as_thread()

    while 1:
        time.sleep(1)
       
        #Читаете с нужного пина состояние
        value_new1=GPIO.input(gpio21)
        value_new2=GPIO.input(gpio22)
        #если новое состояние отличается от старого, пишем в старое состояние новое, и отправляем сообщение
        if value_new1!=value_old1:
            value_old1=value_new1
         
            telegram_bot.sendMessage (chat_id, "pin21_Состояние изменено")

        elif value_new2!=value_old2:
            value_old2=value_new2
         
            telegram_bot.sendMessage (chat_id, "pin22_Состояние изменено")
     
     
    arkadyf нравится это.
  14. Arduino_man

    Arduino_man Гик

    У Вас тут ошибочка вроде.
    Советую вот в этих двух местах заменить chat_id на что-то другое (например, my_chat_id)
    Код (Python):
    chat_id = '1234567890' #Свой ID

    gpio21 = 21 #Статус 1
    gpio22 = 22 #Статус 2
    Код (Python):
    if value_new1!=value_old1:
            value_old1=value_new1
       
            telegram_bot.sendMessage (chat_id, "pin21_Состояние изменено")

        elif value_new2!=value_old2:
            value_old2=value_new2
       
            telegram_bot.sendMessage (chat_id, "pin22_Состояние изменено")
    Не уверен, но если оставить так, возможен конфликт вот с этим местом
    Код (Python):
    def action(msg):
        chat_id = msg['chat']['id']
        command = msg['text']
     
    gigabelka нравится это.
  15. gigabelka

    gigabelka Нерд

    Спасибо большое за подсказку. Начал заниматься питоном только на прошлой неделе, опыта вобще нет.
    Вы были правы, в 3-м питоне был конфликт, во 2-м работал. Запускаю на малинке на девятом дебиане.
    Код поправил. Для новичка самое оно. Тут главное уловить логику.
    Код (Python):

    import time, datetime
    import RPi.GPIO as GPIO
    import telepot
    from telepot.loop import MessageLoop

    #global myChat=chat_id

    telegram_bot = telepot.Bot('1234567890:AAHZX4oe4umvy6875y684SAB9mJ9DLaTns')
    my_chat_id = '0987654321' #Свой ID

    gpio21 = 21 #Статус 1
    gpio22 = 22 #Статус 2

    now = datetime.datetime.now() # получение даты
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)

    GPIO.setup(gpio21, GPIO.IN, pull_up_down=GPIO.PUD_UP) #gpio21 вход
    GPIO.setup(gpio22, GPIO.IN, pull_up_down=GPIO.PUD_UP) #gpio22 вход

    #Вот здесь читаете с нужного пина состояние (вместо X)
    value_new1=GPIO.input(gpio21)
    value_old1=value_new1

    value_new2=GPIO.input(gpio22)
    value_old2=value_new2

    def action(msg):
        chat_id = msg['chat']['id']
        command = msg['text']

        if command == '/stat_21':
            value1 = GPIO.input(gpio21) #В переменную value будет записано состояние пина 21
            telegram_bot.sendMessage (my_chat_id, str("Статус_21: ")+str(value1))
        elif command == '/stat_22':
            value2 = GPIO.input(gpio22) #В переменную value будет записано состояние пина 22
            telegram_bot.sendMessage (my_chat_id, str("Статус_22: ")+str(value2))

    print (telegram_bot.getMe())
    MessageLoop(telegram_bot, action).run_as_thread()

    while 1:
        time.sleep(1)
       
        #Читаете с нужного пина состояние
        value_new1=GPIO.input(gpio21)
        value_new2=GPIO.input(gpio22)
        #если новое состояние отличается от старого, пишем в старое состояние новое, и отправляем сообщение
        if value_new1!=value_old1:
            value_old1=value_new1
         
            telegram_bot.sendMessage (my_chat_id, "pin21_Состояние изменено")

        elif value_new2!=value_old2:
            value_old2=value_new2
         
            telegram_bot.sendMessage (my_chat_id, "pin22_Состояние изменено")
     
     
  16. gigabelka

    gigabelka Нерд

    Может кому пригодиться как шаблон, сыровато, но для эксов потянет. Написал под другую библиотеку pytelegrambotapi. Кнопку подключал через 1 Ком, на всякий случай чтоб случайно не коротнуть лишнего, у малинки пины идут прямо на проц, спалить нефиг делать. Сделал всё методом тыка, "всегда работает".
    Код (Python):

    import RPi.GPIO as GPIO
    import telebot
    from telebot import types
    import time

    GPIO.setmode(GPIO.BCM)
    GPIO.setup(21, GPIO.IN, pull_up_down=GPIO.PUD_UP) # gpio21 вход, подтяжка к питанию

    TOKEN = '0987654321:AAvt4tvX4amsd6Oum86yn95ymB9mJ9DLaTns' # Токен от тетеграм бота
    chat_id = '1234567890' # Свой ID

    bot = telebot.TeleBot(TOKEN)

    @bot.message_handler(commands=['stat_21']) # Должна придти команда /stat_21
    def command_terms(message):
        bot.send_message(chat_id, 'pin21: ' + str(GPIO.input(21))) # Отправка в телеграм pin21 + состояние
        print('pin21:', (GPIO.input(21))) # Вывод в терминал pin21 + состояние

    def button(pin):
        bot.send_message(chat_id, 'pin21: 0')
        print('pin21: 0')

    GPIO.add_event_detect(21, GPIO.FALLING, callback=button, bouncetime=1000)
     
    if __name__ == '__main__':
        bot.polling(none_stop=True)

     
     
  17. urnash

    urnash Нерд

    К сожалению расбери почему-то зависает при работе скрипта, просто к утру перестает отвечать, а на мониторе черный экран, пингов нет.
    Максимум держится 1-1,5 дня.
    Для проверки оставил расбери включенным, но без запущенного скрипта. Уже неделю работает...
    Кто может помочь советом, догадками, методами диагностики? (может есть способ логировать)