使用Web套接字和龙卷风从后端通知ping

时间:2016-12-06 13:07:14

标签: python websocket tornado mqtt

我是网络套接字的新手。我在后端使用tornado / python并编写了以下代码。

class BaseWebSocketHandler(websocket.WebSocketHandler):
    """Base Class to establish an websocket connection."""

    def open(self):
        """Opening the web socket connection."""
        self.write_message('Connection Established.')

    def on_message(self, message):
        """On message module send the response."""
        pass

    def on_close(self):
        """Close the connection."""
        self.write_message('bye')

class MeterInfo(BaseWebSocketHandler):
    """Establish an websocket connection and send meter readings."""

    def on_message(self, message):
        """On message module send to the response."""
        self.write_message({'A': get_meter_reading()})

我的JavaScript代码如下所示,

var meter = new WebSocket("ws://"+window.location.host+"/socket/meterstatus/");
meter.onopen = function() {
      $('#meter-well').text('Establishing connection...');
};
meter.onmessage = function (evt) {
     var data = JSON.parse(evt.data)
     var text = "<div class='meter'><h2>" + data.A +"</h2></div>";
     $('#meter-pre').html(text);
};
meter.onclose = function (evt) {
     console.log(JSON.parse(evt.data))
     $('#meter-pre').append('\n'+evt.data);
};
window.setInterval(function(){ meter.send('') }, 100);

我每100毫秒向后端发出一个空白的Web套接字请求请求。这似乎是一个非常糟糕的解决方案。有没有更好的方法来做到这一点,而不需要在后端进行多次send(),只在抄表中发生任何变化时通知用户?

此外,我已经通过MQTT协议以更好的方式执行此操作,有人可以建议我如何实现它?

1 个答案:

答案 0 :(得分:0)

您几乎找到了解决问题的方法:

class MeterInfo(BaseWebSocketHandler):
"""Establish an websocket connection and send meter readings."""

   def on_message(self, message):
       """On message module send to the response."""
       self.write_message({'A': get_meter_reading()})

您可能会注意到龙卷风需要一些事件来通过write_message方法ping客户端。您正在使用来自客户端的新消息作为此类事件,尝试将简单超时调用更改为事件,如下所示:

# BaseWebSocketHandler removed, because we need to track all opened
# sockets in the class. You could change this later.
class MeterInfo(websocket.WebSocketHandler):
    """Establish an websocket connection and send meter readings."""
    opened_sockets = []
    previous_meter_reading = 0

    def open(self):
    """Opening the web socket connection."""
        self.write_message('Connection Established.')
        MeterInfo.opened_sockets.append(self)

    def on_close(self):
        """Close the connection."""
        self.write_message('bye')
        MeterInfo.opened_sockets.remove(self)

    @classmethod
    def try_send_new_reading(cls):
        """Send new reading to all connected clients"""
        new_reading = get_meter_reading()

        if new_reading == cls.previous_meter_reading:
            return

        cls.previous_meter_reading = new_reading

        for socket in cls.opened_sockets:
            socket.write_message({'A': new_reading})

if __name__ == '__main__':
    # add this after all set up and before starting ioloop
    METER_CHECK_INTERVAL = 100  # ms
    ioloop.PeriodicCallback(MeterInfo.try_send_new_reading,
                            METER_CHECK_INTERVAL).start()
    # start loop
    ioloop.IOLoop.instance().start()

查看tornado.ioloop documentation以了解有关PeriodicCallback和其他选项的更多信息。

如果你想将龙卷风用于MQTT协议,龙卷风是不可能的。例如,您可以尝试emqtt server,但这是实际的服务器,而不是编写应用程序的框架,所以恕我直言,通过龙卷风ping网络套接字会更全面。