Merge branch 'master' of ssh://contiki.git.sourceforge.net/gitroot/contiki/contiki

This commit is contained in:
Nicolas Tsiftes 2012-06-27 15:42:51 +02:00
commit 0ba83a10df
45 changed files with 3154 additions and 426 deletions

View file

@ -0,0 +1 @@
httpd-ws_src = httpd-ws.c

478
apps/httpd-ws/httpd-ws.c Normal file
View 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
View 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
View file

@ -0,0 +1 @@
json_src = jsonparse.c jsontree.c

View file

@ -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
View 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
View 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
View 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
View 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__ */

View 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

View 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).

View 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
#------------------------------------------------------------------------------

View 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));
}
/*---------------------------------------------------------------------------*/

View 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);
}
/*---------------------------------------------------------------------------*/

View file

@ -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__ */

View 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__ */

View 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

View 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();
}
/*---------------------------------------------------------------------------*/

View 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();
}
/*---------------------------------------------------------------------------*/

View file

@ -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)

View file

@ -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);

View file

@ -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";
}

View file

@ -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";
}

View file

@ -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";
}

View file

@ -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";
}

View file

@ -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 {

View file

@ -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 {

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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);*/

View file

@ -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();
}

View file

@ -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);

View file

@ -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;

View file

@ -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";
}
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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()));

View file

@ -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);

View file

@ -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;

View file

@ -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());
};

View file

@ -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;

View file

@ -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;

View file

@ -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.";
}
}
}

View file

@ -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;