From 418a5772e6fc68c5795e7196d63df40533f46e7a Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Thu, 7 Jun 2012 10:35:22 +0200 Subject: [PATCH 01/12] Removed leds debug output --- cpu/msp430/f2xxx/uart0.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/cpu/msp430/f2xxx/uart0.c b/cpu/msp430/f2xxx/uart0.c index d0ad49730..5e3447df8 100644 --- a/cpu/msp430/f2xxx/uart0.c +++ b/cpu/msp430/f2xxx/uart0.c @@ -40,7 +40,6 @@ #include "dev/uart0.h" #include "dev/watchdog.h" #include "lib/ringbuf.h" -#include "dev/leds.h" #include "isr_compat.h" static int (*uart0_input_handler)(unsigned char c); @@ -144,7 +143,6 @@ ISR(USCIAB0RX, uart0_rx_interrupt) uint8_t c; ENERGEST_ON(ENERGEST_TYPE_IRQ); - leds_toggle(LEDS_RED); if(UCA0STAT & UCRXERR) { c = UCA0RXBUF; /* Clear error flags by forcing a dummy read. */ } else { From d1bef2b68afb24dfc73370b2c40aeffffebbf879 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Thu, 7 Jun 2012 10:45:05 +0200 Subject: [PATCH 02/12] Bug fix: setup MAC address based on node id if no MAC address was restored from external flash --- platform/z1/contiki-z1-main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/z1/contiki-z1-main.c b/platform/z1/contiki-z1-main.c index 3b6195437..e97fddf9a 100644 --- a/platform/z1/contiki-z1-main.c +++ b/platform/z1/contiki-z1-main.c @@ -220,8 +220,8 @@ main(int argc, char **argv) node_id_restore(); /* If no MAC address was burned, we use the node ID. */ - if(node_mac[0] | node_mac[1] | node_mac[2] | node_mac[3] | - node_mac[4] | node_mac[5] | node_mac[6] | node_mac[7]) { + if(!(node_mac[0] | node_mac[1] | node_mac[2] | node_mac[3] | + node_mac[4] | node_mac[5] | node_mac[6] | node_mac[7])) { node_mac[0] = 0xc1; /* Hardcoded for Z1 */ node_mac[1] = 0x0c; /* Hardcoded for Revision C */ node_mac[2] = 0x00; /* Hardcoded to arbitrary even number so that From 6da3c038843a516e69929d4cd64e046dfce080e0 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Thu, 7 Jun 2012 10:45:31 +0200 Subject: [PATCH 03/12] Added button interface for Z1 platform --- .../cooja/apps/mspsim/src/se/sics/cooja/mspmote/Z1MoteType.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/Z1MoteType.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/Z1MoteType.java index b74804367..b5a7fdef5 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/Z1MoteType.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/Z1MoteType.java @@ -39,6 +39,7 @@ 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.MspButton; import se.sics.cooja.mspmote.interfaces.MspClock; import se.sics.cooja.mspmote.interfaces.MspDebugOutput; import se.sics.cooja.mspmote.interfaces.MspDefaultSerial; @@ -80,6 +81,7 @@ public class Z1MoteType extends AbstractMspMoteType { MoteAttributes.class, MspClock.class, MspMoteID.class, + MspButton.class, // SkyFlash.class, Msp802154Radio.class, MspDefaultSerial.class, From 019b984b7a262cfee01a69b558ebd9a4fb76aeda Mon Sep 17 00:00:00 2001 From: Fredrik Osterlind Date: Thu, 7 Jun 2012 12:33:29 +0200 Subject: [PATCH 04/12] simplified SerialUI implementation: code was both complex, buggy and contained unused broken functionality (slip, tos mode) --- .../java/se/sics/cooja/dialogs/SerialUI.java | 356 +++++++----------- 1 file changed, 138 insertions(+), 218 deletions(-) diff --git a/tools/cooja/java/se/sics/cooja/dialogs/SerialUI.java b/tools/cooja/java/se/sics/cooja/dialogs/SerialUI.java index 788e9f6f0..edc88ff5c 100644 --- a/tools/cooja/java/se/sics/cooja/dialogs/SerialUI.java +++ b/tools/cooja/java/se/sics/cooja/dialogs/SerialUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Swedish Institute of Computer Science. + * Copyright (c) 2012, Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,8 +44,6 @@ import java.util.Observable; import java.util.Observer; import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; @@ -58,161 +56,165 @@ import org.jdom.Element; import se.sics.cooja.Mote; import se.sics.cooja.interfaces.Log; import se.sics.cooja.interfaces.SerialPort; -import se.sics.cooja.plugins.SLIP; public abstract class SerialUI extends Log implements SerialPort { private static Logger logger = Logger.getLogger(SerialUI.class); - private final static byte SLIP_END = (byte)0300; - private final static byte SLIP_ESC = (byte)0333; - private final static byte SLIP_ESC_END = (byte)0334; - private final static byte SLIP_ESC_ESC = (byte)0335; - - private final static int MAX_LENGTH = 1024; - private String lastLogMessage = ""; - private StringBuilder newMessage = new StringBuilder(); + private byte lastSerialData = 0; /* SerialPort */ + private String lastLogMessage = ""; /* Log */ + private StringBuilder newMessage = new StringBuilder(); /* Log */ - private JTextArea logTextPane = null; - private JTextField commandField; - private JCheckBox slipCheckbox; - private String[] history = new String[50]; - private int historyPos = 0; - private int historyCount = 0; + /* Command history */ + private final static int HISTORY_SIZE = 15; + private ArrayList history = new ArrayList(); + private int historyPos = -1; - private class SerialDataObservable extends Observable { - private void notifyNewData() { + /* Log */ + public String getLastLogMessage() { + return lastLogMessage; + } + + /* SerialPort */ + private abstract class SerialDataObservable extends Observable { + public abstract void notifyNewData(); + } + private SerialDataObservable serialDataObservable = new SerialDataObservable() { + public void notifyNewData() { if (this.countObservers() == 0) { return; } setChanged(); notifyObservers(SerialUI.this); } - } - - private SerialDataObservable serialDataObservable = new SerialDataObservable(); - private byte lastSerialData = 0; - - public String getLastLogMessage() { - return lastLogMessage; - } - - public abstract Mote getMote(); - + }; public void addSerialDataObserver(Observer o) { serialDataObservable.addObserver(o); } - public void deleteSerialDataObserver(Observer o) { serialDataObservable.deleteObserver(o); } - public byte getLastSerialData() { return lastSerialData; } - - public JPanel getInterfaceVisualizer() { - JPanel panel = new JPanel(); - panel.setLayout(new BorderLayout()); - - if (logTextPane == null) { - logTextPane = new JTextArea(); + public void dataReceived(int data) { + if (data == '\n') { + /* Notify observers of new log */ + lastLogMessage = newMessage.toString(); + lastLogMessage = lastLogMessage.replaceAll("[^\\p{Print}]", ""); + newMessage.setLength(0); + this.setChanged(); + this.notifyObservers(getMote()); + } else { + newMessage.append((char) data); + if (newMessage.length() > MAX_LENGTH) { + /*logger.warn("Dropping too large log message (>" + MAX_LENGTH + " bytes).");*/ + lastLogMessage = "# [1024 bytes binary data]"; + newMessage.setLength(0); + this.setChanged(); + this.notifyObservers(getMote()); + } } - // Send RS232 data visualizer - JPanel sendPane = new JPanel(new BorderLayout()); - commandField = new JTextField(15); + /* Notify observers of new serial character */ + lastSerialData = (byte) data; + serialDataObservable.notifyNewData(); + } + + + /* Mote interface visualizer */ + public JPanel getInterfaceVisualizer() { + JPanel panel = new JPanel(new BorderLayout()); + JPanel commandPane = new JPanel(new BorderLayout()); + + final JTextArea logTextPane = new JTextArea(); + final JTextField commandField = new JTextField(15); JButton sendButton = new JButton("Send data"); - ActionListener action = new ActionListener() { + ActionListener sendCommandAction = new ActionListener() { public void actionPerformed(ActionEvent e) { - String command = trim(commandField.getText()); - if (command != null) { - try { - int previous = historyCount - 1; - if (previous < 0) { - previous += history.length; - } - if (!command.equals(history[previous])) { - history[historyCount] = command; - historyCount = (historyCount + 1) % history.length; - } - historyPos = historyCount; - - if (slipCheckbox.isSelected()) { - addToLog("SLIP> " + command); - command += "\n"; - writeArray(SLIP.asSlip(command.getBytes())); - } else { - addToLog("> " + command); - writeString(command); - } - commandField.setText(""); - } catch (Exception ex) { - System.err.println("could not send '" + command + "':"); - ex.printStackTrace(); - JOptionPane.showMessageDialog(logTextPane, - "could not send '" + command + "':\n" - + ex, "ERROR", - JOptionPane.ERROR_MESSAGE); - } - } else { + final String command = trim(commandField.getText()); + if (command == null) { commandField.getToolkit().beep(); + return; + } + + try { + /* Add to history */ + if (history.size() > 0 && command.equals(history.get(0))) { + /* Ignored */ + } else { + history.add(0, command); + while (history.size() > HISTORY_SIZE) { + history.remove(HISTORY_SIZE-1); + } + } + historyPos = -1; + + appendToTextArea(logTextPane, "> " + command); + commandField.setText(""); + if (getMote().getSimulation().isRunning()) { + getMote().getSimulation().invokeSimulationThread(new Runnable() { + public void run() { + writeString(command); + } + }); + } else { + writeString(command); + } + } catch (Exception ex) { + System.err.println("could not send '" + command + "':"); + ex.printStackTrace(); + JOptionPane.showMessageDialog( + logTextPane, + "Could not send '" + command + "':\n" + ex.getMessage(), "Error sending message", + JOptionPane.ERROR_MESSAGE); } } - }; + commandField.addActionListener(sendCommandAction); + sendButton.addActionListener(sendCommandAction); + + /* History */ commandField.addKeyListener(new KeyAdapter() { - @Override public void keyPressed(KeyEvent e) { switch (e.getKeyCode()) { case KeyEvent.VK_UP: { - int nextPos = (historyPos + history.length - 1) % history.length; - if (nextPos == historyCount || history[nextPos] == null) { + historyPos++; + if (historyPos >= history.size()) { + historyPos = history.size() - 1; commandField.getToolkit().beep(); + } + if (historyPos >= 0 && historyPos < history.size()) { + commandField.setText(history.get(historyPos)); } else { - String cmd = trim(commandField.getText()); - if (cmd != null) { - history[historyPos] = cmd; - } - historyPos = nextPos; - commandField.setText(history[historyPos]); + commandField.setText(""); } break; } case KeyEvent.VK_DOWN: { - int nextPos = (historyPos + 1) % history.length; - if (nextPos == historyCount) { - historyPos = nextPos; + historyPos--; + if (historyPos < 0) { + historyPos = -1; commandField.setText(""); - } else if (historyPos == historyCount || history[nextPos] == null) { commandField.getToolkit().beep(); + break; + } + if (historyPos >= 0 && historyPos < history.size()) { + commandField.setText(history.get(historyPos)); } else { - String cmd = trim(commandField.getText()); - if (cmd != null) { - history[historyPos] = cmd; - } - historyPos = nextPos; - commandField.setText(history[historyPos]); + commandField.setText(""); } break; } } } - }); - slipCheckbox = new JCheckBox("", false); - slipCheckbox.setToolTipText("Wrap data as SLIP"); + commandPane.add(BorderLayout.CENTER, commandField); + commandPane.add(BorderLayout.EAST, sendButton); - commandField.addActionListener(action); - sendButton.addActionListener(action); - sendPane.add(BorderLayout.WEST, slipCheckbox); - sendPane.add(BorderLayout.CENTER, commandField); - sendPane.add(BorderLayout.EAST, sendButton); - - // Receive RS232 data visualizer logTextPane.setOpaque(false); logTextPane.setEditable(false); logTextPane.addKeyListener(new KeyAdapter() { @@ -223,52 +225,28 @@ public abstract class SerialUI extends Log implements SerialPort { commandField.requestFocusInWindow(); } }); - if (getLastLogMessage() == null) { - logTextPane.setText(""); - } else { - logTextPane.append(getLastLogMessage()); - } + /* Mote interface observer */ Observer observer; this.addObserver(observer = new Observer() { public void update(Observable obs, Object obj) { final String logMessage = getLastLogMessage(); EventQueue.invokeLater(new Runnable() { public void run() { - addToLog(logMessage); + appendToTextArea(logTextPane, logMessage); } }); } }); - - // Saving observer reference for releaseInterfaceVisualizer panel.putClientProperty("intf_obs", observer); JScrollPane scrollPane = new JScrollPane(logTextPane); scrollPane.setPreferredSize(new Dimension(100, 100)); - panel.add(BorderLayout.NORTH, new JLabel("Last serial data:")); panel.add(BorderLayout.CENTER, scrollPane); - panel.add(BorderLayout.SOUTH, sendPane); + panel.add(BorderLayout.SOUTH, commandPane); return panel; } - protected void addToLog(String text) { - String current = logTextPane.getText(); - int len = current.length(); - if (len > 8192) { - current = current.substring(len - 8192); - } - current = len > 0 ? (current + '\n' + text) : text; - logTextPane.setText(current); - logTextPane.setCaretPosition(current.length()); - - Rectangle visRect = logTextPane.getVisibleRect(); - if (visRect.x > 0) { - visRect.x = 0; - logTextPane.scrollRectToVisible(visRect); - } - } - public void releaseInterfaceVisualizer(JPanel panel) { Observer observer = (Observer) panel.getClientProperty("intf_obs"); if (observer == null) { @@ -279,13 +257,14 @@ public abstract class SerialUI extends Log implements SerialPort { this.deleteObserver(observer); } + private static final String HISTORY_SEPARATOR = "~;"; public Collection getConfigXML() { StringBuilder sb = new StringBuilder(); for (String s: history) { if (s == null) { continue; } - sb.append(s + "~;"); + sb.append(s + HISTORY_SEPARATOR); } if (sb.length() == 0) { return null; @@ -302,101 +281,42 @@ public abstract class SerialUI extends Log implements SerialPort { public void setConfigXML(Collection configXML, boolean visAvailable) { for (Element element : configXML) { if (element.getName().equals("history")) { - String[] history = element.getText().split("~;"); - System.arraycopy(history, 0, this.history, 0, history.length); - historyCount = history.length; - historyPos = historyCount; + String[] history = element.getText().split(HISTORY_SEPARATOR); + for (String h: history) { + this.history.add(h); + } + historyPos = -1; } } } - private int tosChars = 0; - boolean tosMode = false; - private int tosPos = 0; - private int tosLen = 0; - - private int slipCounter = 0; - private int totalTOSChars = 0; - - public void dataReceived(int data) { - if (data == SLIP_END || data == SLIP_ESC) { - slipCounter++; - } - if (tosMode) { - int tmpData = data; - /* needs to add checks to CRC */ - // System.out.println("Received: " + Integer.toString(data, 16) + " = " + (char) data + " tosPos: " + tosPos); - if (data == 0x7e) { - if (tosPos > 6) { - lastLogMessage = "TinyOS: " + newMessage.toString(); - newMessage.setLength(0); - this.setChanged(); - this.notifyObservers(getMote()); - // System.out.println("*** Printing TOS String: " + lastLogMessage); - tosPos = 0; - tosLen = 0; - } else { - /* start of new message! */ - tosPos = 0; - tosLen = 0; - } - } - if (tosPos == 7) { - tosLen = data; - // System.out.println("TOS Payload len: " + tosLen); - } - if (tosPos > 9 && tosPos < 10 + tosLen) { - if (data < 32) { - tmpData = 32; - } - newMessage.append((char) tmpData); - } - } else { - if (data == 0x7e) { - tosChars++; - totalTOSChars = 0; /* XXX Disabled TOS mode due to error */ - totalTOSChars++; - if (tosChars == 2) { - if (totalTOSChars > slipCounter) { - tosMode = true; - tosMode = false; /* XXX Disabled TOS mode due to error */ - /* already read one char here */ - tosPos = 1; - } else { - tosChars = 0; - } - } - } else { - tosChars = 0; - } - if (data == '\n') { - lastLogMessage = newMessage.toString(); - lastLogMessage = lastLogMessage.replaceAll("[^\\p{Print}]", ""); - newMessage.setLength(0); - this.setChanged(); - this.notifyObservers(getMote()); - } else { - newMessage.append((char) data); - if (newMessage.length() > MAX_LENGTH) { - /*logger.warn("Dropping too large log message (>" + MAX_LENGTH + " bytes).");*/ - lastLogMessage = "# [1024 bytes binary data]"; - this.setChanged(); - this.notifyObservers(getMote()); - newMessage.setLength(0); - } - } - } - lastSerialData = (byte) data; - serialDataObservable.notifyNewData(); - } - public void close() { } public void flushInput() { } - private String trim(String text) { + public abstract Mote getMote(); + + + protected static void appendToTextArea(JTextArea textArea, String text) { + String current = textArea.getText(); + int len = current.length(); + if (len > 8192) { + current = current.substring(len - 8192); + } + current = len > 0 ? (current + '\n' + text) : text; + textArea.setText(current); + textArea.setCaretPosition(current.length()); + + Rectangle visRect = textArea.getVisibleRect(); + if (visRect.x > 0) { + visRect.x = 0; + textArea.scrollRectToVisible(visRect); + } + } + + private static String trim(String text) { return (text != null) && ((text = text.trim()).length() > 0) ? text : null; } } From 107bdf116d187b1fc450471922b23d444c433e19 Mon Sep 17 00:00:00 2001 From: Adam Dunkels Date: Fri, 8 Jun 2012 14:30:51 +0200 Subject: [PATCH 05/12] Updated file permissions --- tools/cooja/apps/mspsim/exp5438.png | Bin tools/cooja/apps/mspsim/tyndall.png | Bin tools/cooja/config/external_tools.config | 0 tools/cooja/java/se/sics/cooja/HasQuickHelp.java | 0 4 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 tools/cooja/apps/mspsim/exp5438.png mode change 100755 => 100644 tools/cooja/apps/mspsim/tyndall.png mode change 100755 => 100644 tools/cooja/config/external_tools.config mode change 100755 => 100644 tools/cooja/java/se/sics/cooja/HasQuickHelp.java diff --git a/tools/cooja/apps/mspsim/exp5438.png b/tools/cooja/apps/mspsim/exp5438.png old mode 100755 new mode 100644 diff --git a/tools/cooja/apps/mspsim/tyndall.png b/tools/cooja/apps/mspsim/tyndall.png old mode 100755 new mode 100644 diff --git a/tools/cooja/config/external_tools.config b/tools/cooja/config/external_tools.config old mode 100755 new mode 100644 diff --git a/tools/cooja/java/se/sics/cooja/HasQuickHelp.java b/tools/cooja/java/se/sics/cooja/HasQuickHelp.java old mode 100755 new mode 100644 From 4861aadb94e1867aa8d35d5862d722f2427e8253 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Fri, 8 Jun 2012 12:16:47 +0200 Subject: [PATCH 06/12] Added nmenomic for the exit action --- tools/cooja/java/se/sics/cooja/GUI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/cooja/java/se/sics/cooja/GUI.java b/tools/cooja/java/se/sics/cooja/GUI.java index 603517821..bd0985e17 100644 --- a/tools/cooja/java/se/sics/cooja/GUI.java +++ b/tools/cooja/java/se/sics/cooja/GUI.java @@ -4479,7 +4479,7 @@ public class GUI extends Observable { return getSimulation() != null; } }; - GUIAction exitCoojaAction = new GUIAction("Exit") { + GUIAction exitCoojaAction = new GUIAction("Exit", 'x') { private static final long serialVersionUID = 7523822251658687665L; public void actionPerformed(ActionEvent e) { myGUI.doQuit(true); From 46d1367566a622c65c4bd9429ee30f38084f6075 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Fri, 8 Jun 2012 17:06:29 +0200 Subject: [PATCH 07/12] Fixed compiler unchecked warning --- tools/cooja/java/se/sics/cooja/MoteInterfaceHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/cooja/java/se/sics/cooja/MoteInterfaceHandler.java b/tools/cooja/java/se/sics/cooja/MoteInterfaceHandler.java index a146f7fe1..34ab35327 100644 --- a/tools/cooja/java/se/sics/cooja/MoteInterfaceHandler.java +++ b/tools/cooja/java/se/sics/cooja/MoteInterfaceHandler.java @@ -105,8 +105,8 @@ public class MoteInterfaceHandler { */ public N getInterfaceOfType(Class interfaceType) { for (MoteInterface intf : moteInterfaces) { - if (interfaceType.isAssignableFrom(intf.getClass())) { - return (N) intf; + if (interfaceType.isInstance(intf)) { + return interfaceType.cast(intf); } } From 4a96e12890a588b5d81231724a2adf9b90c6214f Mon Sep 17 00:00:00 2001 From: Matthias Kovatsch Date: Sat, 9 Jun 2012 10:47:09 +0200 Subject: [PATCH 08/12] Added Giovanni Pellerano's radio resource. --- examples/er-rest-example/er-example-server.c | 69 ++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/examples/er-rest-example/er-example-server.c b/examples/er-rest-example/er-example-server.c index 45bbea68b..e9cc9d4ba 100644 --- a/examples/er-rest-example/er-example-server.c +++ b/examples/er-rest-example/er-example-server.c @@ -54,6 +54,7 @@ #define REST_RES_TOGGLE 1 #define REST_RES_LIGHT 0 #define REST_RES_BATTERY 0 +#define REST_RES_RADIO 1 @@ -80,6 +81,9 @@ #if defined (PLATFORM_HAS_SHT11) #include "dev/sht11-sensor.h" #endif +#if defined (PLATFORM_HAS_RADIO) +#include "dev/radio-sensor.h" +#endif /* For CoAP-specific example: not required for normal RESTful Web service. */ @@ -672,6 +676,67 @@ battery_handler(void* request, void* response, uint8_t *buffer, uint16_t preferr #endif /* PLATFORM_HAS_BATTERY */ +#if defined (PLATFORM_HAS_RADIO) && REST_RES_RADIO +/* A simple getter example. Returns the reading of the rssi/lqi from radio sensor */ +RESOURCE(radio, METHOD_GET, "sensor/radio", "title=\"RADIO: ?p=lqi|rssi\";rt=\"RadioSensor\""); + +void +radio_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + size_t len = 0; + const char *p = NULL; + uint8_t param = 0; + int success = 1; + + const uint16_t *accept = NULL; + int num = REST.get_header_accept(request, &accept); + + if ((len=REST.get_query_variable(request, "p", &p))) { + PRINTF("p %.*s\n", len, p); + if (strncmp(p, "lqi", len)==0) { + param = RADIO_SENSOR_LAST_VALUE; + } else if(strncmp(p,"rssi", len)==0) { + param = RADIO_SENSOR_LAST_PACKET; + } else { + success = 0; + } + } else { + success = 0; + } + + if (success) { + if ((num==0) || (num && accept[0]==REST.type.TEXT_PLAIN)) + { + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", radio_sensor.value(param)); + + REST.set_response_payload(response, (uint8_t *)buffer, strlen(buffer)); + } + else if (num && (accept[0]==REST.type.APPLICATION_JSON)) + { + REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + + if (param == RADIO_SENSOR_LAST_VALUE) { + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'lqi':%d}", radio_sensor.value(param)); + } else if (param == RADIO_SENSOR_LAST_PACKET) { + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'rssi':%d}", radio_sensor.value(param)); + } + + REST.set_response_payload(response, buffer, strlen(buffer)); + } + else + { + REST.set_response_status(response, REST.status.UNSUPPORTED_MADIA_TYPE); + const char *msg = "Supporting content-types text/plain and application/json"; + REST.set_response_payload(response, msg, strlen(msg)); + } + } else { + REST.set_response_status(response, REST.status.BAD_REQUEST); + } +} +#endif + + PROCESS(rest_server_example, "Erbium Example Server"); AUTOSTART_PROCESSES(&rest_server_example); @@ -742,6 +807,10 @@ PROCESS_THREAD(rest_server_example, ev, data) SENSORS_ACTIVATE(battery_sensor); rest_activate_resource(&resource_battery); #endif +#if defined (PLATFORM_HAS_RADIO) && REST_RES_RADIO + SENSORS_ACTIVATE(radio_sensor); + rest_activate_resource(&resource_radio); +#endif /* Define application-specific events here. */ while(1) { From 6c813f0fb1331bb4790b69c9261a0f58e10bfff3 Mon Sep 17 00:00:00 2001 From: Matthias Kovatsch Date: Sat, 9 Jun 2012 11:14:25 +0200 Subject: [PATCH 09/12] Fixed bug in debug print noticed by Linus. --- examples/er-rest-example/er-example-server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/er-rest-example/er-example-server.c b/examples/er-rest-example/er-example-server.c index e9cc9d4ba..cccafb26b 100644 --- a/examples/er-rest-example/er-example-server.c +++ b/examples/er-rest-example/er-example-server.c @@ -95,7 +95,7 @@ #warning "Erbium example without CoAP-specifc functionality" #endif /* CoAP-specific example */ -#define DEBUG 0 +#define DEBUG 1 #if DEBUG #define PRINTF(...) printf(__VA_ARGS__) #define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) @@ -479,7 +479,7 @@ pushing_periodic_handler(resource_t *r) ++obs_counter; - PRINTF("TICK %u for /%s\n", periodic_i, r->url); + PRINTF("TICK %u for /%s\n", obs_counter, r->url); /* Build notification. */ coap_packet_t notification[1]; /* This way the packet can be treated as pointer as usual. */ From ed66cfa3643f9eab94a761dd1a33f497bcf01ce2 Mon Sep 17 00:00:00 2001 From: Matthias Kovatsch Date: Sat, 9 Jun 2012 11:18:51 +0200 Subject: [PATCH 10/12] Disabled debugging. --- examples/er-rest-example/er-example-server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/er-rest-example/er-example-server.c b/examples/er-rest-example/er-example-server.c index cccafb26b..5a7da5496 100644 --- a/examples/er-rest-example/er-example-server.c +++ b/examples/er-rest-example/er-example-server.c @@ -95,7 +95,7 @@ #warning "Erbium example without CoAP-specifc functionality" #endif /* CoAP-specific example */ -#define DEBUG 1 +#define DEBUG 0 #if DEBUG #define PRINTF(...) printf(__VA_ARGS__) #define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) From 9096da299e05ae9bee26d96e5001601d45db3fe4 Mon Sep 17 00:00:00 2001 From: Matthias Kovatsch Date: Sat, 9 Jun 2012 12:20:57 +0200 Subject: [PATCH 11/12] Added sub-resource example. --- examples/er-rest-example/er-example-server.c | 58 ++++++++++++++++---- 1 file changed, 46 insertions(+), 12 deletions(-) diff --git a/examples/er-rest-example/er-example-server.c b/examples/er-rest-example/er-example-server.c index 5a7da5496..aff33e10b 100644 --- a/examples/er-rest-example/er-example-server.c +++ b/examples/er-rest-example/er-example-server.c @@ -50,6 +50,7 @@ #define REST_RES_SEPARATE 1 #define REST_RES_PUSHING 1 #define REST_RES_EVENT 1 +#define REST_RES_SUB 1 #define REST_RES_LEDS 1 #define REST_RES_TOGGLE 1 #define REST_RES_LIGHT 0 @@ -533,6 +534,36 @@ event_event_handler(resource_t *r) } #endif /* PLATFORM_HAS_BUTTON */ +/******************************************************************************/ +#if REST_RES_SUB +/* + * Example for a resource that also handles all its sub-resources. + * Use REST.get_url() to multiplex the handling of the request depending on the Uri-Path. + */ +RESOURCE(sub, METHOD_GET | HAS_SUB_RESOURCES, "test/path", "title=\"Sub-resource demo\""); + +void +sub_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + + const char *uri_path = NULL; + int len = REST.get_url(request, &uri_path); + int base_len = strlen(resource_sub.url); + + if (len==base_len) + { + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "Request any sub-resource of /%s", resource_sub.url); + } + else + { + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, ".%s", uri_path+base_len); + } + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); +} +#endif + /******************************************************************************/ #if defined (PLATFORM_HAS_LEDS) /******************************************************************************/ @@ -613,23 +644,23 @@ light_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred if ((num==0) || (num && accept[0]==REST.type.TEXT_PLAIN)) { REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf(buffer, REST_MAX_CHUNK_SIZE, "%u;%u", light_photosynthetic, light_solar); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%u;%u", light_photosynthetic, light_solar); - REST.set_response_payload(response, (uint8_t *)buffer, strlen(buffer)); + REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); } else if (num && (accept[0]==REST.type.APPLICATION_XML)) { REST.set_header_content_type(response, REST.type.APPLICATION_XML); - snprintf(buffer, REST_MAX_CHUNK_SIZE, "", light_photosynthetic, light_solar); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "", light_photosynthetic, light_solar); - REST.set_response_payload(response, buffer, strlen(buffer)); + REST.set_response_payload(response, buffer, strlen((char *)buffer)); } else if (num && (accept[0]==REST.type.APPLICATION_JSON)) { REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf(buffer, REST_MAX_CHUNK_SIZE, "{'light':{'photosynthetic':%u,'solar':%u}}", light_photosynthetic, light_solar); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'light':{'photosynthetic':%u,'solar':%u}}", light_photosynthetic, light_solar); - REST.set_response_payload(response, buffer, strlen(buffer)); + REST.set_response_payload(response, buffer, strlen((char *)buffer)); } else { @@ -655,16 +686,16 @@ battery_handler(void* request, void* response, uint8_t *buffer, uint16_t preferr if ((num==0) || (num && accept[0]==REST.type.TEXT_PLAIN)) { REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf(buffer, REST_MAX_CHUNK_SIZE, "%d", battery); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", battery); - REST.set_response_payload(response, (uint8_t *)buffer, strlen(buffer)); + REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); } else if (num && (accept[0]==REST.type.APPLICATION_JSON)) { REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf(buffer, REST_MAX_CHUNK_SIZE, "{'battery':%d}", battery); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'battery':%d}", battery); - REST.set_response_payload(response, buffer, strlen(buffer)); + REST.set_response_payload(response, buffer, strlen((char *)buffer)); } else { @@ -710,7 +741,7 @@ radio_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred REST.set_header_content_type(response, REST.type.TEXT_PLAIN); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", radio_sensor.value(param)); - REST.set_response_payload(response, (uint8_t *)buffer, strlen(buffer)); + REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); } else if (num && (accept[0]==REST.type.APPLICATION_JSON)) { @@ -722,7 +753,7 @@ radio_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'rssi':%d}", radio_sensor.value(param)); } - REST.set_response_payload(response, buffer, strlen(buffer)); + REST.set_response_payload(response, buffer, strlen((char *)buffer)); } else { @@ -791,6 +822,9 @@ PROCESS_THREAD(rest_server_example, ev, data) #if defined (PLATFORM_HAS_BUTTON) && (REST_RES_EVENT || (REST_RES_SEPARATE && WITH_COAP > 3)) SENSORS_ACTIVATE(button_sensor); #endif +#if REST_RES_SUB + rest_activate_resource(&resource_sub); +#endif #if defined (PLATFORM_HAS_LEDS) #if REST_RES_LEDS rest_activate_resource(&resource_leds); From 37c407b177b17d8424d65c66129210e0dd2f9419 Mon Sep 17 00:00:00 2001 From: David Kopf Date: Sun, 10 Jun 2012 12:54:11 -0400 Subject: [PATCH 12/12] Patch from Landon Fuller adds const to PROGMEM, required for newer avr-gcc --- examples/webserver-ipv6-raven/Huginn/makefsdata.h | 6 +++--- examples/webserver-ipv6-raven/Muninn/makefsdata.h | 6 +++--- .../apps/raven-webserver/httpd-fs/makefsdata.h | 6 +++--- .../avr-atmega128rfa1/apps/raven-webserver/httpd-fsdata.c | 6 +++--- .../avr-raven/apps/raven-webserver/httpd-fs/makefsdata.h | 6 +++--- platform/avr-raven/apps/raven-webserver/httpd.c | 2 -- 6 files changed, 15 insertions(+), 17 deletions(-) diff --git a/examples/webserver-ipv6-raven/Huginn/makefsdata.h b/examples/webserver-ipv6-raven/Huginn/makefsdata.h index 654cb1eab..96e60c27b 100644 --- a/examples/webserver-ipv6-raven/Huginn/makefsdata.h +++ b/examples/webserver-ipv6-raven/Huginn/makefsdata.h @@ -1,9 +1,9 @@ #include /* Link layer ipv6 address will become fe80::2 */ -uint8_t default_mac_address[8] PROGMEM = {0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}; -uint8_t default_server_name[16] PROGMEM = "huginn"; -uint8_t default_domain_name[30] PROGMEM = "localhost"; +const uint8_t default_mac_address[8] PROGMEM = {0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}; +const uint8_t default_server_name[16] PROGMEM = "huginn"; +const uint8_t default_domain_name[30] PROGMEM = "localhost"; uint8_t eemem_mac_address[8] EEMEM = {0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}; uint8_t eemem_server_name[16] EEMEM = "huginn"; uint8_t eemem_domain_name[30] EEMEM = "localhost"; diff --git a/examples/webserver-ipv6-raven/Muninn/makefsdata.h b/examples/webserver-ipv6-raven/Muninn/makefsdata.h index 51b1a428e..f0da8091a 100644 --- a/examples/webserver-ipv6-raven/Muninn/makefsdata.h +++ b/examples/webserver-ipv6-raven/Muninn/makefsdata.h @@ -1,9 +1,9 @@ #include /* Link layer ipv6 address will become fe80::1 */ -uint8_t default_mac_address[8] PROGMEM = {0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; -uint8_t default_server_name[16] PROGMEM = "muninn"; -uint8_t default_domain_name[30] PROGMEM = "localhost"; +const uint8_t default_mac_address[8] PROGMEM = {0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; +const uint8_t default_server_name[16] PROGMEM = "muninn"; +const uint8_t default_domain_name[30] PROGMEM = "localhost"; uint8_t eemem_mac_address[8] EEMEM = {0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; uint8_t eemem_server_name[16] EEMEM = "muninn"; uint8_t eemem_domain_name[30] EEMEM = "localhost"; diff --git a/platform/avr-atmega128rfa1/apps/raven-webserver/httpd-fs/makefsdata.h b/platform/avr-atmega128rfa1/apps/raven-webserver/httpd-fs/makefsdata.h index f532f75e3..512484802 100644 --- a/platform/avr-atmega128rfa1/apps/raven-webserver/httpd-fs/makefsdata.h +++ b/platform/avr-atmega128rfa1/apps/raven-webserver/httpd-fs/makefsdata.h @@ -1,9 +1,9 @@ #include /* Link layer ipv6 address will become fe80::ff:fe:1 */ -uint8_t default_mac_address[8] PROGMEM = {0x02, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x01}; -uint8_t default_server_name[16] PROGMEM = "ATMEGA128rfa1"; -uint8_t default_domain_name[30] PROGMEM = "localhost"; +const uint8_t default_mac_address[8] PROGMEM = {0x02, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x01}; +const uint8_t default_server_name[16] PROGMEM = "ATMEGA128rfa1"; +const uint8_t default_domain_name[30] PROGMEM = "localhost"; uint8_t eemem_mac_address[8] EEMEM = {0x02, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x01}; uint8_t eemem_server_name[16] EEMEM = "ATMEGA128rfa1"; uint8_t eemem_domain_name[30] EEMEM = "localhost"; diff --git a/platform/avr-atmega128rfa1/apps/raven-webserver/httpd-fsdata.c b/platform/avr-atmega128rfa1/apps/raven-webserver/httpd-fsdata.c index 68d44b750..ff217b0f7 100644 --- a/platform/avr-atmega128rfa1/apps/raven-webserver/httpd-fsdata.c +++ b/platform/avr-atmega128rfa1/apps/raven-webserver/httpd-fsdata.c @@ -4,9 +4,9 @@ /* Link layer ipv6 address will become fe80::ff:fe:1 */ -uint8_t default_mac_address[8] PROGMEM = {0x02, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x01}; -uint8_t default_server_name[16] PROGMEM = "ATMEGA128rfa1"; -uint8_t default_domain_name[30] PROGMEM = "localhost"; +const uint8_t default_mac_address[8] PROGMEM = {0x02, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x01}; +const uint8_t default_server_name[16] PROGMEM = "ATMEGA128rfa1"; +const uint8_t default_domain_name[30] PROGMEM = "localhost"; uint8_t eemem_mac_address[8] EEMEM = {0x02, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x01}; uint8_t eemem_server_name[16] EEMEM = "ATMEGA128rfa1"; uint8_t eemem_domain_name[30] EEMEM = "localhost"; diff --git a/platform/avr-raven/apps/raven-webserver/httpd-fs/makefsdata.h b/platform/avr-raven/apps/raven-webserver/httpd-fs/makefsdata.h index b146f8dc6..d9e704ef2 100644 --- a/platform/avr-raven/apps/raven-webserver/httpd-fs/makefsdata.h +++ b/platform/avr-raven/apps/raven-webserver/httpd-fs/makefsdata.h @@ -1,9 +1,9 @@ #include /* Link layer ipv6 address will become fe80::11:22ff:fe33:4455 */ -uint8_t default_mac_address[8] PROGMEM = {0x02, 0x11, 0x22, 0xff, 0xfe, 0x33, 0x44, 0x55}; -uint8_t default_server_name[16] PROGMEM = "Contiki-Raven"; -uint8_t default_domain_name[30] PROGMEM = "localhost"; +const uint8_t default_mac_address[8] PROGMEM = {0x02, 0x11, 0x22, 0xff, 0xfe, 0x33, 0x44, 0x55}; +const uint8_t default_server_name[16] PROGMEM = "Contiki-Raven"; +const uint8_t default_domain_name[30] PROGMEM = "localhost"; uint8_t eemem_mac_address[8] EEMEM = {0x02, 0x11, 0x22, 0xff, 0xfe, 0x33, 0x44, 0x55}; uint8_t eemem_server_name[16] EEMEM = "Contiki-Raven"; uint8_t eemem_domain_name[30] EEMEM = "localhost"; diff --git a/platform/avr-raven/apps/raven-webserver/httpd.c b/platform/avr-raven/apps/raven-webserver/httpd.c index 17a1032ff..1327ca6ad 100644 --- a/platform/avr-raven/apps/raven-webserver/httpd.c +++ b/platform/avr-raven/apps/raven-webserver/httpd.c @@ -307,8 +307,6 @@ generate_header(void *hstr) #endif } /*---------------------------------------------------------------------------*/ -char http_htm[10] PROGMEM ="text/html"; -char http_css[ 9] PROGMEM ="text/css"; const char httpd_mime_htm[] HTTPD_STRING_ATTR = "text/html"; const char httpd_mime_css[] HTTPD_STRING_ATTR = "text/css"; const char httpd_mime_png[] HTTPD_STRING_ATTR = "image/png";