user
/home/user/contiki-3.0/
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.
/home/user/contiki-3.0/examples/simpleUDP
Für das Projekt werden eine C-Datei und ein Makefile benötigt.
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
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 <stdio.h> /* For printf() */ #include <stdlib.h> #include <string.h> #include <ctype.h> #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(); }
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
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.
Starten Sie ein zweites Terminalfenster und testen Sie den Service
ping 172.18.0.2
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.
/** * \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 <stdio.h> #include <string.h> #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(); }