Contiki 2.6

httpd-cgi.c

00001 /*
00002  * Copyright (c) 2001, Adam Dunkels.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. The name of the author may not be used to endorse or promote
00014  *    products derived from this software without specific prior
00015  *    written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
00018  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00019  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00021  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00023  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00025  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00026  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00027  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028  *
00029  * This file is part of the uIP TCP/IP stack.
00030  *
00031  * $Id: httpd-cgi.c,v 1.13 2010/12/23 19:41:07 dak664 Exp $
00032  *
00033  */
00034 #include <util/delay.h>
00035 #define delay_us( us )   ( _delay_us( ( us ) ) )
00036 /*
00037  * This file includes functions that are called by the web server
00038  * scripts. The functions takes no argument, and the return value is
00039  * interpreted as follows. A zero means that the function did not
00040  * complete and should be invoked for the next packet as well. A
00041  * non-zero value indicates that the function has completed and that
00042  * the web server should move along to the next script line.
00043  *
00044  */ 
00045 
00046 #include <stdio.h>
00047 #include <string.h>
00048 
00049 #include "contiki-net.h"
00050 #include "httpd.h"
00051 #include "httpd-cgi.h"
00052 #include "httpd-fs.h"
00053 #include "httpd-fsdata.h"
00054 #include "lib/petsciiconv.h"
00055 
00056 #include "sensors.h"
00057 
00058 #define DEBUGLOGIC 0        //See httpd.c, if 1 must also set it there!
00059 #if DEBUGLOGIC
00060 #define uip_mss(...) 512
00061 #define uip_appdata TCPBUF
00062 extern char TCPBUF[512];
00063 #endif
00064 
00065 /* RADIOSTATS must also be set in clock.c and the radio driver */
00066 #if RF230BB
00067 #define RADIOSTATS 1
00068 #endif
00069 
00070 static struct httpd_cgi_call *calls = NULL;
00071 
00072 /*cgi function names*/
00073 #if HTTPD_FS_STATISTICS
00074 static const char   file_name[] HTTPD_STRING_ATTR = "file-stats";
00075 #endif
00076 static const char    tcp_name[] HTTPD_STRING_ATTR = "tcp-connections";
00077 static const char   proc_name[] HTTPD_STRING_ATTR = "processes";
00078 static const char sensor_name[] HTTPD_STRING_ATTR = "sensors";
00079 static const char   adrs_name[] HTTPD_STRING_ATTR = "addresses";
00080 static const char   nbrs_name[] HTTPD_STRING_ATTR = "neighbors";
00081 static const char   rtes_name[] HTTPD_STRING_ATTR = "routes";
00082 
00083 /*Process states for processes cgi*/
00084 static const char      closed[] HTTPD_STRING_ATTR = "CLOSED";
00085 static const char    syn_rcvd[] HTTPD_STRING_ATTR = "SYN-RCVD";
00086 static const char    syn_sent[] HTTPD_STRING_ATTR = "SYN-SENT";
00087 static const char established[] HTTPD_STRING_ATTR = "ESTABLISHED";
00088 static const char  fin_wait_1[] HTTPD_STRING_ATTR = "FIN-WAIT-1";
00089 static const char  fin_wait_2[] HTTPD_STRING_ATTR = "FIN-WAIT-2";
00090 static const char     closing[] HTTPD_STRING_ATTR = "CLOSING";
00091 static const char   time_wait[] HTTPD_STRING_ATTR = "TIME-WAIT";
00092 static const char    last_ack[] HTTPD_STRING_ATTR = "LAST-ACK";
00093 static const char        none[] HTTPD_STRING_ATTR = "NONE";
00094 static const char     running[] HTTPD_STRING_ATTR = "RUNNING";
00095 static const char      called[] HTTPD_STRING_ATTR = "CALLED";
00096 static const char *states[] = {
00097   closed,
00098   syn_rcvd,
00099   syn_sent,
00100   established,
00101   fin_wait_1,
00102   fin_wait_2,
00103   closing,
00104   time_wait,
00105   last_ack,
00106   none,
00107   running,
00108   called};
00109 
00110   static char sensor_temperature[12]="Not Enabled";
00111   static char sensor_extvoltage[12]="Not Enabled";
00112 //  static unsigned long last_tempupdate,last_extvoltageupdate;
00113   extern unsigned long seconds, sleepseconds;
00114 #if RADIOSTATS
00115   extern unsigned long radioontime;
00116   static unsigned long savedradioontime;
00117   extern uint8_t RF230_radio_on, rf230_last_rssi;
00118   extern uint16_t RF230_sendpackets,RF230_receivepackets,RF230_sendfail,RF230_receivefail;
00119 #endif
00120   
00121 #if 0
00122 void
00123 web_set_temp(char *s)
00124 {
00125   strcpy(sensor_temperature, s);
00126   last_tempupdate=seconds;
00127 }
00128 void
00129 web_set_voltage(char *s)
00130 {
00131   strcpy(sensor_extvoltage, s);
00132   last_extvoltageupdate=seconds;
00133 }
00134 #endif
00135 /*---------------------------------------------------------------------------*/
00136 static
00137 PT_THREAD(nullfunction(struct httpd_state *s, char *ptr))
00138 {
00139   PSOCK_BEGIN(&s->sout);
00140   PSOCK_END(&s->sout);
00141 }
00142 /*---------------------------------------------------------------------------*/
00143 httpd_cgifunction
00144 httpd_cgi(char *name)
00145 {
00146   struct httpd_cgi_call *f;
00147 
00148   /* Find the matching name in the table, return the function. */
00149   for(f = calls; f != NULL; f = f->next) {
00150     if(httpd_strncmp(name, f->name, httpd_strlen(f->name)) == 0) {
00151       return f->function;
00152     }
00153   }
00154   return nullfunction;
00155 }
00156 
00157 #if HTTPD_FS_STATISTICS
00158 static char *thisfilename;
00159 /*---------------------------------------------------------------------------*/
00160 static unsigned short
00161 generate_file_stats(void *arg)
00162 {
00163   static const char httpd_cgi_filestat1[] HTTPD_STRING_ATTR = "<p class=right><br><br><i>This page has been sent %u times</i></div></body></html>";
00164   static const char httpd_cgi_filestat2[] HTTPD_STRING_ATTR = "<tr><td><a href=\"%s\">%s</a></td><td>%d</td>";
00165   static const char httpd_cgi_filestat3[] HTTPD_STRING_ATTR = "%5u";
00166   char tmp[20];
00167   struct httpd_fsdata_file_noconst *f,fram;
00168   uint16_t i;
00169   unsigned short numprinted;
00170 
00171   /* Transfer arg from whichever flash that contains the html file to RAM */
00172   httpd_fs_cpy(&tmp, (char *)arg, 20);
00173 
00174   /* Count for this page, with common page footer */
00175   if (tmp[0]=='.') {
00176     numprinted=httpd_snprintf((char *)uip_appdata, uip_mss(), httpd_cgi_filestat1, httpd_fs_open(thisfilename, 0));
00177 
00178   /* Count for all files */
00179   /* Note buffer will overflow if there are too many files! */
00180   } else if (tmp[0]=='*') {
00181     i=0;numprinted=0;
00182     for(f = (struct httpd_fsdata_file_noconst *)httpd_fs_get_root();
00183         f != NULL;
00184         f = (struct httpd_fsdata_file_noconst *)fram.next) {
00185 
00186       /* Get the linked list file entry into RAM from from wherever it is*/
00187       httpd_memcpy(&fram,f,sizeof(fram));
00188  
00189       /* Get the file name from whatever memory it is in */
00190       httpd_fs_cpy(&tmp, fram.name, sizeof(tmp));
00191 #if HTTPD_FS_STATISTICS==1
00192       numprinted+=httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_filestat2, tmp, tmp, f->count);
00193 #elif HTTPD_FS_STATISTICS==2
00194       numprinted+=httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_filestat2, tmp, tmp, httpd_filecount[i]);
00195 #endif
00196       i++;
00197     }
00198 
00199   /* Count for specified file */
00200   } else {
00201     numprinted=httpd_snprintf((char *)uip_appdata, uip_mss(), httpd_cgi_filestat3, httpd_fs_open(tmp, 0));
00202   }
00203 #if DEBUGLOGIC
00204   return 0;
00205 #endif
00206   return numprinted;
00207 }
00208 /*---------------------------------------------------------------------------*/
00209 static
00210 PT_THREAD(file_stats(struct httpd_state *s, char *ptr))
00211 {
00212 
00213   PSOCK_BEGIN(&s->sout);
00214 
00215   thisfilename=&s->filename[0]; //temporary way to pass filename to generate_file_stats
00216   
00217   PSOCK_GENERATOR_SEND(&s->sout, generate_file_stats, (void *) ptr);
00218   
00219   PSOCK_END(&s->sout);
00220 }
00221 #endif /*HTTPD_FS_STATISTICS*/
00222 /*---------------------------------------------------------------------------*/
00223 static unsigned short
00224 make_tcp_stats(void *arg)
00225 {
00226   static const char httpd_cgi_tcpstat1[] HTTPD_STRING_ATTR = "<tr align=\"center\"><td>%d</td><td>";
00227   static const char httpd_cgi_tcpstat2[] HTTPD_STRING_ATTR = "-%u</td><td>%s</td><td>%u</td><td>%u</td><td>%c %c</td></tr>\r\n";
00228   struct uip_conn *conn;
00229   struct httpd_state *s = (struct httpd_state *)arg;
00230   char tstate[20];
00231   uint16_t numprinted;
00232 
00233   conn = &uip_conns[s->u.count];
00234 
00235   numprinted = httpd_snprintf((char *)uip_appdata, uip_mss(), httpd_cgi_tcpstat1, uip_htons(conn->lport));
00236   numprinted += httpd_cgi_sprint_ip6(conn->ripaddr, uip_appdata + numprinted);
00237   httpd_strcpy(tstate,states[conn->tcpstateflags & UIP_TS_MASK]);
00238   numprinted +=  httpd_snprintf((char *)uip_appdata + numprinted, uip_mss() - numprinted,
00239                  httpd_cgi_tcpstat2,
00240                  uip_htons(conn->rport),
00241                  tstate,
00242                  conn->nrtx,
00243                  conn->timer,
00244                  (uip_outstanding(conn))? '*':' ',
00245                  (uip_stopped(conn))? '!':' ');
00246 
00247   return numprinted;
00248 }
00249 /*---------------------------------------------------------------------------*/
00250 static
00251 PT_THREAD(tcp_stats(struct httpd_state *s, char *ptr))
00252 {
00253   
00254   PSOCK_BEGIN(&s->sout);
00255 
00256   for(s->u.count = 0; s->u.count < UIP_CONNS; ++s->u.count) {
00257     if((uip_conns[s->u.count].tcpstateflags & UIP_TS_MASK) != UIP_CLOSED) {
00258       PSOCK_GENERATOR_SEND(&s->sout, make_tcp_stats, s);
00259     }
00260   }
00261 
00262   PSOCK_END(&s->sout);
00263 }
00264 /*---------------------------------------------------------------------------*/
00265 static unsigned short
00266 make_processes(void *p)
00267 {
00268   static const char httpd_cgi_proc[] HTTPD_STRING_ATTR = "<tr align=\"center\"><td>%p</td><td>%s</td><td>%p</td><td>%s</td></tr>\r\n";
00269   char name[40],tstate[20];
00270 
00271   strncpy(name, PROCESS_NAME_STRING((struct process *)p), 40);
00272   petsciiconv_toascii(name, 40);
00273   httpd_strcpy(tstate,states[9 + ((struct process *)p)->state]);
00274   return httpd_snprintf((char *)uip_appdata, uip_mss(), httpd_cgi_proc, p, name,
00275     *(char *)(&(((struct process *)p)->thread)),
00276 
00277     tstate);
00278 }
00279 /*---------------------------------------------------------------------------*/
00280 static
00281 PT_THREAD(processes(struct httpd_state *s, char *ptr))
00282 {
00283   PSOCK_BEGIN(&s->sout);
00284   for(s->u.ptr = PROCESS_LIST(); s->u.ptr != NULL; s->u.ptr = ((struct process *)s->u.ptr)->next) {
00285     PSOCK_GENERATOR_SEND(&s->sout, make_processes, s->u.ptr);
00286   }
00287   PSOCK_END(&s->sout);
00288 }
00289 /*---------------------------------------------------------------------------*/
00290 static const char httpd_cgi_addrh[] HTTPD_STRING_ATTR = "<code>";
00291 static const char httpd_cgi_addrf[] HTTPD_STRING_ATTR = "</code>[Room for %u more]";
00292 static const char httpd_cgi_addrb[] HTTPD_STRING_ATTR = "<br>";
00293 static const char httpd_cgi_addrn[] HTTPD_STRING_ATTR = "(none)<br>";
00294 extern uip_ds6_nbr_t uip_ds6_nbr_cache[];
00295 extern uip_ds6_route_t uip_ds6_routing_table[];
00296 extern uip_ds6_netif_t uip_ds6_if;
00297 
00298 static unsigned short
00299 make_addresses(void *p)
00300 {
00301 uint8_t i,j=0;
00302 uint16_t numprinted;
00303   numprinted = httpd_snprintf((char *)uip_appdata, uip_mss(),httpd_cgi_addrh);
00304   for (i=0; i<UIP_DS6_ADDR_NB;i++) {
00305     if (uip_ds6_if.addr_list[i].isused) {
00306       j++;
00307       numprinted += httpd_cgi_sprint_ip6(uip_ds6_if.addr_list[i].ipaddr, uip_appdata + numprinted);
00308       numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrb); 
00309     }
00310   }
00311 //if (j==0) numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrn);
00312   numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrf, UIP_DS6_ADDR_NB-j); 
00313   return numprinted;
00314 }
00315 /*---------------------------------------------------------------------------*/
00316 static
00317 PT_THREAD(addresses(struct httpd_state *s, char *ptr))
00318 {
00319   PSOCK_BEGIN(&s->sout);
00320 
00321   PSOCK_GENERATOR_SEND(&s->sout, make_addresses, s->u.ptr);
00322 
00323   PSOCK_END(&s->sout);
00324 }
00325 /*---------------------------------------------------------------------------*/ 
00326 static unsigned short
00327 make_neighbors(void *p)
00328 {
00329 uint8_t i,j=0;
00330 uint16_t numprinted;
00331   numprinted = httpd_snprintf((char *)uip_appdata, uip_mss(),httpd_cgi_addrh);
00332   for (i=0; i<UIP_DS6_NBR_NB;i++) {
00333     if (uip_ds6_nbr_cache[i].isused) {
00334       j++;
00335       numprinted += httpd_cgi_sprint_ip6(uip_ds6_nbr_cache[i].ipaddr, uip_appdata + numprinted);
00336       numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrb); 
00337     }
00338   }
00339 //if (j==0) numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrn);
00340   numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrf,UIP_DS6_NBR_NB-j);
00341   return numprinted;
00342 }
00343 /*---------------------------------------------------------------------------*/
00344 static
00345 PT_THREAD(neighbors(struct httpd_state *s, char *ptr))
00346 {
00347   PSOCK_BEGIN(&s->sout);
00348 
00349   PSOCK_GENERATOR_SEND(&s->sout, make_neighbors, s->u.ptr);  
00350   
00351   PSOCK_END(&s->sout);
00352 }
00353 /*---------------------------------------------------------------------------*/                 
00354 static unsigned short
00355 make_routes(void *p)
00356 {
00357 static const char httpd_cgi_rtes1[] HTTPD_STRING_ATTR = "(%u (via ";
00358 static const char httpd_cgi_rtes2[] HTTPD_STRING_ATTR = ") %lus<br>";
00359 static const char httpd_cgi_rtes3[] HTTPD_STRING_ATTR = ")<br>";
00360 uint8_t i,j=0;
00361 uint16_t numprinted;
00362   numprinted = httpd_snprintf((char *)uip_appdata, uip_mss(),httpd_cgi_addrh);
00363   for (i=0; i<UIP_DS6_ROUTE_NB;i++) {
00364     if (uip_ds6_routing_table[i].isused) {
00365       j++;
00366       numprinted += httpd_cgi_sprint_ip6(uip_ds6_routing_table[i].ipaddr, uip_appdata + numprinted);
00367       numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_rtes1, uip_ds6_routing_table[i].length);
00368       numprinted += httpd_cgi_sprint_ip6(uip_ds6_routing_table[i].nexthop, uip_appdata + numprinted);
00369       if(uip_ds6_routing_table[i].state.lifetime < 3600) {
00370          numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_rtes2, uip_ds6_routing_table[i].state.lifetime);
00371       } else {
00372          numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_rtes3);
00373       }
00374     }
00375   }
00376   if (j==0) numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrn);
00377   numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrf,UIP_DS6_ROUTE_NB-j);
00378   return numprinted;
00379 }
00380 /*---------------------------------------------------------------------------*/
00381 static
00382 PT_THREAD(routes(struct httpd_state *s, char *ptr))
00383 {
00384   PSOCK_BEGIN(&s->sout);
00385  
00386   PSOCK_GENERATOR_SEND(&s->sout, make_routes, s->u.ptr); 
00387  
00388   PSOCK_END(&s->sout);
00389 }
00390 /*---------------------------------------------------------------------------*/
00391 static unsigned short
00392 generate_sensor_readings(void *arg)
00393 {
00394   uint16_t numprinted;
00395   uint16_t h,m,s;
00396   uint8_t p1;
00397 //  static const char httpd_cgi_sensor0[] HTTPD_STRING_ATTR = "[Updated %d seconds ago]<br><br>";
00398 //  static const char httpd_cgi_sensor1[] HTTPD_STRING_ATTR = "<em>Temperature:</em> %s<br>";
00399 //  static const char httpd_cgi_sensor2[] HTTPD_STRING_ATTR = "<em>Battery:</em> %s<br>";
00400   static const char httpd_cgi_sensor1_printf[] HTTPD_STRING_ATTR = "%d.%d C";
00401   static const char httpd_cgi_sensor2_printf[] HTTPD_STRING_ATTR = "%d mv";
00402   static const char httpd_cgi_sensr12[] HTTPD_STRING_ATTR = "<em>Temperature:</em> %s    <em>Battery:<em> %s<br>";
00403   static const char httpd_cgi_sensor3[] HTTPD_STRING_ATTR = "<em>Elapsed timer :</em> %02d:%02d:%02d<br>";
00404   static const char httpd_cgi_sensor4[] HTTPD_STRING_ATTR = "<em>Sleeping time :</em> %02d:%02d:%02d (%d%%)<br>";
00405   
00406   numprinted=0;
00407 //  if (last_tempupdate) {
00408 //    numprinted =httpd_snprintf((char *)uip_appdata, uip_mss(), httpd_cgi_sensor0,seconds-last_tempupdate);
00409 //  }
00410      BATMON = 16; //give BATMON time to stabilize at highest range and lowest voltage
00411 /* Measure internal temperature sensor, see atmega128rfa1 datasheet */
00412 /* This code disabled by default for safety. Selecting an internal reference will short it to
00413    anything connected to the AREF pin!
00414   */
00415 #if 1
00416   ADCSRB|=1<<MUX5;          //this bit buffered till ADMUX written to!
00417   ADMUX =0xc9;              // Select internal 1.6 volt ref, temperature sensor ADC channel
00418   ADCSRA=0x85;              //Enable ADC, not free running, interrupt disabled, clock divider 32 (250 KHz@ 8 MHz)
00419 //  while ((ADCSRB&(1<<AVDDOK))==0);  //wait for AVDD ok
00420 //  while ((ADCSRB&(1<<REFOK))==0);  //wait for ref ok 
00421   ADCSRA|=1<<ADSC;          //Start throwaway conversion
00422   while (ADCSRA&(1<<ADSC)); //Wait till done
00423   ADCSRA|=1<<ADSC;          //Start another conversion
00424   while (ADCSRA&(1<<ADSC)); //Wait till done
00425   h=ADC;                    //Read adc
00426   h=11*h-2728+(h>>2);       //Convert to celcius*10 (should be 11.3*h, approximate with 11.25*h)
00427   ADCSRA=0;                 //disable ADC
00428   ADMUX=0;                  //turn off internal vref      
00429   m=h/10;s=h-10*m;
00430   httpd_snprintf(sensor_temperature,sizeof(sensor_temperature),httpd_cgi_sensor1_printf,m,s);
00431 #endif
00432 
00433 /* Bandgap can't be measured against supply voltage in this chip. */
00434 /* Use BATMON register instead */
00435   for ( p1=16; p1<31; p1++) {
00436     BATMON = p1;
00437  // delay_us(100); //delay needed?
00438     if ((BATMON&(1<<BATMON_OK))==0) break;
00439   }
00440   h=2550-75*16-75+75*p1; //-75 to take the floor of the 75 mv transition window
00441   httpd_snprintf(sensor_extvoltage,sizeof(sensor_extvoltage),httpd_cgi_sensor2_printf,h);
00442 
00443   numprinted+=httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_sensr12, sensor_temperature,sensor_extvoltage);
00444 
00445  // numprinted+=httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_sensor2, sensor_extvoltage);
00446 #if RADIOSTATS
00447   /* Remember radioontime for display below - slow connection might make it report longer than cpu ontime! */
00448   savedradioontime = radioontime;
00449 #endif
00450   h=seconds/3600;
00451   s=seconds-h*3600;
00452   m=s/60;
00453   s=s-m*60;
00454   numprinted+=httpd_snprintf((char *)uip_appdata + numprinted, uip_mss() - numprinted, httpd_cgi_sensor3, h,m,s);
00455   if (sleepseconds) {
00456     p1=100UL*sleepseconds/seconds;
00457     h=sleepseconds/3600;
00458     s=sleepseconds-h*3600;
00459     m=s/60;
00460     s=s-m*60;
00461     numprinted+=httpd_snprintf((char *)uip_appdata + numprinted, uip_mss() - numprinted, httpd_cgi_sensor4, h,m,s,p1);
00462   }
00463   return numprinted;
00464 }
00465 #if RADIOSTATS
00466 /*---------------------------------------------------------------------------*/
00467 static unsigned short
00468 generate_radio_stats(void *arg)
00469 {
00470   uint16_t numprinted;
00471   uint16_t h,m,s;
00472   uint8_t p1,p2;
00473   static const char httpd_cgi_sensor10[] HTTPD_STRING_ATTR = "<em>Radio on time  :</em> %02d:%02d:%02d (%d.%02d%%)<br>";
00474   static const char httpd_cgi_sensor11[] HTTPD_STRING_ATTR = "<em>Packets:</em> Tx=%5d Rx=%5d TxL=%5d RxL=%5d RSSI=%2ddBm\n";
00475 
00476   s=(10000UL*savedradioontime)/seconds;
00477   p1=s/100;
00478   p2=s-p1*100;
00479   h=savedradioontime/3600;
00480   s=savedradioontime-h*3600;
00481   m=s/60;
00482   s=s-m*60;
00483 
00484   numprinted =httpd_snprintf((char *)uip_appdata             , uip_mss()             , httpd_cgi_sensor10,\
00485     h,m,s,p1,p2);
00486 
00487 #if RF230BB
00488   numprinted+=httpd_snprintf((char *)uip_appdata + numprinted, uip_mss() - numprinted, httpd_cgi_sensor11,\
00489     RF230_sendpackets,RF230_receivepackets,RF230_sendfail,RF230_receivefail,-92+rf230_last_rssi);
00490 #else
00491   p1=0;
00492   radio_get_rssi_value(&p1);
00493   p1 = -91*3(p1-1);
00494   numprinted+=httpd_snprintf((char *)uip_appdata + numprinted, uip_mss() - numprinted, httpd_cgi_sensor11,\
00495     RF230_sendpackets,RF230_receivepackets,RF230_sendfail,RF230_receivefail,p1);
00496 #endif
00497  
00498   return numprinted;
00499 }
00500 #endif
00501 /*---------------------------------------------------------------------------*/
00502 static
00503 PT_THREAD(sensor_readings(struct httpd_state *s, char *ptr))
00504 {
00505   PSOCK_BEGIN(&s->sout);
00506 
00507   PSOCK_GENERATOR_SEND(&s->sout, generate_sensor_readings, s);
00508 #if RADIOSTATS
00509   PSOCK_GENERATOR_SEND(&s->sout, generate_radio_stats, s);
00510 #endif
00511 
00512   
00513   PSOCK_END(&s->sout);
00514 }
00515 /*---------------------------------------------------------------------------*/
00516 void
00517 httpd_cgi_add(struct httpd_cgi_call *c)
00518 {
00519   struct httpd_cgi_call *l;
00520 
00521   c->next = NULL;
00522   if(calls == NULL) {
00523     calls = c;
00524   } else {
00525     for(l = calls; l->next != NULL; l = l->next);
00526     l->next = c;
00527   }
00528 }
00529 /*---------------------------------------------------------------------------*/
00530 
00531 #if HTTPD_FS_STATISTICS
00532 HTTPD_CGI_CALL(   file,   file_name,      file_stats);
00533 #endif
00534 HTTPD_CGI_CALL(    tcp,    tcp_name, tcp_stats      );
00535 HTTPD_CGI_CALL(   proc,   proc_name, processes      );
00536 HTTPD_CGI_CALL(   adrs,   adrs_name, addresses      );
00537 HTTPD_CGI_CALL(   nbrs,   nbrs_name, neighbors      );
00538 HTTPD_CGI_CALL(   rtes,   rtes_name, routes         );
00539 HTTPD_CGI_CALL(sensors, sensor_name, sensor_readings);
00540 
00541 void
00542 httpd_cgi_init(void)
00543 {
00544 #if HTTPD_FS_STATISTICS
00545   httpd_cgi_add(   &file);
00546 #endif
00547   httpd_cgi_add(    &tcp);
00548   httpd_cgi_add(   &proc);
00549   httpd_cgi_add(   &adrs);
00550   httpd_cgi_add(   &nbrs);
00551   httpd_cgi_add(   &rtes);
00552   httpd_cgi_add(&sensors);
00553 }
00554 /*---------------------------------------------------------------------------*/
00555 
00556 uint8_t httpd_cgi_sprint_ip6(uip_ip6addr_t addr, char * result)
00557         {
00558         unsigned char zerocnt = 0;
00559         unsigned char numprinted = 0;
00560         char * starting = result;
00561 
00562     unsigned char i = 0;
00563 
00564         while (numprinted < 8)
00565                 {
00566                 //Address is zero, have we used our ability to
00567                 //replace a bunch with : yet?
00568                 if ((addr.u16[i] == 0) && (zerocnt == 0))
00569                         {
00570                         //How mant zeros?
00571                         zerocnt = 0;
00572                         while(addr.u16[zerocnt + i] == 0)
00573                                 zerocnt++;
00574 
00575                         //just one, don't waste our zeros...
00576                         if (zerocnt == 1)
00577                                 {
00578                                 *result++ = '0';
00579                                 numprinted++;
00580                                 break;
00581                                 }
00582 
00583                         //Cool - can replace a bunch of zeros
00584                         i += zerocnt;
00585                         numprinted += zerocnt;
00586                         }
00587                 //Normal address, just print it
00588                 else
00589                         {
00590                         result += sprintf(result, "%x", (unsigned int)(uip_ntohs(addr.u16[i])));
00591                         i++;
00592                         numprinted++;
00593                         }
00594 
00595                 //Don't print : on last one
00596                 if (numprinted != 8)
00597                         *result++ = ':';
00598                 }
00599 
00600     return (result - starting);
00601         }
00602