Multiple Cores Publishing to One Web Page

@Moors7
Firstly, the original code worked for me, and I can see the stream of my data of a specified event. For the number of the devices, I have four spark core devices. At the first, I wanted to display two events side by side in the same page instead of displaying one event in the page as the example does. Now, instead of that, I’d like to concatenate the data from four devices together and display them as one stream. As I mentioned in the previous post, The final displayed data will be (Event1’s Data+Event2’s Data+Event3’s Data+Event4’s Data) as a one stream. I understood the example, and here is what it does through the execution step by step:

<!DOCTYPE HTML>
<html>
<body>
    // This line is to insert the Event name that we would like to get it's data on the cloud
    <P>Event name:<input type="text" name="eventNameBox" id="evText" >

    // This line is to create the table of the CoreID, Data, and Timestamp
    <table id="dataTable" width="300px" border="2">

    // This line shows the content of the header of the table
	<td> Core ID </td>
	<td> Data </td>
	<td> Timestamp </td>
      </tr>
    </table>
	<br><br>

    // This line is to create a button called Connect and it has id of connectbutton, and when we click on it, it will execute the start fuction
	<button id="connectbutton" onclick="start()">Connect</button>

    // This line is to show that we are using JS within the html language
	<script type="text/javascript">

    // This function will execute when we click on the Connect button
    function start(objButton) {

    // This line is to get the data of the element by it's id which is connectbutton here, and after that change the name of the button from Connect to Running
        document.getElementById("connectbutton").innerHTML = "Running";

    // These three lines are to get and save in variables the name of the event that we inserted previously, to save the access token, and to request the data of the events that is related with this token from the particle cloud
        var eventName = document.getElementById('evText').value;
        var accessToken = "0000000000000000000000000000000000000";
	   var requestURL = "https://api.spark.io/v1/events/?access_token=" + accessToken;

    // This line is to get the source of the event from the cloud website
        var eventSource = new EventSource(requestURL);

    // This line is to add listener to the specified event that we entered at the beginning to continue get it's data whenever there is data 
		eventSource.addEventListener('open', function(e) {
            console.log("Opened!"); },false);

    // This line is to show when there is an error with reading the event's data from the cloud
        eventSource.addEventListener('error', function(e) {
            console.log("Errored!"); },false);

    // This function will execute when we listen to the event on the cloud to get it's data
>    eventSource.addEventListener(eventName, function(e) {

    // This line is to parae the data of the event, and save it in a variable e
		var parsedData = JSON.parse(e.data);

    // This line is to get and save data of the table, and save it in a variable dt
	    var dt = document.getElementById("dataTable");

    // This line is to calculate the length of the table's rows, and save it in a variable rows
        var rows = dt.rows.length;

    // This line is to initialize the var foundIt as a boolean expression and give it false value
	    var foundIt = false;

    // This for loop is to increase the number of the rows in the table each time there is a new data from the event
			for(var i=0;i<rows;i++) {

    // This line is to create a new variable, rowN, and put the table data in each rows inside the table
        var rowN = dt.rows[i];

    // This line is to check when the foundIt expression is still false and put the parsed CoreId data in the first cell of the first row in the table
	if (false==foundIt  && rowN.cells[0].innerHTML==parsedData.coreid) {

    // This line is to check when the foundIt expression becomes true, so start insert the data of the event in the second cell of the first row and put the data's published timestamp in the third cell of the first row
		foundIt = true;
		rowN.cells[1].innerHTML = parsedData.data;
		rowN.cells[2].innerHTML = parsedData.published_at;
	      }
	    }

    // This line is to maintain the data in the second line instead of replacing the coming data with the current data
	    //if (false == foundIt) {

    // These four lines are to create new row whenever there is new data and insert three cells inside it 
	    var newRow = dt.insertRow(rows);
        var cell1 = newRow.insertCell(0);
        var cell2 = newRow.insertCell(1);
        var cell3 = newRow.insertCell(2);           

    // These three lines are to put the data of coreid, event's data, and published timestamp of each new data 
			cell1.innerHTML = parsedData.coreid;
			cell2.innerHTML = parsedData.data;
			cell3.innerHTML = parsedData.published_at;
	    //}

        }, false);
    }
    </script>
</body>
</html>

Okay, that looks good. Seems like you’ve got a reasonable understanding of what’s going on. With that knowledge, where in the code does it use the eventName you provided to choose what it needs to listen to? If you could somehow change that to not look at the text box, but rather just take in a hard coded name, you could get rid of the box. Give that a try, and report back.

If all of the devices you use, use the same eventName, then they should all show up in that selected stream, only differing by DeviceID.

1 Like

@Moors7
I got the code working without need to insert the event name. I also deleted the input box. What I did is deleting the following line from the code:

<P>Event name:<input type="text" name="eventNameBox" id="evText" >

and modified the following line from:

var eventName = document.getElementById('evText').value;

to

var eventName = 'MyEventName';

Now, how can I concatenate the event's data from four devices together and display them as one stream? Is it easy to do that?

Thanks.

Use parsedData.coreid to distinguish which core is which in the event handler then take the last text from cores 1,2,3, and 4 (you need to store that) and concatenate them and store them somewhere on the page by setting the innerHTML of the element to the concat’ed string. I am not sure how you will know you are done since the events could potentially come in any order unless you know more about the order the cores will send the events.

1 Like

Dear @bko
Here is the two places in the code that have parsedData.coreid

Firstly, Which one I should use to distinguish the core as you mentioned in your post?
Secondly, you said that I can take the last text from cores 1,2,3,and 4 and store them, but these texts are not constant because they are related with the sensor's data. So how can I display or save them in this case?
Thirdly, how can I setting the innerHTML of the element to the concat'ed string?

Thanks in advance.

Neither. parsedData.coreid is the ID of the device who has published the event. Using that, you can determine which device emitted the event, after you can place it accordingly. You’ll have to write a bit of code yourself to determine which device did what. You can use if() statements, or switch case, which should both work fine.
I’d look something like (pseudocode, this won’t work copy&paste, you’ll have to write your own):

if (parsedData.coreid == 'core1ID'){
  var core1message = parsedData.data;
}
if (parsedData.coreid == 'core2ID'){
  var core2message = parsedData.data;
}
//and so on. 

or

switch (parsedData.coreid){
  case 'core1ID':
    var core1message = parsedData.data;
    break;
  case 'core2ID':
    var core2message = parsedData.data;
    break;
}
//and so on

Doing so, you’ll be saving the data in a new variable. Those variables can then be combined when needed.
Doing a quick google search leads you to “changing HTML using Javascript”, which can explain it better than we probably can. Also, the innerHTML is being used in the original example, so if you take a look at that, you should be able to figure it out.
Best of luck!

1 Like

@bko

Thanks for the great tutorial! Really helped me finish one of my projects.

One question though, is there a way to display the Device Name instead of the ID?

Thanks

@rsaiyid you would likely use parsedData.name rather than parsedData.coreid

here is the api reference https://docs.particle.io/reference/api/#get-device-information

cheers

Considering this is about SSE and not Variables, it’s not as easy as just using ‘name’ instead of ‘id’. The SSE doesn’t contain the Name, so there’s nothing to swap to. You can, however, make a call to list your devices and their names, and then use that to match the name to the corresponding ID.

1 Like

I haven’t read through the whole thread, so I just ask this: Do you want to send the device’s name via Particle.publish() or use it for something else on the device?

In this case you can Particle.subscribe("spark/device/", handler) and request the data from the cloud via Particle.publish("spark/device/name").

See https://docs.particle.io/reference/firmware/photon/#get-device-name

1 Like