JSONP control summary

I spent the last couple of snow days playing with my Mega running a webserver and working out a rich way to interact with it using browser pages. As has been mentioned many times in this forum, serving web pages whole from the Arduino is not it's strongest suit. A better way to communicate using http protocol (fairly straight forward) is to use JSONP requests for data. There are many great suggestions on how to do this sprinkled around this forum but I found the references scattered. I thought it might be useful for others setting out on this course to have a one stop shopping spot for a possible starting point.

JSONP is an acronym for Packaged Javascript Object Network Protocol which allows a web page to send and get a message from a server that is somewhere other than where the original web page came from. This is useful if you want to use the rich graphics of HTML5 to display values from an Arduino or, more importantly for me, develop a web based controller for the Arduino. Nothing in this entry is in any way new, it is merely a consolidation of information from different sources.

There are 2 pieces that have to work together. You have to coordinate javascript on a web page with the responses of the Arduino. Fortunately this isn't as hard as it sounds. To make things easy on the browser side, I use jQuery to help control the web page. I am not a jQuery expert or even a javascript maven yet I found it easy to set up this part of the solution. What follows are the salient pieces although the full code with comments are available as attachments.

[snip]
<!-- Load a copy of jQuery.  It can be local or from one of the many, many servers worldwide -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
[snip]
<script >
	function remoteRequest() {
		//	I agree with the author that although there are shortcut methods within jQuery, I
		//	found that by wrestling with the various options I was able to learn more about
		//	what is actually going on.
		$.ajax({
			url: "http://«ip address of arduino»/",
			// the name of the callback function has to match the function listed below
			jsonp: "analogValues",  // The Arduino can expect this as a trigger for a certain responses
			// tell jQuery we're expecting JSONP
			dataType: "jsonp",
			// because handling POSTs can be tricky we use the GET method
			type: "GET",
			// These can fine tune the request, for example we might use this to select a particular channel
			data: {  CH: "10", ACTION: 0, DOG: "hello", CODA:true },     // or "Hello=there&dog=cat", 
[snip]more boiler plate stuff.

	// This has to match the function provided in the ajax call above.
	function analogValues( responses ) {
		// the details on how you handle this depend on how you structure the response from the Arduino
		var html = '<table>' + 
			'<tr><td>A0</td><td>' + responses['A0'] + '</td></tr>' +
[snip]etc, etc....

<body>
	<h2>SOAP [JSONP] Tester</h2>
	<p id="result">Here is where the data will appear
		</p>
 	<hr/>
[snip]

I stripped the previous code to the bare bones while still trying to maintain clarity. It is fully functional 'as is'. You can hold this html file on your local machine or on a common server. I have a local server (not the arduino) inside my firewall for just such purposes. It can also be out on the interweb :roll_eyes: if you prefer.

The next piece is what has to run on the Arduino. Again, I stripped it down as much as reasonable without loosing clarity. It is fully functional bit of code although it doesn't do much except to read the analog inputs and send them out. I snipped out the extras which are available in the source code file.

[snip]
 
// structure for the jsonRequest from the client
struct JR {
    char* functionName;
    char* clientParameters[maxParameters];
    int nParams;  // not used currently 
    } jsonRequest;


//----------
// Assemble the client's request into a buffer we will later parse.
void getRequest( EthernetClient *client ) {
}

//----------
// Send the response based on the requested function and any parameters.
void sendResponse( EthernetClient *ec ) {
//	Serial.println( "=*= sending response..." );  // DEBUG CHECK
        if ( togLED ) { digitalWrite(PIN,LOW); togLED = false; }
        else { digitalWrite(PIN,HIGH); togLED = true; }

        ec->print(jsonRequest.functionName);
	ec->println("({");

	// output the value of each analog input pin
	for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
		int sensorReading = analogRead(analogChannel);

		ec->print("'A"); ec->print(analogChannel); ec->print("':");
		ec->print(sensorReading); ec->print(",");

	}
	ec->println("'end':'analogReadings'});");
}

//----------
// Send the standard http header prior to responding
void sendHeader( EthernetClient* ec ) {

//----------
// Send an error to an unrecognized command
void sendError( EthernetClient* ec ) {


//----------
// Break the full request in the URI into parts for later processing  if we return false then something is wrong.
boolean parseRequest() {

void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();

  // if the client is non-nil
  if (client) {
	getRequest( &client );
	if ( parseRequest() ) {
            // Successful parse - follows my rules, good client!
            sendHeader( &client );
    	    sendResponse( &client );
        } 
        else { 
            // Unsuccessful parse - bad client!
            sendError( &client );
        }
	
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
  } // valid client 

}

The cool thing to note is that you can specify a callback function which can be picked up by the Arduino as a switch that can toggle between different tasks. You can then fine tune the results returned according to parameters provided in the query portion of the URI.

While it is valuable to do your own leg work, I offer these working snippets up as starting points to help someone else going trying this approach. I did quite a bit of testing to get the working setup provided here. Hopefully a few will find it useful.

jquery ajax jQuery’s Ajax-Related Methods | jQuery Learning Center
jquery http://learn.jquery.com/
http guts RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1

jSONP_ArduinoCode.c (8.01 KB)

JSONP_BrowserCode.html (2.77 KB)