QNX Data server and slinger use with dynamic HTML

I am tasked with developing a web page interface for the device. This page will dynamically auto update data being displayed whose source is the embedded application. I was wondering if you could point me in the right direction.

I found out that QNX comes with a light duty web page server called Slinger. I managed to get the server to load and run. I also discovered that QNX has a data server “ds” that can be used to serve up global data to Slinger. So I wrote some test html and a server application that generates a count string. I managed to get my web page to show the ds server data on it using the qnxvar read function.

Here is the problem I cannot overcome: I think I need some AJAX programming techniques to get an individual DIV to refresh automatically instead of refreshing the whole page. I found a lot of examples of that, most of them use JQUERY and/or SetInterval. However, I have found not a single example where the data source is a qnxvar. I do not know how to use the ds server in conjunction with the html to auto refresh data elements on the web page. I realize this is a javascript learning curve for me, and I am in desperate need of some direction. Am I taking the wrong approach entirely? Please assist me or get me pointed in the right direction.

I have html that refreshes a div. I have a cgi script to get the data from the server. See my code below. The refresh simply prints a string with a counter to the div. The initial load of the body correctly calls my cgi function and initially displays the data correctly.

How can I change the code where the counter is being displayed in order to get data from the cgi?

#include <stdlib.h>
#include <stdio.h>
#include <ds.h>
#include <string.h>

#define DATA_MAX_LENGTH 8

int main(int argc, char *argv[]) {
char DataID[7], Data[DATA_MAX_LENGTH];
int lLength = DATA_MAX_LENGTH;

	ds_t Data_Server_Descriptor;

	//Register data server
	Data_Server_Descriptor = ds_register();
	//Handle error
	if (Data_Server_Descriptor == -1)
	{
		perror("Failed to register Web GUI Data Server!");
		return EXIT_FAILURE;;
	}

	strcpy(DataID, "TestDat");


	//Set to global
	ds_get(Data_Server_Descriptor, DataID, Data, lLength);

	/** Print the CGI response header, required for all HTML output. **/
	/** Note the extra \n, to send the blank line.                   **/
	printf("Content-type: text/html\n\n") ;

	/** Print the HTML response page to STDOUT. **/
	printf("<html>\n") ;
	printf("<head><title>CGI Output</title></head>\n") ;
	printf("<body>\n") ;
	printf("<p>The current data is %s.</p>\n", Data) ;
	printf("</body>\n") ;
	printf("</html>\n") ;


	//ds_clear(Data_Server_Descriptor, DataID);
	//ds_deregister(Data_Server_Descriptor);

	return EXIT_SUCCESS;

}

get an individual DIV to refresh automatically instead of refreshing the whole page.
I found a lot of examples of that, most of them use JQUERY and/or SetInterval.
SetInterval() is basic Javascript - jquery is not required.

SetInterval() can be used to periodically update a particular field on the screen (the document) from a Javascript variable. Of course the javascript variable needs to be updated somehow by the server!

Traditionally, Flash (Actionscript) as been used to display pages with realtime data updates - like stock tickers. (Ameritrade’s TradeArchitect is completely Flash-based.) The reason Flash is used is that unlike html, the socket never closes - so the server can “push” asynchronous data to the Flash plugin - and the screen updates whenever the data arrives. No SetInterval() is required - the update is triggered by the server data.

The architects of HTML5 know how important this concept is and introduced WebSocket() to the Javascript language. With WebSocket, the server can “push” to the browser and updates will occur on data arrival - just like in the Flash model. This feature is available in current major browsers - except IE (prior to IE10). A webserver (or module) designed for WebSocket connections is required!

Short of requiring Flash or HTML5, browsers can make an http request from a server - and the server can choose to just “hold” the request until new data is available. (This “long polling” is often related to XMLHttpRequest and Ajax). I can imagine this type of programming ‘may’ work with slinger and CGI. Suppose you request a URL which triggers an external cgi program to run - the program can take as long as it wants to get the data (maybe a specific timeout) - then formats the data as xml and satisfies the request. The arriving XML can trigger the update on the page.

You may find you want/need to modify a webserver for your application. The open source “bozohttpd” server is almost as small as slinger and has the advantage of supporting https (SSL) connections.

I think you need to separate two things. I agree that AJAX type programming is the way to go to just update a field or a few fields on your page. AJAX programming goes on with JavaScript at the client/browser. The user does download this code from your server, but it runs on the client. The AJAX object sends a URL to the server just like you do when you enter a URL at the browser, but that URL does not (usually) respond with an entire page. The data can be just what you need to update the screen. The format is very flexible. You can use XML, or as is also common, json. The AJAX javascript polls the server, gets the update and changes the screen using the DOM interface.

The flip side is the server where you run a CGI script. Script is a bit of a misnomer here. It could be Perl, Python, PHP, but just as useful IMHO is to write a CGI program in ‘C’. There’s a good open source ‘C’ library that will do the dirty work for you. The name escapes me, but if you ask again, I’ll look it up. So, assuming you are writing a ‘C’ cgi-script, you can use the QNX data server directly, read the variable, package it in whatever format you want, and send it back to the AJAX code using stdout.

I’ve done a lot of this type of programming, and I’d be happy to email directly at maschoen@pobox.com to help you out.

Technically Dennis is mostly correct here. I think that Flash is a bit of overkill, and HTML5 may be just a bit premature for the general public, although if your browser supports it, it’s fine. I believe that there is a timeout on an AJAX call, just like there’s a timeout when a browser sends a URL. So instead you poll. That makes the update not event driven which is unfortunate. But then this is a very soft real time system, right? You just have to balance the polling frequency with the applications. 1 second would be fast enough for most users, though it might be too often if you are expecting a high volume of traffic, say 1000 users all polling at once.

Thank you all for your feedback. I managed to get my slinger to work the way I wanted with the ds data server.

In another part of the code I am trying to write some code that loads an xml configuration file from the server and displays it to the user. I have this debugged and working in Visual Studio. But when I put the files on the QNX virtual machine and let slinger serve it up, it’s as if slinger has no idea where to get the xml file from. I put it in the web page root just like I did in VS. So when I call the XMLHttpRequest.open() followed by the send, the file is not found. Is there a path or environment variable that tells slinger a different path for xml files?

var xhttp;
var xmlDoc;
if (window.XMLHttpRequest)
{
xhttp=new XMLHttpRequest();
}
else
{
xhttp=new ActiveXObject(“Microsoft.XMLHTTP”);
}
xhttp.open(“GET”,“SystemParams.xml”,false);
xhttp.send();
xmlDoc=xhttp.responseXML;

I changed my code a little. Here is the listing working on VS, but not on the qnx vm with slinger. I always end up at the alert dialog because the XML is not populated.

<!DOCTYPE html>
<html> 
<head> 
<script src="loadXMLDoc.js"></script>
<script src="jquery.js"></script> 
<script type="text/javascript">
    $(document).ready(function () {
        var xhttp;
        var xmlDoc;
        if (window.XMLHttpRequest) {
            xhttp = new XMLHttpRequest();
        }
        else {
            xhttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
        xhttp.onreadystatechange = function () {
            if (xhttp.readyState == 4 && xhttp.status == 200) {
                xmlDoc = xhttp.responseXML;
                if ("" != xmlDoc.xml) {
                    document.write("<h1 Ethernet port 0 Settings </h1>");
                    document.write("<table border='1'>");
                    document.write("<tr><td>Auto IP:</td><td>");
                    document.write(xmlDoc.getElementsByTagName("Auto_IP")[0].childNodes[0].nodeValue);
                    document.write("</td><tr>");
                    document.write("<tr><td>IPv4 Address:</td><td>");
                    document.write(xmlDoc.getElementsByTagName("IP4_Address")[0].childNodes[0].nodeValue);
                    document.write("</td><tr>");
                    document.write("<tr><td>IPv6 Address:</td><td>");
                    document.write(xmlDoc.getElementsByTagName("IP6_Address")[0].childNodes[0].nodeValue);
                    document.write("</td><tr>");
                    document.write("<tr><td>Subnet Mask:</td><td>");
                    document.write(xmlDoc.getElementsByTagName("Subnet_Mask")[0].childNodes[0].nodeValue);
                    document.write("</td><tr>");
                    document.write("<tr><td>Default gateway:</td><td>");
                    document.write(xmlDoc.getElementsByTagName("Default_Gateway")[0].childNodes[0].nodeValue);
                    document.write("</td><tr>");
                    document.write("<tr><td>Primary DNS:</td><td>");
                    document.write(xmlDoc.getElementsByTagName("Primary_DNS")[0].childNodes[0].nodeValue);
                    document.write("</td><tr>");
                    document.write("<tr><td>Secondary DNS:</td><td>");
                    document.write(xmlDoc.getElementsByTagName("Secondary_DNS")[0].childNodes[0].nodeValue);
                    document.write("</td><tr>");
                    document.write("</table>");
                }
                else {
                    alert("System Configuration Not Found!");
                }
            }
        }
        xhttp.open("GET", "SystemParams.xml?t=" + Math.random(), true);
        xhttp.send();
    });
</script>
</head> 
<body> 	
	
</body> 
</html>

I guess I have to ask. Did you read the slinger documentation? There are a few environment variables that you need to set, eg. HTTPD_SCRIPTALIAS. I don’t recall which one provides the path prefix for you open, but you should start there.