Contiki 2.6
|
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