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