====== Workshop: Erstellung eines einfachen UDP Service mit Contiki ======
==== 1. Installation der Entwicklungsumgebung: Instant Contiki ====
* Die Installation von [[http://www.contiki-os.org/start.html|Instant Contiki]] benötigt [[http://www.vmware.com/go/downloadplayer/|VMWare Player]], oder [[https://www.virtualbox.org/wiki/Downloads|Virtualbox]]
* Anmeldung an //Instant Contiki// mit dem Passwort: ''user''
* Die folgende Beschreibung bezieht sich immer auf das Quellcode-Verzeichnis: ''/home/user/contiki-3.0/''
==== 2. Anpassungen des Quellcodes ====
Im Workshop werden Contiki-Anwendungen direkt in //Instant Contiki// auf dem Entwicklungsrechner ausgeführt. Dazu müssen einige Veränderungen an Quellcode-Dateien vorgenommen werden. Im ersten Schritt wird die Anwendung für IPv4 erstellt. Die Anpassung für IPv6, sowie die Kompilierung für weitere Hardwareplattformen (Mikrocontrollerboards) ist später möglich.
=== 2.1 Erstellen eines neuen Projekt-Verzeichnisses ===
- Erstellen Sie das Verzeichnis: ''/home/user/contiki-3.0/examples/simpleUDP''
=== 2.2 Erstellen des Makefiles ===
Für das Projekt werden eine C-Datei und ein Makefile benötigt.
- Erstellen Sie folgendes ''Makefile'' im Verzeichnis (für IPv4):
CONTIKI_PROJECT = simpleUDP
all: $(CONTIKI_PROJECT)
WITH_UIP=1
CONTIKI = ../..
include $(CONTIKI)/Makefile.include
Für die Verwendung von IPv6 verwenden Sie das folgende Makefile:
CONTIKI_PROJECT = simpleUDP
all: $(CONTIKI_PROJECT)
UIP_CONF_IPV6=1
UIP_CONF_RPL=0
CFLAGS += -DUIP_CONF_IPV6=1
CONTIKI = ../..
include $(CONTIKI)/Makefile.include
=== 2.3 Erstellen des Quellcodes ===
- Erstellen Sie die C-Datei ''simpleUDP.c'':
/**
* \file
* A very simple Contiki UDP application
* \author
* Thomas Scheffler, Sven Zehl
*/
#include "contiki.h"
#include "contiki-lib.h"
#include "contiki-net.h"
#include "net/ip/uip.h"
#include "net/netstack.h"
#include /* For printf() */
#include
#include
#include
#define UDP_IP_BUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
/*---------------------------------------------------------------------------*/
PROCESS(simpleUDP_process, "Simple UDP process");
AUTOSTART_PROCESSES(&simpleUDP_process);
/*---------------------------------------------------------------------------*/
static struct uip_udp_conn *udpconn;
#define MAX_PAYLOAD_LEN 120
void bsp_udphandler(void)
{
char buf[MAX_PAYLOAD_LEN];
if(uip_newdata())
{
/*Zeige Benutzer den Inhalt der empfangenen Nachricht*/
/*Setze letztes Byte zu Null, fuer String Ende*/
((char *)uip_appdata)[uip_datalen()] = 0;
printf("Server received: %s\n", (char *)uip_appdata);
/*Verwende die Quell- als Zieladresse fuer Antwort */
uip_ipaddr_copy(&udpconn->ripaddr, &UDP_IP_BUF->srcipaddr);
udpconn->rport = UDP_IP_BUF->srcport;
/*Schreibe Antwort-Daten in Buffer*/
sprintf(buf, "Hello from the server");
/*Versende das Antwort-Packet*/
uip_udp_packet_send(udpconn, buf, strlen(buf));
/*Setze Adresse/Port in Verbindungsstruktur auf Null,*/
/*um von jedem Absender Daten empfangen zu koennen*/
memset(&udpconn->ripaddr, 0, sizeof(udpconn->ripaddr));
udpconn->rport = 0;
}
}
PROCESS_THREAD(simpleUDP_process, ev, data)
{
PROCESS_BEGIN();
printf("UDP Echo Server\n");
/*Starte neue UDP Verbindung mit IP 0.0.0.0 und Port 0, */
/* d.h. akzeptiere jede ankommende Verbindung*/
udpconn = udp_new(NULL, UIP_HTONS(0), NULL);
/*Setze den Port auf dem gelauscht wird auf 49999*/
/*HTONS() uebersetzt zur Network Byte Order*/
udp_bind(udpconn, UIP_HTONS(49999));
printf("listening on UDP port %u\n", UIP_HTONS(udpconn->lport));
while(1) {
/* Warte bis ein TCP/IP Event eintrifft */
PROCESS_WAIT_EVENT_UNTIL(ev == tcpip_event);
/*Rufe die Handler-Funktion auf*/
bsp_udphandler();
}
PROCESS_END();
}
==== 3. Übersetzen des UDP Services ====
Im Anschluss kann der UDP Service mit Hilfe des Makefiles übersetzt werden:
make TARGET=minimal-net
Sollte es notwenig sein nachträglich Änderungen am Makefile durchzuführen (zum Beispiel
um zwischen IPv4 und IPv6 zu wechseln), sollte das
Projekt vor der erneuten Übersetzung zurückgesetzt werden:
make TARGET=minimal-net clean
==== 4. Ausführung des UDP-Service ====
Nach der erfolgreichen Übersetzung kann die Anwendung gestartet werden. Das muss
mit dem Befehl ''sudo'' erfolgen. Dazu muss evtl. das Passwort ''user'' erneut eingegeben
werden:
sudo ./simpleUDP.minimal-net
Contiki richtet jetzt ein neues Netzwerkinterface ''tap0'' ein und startet den UDP-Service.
Dabei werden die verwendeten Netzwerkeinstellungen angezeigt.
Anschließend kann über ein zweites Terminalfenster des Entwicklungssystems auf den Contiki-Service zugegriffen
werden.
==== 5. Interaktion mit dem UDP-Service ====
Starten Sie ein zweites Terminalfenster und testen Sie den Service
- Pingen Sie den Contiki UDP-Service: ping 172.18.0.2
- Senden Sie mit dem Programm ''netcat'' Daten an den Contiki UDP-Service: netcat -u 172.18.0.2 49999
Beobachten Sie die Ausgabe des Services, sowie die vom Service gesendete Antwort. Sie sollten mit dem Service kommunizieren können.
==== 6. Contiki UDP-Client ====
/**
* \file
* A very simple Contiki UDP Client
* \author
* Thomas Scheffler
*/
#include "contiki.h"
#include "sys/ctimer.h"
#include "sys/etimer.h"
#include "net/ip/uip.h"
#include "net/ipv6/uip-ds6.h"
#include
#include
#include "simple-udp.h"
#define UDP_PORT 40000
#define SEND_INTERVAL (10 * CLOCK_SECOND)
static struct simple_udp_connection client_connection;
/*---------------------------------------------------------------------------*/
PROCESS(client_example_process, "UDP client example process");
AUTOSTART_PROCESSES(&client_example_process);
/*---------------------------------------------------------------------------*/
static void
receiver(struct simple_udp_connection *c,
const uip_ipaddr_t *sender_addr,
uint16_t sender_port,
const uip_ipaddr_t *receiver_addr,
uint16_t receiver_port,
const uint8_t *data,
uint16_t datalen)
{
printf("Data received on port %d from port %d with length %d\n",
receiver_port, sender_port, datalen);
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(client_example_process, ev, data)
{
static struct etimer periodic_timer;
uip_ipaddr_t addr;
PROCESS_BEGIN();
//ohne simple_udp_register funktioniert das Senden nicht!
simple_udp_register(&client_connection, UDP_PORT,
NULL, UDP_PORT, receiver);
etimer_set(&periodic_timer, SEND_INTERVAL);
while(1)
{
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&periodic_timer));
etimer_reset(&periodic_timer);
printf("Sending UDP-Packet\n");
// senden auf die eigene Adresse 172.18.0.2 funktioniert bei
// Instant-Contiki nicht: arp auf tun0-Interface?
//uip_ipaddr(&addr, 172,18,0,1);
uip_ipaddr(&addr, 127,0,0,1);
simple_udp_sendto(&client_connection, "Test", 4, &addr);
}
PROCESS_END();
}