Add streaming ajax page with csv text buffer

This commit is contained in:
David Kopf 2011-11-03 14:58:33 -04:00
parent 76d7238c77
commit 404895ec04
5 changed files with 217 additions and 8 deletions

View file

@ -42,6 +42,7 @@
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "contiki-net.h"
@ -57,6 +58,9 @@
#if RF230BB
#define RADIOSTATS 1
#endif
#if CONTIKI_TARGET_REDBEE_ECONOTAG
#include "adc.h"
#endif
#if WEBSERVER_CONF_CGI
static struct httpd_cgi_call *calls = NULL;
@ -88,6 +92,9 @@ static const char rtes_name[] HTTPD_STRING_ATTR = "routes";
#if WEBSERVER_CONF_TICTACTOE
static const char tictac_name[] HTTPD_STRING_ATTR = "tictac";
#endif
#if WEBSERVER_CONF_AJAX
static const char ajax_name[] HTTPD_STRING_ATTR = "ajaxdata";
#endif
#endif
/*Process states for processes cgi*/
@ -220,12 +227,17 @@ generate_header(void *arg)
#define _MSS8 44
static const char httpd_cgi_headerm6[] HTTPD_STRING_ATTR = "|<a href=\"/ttt/ttt.shtml\">TicTacToe</a>";
numprinted+=httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_headerm6);
#endif
#if WEBSERVER_CONF_AJAX
#define _MSS9 30
static const char httpd_cgi_headerm7[] HTTPD_STRING_ATTR = "|<a href=\"ajax.shtml\">Ajax</a>";
numprinted+=httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_headerm7);
#endif
static const char httpd_cgi_headerme[] HTTPD_STRING_ATTR = "</pre>";
numprinted+=httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_headerme);
#endif /* WEBSERVER_CONF_MENU */
#if UIP_RECEIVE_WINDOW < _MSS1+_MSS2+_MSS3_+MSS4_+MSS5_MSS6+_MSS7+_MSS8
#if UIP_RECEIVE_WINDOW < _MSS1+_MSS2+_MSS3_+MSS4_+MSS5_MSS6+_MSS7+_MSS8+_MSS9
#warning ************************************************************
#warning UIP_RECEIVE_WINDOW not large enough for header cgi output.
#warning Web pages will not render properly!
@ -550,6 +562,23 @@ generate_sensor_readings(void *arg)
ADCSRA|=1<<ADSC; //Start another conversion
while (ADCSRA&(1<<ADSC)); //Wait till done
h=1131632UL/ADC; //Get supply voltage
#endif
#if CONTIKI_TARGET_REDBEE_ECONOTAG
//#include "adc.h"
{
uint8_t c;
adc_reading[8]=0;
adc_init();
while (adc_reading[8]==0) adc_service();
// for (c=0; c<NUM_ADC_CHAN; c++) printf("%u %04u\r\n", c, adc_reading[c]);
adc_disable();
snprintf(sensor_extvoltage, sizeof(sensor_extvoltage),"%u mV",1200*0xfff/adc_reading[8]);
static const char httpd_cgi_sensorv[] HTTPD_STRING_ATTR = "<em>ADC chans :</em> %u %u %u %u %u %u %u %u \n";
numprinted+=httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_sensorv,
adc_reading[0],adc_reading[1],adc_reading[2],adc_reading[3],adc_reading[4],adc_reading[5],adc_reading[6],adc_reading[7]);
}
#endif
numprinted+=httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_sensor2, sensor_extvoltage);
@ -584,6 +613,7 @@ generate_sensor_readings(void *arg)
#if ENERGEST_CONF_ON
{uint8_t p1,p2;
uint32_t sl;
#if 0
/* Update all the timers to get current values */
for (p1=1;p1<ENERGEST_TYPE_MAX;p1++) {
@ -595,20 +625,26 @@ generate_sensor_readings(void *arg)
#else
energest_flush();
#endif
static const char httpd_cgi_sensor4[] HTTPD_STRING_ATTR = "<em>CPU time (ENERGEST):</em> %02u:%02u:%02u (%u.%02u%%)\n";
static const char httpd_cgi_sensor10[] HTTPD_STRING_ATTR = "<em>Radio (ENERGEST):</em> Tx %02u:%02u:%02u (%u.%02u%%) ";
static const char httpd_cgi_sensor11[] HTTPD_STRING_ATTR = "Rx %02u:%02u:%02u (%u.%02u%%)\n";
s=energest_total_time[ENERGEST_TYPE_TRANSMIT].current/RTIMER_ARCH_SECOND;
h=((10000UL*energest_total_time[ENERGEST_TYPE_TRANSMIT].current)/RTIMER_ARCH_SECOND)/seconds;
p1=h/100;p2=h-p1*100;h=s/3600;s=s-h*3600;m=s/60;s=s-m*60;
sl=energest_total_time[ENERGEST_TYPE_CPU].current/RTIMER_ARCH_SECOND;
h=(10000UL*sl)/seconds;p1=h/100;p2=h-p1*100;h=sl/3600;s=sl-h*3600;m=s/60;s=s-m*60;
numprinted+=httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_sensor4, h,m,s,p1,p2);
if (*(char *)(uip_appdata + numprinted-4)==0) {numprinted-=4;}
else if (*(char *)(uip_appdata + numprinted-3)==0) {numprinted-=3;}
else if (*(char *)(uip_appdata + numprinted-2)==0) {numprinted-=2;}
else if (*(char *)(uip_appdata + numprinted-1)==0) {numprinted-=1;}
sl=energest_total_time[ENERGEST_TYPE_TRANSMIT].current/RTIMER_ARCH_SECOND;
h=(10000UL*sl)/seconds;p1=h/100;p2=h-p1*100;h=sl/3600;s=sl-h*3600;m=s/60;s=s-m*60;
numprinted+=httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_sensor10, h,m,s,p1,p2);
if (*(char *)(uip_appdata + numprinted-4)==0) {numprinted-=4;}
else if (*(char *)(uip_appdata + numprinted-3)==0) {numprinted-=3;}
else if (*(char *)(uip_appdata + numprinted-2)==0) {numprinted-=2;}
else if (*(char *)(uip_appdata + numprinted-1)==0) {numprinted-=1;}
s=energest_total_time[ENERGEST_TYPE_LISTEN].current/RTIMER_ARCH_SECOND;
h=((10000UL*energest_total_time[ENERGEST_TYPE_LISTEN].current)/RTIMER_ARCH_SECOND)/seconds;
p1=h/100;p2=h-p1*100;h=s/3600;s=s-h*3600;m=s/60;s=s-m*60;
sl=energest_total_time[ENERGEST_TYPE_LISTEN].current/RTIMER_ARCH_SECOND;
h=(10000UL*sl)/seconds;p1=h/100;p2=h-p1*100;h=sl/3600;s=sl-h*3600;m=s/60;s=s-m*60;
numprinted+=httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_sensor11, h,m,s,p1,p2);
if (*(char *)(uip_appdata + numprinted-4)==0) {numprinted-=4;}
else if (*(char *)(uip_appdata + numprinted-3)==0) {numprinted-=3;}
@ -847,6 +883,121 @@ PT_THREAD(tictactoe(struct httpd_state *s, char *ptr))
}
#endif /* WEBSERVER_CONF_TICTACTOE */
#if WEBSERVER_CONF_AJAX
/*---------------------------------------------------------------------------*/
static
PT_THREAD(ajax_call(struct httpd_state *s, char *ptr))
{
static struct timer t;
static int iter;
static char buf[128];
static uint8_t numprinted;
PSOCK_BEGIN(&s->sout);
/*TODO:pick up time from ? parameter */
timer_set(&t, 1*CLOCK_SECOND);
iter = 0;
while(1) {
#if CONTIKI_TARGET_SKY
SENSORS_ACTIVATE(sht11_sensor);
SENSORS_ACTIVATE(light_sensor);
numprinted = snprintf(buf, sizeof(buf),
"t(%d);h(%d);l1(%d);l2(%d);",
sht11_sensor.value(SHT11_SENSOR_TEMP),
sht11_sensor.value(SHT11_SENSOR_HUMIDITY),
light_sensor.value(LIGHT_SENSOR_PHOTOSYNTHETIC),
light_sensor.value(LIGHT_SENSOR_TOTAL_SOLAR));
SENSORS_DEACTIVATE(sht11_sensor);
SENSORS_DEACTIVATE(light_sensor);
#elif CONTIKI_TARGET_MB851
SENSORS_ACTIVATE(acc_sensor);
numprinted = snprintf(buf, sizeof(buf),"t(%d);ax(%d);ay(%d);az(%d);",
temperature_sensor.value(0),
acc_sensor.value(ACC_X_AXIS),
acc_sensor.value(ACC_Y_AXIS),
acc_sensor.value(ACC_Z_AXIS));
SENSORS_DEACTIVATE(acc_sensor);
#elif CONTIKI_TARGET_REDBEE_ECONOTAG
{
//#include "adc.h"
uint8_t c;
adc_reading[8]=0;
adc_init();
while (adc_reading[8]==0) adc_service();
adc_disable();
numprinted = snprintf(buf, sizeof(buf),"b(%u);adc(%u,%u,%u,%u,%u,%u,%u,%u);",
1200*0xfff/adc_reading[8],adc_reading[0],adc_reading[1],adc_reading[2],adc_reading[3],adc_reading[4],adc_reading[5],adc_reading[6],adc_reading[7]);
}
#elif CONTIKI_TARGET_MINIMAL_NET
static uint16_t c0=0x3ff,c1=0x3ff,c2=0x3ff,c3=0x3ff,c4=0x3ff,c5=0x3ff,c6=0x3ff,c7=0x3ff;
numprinted = snprintf(buf, sizeof(buf), "t(%d);b(%u);v(%u);",273+(rand()&0x3f),3300-iter/10,iter);
numprinted += snprintf(buf+numprinted, sizeof(buf)-numprinted,"adc(%u,%u,%u,%u,%u,%u,%u,%u);",c0,c1,c2,c3,c4,c5,c6,c7);
c0+=(rand()&0xf)-8;
c1+=(rand()&0xf)-8;
c2+=(rand()&0xf)-7;
c3+=(rand()&0x1f)-15;
c4+=(rand()&0x3)-1;
c5+=(rand()&0xf)-8;
c6+=(rand()&0xf)-8;
c7+=(rand()&0xf)-8;
#else
numprinted = snprintf(buf, sizeof(buf), "v(%u);",iter);
#endif
#if CONTIKIMAC_CONF_COMPOWER
#include "sys/compower.h"
{
//sl=compower_idle_activity.transmit/RTIMER_ARCH_SECOND;
//sl=compower_idle_activity.listen/RTIMER_ARCH_SECOND;
}
#endif
#if RIMESTATS_CONF_ON
#include "net/rime/rimestats.h"
numprinted += snprintf(buf+numprinted, sizeof(buf)-numprinted,"rime(%lu,%lu,%lu,%lu);",
rimestats.tx,rimestats.rx,rimestats.lltx-rimestats.tx,rimestats.llrx-rimestats.rx);
#endif
#if ENERGEST_CONF_ON
{
#if 1
static unsigned long last_cpu, last_lpm, last_listen, last_transmit;
energest_flush();
numprinted += snprintf(buf+numprinted, sizeof(buf)-numprinted,
"p(%lu,%lu,%lu,%lu);",
energest_type_time(ENERGEST_TYPE_CPU) - last_cpu,
energest_type_time(ENERGEST_TYPE_LPM) - last_lpm,
energest_type_time(ENERGEST_TYPE_TRANSMIT) - last_transmit,
energest_type_time(ENERGEST_TYPE_LISTEN) - last_listen);
last_cpu = energest_type_time(ENERGEST_TYPE_CPU);
last_lpm = energest_type_time(ENERGEST_TYPE_LPM);
last_transmit = energest_type_time(ENERGEST_TYPE_TRANSMIT);
last_listen = energest_type_time(ENERGEST_TYPE_LISTEN);
#endif
#if 1
uint16_t cpp,txp,rxp;
energest_flush();
cpp=((10000UL*energest_type_time(ENERGEST_TYPE_CPU))/RTIMER_ARCH_SECOND)/clock_seconds();
txp=((10000UL*energest_type_time(ENERGEST_TYPE_TRANSMIT))/RTIMER_ARCH_SECOND)/clock_seconds();
rxp=((10000UL*energest_type_time(ENERGEST_TYPE_LISTEN))/RTIMER_ARCH_SECOND)/clock_seconds();
numprinted += snprintf(buf+numprinted, sizeof(buf)-numprinted,"ener(%u,%u,%u);",cpp,txp,rxp);
#endif
}
#endif /* ENERGEST_CONF_ON */
PSOCK_SEND_STR(&s->sout, buf);
timer_restart(&t);
PSOCK_WAIT_UNTIL(&s->sout, timer_expired(&t));
iter++;
}
PSOCK_END(&s->sout);
}
#endif /* WEBSERVER_CONF_AJAX */
/*---------------------------------------------------------------------------*/
void
httpd_cgi_add(struct httpd_cgi_call *c)
@ -889,6 +1040,9 @@ HTTPD_CGI_CALL(sensors, sensor_name, sensor_readings);
#if WEBSERVER_CONF_TICTACTOE
HTTPD_CGI_CALL( tictac, tictac_name, tictactoe );
#endif
#if WEBSERVER_CONF_AJAX
HTTPD_CGI_CALL( ajax, ajax_name, ajax_call );
#endif
void
httpd_cgi_init(void)
@ -920,6 +1074,9 @@ httpd_cgi_init(void)
#if WEBSERVER_CONF_TICTACTOE
httpd_cgi_add( &tictac);
#endif
#if WEBSERVER_CONF_AJAX
httpd_cgi_add( &ajax);
#endif
}
#endif /* WEBSERVER_CONF_CGI */

View file

@ -0,0 +1,38 @@
<script>function lo(){li();}window.onload=lo;</script>
<script type="text/javascript">
var sts;
function li(){ls();}
function ls() {
var r;try{r=new XMLHttpRequest();}catch(e) {alert("Your browser does not support AJAX!");return false;}
r.open("GET", "/ajaxdata.shtml", true);//r.setRequestHeader("If-Modified-Since","Sat, 1 Jan 2000 00:00:00 GMT");
var lx=0;sts=new Date();r.onreadystatechange=function() {
if(r.readyState>0) {var img=document.getElementById("date");img.innerHTML=(new Date()).toTimeString();var lr=r.responseText.substr(lx);lx+=lr.length;eval(lr);}
if (ls.stop) r.abort();
}
r.send(null);
}
function e(el){d=document;if(d.getElementById){return d.getElementById(el);}else if (d.all){return d.all[el];}}
function s(el,n,max,text){e(el).innerHTML = '<table width=504 border=0 cellpadding=1 cellspacing=0>'+'<tr><td width=200>'+text+'</td>'+'<td width='+(10+300*n/max)+' bgcolor="gray">&nbsp;</td>'+'<td width='+(310-300*n/max)+' bgcolor="lightgray">&nbsp;</td>'+'</table>';}
function dc(n,d){return n.toFixed(d);}
function t(m){n=dc(m/10,1);s('temp',n,50,'Temperature '+n+' &deg;C');}
function b(m){s('batt',m,5000,'Battery '+dc(m/1000,3)+' volts');}
function ax(m){s('ax',m+2000,4000,'Acceleration (X-axis) '+m+'mg');}
function ay(m){s('ay',m+2000,4000,'Acceleration (Y-axis) '+m+'mg');}
function az(m){s('az',m+2000,4000,'Acceleration (Z-axis) '+m+'mg');}
function rs(m){s('rs',n,100,'RSSI '+n);}
function p(c,l,t,r){
tm=c+1;cp=c*18/tm;lt=t*50.4/tm;lr=r*45.6/tm;n=cp+lt+lr;
s('p',n,100,'Power consumption '+dc(n,2)+' mW');
s('pc',cp,100,'CPU power '+dc(cp,2)+' mW');
s('pr',lr,100,'Radio RX power '+dc(lr,2)+' mW');
s('pt',lt,100,'Radio TX power '+dc(lt,2)+' mW');
}
function adc(a0,a1,a2,a3,a4,a5,a6,a7){
var el=e('csv'),sv=el.scrollTop;
el.innerHTML+=dc(((new Date()).getTime()-sts.getTime())/1000,1)+','+a0+','+a1+','+a2+','+a3+','+a4+','+a5+','+a6+','+a7+'\r';
if((sv+el.clientHeight+30)<el.scrollHeight)el.scrollTop=sv;else el.scrollTop=sv+42;
}
function rime(tx,rx,tl,rl){e('rims').innerHTML='<em>RIMESTATS:</em> Tx= '+tx+' Rx= '+rx+' TxL= '+tl+' RxL= '+rl;}
function ener(cp,tx,rx) {e('ener').innerHTML='<em>ENERGEST :</em> CPU= '+dc(cp/100,2)+'% Tx= '+dc(tx/100,2)+'% Rx= '+dc(rx/100,2)+'%';}
function v(n){e('v').innerHTML='Iterations = '+n;}
</script>

View file

@ -0,0 +1,11 @@
%! header
%!: /ajax.js
<input type="button" value="RUN" onclick="ls.stop=false; ls();"><input type="button" value="STOP" onclick="ls.stop=true;"><br><span id="date"></span>
<div id="v"></div>
<pre><span id="rims"></span><div id="ener"></div></pre>
<h2>Sensors</h2>
<div id="temp"></div><div id="batt"></div>
<div id="ax"></div><div id="ay"></div><div id="az"></div>
<div id="p"></div><div id="pc"></div><div id="pr"></div><div id="pt"></div>
<br><textarea id="csv" class="example-code" READONLY style="height:150px;width:500px;overflow:auto;onclick="this.focus();"></textarea>
%! file-stats .

View file

@ -0,0 +1 @@
%! ajaxdata

View file

@ -81,6 +81,7 @@
#define WEBSERVER_CONF_ROUTES 1
#define WEBSERVER_CONF_SENSORS 0
#define WEBSERVER_CONF_TICTACTOE 0 //Needs passquery of at least 10 chars
#define WEBSERVER_CONF_AJAX 0
//#define WEBSERVER_CONF_PASSQUERY 10
#if WEBSERVER_CONF_PASSQUERY
extern char httpd_query[WEBSERVER_CONF_PASSQUERY];
@ -126,6 +127,7 @@ extern char httpd_query[WEBSERVER_CONF_PASSQUERY];
#define WEBSERVER_CONF_ROUTES 1
#define WEBSERVER_CONF_SENSORS 1
#define WEBSERVER_CONF_TICTACTOE 1 //Needs passquery of at least 10 chars
#define WEBSERVER_CONF_AJAX 1
#define WEBSERVER_CONF_PASSQUERY 10
#if WEBSERVER_CONF_PASSQUERY
extern char httpd_query[WEBSERVER_CONF_PASSQUERY];