Merge branch 'master' of ssh://contiki.git.sourceforge.net/gitroot/contiki/contiki
This commit is contained in:
commit
0ba83a10df
45 changed files with 3154 additions and 426 deletions
1
apps/httpd-ws/Makefile.httpd-ws
Normal file
1
apps/httpd-ws/Makefile.httpd-ws
Normal file
|
@ -0,0 +1 @@
|
|||
httpd-ws_src = httpd-ws.c
|
478
apps/httpd-ws/httpd-ws.c
Normal file
478
apps/httpd-ws/httpd-ws.c
Normal file
|
@ -0,0 +1,478 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2012, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* A simple webserver for web services
|
||||
* \author
|
||||
* Adam Dunkels <adam@sics.se>
|
||||
* Niclas Finne <nfi@sics.se>
|
||||
* Joakim Eriksson <joakime@sics.se>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "contiki-net.h"
|
||||
#include "httpd-ws.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
#define PRINTF(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define PRINTF(...)
|
||||
#endif
|
||||
|
||||
#ifndef WEBSERVER_CONF_CFS_CONNS
|
||||
#define CONNS UIP_CONNS
|
||||
#else /* WEBSERVER_CONF_CFS_CONNS */
|
||||
#define CONNS WEBSERVER_CONF_CFS_CONNS
|
||||
#endif /* WEBSERVER_CONF_CFS_CONNS */
|
||||
|
||||
#ifndef WEBSERVER_CONF_CFS_URLCONV
|
||||
#define URLCONV 0
|
||||
#else /* WEBSERVER_CONF_CFS_URLCONV */
|
||||
#define URLCONV WEBSERVER_CONF_CFS_URLCONV
|
||||
#endif /* WEBSERVER_CONF_CFS_URLCONV */
|
||||
|
||||
#if URLCONV
|
||||
#include "urlconv.h"
|
||||
#endif /* URLCONV */
|
||||
|
||||
static struct httpd_ws_state conns[CONNS];
|
||||
|
||||
PROCESS(httpd_ws_process, "Web server (WS)");
|
||||
|
||||
#define ISO_nl 0x0a
|
||||
#define ISO_space 0x20
|
||||
#define ISO_period 0x2e
|
||||
#define ISO_slash 0x2f
|
||||
|
||||
uint16_t http_connections = 0;
|
||||
|
||||
static const char http_10[] = " HTTP/1.0\r\n";
|
||||
static const char http_content_type[] = "Content-Type:";
|
||||
static const char http_content_type_html[] = "text/html";
|
||||
static const char http_content_len[] = "Content-Length:";
|
||||
static const char http_header_404[] =
|
||||
"HTTP/1.0 404 Not found\r\nServer: Contiki\r\nConnection: close\r\n";
|
||||
static const char http_header_200[] =
|
||||
"HTTP/1.0 200 OK\r\nServer: Contiki\r\nConnection: close\r\n";
|
||||
static const char html_not_found[] =
|
||||
"<html><body><h1>Page not found</h1></body></html>";
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* just set all states to unused */
|
||||
static void
|
||||
httpd_state_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < CONNS; i++) {
|
||||
conns[i].state = HTTPD_WS_STATE_UNUSED;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static struct httpd_ws_state *
|
||||
httpd_state_alloc(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < CONNS; i++) {
|
||||
if(conns[i].state == HTTPD_WS_STATE_UNUSED) {
|
||||
conns[i].state = HTTPD_WS_STATE_INPUT;
|
||||
return &conns[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define httpd_state_free(s) (s->state = HTTPD_WS_STATE_UNUSED)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static
|
||||
PT_THREAD(send_string(struct httpd_ws_state *s, const char *str, uint16_t len))
|
||||
{
|
||||
PSOCK_BEGIN(&s->sout);
|
||||
|
||||
SEND_STRING(&s->sout, str, len);
|
||||
|
||||
PSOCK_END(&s->sout);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static
|
||||
PT_THREAD(send_headers(struct httpd_ws_state *s, const char *statushdr))
|
||||
{
|
||||
PSOCK_BEGIN(&s->sout);
|
||||
|
||||
SEND_STRING(&s->sout, statushdr, strlen(statushdr));
|
||||
s->outbuf_pos = snprintf(s->outbuf, sizeof(s->outbuf),
|
||||
"%s %s\r\n\r\n", http_content_type,
|
||||
s->content_type == NULL
|
||||
? http_content_type_html : s->content_type);
|
||||
SEND_STRING(&s->sout, s->outbuf, s->outbuf_pos);
|
||||
s->outbuf_pos = 0;
|
||||
|
||||
PSOCK_END(&s->sout);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static
|
||||
PT_THREAD(handle_output(struct httpd_ws_state *s))
|
||||
{
|
||||
PT_BEGIN(&s->outputpt);
|
||||
|
||||
s->content_type = http_content_type_html;
|
||||
s->script = httpd_ws_get_script(s);
|
||||
if(s->script == NULL) {
|
||||
PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_404));
|
||||
PT_WAIT_THREAD(&s->outputpt,
|
||||
send_string(s, html_not_found, strlen(html_not_found)));
|
||||
uip_close();
|
||||
/* webserver_log_file(&uip_conn->ripaddr, "404 - not found"); */
|
||||
PT_EXIT(&s->outputpt);
|
||||
} else {
|
||||
if(s->request_type == HTTPD_WS_POST) {
|
||||
/* A post has a body that needs to be read */
|
||||
s->state = HTTPD_WS_STATE_INPUT;
|
||||
PT_WAIT_UNTIL(&s->outputpt, s->state == HTTPD_WS_STATE_OUTPUT);
|
||||
}
|
||||
PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_200));
|
||||
PT_WAIT_THREAD(&s->outputpt, s->script(s));
|
||||
}
|
||||
s->script = NULL;
|
||||
PSOCK_CLOSE(&s->sout);
|
||||
PT_END(&s->outputpt);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static
|
||||
PT_THREAD(handle_request(struct httpd_ws_state *s))
|
||||
{
|
||||
PT_BEGIN(&s->outputpt);
|
||||
|
||||
/* send the request line */
|
||||
PT_WAIT_THREAD(&s->outputpt,
|
||||
send_string(s, s->filename, strlen(s->filename)));
|
||||
/* send host */
|
||||
if(s->outbuf_pos > 0) {
|
||||
PT_WAIT_THREAD(&s->outputpt, send_string(s, s->outbuf, s->outbuf_pos));
|
||||
}
|
||||
|
||||
if(s->content_type != NULL) {
|
||||
s->outbuf_pos = snprintf(s->outbuf, sizeof(s->outbuf), "%s %s\r\n",
|
||||
http_content_type, s->content_type);
|
||||
PT_WAIT_THREAD(&s->outputpt, send_string(s, s->outbuf, s->outbuf_pos));
|
||||
}
|
||||
/* send the extra header(s) */
|
||||
if(s->output_extra_headers != NULL) {
|
||||
s->response_index = 0;
|
||||
while((s->outbuf_pos =
|
||||
s->output_extra_headers(s,
|
||||
s->outbuf, sizeof(s->outbuf),
|
||||
s->response_index)) > 0) {
|
||||
PT_WAIT_THREAD(&s->outputpt, send_string(s, s->outbuf, s->outbuf_pos));
|
||||
s->response_index++;
|
||||
}
|
||||
}
|
||||
|
||||
/* send content length */
|
||||
if(s->content_len > 0) {
|
||||
s->outbuf_pos = snprintf(s->outbuf, sizeof(s->outbuf), "%s %u\r\n",
|
||||
http_content_len, s->content_len);
|
||||
}
|
||||
/* send header separator */
|
||||
if(s->outbuf_pos + 2 < sizeof(s->outbuf)) {
|
||||
s->outbuf[s->outbuf_pos++] = '\r';
|
||||
s->outbuf[s->outbuf_pos++] = '\n';
|
||||
}
|
||||
PT_WAIT_THREAD(&s->outputpt, send_string(s, s->outbuf, s->outbuf_pos));
|
||||
s->outbuf_pos = 0;
|
||||
|
||||
if(s->script != NULL) {
|
||||
PT_WAIT_THREAD(&s->outputpt, s->script(s));
|
||||
}
|
||||
s->state = HTTPD_WS_STATE_REQUEST_INPUT;
|
||||
|
||||
PSOCK_CLOSE(&s->sout);
|
||||
PT_END(&s->outputpt);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static
|
||||
PT_THREAD(handle_input(struct httpd_ws_state *s))
|
||||
{
|
||||
PSOCK_BEGIN(&s->sin);
|
||||
PSOCK_READTO(&s->sin, ISO_space);
|
||||
|
||||
if(strncmp(s->inputbuf, "GET ", 4) == 0) {
|
||||
s->request_type = HTTPD_WS_GET;
|
||||
} else if(strncmp(s->inputbuf, "POST ", 5) == 0) {
|
||||
s->request_type = HTTPD_WS_POST;
|
||||
s->content_len = 0;
|
||||
} else if(strncmp(s->inputbuf, "HTTP ", 5) == 0) {
|
||||
s->request_type = HTTPD_WS_RESPONSE;
|
||||
} else {
|
||||
PSOCK_CLOSE_EXIT(&s->sin);
|
||||
}
|
||||
PSOCK_READTO(&s->sin, ISO_space);
|
||||
|
||||
/* TODO handle HTTP response */
|
||||
|
||||
if(s->inputbuf[0] != ISO_slash) {
|
||||
PSOCK_CLOSE_EXIT(&s->sin);
|
||||
}
|
||||
|
||||
#if URLCONV
|
||||
s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0;
|
||||
urlconv_tofilename(s->filename, s->inputbuf, sizeof(s->filename));
|
||||
#else /* URLCONV */
|
||||
s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0;
|
||||
snprintf(s->filename, sizeof(s->filename), "%s", s->inputbuf);
|
||||
#endif /* URLCONV */
|
||||
|
||||
/* webserver_log_file(&uip_conn->ripaddr, s->filename); */
|
||||
s->state = HTTPD_WS_STATE_OUTPUT;
|
||||
|
||||
while(1) {
|
||||
PSOCK_READTO(&s->sin, ISO_nl);
|
||||
|
||||
if(s->request_type == HTTPD_WS_POST &&
|
||||
strncmp(s->inputbuf, http_content_len, 15) == 0) {
|
||||
s->inputbuf[PSOCK_DATALEN(&s->sin) - 2] = 0;
|
||||
s->content_len = atoi(&s->inputbuf[16]);
|
||||
}
|
||||
|
||||
/* should have a header callback here check_header(s) */
|
||||
|
||||
if(PSOCK_DATALEN(&s->sin) > 2) {
|
||||
s->inputbuf[PSOCK_DATALEN(&s->sin) - 2] = 0;
|
||||
} else if(s->request_type == HTTPD_WS_POST) {
|
||||
PSOCK_READBUF_LEN(&s->sin, s->content_len);
|
||||
s->inputbuf[PSOCK_DATALEN(&s->sin)] = 0;
|
||||
/* printf("Content: '%s'\nSize:%d\n", s->inputbuf, PSOCK_DATALEN(&s->sin)); */
|
||||
s->state = HTTPD_WS_STATE_OUTPUT;
|
||||
}
|
||||
}
|
||||
PSOCK_END(&s->sin);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
handle_connection(struct httpd_ws_state *s)
|
||||
{
|
||||
if(s->state == HTTPD_WS_STATE_REQUEST_OUTPUT) {
|
||||
handle_request(s);
|
||||
}
|
||||
handle_input(s);
|
||||
if(s->state == HTTPD_WS_STATE_OUTPUT) {
|
||||
handle_output(s);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
httpd_ws_appcall(void *state)
|
||||
{
|
||||
struct httpd_ws_state *s = (struct httpd_ws_state *)state;
|
||||
|
||||
if(uip_closed() || uip_aborted() || uip_timedout()) {
|
||||
if(s != NULL) {
|
||||
PRINTF("HTTPD-WS: closed/aborted (%d)\n", http_connections);
|
||||
http_connections--;
|
||||
httpd_state_free(s);
|
||||
} else {
|
||||
PRINTF("HTTPD-WS: closed/aborted ** NO HTTPD_WS_STATE!!! ** (%d)\n",
|
||||
http_connections);
|
||||
}
|
||||
} else if(uip_connected()) {
|
||||
if(s == NULL) {
|
||||
s = httpd_state_alloc();
|
||||
if(s == NULL) {
|
||||
uip_abort();
|
||||
PRINTF("HTTPD-WS: aborting - no resource (%d)\n", http_connections);
|
||||
/* webserver_log_file(&uip_conn->ripaddr, "reset (no memory block)"); */
|
||||
return;
|
||||
}
|
||||
http_connections++;
|
||||
|
||||
tcp_markconn(uip_conn, s);
|
||||
s->state = HTTPD_WS_STATE_INPUT;
|
||||
} else {
|
||||
/* this is a request that is to be sent! */
|
||||
s->state = HTTPD_WS_STATE_REQUEST_OUTPUT;
|
||||
}
|
||||
PSOCK_INIT(&s->sin, (uint8_t *)s->inputbuf, sizeof(s->inputbuf) - 1);
|
||||
PSOCK_INIT(&s->sout, (uint8_t *)s->inputbuf, sizeof(s->inputbuf) - 1);
|
||||
PT_INIT(&s->outputpt);
|
||||
timer_set(&s->timer, CLOCK_SECOND * 30);
|
||||
handle_connection(s);
|
||||
} else if(s != NULL) {
|
||||
if(uip_poll()) {
|
||||
if(timer_expired(&s->timer)) {
|
||||
uip_abort();
|
||||
PRINTF("HTTPD-WS: aborting - http timeout (%d)\n", http_connections);
|
||||
http_connections--;
|
||||
httpd_state_free(s);
|
||||
/* webserver_log_file(&uip_conn->ripaddr, "reset (timeout)"); */
|
||||
} else {
|
||||
PRINTF("HTTPD-WS: uip-poll (%d)\n", http_connections);
|
||||
}
|
||||
} else {
|
||||
/* PRINTF("HTTPD-WS: restart timer %s (%d)\n", s->filename, */
|
||||
/* http_connections); */
|
||||
timer_restart(&s->timer);
|
||||
}
|
||||
handle_connection(s);
|
||||
} else {
|
||||
PRINTF("HTTPD-WS: aborting - no state (%d)\n", http_connections);
|
||||
uip_abort();
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
httpd_ws_init(void)
|
||||
{
|
||||
tcp_listen(UIP_HTONS(80));
|
||||
httpd_state_init();
|
||||
#if URLCONV
|
||||
urlconv_init();
|
||||
#endif /* URLCONV */
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct httpd_ws_state *
|
||||
httpd_ws_request(char request_type, const char *host_ip, const char *host_hdr,
|
||||
uint16_t port, const char *file,
|
||||
const char *content_type, uint16_t content_len,
|
||||
httpd_ws_script_t generator)
|
||||
{
|
||||
struct httpd_ws_state *s;
|
||||
struct uip_conn *conn;
|
||||
uip_ipaddr_t *ipaddr;
|
||||
uip_ipaddr_t addr;
|
||||
char *request_str;
|
||||
|
||||
/* First check if the host is an IP address. */
|
||||
ipaddr = &addr;
|
||||
if(uiplib_ipaddrconv(host_ip, &addr) == 0) {
|
||||
#if 0 && UIP_UDP
|
||||
ipaddr = resolv_lookup(host_ip);
|
||||
|
||||
if(ipaddr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
#else /* UIP_UDP */
|
||||
return NULL;
|
||||
#endif /* UIP_UDP */
|
||||
}
|
||||
|
||||
s = httpd_state_alloc();
|
||||
if(s == NULL) {
|
||||
/* no memory left... do no request... */
|
||||
return NULL;
|
||||
}
|
||||
http_connections++;
|
||||
|
||||
switch(request_type) {
|
||||
case HTTPD_WS_POST:
|
||||
request_str = "POST ";
|
||||
break;
|
||||
case HTTPD_WS_PUT:
|
||||
request_str = "PUT ";
|
||||
break;
|
||||
default:
|
||||
request_str = "GET ";
|
||||
break;
|
||||
}
|
||||
|
||||
s->request_type = request_type;
|
||||
s->content_len = content_len;
|
||||
s->content_type = content_type;
|
||||
s->script = generator;
|
||||
s->state = HTTPD_WS_STATE_REQUEST_OUTPUT;
|
||||
|
||||
/* create a request line for a POST - should check size of it!!! */
|
||||
/* Assume post for now */
|
||||
snprintf(s->filename, sizeof(s->filename), "%s%s%s",
|
||||
request_str, file, http_10);
|
||||
s->outbuf_pos = snprintf(s->outbuf, sizeof(s->outbuf), "Host:%s\r\n",
|
||||
host_hdr != NULL ? host_hdr : host_ip);
|
||||
|
||||
PROCESS_CONTEXT_BEGIN(&httpd_ws_process);
|
||||
conn = tcp_connect(ipaddr, uip_htons(port), s);
|
||||
PROCESS_CONTEXT_END(&httpd_ws_process);
|
||||
if(conn == NULL) {
|
||||
PRINTF("HTTPD-WS: aborting... could not allocate tcp connection (%d)\n",
|
||||
http_connections);
|
||||
httpd_state_free(s);
|
||||
http_connections--;
|
||||
return NULL;
|
||||
}
|
||||
PRINTF("HTTPD-WS: created http connection (%d)\n", http_connections);
|
||||
|
||||
return s;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS_THREAD(httpd_ws_process, ev, data)
|
||||
{
|
||||
static struct etimer et;
|
||||
int i;
|
||||
|
||||
PROCESS_BEGIN();
|
||||
|
||||
httpd_ws_init();
|
||||
|
||||
PRINTF("Buffer size, input %d, output\n",
|
||||
HTTPD_INBUF_SIZE, HTTPD_OUTBUF_SIZE);
|
||||
|
||||
/* Delay 2-4 seconds */
|
||||
etimer_set(&et, CLOCK_SECOND * 10);
|
||||
|
||||
/* GC any http session that is too long lived - either because other
|
||||
end never closed or if any other state cause too long lived http
|
||||
sessions */
|
||||
while(1) {
|
||||
PROCESS_WAIT_EVENT_UNTIL(ev == tcpip_event || etimer_expired(&et));
|
||||
if(ev == tcpip_event) {
|
||||
httpd_ws_appcall(data);
|
||||
} else if(etimer_expired(&et)) {
|
||||
PRINTF("HTTPD States: ");
|
||||
for(i = 0; i < CONNS; i++) {
|
||||
PRINTF("%d ", conns[i].state);
|
||||
if(conns[i].state != HTTPD_WS_STATE_UNUSED &&
|
||||
timer_expired(&conns[i].timer)) {
|
||||
conns[i].state = HTTPD_WS_STATE_UNUSED;
|
||||
PRINTF("\n*** RELEASED HTTPD Session\n");
|
||||
http_connections--;
|
||||
}
|
||||
}
|
||||
PRINTF("\n");
|
||||
etimer_reset(&et);
|
||||
}
|
||||
}
|
||||
|
||||
PROCESS_END();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
125
apps/httpd-ws/httpd-ws.h
Normal file
125
apps/httpd-ws/httpd-ws.h
Normal file
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2012, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* A simple webserver for web services
|
||||
* \author
|
||||
* Adam Dunkels <adam@sics.se>
|
||||
* Niclas Finne <nfi@sics.se>
|
||||
* Joakim Eriksson <joakime@sics.se>
|
||||
*/
|
||||
|
||||
#ifndef __HTTPD_WS_H__
|
||||
#define __HTTPD_WS_H__
|
||||
|
||||
#include "contiki-net.h"
|
||||
|
||||
#ifndef WEBSERVER_CONF_CFS_PATHLEN
|
||||
#define HTTPD_PATHLEN 80
|
||||
#else /* WEBSERVER_CONF_CFS_CONNS */
|
||||
#define HTTPD_PATHLEN WEBSERVER_CONF_CFS_PATHLEN
|
||||
#endif /* WEBSERVER_CONF_CFS_CONNS */
|
||||
|
||||
#ifndef WEBSERVER_CONF_INBUF_SIZE
|
||||
#define HTTPD_INBUF_SIZE (HTTPD_PATHLEN + 90)
|
||||
#else /* WEBSERVER_CONF_INBUF_SIZE */
|
||||
#define HTTPD_INBUF_SIZE WEBSERVER_CONF_INBUF_SIZE
|
||||
#endif /* WEBSERVER_CONF_INBUF_SIZE */
|
||||
|
||||
#if HTTPD_INBUF_SIZE < UIP_TCP_MSS || HTTPD_INBUF_SIZE < UIP_RECEIVE_WINDOW
|
||||
#error HTTPD_INBUF_SIZE is too small. Must be at least a TCP window in size.
|
||||
#endif
|
||||
|
||||
#ifndef WEBSERVER_CONF_OUTBUF_SIZE
|
||||
#define HTTPD_OUTBUF_SIZE (UIP_TCP_MSS + 20)
|
||||
#else /* WEBSERVER_CONF_OUTBUF_SIZE */
|
||||
#define HTTPD_OUTBUF_SIZE WEBSERVER_CONF_OUTBUF_SIZE
|
||||
#endif /* WEBSERVER_CONF_OUTBUF_SIZE */
|
||||
|
||||
struct httpd_ws_state;
|
||||
typedef char (* httpd_ws_script_t)(struct httpd_ws_state *s);
|
||||
typedef int (* httpd_ws_output_headers_t)(struct httpd_ws_state *s,
|
||||
char *buffer, int buf_size,
|
||||
int index);
|
||||
|
||||
#define HTTPD_WS_GET 1
|
||||
#define HTTPD_WS_POST 2
|
||||
#define HTTPD_WS_PUT 3
|
||||
#define HTTPD_WS_RESPONSE 4
|
||||
|
||||
#define HTTPD_WS_STATE_UNUSED 0
|
||||
#define HTTPD_WS_STATE_INPUT 1
|
||||
#define HTTPD_WS_STATE_OUTPUT 2
|
||||
#define HTTPD_WS_STATE_REQUEST_OUTPUT 3
|
||||
#define HTTPD_WS_STATE_REQUEST_INPUT 4
|
||||
|
||||
struct httpd_ws_state {
|
||||
struct timer timer;
|
||||
struct psock sin, sout;
|
||||
struct pt outputpt;
|
||||
char inputbuf[HTTPD_INBUF_SIZE];
|
||||
char filename[HTTPD_PATHLEN];
|
||||
const char *content_type;
|
||||
uint16_t content_len;
|
||||
char outbuf[HTTPD_OUTBUF_SIZE];
|
||||
uint16_t outbuf_pos;
|
||||
char state;
|
||||
char request_type;
|
||||
int response_index;
|
||||
|
||||
httpd_ws_output_headers_t output_extra_headers;
|
||||
httpd_ws_script_t script;
|
||||
|
||||
#ifdef HTTPD_WS_CONF_USER_STATE
|
||||
HTTPD_WS_CONF_USER_STATE;
|
||||
#endif
|
||||
};
|
||||
|
||||
void httpd_ws_init(void);
|
||||
void httpd_ws_appcall(void *state);
|
||||
|
||||
struct httpd_ws_state *httpd_ws_request(char request_type,
|
||||
const char *host_ip,
|
||||
const char *host_hdr,
|
||||
uint16_t port,
|
||||
const char *file,
|
||||
const char *content_type,
|
||||
uint16_t content_len,
|
||||
httpd_ws_script_t generator);
|
||||
|
||||
#define SEND_STRING(s, str, len) PSOCK_SEND((s), (uint8_t *)(str), (len))
|
||||
|
||||
httpd_ws_script_t httpd_ws_get_script(struct httpd_ws_state *s);
|
||||
|
||||
PROCESS_NAME(httpd_ws_process);
|
||||
|
||||
#endif /* __HTTPD_WS_H__ */
|
1
apps/json/Makefile.json
Normal file
1
apps/json/Makefile.json
Normal file
|
@ -0,0 +1 @@
|
|||
json_src = jsonparse.c jsontree.c
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2006, Swedish Institute of Computer Science.
|
||||
* Copyright (c) 2011-2012, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -26,49 +26,45 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: IdIPDistributor.java,v 1.2 2009/09/17 13:20:03 fros4943 Exp $
|
||||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
package se.sics.cooja.ipdistributors;
|
||||
import java.util.Vector;
|
||||
import se.sics.cooja.*;
|
||||
|
||||
/**
|
||||
* Generates IP addresses on the form 10.[id/256 mod 256*256].[id mod 256].1.
|
||||
*
|
||||
* Observe!
|
||||
* - ID must be set before this is called (otherwise IP=0.0.0.0).
|
||||
* - Only supports 256*256 motes, (IPs will wrap if above).
|
||||
*
|
||||
* @author Fredrik Osterlind
|
||||
* \file
|
||||
* A few JSON defines used for parsing and generating JSON.
|
||||
* \author
|
||||
* Niclas Finne <nfi@sics.se>
|
||||
* Joakim Eriksson <joakime@sics.se>
|
||||
*/
|
||||
@ClassDescription("From ID (10.id.id.1)")
|
||||
public class IdIPDistributor extends IPDistributor {
|
||||
private Vector<String> generatedIPAddresses;
|
||||
|
||||
/**
|
||||
* Creates a Id IP distributor.
|
||||
* @param newMotes All motes which later will be assigned IP numbers.
|
||||
*/
|
||||
public IdIPDistributor(Vector<Mote> newMotes) {
|
||||
generatedIPAddresses = new Vector<String>();
|
||||
#ifndef __JSON_H__
|
||||
#define __JSON_H__
|
||||
|
||||
for (int i=0; i < newMotes.size(); i++) {
|
||||
int moteId = newMotes.get(i).getID();
|
||||
generatedIPAddresses.add("10." +
|
||||
(moteId / 256 % (256*256))
|
||||
+ "." +
|
||||
(moteId % 256)
|
||||
+ ".1");
|
||||
}
|
||||
#define JSON_TYPE_ARRAY '['
|
||||
#define JSON_TYPE_OBJECT '{'
|
||||
#define JSON_TYPE_PAIR ':'
|
||||
#define JSON_TYPE_PAIR_NAME 'N' /* for N:V pairs */
|
||||
#define JSON_TYPE_STRING '"'
|
||||
#define JSON_TYPE_INT 'I'
|
||||
#define JSON_TYPE_NUMBER '0'
|
||||
#define JSON_TYPE_ERROR 0
|
||||
|
||||
}
|
||||
/* how should we handle null vs false - both can be 0? */
|
||||
#define JSON_TYPE_NULL 'n'
|
||||
#define JSON_TYPE_TRUE 't'
|
||||
#define JSON_TYPE_FALSE 'f'
|
||||
|
||||
public String getNextIPAddress() {
|
||||
if (generatedIPAddresses.size() > 0)
|
||||
return generatedIPAddresses.remove(0);
|
||||
else
|
||||
return "0.0.0.0";
|
||||
}
|
||||
#define JSON_TYPE_CALLBACK 'C'
|
||||
|
||||
}
|
||||
enum {
|
||||
JSON_ERROR_OK,
|
||||
JSON_ERROR_SYNTAX,
|
||||
JSON_ERROR_UNEXPECTED_ARRAY,
|
||||
JSON_ERROR_UNEXPECTED_END_OF_ARRAY,
|
||||
JSON_ERROR_UNEXPECTED_OBJECT,
|
||||
JSON_ERROR_UNEXPECTED_STRING
|
||||
};
|
||||
|
||||
#define JSON_CONTENT_TYPE "application/json"
|
||||
|
||||
#endif /* __JSON_H__ */
|
257
apps/json/jsonparse.c
Normal file
257
apps/json/jsonparse.c
Normal file
|
@ -0,0 +1,257 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2012, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
#include "jsonparse.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*--------------------------------------------------------------------*/
|
||||
static int
|
||||
push(struct jsonparse_state *state, char c)
|
||||
{
|
||||
state->stack[state->depth] = c;
|
||||
state->depth++;
|
||||
state->vtype = 0;
|
||||
return state->depth < JSONPARSE_MAX_DEPTH;
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
static char
|
||||
pop(struct jsonparse_state *state)
|
||||
{
|
||||
if(state->depth == 0) {
|
||||
return JSON_TYPE_ERROR;
|
||||
}
|
||||
state->depth--;
|
||||
return state->stack[state->depth];
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
/* will pass by the value and store the start and length of the value for
|
||||
atomic types */
|
||||
/*--------------------------------------------------------------------*/
|
||||
static void
|
||||
atomic(struct jsonparse_state *state, char type)
|
||||
{
|
||||
char c;
|
||||
|
||||
state->vstart = state->pos;
|
||||
state->vtype = type;
|
||||
if(type == JSON_TYPE_STRING || type == JSON_TYPE_PAIR_NAME) {
|
||||
while((c = state->json[state->pos++]) && c != '"') {
|
||||
if(c == '\\') {
|
||||
state->pos++; /* skip current char */
|
||||
}
|
||||
}
|
||||
state->vlen = state->pos - state->vstart - 1;
|
||||
} else if(type == JSON_TYPE_NUMBER) {
|
||||
do {
|
||||
c = state->json[state->pos];
|
||||
if((c < '0' || c > '9') && c != '.') {
|
||||
c = 0;
|
||||
} else {
|
||||
state->pos++;
|
||||
}
|
||||
} while(c);
|
||||
/* need to back one step since first char is already gone */
|
||||
state->vstart--;
|
||||
state->vlen = state->pos - state->vstart;
|
||||
}
|
||||
/* no other types for now... */
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
static void
|
||||
skip_ws(struct jsonparse_state *state)
|
||||
{
|
||||
char c;
|
||||
|
||||
while(state->pos < state->len &&
|
||||
((c = state->json[state->pos]) == ' ' || c == '\n')) {
|
||||
state->pos++;
|
||||
}
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
void
|
||||
jsonparse_setup(struct jsonparse_state *state, const char *json, int len)
|
||||
{
|
||||
state->json = json;
|
||||
state->len = len;
|
||||
state->pos = 0;
|
||||
state->depth = 0;
|
||||
state->error = 0;
|
||||
state->stack[0] = 0;
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
int
|
||||
jsonparse_next(struct jsonparse_state *state)
|
||||
{
|
||||
char c;
|
||||
char s;
|
||||
|
||||
skip_ws(state);
|
||||
c = state->json[state->pos];
|
||||
s = jsonparse_get_type(state);
|
||||
state->pos++;
|
||||
|
||||
switch(c) {
|
||||
case '{':
|
||||
push(state, c);
|
||||
return c;
|
||||
case '}':
|
||||
if(s == ':' && state->vtype != 0) {
|
||||
/* printf("Popping vtype: '%c'\n", state->vtype); */
|
||||
pop(state);
|
||||
s = jsonparse_get_type(state);
|
||||
}
|
||||
if(s == '{') {
|
||||
pop(state);
|
||||
} else {
|
||||
state->error = JSON_ERROR_SYNTAX;
|
||||
return JSON_TYPE_ERROR;
|
||||
}
|
||||
return c;
|
||||
case ']':
|
||||
if(s == '[') {
|
||||
pop(state);
|
||||
} else {
|
||||
state->error = JSON_ERROR_UNEXPECTED_END_OF_ARRAY;
|
||||
return JSON_TYPE_ERROR;
|
||||
}
|
||||
return c;
|
||||
case ':':
|
||||
push(state, c);
|
||||
return c;
|
||||
case ',':
|
||||
/* if x:y ... , */
|
||||
if(s == ':' && state->vtype != 0) {
|
||||
pop(state);
|
||||
} else if(s == '[') {
|
||||
/* ok! */
|
||||
} else {
|
||||
state->error = JSON_ERROR_SYNTAX;
|
||||
return JSON_TYPE_ERROR;
|
||||
}
|
||||
return c;
|
||||
case '"':
|
||||
if(s == '{' || s == '[' || s == ':') {
|
||||
atomic(state, c = (s == '{' ? JSON_TYPE_PAIR_NAME : c));
|
||||
} else {
|
||||
state->error = JSON_ERROR_UNEXPECTED_STRING;
|
||||
return JSON_TYPE_ERROR;
|
||||
}
|
||||
return c;
|
||||
case '[':
|
||||
if(s == '{' || s == '[' || s == ':') {
|
||||
push(state, c);
|
||||
} else {
|
||||
state->error = JSON_ERROR_UNEXPECTED_ARRAY;
|
||||
return JSON_TYPE_ERROR;
|
||||
}
|
||||
return c;
|
||||
default:
|
||||
if(s == ':' || s == '[') {
|
||||
if(c <= '9' && c >= '0') {
|
||||
atomic(state, JSON_TYPE_NUMBER);
|
||||
return JSON_TYPE_NUMBER;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
/* get the json value of the current position
|
||||
* works only on "atomic" values such as string, number, null, false, true
|
||||
*/
|
||||
/*--------------------------------------------------------------------*/
|
||||
int
|
||||
jsonparse_copy_value(struct jsonparse_state *state, char *str, int size)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(state->vtype == 0) {
|
||||
return 0;
|
||||
}
|
||||
size = size <= state->vlen ? (size - 1) : state->vlen;
|
||||
for(i = 0; i < size; i++) {
|
||||
str[i] = state->json[state->vstart + i];
|
||||
}
|
||||
str[i] = 0;
|
||||
return state->vtype;
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
int
|
||||
jsonparse_get_value_as_int(struct jsonparse_state *state)
|
||||
{
|
||||
if(state->vtype != JSON_TYPE_NUMBER) {
|
||||
return 0;
|
||||
}
|
||||
return atoi(&state->json[state->vstart]);
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
long
|
||||
jsonparse_get_value_as_long(struct jsonparse_state *state)
|
||||
{
|
||||
if(state->vtype != JSON_TYPE_NUMBER) {
|
||||
return 0;
|
||||
}
|
||||
return atol(&state->json[state->vstart]);
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
/* strcmp - assume no strange chars that needs to be stuffed in string... */
|
||||
/*--------------------------------------------------------------------*/
|
||||
int
|
||||
jsonparse_strcmp_value(struct jsonparse_state *state, const char *str)
|
||||
{
|
||||
if(state->vtype == 0) {
|
||||
return -1;
|
||||
}
|
||||
return strncmp(str, &state->json[state->vstart], state->vlen);
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
int
|
||||
jsonparse_get_len(struct jsonparse_state *state)
|
||||
{
|
||||
return state->vlen;
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
int
|
||||
jsonparse_get_type(struct jsonparse_state *state)
|
||||
{
|
||||
if(state->depth == 0) {
|
||||
return 0;
|
||||
}
|
||||
return state->stack[state->depth - 1];
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
int
|
||||
jsonparse_has_next(struct jsonparse_state *state)
|
||||
{
|
||||
return state->pos < state->len;
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
91
apps/json/jsonparse.h
Normal file
91
apps/json/jsonparse.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2012, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
#ifndef __JSONPARSE_H__
|
||||
#define __JSONPARSE_H__
|
||||
|
||||
#include "contiki-conf.h"
|
||||
#include "json.h"
|
||||
|
||||
#ifdef JSONPARSE_CONF_MAX_DEPTH
|
||||
#define JSONPARSE_MAX_DEPTH JSONPARSE_CONF_MAX_DEPTH
|
||||
#else
|
||||
#define JSONPARSE_MAX_DEPTH 10
|
||||
#endif
|
||||
|
||||
struct jsonparse_state {
|
||||
const char *json;
|
||||
int pos;
|
||||
int len;
|
||||
int depth;
|
||||
/* for handling atomic values */
|
||||
int vstart;
|
||||
int vlen;
|
||||
char vtype;
|
||||
char error;
|
||||
char stack[JSONPARSE_MAX_DEPTH];
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Initialize a JSON parser state.
|
||||
* \param state A pointer to a JSON parser state
|
||||
* \param json The string to parse as JSON
|
||||
* \param len The length of the string to parse
|
||||
*
|
||||
* This function initializes a JSON parser state for
|
||||
* parsing a string as JSON.
|
||||
*/
|
||||
void jsonparse_setup(struct jsonparse_state *state, const char *json,
|
||||
int len);
|
||||
|
||||
/* move to next JSON element */
|
||||
int jsonparse_next(struct jsonparse_state *state);
|
||||
|
||||
/* copy the current JSON value into the specified buffer */
|
||||
int jsonparse_copy_value(struct jsonparse_state *state, char *buf,
|
||||
int buf_size);
|
||||
|
||||
/* get the current JSON value parsed as an int */
|
||||
int jsonparse_get_value_as_int(struct jsonparse_state *state);
|
||||
|
||||
/* get the current JSON value parsed as a long */
|
||||
long jsonparse_get_value_as_long(struct jsonparse_state *state);
|
||||
|
||||
/* get the length of the current JSON value */
|
||||
int jsonparse_get_len(struct jsonparse_state *state);
|
||||
|
||||
/* get the type of the current JSON value */
|
||||
int jsonparse_get_type(struct jsonparse_state *state);
|
||||
|
||||
/* compare the JSON value with the specified string */
|
||||
int jsonparse_strcmp_value(struct jsonparse_state *state, const char *str);
|
||||
|
||||
#endif /* __JSONPARSE_H__ */
|
275
apps/json/jsontree.c
Normal file
275
apps/json/jsontree.c
Normal file
|
@ -0,0 +1,275 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2012, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* JSON output generation
|
||||
* \author
|
||||
* Niclas Finne <nfi@sics.se>
|
||||
* Joakim Eriksson <joakime@sics.se>
|
||||
*/
|
||||
|
||||
#include "contiki.h"
|
||||
#include "jsontree.h"
|
||||
#include "jsonparse.h"
|
||||
#include <string.h>
|
||||
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
#include <stdio.h>
|
||||
#define PRINTF(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define PRINTF(...)
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
jsontree_write_atom(const struct jsontree_context *js_ctx, const char *text)
|
||||
{
|
||||
if(text == NULL) {
|
||||
js_ctx->putchar('0');
|
||||
} else {
|
||||
while(*text != '\0') {
|
||||
js_ctx->putchar(*text++);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
jsontree_write_string(const struct jsontree_context *js_ctx, const char *text)
|
||||
{
|
||||
js_ctx->putchar('"');
|
||||
if(text != NULL) {
|
||||
while(*text != '\0') {
|
||||
if(*text == '"') {
|
||||
js_ctx->putchar('\\');
|
||||
}
|
||||
js_ctx->putchar(*text++);
|
||||
}
|
||||
}
|
||||
js_ctx->putchar('"');
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
jsontree_write_int(const struct jsontree_context *js_ctx, int value)
|
||||
{
|
||||
char buf[10];
|
||||
int l;
|
||||
|
||||
if(value < 0) {
|
||||
js_ctx->putchar('-');
|
||||
value = -value;
|
||||
}
|
||||
|
||||
l = sizeof(buf) - 1;
|
||||
do {
|
||||
buf[l--] = '0' + (value % 10);
|
||||
value /= 10;
|
||||
} while(value > 0 && l >= 0);
|
||||
|
||||
while(++l < sizeof(buf)) {
|
||||
js_ctx->putchar(buf[l]);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
jsontree_setup(struct jsontree_context *js_ctx, struct jsontree_value *root,
|
||||
int (* putchar)(int))
|
||||
{
|
||||
js_ctx->values[0] = root;
|
||||
js_ctx->putchar = putchar;
|
||||
js_ctx->path = 0;
|
||||
jsontree_reset(js_ctx);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
jsontree_reset(struct jsontree_context *js_ctx)
|
||||
{
|
||||
js_ctx->depth = 0;
|
||||
js_ctx->index[0] = 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
const char *
|
||||
jsontree_path_name(const struct jsontree_context *js_ctx, int depth)
|
||||
{
|
||||
if(depth < js_ctx->depth && js_ctx->values[depth]->type == JSON_TYPE_OBJECT) {
|
||||
return ((struct jsontree_object *)js_ctx->values[depth])->
|
||||
pairs[js_ctx->index[depth]].name;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
jsontree_print_next(struct jsontree_context *js_ctx)
|
||||
{
|
||||
struct jsontree_value *v;
|
||||
int index;
|
||||
|
||||
v = js_ctx->values[js_ctx->depth];
|
||||
|
||||
/* Default operation after switch is to back up one level */
|
||||
switch(v->type) {
|
||||
case JSON_TYPE_OBJECT:
|
||||
case JSON_TYPE_ARRAY: {
|
||||
struct jsontree_array *o = (struct jsontree_array *)v;
|
||||
struct jsontree_value *ov;
|
||||
|
||||
index = js_ctx->index[js_ctx->depth];
|
||||
if(index == 0) {
|
||||
js_ctx->putchar(v->type);
|
||||
js_ctx->putchar('\n');
|
||||
}
|
||||
if(index >= o->count) {
|
||||
js_ctx->putchar('\n');
|
||||
js_ctx->putchar(v->type + 2);
|
||||
/* Default operation: back up one level! */
|
||||
break;
|
||||
}
|
||||
|
||||
if(index > 0) {
|
||||
js_ctx->putchar(',');
|
||||
js_ctx->putchar('\n');
|
||||
}
|
||||
if(v->type == JSON_TYPE_OBJECT) {
|
||||
jsontree_write_string(js_ctx,
|
||||
((struct jsontree_object *)o)->pairs[index].name);
|
||||
js_ctx->putchar(':');
|
||||
ov = ((struct jsontree_object *)o)->pairs[index].value;
|
||||
} else {
|
||||
ov = o->values[index];
|
||||
}
|
||||
/* TODO check max depth */
|
||||
js_ctx->depth++; /* step down to value... */
|
||||
js_ctx->index[js_ctx->depth] = 0; /* and init index */
|
||||
js_ctx->values[js_ctx->depth] = ov;
|
||||
/* Continue on this new level */
|
||||
return 1;
|
||||
}
|
||||
case JSON_TYPE_STRING:
|
||||
jsontree_write_string(js_ctx, ((struct jsontree_string *)v)->value);
|
||||
/* Default operation: back up one level! */
|
||||
break;
|
||||
case JSON_TYPE_INT:
|
||||
jsontree_write_int(js_ctx, ((struct jsontree_int *)v)->value);
|
||||
/* Default operation: back up one level! */
|
||||
break;
|
||||
case JSON_TYPE_CALLBACK: { /* pre-formatted json string currently */
|
||||
struct jsontree_callback *callback;
|
||||
|
||||
callback = (struct jsontree_callback *)v;
|
||||
if(js_ctx->index[js_ctx->depth] == 0) {
|
||||
/* First call: reset the callback status */
|
||||
js_ctx->callback_state = 0;
|
||||
}
|
||||
if(callback->output == NULL) {
|
||||
jsontree_write_string(js_ctx, "");
|
||||
} else if(callback->output(js_ctx)) {
|
||||
/* The callback wants to output more */
|
||||
js_ctx->index[js_ctx->depth]++;
|
||||
return 1;
|
||||
}
|
||||
/* Default operation: back up one level! */
|
||||
break;
|
||||
}
|
||||
default:
|
||||
PRINTF("\nError: Illegal json type:'%c'\n", v->type);
|
||||
return 0;
|
||||
}
|
||||
/* Done => back up one level! */
|
||||
if(js_ctx->depth > 0) {
|
||||
js_ctx->depth--;
|
||||
js_ctx->index[js_ctx->depth]++;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static struct jsontree_value *
|
||||
find_next(struct jsontree_context *js_ctx)
|
||||
{
|
||||
struct jsontree_value *v;
|
||||
int index;
|
||||
|
||||
do {
|
||||
v = js_ctx->values[js_ctx->depth];
|
||||
|
||||
/* Default operation after switch is to back up one level */
|
||||
switch(v->type) {
|
||||
case JSON_TYPE_OBJECT:
|
||||
case JSON_TYPE_ARRAY: {
|
||||
struct jsontree_array *o = (struct jsontree_array *)v;
|
||||
struct jsontree_value *ov;
|
||||
|
||||
index = js_ctx->index[js_ctx->depth];
|
||||
if(index >= o->count) {
|
||||
/* Default operation: back up one level! */
|
||||
break;
|
||||
}
|
||||
|
||||
if(v->type == JSON_TYPE_OBJECT) {
|
||||
ov = ((struct jsontree_object *)o)->pairs[index].value;
|
||||
} else {
|
||||
ov = o->values[index];
|
||||
}
|
||||
/* TODO check max depth */
|
||||
js_ctx->depth++; /* step down to value... */
|
||||
js_ctx->index[js_ctx->depth] = 0; /* and init index */
|
||||
js_ctx->values[js_ctx->depth] = ov;
|
||||
/* Continue on this new level */
|
||||
return ov;
|
||||
}
|
||||
default:
|
||||
/* Default operation: back up one level! */
|
||||
break;
|
||||
}
|
||||
/* Done => back up one level! */
|
||||
if(js_ctx->depth > 0) {
|
||||
js_ctx->depth--;
|
||||
js_ctx->index[js_ctx->depth]++;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
} while(1);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct jsontree_value *
|
||||
jsontree_find_next(struct jsontree_context *js_ctx, int type)
|
||||
{
|
||||
struct jsontree_value *v;
|
||||
|
||||
while((v = find_next(js_ctx)) != NULL && v->type != type &&
|
||||
js_ctx->path < js_ctx->depth) {
|
||||
/* search */
|
||||
}
|
||||
js_ctx->callback_state = 0;
|
||||
return js_ctx->path < js_ctx->depth ? v : NULL;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
135
apps/json/jsontree.h
Normal file
135
apps/json/jsontree.h
Normal file
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2012, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* JSON output generation
|
||||
* \author
|
||||
* Niclas Finne <nfi@sics.se>
|
||||
* Joakim Eriksson <joakime@sics.se>
|
||||
*/
|
||||
|
||||
#ifndef __JSONTREE_H__
|
||||
#define __JSONTREE_H__
|
||||
|
||||
#include "contiki-conf.h"
|
||||
#include "json.h"
|
||||
|
||||
#ifdef JSONTREE_CONF_MAX_DEPTH
|
||||
#define JSONTREE_MAX_DEPTH JSONTREE_CONF_MAX_DEPTH
|
||||
#else
|
||||
#define JSONTREE_MAX_DEPTH 10
|
||||
#endif /* JSONTREE_CONF_MAX_DEPTH */
|
||||
|
||||
struct jsontree_context {
|
||||
struct jsontree_value *values[JSONTREE_MAX_DEPTH];
|
||||
uint16_t index[JSONTREE_MAX_DEPTH];
|
||||
int (* putchar)(int);
|
||||
uint8_t depth;
|
||||
uint8_t path;
|
||||
int callback_state;
|
||||
};
|
||||
|
||||
struct jsontree_value {
|
||||
uint8_t type;
|
||||
/* followed by a value */
|
||||
};
|
||||
|
||||
struct jsontree_string {
|
||||
uint8_t type;
|
||||
const char *value;
|
||||
};
|
||||
|
||||
struct jsontree_int {
|
||||
uint8_t type;
|
||||
int value;
|
||||
};
|
||||
|
||||
/* NOTE: the jsontree_callback set will receive a jsonparse state */
|
||||
struct jsonparse_state;
|
||||
struct jsontree_callback {
|
||||
uint8_t type;
|
||||
int (* output)(struct jsontree_context *js_ctx);
|
||||
int (* set)(struct jsontree_context *js_ctx, struct jsonparse_state *parser);
|
||||
};
|
||||
|
||||
struct jsontree_pair {
|
||||
const char *name;
|
||||
struct jsontree_value *value;
|
||||
};
|
||||
|
||||
struct jsontree_object {
|
||||
uint8_t type;
|
||||
uint8_t count;
|
||||
struct jsontree_pair *pairs;
|
||||
};
|
||||
|
||||
struct jsontree_array {
|
||||
uint8_t type;
|
||||
uint8_t count;
|
||||
struct jsontree_value **values;
|
||||
};
|
||||
|
||||
#define JSONTREE_STRING(text) {JSON_TYPE_STRING, (text)}
|
||||
#define JSONTREE_PAIR(name, value) {(name), (struct jsontree_value *)(value)}
|
||||
#define JSONTREE_CALLBACK(output, set) {JSON_TYPE_CALLBACK, (output), (set)}
|
||||
|
||||
#define JSONTREE_OBJECT(name, ...) \
|
||||
static struct jsontree_pair jsontree_pair_##name[] = {__VA_ARGS__}; \
|
||||
static struct jsontree_object name = { \
|
||||
JSON_TYPE_OBJECT, \
|
||||
sizeof(jsontree_pair_##name)/sizeof(struct jsontree_pair), \
|
||||
jsontree_pair_##name }
|
||||
|
||||
#define JSONTREE_OBJECT_EXT(name, ...) \
|
||||
static struct jsontree_pair jsontree_pair_##name[] = {__VA_ARGS__}; \
|
||||
struct jsontree_object name = { \
|
||||
JSON_TYPE_OBJECT, \
|
||||
sizeof(jsontree_pair_##name)/sizeof(struct jsontree_pair), \
|
||||
jsontree_pair_##name }
|
||||
|
||||
void jsontree_setup(struct jsontree_context *js_ctx,
|
||||
struct jsontree_value *root, int (* putchar)(int));
|
||||
void jsontree_reset(struct jsontree_context *js_ctx);
|
||||
|
||||
const char *jsontree_path_name(const struct jsontree_context *js_ctx,
|
||||
int depth);
|
||||
|
||||
void jsontree_write_int(const struct jsontree_context *js_ctx, int value);
|
||||
void jsontree_write_atom(const struct jsontree_context *js_ctx,
|
||||
const char *text);
|
||||
void jsontree_write_string(const struct jsontree_context *js_ctx,
|
||||
const char *text);
|
||||
int jsontree_print_next(struct jsontree_context *js_ctx);
|
||||
struct jsontree_value *jsontree_find_next(struct jsontree_context *js_ctx,
|
||||
int type);
|
||||
|
||||
#endif /* __JSONTREE_H__ */
|
30
examples/ipv6/json-ws/Makefile
Normal file
30
examples/ipv6/json-ws/Makefile
Normal file
|
@ -0,0 +1,30 @@
|
|||
CONTIKI=../../..
|
||||
|
||||
WITH_UIP6=1
|
||||
UIP_CONF_IPV6=1
|
||||
SMALL=1
|
||||
|
||||
PROJECT_SOURCEFILES += json-ws.c
|
||||
|
||||
ifdef WITH_COSM
|
||||
CFLAGS += -DWITH_COSM=1
|
||||
endif
|
||||
|
||||
ifdef WITH_UDP
|
||||
CFLAGS += -DWITH_UDP=1
|
||||
PROJECT_SOURCEFILES += json-ws-udp.c
|
||||
endif
|
||||
|
||||
APPS += httpd-ws json
|
||||
|
||||
CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\"
|
||||
|
||||
ifeq ($(TARGET),)
|
||||
-include Makefile.target
|
||||
endif
|
||||
|
||||
ifneq ($(TARGET),)
|
||||
all: websense-$(TARGET)
|
||||
endif
|
||||
|
||||
include $(CONTIKI)/Makefile.include
|
106
examples/ipv6/json-ws/README-COSM.txt
Normal file
106
examples/ipv6/json-ws/README-COSM.txt
Normal file
|
@ -0,0 +1,106 @@
|
|||
Short description on how to set-up a sensor network for global IPv6 addresses.
|
||||
NOTE: this assumes that you do not have a native IPv6 connection.
|
||||
|
||||
You will need:
|
||||
* PC with Ubuntu (Linux) - 11 or 12 versions
|
||||
* A node for the RPL-Border-Router (examples/ipv6/rpl-border-router)
|
||||
* A node for the json webservice (examples/ipv6/json-ws)
|
||||
|
||||
Set-up IPv6 tunnel and Border Router
|
||||
------------------------------------
|
||||
1. Ensure that you have gogo6c installed.
|
||||
|
||||
> sudo apt-get install gogoc
|
||||
|
||||
2. Register an account at gogo6 and Freenet6 (http://www.gogo6.com).
|
||||
The account at Freenet6 is needed by the gogo6c client.
|
||||
|
||||
3. Edit the gogoc.conf and set your own Freenet6 user and password by
|
||||
changing the lines with "userid" and "passwd".
|
||||
|
||||
4. Start gogoc at command line
|
||||
|
||||
> cd contiki/examples/ipv6/json-ws
|
||||
> sudo gogoc -f gogoc.conf -n
|
||||
|
||||
This will print your prefix - TSP_PREFIX.
|
||||
In my case TSP_PREFIX=2001:05c0:1517:e400 (prefixlen is 56).
|
||||
|
||||
5. Connect one of the nodes to the PC (via USB or serial) and program
|
||||
it with the RPL-border-router (assumes Z1 node).
|
||||
|
||||
> cd contiki/examples/ipv6/rpl-border-router
|
||||
> make DEFINES=DEFINES=NETSTACK_RDC=nullrdc_driver,NULLRDC_CONF_802154_AUTOACK=1 TARGET=z1 border-router.upload
|
||||
|
||||
6. Run tunslip6 which will forward IP from the RPL network to
|
||||
the IPv6 tunnel (and to the Internet).
|
||||
|
||||
> cd contiki/examples/ipv6/rpl-border-router
|
||||
> make connect-router PREFIX=<TSP_PREFIX>::1/64
|
||||
|
||||
When you start this you should get a printout from the border-router
|
||||
which give you the IPv6 address of it.
|
||||
|
||||
Server IPv6 addresses:
|
||||
2001:05c0:1517:e400:c30c::10a
|
||||
fe80::c30c:0:0:10a
|
||||
|
||||
7. Browse using Mozilla Firefox (or any other browser) to the IPv6 address
|
||||
given by the border router. This will show you the list of other nodes
|
||||
connected to the RPL network.
|
||||
|
||||
http://[2001:05c0:1517:e400:c30c::10a]/
|
||||
|
||||
NOTE: this is a global IPv6 address so it should also be reachable from
|
||||
any machine on the Internet.
|
||||
|
||||
Configuration of COSM submission
|
||||
--------------------------------
|
||||
1. Register a COSM account at https://cosm.com/
|
||||
Set-up a feed and create an API key for the feed.
|
||||
|
||||
2. Program the sensor node with (assumes Z1)
|
||||
|
||||
> cd contiki/examples/ipv6/json-ws
|
||||
> make websense-z1.upload WITH_COSM=1 TARGET=z1
|
||||
|
||||
3. Check the IPv6 address of the node via the RPL-border router or
|
||||
by looking at printouts when booting (make login TARGET=z1)
|
||||
|
||||
4. You need to configure the node to push data to the COSM feed and
|
||||
this can be done in several ways. For convenience a Python script
|
||||
is included that pushes the configuration to the nodes.
|
||||
|
||||
Edit the file 'setcosm.py' and replace "<your-key>" and
|
||||
"<your-feed>" with your COSM API key and COSM feed id. You can then
|
||||
use this Python script to configure your nodes.
|
||||
|
||||
This is an example that configures the node with IP address
|
||||
2001:05c0:1517:e400:c30c::10b to push data to the COSM feed with
|
||||
stream 1:
|
||||
|
||||
> cd contiki/examples/ipv6/json-ws
|
||||
> ./setcosm.py [2001:05c0:1517:e400:c30c::10b] 1
|
||||
|
||||
Another way to configure the nodes is to use a REST add-on for the
|
||||
web browser to post a COSM configuration to the node. "REST Client"
|
||||
for Mozilla Firefox is an example of such add-on.
|
||||
|
||||
POST a JSON expression to your node with the following data:
|
||||
This assumes that you have the feed with id 55180 and want to post
|
||||
to stream 1 in that feed. The field 'appdata' should be set to the
|
||||
API key you created at the COSM web site for the feed.
|
||||
|
||||
{
|
||||
"host":"[2001:470:1f10:333::2]",
|
||||
"port":80,
|
||||
"path":"/v2/feeds/55180/datastreams/1",
|
||||
"appdata":"<insert your COSM API key>",
|
||||
"interval":120,
|
||||
"proto":"cosm"
|
||||
}
|
||||
|
||||
This will configure the node to periodically push temperature data
|
||||
every other minute. You can use GET to retrieve the data to se that
|
||||
the node has been successfully configured (the COSM API key will be
|
||||
visualized as a number of stars).
|
351
examples/ipv6/json-ws/gogoc.conf
Normal file
351
examples/ipv6/json-ws/gogoc.conf
Normal file
|
@ -0,0 +1,351 @@
|
|||
#-----------------------------------------------------------------------------
|
||||
# $Id: gogoc.conf.in,v 1.1 2009/11/20 16:53:12 jasminko Exp $
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
########################## READ ME! ################################
|
||||
#
|
||||
# Welcome to the gogoCLIENT configuration file.
|
||||
# In order to use the client, you need to modify the 'userid', 'passwd' and
|
||||
# 'server' parameters below depending on which of these situations applies:
|
||||
#
|
||||
# 1. If you created a Freenet6 account, enter your userid and password below.
|
||||
# Change the server name to "broker.freenet6.net" and auth_method to 'any'.
|
||||
# 2. If you would like to use Freenet6 without creating an account,
|
||||
# do not make any modifications and close this file.
|
||||
# 3. If this software was provided by your ISP, enter the userid, password and
|
||||
# server name provided by your ISP below.
|
||||
#
|
||||
|
||||
|
||||
########################## BASIC CONFIGURATION ################################
|
||||
|
||||
#
|
||||
# User Identification and Password:
|
||||
# Specify your user name and password as provided by your ISP or Freenet6.
|
||||
# If you plan to connect anonymously, leave these values empty.
|
||||
# NOTE: Change auth_method option if you are using a username/password.
|
||||
#
|
||||
# userid=<your_userid>
|
||||
# passwd=<your_password>
|
||||
#
|
||||
userid=<change to your userid>
|
||||
passwd=<change to your password>
|
||||
|
||||
#
|
||||
# gogoSERVER:
|
||||
# Specify a gogoSERVER name or IP address (provided by your ISP or
|
||||
# Freenet6). An optional port number can be added; the default port number
|
||||
# is 3653.
|
||||
#
|
||||
# Examples:
|
||||
# server=hostname # FQDN
|
||||
# server=A.B.C.D # IPv4 address
|
||||
# server=[X:X::X:X] # IPv6 address
|
||||
# server=hostname:port_number
|
||||
# server=A.B.C.D:port_number
|
||||
# server=[X:X::X:X]:port_number
|
||||
#
|
||||
# Freenet6 account holders should enter authenticated.freenet6.net,
|
||||
# otherwise use anonymous.freenet6.net.
|
||||
# Your ISP may provide you with a different server name.
|
||||
#
|
||||
#server=anonymous.freenet6.net
|
||||
#server=authenticated.freenet6.net
|
||||
server=amsterdam.freenet6.net
|
||||
|
||||
#
|
||||
# Authentication Method:
|
||||
#
|
||||
# auth_method=<{anonymous}|{any|passdss-3des-1|digest-md5|plain}>
|
||||
#
|
||||
# anonymous: Sends no username or password
|
||||
#
|
||||
# any: The most secure method will be used.
|
||||
# passdss-3des-1: The password is sent encrypted.
|
||||
# digest-md5: The password is sent encrypted.
|
||||
# plain: Both username and password are sent as plain text.
|
||||
#
|
||||
# Recommended values:
|
||||
# - any: If you are authenticating a username / password.
|
||||
# - anonymous: If you are connecting anonymously.
|
||||
#
|
||||
#auth_method=anonymous
|
||||
auth_method=any
|
||||
|
||||
|
||||
########################## ROUTING CONFIGURATION ##############################
|
||||
# Use these parameters when you wish the client to act as a router and provide
|
||||
# IPv6 connectivity to IPv6-capable devices on your network.
|
||||
|
||||
#
|
||||
# Local Host Type:
|
||||
# Change this value to 'router' to enable IPv6 advertisements.
|
||||
#
|
||||
# host_type=<host|router>
|
||||
#
|
||||
host_type=router
|
||||
#host
|
||||
|
||||
#
|
||||
# Prefix Length:
|
||||
# Length of the requested prefix. Valid values range between 0 and 64 when
|
||||
# using V6*V4 tunnel modes, and between 0 and 32 when using V4V6 tunnel mode.
|
||||
#
|
||||
# prefixlen=<integer>
|
||||
#
|
||||
prefixlen=64
|
||||
|
||||
#
|
||||
# Advertisement Interface Prefix:
|
||||
# Name of the interface that will be configured to send router advertisements.
|
||||
# This is an interface index on Windows (ex: 4) and a name on Linux
|
||||
# and BSD (ex: eth1 or fxp1).
|
||||
#
|
||||
# if_prefix=<interface name>
|
||||
#
|
||||
if_prefix=tun0
|
||||
|
||||
#
|
||||
# DNS Server:
|
||||
# A DNS server list to which the reverse prefix will be delegated. Servers
|
||||
# are separated by the colon(:) delimiter.
|
||||
#
|
||||
# Example: dns_server=ns1.domain:ns2.domain:ns3.domain
|
||||
#
|
||||
dns_server=
|
||||
|
||||
|
||||
######################### ADVANCED CONFIGURATION ##############################
|
||||
|
||||
#
|
||||
# gogoCLIENT Installation Directory:
|
||||
# Directory where the gogoCLIENT will be installed. This value has been
|
||||
# set during installation.
|
||||
#
|
||||
gogoc_dir=
|
||||
|
||||
#
|
||||
# Auto-Retry Connect, Retry Delay and Max Retry Delay:
|
||||
# When auto_retry_connect=yes, the gogoCLIENT will attempt to reconnect
|
||||
# after a disconnection occurred. The time to wait is 'retry_delay' and that
|
||||
# delay is doubled at every 3 failed consecutive reconnection attempt.
|
||||
# However, the wait delay will never exceed retry_delay_max.
|
||||
#
|
||||
#
|
||||
# auto_retry_connect=<yes|no>
|
||||
# retry_delay=<integer: 0..3600>
|
||||
# retry_delay_max=<integer: 0..3600>
|
||||
#
|
||||
# Recommended values: "yes", 30, 300
|
||||
#
|
||||
auto_retry_connect=yes
|
||||
retry_delay=30
|
||||
retry_delay_max=300
|
||||
|
||||
#
|
||||
# Keepalive Feature and Message Interval:
|
||||
# Indicates if and how often the client will send data to keep the tunnel
|
||||
# active.
|
||||
#
|
||||
# keepalive=<yes|no>
|
||||
# keepalive_interval=<integer>
|
||||
#
|
||||
# Recommended values: "yes" and 30
|
||||
#
|
||||
keepalive=yes
|
||||
keepalive_interval=30
|
||||
|
||||
#
|
||||
# Tunnel Encapsulation Mode:
|
||||
# v6v4: IPv6-in-IPv4 tunnel.
|
||||
# v6udpv4: IPv6-in-UDP-in-IPv4 tunnel (for clients behind a NAT).
|
||||
# v6anyv4: Lets the broker choose the best mode for IPv6 tunnel.
|
||||
# v4v6: IPv4-in-IPv6 tunnel.
|
||||
#
|
||||
# Recommended value: v6anyv4
|
||||
#
|
||||
tunnel_mode=v6anyv4
|
||||
|
||||
#
|
||||
# Tunnel Interface Name:
|
||||
# The interface name assigned to the tunnel. This value is O/S dependent.
|
||||
#
|
||||
# if_tunnel_v6v4 is the tunnel interface name for v6v4 encapsulation mode
|
||||
# if_tunnel_v6udpv4 is the tunnel interface name for v6udpv4 encapsulate mode
|
||||
# if_tunnel_v4v6 is the tunnel interface name for v4v6 encapsulation mode
|
||||
#
|
||||
# Default values are set during installation.
|
||||
#
|
||||
if_tunnel_v6v4=sit1
|
||||
if_tunnel_v6udpv4=sit
|
||||
if_tunnel_v4v6=sit0
|
||||
|
||||
#
|
||||
# Local IP Address of the Client:
|
||||
# Allows you to set a specific address as the local tunnel endpoint.
|
||||
#
|
||||
# client_v4=<auto|A.B.C.D (valid ipv4 address)>
|
||||
# client_v6=<auto|X:X::X:X (valid ipv6 address)>
|
||||
# auto: The gogoCLIENT will find the local IP address endpoint.
|
||||
#
|
||||
# Recommended value: auto
|
||||
#
|
||||
client_v4=auto
|
||||
client_v6=auto
|
||||
|
||||
#
|
||||
# Script Name:
|
||||
# File name of the script to run to install the tunnel interface. The
|
||||
# scripts are located in the template directory under the client
|
||||
# installation directory.
|
||||
#
|
||||
# template=<checktunnel|freebsd|netbsd|openbsd|linux|windows|darwin|cisco|solaris>
|
||||
#
|
||||
# Default value is set during installation.
|
||||
#
|
||||
template=linux
|
||||
|
||||
#
|
||||
# Proxy client:
|
||||
# Indicates that this client will request a tunnel for another endpoint,
|
||||
# such as a Cisco router.
|
||||
#
|
||||
# proxy_client=<yes|no>
|
||||
#
|
||||
# NOTE: NAT traversal is not possible in proxy mode.
|
||||
#
|
||||
proxy_client=no
|
||||
|
||||
|
||||
############################ BROKER REDIRECTION ###############################
|
||||
|
||||
#
|
||||
# Broker List File Name:
|
||||
# The 'broker_list' directive specifies the filename where the broker
|
||||
# list received during broker redirection will be saved.
|
||||
#
|
||||
# broker_list=<file_name>
|
||||
#
|
||||
broker_list=/var/lib/gogoc/tsp-broker-list.txt
|
||||
|
||||
#
|
||||
# Last Server Used File Name:
|
||||
# The 'last_server' directive specifies the filename where the address of
|
||||
# the last broker to which a connection was successfully established will
|
||||
# be saved.
|
||||
#
|
||||
# last_server=<file_name>
|
||||
#
|
||||
last_server=/var/lib/gogoc/tsp-last-server.txt
|
||||
|
||||
#
|
||||
# Always Use Last Known Working Server:
|
||||
# The value of the 'always_use_same_server' directive determines whether the
|
||||
# client should always try to connect to the broker found in the
|
||||
# 'last_server' directive filename.
|
||||
#
|
||||
# always_use_same_server=<yes|no>
|
||||
#
|
||||
always_use_same_server=no
|
||||
|
||||
|
||||
#################################### LOGGING ##################################
|
||||
|
||||
#
|
||||
# Log Verbosity Configuration:
|
||||
# The format is 'log_<destination>=level', where possible values for
|
||||
# 'destination' are:
|
||||
#
|
||||
# - console (logging to the console [AKA stdout])
|
||||
# - stderr (logging to standard error)
|
||||
# - file (logging to a file)
|
||||
# - syslog (logging to syslog [Unix only])
|
||||
#
|
||||
# and 'level' is a digit between 0 and 3. A 'level' value of 0 disables
|
||||
# logging to the destination, while values 1 to 3 request increasing levels
|
||||
# of log verbosity and detail. If 'level' is not specified, a value of 1 is
|
||||
# assumed.
|
||||
#
|
||||
# Example:
|
||||
# log_file=3 (Maximal logging to a file)
|
||||
# log_stderr=0 (Logging to standard error disabled)
|
||||
# log_console= (Minimal logging to the console)
|
||||
#
|
||||
# - Default configuration on Windows platforms:
|
||||
#
|
||||
# log_console=0
|
||||
# log_stderr=0
|
||||
# log_file=1
|
||||
#
|
||||
# - Default configuration on Unix platforms:
|
||||
#
|
||||
# log_console=0
|
||||
# log_stderr=1
|
||||
# log_file=0
|
||||
# log_syslog=0
|
||||
#
|
||||
log_console=3
|
||||
log_stderr=0
|
||||
#log_file=
|
||||
#log_syslog=
|
||||
|
||||
#
|
||||
# Log File Name:
|
||||
# When logging to file is requested using the 'log_file' directive, the name
|
||||
# and path of the file to use may be specified using this directive.
|
||||
#
|
||||
# log_filename=<file_name>
|
||||
#
|
||||
log_filename=/var/log/gogoc/gogoc.log
|
||||
|
||||
#
|
||||
# Log File Rotation:
|
||||
# When logging to file is requested using the 'log_file' directive, log file
|
||||
# rotation may be enabled. When enabled, the contents of the log file will
|
||||
# be moved to a backup file just before it reaches the maximum log file size
|
||||
# specified via this directive.
|
||||
#
|
||||
# The name of the backup file is the name of the original log file with
|
||||
# '.<timestamp>' inserted before the file extension. If the file does not
|
||||
# have an extension, '.<timestamp>' is appended to the name of the original
|
||||
# log file. The timestamp specifies when the rotation occurred.
|
||||
#
|
||||
# After the contents of the log file have been moved to the backup file, the
|
||||
# original file is cleared, and logging resumes at the beginning of the file.
|
||||
#
|
||||
# log_rotation=<yes|no>
|
||||
#
|
||||
log_rotation=yes
|
||||
|
||||
#
|
||||
# Log File Rotation Size:
|
||||
# The 'log_rotation_size' directive specifies the maximum size a log file may
|
||||
# reach before rotation occurs, if enabled. The value is expressed in
|
||||
# kilobytes.
|
||||
#
|
||||
# log_rotation_size=<16|32|128|1024>
|
||||
#
|
||||
log_rotation_size=32
|
||||
|
||||
#
|
||||
# Deletion of rotated log files:
|
||||
# The 'log_rotation_delete' directive specifies that no log backup will be
|
||||
# kept. When rotation occurs, the file is immediately wiped out and a new
|
||||
# log file is started.
|
||||
#
|
||||
# log_rotation_delete=<yes|no>
|
||||
#
|
||||
log_rotation_delete=no
|
||||
|
||||
#
|
||||
# Syslog Logging Facility [Unix Only]:
|
||||
# When logging to syslog is requested using the 'log_syslog' directive, the
|
||||
# facility to use may be specified using this directive.
|
||||
#
|
||||
# syslog_facility=<USER|LOCAL[0-7]>
|
||||
#
|
||||
syslog_facility=USER
|
||||
|
||||
|
||||
# end of gogoc.conf
|
||||
#------------------------------------------------------------------------------
|
154
examples/ipv6/json-ws/json-ws-udp.c
Normal file
154
examples/ipv6/json-ws/json-ws-udp.c
Normal file
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2012, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: dmacro.dm,v 1.11 2006/03/18 19:43:52 nfi Exp $
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Code for sending the JSON data as a UDP packet
|
||||
* Specify proto = "udp", port = <server-udp-port>
|
||||
* host = <ipv6-server-address>
|
||||
*
|
||||
* \author
|
||||
* Niclas Finne <nfi@sics.se>
|
||||
* Joakim Eriksson <joakime@sics.se>
|
||||
*/
|
||||
|
||||
#include "contiki.h"
|
||||
#include "httpd-ws.h"
|
||||
#include "jsontree.h"
|
||||
#include "jsonparse.h"
|
||||
#include "json-ws.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DEBUG DEBUG_FULL
|
||||
#include "net/uip-debug.h"
|
||||
|
||||
static struct uip_udp_conn *client_conn;
|
||||
static uip_ipaddr_t server_ipaddr;
|
||||
static uint16_t server_port;
|
||||
|
||||
#define SENDER_PORT 8181
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
json_ws_udp_setup(const char *host, uint16_t port)
|
||||
{
|
||||
|
||||
server_port = port;
|
||||
|
||||
if(client_conn != NULL) {
|
||||
/* this should be a macro uip_udp_conn_free() or something */
|
||||
uip_udp_remove(client_conn);
|
||||
client_conn = NULL;
|
||||
}
|
||||
|
||||
uip_ipaddr_t *ipaddr;
|
||||
|
||||
/* First check if the host is an IP address. */
|
||||
ipaddr = &server_ipaddr;
|
||||
if(uiplib_ipaddrconv(host, &server_ipaddr) == 0) {
|
||||
#if 0 && UIP_UDP
|
||||
ipaddr = resolv_lookup(host);
|
||||
|
||||
if(ipaddr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
#else /* UIP_UDP */
|
||||
return 0;
|
||||
#endif /* UIP_UDP */
|
||||
}
|
||||
|
||||
/* new connection with remote host */
|
||||
client_conn = udp_new(&server_ipaddr, UIP_HTONS(server_port), NULL);
|
||||
udp_bind(client_conn, UIP_HTONS(SENDER_PORT));
|
||||
|
||||
PRINTF("Created a connection with the server ");
|
||||
PRINT6ADDR(&client_conn->ripaddr);
|
||||
PRINTF(" local/remote port %u/%u\n",
|
||||
UIP_HTONS(client_conn->lport), UIP_HTONS(client_conn->rport));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
static char *udp_buf;
|
||||
static int pos;
|
||||
static int size;
|
||||
|
||||
static int
|
||||
putchar_udp(int c)
|
||||
{
|
||||
if(udp_buf != NULL && pos <= size) {
|
||||
udp_buf[pos++] = c;
|
||||
return c;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
json_ws_udp_send(struct jsontree_value *tree, const char *path)
|
||||
{
|
||||
struct jsontree_context json;
|
||||
/* maxsize = 70 bytes */
|
||||
char buf[70];
|
||||
|
||||
udp_buf = buf;
|
||||
|
||||
/* reset state and set max-size */
|
||||
/* NOTE: packet will be truncated at 70 bytes */
|
||||
pos = 0;
|
||||
size = sizeof(buf);
|
||||
|
||||
json.values[0] = (struct json_value *)tree;
|
||||
jsontree_reset(&json);
|
||||
find_json_path(&json, path);
|
||||
json.path = json.depth;
|
||||
json.putchar = putchar_udp;
|
||||
while(jsontree_print_next(&json) && json.path <= json.depth);
|
||||
|
||||
printf("Real UDP size: %d\n", pos);
|
||||
buf[pos] = 0;
|
||||
|
||||
uip_udp_packet_sendto(client_conn, &buf, pos,
|
||||
&server_ipaddr, UIP_HTONS(server_port));
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
json_ws_udp_debug(char *string)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = strlen(string);
|
||||
uip_udp_packet_sendto(client_conn, string, len,
|
||||
&server_ipaddr, UIP_HTONS(server_port));
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
521
examples/ipv6/json-ws/json-ws.c
Normal file
521
examples/ipv6/json-ws/json-ws.c
Normal file
|
@ -0,0 +1,521 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2012, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* JSON webservice util
|
||||
* \author
|
||||
* Niclas Finne <nfi@sics.se>
|
||||
* Joakim Eriksson <joakime@sics.se>
|
||||
* Joel Hoglund <joel@sics.se>
|
||||
*/
|
||||
|
||||
#include "contiki.h"
|
||||
#if PLATFORM_HAS_LEDS
|
||||
#include "dev/leds.h"
|
||||
#endif
|
||||
#include "httpd-ws.h"
|
||||
#include "jsontree.h"
|
||||
#include "jsonparse.h"
|
||||
#include "json-ws.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
#define PRINTF(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define PRINTF(...)
|
||||
#endif
|
||||
|
||||
#ifdef JSON_WS_CONF_CALLBACK_PROTO
|
||||
#define CALLBACK_PROTO JSON_WS_CONF_CALLBACK_PROTO
|
||||
#else
|
||||
#define CALLBACK_PROTO "http"
|
||||
#endif /* JSON_WS_CONF_CALLBACK_PROTO */
|
||||
|
||||
#ifdef JSON_WS_CONF_CALLBACK_PORT
|
||||
#define CALLBACK_PORT JSON_WS_CONF_CALLBACK_PORT
|
||||
#else
|
||||
#define CALLBACK_PORT 8080;
|
||||
#endif /* JSON_WS_CONF_CALLBACK_PORT */
|
||||
|
||||
/* Predefined startup-send interval */
|
||||
#ifdef JSON_WS_CONF_CALLBACK_INTERVAL
|
||||
#define SEND_INTERVAL JSON_WS_CONF_CALLBACK_INTERVAL
|
||||
#else
|
||||
#define SEND_INTERVAL 120
|
||||
#endif
|
||||
|
||||
static const char http_content_type_json[] = "application/json";
|
||||
|
||||
/* Maximum 40 chars in host name?: 5 x 8 */
|
||||
static char callback_host[40] = "[aaaa::1]";
|
||||
static uint16_t callback_port = CALLBACK_PORT;
|
||||
static uint16_t callback_interval = SEND_INTERVAL;
|
||||
static char callback_path[80] = "/debug/";
|
||||
static char callback_appdata[80] = "";
|
||||
static char callback_proto[8] = CALLBACK_PROTO;
|
||||
static const char *callback_json_path = NULL;
|
||||
static struct jsontree_object *tree;
|
||||
static struct ctimer periodic_timer;
|
||||
long json_time_offset = 0;
|
||||
|
||||
/* support for submitting to cosm */
|
||||
#if WITH_COSM
|
||||
extern struct jsontree_callback cosm_value_callback;
|
||||
|
||||
JSONTREE_OBJECT_EXT(cosm_tree,
|
||||
JSONTREE_PAIR("current_value", &cosm_value_callback));
|
||||
#endif /* WITH_COSM */
|
||||
|
||||
static void periodic(void *ptr);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
json_copy_string(struct jsonparse_state *parser, char *string, int len)
|
||||
{
|
||||
jsonparse_next(parser);
|
||||
jsonparse_next(parser);
|
||||
jsonparse_copy_value(parser, string, len);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
cfg_get(struct jsontree_context *js_ctx)
|
||||
{
|
||||
const char *path = jsontree_path_name(js_ctx, js_ctx->depth - 1);
|
||||
|
||||
if(strncmp(path, "host", 4) == 0) {
|
||||
jsontree_write_string(js_ctx, callback_host);
|
||||
} else if(strncmp(path, "port", 4) == 0) {
|
||||
jsontree_write_int(js_ctx, callback_port);
|
||||
} else if(strncmp(path, "interval", 8) == 0) {
|
||||
jsontree_write_int(js_ctx, callback_interval);
|
||||
} else if(strncmp(path, "path", 4) == 0) {
|
||||
jsontree_write_string(js_ctx, callback_path);
|
||||
} else if(strncmp(path, "appdata", 7) == 0) {
|
||||
jsontree_write_string(js_ctx, callback_appdata[0] == '\0' ? "" : "***");
|
||||
} else if(strncmp(path, "proto", 5) == 0) {
|
||||
jsontree_write_string(js_ctx, callback_proto);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int
|
||||
cfg_set(struct jsontree_context *js_ctx, struct jsonparse_state *parser)
|
||||
{
|
||||
int type;
|
||||
int update = 0;
|
||||
|
||||
while((type = jsonparse_next(parser)) != 0) {
|
||||
if(type == JSON_TYPE_PAIR_NAME) {
|
||||
if(jsonparse_strcmp_value(parser, "host") == 0) {
|
||||
json_copy_string(parser, callback_host, sizeof(callback_host));
|
||||
update++;
|
||||
} else if(jsonparse_strcmp_value(parser, "path") == 0) {
|
||||
json_copy_string(parser, callback_path, sizeof(callback_path));
|
||||
update++;
|
||||
} else if(jsonparse_strcmp_value(parser, "appdata") == 0) {
|
||||
json_copy_string(parser, callback_appdata, sizeof(callback_appdata));
|
||||
update++;
|
||||
} else if(jsonparse_strcmp_value(parser, "proto") == 0) {
|
||||
json_copy_string(parser, callback_proto, sizeof(callback_proto));
|
||||
update++;
|
||||
} else if(jsonparse_strcmp_value(parser, "port") == 0) {
|
||||
jsonparse_next(parser);
|
||||
jsonparse_next(parser);
|
||||
callback_port = jsonparse_get_value_as_int(parser);
|
||||
if(callback_port == 0) {
|
||||
callback_port = CALLBACK_PORT;
|
||||
}
|
||||
update++;
|
||||
} else if(jsonparse_strcmp_value(parser, "interval") == 0) {
|
||||
jsonparse_next(parser);
|
||||
jsonparse_next(parser);
|
||||
callback_interval = jsonparse_get_value_as_int(parser);
|
||||
if(callback_interval == 0) {
|
||||
callback_interval = SEND_INTERVAL;
|
||||
}
|
||||
update++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(update && callback_json_path != NULL) {
|
||||
#if WITH_UDP
|
||||
if(strncmp(callback_proto, "udp", 3) == 0) {
|
||||
json_ws_udp_setup(callback_host, callback_port);
|
||||
}
|
||||
#endif
|
||||
ctimer_set(&periodic_timer, CLOCK_SECOND * callback_interval,
|
||||
periodic, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static struct jsontree_callback cfg_callback =
|
||||
JSONTREE_CALLBACK(cfg_get, cfg_set);
|
||||
|
||||
JSONTREE_OBJECT_EXT(json_subscribe_callback,
|
||||
JSONTREE_PAIR("host", &cfg_callback),
|
||||
JSONTREE_PAIR("port", &cfg_callback),
|
||||
JSONTREE_PAIR("path", &cfg_callback),
|
||||
JSONTREE_PAIR("appdata", &cfg_callback),
|
||||
JSONTREE_PAIR("proto", &cfg_callback),
|
||||
JSONTREE_PAIR("interval", &cfg_callback));
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
time_get(struct jsontree_context *js_ctx)
|
||||
{
|
||||
/* unix time */
|
||||
char buf[20];
|
||||
unsigned long time = json_time_offset + clock_seconds();
|
||||
|
||||
snprintf(buf, 20, "%lu", time);
|
||||
jsontree_write_atom(js_ctx, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
time_set(struct jsontree_context *js_ctx, struct jsonparse_state *parser)
|
||||
{
|
||||
int type;
|
||||
unsigned long time;
|
||||
|
||||
while((type = jsonparse_next(parser)) != 0) {
|
||||
if(type == JSON_TYPE_PAIR_NAME) {
|
||||
if(jsonparse_strcmp_value(parser, "time") == 0) {
|
||||
jsonparse_next(parser);
|
||||
jsonparse_next(parser);
|
||||
time = jsonparse_get_value_as_long(parser);
|
||||
json_time_offset = time - clock_seconds();
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct jsontree_callback json_time_callback =
|
||||
JSONTREE_CALLBACK(time_get, time_set);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if PLATFORM_HAS_LEDS
|
||||
#include "dev/leds.h"
|
||||
|
||||
static int
|
||||
ws_leds_get(struct jsontree_context *js_ctx)
|
||||
{
|
||||
char buf[4];
|
||||
unsigned char leds = leds_get();
|
||||
|
||||
snprintf(buf, 4, "%u", leds);
|
||||
jsontree_write_atom(js_ctx, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ws_leds_set(struct jsontree_context *js_ctx, struct jsonparse_state *parser)
|
||||
{
|
||||
int type, old_leds, new_leds;
|
||||
|
||||
while((type = jsonparse_next(parser)) != 0) {
|
||||
if(type == JSON_TYPE_PAIR_NAME) {
|
||||
if(jsonparse_strcmp_value(parser, "leds") == 0) {
|
||||
jsonparse_next(parser);
|
||||
jsonparse_next(parser);
|
||||
new_leds = jsonparse_get_value_as_int(parser);
|
||||
old_leds = leds_get();
|
||||
leds_on(~old_leds & new_leds);
|
||||
leds_off(old_leds & ~new_leds);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct jsontree_callback json_leds_callback =
|
||||
JSONTREE_CALLBACK(ws_leds_get, ws_leds_set);
|
||||
|
||||
#endif /* PLATFORM_HAS_LEDS */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static struct httpd_ws_state *json_putchar_context;
|
||||
static int
|
||||
json_putchar(int c)
|
||||
{
|
||||
if(json_putchar_context != NULL &&
|
||||
json_putchar_context->outbuf_pos < HTTPD_OUTBUF_SIZE) {
|
||||
json_putchar_context->outbuf[json_putchar_context->outbuf_pos++] = c;
|
||||
return c;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int putchar_size = 0;
|
||||
static int
|
||||
json_putchar_count(int c)
|
||||
{
|
||||
putchar_size++;
|
||||
return c;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static
|
||||
PT_THREAD(send_values(struct httpd_ws_state *s))
|
||||
{
|
||||
json_putchar_context = s;
|
||||
|
||||
PSOCK_BEGIN(&s->sout);
|
||||
|
||||
s->json.putchar = json_putchar;
|
||||
s->outbuf_pos = 0;
|
||||
|
||||
if(s->json.values[0] == NULL) {
|
||||
/* Nothing to do */
|
||||
|
||||
} else if(s->request_type == HTTPD_WS_POST &&
|
||||
s->state == HTTPD_WS_STATE_OUTPUT) {
|
||||
/* Set value */
|
||||
struct jsontree_value *v;
|
||||
struct jsontree_callback *c;
|
||||
|
||||
while((v = jsontree_find_next(&s->json, JSON_TYPE_CALLBACK)) != NULL) {
|
||||
c = (struct jsontree_callback *)v;
|
||||
if(c->set != NULL) {
|
||||
struct jsonparse_state js;
|
||||
|
||||
jsonparse_setup(&js, s->inputbuf, s->content_len);
|
||||
c->set(&s->json, &js);
|
||||
}
|
||||
}
|
||||
memcpy(s->outbuf, "{\"Status\":\"OK\"}", 15);
|
||||
s->outbuf_pos = 15;
|
||||
|
||||
} else {
|
||||
/* Get value */
|
||||
while(jsontree_print_next(&s->json) && s->json.path <= s->json.depth) {
|
||||
if(s->outbuf_pos >= UIP_TCP_MSS) {
|
||||
SEND_STRING(&s->sout, s->outbuf, UIP_TCP_MSS);
|
||||
s->outbuf_pos -= UIP_TCP_MSS;
|
||||
if(s->outbuf_pos > 0) {
|
||||
memcpy(s->outbuf, &s->outbuf[UIP_TCP_MSS], s->outbuf_pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(s->outbuf_pos > 0) {
|
||||
SEND_STRING(&s->sout, s->outbuf, s->outbuf_pos);
|
||||
s->outbuf_pos = 0;
|
||||
}
|
||||
PSOCK_END(&s->sout);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct jsontree_value *
|
||||
find_json_path(struct jsontree_context *json, const char *path)
|
||||
{
|
||||
struct jsontree_value *v;
|
||||
const char *start;
|
||||
const char *end;
|
||||
int len;
|
||||
|
||||
v = json->values[0];
|
||||
start = path;
|
||||
do {
|
||||
end = strchr(start, '/');
|
||||
if(end == start) {
|
||||
break;
|
||||
}
|
||||
if(end != NULL) {
|
||||
len = end - start;
|
||||
end++;
|
||||
} else {
|
||||
len = strlen(start);
|
||||
}
|
||||
if(v->type != JSON_TYPE_OBJECT) {
|
||||
v = NULL;
|
||||
} else {
|
||||
struct jsontree_object *o;
|
||||
int i;
|
||||
|
||||
o = (struct jsontree_object *)v;
|
||||
v = NULL;
|
||||
for(i = 0; i < o->count; i++) {
|
||||
if(strncmp(start, o->pairs[i].name, len) == 0) {
|
||||
v = o->pairs[i].value;
|
||||
json->index[json->depth] = i;
|
||||
json->depth++;
|
||||
json->values[json->depth] = v;
|
||||
json->index[json->depth] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
start = end;
|
||||
} while(end != NULL && *end != '\0' && v != NULL);
|
||||
json->callback_state = 0;
|
||||
return v;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
calculate_json_size(const char *path, struct jsontree_value *v)
|
||||
{
|
||||
/* check size of JSON expression */
|
||||
struct jsontree_context json;
|
||||
|
||||
json.values[0] = (v == NULL) ? (struct jsontree_value *)tree : v;
|
||||
jsontree_reset(&json);
|
||||
|
||||
if(path != NULL) {
|
||||
find_json_path(&json, path);
|
||||
}
|
||||
|
||||
json.path = json.depth;
|
||||
json.putchar = json_putchar_count;
|
||||
putchar_size = 0;
|
||||
while(jsontree_print_next(&json) && json.path <= json.depth);
|
||||
|
||||
return putchar_size;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
httpd_ws_script_t
|
||||
httpd_ws_get_script(struct httpd_ws_state *s)
|
||||
{
|
||||
struct jsontree_value *v;
|
||||
|
||||
s->json.values[0] = v = (struct jsontree_value *)tree;
|
||||
jsontree_reset(&s->json);
|
||||
|
||||
if(s->filename[1] == '\0') {
|
||||
/* Default page: show full JSON tree. */
|
||||
} else {
|
||||
v = find_json_path(&s->json, &s->filename[1]);
|
||||
}
|
||||
if(v != NULL) {
|
||||
s->json.path = s->json.depth;
|
||||
s->content_type = http_content_type_json;
|
||||
return send_values;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if JSON_POST_EXTRA_HEADER || WITH_COSM
|
||||
static int
|
||||
output_headers(struct httpd_ws_state *s, char *buffer, int buffer_size,
|
||||
int index)
|
||||
{
|
||||
if(index == 0) {
|
||||
#ifdef JSON_POST_EXTRA_HEADER
|
||||
return snprintf(buffer, buffer_size, "%s\r\n", JSON_POST_EXTRA_HEADER);
|
||||
} else if(index == 1) {
|
||||
#endif
|
||||
#if WITH_COSM
|
||||
if(strncmp(callback_proto, "cosm", 4) == 0 && callback_appdata[0] != '\0') {
|
||||
return snprintf(buffer, buffer_size, "X-PachubeApiKey:%s\r\n",
|
||||
callback_appdata);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* JSON_POST_EXTRA_HEADER || WITH_COSM */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
periodic(void *ptr)
|
||||
{
|
||||
struct httpd_ws_state *s;
|
||||
int callback_size;
|
||||
|
||||
if(callback_json_path != NULL && strlen(callback_host) > 2) {
|
||||
ctimer_restart(&periodic_timer);
|
||||
|
||||
if(strncmp(callback_proto, "http", 4) == 0) {
|
||||
callback_size = calculate_json_size(callback_json_path, NULL);
|
||||
s = httpd_ws_request(HTTPD_WS_POST, callback_host, NULL, callback_port,
|
||||
callback_path, http_content_type_json,
|
||||
callback_size, send_values);
|
||||
if(s != NULL) {
|
||||
PRINTF("PERIODIC POST %s\n", callback_json_path);
|
||||
#if JSON_POST_EXTRA_HEADER
|
||||
s->output_extra_headers = output_headers;
|
||||
#endif
|
||||
s->json.values[0] = (struct jsontree_value *)tree;
|
||||
jsontree_reset(&s->json);
|
||||
find_json_path(&s->json, callback_json_path);
|
||||
s->json.path = s->json.depth;
|
||||
} else {
|
||||
PRINTF("PERIODIC CALLBACK FAILED\n");
|
||||
}
|
||||
#if WITH_COSM
|
||||
} else if(strncmp(callback_proto, "cosm", 4) == 0) {
|
||||
callback_size = calculate_json_size(NULL, (struct jsontree_value *)
|
||||
&cosm_tree);
|
||||
/* printf("JSON Size:%d\n", callback_size); */
|
||||
s = httpd_ws_request(HTTPD_WS_PUT, callback_host, "api.pachube.com",
|
||||
callback_port, callback_path,
|
||||
http_content_type_json, callback_size, send_values);
|
||||
/* host = cosm host */
|
||||
/* path => path to datastream / data point */
|
||||
s->output_extra_headers = output_headers;
|
||||
s->json.values[0] = (struct jsontree_value *)&cosm_tree;
|
||||
jsontree_reset(&s->json);
|
||||
s->json.path = 0;
|
||||
|
||||
PRINTF("PERIODIC cosm callback: %d\n", callback_size);
|
||||
#endif /* WITH_COSM */
|
||||
}
|
||||
#if WITH_UDP
|
||||
else {
|
||||
callback_size = calculate_json_size(callback_json_path, NULL);
|
||||
PRINTF("PERIODIC UDP size: %d\n", callback_size);
|
||||
json_ws_udp_send(tree, callback_json_path);
|
||||
}
|
||||
#endif /* WITH_UDP */
|
||||
} else {
|
||||
printf("PERIODIC CALLBACK - nothing todo\n");
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
json_ws_init(struct jsontree_object *json)
|
||||
{
|
||||
PRINTF("JSON INIT (callback %s every %u seconds)\n",
|
||||
CALLBACK_PROTO, SEND_INTERVAL);
|
||||
tree = json;
|
||||
ctimer_set(&periodic_timer, CLOCK_SECOND * SEND_INTERVAL, periodic, NULL);
|
||||
process_start(&httpd_ws_process, NULL);
|
||||
#if WITH_UDP
|
||||
if(strncmp(callback_proto, "udp", 3) == 0) {
|
||||
json_ws_udp_setup(callback_host, callback_port);
|
||||
}
|
||||
#endif /* WITH_UDP */
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
json_ws_set_callback(const char *path)
|
||||
{
|
||||
callback_json_path = path;
|
||||
ctimer_restart(&periodic_timer);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2006, Swedish Institute of Computer Science.
|
||||
* Copyright (c) 2011-2012, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -26,34 +26,33 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: RandomIPDistributor.java,v 1.2 2009/02/18 12:07:19 fros4943 Exp $
|
||||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
package se.sics.cooja.ipdistributors;
|
||||
import java.util.Random;
|
||||
import java.util.Vector;
|
||||
import se.sics.cooja.*;
|
||||
|
||||
/**
|
||||
* Generates IP addresses randomly on the form 10.10.[1-20].[1-20].
|
||||
* Nothing prevents several motes from getting the same IP number.
|
||||
*
|
||||
* @author Fredrik Osterlind
|
||||
* \file
|
||||
* JSON webservice util
|
||||
* \author
|
||||
* Niclas Finne <nfi@sics.se>
|
||||
* Joakim Eriksson <joakime@sics.se>
|
||||
* Joel Hoglund <joel@sics.se>
|
||||
*/
|
||||
@ClassDescription("Random (10.10.?.?)")
|
||||
public class RandomIPDistributor extends IPDistributor {
|
||||
|
||||
private Random random = new Random(); /* Do not use main random generator for setup */
|
||||
#ifndef __JSON_WS_H__
|
||||
#define __JSON_WS_H__
|
||||
|
||||
/**
|
||||
* Creates a random IP distributor.
|
||||
* @param newMotes All motes which later will be assigned IP numbers.
|
||||
*/
|
||||
public RandomIPDistributor(Vector<Mote> newMotes) {
|
||||
}
|
||||
#include "jsontree.h"
|
||||
|
||||
public String getNextIPAddress() {
|
||||
return "" + 10 + "." + 10 + "." + (1+random.nextInt(20)) + "." + (1+random.nextInt(20));
|
||||
}
|
||||
void json_ws_init(struct jsontree_object *json);
|
||||
void json_ws_set_callback(const char *json_path);
|
||||
int json_ws_udp_setup(const char *host, uint16_t port);
|
||||
|
||||
}
|
||||
extern struct jsontree_object json_subscribe_callback;
|
||||
extern struct jsontree_callback json_time_callback;
|
||||
|
||||
#if PLATFORM_HAS_LEDS
|
||||
extern struct jsontree_callback json_leds_callback;
|
||||
#endif
|
||||
extern struct jsontree_object cosm_tree;
|
||||
|
||||
#endif /* __JSON_WS_H__ */
|
79
examples/ipv6/json-ws/project-conf.h
Normal file
79
examples/ipv6/json-ws/project-conf.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2012, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __PROJECT_CONF_H__
|
||||
#define __PROJECT_CONF_H__
|
||||
|
||||
#include "jsontree.h"
|
||||
#define HTTPD_WS_CONF_USER_STATE struct jsontree_context json
|
||||
|
||||
|
||||
/* #define JSON_WS_CONF_CALLBACK_PROTO "http" | "udp" | "cosm" */
|
||||
#define JSON_WS_CONF_CALLBACK_PROTO "http"
|
||||
#define JSON_WS_CONF_CALLBACK_PORT 80
|
||||
#define JSON_WS_CONF_CALLBACK_INTERVAL 120
|
||||
|
||||
#undef NETSTACK_CONF_RDC
|
||||
#define NETSTACK_CONF_RDC nullrdc_driver
|
||||
/* #define NETSTACK_CONF_RDC contikimac_driver */
|
||||
|
||||
#define CONTIKIMAC_CONF_MAX_PHASE_NEIGHBORS 7
|
||||
|
||||
#undef NULLRDC_CONF_802154_AUTOACK
|
||||
#define NULLRDC_CONF_802154_AUTOACK 1
|
||||
|
||||
/* Reduce code size */
|
||||
#undef ENERGEST_CONF_ON
|
||||
#define ENERGEST_CONF_ON 0
|
||||
|
||||
/* needs to be ~4 for fragmentation to work */
|
||||
#undef QUEUEBUF_CONF_NUM
|
||||
#define QUEUEBUF_CONF_NUM 4
|
||||
|
||||
#undef UIP_CONF_DS6_NBR_NBU
|
||||
#define UIP_CONF_DS6_NBR_NBU 7
|
||||
#undef UIP_CONF_DS6_ROUTE_NBU
|
||||
#define UIP_CONF_DS6_ROUTE_NBU 7
|
||||
|
||||
#undef UIP_CONF_BUFFER_SIZE
|
||||
#define UIP_CONF_BUFFER_SIZE 140
|
||||
|
||||
/* #undef UIP_CONF_RECEIVE_WINDOW */
|
||||
/* #define UIP_CONF_RECEIVE_WINDOW 35 */
|
||||
|
||||
#undef WEBSERVER_CONF_INBUF_SIZE
|
||||
#define WEBSERVER_CONF_INBUF_SIZE 200
|
||||
|
||||
#undef WEBSERVER_CONF_OUTBUF_SIZE
|
||||
#define WEBSERVER_CONF_OUTBUF_SIZE (UIP_TCP_MSS + 20 + 80)
|
||||
|
||||
#undef WEBSERVER_CONF_CFS_CONNS
|
||||
#define WEBSERVER_CONF_CFS_CONNS 3
|
||||
|
||||
#endif /* __PROJECT_CONF_H__ */
|
30
examples/ipv6/json-ws/setcosm.py
Executable file
30
examples/ipv6/json-ws/setcosm.py
Executable file
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# python set time code
|
||||
import httplib,sys
|
||||
|
||||
# edit the key and feed parameters to match your COSM account and feed
|
||||
key = "<your-key>"
|
||||
feed = "<your-feed>"
|
||||
cosmaddr = "[2001:470:1f10:333::2]"
|
||||
|
||||
print "JSON-WS COSM configuration utility\n Currently set to COSM feed: %s Key: '%s'" % (feed, key)
|
||||
if len(sys.argv) > 2:
|
||||
host = sys.argv[1]
|
||||
stream = sys.argv[2]
|
||||
else:
|
||||
print "Usage: ", sys.argv[0], "<host> <feed-id>"
|
||||
sys.exit()
|
||||
|
||||
print "Setting cosm config at:", host, " feed:", feed, " stream:",stream
|
||||
|
||||
conn = httplib.HTTPConnection(host)
|
||||
# NAT64 address =
|
||||
#conn.request("POST","", '{"host":"[2001:778:0:ffff:64:0:d834:e97a]","port":80,"path":"/v2/feeds/55180/datastreams/1","interval":120}')
|
||||
|
||||
requestData = '{"host":"%s","port":80,"path":"/v2/feeds/%s/datastreams/%s","appdata":"%s","interval":120,"proto":"cosm"}' % (cosmaddr, feed, stream, key)
|
||||
print "Posting to node: ", requestData
|
||||
conn.request("POST","", requestData)
|
||||
|
||||
res = conn.getresponse()
|
||||
print res.status, res.reason
|
130
examples/ipv6/json-ws/websense-sky.c
Normal file
130
examples/ipv6/json-ws/websense-sky.c
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2012, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Websense for Sky mote
|
||||
* \author
|
||||
* Niclas Finne <nfi@sics.se>
|
||||
* Joakim Eriksson <joakime@sics.se>
|
||||
* Joel Hoglund <joel@sics.se>
|
||||
*/
|
||||
|
||||
#include "contiki.h"
|
||||
#include "dev/leds.h"
|
||||
#include "dev/sht11-sensor.h"
|
||||
#include "jsontree.h"
|
||||
#include "json-ws.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
#define PRINTF(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define PRINTF(...)
|
||||
#endif
|
||||
|
||||
PROCESS(websense_process, "Websense (sky)");
|
||||
AUTOSTART_PROCESSES(&websense_process);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static CC_INLINE int
|
||||
get_temp(void)
|
||||
{
|
||||
return ((sht11_sensor.value(SHT11_SENSOR_TEMP) / 10) - 396) / 10;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
output_temp(struct jsontree_context *path)
|
||||
{
|
||||
char buf[5];
|
||||
snprintf(buf, sizeof(buf), "%3d", get_temp());
|
||||
jsontree_write_atom(path, buf);
|
||||
return 0;
|
||||
}
|
||||
static struct jsontree_callback temp_sensor_callback =
|
||||
JSONTREE_CALLBACK(output_temp, NULL);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
static struct jsontree_string desc = JSONTREE_STRING("Tmote Sky");
|
||||
static struct jsontree_string temp_unit = JSONTREE_STRING("Celcius");
|
||||
|
||||
JSONTREE_OBJECT(node_tree,
|
||||
JSONTREE_PAIR("node-type", &desc),
|
||||
JSONTREE_PAIR("time", &json_time_callback));
|
||||
|
||||
JSONTREE_OBJECT(temp_sensor_tree,
|
||||
JSONTREE_PAIR("unit", &temp_unit),
|
||||
JSONTREE_PAIR("value", &temp_sensor_callback));
|
||||
|
||||
JSONTREE_OBJECT(rsc_tree,
|
||||
JSONTREE_PAIR("temperature", &temp_sensor_tree),
|
||||
JSONTREE_PAIR("leds", &json_leds_callback));
|
||||
|
||||
/* complete node tree */
|
||||
JSONTREE_OBJECT(tree,
|
||||
JSONTREE_PAIR("node", &node_tree),
|
||||
JSONTREE_PAIR("rsc", &rsc_tree),
|
||||
JSONTREE_PAIR("cfg", &json_subscribe_callback));
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* for cosm plugin */
|
||||
#if WITH_COSM
|
||||
/* set COSM value callback to be the temp sensor */
|
||||
struct jsontree_callback cosm_value_callback =
|
||||
JSONTREE_CALLBACK(output_temp, NULL);
|
||||
#endif
|
||||
|
||||
PROCESS_THREAD(websense_process, ev, data)
|
||||
{
|
||||
static struct etimer timer;
|
||||
|
||||
PROCESS_BEGIN();
|
||||
|
||||
json_ws_init(&tree);
|
||||
|
||||
SENSORS_ACTIVATE(sht11_sensor);
|
||||
|
||||
json_ws_set_callback("rsc");
|
||||
|
||||
while(1) {
|
||||
/* Alive indication with the LED */
|
||||
etimer_set(&timer, CLOCK_SECOND * 5);
|
||||
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&timer));
|
||||
leds_on(LEDS_RED);
|
||||
etimer_set(&timer, CLOCK_SECOND / 8);
|
||||
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&timer));
|
||||
leds_off(LEDS_RED);
|
||||
}
|
||||
|
||||
PROCESS_END();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
136
examples/ipv6/json-ws/websense-z1.c
Normal file
136
examples/ipv6/json-ws/websense-z1.c
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2012, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Websense for Z1 mote
|
||||
* \author
|
||||
* Niclas Finne <nfi@sics.se>
|
||||
* Joakim Eriksson <joakime@sics.se>
|
||||
* Joel Hoglund <joel@sics.se>
|
||||
*/
|
||||
|
||||
#include "contiki.h"
|
||||
#include "dev/leds.h"
|
||||
#include "dev/tmp102.h"
|
||||
#include "dev/z1-phidgets.h"
|
||||
#include "lib/sensors.h"
|
||||
#include "jsontree.h"
|
||||
#include "json-ws.h"
|
||||
|
||||
/* It seems like there normally is an offset of some degrees for the tmp102 */
|
||||
#define TMP102_OFFSET -150
|
||||
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
#include <stdio.h>
|
||||
#define PRINTF(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define PRINTF(...)
|
||||
#endif
|
||||
|
||||
PROCESS(websense_process, "Websense (z1)");
|
||||
AUTOSTART_PROCESSES(&websense_process);
|
||||
|
||||
static int
|
||||
output_sensor(struct jsontree_context *path)
|
||||
{
|
||||
char buf[10];
|
||||
int tmp;
|
||||
int tmp2;
|
||||
|
||||
tmp = tmp102_read_temp_x100();
|
||||
tmp2 = tmp - TMP102_OFFSET;
|
||||
tmp = tmp2 / 100;
|
||||
|
||||
snprintf(buf, sizeof(buf), "%2d.%02d", tmp, tmp2 - (100 * tmp));
|
||||
jsontree_write_atom(path, buf);
|
||||
return 0;
|
||||
}
|
||||
static struct jsontree_callback sensor_callback =
|
||||
JSONTREE_CALLBACK(output_sensor, NULL);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
static struct jsontree_string desc = JSONTREE_STRING("Zolertia Z1");
|
||||
static struct jsontree_string unit = JSONTREE_STRING("Celcius");
|
||||
|
||||
JSONTREE_OBJECT(node_tree,
|
||||
JSONTREE_PAIR("node-type", &desc),
|
||||
JSONTREE_PAIR("time", &json_time_callback));
|
||||
|
||||
JSONTREE_OBJECT(sensor_tree,
|
||||
JSONTREE_PAIR("unit", &unit),
|
||||
JSONTREE_PAIR("value", &sensor_callback));
|
||||
|
||||
JSONTREE_OBJECT(rsc_tree,
|
||||
JSONTREE_PAIR("temperature", &sensor_tree),
|
||||
JSONTREE_PAIR("leds", &json_leds_callback));
|
||||
|
||||
/* complete node tree */
|
||||
JSONTREE_OBJECT(tree,
|
||||
JSONTREE_PAIR("node", &node_tree),
|
||||
JSONTREE_PAIR("rsc", &rsc_tree),
|
||||
JSONTREE_PAIR("cfg", &json_subscribe_callback));
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* for cosm plugin */
|
||||
#if WITH_COSM
|
||||
/* set COSM value callback to be the temp sensor */
|
||||
struct jsontree_callback cosm_value_callback =
|
||||
JSONTREE_CALLBACK(output_sensor, NULL);
|
||||
#endif
|
||||
|
||||
PROCESS_THREAD(websense_process, ev, data)
|
||||
{
|
||||
static struct etimer timer;
|
||||
|
||||
PROCESS_BEGIN();
|
||||
|
||||
json_ws_init(&tree);
|
||||
|
||||
tmp102_init();
|
||||
|
||||
json_ws_set_callback("rsc");
|
||||
|
||||
while(1) {
|
||||
/* Alive indication with the LED */
|
||||
etimer_set(&timer, CLOCK_SECOND * 5);
|
||||
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&timer));
|
||||
leds_on(LEDS_RED);
|
||||
etimer_set(&timer, CLOCK_SECOND / 8);
|
||||
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&timer));
|
||||
leds_off(LEDS_RED);
|
||||
}
|
||||
|
||||
PROCESS_END();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -34,13 +34,17 @@ APPS += $(WITH_WEBSERVER)
|
|||
CFLAGS += -DWEBSERVER=2
|
||||
endif
|
||||
|
||||
ifeq ($(PREFIX),)
|
||||
PREFIX = aaaa::1/64
|
||||
endif
|
||||
|
||||
include $(CONTIKI)/Makefile.include
|
||||
|
||||
$(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c
|
||||
(cd $(CONTIKI)/tools && $(MAKE) tunslip6)
|
||||
|
||||
connect-router: $(CONTIKI)/tools/tunslip6
|
||||
sudo $(CONTIKI)/tools/tunslip6 aaaa::1/64
|
||||
sudo $(CONTIKI)/tools/tunslip6 $(PREFIX)
|
||||
|
||||
connect-router-cooja: $(CONTIKI)/tools/tunslip6
|
||||
sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 aaaa::1/64
|
||||
sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 $(PREFIX)
|
||||
|
|
|
@ -37,6 +37,7 @@ import java.awt.Dimension;
|
|||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
|
@ -44,8 +45,10 @@ import javax.swing.Icon;
|
|||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextArea;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jdom.Element;
|
||||
|
||||
import se.sics.cooja.AbstractionLevelDescription;
|
||||
import se.sics.cooja.ClassDescription;
|
||||
import se.sics.cooja.GUI;
|
||||
|
@ -68,10 +71,10 @@ import se.sics.cooja.interfaces.Position;
|
|||
|
||||
/**
|
||||
* AVR-based MicaZ mote types emulated in Avrora.
|
||||
*
|
||||
*
|
||||
* @author Joakim Eriksson, Fredrik Osterlind
|
||||
*/
|
||||
@ClassDescription("MicaZ mote...")
|
||||
@ClassDescription("MicaZ mote")
|
||||
@AbstractionLevelDescription("Emulated level")
|
||||
public class MicaZMoteType implements MoteType {
|
||||
private static Logger logger = Logger.getLogger(MicaZMoteType.class);
|
||||
|
|
|
@ -31,13 +31,25 @@
|
|||
|
||||
package se.sics.cooja.mspmote;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Container;
|
||||
import java.awt.Image;
|
||||
import java.awt.MediaTracker;
|
||||
import java.awt.Toolkit;
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import javax.swing.*;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import se.sics.cooja.*;
|
||||
|
||||
import se.sics.cooja.AbstractionLevelDescription;
|
||||
import se.sics.cooja.ClassDescription;
|
||||
import se.sics.cooja.GUI;
|
||||
import se.sics.cooja.MoteInterface;
|
||||
import se.sics.cooja.MoteType;
|
||||
import se.sics.cooja.Simulation;
|
||||
import se.sics.cooja.dialogs.CompileContiki;
|
||||
import se.sics.cooja.dialogs.MessageList;
|
||||
import se.sics.cooja.dialogs.MessageList.MessageContainer;
|
||||
|
@ -53,7 +65,7 @@ import se.sics.cooja.mspmote.interfaces.MspMoteID;
|
|||
import se.sics.cooja.mspmote.interfaces.MspSerial;
|
||||
import se.sics.cooja.mspmote.interfaces.TR1001Radio;
|
||||
|
||||
@ClassDescription("ESB mote...")
|
||||
@ClassDescription("ESB mote")
|
||||
@AbstractionLevelDescription("Emulated level")
|
||||
public class ESBMoteType extends MspMoteType {
|
||||
private static Logger logger = Logger.getLogger(ESBMoteType.class);
|
||||
|
@ -209,7 +221,7 @@ public class ESBMoteType extends MspMoteType {
|
|||
|
||||
return new File(parentDir, sourceNoExtension + ".esb");
|
||||
}
|
||||
|
||||
|
||||
protected String getTargetName() {
|
||||
return "esb";
|
||||
}
|
||||
|
|
|
@ -56,13 +56,13 @@ import se.sics.cooja.interfaces.MoteAttributes;
|
|||
import se.sics.cooja.interfaces.Position;
|
||||
import se.sics.cooja.interfaces.RimeAddress;
|
||||
import se.sics.cooja.mspmote.interfaces.Exp5438LED;
|
||||
import se.sics.cooja.mspmote.interfaces.Msp802154Radio;
|
||||
import se.sics.cooja.mspmote.interfaces.MspClock;
|
||||
import se.sics.cooja.mspmote.interfaces.MspDebugOutput;
|
||||
import se.sics.cooja.mspmote.interfaces.MspMoteID;
|
||||
import se.sics.cooja.mspmote.interfaces.Msp802154Radio;
|
||||
import se.sics.cooja.mspmote.interfaces.UsciA1Serial;
|
||||
|
||||
@ClassDescription("EXP430F5438 mote...")
|
||||
@ClassDescription("EXP430F5438 mote")
|
||||
@AbstractionLevelDescription("Emulated level")
|
||||
public class Exp5438MoteType extends MspMoteType {
|
||||
private static Logger logger = Logger.getLogger(Exp5438MoteType.class);
|
||||
|
@ -190,7 +190,7 @@ public class Exp5438MoteType extends MspMoteType {
|
|||
MspMoteID.class,
|
||||
Msp802154Radio.class,
|
||||
UsciA1Serial.class,
|
||||
Exp5438LED.class,
|
||||
Exp5438LED.class,
|
||||
/*Exp5438LCD.class,*/ /* TODO */
|
||||
MspDebugOutput.class
|
||||
};
|
||||
|
@ -202,7 +202,7 @@ public class Exp5438MoteType extends MspMoteType {
|
|||
|
||||
return new File(parentDir, sourceNoExtension + ".exp5438");
|
||||
}
|
||||
|
||||
|
||||
protected String getTargetName() {
|
||||
return "exp5438";
|
||||
}
|
||||
|
|
|
@ -58,18 +58,18 @@ import se.sics.cooja.interfaces.Mote2MoteRelations;
|
|||
import se.sics.cooja.interfaces.MoteAttributes;
|
||||
import se.sics.cooja.interfaces.Position;
|
||||
import se.sics.cooja.interfaces.RimeAddress;
|
||||
import se.sics.cooja.mspmote.interfaces.Msp802154Radio;
|
||||
import se.sics.cooja.mspmote.interfaces.MspClock;
|
||||
import se.sics.cooja.mspmote.interfaces.MspDebugOutput;
|
||||
import se.sics.cooja.mspmote.interfaces.MspMoteID;
|
||||
import se.sics.cooja.mspmote.interfaces.MspSerial;
|
||||
import se.sics.cooja.mspmote.interfaces.SkyButton;
|
||||
import se.sics.cooja.mspmote.interfaces.Msp802154Radio;
|
||||
import se.sics.cooja.mspmote.interfaces.SkyCoffeeFilesystem;
|
||||
import se.sics.cooja.mspmote.interfaces.SkyFlash;
|
||||
import se.sics.cooja.mspmote.interfaces.SkyLED;
|
||||
import se.sics.cooja.mspmote.interfaces.MspSerial;
|
||||
import se.sics.cooja.mspmote.interfaces.SkyTemperature;
|
||||
|
||||
@ClassDescription("Sky mote...")
|
||||
@ClassDescription("Sky mote")
|
||||
@AbstractionLevelDescription("Emulated level")
|
||||
public class SkyMoteType extends MspMoteType {
|
||||
private static Logger logger = Logger.getLogger(SkyMoteType.class);
|
||||
|
@ -229,7 +229,7 @@ public class SkyMoteType extends MspMoteType {
|
|||
|
||||
return new File(parentDir, sourceNoExtension + ".sky");
|
||||
}
|
||||
|
||||
|
||||
protected String getTargetName() {
|
||||
return "sky";
|
||||
}
|
||||
|
|
|
@ -55,14 +55,14 @@ import se.sics.cooja.interfaces.Mote2MoteRelations;
|
|||
import se.sics.cooja.interfaces.MoteAttributes;
|
||||
import se.sics.cooja.interfaces.Position;
|
||||
import se.sics.cooja.interfaces.RimeAddress;
|
||||
import se.sics.cooja.mspmote.interfaces.Msp802154Radio;
|
||||
import se.sics.cooja.mspmote.interfaces.MspClock;
|
||||
import se.sics.cooja.mspmote.interfaces.MspDebugOutput;
|
||||
import se.sics.cooja.mspmote.interfaces.MspMoteID;
|
||||
import se.sics.cooja.mspmote.interfaces.Msp802154Radio;
|
||||
import se.sics.cooja.mspmote.interfaces.TyndallLED;
|
||||
import se.sics.cooja.mspmote.interfaces.UsciA0Serial;
|
||||
|
||||
@ClassDescription("Tyndall mote...")
|
||||
@ClassDescription("Tyndall mote")
|
||||
@AbstractionLevelDescription("Emulated level")
|
||||
public class TyndallMoteType extends MspMoteType {
|
||||
private static Logger logger = Logger.getLogger(TyndallMoteType.class);
|
||||
|
@ -201,7 +201,7 @@ public class TyndallMoteType extends MspMoteType {
|
|||
|
||||
return new File(parentDir, sourceNoExtension + ".tyndall");
|
||||
}
|
||||
|
||||
|
||||
protected String getTargetName() {
|
||||
return "tyndall";
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ import se.sics.cooja.mspmote.interfaces.MspDefaultSerial;
|
|||
import se.sics.cooja.mspmote.interfaces.MspLED;
|
||||
import se.sics.cooja.mspmote.interfaces.MspMoteID;
|
||||
|
||||
@ClassDescription("Wismote mote...")
|
||||
@ClassDescription("Wismote mote")
|
||||
@AbstractionLevelDescription("Emulated level")
|
||||
public class WismoteMoteType extends AbstractMspMoteType {
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ import se.sics.cooja.mspmote.interfaces.MspDefaultSerial;
|
|||
import se.sics.cooja.mspmote.interfaces.MspLED;
|
||||
import se.sics.cooja.mspmote.interfaces.MspMoteID;
|
||||
|
||||
@ClassDescription("Z1 mote...")
|
||||
@ClassDescription("Z1 mote")
|
||||
@AbstractionLevelDescription("Emulated level")
|
||||
public class Z1MoteType extends AbstractMspMoteType {
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ import se.sics.cooja.interfaces.Radio;
|
|||
*
|
||||
* @author Fredrik Osterlind, Adam Dunkels
|
||||
*/
|
||||
@ClassDescription("Mote radio duty cycle...")
|
||||
@ClassDescription("Mote radio duty cycle")
|
||||
@PluginType(PluginType.SIM_PLUGIN)
|
||||
public class PowerTracker extends VisPlugin {
|
||||
private static Logger logger = Logger.getLogger(PowerTracker.class);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
se.sics.cooja.GUI.MOTETYPES = se.sics.cooja.motes.DisturberMoteType se.sics.cooja.contikimote.ContikiMoteType se.sics.cooja.mspmote.ESBMoteType se.sics.cooja.mspmote.SkyMoteType
|
||||
se.sics.cooja.GUI.PLUGINS = se.sics.cooja.plugins.Visualizer se.sics.cooja.plugins.LogListener se.sics.cooja.plugins.MoteInformation se.sics.cooja.plugins.MoteInterfaceViewer se.sics.cooja.plugins.VariableWatcher se.sics.cooja.plugins.EventListener se.sics.cooja.plugins.RadioLogger se.sics.cooja.mspmote.plugins.MspCodeWatcher se.sics.cooja.mspmote.plugins.MspStackWatcher se.sics.cooja.mspmote.plugins.MspCycleWatcher
|
||||
se.sics.cooja.GUI.IP_DISTRIBUTORS = se.sics.cooja.ipdistributors.RandomIPDistributor se.sics.cooja.ipdistributors.SpatialIPDistributor se.sics.cooja.ipdistributors.IdIPDistributor
|
||||
se.sics.cooja.GUI.POSITIONERS = se.sics.cooja.positioners.RandomPositioner se.sics.cooja.positioners.LinearPositioner se.sics.cooja.positioners.EllipsePositioner se.sics.cooja.positioners.ManualPositioner
|
||||
se.sics.cooja.GUI.RADIOMEDIUMS = se.sics.cooja.radiomediums.UDGM se.sics.cooja.radiomediums.UDGMConstantLoss se.sics.cooja.radiomediums.DirectedGraphMedium se.sics.mrm.MRM se.sics.cooja.radiomediums.SilentRadioMedium
|
||||
|
|
|
@ -4,6 +4,5 @@ se.sics.cooja.contikimote.ContikiMoteType.MOTE_INTERFACES = se.sics.cooja.interf
|
|||
se.sics.cooja.contikimote.ContikiMoteType.C_SOURCES =
|
||||
se.sics.cooja.GUI.MOTETYPES = se.sics.cooja.motes.ImportAppMoteType se.sics.cooja.motes.DisturberMoteType se.sics.cooja.contikimote.ContikiMoteType
|
||||
se.sics.cooja.GUI.PLUGINS = se.sics.cooja.plugins.Visualizer se.sics.cooja.plugins.LogListener se.sics.cooja.plugins.TimeLine se.sics.cooja.plugins.MoteInformation se.sics.cooja.plugins.MoteInterfaceViewer se.sics.cooja.plugins.VariableWatcher se.sics.cooja.plugins.EventListener se.sics.cooja.plugins.RadioLogger se.sics.cooja.plugins.ScriptRunner se.sics.cooja.plugins.Notes se.sics.cooja.plugins.BufferListener
|
||||
se.sics.cooja.GUI.IP_DISTRIBUTORS = se.sics.cooja.ipdistributors.RandomIPDistributor se.sics.cooja.ipdistributors.SpatialIPDistributor se.sics.cooja.ipdistributors.IdIPDistributor
|
||||
se.sics.cooja.GUI.POSITIONERS = se.sics.cooja.positioners.RandomPositioner se.sics.cooja.positioners.LinearPositioner se.sics.cooja.positioners.EllipsePositioner se.sics.cooja.positioners.ManualPositioner
|
||||
se.sics.cooja.GUI.RADIOMEDIUMS = se.sics.cooja.radiomediums.UDGM se.sics.cooja.radiomediums.UDGMConstantLoss se.sics.cooja.radiomediums.DirectedGraphMedium se.sics.cooja.radiomediums.SilentRadioMedium
|
||||
|
|
|
@ -829,7 +829,7 @@ public class GUI extends Observable {
|
|||
}
|
||||
|
||||
String description = GUI.getDescriptionOf(moteTypeClass);
|
||||
menuItem = new JMenuItem(description);
|
||||
menuItem = new JMenuItem(description + "...");
|
||||
menuItem.setActionCommand("create mote type");
|
||||
menuItem.putClientProperty("class", moteTypeClass);
|
||||
/* menuItem.setToolTipText(abstractionLevelDescription);*/
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2006, Swedish Institute of Computer Science. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer. 2. Redistributions in
|
||||
* binary form must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution. 3. Neither the name of the
|
||||
* Institute nor the names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: IPDistributor.java,v 1.2 2007/01/10 14:57:42 fros4943 Exp $
|
||||
*/
|
||||
|
||||
package se.sics.cooja;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Vector;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
* A IP distributor is used for determining IP addresses of newly created motes.
|
||||
*
|
||||
* @see se.sics.cooja.Positioner
|
||||
* @author Fredrik Osterlind
|
||||
*/
|
||||
public abstract class IPDistributor {
|
||||
private static Logger logger = Logger.getLogger(IPDistributor.class);
|
||||
|
||||
/**
|
||||
* This method creates an instance of the given class with the given vector as
|
||||
* constructor argument. Instead of calling the constructors directly this
|
||||
* method may be used.
|
||||
*
|
||||
* @param ipDistClass
|
||||
* Class
|
||||
* @param newMotes
|
||||
* All motes that later should be assigned IP numbers
|
||||
* @return IP distributor instance
|
||||
*/
|
||||
public static final IPDistributor generateIPDistributor(
|
||||
Class<? extends IPDistributor> ipDistClass, Vector<Mote> newMotes) {
|
||||
try {
|
||||
// Generating IP distributor
|
||||
Constructor constr = ipDistClass
|
||||
.getConstructor(new Class[] { Vector.class });
|
||||
return (IPDistributor) constr.newInstance(new Object[] { newMotes });
|
||||
} catch (Exception e) {
|
||||
logger.fatal("Exception when creating " + ipDistClass + ": " + e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next mote IP address.
|
||||
*
|
||||
* @return IP Address
|
||||
*/
|
||||
public abstract String getNextIPAddress();
|
||||
|
||||
}
|
|
@ -90,7 +90,7 @@ import se.sics.cooja.util.StringUtils;
|
|||
*
|
||||
* @author Fredrik Osterlind
|
||||
*/
|
||||
@ClassDescription("Cooja mote...")
|
||||
@ClassDescription("Cooja mote")
|
||||
@AbstractionLevelDescription("OS level")
|
||||
public class ContikiMoteType implements MoteType {
|
||||
private static Logger logger = Logger.getLogger(ContikiMoteType.class);
|
||||
|
|
|
@ -31,16 +31,45 @@
|
|||
|
||||
package se.sics.cooja.dialogs;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.beans.*;
|
||||
import java.text.*;
|
||||
import java.util.*;
|
||||
import javax.swing.*;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dialog;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.ParseException;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFormattedTextField;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import se.sics.cooja.*;
|
||||
import se.sics.cooja.interfaces.*;
|
||||
import se.sics.cooja.GUI;
|
||||
import se.sics.cooja.Mote;
|
||||
import se.sics.cooja.MoteType;
|
||||
import se.sics.cooja.Positioner;
|
||||
import se.sics.cooja.Simulation;
|
||||
import se.sics.cooja.interfaces.MoteID;
|
||||
import se.sics.cooja.interfaces.Position;
|
||||
|
||||
/**
|
||||
* A dialog for adding motes.
|
||||
|
@ -66,7 +95,7 @@ public class AddMoteDialog extends JDialog {
|
|||
|
||||
private JFormattedTextField numberOfMotesField, startX, endX, startY, endY,
|
||||
startZ, endZ;
|
||||
private JComboBox positionDistributionBox /*, ipDistributionBox*/;
|
||||
private JComboBox positionDistributionBox;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -176,36 +205,6 @@ public class AddMoteDialog extends JDialog {
|
|||
mainPane.add(smallPane);
|
||||
mainPane.add(Box.createRigidArea(new Dimension(0, 5)));
|
||||
|
||||
// IP address distribution
|
||||
/*smallPane = new JPanel();
|
||||
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.X_AXIS));
|
||||
label = new JLabel("IP Addressing");
|
||||
label.setPreferredSize(new Dimension(LABEL_WIDTH, LABEL_HEIGHT));
|
||||
|
||||
Vector<Class<? extends IPDistributor>> ipDistributors = simulation.getGUI()
|
||||
.getRegisteredIPDistributors();
|
||||
String[] ipDistributions = new String[ipDistributors.size()];
|
||||
for (int i = 0; i < ipDistributions.length; i++) {
|
||||
ipDistributions[i] = GUI.getDescriptionOf(ipDistributors.get(i));
|
||||
}
|
||||
|
||||
comboBox = new JComboBox(ipDistributions);
|
||||
|
||||
comboBox.setSelectedIndex(0);
|
||||
comboBox.addActionListener(myEventHandler);
|
||||
comboBox.addFocusListener(myEventHandler);
|
||||
ipDistributionBox = comboBox;
|
||||
label.setLabelFor(comboBox);
|
||||
|
||||
smallPane.add(label);
|
||||
smallPane.add(Box.createHorizontalStrut(10));
|
||||
smallPane.add(comboBox);
|
||||
|
||||
mainPane.add(smallPane);
|
||||
mainPane.add(Box.createRigidArea(new Dimension(0, 5)));
|
||||
*/
|
||||
|
||||
// Position distribution
|
||||
smallPane = new JPanel();
|
||||
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
|
@ -504,7 +503,7 @@ public class AddMoteDialog extends JDialog {
|
|||
}
|
||||
}
|
||||
|
||||
/* Set unique mote id's for all new motes
|
||||
/* Set unique mote id's for all new motes
|
||||
* TODO ID should be provided differently; not rely on the unsafe MoteID interface */
|
||||
int nextMoteID = 1;
|
||||
for (Mote m: simulation.getMotes()) {
|
||||
|
@ -522,33 +521,6 @@ public class AddMoteDialog extends JDialog {
|
|||
}
|
||||
}
|
||||
|
||||
// IP address new motes
|
||||
/*Class<? extends IPDistributor> ipDistClass = null;
|
||||
for (Class<? extends IPDistributor> ipDistributor : simulation.getGUI()
|
||||
.getRegisteredIPDistributors()) {
|
||||
if (GUI.getDescriptionOf(ipDistributor).equals(
|
||||
ipDistributionBox.getSelectedItem())) {
|
||||
ipDistClass = ipDistributor;
|
||||
}
|
||||
}
|
||||
|
||||
IPDistributor ipDistributor = IPDistributor.generateIPDistributor(
|
||||
ipDistClass, newMotes);
|
||||
|
||||
if (ipDistributor == null) {
|
||||
logger.fatal("Could not create IP distributor");
|
||||
dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < newMotes.size(); i++) {
|
||||
String newIPString = ipDistributor.getNextIPAddress();
|
||||
if (newMotes.get(i).getInterfaces().getIPAddress() != null) {
|
||||
newMotes.get(i).getInterfaces().getIPAddress().setIPString(
|
||||
newIPString);
|
||||
}
|
||||
}*/
|
||||
|
||||
dispose();
|
||||
} catch (OutOfMemoryError e2) {
|
||||
newMotes = null;
|
||||
|
|
|
@ -1,106 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2006, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: SpatialIPDistributor.java,v 1.1 2006/08/21 12:13:07 fros4943 Exp $
|
||||
*/
|
||||
|
||||
package se.sics.cooja.ipdistributors;
|
||||
import java.util.Vector;
|
||||
import se.sics.cooja.*;
|
||||
|
||||
/**
|
||||
* Generates spatial IP addresses on the form 10.[z-coord].[y-coord].[x-coord].
|
||||
* The smallest coordinate in each interval will be mapped onto address 1,
|
||||
* and the biggest coordinate onto address 200.
|
||||
* Nothing prevents several motes from getting the same IP number.
|
||||
*
|
||||
* @author Fredrik Osterlind
|
||||
*/
|
||||
@ClassDescription("Spatial (10.x.y.z)")
|
||||
public class SpatialIPDistributor extends IPDistributor {
|
||||
private double lowestX, biggestX, lowestY, biggestY, lowestZ, biggestZ;
|
||||
private Vector<String> generatedIPAddresses;
|
||||
|
||||
/**
|
||||
* Creates a random IP distributor.
|
||||
* @param newMotes All motes which later will be assigned IP numbers.
|
||||
*/
|
||||
public SpatialIPDistributor(Vector<Mote> newMotes) {
|
||||
lowestX = newMotes.get(0).getInterfaces().getPosition().getXCoordinate();
|
||||
biggestX = newMotes.get(0).getInterfaces().getPosition().getXCoordinate();
|
||||
lowestY = newMotes.get(0).getInterfaces().getPosition().getYCoordinate();
|
||||
biggestY = newMotes.get(0).getInterfaces().getPosition().getYCoordinate();
|
||||
lowestZ = newMotes.get(0).getInterfaces().getPosition().getZCoordinate();
|
||||
biggestZ = newMotes.get(0).getInterfaces().getPosition().getZCoordinate();
|
||||
|
||||
for (int i=0; i < newMotes.size(); i++) {
|
||||
if (newMotes.get(i).getInterfaces().getPosition().getXCoordinate() < lowestX)
|
||||
lowestX = newMotes.get(i).getInterfaces().getPosition().getXCoordinate();
|
||||
if (newMotes.get(i).getInterfaces().getPosition().getXCoordinate() > biggestX)
|
||||
biggestX = newMotes.get(i).getInterfaces().getPosition().getXCoordinate();
|
||||
|
||||
if (newMotes.get(i).getInterfaces().getPosition().getYCoordinate() < lowestY)
|
||||
lowestY = newMotes.get(i).getInterfaces().getPosition().getYCoordinate();
|
||||
if (newMotes.get(i).getInterfaces().getPosition().getYCoordinate() > biggestY)
|
||||
biggestY = newMotes.get(i).getInterfaces().getPosition().getYCoordinate();
|
||||
|
||||
if (newMotes.get(i).getInterfaces().getPosition().getZCoordinate() < lowestZ)
|
||||
lowestZ = newMotes.get(i).getInterfaces().getPosition().getZCoordinate();
|
||||
if (newMotes.get(i).getInterfaces().getPosition().getZCoordinate() > biggestZ)
|
||||
biggestZ = newMotes.get(i).getInterfaces().getPosition().getZCoordinate();
|
||||
}
|
||||
|
||||
generatedIPAddresses = new Vector<String>();
|
||||
for (int i=0; i < newMotes.size(); i++) {
|
||||
String ipAddress = "10.";
|
||||
int partIP;
|
||||
|
||||
// Z coord
|
||||
partIP = (int) (1 + 199*(newMotes.get(i).getInterfaces().getPosition().getZCoordinate() - lowestZ) / (biggestZ - lowestZ));
|
||||
ipAddress = ipAddress.concat(partIP + ".");
|
||||
|
||||
// Y coord
|
||||
partIP = (int) (1 + 199*(newMotes.get(i).getInterfaces().getPosition().getYCoordinate() - lowestY) / (biggestY - lowestY));
|
||||
ipAddress = ipAddress.concat(partIP + ".");
|
||||
|
||||
// X coord
|
||||
partIP = (int) (1 + 199*(newMotes.get(i).getInterfaces().getPosition().getXCoordinate() - lowestX) / (biggestX - lowestX));
|
||||
ipAddress = ipAddress.concat(partIP + "");
|
||||
|
||||
generatedIPAddresses.add(ipAddress);
|
||||
}
|
||||
}
|
||||
|
||||
public String getNextIPAddress() {
|
||||
if (generatedIPAddresses.size() > 0)
|
||||
return generatedIPAddresses.remove(0);
|
||||
else
|
||||
return "0.0.0.0";
|
||||
}
|
||||
|
||||
}
|
|
@ -40,7 +40,9 @@ import java.net.URL;
|
|||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.jdom.Element;
|
||||
|
||||
import se.sics.cooja.AbstractionLevelDescription;
|
||||
import se.sics.cooja.ClassDescription;
|
||||
import se.sics.cooja.Mote;
|
||||
|
@ -52,7 +54,7 @@ import se.sics.cooja.util.ArrayUtils;
|
|||
/**
|
||||
* @author Fredrik Osterlind
|
||||
*/
|
||||
@ClassDescription("Import Java mote...")
|
||||
@ClassDescription("Import Java mote")
|
||||
@AbstractionLevelDescription("Application level")
|
||||
public class ImportAppMoteType extends AbstractApplicationMoteType {
|
||||
|
||||
|
@ -109,7 +111,7 @@ public class ImportAppMoteType extends AbstractApplicationMoteType {
|
|||
}
|
||||
|
||||
public boolean configureAndInit(Container parentContainer,
|
||||
Simulation simulation, boolean visAvailable)
|
||||
Simulation simulation, boolean visAvailable)
|
||||
throws MoteTypeCreationException {
|
||||
this.simulation = simulation;
|
||||
|
||||
|
@ -256,7 +258,7 @@ public class ImportAppMoteType extends AbstractApplicationMoteType {
|
|||
public boolean isTestSubclass(Class<?> type) {
|
||||
return type.isAssignableFrom(testClass);
|
||||
}
|
||||
|
||||
|
||||
public Class<?> getTestClass() {
|
||||
return testClass;
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ import se.sics.cooja.util.StringUtils;
|
|||
/**
|
||||
* @author Fredrik Osterlind, Niclas Finne
|
||||
*/
|
||||
@ClassDescription("Buffer view...")
|
||||
@ClassDescription("Buffer view")
|
||||
@PluginType(PluginType.SIM_PLUGIN)
|
||||
public class BufferListener extends VisPlugin {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -132,7 +132,7 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
final static int MAX_BUFFER_SIZE = 128;
|
||||
|
||||
private static ArrayList<Class<? extends Parser>> bufferParsers =
|
||||
private static ArrayList<Class<? extends Parser>> bufferParsers =
|
||||
new ArrayList<Class<? extends Parser>>();
|
||||
static {
|
||||
registerBufferParser(ByteArrayParser.class);
|
||||
|
@ -148,7 +148,7 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
/* TODO Hide identical lines? */
|
||||
|
||||
private static ArrayList<Class<? extends Buffer>> bufferTypes =
|
||||
private static ArrayList<Class<? extends Buffer>> bufferTypes =
|
||||
new ArrayList<Class<? extends Buffer>>();
|
||||
static {
|
||||
registerBufferType(PacketbufBuffer.class);
|
||||
|
@ -787,7 +787,7 @@ public class BufferListener extends VisPlugin {
|
|||
private void updateTitle() {
|
||||
if (buffer != null) {
|
||||
String status = buffer.getStatusString();
|
||||
setTitle("Buffer Listener - " +
|
||||
setTitle("Buffer Listener - " +
|
||||
((status!=null)?status:GUI.getDescriptionOf(buffer)) + " " +
|
||||
"- " + memoryMonitors.size() + " buffers on " + motes.size() + " motes");
|
||||
}
|
||||
|
@ -872,7 +872,7 @@ public class BufferListener extends VisPlugin {
|
|||
repaintTimeColumn();
|
||||
} else if ("parser".equals(name)) {
|
||||
String parserClassname = element.getText();
|
||||
Class<? extends Parser> parserClass =
|
||||
Class<? extends Parser> parserClass =
|
||||
simulation.getGUI().tryLoadClass(this, Parser.class, parserClassname);
|
||||
if (parserClass == null) {
|
||||
logger.warn("Could not create buffer parser: could not find class: " + parserClassname);
|
||||
|
@ -960,7 +960,7 @@ public class BufferListener extends VisPlugin {
|
|||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public static class BufferAccess {
|
||||
|
@ -1271,7 +1271,7 @@ public class BufferListener extends VisPlugin {
|
|||
@SuppressWarnings("unchecked")
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Class<? extends Parser> bpClass =
|
||||
(Class<? extends Parser>)
|
||||
(Class<? extends Parser>)
|
||||
((JMenuItem) e.getSource()).getClientProperty("CLASS");
|
||||
setParser(bpClass);
|
||||
}
|
||||
|
@ -1291,7 +1291,7 @@ public class BufferListener extends VisPlugin {
|
|||
@SuppressWarnings("unchecked")
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Class<? extends Buffer> btClass =
|
||||
(Class<? extends Buffer>)
|
||||
(Class<? extends Buffer>)
|
||||
((JMenuItem) e.getSource()).getClientProperty("CLASS");
|
||||
|
||||
Buffer b = createBufferInstance(btClass);
|
||||
|
@ -1610,7 +1610,7 @@ public class BufferListener extends VisPlugin {
|
|||
public static class PrintableCharactersParser extends StringParser {
|
||||
public String parseString(BufferAccess ba) {
|
||||
/* TODO Diff? */
|
||||
return new String(ba.mem).replaceAll("[^\\p{Print}]", "");
|
||||
return new String(ba.mem).replaceAll("[^\\p{Print}]", "");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1692,7 +1692,7 @@ public class BufferListener extends VisPlugin {
|
|||
if (diff != null && diff[x]) {
|
||||
red = true;
|
||||
}
|
||||
int v = (int)0xff&ba.mem[x];
|
||||
int v = 0xff&ba.mem[x];
|
||||
int h = Math.min(v/16, 15); /* crop */
|
||||
if (red) {
|
||||
g.setColor(Color.RED);
|
||||
|
|
|
@ -30,16 +30,42 @@
|
|||
package se.sics.cooja.plugins;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.event.*;
|
||||
import java.util.*;
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Collection;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jdom.Element;
|
||||
|
||||
import se.sics.cooja.*;
|
||||
import se.sics.cooja.GUI.PluginConstructionException;
|
||||
import se.sics.cooja.ClassDescription;
|
||||
import se.sics.cooja.GUI;
|
||||
import se.sics.cooja.Mote;
|
||||
import se.sics.cooja.MoteInterface;
|
||||
import se.sics.cooja.MoteType;
|
||||
import se.sics.cooja.PluginType;
|
||||
import se.sics.cooja.Simulation;
|
||||
import se.sics.cooja.VisPlugin;
|
||||
import se.sics.cooja.contikimote.ContikiMoteType;
|
||||
import se.sics.cooja.interfaces.*;
|
||||
import se.sics.cooja.interfaces.Button;
|
||||
import se.sics.cooja.interfaces.LED;
|
||||
import se.sics.cooja.interfaces.Log;
|
||||
import se.sics.cooja.interfaces.PIR;
|
||||
import se.sics.cooja.interfaces.Position;
|
||||
import se.sics.cooja.interfaces.Radio;
|
||||
|
||||
/**
|
||||
* Allows a user to observe several different parts of the simulator, stopping a
|
||||
|
@ -47,7 +73,7 @@ import se.sics.cooja.interfaces.*;
|
|||
*
|
||||
* @author Fredrik Osterlind
|
||||
*/
|
||||
@ClassDescription("Breakpoints...")
|
||||
@ClassDescription("Breakpoints")
|
||||
@PluginType(PluginType.SIM_PLUGIN)
|
||||
public class EventListener extends VisPlugin {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -113,7 +139,7 @@ public class EventListener extends VisPlugin {
|
|||
+ myParent.mySimulation.getSimulationTime(), new AbstractAction(
|
||||
"View interface visualizer") {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
MoteInterfaceViewer plugin =
|
||||
MoteInterfaceViewer plugin =
|
||||
(MoteInterfaceViewer) mySimulation.getGUI().tryStartPlugin(
|
||||
MoteInterfaceViewer.class, mySimulation.getGUI(), mySimulation, myMote);
|
||||
plugin.setSelectedInterface(GUI.getDescriptionOf(moteInterface.getClass()));
|
||||
|
|
|
@ -103,7 +103,7 @@ import se.sics.cooja.util.ArrayQueue;
|
|||
*
|
||||
* @author Fredrik Osterlind, Niclas Finne
|
||||
*/
|
||||
@ClassDescription("Mote output...")
|
||||
@ClassDescription("Mote output")
|
||||
@PluginType(PluginType.SIM_STANDARD_PLUGIN)
|
||||
public class LogListener extends VisPlugin implements HasQuickHelp {
|
||||
private static final long serialVersionUID = 3294595371354857261L;
|
||||
|
@ -132,7 +132,7 @@ public class LogListener extends VisPlugin implements HasQuickHelp {
|
|||
private ArrayQueue<LogData> logs = new ArrayQueue<LogData>();
|
||||
|
||||
private Simulation simulation;
|
||||
|
||||
|
||||
private JTextField filterTextField = null;
|
||||
private JLabel filterLabel = new JLabel("Filter: ");
|
||||
private Color filterTextFieldBackground;
|
||||
|
@ -208,18 +208,18 @@ public class LogListener extends VisPlugin implements HasQuickHelp {
|
|||
menuBar.add(editMenu);
|
||||
menuBar.add(showMenu);
|
||||
this.setJMenuBar(menuBar);
|
||||
|
||||
|
||||
editMenu.add(new JMenuItem(copyAllAction));
|
||||
editMenu.add(new JMenuItem(copyAllMessagesAction));
|
||||
editMenu.add(new JMenuItem(copyAction));
|
||||
editMenu.addSeparator();
|
||||
editMenu.add(new JMenuItem(clearAction));
|
||||
|
||||
|
||||
|
||||
|
||||
fileMenu.add(new JMenuItem(saveAction));
|
||||
appendCheckBox = new JCheckBoxMenuItem(appendAction);
|
||||
fileMenu.add(appendCheckBox);
|
||||
|
||||
|
||||
colorCheckbox = new JCheckBoxMenuItem("Mote-specific coloring");
|
||||
showMenu.add(colorCheckbox);
|
||||
colorCheckbox.addActionListener(new ActionListener() {
|
||||
|
@ -400,7 +400,7 @@ public class LogListener extends VisPlugin implements HasQuickHelp {
|
|||
adjuster.packColumns();
|
||||
|
||||
/* Popup menu */
|
||||
|
||||
|
||||
JPopupMenu popupMenu = new JPopupMenu();
|
||||
/*
|
||||
JMenu copyClipboard = new JMenu("Copy to clipboard");
|
||||
|
@ -543,7 +543,7 @@ public class LogListener extends VisPlugin implements HasQuickHelp {
|
|||
|
||||
updateTitle();
|
||||
pack();
|
||||
|
||||
|
||||
/* XXX HACK: here we set the position and size of the window when it appears on a blank simulation screen. */
|
||||
this.setLocation(400, 160);
|
||||
this.setSize(gui.getDesktopPane().getWidth() - 400, 240);
|
||||
|
|
|
@ -56,7 +56,7 @@ import se.sics.cooja.PluginType;
|
|||
import se.sics.cooja.Simulation;
|
||||
import se.sics.cooja.VisPlugin;
|
||||
|
||||
@ClassDescription("Notes...")
|
||||
@ClassDescription("Notes")
|
||||
@PluginType(PluginType.SIM_STANDARD_PLUGIN)
|
||||
public class Notes extends VisPlugin {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -85,7 +85,7 @@ public class Notes extends VisPlugin {
|
|||
public void mousePressed(MouseEvent e) {
|
||||
if (e.isPopupTrigger()) {
|
||||
popup.show(Notes.this, e.getX(), e.getY());
|
||||
}
|
||||
}
|
||||
}
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
if (e.isPopupTrigger()) {
|
||||
|
@ -109,11 +109,11 @@ public class Notes extends VisPlugin {
|
|||
public String getNotes() {
|
||||
return notes.getText();
|
||||
}
|
||||
|
||||
|
||||
public void setNotes(String text) {
|
||||
this.notes.setText(text);
|
||||
}
|
||||
|
||||
|
||||
private void setDecorationsVisible(boolean visible) {
|
||||
if (!(Notes.this.getUI() instanceof BasicInternalFrameUI)) {
|
||||
return;
|
||||
|
@ -124,7 +124,7 @@ public class Notes extends VisPlugin {
|
|||
ui.getNorthPane().setPreferredSize(null);
|
||||
} else {
|
||||
ui.getNorthPane().setPreferredSize(new Dimension(0,0));
|
||||
}
|
||||
}
|
||||
|
||||
Notes.this.revalidate();
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
|
@ -135,7 +135,7 @@ public class Notes extends VisPlugin {
|
|||
|
||||
decorationsVisible = visible;
|
||||
}
|
||||
|
||||
|
||||
public Collection<Element> getConfigXML() {
|
||||
ArrayList<Element> config = new ArrayList<Element>();
|
||||
Element element;
|
||||
|
|
|
@ -102,8 +102,8 @@ import se.sics.cooja.util.StringUtils;
|
|||
*
|
||||
* @author Fredrik Osterlind
|
||||
*/
|
||||
@ClassDescription("Radio messages...")
|
||||
@PluginType(PluginType.SIM_PLUGIN)
|
||||
@ClassDescription("Radio messages")
|
||||
@PluginType(PluginType.SIM_PLUGIN)
|
||||
public class RadioLogger extends VisPlugin {
|
||||
private static Logger logger = Logger.getLogger(RadioLogger.class);
|
||||
private static final long serialVersionUID = -6927091711697081353L;
|
||||
|
@ -115,7 +115,7 @@ public class RadioLogger extends VisPlugin {
|
|||
|
||||
private JSplitPane splitPane;
|
||||
private JTextPane verboseBox = null;
|
||||
|
||||
|
||||
private final static String[] COLUMN_NAMES = {
|
||||
"Time",
|
||||
"From",
|
||||
|
@ -139,7 +139,7 @@ public class RadioLogger extends VisPlugin {
|
|||
public RadioLogger(final Simulation simulationToControl, final GUI gui) {
|
||||
super("Radio messages", gui);
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
|
||||
simulation = simulationToControl;
|
||||
radioMedium = simulation.getRadioMedium();
|
||||
|
||||
|
@ -149,14 +149,14 @@ public class RadioLogger extends VisPlugin {
|
|||
JMenu editMenu = new JMenu("Edit");
|
||||
JMenu analyzerMenu = new JMenu("Analyzer");
|
||||
JMenu payloadMenu = new JMenu("Payload");
|
||||
|
||||
|
||||
menuBar.add(fileMenu);
|
||||
menuBar.add(editMenu);
|
||||
menuBar.add(analyzerMenu);
|
||||
menuBar.add(payloadMenu);
|
||||
|
||||
|
||||
this.setJMenuBar(menuBar);
|
||||
|
||||
|
||||
ArrayList<PacketAnalyzer> lowpanAnalyzers = new ArrayList<PacketAnalyzer>();
|
||||
lowpanAnalyzers.add(new IEEE802154Analyzer(false));
|
||||
lowpanAnalyzers.add(new IPHCPacketAnalyzer());
|
||||
|
@ -297,7 +297,7 @@ public class RadioLogger extends VisPlugin {
|
|||
public void keyPressed(KeyEvent e) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
|
||||
showInAllAction.actionPerformed(null);
|
||||
} else if (e.getKeyCode() == KeyEvent.VK_F &&
|
||||
} else if (e.getKeyCode() == KeyEvent.VK_F &&
|
||||
(e.getModifiers() & KeyEvent.CTRL_MASK) != 0) {
|
||||
searchField.setVisible(true);
|
||||
searchField.requestFocus();
|
||||
|
@ -333,14 +333,14 @@ public class RadioLogger extends VisPlugin {
|
|||
editMenu.add(new JMenuItem(copyAction));
|
||||
editMenu.add(new JSeparator());
|
||||
editMenu.add(new JMenuItem(clearAction));
|
||||
|
||||
|
||||
payloadMenu.add(new JMenuItem(aliasAction));
|
||||
|
||||
|
||||
fileMenu.add(new JMenuItem(saveAction));
|
||||
|
||||
|
||||
|
||||
JPopupMenu popupMenu = new JPopupMenu();
|
||||
|
||||
|
||||
JMenu focusMenu = new JMenu("Show in");
|
||||
focusMenu.add(new JMenuItem(showInAllAction));
|
||||
focusMenu.addSeparator();
|
||||
|
@ -349,7 +349,7 @@ public class RadioLogger extends VisPlugin {
|
|||
popupMenu.add(focusMenu);
|
||||
|
||||
//a group of radio button menu items
|
||||
|
||||
|
||||
ButtonGroup group = new ButtonGroup();
|
||||
JRadioButtonMenuItem rbMenuItem = new JRadioButtonMenuItem(
|
||||
createAnalyzerAction("No Analyzer", "none", null, true));
|
||||
|
@ -366,7 +366,7 @@ public class RadioLogger extends VisPlugin {
|
|||
group.add(rbMenuItem);
|
||||
analyzerMenu.add(rbMenuItem);
|
||||
|
||||
|
||||
|
||||
/* Load additional analyzers specified by projects (cooja.config) */
|
||||
String[] projectAnalyzerSuites =
|
||||
gui.getProjectConfig().getStringArrayValue(RadioLogger.class, "ANALYZERS");
|
||||
|
@ -389,17 +389,17 @@ public class RadioLogger extends VisPlugin {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dataTable.setComponentPopupMenu(popupMenu);
|
||||
dataTable.setFillsViewportHeight(true);
|
||||
|
||||
verboseBox = new JTextPane();
|
||||
verboseBox.setContentType("text/html");
|
||||
verboseBox.setContentType("text/html");
|
||||
verboseBox.setEditable(false);
|
||||
verboseBox.setComponentPopupMenu(popupMenu);
|
||||
|
||||
/* Search text field */
|
||||
searchField.setVisible(false);
|
||||
searchField.setVisible(false);
|
||||
searchField.addKeyListener(new KeyAdapter() {
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||
|
@ -413,14 +413,14 @@ public class RadioLogger extends VisPlugin {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
|
||||
new JScrollPane(dataTable), new JScrollPane(verboseBox));
|
||||
splitPane.setOneTouchExpandable(true);
|
||||
splitPane.setDividerLocation(150);
|
||||
add(BorderLayout.NORTH, searchField);
|
||||
add(BorderLayout.CENTER, splitPane);
|
||||
|
||||
|
||||
TableColumnAdjuster adjuster = new TableColumnAdjuster(dataTable);
|
||||
adjuster.setDynamicAdjustment(true);
|
||||
adjuster.packColumns();
|
||||
|
@ -455,7 +455,7 @@ public class RadioLogger extends VisPlugin {
|
|||
dataTable.scrollRectToVisible(dataTable.getCellRect(dataTable.getRowCount() - 1, 0, true));
|
||||
}
|
||||
setTitle("Radio messages: " + dataTable.getRowCount() + " messages seen");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -476,7 +476,7 @@ public class RadioLogger extends VisPlugin {
|
|||
if (row < 0) {
|
||||
row = 0;
|
||||
}
|
||||
|
||||
|
||||
if (!reverse) {
|
||||
row++;
|
||||
} else {
|
||||
|
@ -502,10 +502,10 @@ public class RadioLogger extends VisPlugin {
|
|||
}
|
||||
searchField.setBackground(Color.RED);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Selects a logged radio packet close to the given time.
|
||||
*
|
||||
*
|
||||
* @param time Start time
|
||||
*/
|
||||
public void trySelectTime(final long time) {
|
||||
|
@ -520,9 +520,9 @@ public class RadioLogger extends VisPlugin {
|
|||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void prepareDataString(RadioConnectionLog conn) {
|
||||
byte[] data;
|
||||
if (conn.packet == null) {
|
||||
|
@ -564,7 +564,7 @@ public class RadioLogger extends VisPlugin {
|
|||
conn.data = data.length + ": 0x" + StringUtils.toHex(data, 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean analyzePacket(PacketAnalyzer.Packet packet, StringBuffer brief, StringBuffer verbose) {
|
||||
if (analyzers == null) return false;
|
||||
try {
|
||||
|
@ -688,7 +688,7 @@ public class RadioLogger extends VisPlugin {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private class RadioConnectionLog {
|
||||
long startTime;
|
||||
long endTime;
|
||||
|
@ -697,7 +697,7 @@ public class RadioLogger extends VisPlugin {
|
|||
|
||||
String data = null;
|
||||
String tooltip = null;
|
||||
|
||||
|
||||
public String toString() {
|
||||
if (data == null) {
|
||||
RadioLogger.this.prepareDataString(this);
|
||||
|
@ -765,7 +765,7 @@ public class RadioLogger extends VisPlugin {
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private Action copyAction = new AbstractAction("Copy selected") {
|
||||
private static final long serialVersionUID = 8412062977916108054L;
|
||||
|
||||
|
@ -786,7 +786,7 @@ public class RadioLogger extends VisPlugin {
|
|||
clipboard.setContents(stringSelection, null);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private Action copyAllAction = new AbstractAction("Copy all") {
|
||||
private static final long serialVersionUID = 1905586689441157304L;
|
||||
|
||||
|
@ -805,7 +805,7 @@ public class RadioLogger extends VisPlugin {
|
|||
clipboard.setContents(stringSelection, null);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private Action saveAction = new AbstractAction("Save to file...") {
|
||||
private static final long serialVersionUID = -3942984643211482179L;
|
||||
|
||||
|
@ -865,7 +865,7 @@ public class RadioLogger extends VisPlugin {
|
|||
if (!(p instanceof TimeLine)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/* Select simulation time */
|
||||
TimeLine plugin = (TimeLine) p;
|
||||
plugin.trySelectTime(time);
|
||||
|
@ -885,7 +885,7 @@ public class RadioLogger extends VisPlugin {
|
|||
if (!(p instanceof LogListener)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/* Select simulation time */
|
||||
LogListener plugin = (LogListener) p;
|
||||
plugin.trySelectTime(time);
|
||||
|
@ -918,7 +918,7 @@ public class RadioLogger extends VisPlugin {
|
|||
}
|
||||
|
||||
String alias = (String) JOptionPane.showInputDialog(
|
||||
GUI.getTopParentContainer(),
|
||||
GUI.getTopParentContainer(),
|
||||
"Enter alias for all packets with identical payload.\n" +
|
||||
"An empty string removes the current alias.\n\n" +
|
||||
connections.get(selectedRow).data + "\n",
|
||||
|
@ -940,7 +940,7 @@ public class RadioLogger extends VisPlugin {
|
|||
/* Remove current alias */
|
||||
if (alias.equals("")) {
|
||||
aliases.remove(connections.get(selectedRow).data);
|
||||
|
||||
|
||||
/* Should be null if empty */
|
||||
if (aliases.isEmpty()) {
|
||||
aliases = null;
|
||||
|
@ -954,7 +954,7 @@ public class RadioLogger extends VisPlugin {
|
|||
repaint();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public String getConnectionsString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
RadioConnectionLog[] cs = connections.toArray(new RadioConnectionLog[0]);
|
||||
|
@ -963,7 +963,7 @@ public class RadioLogger extends VisPlugin {
|
|||
}
|
||||
return sb.toString();
|
||||
};
|
||||
|
||||
|
||||
public void saveConnectionsToFile(String fileName) {
|
||||
StringUtils.saveToFile(new File(fileName), getConnectionsString());
|
||||
};
|
||||
|
|
|
@ -87,7 +87,7 @@ import se.sics.cooja.VisPlugin;
|
|||
import se.sics.cooja.dialogs.MessageList;
|
||||
import se.sics.cooja.util.StringUtils;
|
||||
|
||||
@ClassDescription("Simulation script editor...")
|
||||
@ClassDescription("Simulation script editor")
|
||||
@PluginType(PluginType.SIM_PLUGIN)
|
||||
public class ScriptRunner extends VisPlugin {
|
||||
private static final long serialVersionUID = 7614358340336799109L;
|
||||
|
|
|
@ -63,7 +63,7 @@ import se.sics.cooja.VisPlugin;
|
|||
*
|
||||
* @author Fredrik Osterlind
|
||||
*/
|
||||
@ClassDescription("Simulation control...")
|
||||
@ClassDescription("Simulation control")
|
||||
@PluginType(PluginType.SIM_STANDARD_PLUGIN)
|
||||
public class SimControl extends VisPlugin implements HasQuickHelp {
|
||||
private static final int LABEL_UPDATE_INTERVAL = 150;
|
||||
|
|
|
@ -56,7 +56,6 @@ import java.util.Observer;
|
|||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JCheckBoxMenuItem;
|
||||
import javax.swing.JComboBox;
|
||||
|
@ -70,7 +69,6 @@ import javax.swing.JOptionPane;
|
|||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.JSlider;
|
||||
import javax.swing.JSplitPane;
|
||||
import javax.swing.JToolTip;
|
||||
|
@ -107,7 +105,7 @@ import se.sics.cooja.motes.AbstractEmulatedMote;
|
|||
*
|
||||
* @author Fredrik Osterlind
|
||||
*/
|
||||
@ClassDescription("Timeline...")
|
||||
@ClassDescription("Timeline")
|
||||
@PluginType(PluginType.SIM_STANDARD_PLUGIN)
|
||||
public class TimeLine extends VisPlugin implements HasQuickHelp {
|
||||
private static final long serialVersionUID = -883154261246961973L;
|
||||
|
@ -177,16 +175,16 @@ public class TimeLine extends VisPlugin implements HasQuickHelp {
|
|||
JMenu eventsMenu = new JMenu("Events");
|
||||
JMenu viewMenu = new JMenu("View");
|
||||
JMenu zoomMenu = new JMenu("Zoom");
|
||||
|
||||
|
||||
menuBar.add(fileMenu);
|
||||
menuBar.add(editMenu);
|
||||
menuBar.add(viewMenu);
|
||||
menuBar.add(zoomMenu);
|
||||
menuBar.add(eventsMenu);
|
||||
menuBar.add(motesMenu);
|
||||
|
||||
|
||||
this.setJMenuBar(menuBar);
|
||||
|
||||
|
||||
motesMenu.add(new JMenuItem(addMoteAction));
|
||||
zoomMenu.add(new JMenuItem(zoomInAction));
|
||||
zoomMenu.add(new JMenuItem(zoomOutAction));
|
||||
|
@ -203,7 +201,7 @@ public class TimeLine extends VisPlugin implements HasQuickHelp {
|
|||
return radioChannels;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
fileMenu.add(new JMenuItem(saveDataAction));
|
||||
fileMenu.add(new JMenuItem(statisticsAction));
|
||||
editMenu.add(new JMenuItem(clearAction));
|
||||
|
@ -270,14 +268,14 @@ public class TimeLine extends VisPlugin implements HasQuickHelp {
|
|||
}
|
||||
});
|
||||
eventsMenu.add(eventCheckBox);
|
||||
|
||||
|
||||
/* Box: events to observe */
|
||||
|
||||
|
||||
eventCheckboxes = Box.createVerticalBox();
|
||||
/*
|
||||
eventCheckboxes.add(new JButton(addMoteAction));
|
||||
eventCheckboxes.add(new JSeparator());
|
||||
|
||||
|
||||
JCheckBox eventCheckBox;
|
||||
eventCheckBox = createEventCheckbox("Radio RX/TX", "Show radio transmissions, receptions, and collisions");
|
||||
eventCheckBox.setSelected(showRadioRXTX);
|
||||
|
@ -347,7 +345,7 @@ public class TimeLine extends VisPlugin implements HasQuickHelp {
|
|||
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
|
||||
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
|
||||
timelineScrollPane.getHorizontalScrollBar().setUnitIncrement(50);
|
||||
|
||||
|
||||
timelineMoteRuler = new MoteRuler();
|
||||
timelineScrollPane.setRowHeaderView(timelineMoteRuler);
|
||||
timelineScrollPane.setBackground(Color.WHITE);
|
||||
|
@ -420,7 +418,7 @@ public class TimeLine extends VisPlugin implements HasQuickHelp {
|
|||
timer.start();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/* XXX HACK: here we set the position and size of the window when it appears on a blank simulation screen. */
|
||||
this.setLocation(0, gui.getDesktopPane().getHeight() - 166);
|
||||
this.setSize(gui.getDesktopPane().getWidth(), 166);
|
||||
|
@ -2513,5 +2511,5 @@ public class TimeLine extends VisPlugin implements HasQuickHelp {
|
|||
"<br>Shows LED state: red, green, and blue. (Assumes all mote types have exactly three LEDs.)" +
|
||||
"<p><b>Watchpoints</b>" +
|
||||
"<br>Shows triggered watchpoints, currently only supported by MSPSim-based motes. To add watchpoints, use the Msp Code Watcher plugin.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ import se.sics.cooja.plugins.skins.UDGMVisualizerSkin;
|
|||
* @see UDGMVisualizerSkin
|
||||
* @author Fredrik Osterlind
|
||||
*/
|
||||
@ClassDescription("Network...")
|
||||
@ClassDescription("Network")
|
||||
@PluginType(PluginType.SIM_STANDARD_PLUGIN)
|
||||
public class Visualizer extends VisPlugin implements HasQuickHelp {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
|
Loading…
Reference in a new issue