websocket 在python线程中创建client.write_message

ep6jt1vc  于 2022-11-11  发布在  Python
关注(0)|答案(1)|浏览(185)

我目前正在用python Tornado做一个WebSocket服务器来管理我家的家庭自动化,原理如下:用户从网页发送命令(例如:打开供水),服务器接收该命令并激活连接到ESP32的继电器。
为了创建浇水时间表,我想我可以创建一个具有无限循环的线程,它查看数据库中保存的时间,我做了一个时间。睡眠的浇水时间减去当前时间,然后开始浇水。这部分是好的一切工作正常。但在那之后,我必须沟通连接的用户浇水是开着的,因此做了一个客户端。write_message(“浇水开始了”)但不幸的是,龙卷风不允许这样做。那么我怎么才能实现这样的目标呢?
在一些论坛上,人们建议用一个无限循环来一个接一个地处理命令,但这不适合我,它阻止了我的程序。
提前感谢您的回答。

class WSHandler(tornado.websocket.WebSocketHandler):
    def wateringProgram():
            time.sleep(secondsBeforeOnWatering) # secondsBeforeOnWatering in a db
            watering.on()
            for client in clients:
                client.write_message('watering is on')
            time.sleep(wateringDuration) # wateringDuration in a db
            watering.off()
            for client in clients:
                client.write_message('watering is off')

    threadProgram = threading.Thread(target=wateringProgram, args=())
    threadProgram.start()

    def open(self):
        WSHandler.clients.add(self) 
        self.write_message('logs')
        print ('[SERVEUR] Connection was opened')

    def on_message(self, message):
        if message == 'program changing':
            threadProgram.restart() # restart with the new timing

    def on_close(self):
        WSHandler.clients.remove(self)
        print ('[WS] Connection was closed.')

application = tornado.web.Application([
    (r'/ws', WSHandler),
],**settings)

if __name__ == "__main__":
    try:
        http_server = tornado.httpserver.HTTPServer(application)
        http_server.listen(PORT)
        main_loop = tornado.ioloop.IOLoop.instance()

        print ("Tornado Server started")
        main_loop.start()
    except:
        print ("Exception triggered - Tornado Server stopped.")

以上代码经过简化,更加简洁

2wnc66cl

2wnc66cl1#

我不认为你可以从龙卷风的线程发送消息。你必须调用主线程来传递消息。
首先,将当前IOLoop示例传递给wateringProgram函数。
第二步,使用IOLoop.add_callback从主线程发送消息。
下面是一个例子:

class WSHandler(tornado.websocket.WebSocketHandler):
    def wateringProgram(loop):
        time.sleep(secondsBeforeOnWatering) # secondsBeforeOnWatering in a db
        watering.on()

        loop.add_callback(WSHandler.send_message_to_all, msg='watering is on')

        time.sleep(wateringDuration) # wateringDuration in a db
        watering.off()

        loop.add_callback(WSHandler.send_message_to_all, msg='watering is on')

    threadProgram = threading.Thread(target=wateringProgram, args=(tornado.ioloop.IOLoop.current(),))
    threadProgram.start()

    @classmethod
    def send_message_to_all(cls, msg):
        for client in cls.clients:
            client.write_message(msg)

相关问题