0

我正在尝试制作一个与我正在开发的物联网系统交互的电报机器人。实际上我一直在编写python电报机器人;她是我的问题:在机器人的聊天中,用户可以调用 InlineKeyboardButtons 来打开/关闭灯或设置计时器。当用户选择“计时器”按钮时,我想打开另一个 InlineKeyboardButtons 以使用户选择其他参数,但使用我当前的代码我无法做到这一点,因为代码跳转到“回调处理程序”。有什么建议吗?我将发布整个代码:

from MyMQTT import *
import time
from datetime import datetime, timedelta
import json
import requests
import random
import telepot
from telepot.loop import MessageLoop
from telepot.namedtuple import InlineKeyboardMarkup, InlineKeyboardButton, ReplyKeyboardMarkup
test=1

class tg_pub(object):
 
    def __init__(self, clientID, broker, port, topic):
        self.clientID = clientID
        # self.topic = str(topic)
        # self.topic = '/'.join([self.topic])
        self.client = MyMQTT(clientID, broker, port, self)
        self.__message = {
                "bn": "TelegramBot",
                "ip": "",
                "e": [
                    {
                        "n": "lights_command",
                        "u": "boolean",
                        "t": "2021-04-15 16:59:12.586822",
                        "v": "ON"
                    },
                    {
                        "n": "conditioner_command",
                        "u": "boolean",
                        "t": "2021-04-15 16:59:12.586822",
                        "v": "OFF"
                    }
                ]
            }

    def sendData(self, topic, output):
        message = self.__message
        message['e'][0]['v'] = output
        message['e'][0]['t'] = str(datetime.now())
        self.client.myPublish(topic, message)

    def start(self):
        self.client.start()

    def stop(self):
        self.client.stop()

class Room_Bot:
    def __init__(self, token, broker, port, topic):
        # the bot token is to be saved in the Catalog  !!!!
        self.tokenBot = token    # local token
        # self.tokenBot = requests.get("http://catalogIP/telegram_token").json()["telegramToken"]      # Catalog token
        self.bot= telepot.Bot(self.tokenBot)
        self.client = MyMQTT("telegramBot", broker, port, None)   # to be a publisher
        self.client.start()
        self.topic = topic
        self.__message={
                "bn": "TelegramBot",
                "ip": "",
                "e": [
                    {
                        "n": "lights_command",
                        "u": "boolean",
                        "t": "2021-04-15 16:59:12.586822",
                        "v": "ON"
                    },
                    {
                        "n": "conditioner_command",
                        "u": "boolean",
                        "t": "2021-04-15 16:59:12.586822",
                        "v": "OFF"
                    }
                ]
            }

        ### USING MESSAGES ###
        # MessageLoop(self.bot,{'chat': self.on_chat_message}).run_as_thread()

        ### USING BUTTONS -> query callback ###
        MessageLoop(self.bot, {'chat': self.on_chat_message, 'callback_query': self.on_callback_query}).run_as_thread()

    def sendMessage(self, topic):
        message=self.__message
        message['e'][0]['v']=random.randint(0,1)  # 0 = no movement detected
        message['e'][0]['t']=str(datetime.now())
        self.client.myPublish(topic, message)

    def start (self):
        self.client.start()

    def stop (self):
        self.client.stop()

    #HANDLING THE MESSAGES
    def on_chat_message(self, msg): 
        content_type, chat_type ,chat_ID = telepot.glance(msg)
        message = msg['text'] #retrieve the message from the key 'text' in the json
        
        ### USING MESSAGES ###
        # if message == "/switch_Lights_ON":
        #     payload = self.__message.copy()
        #     payload['e'][0]['v'] = "on"
        #     payload['e'][0]['t'] = str(datetime.now())
        #     self.client.myPublish(self.topic,payload)
        #     self.bot.sendMessage(chat_ID,text = "Lights switched on")
        # else:
        #     self.bot.sendMessage(chat_ID, text="Command not supported")

        ## USING BUTTONS ###
        if message == "/start":
            #self.bot.sendMessage(chat_ID, text="Welcome, I am HioTel. Please press one of the available buttons to get started.")
            keyboard = ReplyKeyboardMarkup(keyboard=[['Lights', 'Heater'], ['Status Info']])
            
            self.bot.sendMessage(chat_ID, text='Welcome, I am HioTel. Please press one of the available buttons to get started.', reply_markup=keyboard)

        elif message == "Lights":

            #Matrix of buttons
            keyboard = InlineKeyboardMarkup(inline_keyboard=[
                [
                    InlineKeyboardButton(text=f'Lights on ', callback_data=f'direct ON '),
                    InlineKeyboardButton(text=f'Lights off ⚫', callback_data=f'direct OFF')
                    ],
                    [
                        InlineKeyboardButton(text=f'Set timer ⏲️', callback_data=f'light_timer',test=0)
                    ]
                    ])
            self.bot.sendMessage(chat_ID, text='Lights menu:', reply_markup=keyboard) #REPLY TO USER

            
            

        elif message == "Heater":
            keyboard = InlineKeyboardMarkup(inline_keyboard=[
                [
                    InlineKeyboardButton(text=f'Heat on ', callback_data=f'heater_on'),
                    InlineKeyboardButton(text=f'Heat off ⚫', callback_data=f'heater_off')
                    ],
                    [
                    InlineKeyboardButton(text=f'Heat up ☀️', callback_data=f'heat_up'),
                    InlineKeyboardButton(text=f'Heat down ❄️', callback_data=f'heat_down')
                    ],
                    [
                        InlineKeyboardButton(text=f'Set timer ⏲️', callback_data=f'heater_timer')
                    ]
                    ])
            self.bot.sendMessage(chat_ID, text='Heater menu:', reply_markup=keyboard)


        elif message == "Status Info":
            self.bot.sendMessage(chat_ID, text=' Lights: ON\n\n Air conditioner: ON, set on tot°\nCurrent room conditions:\n tot° - umidiccio')
        else:
            self.bot.sendMessage(chat_ID, text="Command not supported")

    #HANDLING THE CALLBACKS 
    def on_callback_query(self, msg):
        query_ID , chat_ID , query_data = telepot.glance(msg, flavor='callback_query')
        payload = self.__message.copy()
        #if query_data=="light_timer":
            #keyboard = InlineKeyboardMarkup(inline_keyboard=[
                #[
                   # InlineKeyboardButton(text=f'5 minutes', callback_data=f'durati ON  5'),
                    #InlineKeyboardButton(text=f'15 minutes', callback_data=f'durati ON  15')
                    #],
                   # [
                     #   InlineKeyboardButton(text=f'30 minutes ', callback_data=f'durati ON  30')
                    #]
                   # ])
           # self.bot.sendMessage(chat_ID, text='Set timer:', reply_markup=keyboard)
            
        payload['e'][0]['v'] = query_data #SET AS MESSAGE WHAT USER SELECTED IN CHAT BUTTONS 
        payload['e'][0]['t'] = str(datetime.now())

        self.client.myPublish(self.topic, payload) #PUBLISH MQTT MESSAGE
        self.bot.sendMessage(chat_ID, text=f"{query_data}: done ✔") #FEEDBACK FOR THE USER
        print(test)



if __name__ == '__main__':
    
    url = "xxxxxx"
    clientID = 'telegram'

    settings = requests.post(url)
    
    config = list(settings.json())
    broker = config[0]["settings"][0]["broker"]
    port = config[0]["settings"][0]["port"]
    token = config[0]["settings"][0]["botToken"]
    baseTopic = config[0]["settings"][0]["baseTopic"]
    topic_pub_l = baseTopic +  config[0]["settings"][0]["lightControlTopic"]
    topic_pub_c = baseTopic +  config[0]["settings"][0]["conditControlTopic"]
    
    topic = baseTopic + topic_pub_l

    pub_l = tg_pub(clientID, broker, port, topic_pub_l)
    pub_l.start()

    output = None
    pub_l.sendData("hotel/catalog", output)
    time.sleep(random.randint(1,10))
    requests.post(url)
    

    bot = Room_Bot(token,broker,port,topic)
    
    while True:
        time.sleep(2)
4

1 回答 1

0

这是正确的,因为按下任何按钮 ( InlineKeyboardButtons ) 都会触发CallbackHandler负责处理响应的按钮。

一种选择是重构代码以创建发送给定响应的方法,例如

   def send_lights(chat_ID) :
     keyboard = InlineKeyboardMarkup(inline_keyboard=[
            [
                InlineKeyboardButton(text=f'Heat on ', callback_data=f'heater_on'),
                InlineKeyboardButton(text=f'Heat off ⚫', callback_data=f'heater_off')
                ],
                [
                InlineKeyboardButton(text=f'Heat up ☀️', callback_data=f'heat_up'),
                InlineKeyboardButton(text=f'Heat down ❄️', callback_data=f'heat_down')
                ],
                [
                    InlineKeyboardButton(text=f'Set timer ⏲️', callback_data=f'heater_timer')
                ]
                ])
        self.bot.sendMessage(chat_ID, text='Heater menu:', reply_markup=keyboard)

send_lights当用户按下给定按钮时,您可以从 CallbackHandler 调用新方法 ( )。

第二种选择是使用一个同时处理消息和回调的方法:老实说,我不确定您是如何做到的telepot,但是使用 PythonTelegramBot 是可能的:在这种情况下,您可以在同一个地方处理所有响应。

于 2021-04-24T15:09:27.557 回答