fanout / django-eventstream

Server-Sent Events for Django
MIT License
650 stars 85 forks source link

Channel seems closed after receiving two messages #17

Closed vnahmias closed 6 years ago

vnahmias commented 6 years ago

Hello i am working on a iot system monitoring web application : here is my problem i receive in continuous data on a django server and each time i receive a new message i wanna send it to my client through django channels : here is my server code :

async def runCoap(self):
        protocol = await Context.create_client_context()
        while True:
            requestTemp = Message(code=GET, uri='coap://129.6.60.38/other/sensors/temperature')
            requestHumidity = Message(code=GET, uri='coap://129.6.60.38/other/sensors/humidity')
            try:
                responseTemp = await protocol.request(requestTemp).response
                responseHumidity = await protocol.request(requestHumidity).response
                await asyncio.sleep(1)
            except Exception as e:
                print('Failed to fetch resource:')
                print(e)
            else:
                payloadTemp=responseTemp.payload.decode("utf-8")
                payloadHumidity=responseHumidity.payload.decode("utf-8")
                a=len(payloadTemp)
                b=len(payloadHumidity)
                payloadTemp=json.loads(payloadTemp[:a-77])
                payloadHumidity=json.loads(payloadHumidity[:b-77])
                print("-----------------------------------------------")
                send_event('test', 'message', payloadTemp)
                send_event('test', 'message', payloadHumidity)

and here is my client code :

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
{% load staticfiles %}

<html lang="en">
  <head>
    {% load render_bundle from webpack_loader %}
    <script src="{% static 'django_eventstream/json2.js' %}"></script>
    <script src="{% static 'django_eventstream/eventsource.min.js' %}"></script>
    <script src="{% static 'django_eventstream/reconnecting-eventsource.js' %}"></script>
    <script>
      var logMessage = function (s) {
        console.log(s)
      };

      var start = function () {
        logMessage('connecting...');

        {% if last_id %}
          var es = new ReconnectingEventSource('{{ url|safe }}', {lastEventId: '{{ last_id }}'});
        {% else %}
          var es = new ReconnectingEventSource('{{ url|safe }}');
        {% endif %}

        es.onopen = function () {
          logMessage('connected');
        };

        es.onerror = function () {
          logMessage('connection error');
        };

        es.addEventListener('stream-reset', function (e) {
          e = JSON.parse(e.data);
          logMessage('stream reset: ' + JSON.stringify(e.channels));
        }, false);

        es.addEventListener('stream-error', function (e) {
          // hard stop
          es.close();
          e = JSON.parse(e.data);
          logMessage('stream error: ' + e.condition + ': ' + e.text);
        }, false);

        es.addEventListener('message', function (e) {
          logMessage('message: ' + e.data);
        }, false);
      };
    </script>

  </head>
  <body onload="start();">
    <div id= "Dashboard">
      {% render_bundle "IOT_Testbed_Dashboard" %}
      {% block content %}
      {% endblock %}
    </div>
  </body>
</html>

the issue is i only see two messages printed on my client side it looks like after receiving those messages the script is not running anymore or something i don't really know what to do (newbie at javascript/front end programmation))

jkarneges commented 6 years ago

Are you using Daphne? How are you launching the server? Where is runCoap running?

vnahmias commented 6 years ago

i launch the server running : python3 manage.py runserver and this function is ran just after the initialization of the app

jkarneges commented 6 years ago

Hmm, I don't see anything obviously wrong. Some debugging ideas:

  1. Use curl to read the stream, and see if it also stops printing messages.
  2. Make a function that just sends a test message in a loop, without the coap stuff, and see if that works any better.
vnahmias commented 6 years ago

Okay i am going to try this tmr i'll keep you updated

vnahmias commented 6 years ago

okay so i have made a few tests :

def test(self):
        while True:
            send_event('test', 'message', "Hello my name is Vincent")
            time.sleep(5)

this function only send a continuous stream if the line time.sleep(5) is commented but in the navigator console it shows me like 85 messages then i wait a bit and refresh the page and here i have 1000 messages but it is not really real time. So in my case removed the line await asyncio.sleep and it seems to work better but i was expecting a real continuous stream

jkarneges commented 6 years ago

time.sleep will block the eventloop. Try with await asyncio.sleep(5).

Also what happens if you curl? If you see a continuous stream there or not will tell us whether the issue is potentially browser related.

vnahmias commented 6 years ago

I don't know where you want me to use curl and how, sorry i am a newbie to web programming

jkarneges commented 6 years ago

curl -i url

(where url is the value you're currently passing to ReconnectingEventSource)

This will make the same request to the server that the browser is doing, and print the response data as it arrives.

vnahmias commented 6 years ago

i ran curl -i "http://localhost:8000/" in my terminal, and the output is the code of my html page i am not sure about what you want me to try

jkarneges commented 6 years ago

You'll want to use the URL being passed to ReconnectingEventSource, not the URL of the page.

jkarneges commented 6 years ago

@vnahmias , did you manage to resolve this?

vnahmias commented 6 years ago

Hello no i finally got rid off the django server and using Flask instead

jkarneges commented 6 years ago

Oh okay. I'll close this issue then.