[Question] Photon + web server real time signal

Hi guys, I have in mind a project, to show the real time signal such as ECG, Spo2…in website via WIFI !!!

Can you give me advice where should I begin to learn and can we do it at least ? If you’ve some information about this project, please give me a tutorial or a link that I can watch & learn step by step.

Thank you guys so much for your support !

This should get you started

Br
Emilkl

1 Like

Thank you for your help. I’ll give it time to learn from now.

Which update frequency are you aiming for ?
You can get 1update per second using .publish and listening via server sent events, if that is not fast enough you need to do some manual magic.

1st improvement could be hosting a website on the photon and calling a ajax endpoint often, that could get you to 10 updates per second or so.

If you need 100+ you are looking at direct tcp/udp communication, so if a website is required, you need a intermediate server.

1 Like

Thank you MORA for these details information.
With this simple example :smile:

for(i=0; i<10; i++) {
   //send data to website 
    delay(20); //delay 20ms
}

Can you make an easy & simple tutorial to plot this sawtooth wave for me ? If the plotting step cost you quite too much time, I just need to see the value will show from 0 -> 10 repeatly without loosing any number, to make sure those data will totally go to website.

Too many solution on Google but I really dont know where will I begin.
One small question : Did you ever try Webduino ? I suddenly saw it somewhere in this forum.
Thank you MORA, once again !

20ms is pretty fast but doable…
Either you need a tcp connection that stays open and you just send more data, or you can use udp.
UDP does not gurantee delivery, especially if going over the internet, but if your data is for display anyway, a lost value may be preferable to a lagged value.

I made a small demo in python

import socket
import thread
import time
from SimpleWebSocketServer import SimpleWebSocketServer, WebSocket

clients = []
class SimpleChat(WebSocket):

    def handleMessage(self):
       for client in clients:
          if client != self:
             client.sendMessage(self.address[0] + u' - ' + self.data)

    def handleConnected(self):
       print self.address, 'connected'
       for client in clients:
          client.sendMessage(self.address[0] + u' - connected')
       clients.append(self)

    def handleClose(self):
       clients.remove(self)
       print self.address, 'closed'
       for client in clients:
          client.sendMessage(self.address[0] + u' - disconnected')

def udplisten():
   UDPSock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
   listen_addr = ("",5000)
   UDPSock.bind(listen_addr)
   print 'UDP listen done'
   while True:
      data,addr = UDPSock.recvfrom(1024)
      for client in clients:
         client.sendMessage(data.decode());
      print data.strip(),addr

thread.start_new_thread( udplisten, () )

server = SimpleWebSocketServer('', 8000, SimpleChat)
server.serveforever()

And a HTML page to show it

<!DOCTYPE html>

<meta charset="utf-8" />

<title>WebSocket Test</title>

<script language="javascript" type="text/javascript">


  function init()
  {
        document.myform.url.value = "ws://188.166.166.132:8000/"
        document.myform.inputtext.value = "Hello World!"
        document.myform.disconnectButton.disabled = true;
  }

  function doConnect()
  {
    websocket = new WebSocket(document.myform.url.value);
    websocket.onopen = function(evt) { onOpen(evt) };
    websocket.onclose = function(evt) { onClose(evt) };
    websocket.onmessage = function(evt) { onMessage(evt) };
    websocket.onerror = function(evt) { onError(evt) };
  }

  function onOpen(evt)
  {
    writeToScreen("connected\n");
        document.myform.connectButton.disabled = true;
        document.myform.disconnectButton.disabled = false;
  }

  function onClose(evt)
  {
    writeToScreen("disconnected\n");
        document.myform.connectButton.disabled = false;
        document.myform.disconnectButton.disabled = true;
  }

  function onMessage(evt)
  {
    writeToScreen("response: " + evt.data + '\n');
  }

  function onError(evt)
  {
    writeToScreen('error: ' + evt.data + '\n');

        websocket.close();

        document.myform.connectButton.disabled = false;
        document.myform.disconnectButton.disabled = true;

  }

  function doSend(message)
  {
    writeToScreen("sent: " + message + '\n');
    websocket.send(message);
  }

  function writeToScreen(message)
  {
    document.myform.outputtext.value += message
        document.myform.outputtext.scrollTop = document.myform.outputtext.scrollHeight;

  }

  window.addEventListener("load", init, false);


   function sendText() {
                doSend( document.myform.inputtext.value );
   }

  function clearText() {
                document.myform.outputtext.value = "";
   }

   function doDisconnect() {
                websocket.close();
   }


</script>

<div id="output"></div>

<form name="myform">
<p>
<textarea name="outputtext" rows="20" cols="50"></textarea>
</p>
<p style="display:none">
<textarea name="inputtext" cols="50"></textarea>
</p>
<p>
<textarea name="url" cols="50"></textarea>
</p>
<p>
<input type="button" name=sendButton value="Send" onClick="sendText();" style="display:none">
<input type="button" name=clearButton value="Clear" onClick="clearText();">
<input type="button" name=disconnectButton value="Disconnect" onClick="doDisconnect();">
<input type="button" name=connectButton value="Connect" onClick="doConnect();">
</p>


</form>
</html>

Photon script

UDP Udp;


IPAddress remoteIP(188, 166, 166, 132);
char buffer[10];

void setup() {
    Particle.publish("Connected ...");
    
    Udp.begin(5000);

    for(int i=0; i<100; i++) {
        //buffer[0] = 48+i; //Ascii value 48 = 0
        itoa(i, buffer, 10);
        Udp.sendPacket(buffer, sizeof(buffer), remoteIP, 5000);
        delay(20); //delay 20ms
    }
}

I tested it over the internet with 100 packages and while the log can keep up, 20ms is very fast to be making a graph :smile:

The server used in the code above are still running if you fancy a demo…

I’m sorry but I had not learned Python yet :expressionless:

Can we display number from 0 -> 10 in HTML from your demo above ? :expressionless: I had run the code in Photon, and open the HTML, “connected” but nothing else been displayed :frowning:

Did you use the ip above for the html or just opened it locally ?
Since we are using raw network packages, you need some sort of server inbetween the photon and the webclient.

I dont know a lot of python myself, I mostly use PHP or nodeJS, but python is very nice when dealing with lots of traffic, compared to PHP and nodeJS it uses less than 1% of the resources to do the job.

If you open http://188.166.166.132/websocket.html and click Connect
Then flash the photon above to your photon it will show 0-99 in the listbox.

Thank you for your solution at the bottom, but why we have to flash the Photon again after click “Connect” in HTML file, these number appear ok, then if we click “Disconnect” and “Connect” once again, this time these number will not show just like that ? Basically we have to flash Photon again and again after click “Connect” in HTML file.

This demo is very great, but how can we just flash Photon only one time, then right after click “Connect”, numbers will show normally, if we “disconnect” and “connect” again, numbers will show again. That exactly what I really need, that’s why I want to run ECG, SPO2 24/24 hours without flashing Photon several times

Please give me the solution.

Ah, one more thing, so finally, what is the purpose of the Python code above, I thought we just need HTML and Photon code then things would work :slight_smile:

You dont have to flash it again, I just didnt include a loop() function, partly as a safety feature if the code was bad, you can just reset the photon and it will upload again.

The connect/disconnect buttons controls your webbrowsers connection to the websocket server, not the photon directly.
The python code listens for UDP packages from the photon and forwards these packages to all connected clients.

For 50hz data, unless you can make a websocket server on the photon, you need a intermediate program that connects the photon and the browser, because browser network communication is somewhat limited on purpose.

Remember with great power and all that :wink:

UDP Udp;
IPAddress remoteIP(188, 166, 166, 132);
char buffer[10];

void setup() {
    Udp.begin(5000);
}
void loop()
{
    for(int i=0; i<10; i++) {
        //buffer[0] = 48+i; //Ascii value 48 = 0
        itoa(i, buffer, 10);
        Udp.sendPacket(buffer, sizeof(buffer), remoteIP, 5000);
        delay(20); //delay 20ms
    }
}

I don’t know where I need to put the python code to, now I only use HTML and Photon, seems like ok, right ?

I saw you wrote about the “intermediate program”, what is it ? Can you give me some information ?

This is what I get after running your code, how can we remove the whole weird character right after every each number ?

I’m sorry because It’s very brand new to me, so I always wanna ask as much as I can to learn more. Thank you for all your support MORA !

The reason it works on that ip is that the python server is already running :smile:
The intermediate program is the python code.

Its a bit complex setup because of the 50hz design requirement, I didnt get those chars when I tried it, so maybe an encoding issue.

The problem is photon and webclient cant directly talk to each other at high speed, AJAX allows some communication, but it could miss data and 50hz ajax is pretty agressive since each connection has the full tcp and http overhead.

How can we store the evt.data as array, MORA ?

The demo uses strings, but you can send a json encoded array or change it to comma seperated values etc.

Dear MORA, I got a weird problem once again. With your original code, but now when I click on “Connect”, it shows “Error : undefined”, “disconnected”. What’s wrong with my Photon ?

The demo server isnt running anymore, so you need to change to html to point to the ip where the python code is running, which should be the same as the webserver hosting the html.

I just wanted to demonstrate how you could transfer highspeed data from photon to a webbrowser, you need to put in some work to make it fit for your project, 50hz data from photon to webclient is not a simple scenario.

The intermediate server does not have to be python, it can be any language that supports sockets, but not all are suitable due to resources.