简体   繁体   中英

Notification ping from backend using Web sockets and tornado

I am new to web-sockets. I am using tornado/python for my back-end and written the following code.

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()})

My JavaScript code is like the following,

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);

I am making a blank web-socket request request to the back-end every 100 millisecond. this seems a very bad solution to me. Is there any better way to do it without making multiple send() to the back-end and only notifying the user only on any changes in the meter reading?

Also i have gone through MQTT protocol to do this in a better way, can someone suggest how can i implement that?

You almost found the solution to your issue here:

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()})

As you could notice tornado needs some event to ping client through write_message method. You are using new message from client as such event, try to change to simple timeout call as event, like this:

# 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()

Check out tornado.ioloop documentation for more about PeriodicCallback and other options.

If you want to use tornado to MQTT protocol, it's not possible with tornado. You could try emqtt server for example, but this is actual server, not framework to write apps, so IMHO it would be more comprehensive that ping through web socket with tornado.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM