├── CoAPEngine.cpp ├── CoAPEngine.h ├── ICMP_Constants.h ├── MACLayer.h ├── ND_Constants.h ├── PicoIPv6Connection.h ├── PicoIPv6State.cpp ├── PicoIPv6State.h ├── PicoIPv6StateConnectedState.cpp ├── PicoIPv6StateConnectedState.h ├── PicoIPv6StateSearchingDIOState.cpp ├── PicoIPv6StateSearchingDIOState.h ├── PicoIPv6StateSendingDAOState.cpp ├── PicoIPv6StateSendingDAOState.h ├── README.md ├── RPL_Constants.h ├── XBee.cpp ├── XBee.h ├── XBeeMACLayer.cpp ├── XBeeMACLayer.h ├── arduino_debug.cpp ├── arduino_debug.h ├── clock.c ├── clock.h ├── conf.h ├── examples ├── .DS_Store ├── CoAP │ └── CoAPSendPeriodic │ │ ├── .DS_Store │ │ ├── CoAPSendPeriodic.h │ │ └── CoAPSendPeriodic.pde ├── Old │ ├── picoIPv6UDPEco.h │ ├── picoIPv6UDPEco.inojo │ ├── picoIPv6UDPEco.old.inojo │ ├── picoIPv6UDPReceive.h │ └── picoIPv6UDPReceive.inojo └── UDP │ ├── .DS_Store │ ├── UDPReceiveAndSendEcho │ ├── .DS_Store │ ├── UDPReceiveAndSendEcho.h │ └── UDPReceiveAndSendEcho.pde │ ├── UDPReceiveCallbackSendEchoInverted │ ├── .DS_Store │ ├── UDPReceiveCallbackSendEchoInverted.h │ └── UDPReceiveCallbackSendEchoInverted.pde │ └── UDPSendPeriodic │ ├── .DS_Store │ ├── UDPSendPeriodic.h │ └── UDPSendPeriodic.pde ├── keywords.txt ├── picoIPv6MacV1.ino ├── rimeaddr.c ├── rimeaddr.h ├── sicsLowPan.c ├── sicsLowPan.h ├── timer.c ├── timer.h └── tutorial ├── .DS_Store ├── ipv6config_generic_comands.txt ├── nat66_linux_deployment.zip └── picoIPv6_tutorial.txt /CoAPEngine.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imt-atlantique/Arduino-pIPv6Stack/07a05a8be4c7b9f58714d8e410bfba70f5f62e0c/CoAPEngine.cpp -------------------------------------------------------------------------------- /CoAPEngine.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CoAPEngine.h 3 | * 4 | * Created on: Apr 12, 2013 5 | * Author: rnavas 6 | */ 7 | 8 | #ifndef COAPENGINE_H_ 9 | #define COAPENGINE_H_ 10 | 11 | #include "Arduino.h" 12 | #include "PicoIPv6Connection.h" 13 | 14 | 15 | 16 | class CoAPEngine { 17 | private: 18 | PicoIPv6Connection picoIPv6Connection; 19 | 20 | static const u16_t coap_port = 5683; // CoAP packets are sent 5683 by default. 21 | static const u16_t source_port = 61616; // UDP Source Port Number. Chosed 61616 (0xF0B0) for 6lowpan compression from 16 to 4 bits http://tools.ietf.org/html/rfc6282#section-4.3.1 22 | static const int COAP_PACKET_SIZE = UIP_UDP_PAYLOAD_MAX_BUFSIZE; // CoAP packet should be less than UIP_UDP_PAYLOAD_MAX_BUFSIZE 112 bytes in this example 23 | char packetBuffer[ COAP_PACKET_SIZE ]; // Buffer to hold outgoing packets 24 | word messageID; 25 | 26 | public: 27 | CoAPEngine(); 28 | void init(const PicoIPv6Connection& picoIPv6Connection); 29 | 30 | const PicoIPv6Connection& getPicoIPv6Connection() const { return picoIPv6Connection; } 31 | void setPicoIPv6Connection(const PicoIPv6Connection& picoIPv6Connection) { this->picoIPv6Connection = picoIPv6Connection; } 32 | 33 | void sendCoAPpacket(uip_ipaddr_t& address, const String& uri, const String& query, const String& secondQuery, const String& payload); 34 | 35 | 36 | }; 37 | 38 | #endif /* COAPENGINE_H_ */ 39 | -------------------------------------------------------------------------------- /ICMP_Constants.h: -------------------------------------------------------------------------------- 1 | 2 | /*---ICMP CONSTANTS---*/ 3 | /** \name ICMPv6 message types */ 4 | /** @{ */ 5 | #define ICMP6_DST_UNREACH 1 /**< dest unreachable */ 6 | #define ICMP6_PACKET_TOO_BIG 2 /**< packet too big */ 7 | #define ICMP6_TIME_EXCEEDED 3 /**< time exceeded */ 8 | #define ICMP6_PARAM_PROB 4 /**< ip6 header bad */ 9 | #define ICMP6_ECHO_REQUEST 128 /**< Echo request */ 10 | #define ICMP6_ECHO_REPLY 129 /**< Echo reply */ 11 | 12 | #define ICMP6_RS 133 /**< Router Solicitation */ 13 | #define ICMP6_RA 134 /**< Router Advertisement */ 14 | #define ICMP6_NS 135 /**< Neighbor Solicitation */ 15 | #define ICMP6_NA 136 /**< Neighbor advertisement */ 16 | #define ICMP6_REDIRECT 137 /**< Redirect */ 17 | 18 | #define ICMP6_RPL 155 /**< RPL */ 19 | /** @} */ 20 | 21 | 22 | /** \name ICMPv6 Destination Unreachable message codes*/ 23 | /** @{ */ 24 | #define ICMP6_DST_UNREACH_NOROUTE 0 /**< no route to destination */ 25 | #define ICMP6_DST_UNREACH_ADMIN 1 /**< administratively prohibited */ 26 | #define ICMP6_DST_UNREACH_NOTNEIGHBOR 2 /**< not a neighbor(obsolete) */ 27 | #define ICMP6_DST_UNREACH_BEYONDSCOPE 2 /**< beyond scope of source address */ 28 | #define ICMP6_DST_UNREACH_ADDR 3 /**< address unreachable */ 29 | #define ICMP6_DST_UNREACH_NOPORT 4 /**< port unreachable */ 30 | /** @} */ 31 | 32 | /** \name ICMPv6 Time Exceeded message codes*/ 33 | /** @{ */ 34 | #define ICMP6_TIME_EXCEED_TRANSIT 0 /**< ttl==0 in transit */ 35 | #define ICMP6_TIME_EXCEED_REASSEMBLY 1 /**< ttl==0 in reass */ 36 | /** @} */ 37 | 38 | /** \name ICMPv6 Parameter Problem message codes*/ 39 | /** @{ */ 40 | #define ICMP6_PARAMPROB_HEADER 0 /**< erroneous header field */ 41 | #define ICMP6_PARAMPROB_NEXTHEADER 1 /**< unrecognized next header */ 42 | #define ICMP6_PARAMPROB_OPTION 2 /**< unrecognized option */ 43 | /** @} */ 44 | 45 | /** \brief Echo Request constant part length */ 46 | #define UIP_ICMP6_ECHO_REQUEST_LEN 4 47 | 48 | /** \brief ICMPv6 Error message constant part length */ 49 | #define UIP_ICMP6_ERROR_LEN 4 50 | 51 | /*--ICPMP CONST END--*/ 52 | -------------------------------------------------------------------------------- /MACLayer.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __MACLAYER__ 3 | #define __MACLAYER__ 4 | 5 | extern "C" { 6 | #include "conf.h" 7 | #include "sicsLowPan.h" 8 | } 9 | 10 | 11 | /* Generic MAC return values. */ 12 | enum MACTransmissionStatus{ 13 | /**< The MAC layer transmission was OK. */ 14 | MAC_TX_STATUS_OK, 15 | 16 | /**< The MAC layer transmission could not be performed due to a 17 | collision. */ 18 | MAC_TX_STATUS_COLLISION, 19 | 20 | /**< The MAC layer did not get an acknowledgement for the packet. */ 21 | MAC_TX_STATUS_NO_ACK, 22 | 23 | /**< The MAC layer deferred the transmission for a later time. */ 24 | MAC_TX_STATUS_DEFERRED, 25 | 26 | /**< The MAC layer transmission could not be performed because of an 27 | error. The upper layer may try again later. */ 28 | MAC_TX_STATUS_ERR, 29 | 30 | /**< The MAC layer transmission could not be performed because of a 31 | fatal error. The upper layer does not need to try again, as the 32 | error will be fatal then as well. */ 33 | MAC_TX_STATUS_ERR_FATAL, 34 | }; 35 | 36 | class MACLayer{ 37 | public: 38 | //********************************************************************************************************// 39 | /*____function init(): Initializes the MAC Layer. Must be called before performing any other operation. 40 | * 41 | * ____In: void 42 | * ____Out: boolean: true-- MAC Layer was correctly initialized. Can utilize getMacAddress, send and receive commands 43 | * false-- MAC Layer was not properly initialized. Error ocurred and we must not continue. 44 | */ 45 | virtual bool init() = 0; 46 | //********************************************************************************************************// 47 | 48 | //********************************************************************************************************// 49 | /*____function send: Sends a MAC frame 50 | * ____In: const uip_lladdr_t* lladdr_dest: MAC@ of the destination (Broadcast will be represented by an all-zeroes address) 51 | * uint8_t* data: (a pointer to) the data to send 52 | * uint16_t length: the size of the data (in bytes) 53 | * int* number_transmissions: The pointed address will be filled with the total number of 54 | * MAC layer transmissions that were performed (1 or more). 55 | * 56 | * ____Out: MACTransmissionStatus: return the status of the MACLayer defined at the beginning of this class 57 | */ 58 | virtual MACTransmissionStatus send(const uip_lladdr_t* lladdr_dest, uint8_t* data, uint16_t length, int* number_transmissions) = 0; 59 | //********************************************************************************************************// 60 | 61 | //********************************************************************************************************// 62 | /*____function receive : Polls the MAC layer to see if it received a new MAC frame/packet. 63 | * If new packet (to myself or multicast/bcast): Use the packet, return true; 64 | * No new packet: Do nothing, return false. 65 | * 66 | *____In: uip_lladdr_t* lladdr_src: (MUST point to a valid uip_lladdr_t variable -with reserved memory-). If we receive 67 | * a new packet, pointed destination will be filled with the sender's MAC@. 68 | * 69 | * uip_lladdr_t* lladdr_dest: (If new packet arrived) 70 | * If destination MAC@ is Broadcast, uip_lladdr_t* lladdr_dest pointer will point to a uip_lladdr_t with all ZEROES 71 | * 72 | * If packet is for myself (unicast) uip_lladdr_t* lladdr_dest pointer will point to a uip_lladdr_t variable with my MAC@. 73 | * 74 | * uint8_t* data: Pointer to where the received data will be copied (if a new packet arrived). 75 | * 76 | * uint16_t* length: The pointed address will be filled with the length (in bytes) of the new data. 77 | * 78 | *____Out: boolean : true-- packet for myself, and store the dst and src MAC@ 79 | * false-- packet for someone else 80 | */ 81 | virtual bool receive(uip_lladdr_t* lladdr_src, uip_lladdr_t* lladdr_dest, uint8_t* data, uint16_t* length) = 0; 82 | //********************************************************************************************************// 83 | 84 | //********************************************************************************************************// 85 | /*___________________function getMAcAdress: return the MAC@ address of the MAC Layer 86 | *___________________In:void 87 | * 88 | *___________________Out: uip_lladdr_t*: Pointer to a uip_lladdr_t with my MAC Address. 89 | */ 90 | virtual const uip_lladdr_t* getMacAddress() = 0; 91 | //********************************************************************************************************// 92 | }; 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /ND_Constants.h: -------------------------------------------------------------------------------- 1 | /**@{ Pointers to messages just after icmp header */ 2 | #define UIP_ND6_NS_BUF ((uip_nd6_ns *)&uip_buf[uip_l2_l3_icmp_hdr_len]) 3 | #define UIP_ND6_NA_BUF ((uip_nd6_na *)&uip_buf[uip_l2_l3_icmp_hdr_len]) 4 | /** @} */ 5 | /** Pointer to ND option */ 6 | #define UIP_ND6_OPT_HDR_BUF ((uip_nd6_opt_hdr *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]) 7 | #define UIP_ND6_OPT_PREFIX_BUF ((uip_nd6_opt_prefix_info *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]) 8 | #define UIP_ND6_OPT_MTU_BUF ((uip_nd6_opt_mtu *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]) 9 | /** @} */ 10 | 11 | 12 | #define uip_ext_len 0 13 | 14 | /** \name ND6 option types */ 15 | /** @{ */ 16 | #define UIP_ND6_OPT_SLLAO 1 17 | #define UIP_ND6_OPT_TLLAO 2 18 | #define UIP_ND6_OPT_PREFIX_INFO 3 19 | #define UIP_ND6_OPT_REDIRECTED_HDR 4 20 | #define UIP_ND6_OPT_MTU 5 21 | /** @} */ 22 | 23 | /** \name ND6 message length (excluding options) */ 24 | /** @{ */ 25 | #define UIP_ND6_NA_LEN 20 26 | #define UIP_ND6_NS_LEN 20 27 | 28 | /** \name Neighbor Advertisement flags masks */ 29 | /** @{ */ 30 | #define UIP_ND6_NA_FLAG_ROUTER 0x80 31 | #define UIP_ND6_NA_FLAG_SOLICITED 0x40 32 | #define UIP_ND6_NA_FLAG_OVERRIDE 0x20 33 | #define UIP_ND6_RA_FLAG_ONLINK 0x80 34 | #define UIP_ND6_RA_FLAG_AUTONOMOUS 0x40 35 | /** @} */ 36 | 37 | /* If the interface is 802.15.4. For now we use only long addresses */ 38 | #define UIP_ND6_OPT_SHORT_LLAO_LEN 8 39 | #define UIP_ND6_OPT_LONG_LLAO_LEN 16 40 | /** \brief length of a ND6 LLAO option for 802.15.4 */ 41 | #define UIP_ND6_OPT_LLAO_LEN UIP_ND6_OPT_LONG_LLAO_LEN 42 | 43 | /** \name ND6 option types */ 44 | /** @{ */ 45 | #define UIP_ND6_OPT_TYPE_OFFSET 0 46 | #define UIP_ND6_OPT_LEN_OFFSET 1 47 | #define UIP_ND6_OPT_DATA_OFFSET 2 48 | 49 | #define UIP_ND6_HOP_LIMIT 255 50 | 51 | 52 | /** 53 | * \name ND Option structures 54 | * @{ 55 | */ 56 | 57 | /** \brief ND option header */ 58 | typedef struct uip_nd6_opt_hdr { 59 | uint8_t type; 60 | uint8_t len; 61 | } uip_nd6_opt_hdr; 62 | 63 | /** 64 | * \name ND message structures 65 | * @{ 66 | */ 67 | 68 | /** 69 | * \brief A neighbor solicitation constant part 70 | * 71 | * Possible option is: SLLAO 72 | */ 73 | typedef struct uip_nd6_ns { 74 | uint32_t reserved; 75 | uip_ipaddr_t tgtipaddr; 76 | } uip_nd6_ns; 77 | 78 | /** 79 | * \brief A neighbor advertisement constant part. 80 | * 81 | * Possible option is: TLLAO 82 | */ 83 | typedef struct uip_nd6_na { 84 | uint8_t flagsreserved; 85 | uint8_t reserved[3]; 86 | uip_ipaddr_t tgtipaddr; 87 | } uip_nd6_na; 88 | -------------------------------------------------------------------------------- /PicoIPv6Connection.h: -------------------------------------------------------------------------------- 1 | #ifndef PICOIPV6CONNECTION_H_ 2 | #define PICOIPV6CONNECTION_H_ 3 | 4 | #include "arduino_debug.h" 5 | #include "MACLayer.h" 6 | #include "PicoIPv6State.h" 7 | #include "PicoIPv6StateSearchingDIOState.h" 8 | #include "PicoIPv6StateSendingDAOState.h" 9 | #include "PicoIPv6StateConnectedState.h" 10 | 11 | #define TIMEOUT_RECEIVING_DIO 8000 12 | 13 | #define TIMEOUT_RECEIVING_DAO_ACK 8000 14 | 15 | /** 16 | * \brief SET LINK LAYER ADDRESS TO 0 (MEANS BROADCAST 0xFFFF FOR THIS PURPOSES) 17 | */ 18 | #define uip_set_lladdr_broadcast(a) do { \ 19 | (a)->addr[0] = 0; \ 20 | (a)->addr[1] = 0; \ 21 | (a)->addr[2] = 0; \ 22 | (a)->addr[3] = 0; \ 23 | (a)->addr[4] = 0; \ 24 | (a)->addr[5] = 0; \ 25 | (a)->addr[6] = 0; \ 26 | (a)->addr[7] = 0; \ 27 | } while(0) 28 | 29 | /** \brief set IP address a to the link local all-nodes multicast address */ 30 | #define uip_create_linklocal_allnodes_mcast(a) uip_ip6addr(a, 0xff02, 0, 0, 0, 0, 0, 0, 0x0001) 31 | 32 | /* This function needs to be defined in an external file */ 33 | /* This function will be automatically invoked when we call PicoIPv6Connection->receive() method 34 | * and there is new UDP Data. 35 | * * udp_data: contains new UDP datagram payload. 36 | * * length: contains new UDP datagram payload lenght. 37 | * 38 | * [ At lower level it is actually called from PicoIPv6State.udp_input() ] 39 | * [ only when the PicoIPv6State subclass is ConnectedState ] 40 | * 41 | * */ 42 | extern void udp_input_callback(uint8_t* udp_data, uint16_t length); 43 | 44 | class PicoIPv6Connection{ 45 | private: 46 | PicoIPv6State* state; 47 | u8_t* buffer; 48 | MACLayer* mac; 49 | 50 | uip_lladdr_t* own_ll_address_ptr; 51 | uip_lladdr_t own_ll_address; 52 | 53 | //Gateway 54 | uip_ipaddr_t gateway_ip_addr; 55 | uip_lladdr_t gateway_ll_addr; 56 | 57 | uip_ipaddr_t link_local_addr; 58 | 59 | void initClassPrivate(MACLayer* mac, u8_t* buffer){ 60 | this->mac = mac; 61 | 62 | own_ll_address_ptr = &own_ll_address; // Bugfix for having reserved Memory on own_ll_address_ptr 63 | memcpy(this->own_ll_address_ptr, mac->getMacAddress(), UIP_LLADDR_LEN); // Solved BUG: memcpy over own_ll_address with no reserved memory, solution: own_ll_address_ptr = &own_ll_address; 64 | 65 | this->buffer = buffer; 66 | 67 | uip_create_linklocal_allnodes_mcast(&link_local_addr); 68 | uip_create_linklocal_rplnodes_mcast(&gateway_ip_addr); 69 | uip_set_lladdr_broadcast(&gateway_ll_addr); 70 | 71 | this->state = new PicoIPv6StateSearchingDIOState(mac, buffer, own_ll_address_ptr, TIMEOUT_RECEIVING_DIO, &gateway_ll_addr, &gateway_ip_addr); 72 | this->state->setBuffer(buffer); 73 | } 74 | 75 | public: 76 | PicoIPv6Connection(){}; 77 | PicoIPv6Connection(MACLayer* mac, u8_t* buffer){ 78 | initClassPrivate(mac, buffer); 79 | } 80 | 81 | void init( MACLayer* mac , u8_t* buffer ){ 82 | initClassPrivate(mac, buffer); 83 | } 84 | 85 | ConnectionState connect(){ 86 | uint8_t instance_id; 87 | switch (this->state->connect()){ 88 | case WAITING_DIO: 89 | //if we are waiting for a DIO, we should send again a DIS and continue waiting (TODO: INCREMENT THE TIMEOUT FOR RECEIVING DIO?) 90 | if (!this->state->has_timer_expired()){ 91 | //if timer did not expire, we need to continue waiting 92 | PRINTF("WAIT DIO. TIMER NOT EXPIRED"); 93 | break; 94 | } 95 | case DISCONNECTED: 96 | PRINTF("LIKE DISCONNECTED"); 97 | //if we are disconnected, start connection by searching for DIO (send DIS and wait) 98 | delete(this->state); 99 | this->state = new PicoIPv6StateSearchingDIOState(mac, buffer, own_ll_address_ptr, TIMEOUT_RECEIVING_DIO, &gateway_ll_addr, &gateway_ip_addr); 100 | PRINTF("NEW SEARCH DIO STATE.. RECONNECTING"); 101 | this->connect(); 102 | break; 103 | 104 | case WAITING_DAO_ACK: 105 | //if we are waiting for a DAO ACK, we should send again a DAO and continue waiting (TODO: INCREMENT THE TIMEOUT FOR RECEIVING DAO ACK? ALSO, IS IT NECESSARY TO RESTART AFTER WAITING TOO LONG?) 106 | if (!this->state->has_timer_expired()){ 107 | //if timer did not expire, we need to continue waiting 108 | break; 109 | } 110 | case DIO_RECEIVED: 111 | //if we received a DIO, it is time to send a DAO, change the state! 112 | instance_id = this->state->getInstanceId(); 113 | if (instance_id != -1){ 114 | delete(this->state); 115 | this->state = new PicoIPv6StateSendingDAOState(mac, buffer, own_ll_address_ptr, TIMEOUT_RECEIVING_DAO_ACK, &gateway_ll_addr, &gateway_ip_addr, instance_id); 116 | }else{ 117 | //We did not actually received a valid DIO cause we do not have the instance ID 118 | this->state->changeState(DISCONNECTED); 119 | //retry to connect? 120 | //this->connect(); 121 | } 122 | this->connect(); 123 | break; 124 | 125 | case DAO_ACK_RECEIVED: 126 | //In this case, change the state for a CONNECTED STATE 127 | instance_id = this->state->getInstanceId(); 128 | delete(this->state); 129 | this->state = new PicoIPv6StateConnectedState(mac, buffer, own_ll_address_ptr, /*0,*/ &gateway_ll_addr, &gateway_ip_addr, &udp_input_callback, instance_id); //by now, we do not use timers when connected 130 | break; 131 | 132 | case CONNECTED: 133 | //Do nothing (we are already connected!) (TODO: SHOULD WE CHECK IF CONNECTION IS STILL ALIVE?) 134 | break; 135 | 136 | } 137 | return this->state->getState(); 138 | } 139 | 140 | boolean isConnected(){ return getConnectionState() == CONNECTED; } 141 | 142 | void udp_send(uip_ipaddr_t *dest, u16_t src_port, u16_t dest_port, char* payload, u16_t payload_len){ 143 | this->state->udp_send(dest, src_port, dest_port, payload, payload_len); 144 | } 145 | 146 | ConnectionState getConnectionState(){ return this->state->getState(); } 147 | 148 | bool receive(){ return this->state->receive(); } 149 | 150 | uip_ipaddr_t* getLastSenderIPAddress(){ return this->state->getLastSenderIPAddress(); } // Get last sender IP Address 151 | uint16_t getLastSenderUDPSourcePort(){ return this->state->getLastSenderUDPSourcePort(); } // Get last UDP sender UDP source Port 152 | uint16_t getUdpDataLength() { return this->state->getUdpDataLength(); } // Get last UDP packet data/payload size 153 | uint16_t getUdpData(char * buffer) { return this->state->getUdpData(buffer); } // Get UDP data/payload, copies into udp_msg_buf, return bytes of data copied 154 | 155 | /* Returns the Local Multicast IPv6 Address */ 156 | uip_ipaddr_t* getLinkLocalMcastIPAddress(){ return &this->link_local_addr; } 157 | 158 | ReceivedPacketType getLastReceivedPacketType(){ return this->state->getLastReceivedPacketType();} 159 | }; 160 | 161 | 162 | #endif /* PICOIPV6CONNECTION_H_ */ 163 | -------------------------------------------------------------------------------- /PicoIPv6State.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "arduino_debug.h" 3 | #include "PicoIPv6State.h" 4 | u16_t 5 | PicoIPv6State::uip_htons(u16_t val) 6 | { 7 | return UIP_HTONS(val); 8 | } 9 | 10 | u32_t 11 | PicoIPv6State::uip_htonl(u32_t val) 12 | { 13 | return UIP_HTONL(val); 14 | } 15 | 16 | u16_t 17 | PicoIPv6State::chksum(u16_t sum, const u8_t *data, u16_t len) 18 | { 19 | u16_t t; 20 | const u8_t *dataptr; 21 | const u8_t *last_byte; 22 | 23 | dataptr = data; 24 | last_byte = data + len - 1; 25 | 26 | while(dataptr < last_byte) { /* At least two more bytes */ 27 | t = (dataptr[0] << 8) + dataptr[1]; 28 | sum += t; 29 | if(sum < t) { 30 | sum++; /* carry */ 31 | } 32 | dataptr += 2; 33 | } 34 | 35 | if(dataptr == last_byte) { 36 | t = (dataptr[0] << 8) + 0; 37 | sum += t; 38 | if(sum < t) { 39 | sum++; /* carry */ 40 | } 41 | } 42 | 43 | /* Return sum in host byte order. */ 44 | return sum; 45 | } 46 | 47 | u16_t 48 | PicoIPv6State::uip_chksum(u16_t *data, u16_t len) 49 | { 50 | return uip_htons(chksum(0, (u8_t *)data, len)); 51 | } 52 | 53 | u16_t 54 | PicoIPv6State::uip_ipchksum(void) 55 | { 56 | u16_t sum; 57 | 58 | sum = chksum(0, uip_buffer, UIP_IPH_LEN); 59 | return (sum == 0) ? 0xffff : uip_htons(sum); 60 | } 61 | 62 | 63 | u16_t 64 | PicoIPv6State::upper_layer_chksum(u8_t proto) 65 | { 66 | volatile u16_t upper_layer_len; 67 | u16_t sum; 68 | 69 | upper_layer_len = (((u16_t)(UIP_IP_BUF->len[0]) << 8) + UIP_IP_BUF->len[1]) ; 70 | 71 | /* First sum pseudoheader. */ 72 | /* IP protocol and length fields. This addition cannot carry. */ 73 | sum = upper_layer_len + proto; 74 | /* Sum IP source and destination addresses. */ 75 | sum = chksum(sum, (u8_t *)&UIP_IP_BUF->srcipaddr, 2 * sizeof(uip_ipaddr_t)); 76 | 77 | /* Sum TCP header and data. */ 78 | sum = chksum(sum, &uip_buffer[UIP_IPH_LEN], 79 | upper_layer_len); 80 | 81 | return (sum == 0) ? 0xffff : uip_htons(sum); 82 | } 83 | 84 | 85 | u16_t 86 | PicoIPv6State::uip_udpchksum(void) 87 | { 88 | return upper_layer_chksum(UIP_PROTO_UDP); 89 | } 90 | 91 | u16_t 92 | PicoIPv6State::uip_icmp6chksum(void) 93 | { 94 | return upper_layer_chksum(UIP_PROTO_ICMP6); 95 | 96 | } 97 | 98 | /*---------------------------------------------------------------------------*/ 99 | void 100 | uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, uip_lladdr_t * lladdr) 101 | { 102 | /* We consider only links with IEEE EUI-64 identifier MAC addresses */ 103 | #if (UIP_LLADDR_LEN == 8) 104 | memcpy(ipaddr->u8 + 8, lladdr, UIP_LLADDR_LEN); 105 | ipaddr->u8[8] ^= 0x02; 106 | #else 107 | #error uip-ds6.c cannot build interface address when UIP_LLADDR_LEN is not 6 or 8 108 | #endif 109 | } 110 | 111 | /*---------------------------------------------------------------------------*/ 112 | 113 | void 114 | PicoIPv6State::icmp6_send(uip_ipaddr_t *dest, int type, int code, int payload_len) 115 | { 116 | 117 | UIP_IP_BUF->vtc = 0x60; 118 | UIP_IP_BUF->tcflow = 0; 119 | UIP_IP_BUF->flow = 0; 120 | UIP_IP_BUF->proto = UIP_PROTO_ICMP6; 121 | UIP_IP_BUF->ttl = HOP_LIMIT; //uip_ds6_if.cur_hop_limit; 122 | UIP_IP_BUF->len[0] = (UIP_ICMPH_LEN + payload_len) >> 8; 123 | UIP_IP_BUF->len[1] = (UIP_ICMPH_LEN + payload_len) & 0xff; 124 | 125 | //copy dest 126 | memcpy(&UIP_IP_BUF->destipaddr, dest, sizeof(*dest)); 127 | 128 | //copy src (Link Local for ICMP) 129 | //memcpy(&UIP_IP_BUF->srcipaddr, &own_ll_ip_address, sizeof(own_ll_ip_address)); 130 | memcpy(&UIP_IP_BUF->srcipaddr, &own_ip_address, sizeof(own_ip_address)); 131 | //We need to put a link local FE80:: 132 | uip_create_linklocal_prefix(&UIP_IP_BUF->srcipaddr); 133 | 134 | UIP_ICMP_BUF->type = type; 135 | UIP_ICMP_BUF->icode = code; 136 | 137 | UIP_ICMP_BUF->icmpchksum = 0; 138 | UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); 139 | 140 | uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + payload_len; 141 | 142 | ip_send(dest); 143 | 144 | } 145 | 146 | void 147 | PicoIPv6State::udp_send(uip_ipaddr_t *dest, u16_t src_port, u16_t dest_port, char* payload, u16_t payload_len) 148 | { 149 | //PRINTF("UDP SEND.."); 150 | UIP_UDPIP_BUF->vtc = 0x60; 151 | UIP_UDPIP_BUF->tcf = 0; 152 | UIP_UDPIP_BUF->flow = 0; 153 | UIP_UDPIP_BUF->proto = UIP_PROTO_UDP; 154 | UIP_UDPIP_BUF->ttl = HOP_LIMIT; //uip_ds6_if.cur_hop_limit; 155 | UIP_UDPIP_BUF->len[0] = (UIP_UDPH_LEN + payload_len) >> 8; 156 | UIP_UDPIP_BUF->len[1] = (UIP_UDPH_LEN + payload_len) & 0xff; 157 | 158 | //PRINTF("UIP HEADER READY"); 159 | //copy dest 160 | memcpy(&UIP_UDPIP_BUF->destipaddr, dest, sizeof(*dest)); 161 | 162 | //PRINTF("DEST ADDR READY"); 163 | //copy src 164 | memcpy(&UIP_UDPIP_BUF->srcipaddr, &own_ip_address, sizeof(own_ip_address)); 165 | 166 | //PRINTF("SRC ADDR READY"); 167 | 168 | UIP_UDPIP_BUF->srcport = UIP_HTONS(src_port); 169 | UIP_UDPIP_BUF->destport = UIP_HTONS(dest_port); 170 | 171 | UIP_UDPIP_BUF->udplen = UIP_HTONS(UIP_UDPH_LEN + payload_len); //NEED TO PUT THE SAME LENGTH AS THE IP PACKET!! (UDP header + UDP payload length) 172 | 173 | //PRINTF("UDP HEADER READY"); 174 | 175 | //copy UDP payload 176 | memcpy(&uip_buffer[UIP_IPUDPH_LEN], payload, payload_len); 177 | 178 | //PRINTF("PAYLOAD READY"); 179 | 180 | UIP_UDPIP_BUF->udpchksum = 0; 181 | UIP_UDPIP_BUF->udpchksum = ~uip_udpchksum(); 182 | 183 | //PRINTF("CHECKSUM READY"); 184 | 185 | uip_len = UIP_IPUDPH_LEN + payload_len; 186 | 187 | ip_send(dest); 188 | 189 | } 190 | 191 | void PicoIPv6State::ip_send(uip_ipaddr_t *dest){ 192 | if(uip_len == 0) { 193 | PRINTF("Nothing to send"); 194 | return; 195 | } 196 | 197 | if(uip_len > UIP_LINK_MTU) { 198 | PRINTF("Packet to big"); 199 | uip_len = 0; 200 | return; 201 | } 202 | if(uip_is_addr_unspecified(dest)){ 203 | PRINTF("Destination address unspecified"); 204 | uip_len = 0; 205 | return; 206 | } 207 | if(!uip_is_addr_mcast(dest)) { 208 | if (!rimeaddr_cmp((rimeaddr_t*)gateway_ll_address, &rimeaddr_null, UIP_LLADDR_LEN)){ 209 | compress(gateway_ll_address); 210 | }else{ 211 | 212 | PRINTF("Destination address not mcast and no gway"); 213 | 214 | } 215 | }else{ 216 | //Serial.println("[ip_send] ip_send IP Multicast. SEND LL Broadcast"); // DEBUGGING 217 | compress( (uip_lladdr_t*) (&rimeaddr_null) ); // We send a MAC Broadcast. // old code: compress(NULL); --> FAILS because convention for send_at_mac broadcast convention now is all-zeroes address and not a NULL pointer. 218 | 219 | } 220 | uip_len = 0; 221 | } 222 | 223 | void PicoIPv6State::send_at_mac(uip_lladdr_t* ll_dest_addr){ 224 | /* 225 | // DEBUGGING 226 | Serial.println("[SEND] send_at_mac destination MAC ADDRESS (Other's or Broadcast): 0x"); 227 | for (int i=0; i<8; ++i){ Serial.println( ll_dest_addr->addr[i], HEX); } 228 | */ 229 | int num_trans = 0; 230 | mac->send(ll_dest_addr, uip_6lp_buf.u8, uip_6lp_len, &num_trans); 231 | } 232 | 233 | void PicoIPv6State::compress(uip_lladdr_t* ll_dest_addr){ 234 | //set the variables that are needed for the compression 235 | uip_length = this->uip_len; 236 | uip_buf = uip_buffer; 237 | 238 | //compress 239 | output(ll_dest_addr); 240 | 241 | send_at_mac(ll_dest_addr); 242 | 243 | uip_length = 0; 244 | } 245 | 246 | PicoIPv6State::PicoIPv6State(MACLayer* mac, u8_t* buffer, uip_lladdr_t* own_ll_address, uip_lladdr_t* gateway_ll_address, uip_ip6addr_t* gateway_ip_address){ 247 | //PRINTF("CONSTRUCTOR RA STATE"); 248 | uip_len = 0; 249 | uip_buf = buffer; 250 | this->mac = mac; 251 | this->uip_buffer = buffer; 252 | this->own_ll_address = own_ll_address; 253 | this->gateway_ll_address = gateway_ll_address; 254 | this->gateway_ip_address = gateway_ip_address; 255 | this->udp_input_callback = NULL; 256 | //uip_create_linklocal_prefix(&own_ll_ip_address); 257 | //uip_ds6_set_addr_iid(&own_ll_ip_address, own_ll_address); 258 | uip_ip6addr(&own_ip_address, 0, 0, 0, 0, 0, 0, 0, 0); 259 | uip_ds6_set_addr_iid(&own_ip_address, own_ll_address); 260 | sicslowpan_init(own_ll_address); 261 | dodag_instance_id = -1; //not yet initialized 262 | lastReceived = NOT_EXPECTED_OR_ERROR; 263 | 264 | } 265 | 266 | PicoIPv6State::~PicoIPv6State(){} 267 | 268 | 269 | MACLayer* PicoIPv6State::getMacCommunicator(){ 270 | return mac; 271 | } 272 | 273 | uint8_t PicoIPv6State::getInstanceId(){ 274 | return dodag_instance_id; 275 | } 276 | 277 | void PicoIPv6State::changeState(ConnectionState newState){ 278 | this->currentState = newState; 279 | } 280 | 281 | ConnectionState PicoIPv6State::getState(){ 282 | return currentState; 283 | } 284 | 285 | 286 | FrameReceptionResult PicoIPv6State::receive_mac(){ 287 | 288 | if (mac->receive(&src_resp, &dst_resp, uip_6lp_buf.u8, &uip_6lp_len)){ 289 | 290 | /* 291 | // DEBUGGING 292 | // Test for dst_resp_ptr proper modification if Broadcast or Unicast destination. 293 | Serial.println(""); 294 | Serial.println("[RECEIVE] receive_mac destination MAC ADDRESS (Myself or Broadcast): 0x"); 295 | for (int i=0; i<8; ++i){ Serial.println( dst_resp.addr[i], HEX); } 296 | */ 297 | 298 | //Now decompress (sicslowpan) 299 | input(&src_resp, &dst_resp); 300 | 301 | this->uip_len = uip_length;//we assign the decompressed length of the ipv6 packet 302 | 303 | PRINTF("DECOMPRESSED"); 304 | 305 | PRINTHEX(uip_len); 306 | 307 | for(int i=0; iicode) { 325 | case RPL_CODE_DIO: 326 | process_input(); 327 | lastReceived = DIO; 328 | /* DAG Information Object */ 329 | PRINTF("RPL: Received a DIO"); 330 | break; 331 | case RPL_CODE_DIS: 332 | //dis_input(); 333 | PRINTF("RPL: Received a DIS"); 334 | break; 335 | case RPL_CODE_DAO: 336 | //dao_input(); 337 | PRINTF("RPL: Received a DAO"); 338 | break; 339 | case RPL_CODE_DAO_ACK: 340 | //dao_ack_input(); 341 | process_input(); 342 | lastReceived = DAO_ACK; 343 | PRINTF("RPL: Received a DAO ACK"); 344 | break; 345 | default: 346 | PRINTF("RPL: received an unknown ICMP6 code"); 347 | break; 348 | } 349 | 350 | uip_len = 0; 351 | 352 | return UIP_ICMP_BUF->icode; 353 | } 354 | 355 | /*------------------*/ 356 | 357 | 358 | #define DROP drop(); \ 359 | return lastReceived 360 | 361 | /*---------------------------------*/ 362 | 363 | ReceivedPacketType PicoIPv6State::udp_input(){ 364 | uint16_t udp_data_len; 365 | uint8_t* udp_data; 366 | 367 | PRINTF("Receiving UDP packet"); 368 | 369 | /* UDP processing is really just a hack. We don't do anything to the 370 | UDP/IP headers, but let the UDP application do all the hard 371 | work. If the application sets uip_slen, it has a packet to 372 | send. */ 373 | 374 | #if UIP_UDP_CHECKSUMS 375 | if(UIP_UDPIP_BUF->udpchksum != 0 && uip_udpchksum() != 0xffff) { 376 | PRINTF("udp: bad checksum"); 377 | DROP; 378 | } 379 | #endif /* UIP_UDP_CHECKSUMS */ 380 | 381 | udp_data = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; 382 | udp_data_len = uip_len - UIP_IPUDPH_LEN; 383 | 384 | PRINTHEX(udp_data_len); 385 | 386 | /* Make sure that the UDP destination port number is not zero. */ 387 | if(UIP_UDPIP_BUF->destport == 0) { 388 | PRINTF("udp: zero port."); 389 | DROP; 390 | } 391 | 392 | //UIP_UDP_APPCALL(); 393 | this->udp_input_callback(udp_data, udp_data_len); 394 | 395 | lastReceived = UDP; 396 | 397 | return lastReceived; 398 | } 399 | 400 | 401 | /*------------------------------------------------------------------*/ 402 | /* create a llao */ 403 | void PicoIPv6State::create_llao(uint8_t *llao, uint8_t type) { 404 | llao[UIP_ND6_OPT_TYPE_OFFSET] = type; 405 | llao[UIP_ND6_OPT_LEN_OFFSET] = UIP_ND6_OPT_LLAO_LEN >> 3; 406 | memcpy(&llao[UIP_ND6_OPT_DATA_OFFSET], own_ll_address, UIP_LLADDR_LEN); 407 | /* padding on some */ 408 | memset(&llao[UIP_ND6_OPT_DATA_OFFSET + UIP_LLADDR_LEN], 0, 409 | UIP_ND6_OPT_LLAO_LEN - 2 - UIP_LLADDR_LEN); 410 | } 411 | 412 | /*------------------------------------------------------------------*/ 413 | 414 | void PicoIPv6State::uip_nd6_ns_input(void) 415 | { 416 | PRINTF("Received NS"); 417 | u8_t flags; 418 | bool gotoDiscard = true; 419 | 420 | #if UIP_CONF_IPV6_CHECKS 421 | if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) || 422 | (uip_is_addr_mcast(&UIP_ND6_NS_BUF->tgtipaddr)) || 423 | (UIP_ICMP_BUF->icode != 0)) { 424 | PRINTF("NS received is bad"); 425 | goto discard; 426 | } 427 | #endif /* UIP_CONF_IPV6_CHECKS */ 428 | 429 | uint8_t nd6_opt_offset; /** Offset from the end of the icmpv6 header to the option in uip_buf*/ 430 | uint8_t *nd6_opt_llao; /** Pointer to llao option in uip_buf */ 431 | /* Options processing */ 432 | nd6_opt_llao = NULL; 433 | nd6_opt_offset = UIP_ND6_NS_LEN; 434 | while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) { 435 | #if UIP_CONF_IPV6_CHECKS 436 | if(UIP_ND6_OPT_HDR_BUF->len == 0) { 437 | PRINTF("NS received is bad"); 438 | goto discard; 439 | } 440 | #endif /* UIP_CONF_IPV6_CHECKS */ 441 | switch (UIP_ND6_OPT_HDR_BUF->type) { 442 | case UIP_ND6_OPT_SLLAO: 443 | nd6_opt_llao = &uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]; 444 | #if UIP_CONF_IPV6_CHECKS 445 | /* There must be NO option in a DAD NS */ 446 | if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { 447 | PRINTF("NS received is bad"); 448 | goto discard; 449 | } 450 | #endif /*UIP_CONF_IPV6_CHECKS */ 451 | break; 452 | default: 453 | PRINTF("ND option not supported in NS"); 454 | break; 455 | } 456 | nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3); 457 | } 458 | 459 | //Is this (target address) my own ip address 460 | if (uip_is_addr_linklocal(&UIP_ND6_NS_BUF->tgtipaddr)){ 461 | //Check if it is our link local address 462 | uip_create_linklocal_prefix(&own_ip_address); 463 | if(uip_ipaddr_cmp(&own_ip_address, &UIP_ND6_NS_BUF->tgtipaddr)){ 464 | gotoDiscard = false; 465 | } 466 | //Go back to our real address 467 | uip_create_default_prefix(&own_ip_address); 468 | }else{ 469 | if (uip_ipaddr_cmp(&own_ip_address, &UIP_ND6_NS_BUF->tgtipaddr)) 470 | gotoDiscard = false; 471 | } 472 | if(!gotoDiscard) { 473 | if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { 474 | /* DAD CASE */ 475 | #if UIP_CONF_IPV6_CHECKS 476 | if(!uip_is_addr_solicited_node(&UIP_IP_BUF->destipaddr)) { 477 | PRINTF("NS received is bad"); 478 | goto discard; 479 | } 480 | #endif /* UIP_CONF_IPV6_CHECKS */ 481 | /* 482 | if(addr->state != ADDR_TENTATIVE) { 483 | uip_create_linklocal_allnodes_mcast(&UIP_IP_BUF->destipaddr); 484 | uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); 485 | flags = UIP_ND6_NA_FLAG_OVERRIDE; 486 | goto create_na; 487 | } else { 488 | uip_ds6_dad_failed(addr); 489 | goto discard; 490 | } 491 | */ 492 | } 493 | #if UIP_CONF_IPV6_CHECKS 494 | if(/*uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)*/uip_ipaddr_cmp(&own_ip_address, &UIP_IP_BUF->srcipaddr)) { 495 | /** 496 | * \NOTE do we do something here? we both are using the same address. 497 | * If we are doing dad, we could cancel it, though we should receive a 498 | * NA in response of DAD NS we sent, hence DAD will fail anyway. If we 499 | * were not doing DAD, it means there is a duplicate in the network! 500 | */ 501 | PRINTF("NS received is bad"); 502 | goto discard; 503 | } 504 | #endif /*UIP_CONF_IPV6_CHECKS */ 505 | 506 | /* Address resolution case */ 507 | if(uip_is_addr_solicited_node(&UIP_IP_BUF->destipaddr)) { 508 | uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr); 509 | uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &UIP_ND6_NS_BUF->tgtipaddr); 510 | flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE; 511 | goto create_na; 512 | } 513 | 514 | /* NUD CASE */ 515 | uip_create_linklocal_prefix(&this->own_ip_address); 516 | 517 | if(uip_ipaddr_cmp(&own_ip_address, &UIP_IP_BUF->destipaddr)) { 518 | 519 | uip_create_default_prefix(&this->own_ip_address); //Go back to our real address 520 | uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr); 521 | uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &UIP_ND6_NS_BUF->tgtipaddr); 522 | flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE; 523 | goto create_na; 524 | 525 | } else { 526 | 527 | uip_create_default_prefix(&this->own_ip_address); //Go back to our real address 528 | #if UIP_CONF_IPV6_CHECKS 529 | PRINTF("NS received is bad"); 530 | goto discard; 531 | #endif /* UIP_CONF_IPV6_CHECKS */ 532 | 533 | } 534 | 535 | 536 | }else { 537 | goto discard; 538 | } 539 | 540 | 541 | create_na: 542 | UIP_IP_BUF->vtc = 0x60; 543 | UIP_IP_BUF->tcflow = 0; 544 | UIP_IP_BUF->flow = 0; 545 | UIP_IP_BUF->len[0] = 0; /* length will not be more than 255 */ 546 | UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN; 547 | UIP_IP_BUF->proto = UIP_PROTO_ICMP6; 548 | UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT; 549 | 550 | UIP_ICMP_BUF->type = ICMP6_NA; 551 | UIP_ICMP_BUF->icode = 0; 552 | 553 | UIP_ND6_NA_BUF->flagsreserved = flags; 554 | memcpy(&UIP_ND6_NA_BUF->tgtipaddr, &UIP_ND6_NS_BUF->tgtipaddr, sizeof(uip_ipaddr_t)); 555 | 556 | create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NA_LEN], UIP_ND6_OPT_TLLAO); 557 | 558 | UIP_ICMP_BUF->icmpchksum = 0; 559 | UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); 560 | 561 | uip_len = 562 | UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN; 563 | 564 | PRINTF("Sending NA"); 565 | //READY TO SEND! WE SEND IT RIGHT NOW 566 | ip_send(&UIP_IP_BUF->destipaddr); 567 | this->lastReceived = NS; 568 | 569 | return; 570 | 571 | discard: 572 | uip_len = 0; 573 | return; 574 | } 575 | 576 | /*---------------------------------*/ 577 | 578 | ReceivedPacketType PicoIPv6State::icmp6_input(){ 579 | /* This is IPv6 ICMPv6 processing code. */ 580 | PRINTF("icmp6_input: length"); 581 | 582 | #if UIP_CONF_IPV6_CHECKS 583 | /* Compute and check the ICMP header checksum */ 584 | if(uip_icmp6chksum() != 0xffff) { 585 | UIP_STAT(++uip_stat.icmp.drop); 586 | UIP_STAT(++uip_stat.icmp.chkerr); 587 | UIP_LOG("icmpv6: bad checksum."); 588 | DROP; 589 | } 590 | #endif /*UIP_CONF_IPV6_CHECKS*/ 591 | 592 | UIP_STAT(++uip_stat.icmp.recv); 593 | 594 | switch(UIP_ICMP_BUF->type) { 595 | 596 | case ICMP6_RPL: 597 | uip_rpl_input(); 598 | break; 599 | 600 | case ICMP6_NS: 601 | uip_nd6_ns_input(); 602 | break; 603 | case ICMP6_NA: 604 | DROP; 605 | break; 606 | case ICMP6_RS: 607 | DROP; 608 | break; 609 | case ICMP6_RA: 610 | DROP; 611 | break; 612 | case ICMP6_ECHO_REQUEST: 613 | DROP; 614 | break; 615 | case ICMP6_ECHO_REPLY: 616 | DROP; 617 | break; 618 | default: 619 | PRINTF("Not expected icmp6 message type"); 620 | UIP_STAT(++uip_stat.icmp.drop); 621 | UIP_STAT(++uip_stat.icmp.typeerr); 622 | UIP_LOG("icmp6: unknown ICMP message."); 623 | DROP; 624 | break; 625 | } 626 | 627 | return lastReceived; 628 | 629 | } 630 | 631 | /*---------------------------------*/ 632 | 633 | void PicoIPv6State::drop(){ 634 | uip_len = 0; 635 | /*uip_ext_len = 0; 636 | uip_ext_bitmap = 0; 637 | uip_flags = 0;*/ 638 | lastReceived = NOT_EXPECTED_OR_ERROR; 639 | } 640 | 641 | /*--------------------------------*/ 642 | 643 | ReceivedPacketType PicoIPv6State::receive_ipv6(){ 644 | if (uip_len <= 0){ 645 | PRINTF("NO IP LENGTH"); 646 | DROP; 647 | } 648 | 649 | /* Start of IP input header processing code. */ 650 | 651 | /* Check validity of the IP header. */ 652 | if((UIP_IP_BUF->vtc & 0xf0) != 0x60) { /* IP version and header length. */ 653 | UIP_STAT(++uip_stat.ip.drop); 654 | UIP_STAT(++uip_stat.ip.vhlerr); 655 | UIP_LOG("ipv6: invalid version."); 656 | DROP; 657 | } 658 | /* 659 | * Check the size of the packet. If the size reported to us in 660 | * uip_len is smaller the size reported in the IP header, we assume 661 | * that the packet has been corrupted in transit. If the size of 662 | * uip_len is larger than the size reported in the IP packet header, 663 | * the packet has been padded and we set uip_len to the correct 664 | * value.. 665 | */ 666 | 667 | if((UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] <= uip_len) { 668 | uip_len = (UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] + UIP_IPH_LEN; 669 | /* 670 | * The length reported in the IPv6 header is the 671 | * length of the payload that follows the 672 | * header. However, uIP uses the uip_len variable 673 | * for holding the size of the entire packet, 674 | * including the IP header. For IPv4 this is not a 675 | * problem as the length field in the IPv4 header 676 | * contains the length of the entire packet. But 677 | * for IPv6 we need to add the size of the IPv6 678 | * header (40 bytes). 679 | */ 680 | } else { 681 | UIP_LOG("ip: packet shorter than reported in IP header."); 682 | DROP; 683 | } 684 | 685 | PRINTF("IPv6 packet received from "); 686 | PRINT6ADDR(&UIP_IP_BUF->srcipaddr); 687 | PRINTF(" to "); 688 | PRINT6ADDR(&UIP_IP_BUF->destipaddr); 689 | PRINTF("\n"); 690 | 691 | if(uip_is_addr_mcast(&UIP_IP_BUF->srcipaddr)){ 692 | UIP_STAT(++uip_stat.ip.drop); 693 | PRINTF("Dropping packet, src is mcast\n"); 694 | DROP; 695 | } 696 | 697 | /* TODO: SEE WHICH ADDRESS RECEIVES THE PACKETS AND COMPARE IF IT IS OURS 698 | if(!uip_ds6_is_my_addr(&UIP_IP_BUF->destipaddr)) { 699 | PRINTF("Dropping packet, not for me\n"); 700 | UIP_STAT(++uip_stat.ip.drop); 701 | DROP; 702 | } 703 | */ 704 | 705 | uip_ipaddr_copy(&src_ip_address, &UIP_IP_BUF->srcipaddr); 706 | 707 | /* 708 | * Next header field processing. In IPv6, we can have extension headers, 709 | * they are processed here 710 | */ 711 | switch(UIP_IP_BUF->proto){ 712 | case UIP_PROTO_UDP: 713 | /* UDP, for both IPv4 and IPv6 */ 714 | udp_input(); 715 | break; 716 | case UIP_PROTO_ICMP6: 717 | /* ICMPv6 */ 718 | icmp6_input(); 719 | break; 720 | default: 721 | DROP; 722 | break; 723 | } 724 | 725 | uip_len = 0; 726 | 727 | return lastReceived; 728 | 729 | } 730 | 731 | void PicoIPv6State::uip_lladdr_copy(uip_lladdr_t *dest, const uip_lladdr_t *src, uint8_t addr_size) 732 | { 733 | u8_t i; 734 | for(i = 0; i < addr_size; i++) { 735 | dest->addr[i] = src->addr[i]; 736 | } 737 | } 738 | 739 | bool PicoIPv6State::receive(){ 740 | if (receive_mac() == RECEIVED){ //GOT SOMETHING AT MAC LEVEL 741 | PRINTF("RECEIVED AT MAC LEVEL"); 742 | if (receive_ipv6() != NOT_EXPECTED_OR_ERROR){ //IF WE RECEIVED SOMETHING THAT WE COULD EXPECT, RECEPTION IS SUCCESSFUL 743 | PRINTF("RECEIVED STH"); 744 | return true; 745 | } 746 | } 747 | return false; 748 | } 749 | 750 | void PicoIPv6State::setBuffer(uint8_t* buffer){ 751 | this->uip_buffer = buffer; 752 | } 753 | 754 | uip_ip6addr_t* PicoIPv6State::getLastSenderIPAddress(){ 755 | return &src_ip_address; 756 | } 757 | 758 | u16_t PicoIPv6State::getLastSenderUDPSourcePort(){ 759 | return UIP_NTOHS(UIP_UDPIP_BUF->srcport); 760 | } 761 | 762 | uint16_t PicoIPv6State::getUdpDataLength(){ 763 | // uip_len has value 0 does not work, should be fixed by : 764 | // uip_len = (UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] + UIP_IPH_LEN; 765 | // and then return uip_len - UIP_IPUDPH_LEN; 766 | 767 | return UIP_NTOHS(UIP_UDPIP_BUF->udplen) - UIP_UDPH_LEN; // Works OK. 768 | } 769 | 770 | u16_t PicoIPv6State::getUdpData(char * buffer) { 771 | //copy UDP payload 772 | u16_t udp_data_len = getUdpDataLength(); 773 | memcpy(buffer, &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN] , udp_data_len); //&uip_buffer[UIP_IPUDPH_LEN] 774 | return udp_data_len; 775 | } 776 | 777 | ReceivedPacketType PicoIPv6State::getLastReceivedPacketType(){ 778 | return lastReceived; 779 | } 780 | -------------------------------------------------------------------------------- /PicoIPv6State.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __SUPPRASTATE_H__ 3 | #define __SUPPRASTATE_H__ 4 | 5 | extern "C" { 6 | #include 7 | #include "conf.h" 8 | #include "sicsLowPan.h" 9 | } 10 | 11 | #include 12 | #include "MACLayer.h" 13 | #include "RPL_Constants.h" 14 | #include "ICMP_Constants.h" 15 | #include "ND_Constants.h" 16 | 17 | /*-----DEBUGGING-----*/ 18 | #define DEBUG 0 19 | 20 | #if DEBUG 21 | #include 22 | #define PRINTF(s) arduino_debug(s)//printf(__VA_ARGS__) 23 | #define PRINTHEX(s) arduino_debug_hex(s) 24 | #define PRINT6ADDR(addr) //PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((u8_t *)addr)[0], ((u8_t *)addr)[1], ((u8_t *)addr)[2], ((u8_t *)addr)[3], ((u8_t *)addr)[4], ((u8_t *)addr)[5], ((u8_t *)addr)[6], ((u8_t *)addr)[7], ((u8_t *)addr)[8], ((u8_t *)addr)[9], ((u8_t *)addr)[10], ((u8_t *)addr)[11], ((u8_t *)addr)[12], ((u8_t *)addr)[13], ((u8_t *)addr)[14], ((u8_t *)addr)[15]) 25 | #define PRINTLLADDR(lladdr) //PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",lladdr->addr[0], lladdr->addr[1], lladdr->addr[2], lladdr->addr[3],lladdr->addr[4], lladdr->addr[5]) 26 | #else 27 | #define PRINTF(s) 28 | #define PRINTHEX(s) 29 | #define PRINT6ADDR(addr) 30 | #endif 31 | 32 | #define UIP_LOGGING 1 33 | #if UIP_LOGGING 34 | #include 35 | #define UIP_LOG(m) arduino_debug(m); 36 | #else 37 | #define UIP_LOG(m) 38 | #endif 39 | /*-----DEBUGGING END-----*/ 40 | 41 | #define UIP_STATISTICS 0 42 | #if UIP_STATISTICS == 1 43 | extern struct uip_stats uip_stat; 44 | #define UIP_STAT(s) s 45 | #else 46 | #define UIP_STAT(s) 47 | #endif /* UIP_STATISTICS == 1 */ 48 | 49 | /*-----POINTER REDEFINITION-----*/ 50 | #define UIP_IP_BUF ((struct uip_ip_hdr *)uip_buffer) 51 | #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buffer[uip_l3_hdr_len]) 52 | #define UIP_ICMP_PAYLOAD ((unsigned char *)&uip_buffer[uip_l3_icmp_hdr_len]) 53 | #define UIP_UDPIP_BUF ((struct uip_udpip_hdr *)uip_buffer) 54 | /*-----POINTER REDEFINITION END-----*/ 55 | 56 | #define UIP_LINK_MTU 1280 //Too high.. should change for a more realistic value 57 | 58 | /** 59 | * Toggles if UDP checksums should be used or not. 60 | * 61 | * \note Support for UDP checksums is currently not included in uIP, 62 | * so this option has no function. 63 | * 64 | * \hideinitializer 65 | */ 66 | #ifdef UIP_CONF_UDP_CHECKSUMS 67 | #define UIP_UDP_CHECKSUMS (UIP_CONF_UDP_CHECKSUMS) 68 | #else 69 | #define UIP_UDP_CHECKSUMS (UIP_CONF_IPV6) 70 | #endif 71 | 72 | /** 73 | * The sums below are quite used in ND. When used for uip_buf, we 74 | * include link layer length when used for uip_len, we do not, hence 75 | * we need values with and without LLH_LEN we do not use capital 76 | * letters as these values are variable 77 | */ 78 | #define uip_l2_l3_hdr_len (UIP_LLH_LEN + UIP_IPH_LEN + uip_ext_len) 79 | #define uip_l2_l3_icmp_hdr_len (UIP_LLH_LEN + UIP_IPH_LEN + uip_ext_len + UIP_ICMPH_LEN) 80 | #define uip_l3_hdr_len (UIP_IPH_LEN + uip_ext_len) 81 | #define uip_l3_icmp_hdr_len (UIP_IPH_LEN + uip_ext_len + UIP_ICMPH_LEN) 82 | 83 | /* The UDP and IP headers. */ 84 | struct uip_udpip_hdr { 85 | /* IPv6 header. */ 86 | u8_t vtc, 87 | tcf; 88 | u16_t flow; 89 | u8_t len[2]; 90 | u8_t proto, ttl; 91 | uip_ip6addr_t srcipaddr, destipaddr; 92 | /* UDP header. */ 93 | u16_t srcport, 94 | destport; 95 | u16_t udplen; 96 | u16_t udpchksum; 97 | }; 98 | 99 | /** 100 | * Construct an IPv6 address from eight 16-bit words. 101 | * 102 | * This function constructs an IPv6 address. 103 | * 104 | * \hideinitializer 105 | */ 106 | #define uip_ip6addr(addr, addr0,addr1,addr2,addr3,addr4,addr5,addr6,addr7) do { \ 107 | (addr)->u16[0] = UIP_HTONS(addr0); \ 108 | (addr)->u16[1] = UIP_HTONS(addr1); \ 109 | (addr)->u16[2] = UIP_HTONS(addr2); \ 110 | (addr)->u16[3] = UIP_HTONS(addr3); \ 111 | (addr)->u16[4] = UIP_HTONS(addr4); \ 112 | (addr)->u16[5] = UIP_HTONS(addr5); \ 113 | (addr)->u16[6] = UIP_HTONS(addr6); \ 114 | (addr)->u16[7] = UIP_HTONS(addr7); \ 115 | } while(0) 116 | 117 | 118 | /** \brief set IP address a to the link local all-rpl nodes multicast address */ 119 | #define uip_create_linklocal_rplnodes_mcast(a) uip_ip6addr(a, 0xff02, 0, 0, 0, 0, 0, 0, 0x001a) 120 | 121 | /** 122 | * \brief is address a multicast address, see RFC 3513 123 | * a is of type uip_ipaddr_t* 124 | * */ 125 | #define uip_is_addr_mcast(a) \ 126 | (((a)->u8[0]) == 0xFF) 127 | 128 | 129 | /** 130 | * \brief is addr (a) a solicited node multicast address, see RFC3513 131 | * a is of type uip_ipaddr_t* 132 | */ 133 | #define uip_is_addr_solicited_node(a) \ 134 | ((((a)->u8[0]) == 0xFF) && \ 135 | (((a)->u8[1]) == 0x02) && \ 136 | (((a)->u16[1]) == 0x00) && \ 137 | (((a)->u16[2]) == 0x00) && \ 138 | (((a)->u16[3]) == 0x00) && \ 139 | (((a)->u16[4]) == 0x00) && \ 140 | (((a)->u8[10]) == 0x00) && \ 141 | (((a)->u8[11]) == 0x01) && \ 142 | (((a)->u8[12]) == 0xFF)) 143 | 144 | #define uip_ipaddr_cmp(addr1, addr2) (memcmp(addr1, addr2, sizeof(uip_ip6addr_t)) == 0) 145 | 146 | #ifndef uip_ipaddr_copy 147 | #define uip_ipaddr_copy(dest, src) (*(dest) = *(src)) 148 | #endif 149 | 150 | #define uip_create_default_prefix(addr) do { \ 151 | (addr)->u16[0] = 0; \ 152 | (addr)->u16[1] = 0; \ 153 | (addr)->u16[2] = 0; \ 154 | (addr)->u16[3] = 0; \ 155 | } while(0) 156 | 157 | #define uip_create_linklocal_prefix(addr) do { \ 158 | (addr)->u16[0] = UIP_HTONS(0xfe80); \ 159 | (addr)->u16[1] = 0; \ 160 | (addr)->u16[2] = 0; \ 161 | (addr)->u16[3] = 0; \ 162 | } while(0) 163 | 164 | /** 165 | * \brief Checks whether the address a is link local. 166 | * a is of type uip_ipaddr_t 167 | */ 168 | #define uip_is_addr_linklocal(a) \ 169 | ((a)->u8[0] == 0xfe && \ 170 | (a)->u8[1] == 0x80) 171 | 172 | /*-----ENUMS-----*/ 173 | enum ConnectionState{ 174 | DISCONNECTED, //means we have to send DIS 175 | WAITING_DIO, //means we sent DIS and we wait for the reception of a DIO 176 | DIO_RECEIVED, //means we received DIO and we have to send DAO 177 | WAITING_DAO_ACK, //means we sent DAO and we wait for the reception of a DAO ACK 178 | DAO_ACK_RECEIVED, //means we received the ACK of the DAO sent and that would be enough to consider connected 179 | CONNECTED //means we are already connected 180 | }; 181 | 182 | enum FrameReceptionResult{ 183 | TIMEOUT, 184 | RECEIVED, 185 | ERROR, 186 | NOTHING 187 | }; 188 | 189 | enum ReceivedPacketType{ 190 | DIO, 191 | DAO_ACK, 192 | UDP, 193 | NOT_EXPECTED_OR_ERROR, 194 | NS 195 | }; 196 | /*-----ENUMS END-----*/ 197 | 198 | class PicoIPv6State{ 199 | 200 | private: 201 | 202 | ReceivedPacketType icmp6_input(); 203 | 204 | ReceivedPacketType udp_input(); 205 | 206 | int uip_rpl_input(void); 207 | 208 | void uip_nd6_ns_input(void); 209 | 210 | void create_llao(uint8_t *llao, uint8_t type); 211 | 212 | void drop(); 213 | protected: 214 | MACLayer* mac; 215 | 216 | ReceivedPacketType lastReceived; 217 | 218 | uint8_t dodag_instance_id; //instance id of the last DIO received 219 | 220 | uip_lladdr_t dst_resp; // link layer destination address of the last received frame (own or broadcast) 221 | uip_lladdr_t src_resp; // link layer source address of last received frame 222 | 223 | 224 | uip_ipaddr_t src_ip_address; // ipv6 address of the source of the last received frame 225 | 226 | uip_lladdr_t* own_ll_address; // link layer address of this device (pointer to) 227 | uip_ip6addr_t own_ip_address; // this device's ip address 228 | 229 | uip_lladdr_t* gateway_ll_address; // link layer address of the gateway corresponding to this device 230 | uip_ip6addr_t* gateway_ip_address; // ip address of the gateway 231 | 232 | u8_t* uip_buffer; 233 | u16_t uip_len; // length of the data into the uip_buffer (this buffer contains the ip packet received or to be sent) 234 | 235 | void (* udp_input_callback)(uint8_t* udp_data, uint16_t length);//callback function called whenever an UDP packet is received. udp_data: pointer to the UDP payload received. length: size of the payload data 236 | 237 | 238 | u16_t uip_htons(u16_t val); 239 | 240 | u32_t uip_htonl(u32_t val); 241 | 242 | u16_t chksum(u16_t sum, const u8_t *data, u16_t len); 243 | 244 | u16_t uip_chksum(u16_t *data, u16_t len); 245 | 246 | u16_t uip_ipchksum(void); 247 | 248 | u16_t upper_layer_chksum(u8_t proto); 249 | 250 | u16_t uip_udpchksum(void); 251 | 252 | u16_t uip_icmp6chksum(void); 253 | 254 | void icmp6_send(uip_ipaddr_t *dest, int type, int code, int payload_len); 255 | 256 | void ip_send(uip_ipaddr_t *dest); 257 | 258 | void compress(uip_lladdr_t* ll_dest_addr); 259 | 260 | void send_at_mac(uip_lladdr_t* ll_dest_addr); 261 | 262 | FrameReceptionResult receive_mac(/*int timeout*/); 263 | 264 | ReceivedPacketType receive_ipv6(); 265 | 266 | ConnectionState currentState; 267 | 268 | virtual void process_input() = 0; 269 | 270 | void uip_lladdr_copy(uip_lladdr_t *dest, const uip_lladdr_t *src, uint8_t addr_size); 271 | 272 | public: 273 | 274 | PicoIPv6State(MACLayer* mac, u8_t* buffer, uip_lladdr_t* own_ll_address, uip_lladdr_t* gateway_ll_address, uip_ip6addr_t* gateway_ip_address); 275 | 276 | virtual ~PicoIPv6State(); 277 | 278 | virtual ConnectionState connect() = 0; 279 | 280 | void setBuffer(uint8_t* buffer); 281 | 282 | uip_lladdr_t* getLastSenderMacAddress(); 283 | 284 | uip_ip6addr_t* getLastSenderIPAddress(); 285 | 286 | 287 | u16_t getLastSenderUDPSourcePort(); 288 | uint16_t getUdpDataLength(); 289 | u16_t getUdpData(char * buffer); 290 | 291 | MACLayer* getMacCommunicator(); 292 | 293 | uint8_t getInstanceId(); 294 | 295 | void changeState(ConnectionState newState); 296 | 297 | ConnectionState getState(); 298 | 299 | virtual bool has_timer_expired() = 0; 300 | 301 | void udp_send(uip_ipaddr_t *dest, u16_t src_port, u16_t dest_port, char* payload, u16_t payload_len); 302 | 303 | bool receive(); 304 | 305 | ReceivedPacketType getLastReceivedPacketType(); 306 | }; 307 | 308 | #endif 309 | -------------------------------------------------------------------------------- /PicoIPv6StateConnectedState.cpp: -------------------------------------------------------------------------------- 1 | #include "PicoIPv6StateConnectedState.h" 2 | 3 | PicoIPv6StateConnectedState::PicoIPv6StateConnectedState(MACLayer* mac, u8_t* buffer, uip_lladdr_t* own_ll_address, /*int timeout,*/ uip_lladdr_t* gateway_ll_address, uip_ip6addr_t* gateway_ip_address, void (* udp_input_callback)(uint8_t* udp_data, uint16_t length), uint8_t instance_id):PicoIPv6State(mac, buffer, own_ll_address, gateway_ll_address, gateway_ip_address){ 4 | this->currentState = CONNECTED; 5 | this->dodag_instance_id = instance_id; 6 | this->udp_input_callback = udp_input_callback; 7 | } 8 | 9 | void PicoIPv6StateConnectedState::process_input(){ 10 | // DO NOTHING BY NOW 11 | } 12 | 13 | ConnectionState PicoIPv6StateConnectedState::connect(){ 14 | //We are already connected! (TODO: discuss if we have to validate connection every X time. Could use the timer for that) 15 | return currentState; 16 | } 17 | 18 | bool PicoIPv6StateConnectedState::has_timer_expired(){ 19 | //By now we say that it has expired because there is nothing to check 20 | return true; 21 | } 22 | -------------------------------------------------------------------------------- /PicoIPv6StateConnectedState.h: -------------------------------------------------------------------------------- 1 | #ifndef __CONNECTEDSTATE_H__ 2 | #define __CONNECTEDSTATE_H__ 3 | 4 | #include "PicoIPv6State.h" 5 | 6 | #define DEBUG 0 7 | 8 | class PicoIPv6StateConnectedState : public PicoIPv6State{ 9 | private: 10 | 11 | virtual void process_input(); 12 | 13 | public: 14 | 15 | PicoIPv6StateConnectedState(MACLayer* mac, u8_t* buffer, uip_lladdr_t* own_ll_address, /*int timeout, */uip_lladdr_t* gateway_ll_address, uip_ip6addr_t* gateway_ip_address, void (* udp_input_callback)(uint8_t* udp_data, uint16_t length), uint8_t instance_id); 16 | 17 | virtual ConnectionState connect(); 18 | 19 | virtual bool has_timer_expired(); 20 | 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /PicoIPv6StateSearchingDIOState.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "PicoIPv6StateSearchingDIOState.h" 3 | #include "arduino_debug.h" 4 | 5 | void 6 | PicoIPv6StateSearchingDIOState::dis_output(uip_ipaddr_t *addr) 7 | { 8 | unsigned char *buffer; 9 | 10 | /* DAG Information Solicitation - 2 bytes reserved */ 11 | /* 0 1 2 */ 12 | /* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 */ 13 | /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ 14 | /* | Flags | Reserved | Option(s)... */ 15 | /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ 16 | 17 | buffer = UIP_ICMP_PAYLOAD; 18 | buffer[0] = buffer[1] = 0; 19 | 20 | icmp6_send(addr, ICMP6_RPL, RPL_CODE_DIS, 2); 21 | } 22 | 23 | bool PicoIPv6StateSearchingDIOState::receive_DIO(){ 24 | if (receive_mac() == RECEIVED){ //GOT SOMETHING AT MAC LEVEL 25 | PRINTF("RECEIVED AT MAC LEVEL"); 26 | if (receive_ipv6() != NOT_EXPECTED_OR_ERROR){ //IF WE RECEIVED SOMETHING THAT WE COULD EXPECT, SEE IF IT IS A DIO 27 | PRINTF("RECEIVED SOMETHING EXPECTED"); 28 | if (lastReceived == DIO){ 29 | PRINTF("RECEIVED DIO"); 30 | if (dodag_instance_id != -1){ 31 | //DIO IS VALID AND WE GOT ITS INSTANCE ID 32 | PRINTF("VALID DIO!"); 33 | return true; 34 | } 35 | } 36 | } 37 | } 38 | return false; 39 | } 40 | 41 | PicoIPv6StateSearchingDIOState::PicoIPv6StateSearchingDIOState(MACLayer* mac, u8_t* buffer, uip_lladdr_t* own_ll_address, int timeout, uip_lladdr_t* gateway_ll_address, uip_ip6addr_t* gateway_ip_address):PicoIPv6State(mac, buffer, own_ll_address, gateway_ll_address, gateway_ip_address){ 42 | this->currentState = DISCONNECTED; 43 | this->timeout = timeout; 44 | } 45 | 46 | ConnectionState PicoIPv6StateSearchingDIOState::connect(){ 47 | if (currentState == DISCONNECTED){ 48 | dis_output(gateway_ip_address); 49 | delay(200); 50 | currentState = WAITING_DIO; 51 | timer_set(&wait_dio_timer, timeout); 52 | } 53 | if (currentState == WAITING_DIO && !timer_expired(&wait_dio_timer)){ 54 | if (receive_DIO()){ 55 | currentState = DIO_RECEIVED; 56 | //now that we received a DIO, copy the values of gateways! (at layers 3 and 2) 57 | uip_ipaddr_copy(gateway_ip_address, &src_ip_address); 58 | uip_lladdr_copy(gateway_ll_address, &src_resp, UIP_LLADDR_LEN); 59 | } 60 | } 61 | 62 | return currentState; 63 | } 64 | 65 | /*--------------------------------*/ 66 | void 67 | PicoIPv6StateSearchingDIOState::dio_input(void) 68 | { 69 | 70 | dodag_instance_id = ((unsigned char *)UIP_ICMP_PAYLOAD)[0]; 71 | 72 | } 73 | 74 | bool PicoIPv6StateSearchingDIOState::has_timer_expired(){ 75 | if (currentState == WAITING_DIO){//if we do not have the WAITING DIO state, we have not even initialized the timer! 76 | if (timer_expired(&wait_dio_timer)) 77 | return true; 78 | } 79 | return false; 80 | } 81 | 82 | void PicoIPv6StateSearchingDIOState::process_input(){ 83 | dio_input(); 84 | } 85 | 86 | -------------------------------------------------------------------------------- /PicoIPv6StateSearchingDIOState.h: -------------------------------------------------------------------------------- 1 | #ifndef __SEARCHDIOSTATE_H__ 2 | #define __SEARCHDIOSTATE_H__ 3 | 4 | 5 | extern "C"{ 6 | #include "timer.h" 7 | } 8 | 9 | #include "PicoIPv6State.h" 10 | 11 | #define DEBUG 0 12 | 13 | class PicoIPv6StateSearchingDIOState : public PicoIPv6State{ 14 | private: 15 | void dis_output(uip_ipaddr_t *addr); 16 | 17 | bool receive_DIO(); 18 | 19 | void dio_input(); 20 | 21 | int timeout; 22 | 23 | virtual void process_input(); 24 | 25 | struct timer wait_dio_timer; 26 | 27 | public: 28 | 29 | PicoIPv6StateSearchingDIOState(MACLayer* mac, u8_t* buffer, uip_lladdr_t* own_ll_address, int timeout, uip_lladdr_t* gateway_ll_address, uip_ip6addr_t* gateway_ip_address); 30 | 31 | virtual ConnectionState connect(); 32 | 33 | virtual bool has_timer_expired(); 34 | }; 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /PicoIPv6StateSendingDAOState.cpp: -------------------------------------------------------------------------------- 1 | #include "PicoIPv6StateSendingDAOState.h" 2 | #include "arduino_debug.h" 3 | 4 | uint8_t PicoIPv6StateSendingDAOState::dao_sequence = 0; 5 | 6 | #define PREFIX_LENGTH 8 7 | 8 | u8_t prefix[PREFIX_LENGTH] = {0, 0, 0, 0, 0, 0, 0, 0}; 9 | 10 | void PicoIPv6StateSendingDAOState::dao_output(uip_ipaddr_t *addr_dest, rpl_lifetime_t lifetime, uint8_t instance_id) 11 | { 12 | unsigned char *buffer; 13 | uint8_t prefixlen; 14 | uip_ipaddr_t addr; 15 | int pos; 16 | 17 | buffer = UIP_ICMP_PAYLOAD; 18 | 19 | ++dao_sequence; 20 | pos = 0; 21 | 22 | buffer[pos++] = instance_id; 23 | #if RPL_CONF_DAO_ACK 24 | buffer[pos++] = RPL_DAO_K_FLAG; /* DAO ACK request, no DODAGID */ 25 | #else 26 | buffer[pos++] = 0; /* No DAO ACK request, no DODAGID */ 27 | #endif 28 | buffer[pos++] = 0; /* reserved */ 29 | buffer[pos++] = dao_sequence & 0xff; 30 | 31 | /* create target subopt */ 32 | prefixlen = PREFIX_LENGTH * CHAR_BIT; 33 | buffer[pos++] = RPL_OPTION_TARGET; 34 | buffer[pos++] = 18;//2 + ((prefixlen + 7) / CHAR_BIT); 35 | buffer[pos++] = 0; /* reserved */ 36 | buffer[pos++] = 128; 37 | memcpy(buffer + pos, &own_ip_address, 16); 38 | pos += 16; 39 | 40 | /* Create a transit information sub-option. */ 41 | buffer[pos++] = RPL_OPTION_TRANSIT; 42 | buffer[pos++] = 4; 43 | buffer[pos++] = 0; /* flags - ignored */ 44 | buffer[pos++] = 0; /* path control - ignored */ 45 | buffer[pos++] = 0; /* path seq - ignored */ 46 | buffer[pos++] = lifetime; 47 | 48 | icmp6_send(addr_dest, ICMP6_RPL, RPL_CODE_DAO, pos); 49 | } 50 | 51 | PicoIPv6StateSendingDAOState::PicoIPv6StateSendingDAOState(MACLayer* mac, u8_t* buffer, uip_lladdr_t* own_ll_address, int timeout, uip_lladdr_t* gateway_ll_address, uip_ip6addr_t* gateway_ip_address, uint8_t instance_id):PicoIPv6State(mac, buffer, own_ll_address, gateway_ll_address, gateway_ip_address){ 52 | this->dodag_instance_id = instance_id; 53 | this->currentState = DIO_RECEIVED; 54 | this->timeout = timeout; 55 | } 56 | 57 | bool PicoIPv6StateSendingDAOState::receive_DAO_ACK(){ 58 | 59 | if (receive_mac() == RECEIVED){ //GOT SOMETHING AT MAC LEVEL 60 | PRINTF("RECEIVED AT MAC LEVEL"); 61 | 62 | if (receive_ipv6() != NOT_EXPECTED_OR_ERROR){ //IF WE RECEIVED SOMETHING THAT WE COULD EXPECT, SEE IF IT IS A DIO 63 | PRINTF("RECEIVED SOMETHING EXPECTED"); 64 | 65 | if (lastReceived == DAO_ACK){ 66 | PRINTF("RECEIVED DAO ACK!"); 67 | return true; 68 | }else{ 69 | if (this->lastReceived == NS){ 70 | //if we are expecting a DAO ACK but we receive an NS, this means that the GW is performing ND with us so we have just sent a NA as response. 71 | //This means also that if the GW received the NA successfully, it will be able to respond our DAO with a DAO ACK this time, so send a new DAO! 72 | dao_output(this->gateway_ip_address, RPL_DEFAULT_LIFETIME, this->dodag_instance_id); 73 | return false; //Because we did not yet receive the DAO ACK 74 | } 75 | } 76 | } 77 | } 78 | return false; 79 | } 80 | 81 | ConnectionState PicoIPv6StateSendingDAOState::connect(){ 82 | if (dodag_instance_id != -1){ 83 | if (currentState == DIO_RECEIVED){ 84 | dao_output(gateway_ip_address, RPL_DEFAULT_LIFETIME, dodag_instance_id); 85 | delay(200); 86 | currentState = WAITING_DAO_ACK; 87 | timer_set(&wait_dao_ack_timer, timeout); 88 | } 89 | if (currentState == WAITING_DAO_ACK && !timer_expired(&wait_dao_ack_timer)){ 90 | if (receive_DAO_ACK()){ 91 | currentState = DAO_ACK_RECEIVED; 92 | } 93 | } 94 | }else{ 95 | //dodag_instance_id not valid! we should remain disconnected 96 | PRINTF("NOT VALID INSTANCE ID! Changing state to DISCONNECTED"); 97 | currentState = DISCONNECTED; 98 | } 99 | return currentState; 100 | } 101 | 102 | bool PicoIPv6StateSendingDAOState::has_timer_expired(){ 103 | if (currentState == WAITING_DAO_ACK){ 104 | if (timer_expired(&wait_dao_ack_timer)) 105 | return true; 106 | } 107 | return false; 108 | } 109 | 110 | void PicoIPv6StateSendingDAOState::process_input(){ 111 | //DO NOTHING BY NOW.. 112 | } 113 | -------------------------------------------------------------------------------- /PicoIPv6StateSendingDAOState.h: -------------------------------------------------------------------------------- 1 | #ifndef __SENDINGDAOSTATE_H__ 2 | #define __SENDINGDAOSTATE_H__ 3 | 4 | extern "C"{ 5 | #include "timer.h" 6 | } 7 | 8 | #include "PicoIPv6State.h" 9 | 10 | #define DEBUG 0 11 | 12 | class PicoIPv6StateSendingDAOState : public PicoIPv6State{ 13 | private: 14 | void dao_output(uip_ipaddr_t *addr, rpl_lifetime_t lifetime, uint8_t instance_id); 15 | 16 | bool receive_DAO_ACK(); 17 | 18 | int timeout; 19 | 20 | static uint8_t dao_sequence; 21 | 22 | struct timer wait_dao_ack_timer; 23 | 24 | protected: 25 | 26 | virtual void process_input(); 27 | 28 | public: 29 | 30 | PicoIPv6StateSendingDAOState(MACLayer* mac, u8_t* buffer, uip_lladdr_t* own_ll_address, int timeout, uip_lladdr_t* gateway_ll_address, uip_ip6addr_t* gateway_ip_address, uint8_t instance_id); 31 | 32 | virtual ConnectionState connect(); 33 | 34 | virtual bool has_timer_expired(); 35 | 36 | }; 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Arduino pico IPv6 stack 2 | ======================= 3 | 4 | A very light IPv6 stack for [Arduinos](http://www.arduino.cc/) UNO and [Xbee](http://www.digi.com/en/products/wireless/point-multipoint/xbee-series1-module) 5 | based on [Contiki OS](http://www.contiki-os.org/) network stack. 6 | 7 | If you are using our [Arduino µIPv6 stack](https://github.com/telecombretagne/Arduino-IPv6Stack/), you're 8 | probably wondering why we created a lighter stack ? 9 | Because Arduino UNO has to be IPv6 ready too ! With this stack, you'll be able to join a 6LoWPAN network using 10 | Arduinos UNO (which only have 2kB of RAM). 11 | With pIPv6 stack, we reduced RPL and CoAP functionnalities to keep an ultra small memory footprint ( **pIPv6** acronym 12 | stands for " **p**ico **I**nternet **P**rotocol **v**ersion **6**"). 13 | 14 | 15 | ![Arduino pIPv6 Stack](http://departements.telecom-bretagne.eu/data/rsm/pIPv6%20stack%20diagram.png) 16 | 17 | 18 | Features 19 | -------- 20 | 21 | * IP network stack with low-power standards : [6LoWPAN](http://datatracker.ietf.org/wg/6lowpan/charter/), reduced [RPL](http://tools.ietf.org/html/rfc6550), and [CoAP](http://datatracker.ietf.org/doc/draft-ietf-core-coap/) 22 | * Compatible with all [Arduino](http://arduino.cc/en/Main/Products) boards 23 | * Based on [Contiki OS](http://www.contiki-os.org/) network stack 24 | * Can be used on top of [IEEE 802.15.4](http://www.digi.com/products/wireless-wired-embedded-solutions/zigbee-rf-modules/point-multipoint-rfmodules/xbee-series1-module), IEEE 802.3 (Ethernet), IEEE 802.11 (Wifi) MAC layers * 25 | 26 | *: We are only providing [XBee Series 1](http://www.digi.com/products/wireless-wired-embedded-solutions/zigbee-rf-modules/point-multipoint-rfmodules/xbee-series1-module) interface for now. 27 | 28 | Get Started 29 | ----------- 30 | 31 | To get started using pIPv6 stack, go to the [wiki](https://github.com/telecombretagne/Arduino-pIPv6Stack/wiki). The wiki 32 | contains a step-by-step tutorial and examples necessary to build your first Arduino UNO Wireless Sensor Network. 33 | 34 | ![Arduino WSN](http://departements.telecom-bretagne.eu/data/rsm/heterogeneous%20wsn%20arch.png) 35 | 36 | 37 | License 38 | ------- 39 | 40 | This stack is open source software : it can be freely used both in commercial and non-commercial systems and the full source code is available. 41 | 42 | 43 | People 44 | ------- 45 | [Renzo Navas](renzo.navas@telecom-bretagne.eu) (Télecom Bretagne, RSM dpt) : *project maintainer* 46 | 47 | [Baptiste Gaultier](baptiste.gaultier@telecom-bretagne.eu) (Télecom Bretagne, RSM dpt) : *developer and documentation maintainer* 48 | 49 | [Laurent Toutain](Laurent.Toutain@telecom-bretagne.eu) (Télecom Bretagne, RSM dpt) : *associate professor and project lead* 50 | -------------------------------------------------------------------------------- /RPL_Constants.h: -------------------------------------------------------------------------------- 1 | 2 | /* RPL message types */ 3 | #define RPL_CODE_DIS 0x00 /* DAG Information Solicitation */ 4 | #define RPL_CODE_DIO 0x01 /* DAG Information Option */ 5 | #define RPL_CODE_DAO 0x02 /* Destination Advertisement Option */ 6 | #define RPL_CODE_DAO_ACK 0x03 /* DAO acknowledgment */ 7 | 8 | /* RPL control message options. */ 9 | #define RPL_OPTION_PAD1 0 10 | #define RPL_OPTION_PADN 1 11 | #define RPL_OPTION_DAG_METRIC_CONTAINER 2 12 | #define RPL_OPTION_ROUTE_INFO 3 13 | #define RPL_OPTION_DAG_CONF 4 14 | #define RPL_OPTION_TARGET 5 15 | #define RPL_OPTION_TRANSIT 6 16 | #define RPL_OPTION_SOLICITED_INFO 7 17 | #define RPL_OPTION_PREFIX_INFO 8 18 | #define RPL_OPTION_TARGET_DESC 9 19 | 20 | /* Default route lifetime as a multiple of the lifetime unit. */ 21 | #define RPL_DEFAULT_LIFETIME 0xff 22 | 23 | #define ICMP6_RPL 155 24 | 25 | #define RPL_DAO_K_FLAG 0x80 /* DAO ACK requested */ 26 | 27 | #define HOP_LIMIT 0x40 28 | 29 | typedef uint8_t rpl_lifetime_t; 30 | -------------------------------------------------------------------------------- /XBee.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2009 Andrew Rapp. All rights reserved. 3 | * 4 | * This file is part of XBee-Arduino. 5 | * 6 | * XBee-Arduino is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * XBee-Arduino is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with XBee-Arduino. If not, see . 18 | */ 19 | 20 | #ifndef XBee_h 21 | #define XBee_h 22 | 23 | #if defined(ARDUINO) && ARDUINO >= 100 24 | #include "Arduino.h" 25 | #else 26 | #include "WProgram.h" 27 | #endif 28 | 29 | #include 30 | 31 | #define SERIES_1 32 | #define SERIES_2 33 | 34 | // set to ATAP value of XBee. AP=2 is recommended 35 | #define ATAP 2 36 | 37 | #define START_BYTE 0x7e 38 | #define ESCAPE 0x7d 39 | #define XON 0x11 40 | #define XOFF 0x13 41 | 42 | // This value determines the size of the byte array for receiving RX packets 43 | // Most users won't be dealing with packets this large so you can adjust this 44 | // value to reduce memory consumption. But, remember that 45 | // if a RX packet exceeds this size, it cannot be parsed! 46 | 47 | // This value is determined by the largest packet size (100 byte payload + 64-bit address + option byte and rssi byte) of a series 1 radio 48 | #define MAX_FRAME_DATA_SIZE 110 49 | 50 | #define BROADCAST_ADDRESS 0xffff 51 | #define ZB_BROADCAST_ADDRESS 0xfffe 52 | 53 | // the non-variable length of the frame data (not including frame id or api id or variable data size (e.g. payload, at command set value) 54 | #define ZB_TX_API_LENGTH 12 55 | #define TX_16_API_LENGTH 3 56 | #define TX_64_API_LENGTH 9 57 | #define AT_COMMAND_API_LENGTH 2 58 | #define REMOTE_AT_COMMAND_API_LENGTH 13 59 | // start/length(2)/api/frameid/checksum bytes 60 | #define PACKET_OVERHEAD_LENGTH 6 61 | // api is always the third byte in packet 62 | #define API_ID_INDEX 3 63 | 64 | // frame position of rssi byte 65 | #define RX_16_RSSI_OFFSET 2 66 | #define RX_64_RSSI_OFFSET 8 67 | 68 | #define DEFAULT_FRAME_ID 1 69 | #define NO_RESPONSE_FRAME_ID 0 70 | 71 | // TODO put in tx16 class 72 | #define ACK_OPTION 0 73 | #define DISABLE_ACK_OPTION 1 74 | #define BROADCAST_OPTION 4 75 | 76 | // RX options 77 | #define ZB_PACKET_ACKNOWLEDGED 0x01 78 | #define ZB_BROADCAST_PACKET 0x02 79 | 80 | // not everything is implemented! 81 | /** 82 | * Api Id constants 83 | */ 84 | #define TX_64_REQUEST 0x0 85 | #define TX_16_REQUEST 0x1 86 | #define AT_COMMAND_REQUEST 0x08 87 | #define AT_COMMAND_QUEUE_REQUEST 0x09 88 | #define REMOTE_AT_REQUEST 0x17 89 | #define ZB_TX_REQUEST 0x10 90 | #define ZB_EXPLICIT_TX_REQUEST 0x11 91 | #define RX_64_RESPONSE 0x80 92 | #define RX_16_RESPONSE 0x81 93 | #define RX_64_IO_RESPONSE 0x82 94 | #define RX_16_IO_RESPONSE 0x83 95 | #define AT_RESPONSE 0x88 96 | #define TX_STATUS_RESPONSE 0x89 97 | #define MODEM_STATUS_RESPONSE 0x8a 98 | #define ZB_RX_RESPONSE 0x90 99 | #define ZB_EXPLICIT_RX_RESPONSE 0x91 100 | #define ZB_TX_STATUS_RESPONSE 0x8b 101 | #define ZB_IO_SAMPLE_RESPONSE 0x92 102 | #define ZB_IO_NODE_IDENTIFIER_RESPONSE 0x95 103 | #define AT_COMMAND_RESPONSE 0x88 104 | #define REMOTE_AT_COMMAND_RESPONSE 0x97 105 | 106 | 107 | /** 108 | * TX STATUS constants 109 | */ 110 | #define SUCCESS 0x0 111 | #define CCA_FAILURE 0x2 112 | #define INVALID_DESTINATION_ENDPOINT_SUCCESS 0x15 113 | #define NETWORK_ACK_FAILURE 0x21 114 | #define NOT_JOINED_TO_NETWORK 0x22 115 | #define SELF_ADDRESSED 0x23 116 | #define ADDRESS_NOT_FOUND 0x24 117 | #define ROUTE_NOT_FOUND 0x25 118 | #define PAYLOAD_TOO_LARGE 0x74 119 | 120 | // modem status 121 | #define HARDWARE_RESET 0 122 | #define WATCHDOG_TIMER_RESET 1 123 | #define ASSOCIATED 2 124 | #define DISASSOCIATED 3 125 | #define SYNCHRONIZATION_LOST 4 126 | #define COORDINATOR_REALIGNMENT 5 127 | #define COORDINATOR_STARTED 6 128 | 129 | #define ZB_BROADCAST_RADIUS_MAX_HOPS 0 130 | 131 | #define ZB_TX_UNICAST 0 132 | #define ZB_TX_BROADCAST 8 133 | 134 | #define AT_OK 0 135 | #define AT_ERROR 1 136 | #define AT_INVALID_COMMAND 2 137 | #define AT_INVALID_PARAMETER 3 138 | #define AT_NO_RESPONSE 4 139 | 140 | #define NO_ERROR 0 141 | #define CHECKSUM_FAILURE 1 142 | #define PACKET_EXCEEDS_BYTE_ARRAY_LENGTH 2 143 | #define UNEXPECTED_START_BYTE 3 144 | 145 | /** 146 | * The super class of all XBee responses (RX packets) 147 | * Users should never attempt to create an instance of this class; instead 148 | * create an instance of a subclass 149 | * It is recommend to reuse subclasses to conserve memory 150 | */ 151 | class XBeeResponse { 152 | public: 153 | //static const int MODEM_STATUS = 0x8a; 154 | /** 155 | * Default constructor 156 | */ 157 | XBeeResponse(); 158 | /** 159 | * Returns Api Id of the response 160 | */ 161 | uint8_t getApiId(); 162 | void setApiId(uint8_t apiId); 163 | /** 164 | * Returns the MSB length of the packet 165 | */ 166 | uint8_t getMsbLength(); 167 | void setMsbLength(uint8_t msbLength); 168 | /** 169 | * Returns the LSB length of the packet 170 | */ 171 | uint8_t getLsbLength(); 172 | void setLsbLength(uint8_t lsbLength); 173 | /** 174 | * Returns the packet checksum 175 | */ 176 | uint8_t getChecksum(); 177 | void setChecksum(uint8_t checksum); 178 | /** 179 | * Returns the length of the frame data: all bytes after the api id, and prior to the checksum 180 | * Note up to release 0.1.2, this was incorrectly including the checksum in the length. 181 | */ 182 | uint8_t getFrameDataLength(); 183 | void setFrameData(uint8_t* frameDataPtr); 184 | /** 185 | * Returns the buffer that contains the response. 186 | * Starts with byte that follows API ID and includes all bytes prior to the checksum 187 | * Length is specified by getFrameDataLength() 188 | * Note: Unlike Digi's definition of the frame data, this does not start with the API ID.. 189 | * The reason for this is all responses include an API ID, whereas my frame data 190 | * includes only the API specific data. 191 | */ 192 | uint8_t* getFrameData(); 193 | 194 | void setFrameLength(uint8_t frameLength); 195 | // to support future 65535 byte packets I guess 196 | /** 197 | * Returns the length of the packet 198 | */ 199 | uint16_t getPacketLength(); 200 | /** 201 | * Resets the response to default values 202 | */ 203 | void reset(); 204 | /** 205 | * Initializes the response 206 | */ 207 | void init(); 208 | #ifdef SERIES_2 209 | /** 210 | * Call with instance of ZBTxStatusResponse class only if getApiId() == ZB_TX_STATUS_RESPONSE 211 | * to populate response 212 | */ 213 | void getZBTxStatusResponse(XBeeResponse &response); 214 | /** 215 | * Call with instance of ZBRxResponse class only if getApiId() == ZB_RX_RESPONSE 216 | * to populate response 217 | */ 218 | void getZBRxResponse(XBeeResponse &response); 219 | /** 220 | * Call with instance of ZBRxIoSampleResponse class only if getApiId() == ZB_IO_SAMPLE_RESPONSE 221 | * to populate response 222 | */ 223 | void getZBRxIoSampleResponse(XBeeResponse &response); 224 | #endif 225 | #ifdef SERIES_1 226 | /** 227 | * Call with instance of TxStatusResponse only if getApiId() == TX_STATUS_RESPONSE 228 | */ 229 | void getTxStatusResponse(XBeeResponse &response); 230 | /** 231 | * Call with instance of Rx16Response only if getApiId() == RX_16_RESPONSE 232 | */ 233 | void getRx16Response(XBeeResponse &response); 234 | /** 235 | * Call with instance of Rx64Response only if getApiId() == RX_64_RESPONSE 236 | */ 237 | void getRx64Response(XBeeResponse &response); 238 | /** 239 | * Call with instance of Rx16IoSampleResponse only if getApiId() == RX_16_IO_RESPONSE 240 | */ 241 | void getRx16IoSampleResponse(XBeeResponse &response); 242 | /** 243 | * Call with instance of Rx64IoSampleResponse only if getApiId() == RX_64_IO_RESPONSE 244 | */ 245 | void getRx64IoSampleResponse(XBeeResponse &response); 246 | #endif 247 | /** 248 | * Call with instance of AtCommandResponse only if getApiId() == AT_COMMAND_RESPONSE 249 | */ 250 | void getAtCommandResponse(XBeeResponse &responses); 251 | /** 252 | * Call with instance of RemoteAtCommandResponse only if getApiId() == REMOTE_AT_COMMAND_RESPONSE 253 | */ 254 | void getRemoteAtCommandResponse(XBeeResponse &response); 255 | /** 256 | * Call with instance of ModemStatusResponse only if getApiId() == MODEM_STATUS_RESPONSE 257 | */ 258 | void getModemStatusResponse(XBeeResponse &response); 259 | /** 260 | * Returns true if the response has been successfully parsed and is complete and ready for use 261 | */ 262 | bool isAvailable(); 263 | void setAvailable(bool complete); 264 | /** 265 | * Returns true if the response contains errors 266 | */ 267 | bool isError(); 268 | /** 269 | * Returns an error code, or zero, if successful. 270 | * Error codes include: CHECKSUM_FAILURE, PACKET_EXCEEDS_BYTE_ARRAY_LENGTH, UNEXPECTED_START_BYTE 271 | */ 272 | uint8_t getErrorCode(); 273 | void setErrorCode(uint8_t errorCode); 274 | protected: 275 | // pointer to frameData 276 | uint8_t* _frameDataPtr; 277 | private: 278 | void setCommon(XBeeResponse &target); 279 | uint8_t _apiId; 280 | uint8_t _msbLength; 281 | uint8_t _lsbLength; 282 | uint8_t _checksum; 283 | uint8_t _frameLength; 284 | bool _complete; 285 | uint8_t _errorCode; 286 | }; 287 | 288 | class XBeeAddress { 289 | public: 290 | XBeeAddress(); 291 | }; 292 | 293 | /** 294 | * Represents a 64-bit XBee Address 295 | */ 296 | class XBeeAddress64 : public XBeeAddress { 297 | public: 298 | XBeeAddress64(uint32_t msb, uint32_t lsb); 299 | XBeeAddress64(); 300 | uint32_t getMsb(); 301 | uint32_t getLsb(); 302 | void setMsb(uint32_t msb); 303 | void setLsb(uint32_t lsb); 304 | protected: 305 | uint32_t _msb; 306 | uint32_t _lsb; 307 | }; 308 | 309 | //class XBeeAddress16 : public XBeeAddress { 310 | //public: 311 | // XBeeAddress16(uint16_t addr); 312 | // XBeeAddress16(); 313 | // uint16_t getAddress(); 314 | // void setAddress(uint16_t addr); 315 | //private: 316 | // uint16_t _addr; 317 | //}; 318 | 319 | /** 320 | * This class is extended by all Responses that include a frame id 321 | */ 322 | class FrameIdResponse : public XBeeResponse { 323 | public: 324 | FrameIdResponse(); 325 | uint8_t getFrameId(); 326 | private: 327 | uint8_t _frameId; 328 | }; 329 | 330 | /** 331 | * Common functionality for both Series 1 and 2 data RX data packets 332 | */ 333 | class RxDataResponse : public XBeeResponse { 334 | public: 335 | RxDataResponse(); 336 | /** 337 | * Returns the specified index of the payload. The index may be 0 to getDataLength() - 1 338 | * This method is deprecated; use uint8_t* getData() 339 | */ 340 | uint8_t getData(int index); 341 | /** 342 | * Returns the payload array. This may be accessed from index 0 to getDataLength() - 1 343 | */ 344 | uint8_t* getData(); 345 | /** 346 | * Returns the length of the payload 347 | */ 348 | virtual uint8_t getDataLength() = 0; 349 | /** 350 | * Returns the position in the frame data where the data begins 351 | */ 352 | virtual uint8_t getDataOffset() = 0; 353 | }; 354 | 355 | // getResponse to return the proper subclass: 356 | // we maintain a pointer to each type of response, when a response is parsed, it is allocated only if NULL 357 | // can we allocate an object in a function? 358 | 359 | #ifdef SERIES_2 360 | /** 361 | * Represents a Series 2 TX status packet 362 | */ 363 | class ZBTxStatusResponse : public FrameIdResponse { 364 | public: 365 | ZBTxStatusResponse(); 366 | uint16_t getRemoteAddress(); 367 | uint8_t getTxRetryCount(); 368 | uint8_t getDeliveryStatus(); 369 | uint8_t getDiscoveryStatus(); 370 | bool isSuccess(); 371 | }; 372 | 373 | /** 374 | * Represents a Series 2 RX packet 375 | */ 376 | class ZBRxResponse : public RxDataResponse { 377 | public: 378 | ZBRxResponse(); 379 | XBeeAddress64& getRemoteAddress64(); 380 | uint16_t getRemoteAddress16(); 381 | uint8_t getOption(); 382 | uint8_t getDataLength(); 383 | // frame position where data starts 384 | uint8_t getDataOffset(); 385 | private: 386 | XBeeAddress64 _remoteAddress64; 387 | }; 388 | 389 | /** 390 | * Represents a Series 2 RX I/O Sample packet 391 | */ 392 | class ZBRxIoSampleResponse : public ZBRxResponse { 393 | public: 394 | ZBRxIoSampleResponse(); 395 | bool containsAnalog(); 396 | bool containsDigital(); 397 | /** 398 | * Returns true if the pin is enabled 399 | */ 400 | bool isAnalogEnabled(uint8_t pin); 401 | /** 402 | * Returns true if the pin is enabled 403 | */ 404 | bool isDigitalEnabled(uint8_t pin); 405 | /** 406 | * Returns the 10-bit analog reading of the specified pin. 407 | * Valid pins include ADC:xxx. 408 | */ 409 | uint16_t getAnalog(uint8_t pin); 410 | /** 411 | * Returns true if the specified pin is high/on. 412 | * Valid pins include DIO:xxx. 413 | */ 414 | bool isDigitalOn(uint8_t pin); 415 | uint8_t getDigitalMaskMsb(); 416 | uint8_t getDigitalMaskLsb(); 417 | uint8_t getAnalogMask(); 418 | }; 419 | 420 | #endif 421 | 422 | #ifdef SERIES_1 423 | /** 424 | * Represents a Series 1 TX Status packet 425 | */ 426 | class TxStatusResponse : public FrameIdResponse { 427 | public: 428 | TxStatusResponse(); 429 | uint8_t getStatus(); 430 | bool isSuccess(); 431 | }; 432 | 433 | /** 434 | * Represents a Series 1 RX packet 435 | */ 436 | class RxResponse : public RxDataResponse { 437 | public: 438 | RxResponse(); 439 | // remember rssi is negative but this is unsigned byte so it's up to you to convert 440 | uint8_t getRssi(); 441 | uint8_t getOption(); 442 | bool isAddressBroadcast(); 443 | bool isPanBroadcast(); 444 | uint8_t getDataLength(); 445 | uint8_t getDataOffset(); 446 | virtual uint8_t getRssiOffset() = 0; 447 | }; 448 | 449 | /** 450 | * Represents a Series 1 16-bit address RX packet 451 | */ 452 | class Rx16Response : public RxResponse { 453 | public: 454 | Rx16Response(); 455 | uint8_t getRssiOffset(); 456 | uint16_t getRemoteAddress16(); 457 | protected: 458 | uint16_t _remoteAddress; 459 | }; 460 | 461 | /** 462 | * Represents a Series 1 64-bit address RX packet 463 | */ 464 | class Rx64Response : public RxResponse { 465 | public: 466 | Rx64Response(); 467 | uint8_t getRssiOffset(); 468 | XBeeAddress64& getRemoteAddress64(); 469 | private: 470 | XBeeAddress64 _remoteAddress; 471 | }; 472 | 473 | /** 474 | * Represents a Series 1 RX I/O Sample packet 475 | */ 476 | class RxIoSampleBaseResponse : public RxResponse { 477 | public: 478 | RxIoSampleBaseResponse(); 479 | /** 480 | * Returns the number of samples in this packet 481 | */ 482 | uint8_t getSampleSize(); 483 | bool containsAnalog(); 484 | bool containsDigital(); 485 | /** 486 | * Returns true if the specified analog pin is enabled 487 | */ 488 | bool isAnalogEnabled(uint8_t pin); 489 | /** 490 | * Returns true if the specified digital pin is enabled 491 | */ 492 | bool isDigitalEnabled(uint8_t pin); 493 | /** 494 | * Returns the 10-bit analog reading of the specified pin. 495 | * Valid pins include ADC:0-5. Sample index starts at 0 496 | */ 497 | uint16_t getAnalog(uint8_t pin, uint8_t sample); 498 | /** 499 | * Returns true if the specified pin is high/on. 500 | * Valid pins include DIO:0-8. Sample index starts at 0 501 | */ 502 | bool isDigitalOn(uint8_t pin, uint8_t sample); 503 | uint8_t getSampleOffset(); 504 | private: 505 | }; 506 | 507 | class Rx16IoSampleResponse : public RxIoSampleBaseResponse { 508 | public: 509 | Rx16IoSampleResponse(); 510 | uint16_t getRemoteAddress16(); 511 | uint8_t getRssiOffset(); 512 | 513 | }; 514 | 515 | class Rx64IoSampleResponse : public RxIoSampleBaseResponse { 516 | public: 517 | Rx64IoSampleResponse(); 518 | XBeeAddress64& getRemoteAddress64(); 519 | uint8_t getRssiOffset(); 520 | private: 521 | XBeeAddress64 _remoteAddress; 522 | }; 523 | 524 | #endif 525 | 526 | /** 527 | * Represents a Modem Status RX packet 528 | */ 529 | class ModemStatusResponse : public XBeeResponse { 530 | public: 531 | ModemStatusResponse(); 532 | uint8_t getStatus(); 533 | }; 534 | 535 | /** 536 | * Represents an AT Command RX packet 537 | */ 538 | class AtCommandResponse : public FrameIdResponse { 539 | public: 540 | AtCommandResponse(); 541 | /** 542 | * Returns an array containing the two character command 543 | */ 544 | uint8_t* getCommand(); 545 | /** 546 | * Returns the command status code. 547 | * Zero represents a successful command 548 | */ 549 | uint8_t getStatus(); 550 | /** 551 | * Returns an array containing the command value. 552 | * This is only applicable to query commands. 553 | */ 554 | uint8_t* getValue(); 555 | /** 556 | * Returns the length of the command value array. 557 | */ 558 | uint8_t getValueLength(); 559 | /** 560 | * Returns true if status equals AT_OK 561 | */ 562 | bool isOk(); 563 | }; 564 | 565 | /** 566 | * Represents a Remote AT Command RX packet 567 | */ 568 | class RemoteAtCommandResponse : public AtCommandResponse { 569 | public: 570 | RemoteAtCommandResponse(); 571 | /** 572 | * Returns an array containing the two character command 573 | */ 574 | uint8_t* getCommand(); 575 | /** 576 | * Returns the command status code. 577 | * Zero represents a successful command 578 | */ 579 | uint8_t getStatus(); 580 | /** 581 | * Returns an array containing the command value. 582 | * This is only applicable to query commands. 583 | */ 584 | uint8_t* getValue(); 585 | /** 586 | * Returns the length of the command value array. 587 | */ 588 | uint8_t getValueLength(); 589 | /** 590 | * Returns the 16-bit address of the remote radio 591 | */ 592 | uint16_t getRemoteAddress16(); 593 | /** 594 | * Returns the 64-bit address of the remote radio 595 | */ 596 | XBeeAddress64& getRemoteAddress64(); 597 | /** 598 | * Returns true if command was successful 599 | */ 600 | bool isOk(); 601 | private: 602 | XBeeAddress64 _remoteAddress64; 603 | }; 604 | 605 | 606 | /** 607 | * Super class of all XBee requests (TX packets) 608 | * Users should never create an instance of this class; instead use an subclass of this class 609 | * It is recommended to reuse Subclasses of the class to conserve memory 610 | *

611 | * This class allocates a buffer to 612 | */ 613 | class XBeeRequest { 614 | public: 615 | /** 616 | * Constructor 617 | * TODO make protected 618 | */ 619 | XBeeRequest(uint8_t apiId, uint8_t frameId); 620 | /** 621 | * Sets the frame id. Must be between 1 and 255 inclusive to get a TX status response. 622 | */ 623 | void setFrameId(uint8_t frameId); 624 | /** 625 | * Returns the frame id 626 | */ 627 | uint8_t getFrameId(); 628 | /** 629 | * Returns the API id 630 | */ 631 | uint8_t getApiId(); 632 | // setting = 0 makes this a pure virtual function, meaning the subclass must implement, like abstract in java 633 | /** 634 | * Starting after the frame id (pos = 0) and up to but not including the checksum 635 | * Note: Unlike Digi's definition of the frame data, this does not start with the API ID. 636 | * The reason for this is the API ID and Frame ID are common to all requests, whereas my definition of 637 | * frame data is only the API specific data. 638 | */ 639 | virtual uint8_t getFrameData(uint8_t pos) = 0; 640 | /** 641 | * Returns the size of the api frame (not including frame id or api id or checksum). 642 | */ 643 | virtual uint8_t getFrameDataLength() = 0; 644 | //void reset(); 645 | protected: 646 | void setApiId(uint8_t apiId); 647 | private: 648 | uint8_t _apiId; 649 | uint8_t _frameId; 650 | }; 651 | 652 | // TODO add reset/clear method since responses are often reused 653 | /** 654 | * Primary interface for communicating with an XBee Radio. 655 | * This class provides methods for sending and receiving packets with an XBee radio via the serial port. 656 | * The XBee radio must be configured in API (packet) mode (AP=2) 657 | * in order to use this software. 658 | *

659 | * Since this code is designed to run on a microcontroller, with only one thread, you are responsible for reading the 660 | * data off the serial buffer in a timely manner. This involves a call to a variant of readPacket(...). 661 | * If your serial port is receiving data faster than you are reading, you can expect to lose packets. 662 | * Arduino only has a 128 byte serial buffer so it can easily overflow if two or more packets arrive 663 | * without a call to readPacket(...) 664 | *

665 | * In order to conserve resources, this class only supports storing one response packet in memory at a time. 666 | * This means that you must fully consume the packet prior to calling readPacket(...), because calling 667 | * readPacket(...) overwrites the previous response. 668 | *

669 | * This class creates an array of size MAX_FRAME_DATA_SIZE for storing the response packet. You may want 670 | * to adjust this value to conserve memory. 671 | * 672 | * \author Andrew Rapp 673 | */ 674 | class XBee { 675 | public: 676 | XBee(); 677 | /** 678 | * Reads all available serial bytes until a packet is parsed, an error occurs, or the buffer is empty. 679 | * You may call xbee.getResponse().isAvailable() after calling this method to determine if 680 | * a packet is ready, or xbee.getResponse().isError() to determine if 681 | * a error occurred. 682 | *

683 | * This method should always return quickly since it does not wait for serial data to arrive. 684 | * You will want to use this method if you are doing other timely stuff in your loop, where 685 | * a delay would cause problems. 686 | * NOTE: calling this method resets the current response, so make sure you first consume the 687 | * current response 688 | */ 689 | void readPacket(); 690 | /** 691 | * Waits a maximum of timeout milliseconds for a response packet before timing out; returns true if packet is read. 692 | * Returns false if timeout or error occurs. 693 | */ 694 | bool readPacket(int timeout); 695 | /** 696 | * Reads until a packet is received or an error occurs. 697 | * Caution: use this carefully since if you don't get a response, your Arduino code will hang on this 698 | * call forever!! often it's better to use a timeout: readPacket(int) 699 | */ 700 | void readPacketUntilAvailable(); 701 | /** 702 | * Starts the serial connection at the supplied baud rate 703 | */ 704 | void begin(long baud); 705 | void getResponse(XBeeResponse &response); 706 | /** 707 | * Returns a reference to the current response 708 | * Note: once readPacket is called again this response will be overwritten! 709 | */ 710 | XBeeResponse& getResponse(); 711 | /** 712 | * Sends a XBeeRequest (TX packet) out the serial port 713 | */ 714 | void send(XBeeRequest &request); 715 | //uint8_t sendAndWaitForResponse(XBeeRequest &request, int timeout); 716 | /** 717 | * Returns a sequential frame id between 1 and 255 718 | */ 719 | uint8_t getNextFrameId(); 720 | /** 721 | * Specify the serial port. Only relevant for Arduinos that support multiple serial ports (e.g. Mega) 722 | */ 723 | void setSerial(HardwareSerial &serial); 724 | private: 725 | bool available(); 726 | uint8_t read(); 727 | void flush(); 728 | void write(uint8_t val); 729 | void sendByte(uint8_t b, bool escape); 730 | void resetResponse(); 731 | XBeeResponse _response; 732 | bool _escape; 733 | // current packet position for response. just a state variable for packet parsing and has no relevance for the response otherwise 734 | uint8_t _pos; 735 | // last byte read 736 | uint8_t b; 737 | uint8_t _checksumTotal; 738 | uint8_t _nextFrameId; 739 | // buffer for incoming RX packets. holds only the api specific frame data, starting after the api id byte and prior to checksum 740 | uint8_t _responseFrameData[MAX_FRAME_DATA_SIZE]; 741 | HardwareSerial* _serial; 742 | }; 743 | 744 | /** 745 | * All TX packets that support payloads extend this class 746 | */ 747 | class PayloadRequest : public XBeeRequest { 748 | public: 749 | PayloadRequest(uint8_t apiId, uint8_t frameId, uint8_t *payload, uint8_t payloadLength); 750 | /** 751 | * Returns the payload of the packet, if not null 752 | */ 753 | uint8_t* getPayload(); 754 | /** 755 | * Sets the payload array 756 | */ 757 | void setPayload(uint8_t* payloadPtr); 758 | /** 759 | * Returns the length of the payload array, as specified by the user. 760 | */ 761 | uint8_t getPayloadLength(); 762 | /** 763 | * Sets the length of the payload to include in the request. For example if the payload array 764 | * is 50 bytes and you only want the first 10 to be included in the packet, set the length to 10. 765 | * Length must be <= to the array length. 766 | */ 767 | void setPayloadLength(uint8_t payloadLength); 768 | private: 769 | uint8_t* _payloadPtr; 770 | uint8_t _payloadLength; 771 | }; 772 | 773 | #ifdef SERIES_1 774 | 775 | /** 776 | * Represents a Series 1 TX packet that corresponds to Api Id: TX_16_REQUEST 777 | *

778 | * Be careful not to send a data array larger than the max packet size of your radio. 779 | * This class does not perform any validation of packet size and there will be no indication 780 | * if the packet is too large, other than you will not get a TX Status response. 781 | * The datasheet says 100 bytes is the maximum, although that could change in future firmware. 782 | */ 783 | class Tx16Request : public PayloadRequest { 784 | public: 785 | Tx16Request(uint16_t addr16, uint8_t option, uint8_t *payload, uint8_t payloadLength, uint8_t frameId); 786 | /** 787 | * Creates a Unicast Tx16Request with the ACK option and DEFAULT_FRAME_ID 788 | */ 789 | Tx16Request(uint16_t addr16, uint8_t *payload, uint8_t payloadLength); 790 | /** 791 | * Creates a default instance of this class. At a minimum you must specify 792 | * a payload, payload length and a destination address before sending this request. 793 | */ 794 | Tx16Request(); 795 | uint16_t getAddress16(); 796 | void setAddress16(uint16_t addr16); 797 | uint8_t getOption(); 798 | void setOption(uint8_t option); 799 | uint8_t getFrameData(uint8_t pos); 800 | uint8_t getFrameDataLength(); 801 | protected: 802 | private: 803 | uint16_t _addr16; 804 | uint8_t _option; 805 | }; 806 | 807 | /** 808 | * Represents a Series 1 TX packet that corresponds to Api Id: TX_64_REQUEST 809 | * 810 | * Be careful not to send a data array larger than the max packet size of your radio. 811 | * This class does not perform any validation of packet size and there will be no indication 812 | * if the packet is too large, other than you will not get a TX Status response. 813 | * The datasheet says 100 bytes is the maximum, although that could change in future firmware. 814 | */ 815 | class Tx64Request : public PayloadRequest { 816 | public: 817 | Tx64Request(XBeeAddress64 &addr64, uint8_t option, uint8_t *payload, uint8_t payloadLength, uint8_t frameId); 818 | /** 819 | * Creates a unicast Tx64Request with the ACK option and DEFAULT_FRAME_ID 820 | */ 821 | Tx64Request(XBeeAddress64 &addr64, uint8_t *payload, uint8_t payloadLength); 822 | /** 823 | * Creates a default instance of this class. At a minimum you must specify 824 | * a payload, payload length and a destination address before sending this request. 825 | */ 826 | Tx64Request(); 827 | XBeeAddress64& getAddress64(); 828 | void setAddress64(XBeeAddress64& addr64); 829 | // TODO move option to superclass 830 | uint8_t getOption(); 831 | void setOption(uint8_t option); 832 | uint8_t getFrameData(uint8_t pos); 833 | uint8_t getFrameDataLength(); 834 | private: 835 | XBeeAddress64 _addr64; 836 | uint8_t _option; 837 | }; 838 | 839 | #endif 840 | 841 | 842 | #ifdef SERIES_2 843 | 844 | /** 845 | * Represents a Series 2 TX packet that corresponds to Api Id: ZB_TX_REQUEST 846 | * 847 | * Be careful not to send a data array larger than the max packet size of your radio. 848 | * This class does not perform any validation of packet size and there will be no indication 849 | * if the packet is too large, other than you will not get a TX Status response. 850 | * The datasheet says 72 bytes is the maximum for ZNet firmware and ZB Pro firmware provides 851 | * the ATNP command to get the max supported payload size. This command is useful since the 852 | * maximum payload size varies according to certain settings, such as encryption. 853 | * ZB Pro firmware provides a PAYLOAD_TOO_LARGE that is returned if payload size 854 | * exceeds the maximum. 855 | */ 856 | class ZBTxRequest : public PayloadRequest { 857 | public: 858 | /** 859 | * Creates a unicast ZBTxRequest with the ACK option and DEFAULT_FRAME_ID 860 | */ 861 | ZBTxRequest(XBeeAddress64 &addr64, uint8_t *payload, uint8_t payloadLength); 862 | ZBTxRequest(XBeeAddress64 &addr64, uint16_t addr16, uint8_t broadcastRadius, uint8_t option, uint8_t *payload, uint8_t payloadLength, uint8_t frameId); 863 | /** 864 | * Creates a default instance of this class. At a minimum you must specify 865 | * a payload, payload length and a destination address before sending this request. 866 | */ 867 | ZBTxRequest(); 868 | XBeeAddress64& getAddress64(); 869 | uint16_t getAddress16(); 870 | uint8_t getBroadcastRadius(); 871 | uint8_t getOption(); 872 | void setAddress64(XBeeAddress64& addr64); 873 | void setAddress16(uint16_t addr16); 874 | void setBroadcastRadius(uint8_t broadcastRadius); 875 | void setOption(uint8_t option); 876 | protected: 877 | // declare virtual functions 878 | uint8_t getFrameData(uint8_t pos); 879 | uint8_t getFrameDataLength(); 880 | private: 881 | XBeeAddress64 _addr64; 882 | uint16_t _addr16; 883 | uint8_t _broadcastRadius; 884 | uint8_t _option; 885 | }; 886 | 887 | #endif 888 | 889 | /** 890 | * Represents an AT Command TX packet 891 | * The command is used to configure the serially connected XBee radio 892 | */ 893 | class AtCommandRequest : public XBeeRequest { 894 | public: 895 | AtCommandRequest(); 896 | AtCommandRequest(uint8_t *command); 897 | AtCommandRequest(uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength); 898 | uint8_t getFrameData(uint8_t pos); 899 | uint8_t getFrameDataLength(); 900 | uint8_t* getCommand(); 901 | void setCommand(uint8_t* command); 902 | uint8_t* getCommandValue(); 903 | void setCommandValue(uint8_t* command); 904 | uint8_t getCommandValueLength(); 905 | void setCommandValueLength(uint8_t length); 906 | /** 907 | * Clears the optional commandValue and commandValueLength so that a query may be sent 908 | */ 909 | void clearCommandValue(); 910 | //void reset(); 911 | private: 912 | uint8_t *_command; 913 | uint8_t *_commandValue; 914 | uint8_t _commandValueLength; 915 | }; 916 | 917 | /** 918 | * Represents an Remote AT Command TX packet 919 | * The command is used to configure a remote XBee radio 920 | */ 921 | class RemoteAtCommandRequest : public AtCommandRequest { 922 | public: 923 | RemoteAtCommandRequest(); 924 | /** 925 | * Creates a RemoteAtCommandRequest with 16-bit address to set a command. 926 | * 64-bit address defaults to broadcast and applyChanges is true. 927 | */ 928 | RemoteAtCommandRequest(uint16_t remoteAddress16, uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength); 929 | /** 930 | * Creates a RemoteAtCommandRequest with 16-bit address to query a command. 931 | * 64-bit address defaults to broadcast and applyChanges is true. 932 | */ 933 | RemoteAtCommandRequest(uint16_t remoteAddress16, uint8_t *command); 934 | /** 935 | * Creates a RemoteAtCommandRequest with 64-bit address to set a command. 936 | * 16-bit address defaults to broadcast and applyChanges is true. 937 | */ 938 | RemoteAtCommandRequest(XBeeAddress64 &remoteAddress64, uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength); 939 | /** 940 | * Creates a RemoteAtCommandRequest with 16-bit address to query a command. 941 | * 16-bit address defaults to broadcast and applyChanges is true. 942 | */ 943 | RemoteAtCommandRequest(XBeeAddress64 &remoteAddress64, uint8_t *command); 944 | uint16_t getRemoteAddress16(); 945 | void setRemoteAddress16(uint16_t remoteAddress16); 946 | XBeeAddress64& getRemoteAddress64(); 947 | void setRemoteAddress64(XBeeAddress64 &remoteAddress64); 948 | bool getApplyChanges(); 949 | void setApplyChanges(bool applyChanges); 950 | uint8_t getFrameData(uint8_t pos); 951 | uint8_t getFrameDataLength(); 952 | static XBeeAddress64 broadcastAddress64; 953 | // static uint16_t broadcast16Address; 954 | private: 955 | XBeeAddress64 _remoteAddress64; 956 | uint16_t _remoteAddress16; 957 | bool _applyChanges; 958 | }; 959 | 960 | 961 | 962 | #endif //XBee_h 963 | -------------------------------------------------------------------------------- /XBeeMACLayer.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "XBeeMACLayer.h" 3 | 4 | #define XBEE_INIT_WAITING_TIME 3000 // XBee initialization waiting time 5 | 6 | XBeeMACLayer::XBeeMACLayer(){ 7 | } 8 | 9 | // serial high 10 | uint8_t shCmd[] = {'S','H'}; 11 | // serial low 12 | uint8_t slCmd[] = {'S','L'}; 13 | // cca failures 14 | uint8_t ecCmd[] = {'E','C'}; 15 | 16 | uint8_t mac_position; 17 | 18 | AtCommandRequest atRequest = AtCommandRequest(shCmd); 19 | AtCommandResponse atResponse = AtCommandResponse(); 20 | 21 | #define AT_RESPONSE_MAX_ATTEMPTS 5 22 | #define AT_REQUEST_MAX_ATTEMPTS 20 23 | 24 | bool XBeeMACLayer::getResponseMAC(){ 25 | if (atResponse.getValueLength() == 4) { 26 | for (int i = 0; i < atResponse.getValueLength(); i++) { 27 | my_mac.addr[mac_position++] = atResponse.getValue()[i]; 28 | } 29 | return true; 30 | } 31 | return false; 32 | } 33 | 34 | uint16_t cca_retries = 0; 35 | 36 | bool XBeeMACLayer::getResponseCCAFailure(){ 37 | if (atResponse.getValueLength() == 2) { 38 | for (int i = 0; i < atResponse.getValueLength(); i++) { 39 | ((char*)(&cca_retries))[1] = atResponse.getValue()[0]; 40 | ((char*)(&cca_retries))[0] = atResponse.getValue()[1]; 41 | } 42 | return true; 43 | } 44 | return false; 45 | } 46 | 47 | bool XBeeMACLayer::sendAtCommand() { 48 | for(int i=0; iaddr[0]; 131 | ((char*)(&dest))[2] = lladdr_dest->addr[1]; 132 | ((char*)(&dest))[1] = lladdr_dest->addr[2]; 133 | ((char*)(&dest))[0] = lladdr_dest->addr[3]; 134 | destAddr64.setMsb(dest); 135 | ((char*)(&dest))[3] = lladdr_dest->addr[4]; 136 | ((char*)(&dest))[2] = lladdr_dest->addr[5]; 137 | ((char*)(&dest))[1] = lladdr_dest->addr[6]; 138 | ((char*)(&dest))[0] = lladdr_dest->addr[7]; 139 | destAddr64.setLsb(dest); 140 | Tx64Request longReq(destAddr64, data, length); 141 | xbeeRequest = &longReq; 142 | }else{ 143 | ((char*)(&dest))[1] = lladdr_dest->addr[0]; 144 | ((char*)(&dest))[0] = lladdr_dest->addr[1]; 145 | Tx16Request shortReq(dest16, data, length); 146 | xbeeRequest = &shortReq; 147 | } 148 | }else{// lladdr_dest is a broadcast address, we send to broadcast 149 | Tx16Request shortReq(0xFFFF, data, length); 150 | xbeeRequest = &shortReq; 151 | } 152 | send_start_time = millis(); 153 | xbee.send(*xbeeRequest); 154 | 155 | 156 | // after sending a tx request, we expect a status response 157 | // wait up to 5 seconds for the status response 158 | for(int i=0; iaddr[0] = 0; // Copy all-zeroes address to lladdr_dest 208 | lladdr_dest->addr[1] = 0; 209 | //lladdr_dest = NULL; 210 | 211 | }else{ 212 | //get dest address (it is my own) 213 | //lladdr_dest = &my_mac; 214 | lladdr_dest->addr[0] = my_mac.addr[0]; // Copy my_mac address to lladdr_dest 215 | lladdr_dest->addr[1] = my_mac.addr[1]; 216 | } 217 | 218 | lladdr_src->addr[0] = rxResp.getRemoteAddress16() >> 8; 219 | lladdr_src->addr[1] = rxResp.getRemoteAddress16() & 0x00FF; 220 | }else 221 | return false; 222 | } else { 223 | if (UIP_LLADDR_LEN == UIP_802154_LONGADDR_LEN){ 224 | Rx64Response rx64 = Rx64Response(); 225 | xbee.getResponse().getRx64Response(rx64); 226 | memcpy(data, rx64.getData(), rx64.getDataLength()); 227 | *length = rx64.getDataLength(); 228 | 229 | //get destination addresses 230 | if(rx64.getOption() == ZB_BROADCAST_PACKET){ //Then packet was a broadcast.. destination address is 0xFFFF, we use an all-zeroes address to represent broadcast 231 | //lladdr_dest = NULL; 232 | rimeaddr_copy((rimeaddr_t*)lladdr_dest , &rimeaddr_null, UIP_LLADDR_LEN); // Copy an all-zeroes address to lladdr_dest 233 | }else{ 234 | //get dest address (it is my own) 235 | //lladdr_dest = &my_mac; 236 | rimeaddr_copy((rimeaddr_t*)lladdr_dest , (rimeaddr_t*)(&my_mac), UIP_LLADDR_LEN); // Copy my_mac address to lladdr_dest 237 | } 238 | 239 | //get sorce address 240 | for(int i=0; iaddr[i] = rx64.getFrameData()[i]; 242 | } 243 | 244 | }else 245 | return false; 246 | } 247 | 248 | return true; 249 | 250 | } 251 | } else if (xbee.getResponse().isError()) { 252 | uint8_t code = xbee.getResponse().getErrorCode(); 253 | if (code == CHECKSUM_FAILURE){ 254 | }else if (code == PACKET_EXCEEDS_BYTE_ARRAY_LENGTH){ 255 | }else if(code == UNEXPECTED_START_BYTE ){ 256 | } 257 | } 258 | 259 | return false; 260 | } 261 | 262 | const uip_lladdr_t* XBeeMACLayer::getMacAddress(){ 263 | return &my_mac; 264 | } 265 | -------------------------------------------------------------------------------- /XBeeMACLayer.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __XBEEMACLAYER__ 3 | #define __XBEEMACLAYER__ 4 | 5 | #include "XBee.h" 6 | #include "MACLayer.h" 7 | #include "arduino_debug.h" 8 | 9 | class XBeeMACLayer: public MACLayer{ 10 | private: 11 | XBee xbee; 12 | uip_lladdr_t my_mac; 13 | 14 | bool sendAtCommand(); 15 | bool getResponseMAC(); 16 | bool getResponseCCAFailure(); 17 | int getNumberOfTransmissions(); 18 | 19 | public: 20 | XBeeMACLayer(); 21 | bool init(); 22 | MACTransmissionStatus send(const uip_lladdr_t* lladdr_dest, uint8_t* data, uint16_t length, int *number_transmissions); 23 | virtual bool receive(uip_lladdr_t* lladdr_src, uip_lladdr_t* lladdr_dest, uint8_t* data, uint16_t* length); 24 | const uip_lladdr_t* getMacAddress(); 25 | }; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /arduino_debug.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "arduino_debug.h" 3 | 4 | void arduino_debug_init() { 5 | Serial.begin(9600); 6 | } 7 | 8 | void arduino_debug(char* s) { 9 | Serial.println(s); 10 | } 11 | 12 | void arduino_debug_hex(int b) { 13 | Serial.println(b, HEX); 14 | } 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /arduino_debug.h: -------------------------------------------------------------------------------- 1 | #ifndef __ARDUINODEBUG_H__ 2 | #define __ARDUINODEBUG_H__ 3 | 4 | #define ARDUINO_DEBUG 1 5 | 6 | extern "C" { 7 | extern void arduino_debug_init(); 8 | extern void arduino_debug(char* s); 9 | extern void arduino_debug_hex(int b); 10 | } 11 | 12 | #endif /* __ARDUINODEBUG_H__ */ 13 | -------------------------------------------------------------------------------- /clock.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2009 Fredrik Lindberg 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | */ 26 | 27 | /* 28 | * 29 | * adjusted for the Arduino system 30 | * 31 | */ 32 | 33 | #include 34 | 35 | typedef uint32_t clock_time_t; 36 | static clock_time_t global_system_ticks = 0; 37 | 38 | clock_time_t clock_time() 39 | { 40 | return millis();// /32; TODO: WHY THIS??? 41 | } 42 | 43 | 44 | void 45 | clock_init() 46 | { 47 | } 48 | -------------------------------------------------------------------------------- /clock.h: -------------------------------------------------------------------------------- 1 | /** \addtogroup sys 2 | * @{ 3 | */ 4 | 5 | /** 6 | * \defgroup clock Clock library 7 | * 8 | * The clock library is the interface between Contiki and the platform 9 | * specific clock functionality. The clock library performs a single 10 | * function: measuring time. Additionally, the clock library provides 11 | * a macro, CLOCK_SECOND, which corresponds to one second of system 12 | * time. 13 | * 14 | * \note The clock library need in many cases not be used 15 | * directly. Rather, the \ref timer "timer library" or the \ref etimer 16 | * "event timers" should be used. 17 | * 18 | * \sa \ref timer "Timer library" 19 | * \sa \ref etimer "Event timers" 20 | * 21 | * @{ 22 | */ 23 | 24 | /* 25 | * Copyright (c) 2004, Swedish Institute of Computer Science. 26 | * All rights reserved. 27 | * 28 | * Redistribution and use in source and binary forms, with or without 29 | * modification, are permitted provided that the following conditions 30 | * are met: 31 | * 1. Redistributions of source code must retain the above copyright 32 | * notice, this list of conditions and the following disclaimer. 33 | * 2. Redistributions in binary form must reproduce the above copyright 34 | * notice, this list of conditions and the following disclaimer in the 35 | * documentation and/or other materials provided with the distribution. 36 | * 3. Neither the name of the Institute nor the names of its contributors 37 | * may be used to endorse or promote products derived from this software 38 | * without specific prior written permission. 39 | * 40 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 41 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 43 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 44 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 45 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 46 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 48 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 49 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 50 | * SUCH DAMAGE. 51 | * 52 | * This file is part of the Contiki operating system. 53 | * 54 | * Author: Adam Dunkels 55 | * 56 | * $Id: clock.h,v 1.11 2009/01/24 15:20:11 adamdunkels Exp $ 57 | */ 58 | #ifndef __CLOCK_H__ 59 | #define __CLOCK_H__ 60 | 61 | 62 | #include "conf.h" 63 | 64 | #if 0 /* XXX problems with signedness and use in timer_expired(). #if:ed it out for now. */ 65 | /** 66 | * Check if a clock time value is less than another clock time value. 67 | * 68 | * This macro checks if a clock time value is less than another clock 69 | * time value. This macro is needed to correctly handle wrap-around of 70 | * clock time values. 71 | * 72 | */ 73 | #define CLOCK_LT(a, b) ((clock_time_t)((a) - (b)) < ((clock_time_t)(~((clock_time_t)0)) >> 1)) 74 | #endif /* 0 */ 75 | 76 | 77 | /** 78 | * Initialize the clock library. 79 | * 80 | * This function initializes the clock library and should be called 81 | * from the main() function of the system. 82 | * 83 | */ 84 | void clock_init(void); 85 | 86 | /** 87 | * Get the current clock time. 88 | * 89 | * This function returns the current system clock time. 90 | * 91 | * \return The current clock time, measured in system ticks. 92 | */ 93 | clock_time_t clock_time(void); 94 | 95 | void clock_delay(unsigned int); 96 | 97 | /** 98 | * A second, measured in system clock time. 99 | * 100 | * \hideinitializer 101 | */ 102 | #ifdef CLOCK_CONF_SECOND 103 | #define CLOCK_SECOND CLOCK_CONF_SECOND 104 | #else 105 | #define CLOCK_SECOND (clock_time_t)32 106 | #endif 107 | 108 | int clock_fine_max(void); 109 | unsigned short clock_fine(void); 110 | 111 | 112 | #endif /* __CLOCK_H__ */ 113 | 114 | /** @} */ 115 | /** @} */ 116 | -------------------------------------------------------------------------------- /conf.h: -------------------------------------------------------------------------------- 1 | #ifndef __CONF_H__ 2 | #define __CONF_H__ 3 | 4 | #include 5 | #include 6 | 7 | 8 | typedef uint8_t u8_t; 9 | typedef uint16_t u16_t; 10 | typedef uint32_t u32_t; 11 | typedef int32_t s32_t; 12 | 13 | #ifndef UIP_LITTLE_ENDIAN 14 | #define UIP_LITTLE_ENDIAN 3412 15 | #endif /* UIP_LITTLE_ENDIAN */ 16 | #ifndef UIP_BIG_ENDIAN 17 | #define UIP_BIG_ENDIAN 1234 18 | #endif /* UIP_BIG_ENDIAN */ 19 | 20 | #define UIP_CONF_BYTE_ORDER UIP_LITTLE_ENDIAN 21 | 22 | #ifdef UIP_CONF_BYTE_ORDER 23 | #define UIP_BYTE_ORDER (UIP_CONF_BYTE_ORDER) 24 | #else /* UIP_CONF_BYTE_ORDER */ 25 | #define UIP_BYTE_ORDER (UIP_LITTLE_ENDIAN) 26 | #endif /* UIP_CONF_BYTE_ORDER */ 27 | 28 | 29 | /** 30 | * Convert 16-bit quantity from host byte order to network byte order. 31 | * 32 | */ 33 | # if UIP_BYTE_ORDER == UIP_BIG_ENDIAN 34 | # define UIP_HTONS(n) (n) 35 | # define UIP_HTONL(n) (n) 36 | # else /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */ 37 | # define UIP_HTONS(n) (u16_t)((((u16_t) (n)) << 8) | (((u16_t) (n)) >> 8)) 38 | # define UIP_HTONL(n) (((u32_t)UIP_HTONS(n) << 16) | UIP_HTONS((u32_t)(n) >> 16)) 39 | # endif /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */ 40 | 41 | /** 42 | * Convert 16-bit quantity from network byte order to host byte order. 43 | */ 44 | #ifndef UIP_NTOHS 45 | #define UIP_NTOHS UIP_HTONS 46 | #endif 47 | 48 | 49 | #define UIP_CONF_IPV6 1 50 | 51 | #define UIP_CONF_UDP 1 52 | #define UIP_CONF_UDP_CONNS 1 53 | 54 | #define UIP_CONF_BYTE_ORDER UIP_LITTLE_ENDIAN 55 | #define UIP_CONF_BUFFER_SIZE 420 56 | #define UIP_CONF_TCP 0 57 | #define UIP_CONF_MAX_CONNECTIONS 3 58 | #define UIP_CONF_MAX_LISTENPORTS 1 59 | #define UIP_CONF_TCP_SPLIT 1 60 | #define UIP_CONF_LOGGING 0 61 | #define UIP_CONF_UDP_CHECKSUMS 1 62 | 63 | #if UIP_CONF_IPV6 64 | #define UIP_CONF_IPV6_CHECKS 1 65 | #define UIP_CONF_IPV6_QUEUE_PKT 0 66 | #define UIP_CONF_IPV6_REASSEMBLY 0 67 | #define UIP_CONF_NETIF_MAX_ADDRESSES 10 68 | #define UIP_CONF_ND6_MAX_PREFIXES 2 69 | #define UIP_CONF_ND6_MAX_NEIGHBORS 3 70 | #define UIP_CONF_ND6_MAX_DEFROUTERS 1 71 | #define UIP_CONF_ICMP6 1 72 | #endif /* UIP_CONF_ICMP6 */ 73 | 74 | #define SICSLOWPAN_CONF_FRAG 0 75 | 76 | #define SICSLOWPAN_CONF_COMPRESSION_IPV6 0 77 | #define SICSLOWPAN_CONF_COMPRESSION_HC1 1 78 | #define SICSLOWPAN_CONF_COMPRESSION_HC06 2 79 | #define SICSLOWPAN_CONF_COMPRESSION 2//SICSLOWPAN_COMPRESSION_HC06 80 | 81 | /* Specify a minimum packet size for 6lowpan compression to be 82 | enabled. This is needed for ContikiMAC, which needs packets to be 83 | larger than a specified size, if no ContikiMAC header should be 84 | used. */ 85 | #define SICSLOWPAN_CONF_COMPRESSION_THRESHOLD 64 // 0: Always Compress a Packet Using SICSLOWPAN 86 | 87 | #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 1 88 | 89 | #define RPL_CONF_DAO_ACK 1 90 | 91 | #define UIP_PROTO_ICMP 1 92 | #define UIP_PROTO_TCP 6 93 | #define UIP_PROTO_UDP 17 94 | #define UIP_PROTO_ICMP6 58 95 | 96 | #define UIP_IPH_LEN 40 /* Size of IPv6 header */ 97 | #define UIP_FRAGH_LEN 8 98 | 99 | #define UIP_UDPH_LEN 8 /* Size of UDP header */ 100 | #define UIP_ICMPH_LEN 4 /* Size of ICMP header */ 101 | #define UIP_IPUDPH_LEN (UIP_UDPH_LEN + UIP_IPH_LEN) /* Size of IP + UDP header */ 102 | #define UIP_TCPIP_HLEN UIP_IPTCPH_LEN 103 | #define UIP_IPICMPH_LEN (UIP_IPH_LEN + UIP_ICMPH_LEN) /* size of ICMP + IP header */ 104 | 105 | #define uip_l3_hdr_len (UIP_IPH_LEN) 106 | #define uip_l3_icmp_hdr_len (UIP_IPH_LEN + UIP_ICMPH_LEN) 107 | 108 | typedef union uip_ip6addr_t { 109 | u8_t u8[16]; /* Initializer, must come first!!! */ 110 | u16_t u16[8]; 111 | } uip_ip6addr_t; 112 | 113 | typedef uip_ip6addr_t uip_ipaddr_t; 114 | 115 | /* 116 | * In IPv6 the length of the L3 headers before the transport header is 117 | * not fixed, due to the possibility to include extension option headers 118 | * after the IP header. hence we split here L3 and L4 headers 119 | */ 120 | /* The IP header */ 121 | struct uip_ip_hdr { 122 | /* IPV6 header */ 123 | u8_t vtc; 124 | u8_t tcflow; 125 | u16_t flow; 126 | u8_t len[2]; 127 | u8_t proto, ttl; 128 | uip_ip6addr_t srcipaddr, destipaddr; 129 | }; 130 | 131 | 132 | /* The ICMP headers. */ 133 | struct uip_icmp_hdr { 134 | u8_t type, icode; 135 | u16_t icmpchksum; 136 | }; 137 | 138 | 139 | /* The UDP headers. */ 140 | struct uip_udp_hdr { 141 | u16_t srcport; 142 | u16_t destport; 143 | u16_t udplen; 144 | u16_t udpchksum; 145 | }; 146 | 147 | typedef uint32_t clock_time_t; 148 | #define CLOCK_CONF_SECOND 32 149 | 150 | #define UIP_802154_LONGADDR_LEN 8 151 | #define UIP_802154_SHORTADDR_LEN 2 152 | 153 | #define UIP_LLADDR_LEN UIP_802154_LONGADDR_LEN 154 | 155 | typedef struct uip_802154_longaddr { 156 | u8_t addr[UIP_LLADDR_LEN]; 157 | } uip_802154_longaddr; 158 | 159 | typedef uip_802154_longaddr uip_lladdr_t; 160 | 161 | #define UIP_LLH_LEN 0 //no additional Link Layer headers 162 | 163 | #define UIP_LLIPH_LEN (UIP_LLH_LEN + UIP_IPH_LEN) /* size of L2 164 | + IP header */ 165 | 166 | #define UIP_BUFSIZE 160 // The size of the uIP packet buffer. 167 | #define UIP_UDP_PAYLOAD_MAX_BUFSIZE (UIP_BUFSIZE - UIP_IPUDPH_LEN) // The max size of the UDP datagram payload buffer. ( 160 - 48 ) 168 | 169 | #define CHAR_BIT 8 170 | 171 | #endif 172 | -------------------------------------------------------------------------------- /examples/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imt-atlantique/Arduino-pIPv6Stack/07a05a8be4c7b9f58714d8e410bfba70f5f62e0c/examples/.DS_Store -------------------------------------------------------------------------------- /examples/CoAP/CoAPSendPeriodic/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imt-atlantique/Arduino-pIPv6Stack/07a05a8be4c7b9f58714d8e410bfba70f5f62e0c/examples/CoAP/CoAPSendPeriodic/.DS_Store -------------------------------------------------------------------------------- /examples/CoAP/CoAPSendPeriodic/CoAPSendPeriodic.h: -------------------------------------------------------------------------------- 1 | // Only modify this file to include 2 | // - function definitions (prototypes) 3 | // - include files 4 | // - extern variable definitions 5 | // In the appropriate section 6 | 7 | #ifndef UDPPERIODICSEND_H_ 8 | #define UDPPERIODICSEND_H_ 9 | #include "Arduino.h" 10 | //add your includes for the project picoIPv6 here 11 | 12 | 13 | //end of add your includes here 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | void loop(); 18 | void setup(); 19 | #ifdef __cplusplus 20 | } // extern "C" 21 | #endif 22 | 23 | //add your function definitions for the project picoIPv6 here 24 | 25 | 26 | 27 | 28 | //Do not add code below this line 29 | #endif /* UDPPERIODICSEND_H_ */ 30 | -------------------------------------------------------------------------------- /examples/CoAP/CoAPSendPeriodic/CoAPSendPeriodic.pde: -------------------------------------------------------------------------------- 1 | // Do not remove the include below 2 | #include "CoapSendPeriodic.h" 3 | 4 | #include "XBeeMACLayer.h" 5 | #include "PicoIPv6Connection.h" 6 | #include "CoAPEngine.h" 7 | 8 | 9 | XBeeMACLayer macLayer; // XBee MAC Layer 10 | PicoIPv6Connection picoIPv6Connection; // PicoIPv6 Connection 11 | u8_t picoip_buffer[UIP_BUFSIZE]; // Defines the picoIPv6 packet buffer. 12 | CoAPEngine coap; // CoAPEngine-alpha. Sends CoAP PUT Non-Confirmable messages with URI, Query, optional second Query, and payload. 13 | 14 | // Definitions for the Data/CoAP Sending Loop 15 | #define DATA_SEND_PERIOD 5000 // loop period (miliseconds) 16 | struct timer data_send_timer; //loop timer 17 | 18 | 19 | 20 | 21 | void setup() { 22 | 23 | /*Serial.begin(9600);*/ // Disabled for more RAM 24 | 25 | // Start the MACLayer and PicoIPv6 Connection: 26 | // 1) Initialization of the MAC Layer. 27 | if ( !macLayer.init() ) { 28 | while (1){}; // Cannot initialize MAC Layer and will not continue. 29 | } 30 | 31 | // 2) Initialization of the picoIPv6 Connection. 32 | picoIPv6Connection.init(&macLayer, picoip_buffer); // Definition of an object of the class PicoIPv6Connection 33 | 34 | // 3) Initialize the CoAP Engine with a picoIPv6 connection. 35 | coap.setPicoIPv6Connection(picoIPv6Connection); 36 | 37 | // 4) Set up of the timer for the Data/CoAP Sending Loop. 38 | timer_set(&data_send_timer, DATA_SEND_PERIOD); 39 | 40 | } 41 | 42 | 43 | // Definitions for the CoAP Message to be sent 44 | static uip_ipaddr_t coap_server_addr = {0xbb, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; // Remote server IPv6 Address. Ex.: [bbbb::3] 45 | 46 | String coap_uri = "uri_test"; // CoAP Option: URI 47 | String coap_query = "apikey=fd205ed589";// CoAP Option: Query. Emoncms: "apikey=" 48 | String coap_query_opt = "node=1"; // CoAP Option: Query (Optional) 49 | String coap_payload_string = " "; // CoAP Payload. 50 | 51 | static uint16_t msg_counter = 0; // number of messages sent counter. 52 | 53 | void loop() { 54 | 55 | if (picoIPv6Connection.isConnected()){ 56 | // There is a connection at picoIPv6 level. 57 | if (timer_expired(&data_send_timer)){ 58 | // Send timer has expired. We send an CoAP Message. 59 | // 1) Obtain the data to be sent and set the proper CoAP URI. 60 | coap_uri = "msg_counter"; 61 | ++msg_counter; 62 | coap_payload_string = String(msg_counter); 63 | 64 | // 2) Send the CoAP Message. 65 | coap.sendCoAPpacket(coap_server_addr, coap_uri , coap_query , coap_query_opt , coap_payload_string); 66 | 67 | 68 | // Repeat steps 1 and 2 for any data that wants to be sent. 69 | 70 | 71 | // Send_Loop_END) Restart send timer. 72 | timer_restart(&data_send_timer); 73 | 74 | }//else{} // Send timer has NOT expired. 75 | } 76 | else{// There is NOT a connection at picoIPv6 level. 77 | picoIPv6Connection.connect(); // We initialize a picoIPv6 connection. 78 | delay(200); // Add a delay time to establish a picoIPv6 connection. 79 | } 80 | 81 | } 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | /* This function is automatically invoked when we call PicoIPv6Connection->receive() and there is new UDP Data. 90 | * * udp_data: contains new UDP datagram payload. 91 | * * length: contains new UDP datagram payload lenght. 92 | * 93 | * [ At lower level it is actually called from PicoIPv6State.udp_input() ] 94 | * [ only when the PicoIPv6State subclass is ConnectedState ] 95 | * */ 96 | void udp_input_callback(uint8_t* udp_data, uint16_t length) {} 97 | -------------------------------------------------------------------------------- /examples/Old/picoIPv6UDPEco.h: -------------------------------------------------------------------------------- 1 | // Only modify this file to include 2 | // - function definitions (prototypes) 3 | // - include files 4 | // - extern variable definitions 5 | // In the appropriate section 6 | 7 | #ifndef PICOIPV6UDPECO_H_ 8 | #define PICOIPV6UDPECO_H_ 9 | #include "Arduino.h" 10 | //add your includes for the project picoIPv6 here 11 | 12 | 13 | //end of add your includes here 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | void loop(); 18 | void setup(); 19 | #ifdef __cplusplus 20 | } // extern "C" 21 | #endif 22 | 23 | //add your function definitions for the project picoIPv6 here 24 | 25 | 26 | 27 | 28 | //Do not add code below this line 29 | #endif /* PICOIPV6UDPRXTX_H_ */ 30 | -------------------------------------------------------------------------------- /examples/Old/picoIPv6UDPEco.inojo: -------------------------------------------------------------------------------- 1 | // Do not remove the include below 2 | #include "picoIPv6UDPEco.h" 3 | 4 | #include 5 | #include "XBeeInitHelper.h" 6 | #include "picoIPv6Connection.h" 7 | 8 | 9 | #define DEBUG 0 10 | 11 | int mem(){ 12 | uint8_t * heapptr, * stackptr; 13 | stackptr = (uint8_t *)malloc(4); 14 | heapptr = stackptr; 15 | free(stackptr); 16 | stackptr = (uint8_t *)(SP); 17 | return stackptr - heapptr; 18 | } 19 | 20 | /*-------------------------------------------------------------------------------------*/ 21 | 22 | 23 | //************* XBee ************* 24 | XBeeInitHelper xbeeHelper; 25 | 26 | //***** PicoIPv6 Connection ***** 27 | PicoIPv6Connection* picoConnection; 28 | 29 | 30 | u8_t picoip_buffer[UIP_BUFSIZE]; 31 | #define UDP_CLIENT_PORT 8765 32 | #define UDP_SEND_TIME 10000 33 | struct timer udp_msg_timer; 34 | 35 | void setup() { 36 | Serial.begin(9600); 37 | delay(1000); 38 | 39 | /* 1) Initialization of the XBee Module */ 40 | if (!xbeeHelper.init()){ 41 | PRINTF("CANNOT INITIALIZE XBEE MODULE.. CANNOT CONTINUE"); 42 | while (1){}; 43 | } 44 | 45 | /* 2) Initialization of the picoIPv6 Connection */ 46 | picoConnection = new PicoIPv6Connection(&(xbeeHelper.getXbee()), &(xbeeHelper.getMyMac()), picoip_buffer); 47 | 48 | //Send one message to broadcast 49 | //connection->udp_send(connection->getLinkLocalMcastIPAddress(), UDP_CLIENT_PORT, UDP_CLIENT_PORT, "HELLO", 5); // TODO: can sniff packet but not sure if arriver router 50 | 51 | PRINTF("MEMORY RAM LEFT: "); 52 | Serial.println(mem(), DEC); 53 | delay(100); 54 | 55 | // 3) Set up the timer for sending UDP Messages 56 | timer_set(&udp_msg_timer, UDP_SEND_TIME); 57 | } 58 | 59 | 60 | char msg_buf[160]; 61 | uint16_t udp_msg_length; 62 | static uint16_t msg_counter = 0; 63 | static uip_ipaddr_t remote_client_ipaddr = {0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; 64 | 65 | 66 | void loop() { 67 | 68 | Serial.println(mem()); 69 | 70 | if (picoConnection->isConnected()){ 71 | PRINTF("CONNECTED!"); 72 | delay(100); 73 | 74 | 75 | if (timer_expired(&udp_msg_timer)){ 76 | PRINTF("UDP TIMER EXPIRED! SEND.."); 77 | Serial.println("SND"); 78 | ++msg_counter; 79 | sprintf(msg_buf, "msg UDP MSG-COAP:%hu \n", msg_counter); // %hu h:short u:unsigned 80 | picoConnection->udp_send(&remote_client_ipaddr, UDP_CLIENT_PORT, UDP_CLIENT_PORT, msg_buf, strlen(msg_buf)); 81 | timer_restart(&udp_msg_timer); 82 | }else{ 83 | //PRINTF("UDP TIMER NOT EXPIRED."); 84 | } 85 | 86 | 87 | if (picoConnection->receive()){//We answer the message we have just reverted in the msg_buffer 88 | PRINTF("RECEIVED!"); 89 | if (picoConnection->getLastReceivedPacketType() == UDP){ 90 | PRINTF(""); 91 | PRINTF(""); 92 | PRINTF("IT IS UDP MESSAGE!!"); 93 | picoConnection->udp_send(picoConnection->getLastSenderIPAddress(), UDP_CLIENT_PORT, UDP_CLIENT_PORT, msg_buf, udp_msg_length); 94 | delay(100); 95 | msg_buf[udp_msg_length] = 0; //in order to print it for debugging, we finish the string with a 0 96 | PRINTF(""); 97 | PRINTF("MSG received: "); 98 | PRINTF(msg_buf); 99 | PRINTF(""); 100 | PRINTF(""); 101 | } 102 | } 103 | //delay(UDP_SEND_TIME); 104 | }else{ 105 | picoConnection->connect(); 106 | delay(200); 107 | if (picoConnection->isConnected()){//We have just connected for the first time or from a disconnection 108 | //timer_restart(&udp_msg_timer); 109 | //PRINTF("NEW UDP SENDING TIMER SET"); 110 | PRINTF("CONNECTED!"); 111 | } 112 | } 113 | delay(100); 114 | } 115 | 116 | 117 | /* This function is called when we receive UDP Data 118 | * on function PicoIPv6State.udp_input() , 119 | * but is only used in ConnectedState subclass 120 | * */ 121 | void udp_input_callback(uint8_t* udp_data, uint16_t length){ 122 | uint8_t i; 123 | 124 | PRINTF(""); 125 | PRINTF(""); 126 | PRINTF("DATA rcv: "); 127 | for (i=0; i < length; ++i){ 128 | PRINTHEX((char)udp_data[i]); 129 | } 130 | PRINTF(""); 131 | PRINTF(""); 132 | 133 | for(i=0; i 5 | #include "XBeeInitHelper.h" 6 | #include "PicoIPv6Connection.h" 7 | //#include 8 | 9 | 10 | #define DEBUG 0 11 | 12 | int mem(){ 13 | uint8_t * heapptr, * stackptr; 14 | stackptr = (uint8_t *)malloc(4); 15 | heapptr = stackptr; 16 | free(stackptr); 17 | stackptr = (uint8_t *)(SP); 18 | return stackptr - heapptr; 19 | } 20 | 21 | /*-------------------------------------------------------------------------------------*/ 22 | 23 | 24 | //************* XBee ************* 25 | XBeeInitHelper xbeeHelper; 26 | 27 | //***** PicoIPv6 Connection ***** 28 | PicoIPv6Connection* connection; 29 | 30 | 31 | u8_t buf[UIP_BUFSIZE]; 32 | #define UDP_CLIENT_PORT 8765 33 | //static uip_ipaddr_t remote_client_ipaddr = {0x20, 0x01, 0x06, 0x60, 0x73, 0x01, 0x00, 0x51, 0x62, 0x33, 0x4b, 0xff, 0xfe, 0x15, 0xa6, 0x0f};/*{0xbb, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};*//*{0xAA, 0xAA, 0, 0, 0, 0, 0, 0, 0x02, 0x12, 0x74, 0x00, 0x13, 0xEA, 0x45, 0xD1};*/ 34 | //static uip_lladdr_t my_mac = {0x00, 0x13, 0xA2, 0x00, 0x40, 0x7B, 0x2F, 0x57}; 35 | #define UDP_SEND_TIME 10000 36 | struct timer udp_msg_timer; 37 | 38 | void setup() { 39 | Serial.begin(9600); 40 | delay(1000); 41 | 42 | if (!xbeeHelper.init()){ 43 | PRINTF("CANNOT INITIALIZE XBEE MODULE.. CANNOT CONTINUE"); 44 | while (1){}; 45 | } 46 | 47 | connection = new PicoIPv6Connection(&(xbeeHelper.getXbee()), &(xbeeHelper.getMyMac()), buf); 48 | 49 | //Send one message to broadcast 50 | connection->udp_send(connection->getLinkLocalMcastIPAddress(), UDP_CLIENT_PORT, UDP_CLIENT_PORT, "HELLO", 5); 51 | 52 | 53 | PRINTF("MEMORY RAM LEFT: "); 54 | Serial.println(mem(), DEC); 55 | delay(100); 56 | 57 | timer_set(&udp_msg_timer, UDP_SEND_TIME); 58 | } 59 | 60 | 61 | char msg_buf[160]; 62 | uint16_t msg_length; 63 | 64 | /* This function is called when we receive UDP Data 65 | * on function PicoIPv6State.udp_input() , 66 | * but only used in ConnectedState subclass 67 | * */ 68 | 69 | void udp_input_callback(uint8_t* udp_data, uint16_t length){ 70 | uint8_t i; 71 | 72 | PRINTF(""); 73 | PRINTF(""); 74 | PRINTF("DATA rcv: "); 75 | for (i=0; i < length; ++i){ 76 | PRINTHEX((char)udp_data[i]); 77 | } 78 | PRINTF(""); 79 | PRINTF(""); 80 | 81 | for(i=0; iisConnected()){ 102 | PRINTF("CONNECTED!"); 103 | delay(100); 104 | 105 | /* 106 | if (timer_expired(&udp_msg_timer)){ 107 | PRINTF("UDP TIMER EXPIRED! SEND.."); 108 | ++msg_counter; 109 | sprintf(msg_buf, "msg UDP MSG", msg_counter); 110 | connection->udp_send(&remote_client_ipaddr, UDP_CLIENT_PORT, UDP_CLIENT_PORT, msg_buf, strlen(msg_buf)); 111 | timer_restart(&udp_msg_timer); 112 | }else{ 113 | //PRINTF("UDP TIMER NOT EXPIRED."); 114 | } 115 | */ 116 | 117 | 118 | if (connection->receive()){//We answer the message we have just reverted in the msg_buffer 119 | PRINTF("RECEIVED!"); 120 | if (connection->getLastReceivedPacketType() == UDP){ 121 | PRINTF(""); 122 | PRINTF(""); 123 | PRINTF("IT IS UDP MESSAGE!!"); 124 | connection->udp_send(connection->getLastSenderIPAddress(), UDP_CLIENT_PORT, UDP_CLIENT_PORT, msg_buf, msg_length); 125 | delay(100); 126 | msg_buf[msg_length] = 0; //in order to print it for debugging, we finish the string with a 0 127 | PRINTF(""); 128 | PRINTF("MSG received: "); 129 | PRINTF(msg_buf); 130 | PRINTF(""); 131 | PRINTF(""); 132 | } 133 | } 134 | 135 | //delay(UDP_SEND_TIME); 136 | }else{ 137 | connection->connect(); 138 | delay(200); 139 | if (connection->isConnected()){//We have just connected for the first time or from a disconnection 140 | //timer_restart(&udp_msg_timer); 141 | //PRINTF("NEW UDP SENDING TIMER SET"); 142 | PRINTF("CONNECTED!"); 143 | } 144 | } 145 | delay(100); 146 | } 147 | 148 | -------------------------------------------------------------------------------- /examples/Old/picoIPv6UDPReceive.h: -------------------------------------------------------------------------------- 1 | // Only modify this file to include 2 | // - function definitions (prototypes) 3 | // - include files 4 | // - extern variable definitions 5 | // In the appropriate section 6 | 7 | #ifndef picoIPv6UDPReceive_H_ 8 | #define picoIPv6UDPReceive_H_ 9 | #include "Arduino.h" 10 | //add your includes for the project picoIPv6 here 11 | 12 | 13 | //end of add your includes here 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | void loop(); 18 | void setup(); 19 | #ifdef __cplusplus 20 | } // extern "C" 21 | #endif 22 | 23 | //add your function definitions for the project picoIPv6 here 24 | 25 | 26 | 27 | 28 | //Do not add code below this line 29 | #endif /* picoIPv6UDPReceive_H_ */ 30 | -------------------------------------------------------------------------------- /examples/Old/picoIPv6UDPReceive.inojo: -------------------------------------------------------------------------------- 1 | // Do not remove the include below 2 | #include "picoIPv6UDPReceive.h" 3 | 4 | #include 5 | #include "picoIPv6Connection.h" 6 | 7 | 8 | #define DEBUG 0 9 | 10 | int mem(){ 11 | uint8_t * heapptr, * stackptr; 12 | stackptr = (uint8_t *)malloc(4); 13 | heapptr = stackptr; 14 | free(stackptr); 15 | stackptr = (uint8_t *)(SP); 16 | return stackptr - heapptr; 17 | } 18 | 19 | u8_t buf[UIP_BUFSIZE]; 20 | 21 | /*-------------------------------------------------------------------------------------*/ 22 | 23 | //#define UDP_SEND_TIME 10000 24 | 25 | #define UDP_CLIENT_PORT 8765 26 | 27 | //static uip_ipaddr_t remote_client_ipaddr = {0x20, 0x01, 0x06, 0x60, 0x73, 0x01, 0x00, 0x51, 0x62, 0x33, 0x4b, 0xff, 0xfe, 0x15, 0xa6, 0x0f};/*{0xbb, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};*//*{0xAA, 0xAA, 0, 0, 0, 0, 0, 0, 0x02, 0x12, 0x74, 0x00, 0x13, 0xEA, 0x45, 0xD1};*/ 28 | 29 | //static uip_lladdr_t my_mac = {0x00, 0x13, 0xA2, 0x00, 0x40, 0x7B, 0x2F, 0x57}; 30 | 31 | 32 | // ****** XBee CODE 33 | XBee xbee; 34 | 35 | // serial high 36 | uint8_t shCmd[] = {'S','H'}; 37 | // serial low 38 | uint8_t slCmd[] = {'S','L'}; 39 | 40 | AtCommandRequest atRequest = AtCommandRequest(shCmd); 41 | AtCommandResponse atResponse = AtCommandResponse(); 42 | 43 | uint8_t mac_position = 0; 44 | 45 | static uip_lladdr_t my_mac; 46 | 47 | #define AT_RESPONSE_MAX_ATTEMPTS 5 48 | #define AT_REQUEST_MAX_ATTEMPTS 20 49 | 50 | // ****** XBee CODE 51 | 52 | 53 | bool getResponseMAC(){ 54 | if (atResponse.getValueLength() == 4) { 55 | for (int i = 0; i < atResponse.getValueLength(); i++) { 56 | my_mac.addr[mac_position++] = atResponse.getValue()[i]; 57 | } 58 | return true; 59 | } 60 | return false; 61 | } 62 | 63 | bool sendAtCommand() { 64 | PRINTF("FUN sendAtCommand"); 65 | for(int i=0; iudp_send(connection->getLinkLocalMcastIPAddress(), UDP_CLIENT_PORT, UDP_CLIENT_PORT, "HELLO", 5); 149 | 150 | Serial.println(); 151 | Serial.println(); 152 | PRINTF("MEMORY RAM LEFT: "); 153 | Serial.println(mem(), DEC); 154 | Serial.println(); 155 | delay(100); 156 | 157 | timer_set(&udp_msg_timer, UDP_SEND_TIME); 158 | } 159 | 160 | char msg_buf[160]; 161 | 162 | uint16_t msg_length; 163 | 164 | void udp_input_callback(uint8_t* udp_data, uint16_t length){ 165 | uint8_t i; 166 | 167 | PRINTF(""); 168 | PRINTF(""); 169 | PRINTF("DATA rcv: "); 170 | for (i=0; i < length; ++i){ 171 | PRINTHEX((char)udp_data[i]); 172 | } 173 | PRINTF(""); 174 | PRINTF(""); 175 | 176 | for(i=0; iisConnected()){ 194 | PRINTF("CONNECTED!"); 195 | delay(100); 196 | 197 | /* 198 | if (timer_expired(&udp_msg_timer)){ 199 | PRINTF("UDP TIMER EXPIRED! SEND.."); 200 | ++msg_counter; 201 | sprintf(msg_buf, "msg UDP MSG", msg_counter); 202 | connection->udp_send(&remote_client_ipaddr, UDP_CLIENT_PORT, UDP_CLIENT_PORT, msg_buf, strlen(msg_buf)); 203 | timer_restart(&udp_msg_timer); 204 | }else{ 205 | //PRINTF("UDP TIMER NOT EXPIRED."); 206 | } 207 | */ 208 | 209 | 210 | if (connection->receive()){//We answer the message we have just reverted in the msg_buffer 211 | PRINTF("RECEIVED!"); 212 | if (connection->getLastReceivedPacketType() == UDP){ 213 | PRINTF(""); 214 | PRINTF(""); 215 | PRINTF("IT IS UDP MESSAGE!!"); 216 | connection->udp_send(connection->getLastSenderIPAddress(), UDP_CLIENT_PORT, UDP_CLIENT_PORT, msg_buf, msg_length); 217 | delay(100); 218 | msg_buf[msg_length] = 0; //in order to print it for debugging, we finish the string with a 0 219 | PRINTF(""); 220 | PRINTF("MSG received: "); 221 | PRINTF(msg_buf); 222 | PRINTF(""); 223 | PRINTF(""); 224 | } 225 | } 226 | 227 | //delay(UDP_SEND_TIME); 228 | }else{ 229 | connection->connect(); 230 | delay(200); 231 | if (connection->isConnected()){//We have just connected for the first time or from a disconnection 232 | //timer_restart(&udp_msg_timer); 233 | //PRINTF("NEW UDP SENDING TIMER SET"); 234 | PRINTF("CONNECTED!"); 235 | } 236 | } 237 | delay(100); 238 | } 239 | 240 | -------------------------------------------------------------------------------- /examples/UDP/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imt-atlantique/Arduino-pIPv6Stack/07a05a8be4c7b9f58714d8e410bfba70f5f62e0c/examples/UDP/.DS_Store -------------------------------------------------------------------------------- /examples/UDP/UDPReceiveAndSendEcho/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imt-atlantique/Arduino-pIPv6Stack/07a05a8be4c7b9f58714d8e410bfba70f5f62e0c/examples/UDP/UDPReceiveAndSendEcho/.DS_Store -------------------------------------------------------------------------------- /examples/UDP/UDPReceiveAndSendEcho/UDPReceiveAndSendEcho.h: -------------------------------------------------------------------------------- 1 | // Only modify this file to include 2 | // - function definitions (prototypes) 3 | // - include files 4 | // - extern variable definitions 5 | // In the appropriate section 6 | 7 | #ifndef PICOIPV6UDPECO_H_ 8 | #define PICOIPV6UDPECO_H_ 9 | #include "Arduino.h" 10 | //add your includes for the project picoIPv6 here 11 | 12 | 13 | //end of add your includes here 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | void loop(); 18 | void setup(); 19 | #ifdef __cplusplus 20 | } // extern "C" 21 | #endif 22 | 23 | //add your function definitions for the project picoIPv6 here 24 | 25 | 26 | 27 | 28 | //Do not add code below this line 29 | #endif /* PICOIPV6UDPRXTX_H_ */ 30 | -------------------------------------------------------------------------------- /examples/UDP/UDPReceiveAndSendEcho/UDPReceiveAndSendEcho.pde: -------------------------------------------------------------------------------- 1 | // Do not remove the include below 2 | #include "UDPReceiveAndSendEcho.h" 3 | 4 | #include "XBeeMACLayer.h" 5 | #include "PicoIPv6Connection.h" 6 | 7 | 8 | XBeeMACLayer macLayer; // XBee MAC Layer 9 | PicoIPv6Connection* picoIPv6Connection; // PicoIPv6 Connection 10 | u8_t picoip_buffer[UIP_BUFSIZE]; // Defines the picoIPv6 packet buffer. 11 | 12 | void setup() { 13 | 14 | Serial.begin(9600); 15 | 16 | // Start the MACLayer and PicoIPv6 Connection: 17 | // 1) Initialization of the MAC Layer. 18 | if ( !macLayer.init() ) { 19 | while (1){}; // Cannot initialize MAC Layer and will not continue. 20 | } 21 | 22 | // 2) Initialization of the picoIPv6 Connection. 23 | picoIPv6Connection = new PicoIPv6Connection(&macLayer, picoip_buffer); // Definition of an object of the class PicoIPv6Connection 24 | 25 | } 26 | 27 | 28 | // Definitions for the UDP Message to be sent 29 | const u16_t udp_source_port = 8765; // UDP Source Port Number. 30 | u16_t udp_destination_port = 8765; // UDP Destination Port Number. 31 | uip_ipaddr_t* ip_destination_address = 0; // IPv6 Destination Address 32 | 33 | // Definition of UDP message payload buffer and messages counter. 34 | char udp_msg_buf[UIP_UDP_PAYLOAD_MAX_BUFSIZE]; // UDP payload buffer. 35 | u16_t udp_msg_length; // UDP payload size 36 | char udp_msg_aux[UIP_UDP_PAYLOAD_MAX_BUFSIZE]; // Auxiliar UDP payload buffer 37 | 38 | void loop() { 39 | 40 | if (picoIPv6Connection->isConnected()){ 41 | // There is a connection at picoIPv6 level. 42 | 43 | if (picoIPv6Connection->receive()){//We answer the message we have just reverted in the msg_buffer 44 | 45 | if (picoIPv6Connection->getLastReceivedPacketType() == UDP){ 46 | 47 | // 1) Get UDP received packet Payload Length and Payload 48 | // udp_msg_length = picoIPv6Connection->getUdpDataLength(); // Method also available to get UDP Payload Lenght 49 | udp_msg_length = picoIPv6Connection->getUdpData(udp_msg_aux); // Copies UDP Payload into udp_msg_aux and returns payload lenght. 50 | udp_msg_aux[udp_msg_length] = '\0'; // We NULL Terminate the string to make possible to sprintf(,"%s",) correctly detect the end of the string. 51 | 52 | // 2) Create new UDP Payload 53 | // We generate udp_msg_buf indicating received payload lenght and sending/echoing the payload again. 54 | sprintf(udp_msg_buf, "ACK.PayLen.%hu:%s\n", udp_msg_length, udp_msg_aux); // Generate the payload 55 | udp_msg_length = strlen(udp_msg_buf); // Get new payload lenght 56 | 57 | // 3) Send UDP message to Last Sender (IP address and UDP Port) 58 | ip_destination_address = picoIPv6Connection->getLastSenderIPAddress(); // Get Last Sender's IP Address. 59 | udp_destination_port = picoIPv6Connection->getLastSenderUDPSourcePort(); // Get Last Sender's UDP Source Port. 60 | picoIPv6Connection->udp_send(ip_destination_address , udp_source_port, udp_destination_port, udp_msg_buf, udp_msg_length ); // Send UDP message. 61 | 62 | delay(100); 63 | 64 | } 65 | } 66 | 67 | }else{ 68 | // There is NOT a connection at picoIPv6 level. 69 | picoIPv6Connection->connect(); // We initialize a picoIPv6 connection. 70 | delay(200); // Add a delay time to establish a picoIPv6 connection. 71 | } 72 | 73 | } 74 | 75 | 76 | /* This function is automatically invoked when we call PicoIPv6Connection->receive() and there is new UDP Data. 77 | * * udp_data: contains new UDP datagram payload. 78 | * * length: contains new UDP datagram payload lenght. 79 | * 80 | * [ At lower level it is actually called from PicoIPv6State.udp_input() ] 81 | * [ only when the PicoIPv6State subclass is ConnectedState ] 82 | * */ 83 | void udp_input_callback(uint8_t* udp_data, uint16_t length){} 84 | 85 | -------------------------------------------------------------------------------- /examples/UDP/UDPReceiveCallbackSendEchoInverted/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imt-atlantique/Arduino-pIPv6Stack/07a05a8be4c7b9f58714d8e410bfba70f5f62e0c/examples/UDP/UDPReceiveCallbackSendEchoInverted/.DS_Store -------------------------------------------------------------------------------- /examples/UDP/UDPReceiveCallbackSendEchoInverted/UDPReceiveCallbackSendEchoInverted.h: -------------------------------------------------------------------------------- 1 | // Only modify this file to include 2 | // - function definitions (prototypes) 3 | // - include files 4 | // - extern variable definitions 5 | // In the appropriate section 6 | 7 | #ifndef PICOIPV6UDPECO_H_ 8 | #define PICOIPV6UDPECO_H_ 9 | #include "Arduino.h" 10 | //add your includes for the project picoIPv6 here 11 | 12 | 13 | //end of add your includes here 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | void loop(); 18 | void setup(); 19 | #ifdef __cplusplus 20 | } // extern "C" 21 | #endif 22 | 23 | //add your function definitions for the project picoIPv6 here 24 | 25 | 26 | 27 | 28 | //Do not add code below this line 29 | #endif /* PICOIPV6UDPRXTX_H_ */ 30 | -------------------------------------------------------------------------------- /examples/UDP/UDPReceiveCallbackSendEchoInverted/UDPReceiveCallbackSendEchoInverted.pde: -------------------------------------------------------------------------------- 1 | // Do not remove the include below 2 | #include "UDPReceiveCallbackSendEchoInverted.h" 3 | 4 | #include "XBeeMACLayer.h" 5 | #include "PicoIPv6Connection.h" 6 | 7 | 8 | XBeeMACLayer macLayer; // XBee MAC Layer 9 | PicoIPv6Connection* picoIPv6Connection; // PicoIPv6 Connection 10 | u8_t picoip_buffer[UIP_BUFSIZE]; // Defines the picoIPv6 packet buffer. 11 | 12 | void setup() { 13 | 14 | Serial.begin(9600); 15 | 16 | // Start the MACLayer and PicoIPv6 Connection: 17 | // 1) Initialization of the MAC Layer. 18 | if ( !macLayer.init() ) { 19 | while (1){}; // Cannot initialize MAC Layer and will not continue. 20 | } 21 | 22 | // 2) Initialization of the picoIPv6 Connection. 23 | picoIPv6Connection = new PicoIPv6Connection(&macLayer, picoip_buffer); // Definition of an object of the class PicoIPv6Connection 24 | 25 | } 26 | 27 | 28 | // Definitions for the UDP Message to be sent 29 | const u16_t udp_source_port = 8765; // UDP Source Port Number. 30 | u16_t udp_destination_port = 8765; // UDP Destination Port Number. 31 | 32 | // Definition of UDP message payload buffer and messages counter. 33 | char udp_msg_buf[UIP_UDP_PAYLOAD_MAX_BUFSIZE]; // UDP payload buffer. 34 | u16_t udp_msg_length; 35 | 36 | void loop() { 37 | 38 | if (picoIPv6Connection->isConnected()){ 39 | // There is a connection at picoIPv6 level. 40 | 41 | if (picoIPv6Connection->receive()){//We answer the message we have just reverted in the msg_buffer 42 | 43 | if (picoIPv6Connection->getLastReceivedPacketType() == UDP){ 44 | 45 | /* 0) The function udp_input_callback has already been invoked by picoIPv6Connection->receive() because this is an UDP packet 46 | * On udp_input_callback we can make all preprocessing needed to the UDP payload we just received. 47 | * 48 | * On the current example we inverted the payload content and copied it to udp_msg_buf, 49 | * also setting the proper payload lenght to udp_msg_length 50 | */ 51 | 52 | 53 | // 1) Send UDP message to Last Sender (IP address and UDP Port) 54 | udp_destination_port = picoIPv6Connection->getLastSenderUDPSourcePort(); // Get Last Sender's UDP Source Port. 55 | picoIPv6Connection->udp_send(picoIPv6Connection->getLastSenderIPAddress(), udp_source_port, udp_destination_port, udp_msg_buf, udp_msg_length); // Send UDP message to Last Sender's IP Address. 56 | 57 | delay(100); 58 | } 59 | } 60 | 61 | }else{ 62 | // There is NOT a connection at picoIPv6 level. 63 | picoIPv6Connection->connect(); // We initialize a picoIPv6 connection. 64 | delay(200); // Add a delay time to establish a picoIPv6 connection. 65 | } 66 | 67 | } 68 | 69 | 70 | /* This function is automatically invoked when we call PicoIPv6Connection->receive() and there is new UDP Data. 71 | * * udp_data: contains new UDP datagram payload. 72 | * * length: contains new UDP datagram payload lenght. 73 | * 74 | * [ At lower level it is actually called from PicoIPv6State.udp_input() ] 75 | * [ only when the PicoIPv6State subclass is ConnectedState ] 76 | * */ 77 | void udp_input_callback(uint8_t* udp_data, uint16_t length){ 78 | 79 | // We will define a function that inverts udp_data string and put it into udp_msg_buf 80 | // Also we will set the new udp_msg_length = length 81 | uint8_t i; 82 | 83 | for(i=0; iisConnected()){ 48 | // There is a connection at picoIPv6 level. 49 | if (timer_expired(&udp_msg_timer)){ 50 | // UDP timer has expired. We send an UDP Message. 51 | // 1) Create UDP Message to be sent. 52 | ++udp_msg_counter; 53 | sprintf(udp_msg_buf, "UDP Message Nr.%hu\n", udp_msg_counter); // [ %hu h:short u:unsigned ] 54 | 55 | // 2) Send UDP Message. 56 | picoIPv6Connection->udp_send(&remote_client_ipaddr, udp_source_port, udp_destination_port, udp_msg_buf, strlen(udp_msg_buf)); 57 | 58 | // 3) Restart UDP timer. 59 | timer_restart(&udp_msg_timer); 60 | 61 | }//else{} // UDP timer has NOT expired. 62 | } 63 | else{// There is NOT a connection at picoIPv6 level. 64 | picoIPv6Connection->connect(); // We initialize a picoIPv6 connection. 65 | delay(200); // Add a delay time to establish a picoIPv6 connection. 66 | } 67 | 68 | } 69 | 70 | 71 | /* This function is automatically invoked when we call PicoIPv6Connection->receive() and there is new UDP Data. 72 | * * udp_data: contains new UDP datagram payload. 73 | * * length: contains new UDP datagram payload lenght. 74 | * 75 | * [ At lower level it is actually called from PicoIPv6State.udp_input() ] 76 | * [ only when the PicoIPv6State subclass is ConnectedState ] 77 | * */ 78 | void udp_input_callback(uint8_t* udp_data, uint16_t length) {} 79 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For picoIPv6 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | PicoIPv6Connection KEYWORD1 10 | XBeeMACLayer KEYWORD1 11 | MACLayer KEYWORD1 12 | MACTransmissionStatus KEYWORD1 13 | CoAPEngine KEYWORD1 14 | u8_t KEYWORD1 15 | struct KEYWORD1 16 | timer KEYWORD1 17 | uip_ipaddr_t KEYWORD1 18 | uint16_t KEYWORD1 19 | uint8_t KEYWORD1 20 | u16_t KEYWORD1 21 | 22 | 23 | 24 | 25 | ####################################### 26 | # Methods and Functions (KEYWORD2) 27 | ####################################### 28 | 29 | init KEYWORD2 30 | send KEYWORD2 31 | receive KEYWORD2 32 | getMacAddress KEYWORD2 33 | connect KEYWORD2 34 | setPicoIPv6Connection KEYWORD2 35 | isConnected KEYWORD2 36 | sendCoAPpacket KEYWORD2 37 | timer_restart KEYWORD2 38 | timer_set KEYWORD2 39 | timer_expired KEYWORD2 40 | udp_input_callback KEYWORD2 41 | strlen KEYWORD2 42 | sprintf KEYWORD2 43 | getLastReceivedPacketType KEYWORD2 44 | getLastSenderIPAddress KEYWORD2 45 | getLastSenderUDPSourcePort KEYWORD2 46 | getUdpData KEYWORD2 47 | udp_send KEYWORD2 48 | 49 | 50 | ####################################### 51 | # Constants (LITERAL1) 52 | ####################################### 53 | UIP_BUFSIZE LITERAL1 54 | DATA_SEND_PERIOD LITERAL1 55 | UDP_SEND_TIME LITERAL1 56 | UIP_UDP_PAYLOAD_MAX_BUFSIZE LITERAL1 -------------------------------------------------------------------------------- /picoIPv6MacV1.ino: -------------------------------------------------------------------------------- 1 | #include "XBeeMACLayer.h" 2 | #include "PicoIPv6Connection.h" 3 | //#include "CoAPEngine.h" 4 | #define DEBUG 0 5 | 6 | int mem(){ 7 | uint8_t * heapptr, * stackptr; 8 | stackptr = (uint8_t *)malloc(4); 9 | heapptr = stackptr; 10 | free(stackptr); 11 | stackptr = (uint8_t *)(SP); 12 | return stackptr - heapptr; 13 | } 14 | 15 | u8_t buf[UIP_BUFSIZE]; 16 | 17 | /*-------------------------------------------------------------------------------------*/ 18 | 19 | 20 | #define UDP_CLIENT_PORT 8765 21 | 22 | XBeeMACLayer mac; 23 | 24 | PicoIPv6Connection* connection; 25 | //CoAPEngine coap; // CoAPEngine-alpha. Sends CoAP PUT Non-Confirmable messages with URI, Query, optional second Query, and payload. 26 | 27 | 28 | //struct timer udp_msg_timer; 29 | 30 | void setup() { 31 | Serial.begin(9600); 32 | delay(1000); 33 | 34 | if (!mac.init()){ 35 | PRINTF("CANNOT INITIALIZE XBEE MODULE.. CANNOT CONTINUE"); 36 | while (1){}; 37 | } 38 | 39 | Serial.println("MAC ADDRESS: 0x"); 40 | for (int i=0; i<8; ++i){ 41 | Serial.println( mac.getMacAddress()->addr[i], HEX); 42 | } 43 | 44 | Serial.println("MACOK"); 45 | 46 | connection = new PicoIPv6Connection(&mac, buf); 47 | 48 | Serial.println("CONOK"); 49 | 50 | //Send one message to broadcast 51 | char aux[] = "HELLO"; 52 | connection->udp_send(connection->getLinkLocalMcastIPAddress(), UDP_CLIENT_PORT, UDP_CLIENT_PORT, aux , 5); 53 | 54 | Serial.println("MCASTOK"); 55 | 56 | //Serial.println(); 57 | //Serial.println(); 58 | PRINTF("MEMORY RAM LEFT: "); 59 | Serial.println(mem(), DEC); 60 | //Serial.println(); 61 | delay(100); 62 | //timer_set(&udp_msg_timer, UDP_SEND_TIME); 63 | } 64 | 65 | char msg_buf[160]; 66 | 67 | uint16_t msg_length; 68 | 69 | void udp_input_callback(uint8_t* udp_data, uint16_t length){ 70 | uint8_t i; 71 | 72 | PRINTF(); 73 | PRINTF(); 74 | PRINTF("DATA rcv: "); 75 | for (i=0; i < length; ++i){ 76 | PRINTHEX((char)udp_data[i]); 77 | } 78 | PRINTF(); 79 | PRINTF(); 80 | 81 | for(i=0; iisConnected()){ 96 | PRINTF("CONNECTED!"); 97 | Serial.println("CONN!"); 98 | delay(100); 99 | /* 100 | if (timer_expired(&udp_msg_timer)){ 101 | PRINTF("UDP TIMER EXPIRED! SEND.."); 102 | ++msg_counter; 103 | sprintf(msg_buf, msg, msg_counter); 104 | connection->udp_send(&remote_client_ipaddr, UDP_CLIENT_PORT, UDP_CLIENT_PORT, msg_buf, strlen(msg_buf)); 105 | timer_restart(&udp_msg_timer); 106 | }else{ 107 | PRINTF("UDP TIMER NOT EXPIRED."); 108 | } 109 | */ 110 | if (connection->receive()){//We answer the message we have just reverted in the msg_buffer 111 | PRINTF("RECEIVED!"); 112 | if (connection->getLastReceivedPacketType() == UDP){ 113 | PRINTF(); 114 | PRINTF(); 115 | PRINTF("IT IS UDP MESSAGE!!"); 116 | connection->udp_send(connection->getLastSenderIPAddress(), UDP_CLIENT_PORT, UDP_CLIENT_PORT, msg_buf, msg_length); 117 | // Serial.println(""); 118 | // Serial.println(mem(), DEC); 119 | 120 | delay(100); 121 | msg_buf[msg_length] = 0; //in order to print it for debugging, we finish the string with a 0 122 | PRINTF(); 123 | PRINTF("MSG received: "); 124 | PRINTF(msg_buf); 125 | PRINTF(); 126 | PRINTF(); 127 | } 128 | } 129 | 130 | //delay(UDP_SEND_TIME); 131 | }else{ 132 | 133 | Serial.println("NOC"); 134 | Serial.println(mem(), DEC); 135 | connection->connect(); 136 | delay(200); 137 | if (connection->isConnected()){//We have just connected for the first time or from a disconnection 138 | //timer_restart(&udp_msg_timer); 139 | //PRINTF("NEW UDP SENDING TIMER SET"); 140 | PRINTF("CONNECTED!"); 141 | } 142 | } 143 | delay(200); 144 | } 145 | 146 | 147 | -------------------------------------------------------------------------------- /rimeaddr.c: -------------------------------------------------------------------------------- 1 | /** 2 | * \addtogroup rimeaddr 3 | * @{ 4 | */ 5 | 6 | /* 7 | * Copyright (c) 2007, Swedish Institute of Computer Science. 8 | * All rights reserved. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the Institute nor the names of its contributors 19 | * may be used to endorse or promote products derived from this software 20 | * without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 | * SUCH DAMAGE. 33 | * 34 | * This file is part of the Contiki operating system. 35 | * 36 | * $Id: rimeaddr.c,v 1.9 2008/11/30 18:26:57 adamdunkels Exp $ 37 | */ 38 | 39 | /** 40 | * \file 41 | * Functions for manipulating Rime addresses 42 | * \author 43 | * Adam Dunkels 44 | */ 45 | 46 | #include "rimeaddr.h" 47 | 48 | //rimeaddr_t rimeaddr_node_addr; 49 | /*#if RIMEADDR_SIZE == 2 50 | const rimeaddr_t rimeaddr_null = { { 0, 0 } }; 51 | #else 52 | #if RIMEADDR_SIZE == 8*/ 53 | const rimeaddr_t rimeaddr_null = { { 0, 0, 0, 0, 0, 0, 0, 0 } }; 54 | /*#endif 55 | #endif */ 56 | 57 | //const rimeaddr_t rimeaddr_broadcast = { { 0xFF, 0xFF } }; 58 | 59 | 60 | /*---------------------------------------------------------------------------*/ 61 | void 62 | rimeaddr_copy(rimeaddr_t *dest, const rimeaddr_t *src, uint8_t addr_size) 63 | { 64 | u8_t i; 65 | for(i = 0; i < addr_size; i++) { 66 | dest->u8[i] = src->u8[i]; 67 | } 68 | } 69 | /*---------------------------------------------------------------------------*/ 70 | int 71 | rimeaddr_cmp(const rimeaddr_t *addr1, const rimeaddr_t *addr2, uint8_t addr_size) 72 | { 73 | u8_t i; 74 | for(i = 0; i < addr_size; i++) { 75 | if(addr1->u8[i] != addr2->u8[i]) { 76 | return 0; 77 | } 78 | } 79 | return 1; 80 | } 81 | /*---------------------------------------------------------------------------* 82 | void 83 | rimeaddr_set_node_addr(rimeaddr_t *t, uint8_t addr_size) 84 | { 85 | rimeaddr_copy(&rimeaddr_node_addr, t, addr_size); 86 | } 87 | *---------------------------------------------------------------------------*/ 88 | /** @} */ 89 | -------------------------------------------------------------------------------- /rimeaddr.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \addtogroup rime 3 | * @{ 4 | */ 5 | 6 | /** 7 | * \defgroup rimeaddr Rime addresses 8 | * @{ 9 | * 10 | * The rimeaddr module is an abstract representation of addresses in 11 | * Rime. 12 | * 13 | */ 14 | 15 | /* 16 | * Copyright (c) 2007, Swedish Institute of Computer Science. 17 | * All rights reserved. 18 | * 19 | * Redistribution and use in source and binary forms, with or without 20 | * modification, are permitted provided that the following conditions 21 | * are met: 22 | * 1. Redistributions of source code must retain the above copyright 23 | * notice, this list of conditions and the following disclaimer. 24 | * 2. Redistributions in binary form must reproduce the above copyright 25 | * notice, this list of conditions and the following disclaimer in the 26 | * documentation and/or other materials provided with the distribution. 27 | * 3. Neither the name of the Institute nor the names of its contributors 28 | * may be used to endorse or promote products derived from this software 29 | * without specific prior written permission. 30 | * 31 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 32 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 33 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 34 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 35 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 39 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 40 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 41 | * SUCH DAMAGE. 42 | * 43 | * This file is part of the Contiki operating system. 44 | * 45 | * $Id: rimeaddr.h,v 1.6 2009/05/26 13:58:53 nvt-se Exp $ 46 | */ 47 | 48 | /** 49 | * \file 50 | * Header file for the Rime address representation 51 | * \author 52 | * Adam Dunkels 53 | */ 54 | 55 | #ifndef __RIMEADDR_H__ 56 | #define __RIMEADDR_H__ 57 | 58 | #include "conf.h" 59 | /* 60 | #ifdef RIMEADDR_CONF_SIZE 61 | #define RIMEADDR_SIZE RIMEADDR_CONF_SIZE 62 | #else 63 | #define RIMEADDR_SIZE 2 64 | #endif 65 | */ 66 | typedef union { 67 | unsigned char u8[8]; 68 | } rimeaddr_t; 69 | 70 | 71 | /** 72 | * \brief Copy a Rime address 73 | * \param dest The destination 74 | * \param from The source 75 | * 76 | * This function copies a Rime address from one location 77 | * to another. 78 | * 79 | */ 80 | void rimeaddr_copy(rimeaddr_t *dest, const rimeaddr_t *from, uint8_t addr_size); 81 | 82 | /** 83 | * \brief Compare two Rime addresses 84 | * \param addr1 The first address 85 | * \param addr2 The second address 86 | * \return Non-zero if the addresses are the same, zero if they are different 87 | * 88 | * This function compares two Rime addresses and returns 89 | * the result of the comparison. The function acts like 90 | * the '==' operator and returns non-zero if the addresses 91 | * are the same, and zero if the addresses are different. 92 | * 93 | */ 94 | int rimeaddr_cmp(const rimeaddr_t *addr1, const rimeaddr_t *addr2, uint8_t addr_size); 95 | 96 | 97 | /** 98 | * \brief Set the address of the current node 99 | * \param addr The address 100 | * 101 | * This function sets the Rime address of the node. 102 | * 103 | */ 104 | void rimeaddr_set_node_addr(rimeaddr_t *addr, uint8_t addr_size); 105 | 106 | /** 107 | * \brief The Rime address of the node 108 | * 109 | * This variable contains the Rime address of the 110 | * node. This variable should not be changed directly; 111 | * rather, the rimeaddr_set_node_addr() function should be 112 | * used. 113 | * 114 | */ 115 | extern rimeaddr_t rimeaddr_node_addr; 116 | 117 | /** 118 | * \brief The null Rime address 119 | * 120 | * This variable contains the null Rime address. The null 121 | * address is used in route tables to indicate that the 122 | * table entry is unused. Nodes with no configured address 123 | * has the null address. Nodes with their node address set 124 | * to the null address will have problems communicating 125 | * with other nodes. 126 | * 127 | */ 128 | extern const rimeaddr_t rimeaddr_null; 129 | 130 | //ADDED ALE 131 | //extern const rimeaddr_t rimeaddr_broadcast; 132 | 133 | #endif /* __RIMEADDR_H__ */ 134 | /** @} */ 135 | /** @} */ 136 | -------------------------------------------------------------------------------- /sicsLowPan.h: -------------------------------------------------------------------------------- 1 | #ifndef SICSLOWPAN_H_ 2 | #define SICSLOWPAN_H_ 3 | 4 | /** 5 | * \addtogroup sicslowpan 6 | * @{ 7 | */ 8 | 9 | /* 10 | * Copyright (c) 2008, Swedish Institute of Computer Science. 11 | * All rights reserved. 12 | * 13 | * Redistribution and use in source and binary forms, with or without 14 | * modification, are permitted provided that the following conditions 15 | * are met: 16 | * 1. Redistributions of source code must retain the above copyright 17 | * notice, this list of conditions and the following disclaimer. 18 | * 2. Redistributions in binary form must reproduce the above copyright 19 | * notice, this list of conditions and the following disclaimer in the 20 | * documentation and/or other materials provided with the distribution. 21 | * 3. Neither the name of the Institute nor the names of its contributors 22 | * may be used to endorse or promote products derived from this software 23 | * without specific prior written permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 | * SUCH DAMAGE. 36 | * 37 | * This file is part of the Contiki operating system. 38 | * 39 | * $Id: sicslowpan.h,v 1.13 2010/03/26 10:28:51 joxe Exp $ 40 | */ 41 | /** 42 | * \file 43 | * Header file for the 6lowpan implementation 44 | * (RFC4944 and draft-hui-6lowpan-hc-01) 45 | * \author Adam Dunkels 46 | * \author Nicolas Tsiftes 47 | * \author Niclas Finne 48 | * \author Mathilde Durvy 49 | * \author Julien Abeille 50 | */ 51 | 52 | #include "conf.h" 53 | #include "rimeaddr.h" 54 | 55 | 56 | /** 57 | * \name General sicslowpan defines 58 | * @{ 59 | */ 60 | /* Min and Max compressible UDP ports - HC06 */ 61 | #define SICSLOWPAN_UDP_4_BIT_PORT_MIN 0xF0B0 62 | #define SICSLOWPAN_UDP_4_BIT_PORT_MAX 0xF0BF /* F0B0 + 15 */ 63 | #define SICSLOWPAN_UDP_8_BIT_PORT_MIN 0xF000 64 | #define SICSLOWPAN_UDP_8_BIT_PORT_MAX 0xF0FF /* F000 + 255 */ 65 | 66 | #define SICSLOWPAN_CONF_COMPRESSION_IPV6 0 67 | #define SICSLOWPAN_CONF_COMPRESSION_HC1 1 68 | #define SICSLOWPAN_CONF_COMPRESSION_HC06 2 69 | 70 | /** 71 | * \name 6lowpan dispatches 72 | * @{ 73 | */ 74 | #define SICSLOWPAN_DISPATCH_IPV6 0x41 /* 01000001 = 65 */ 75 | #define SICSLOWPAN_DISPATCH_HC1 0x42 /* 01000010 = 66 */ 76 | #define SICSLOWPAN_DISPATCH_IPHC 0x60 /* 011xxxxx = ... */ 77 | #define SICSLOWPAN_DISPATCH_FRAG1 0xc0 /* 11000xxx */ 78 | #define SICSLOWPAN_DISPATCH_FRAGN 0xe0 /* 11100xxx */ 79 | /** @} */ 80 | 81 | /** \name HC1 encoding 82 | * @{ 83 | */ 84 | #define SICSLOWPAN_HC1_NH_UDP 0x02 85 | #define SICSLOWPAN_HC1_NH_TCP 0x06 86 | #define SICSLOWPAN_HC1_NH_ICMP6 0x04 87 | /** @} */ 88 | 89 | /** \name HC_UDP encoding (works together with HC1) 90 | * @{ 91 | */ 92 | #define SICSLOWPAN_HC_UDP_ALL_C 0xE0 93 | /** @} */ 94 | 95 | /** 96 | * \name IPHC encoding 97 | * @{ 98 | */ 99 | /* 100 | * Values of fields within the IPHC encoding first byte 101 | * (C stands for compressed and I for inline) 102 | */ 103 | #define SICSLOWPAN_IPHC_FL_C 0x10 104 | #define SICSLOWPAN_IPHC_TC_C 0x08 105 | #define SICSLOWPAN_IPHC_NH_C 0x04 106 | #define SICSLOWPAN_IPHC_TTL_1 0x01 107 | #define SICSLOWPAN_IPHC_TTL_64 0x02 108 | #define SICSLOWPAN_IPHC_TTL_255 0x03 109 | #define SICSLOWPAN_IPHC_TTL_I 0x00 110 | 111 | 112 | /* Values of fields within the IPHC encoding second byte */ 113 | #define SICSLOWPAN_IPHC_CID 0x80 114 | 115 | #define SICSLOWPAN_IPHC_SAC 0x40 116 | #define SICSLOWPAN_IPHC_SAM_00 0x00 117 | #define SICSLOWPAN_IPHC_SAM_01 0x10 118 | #define SICSLOWPAN_IPHC_SAM_10 0x20 119 | #define SICSLOWPAN_IPHC_SAM_11 0x30 120 | 121 | #define SICSLOWPAN_IPHC_SAM_BIT 4 122 | 123 | #define SICSLOWPAN_IPHC_M 0x08 124 | #define SICSLOWPAN_IPHC_DAC 0x04 125 | #define SICSLOWPAN_IPHC_DAM_00 0x00 126 | #define SICSLOWPAN_IPHC_DAM_01 0x01 127 | #define SICSLOWPAN_IPHC_DAM_10 0x02 128 | #define SICSLOWPAN_IPHC_DAM_11 0x03 129 | 130 | #define SICSLOWPAN_IPHC_DAM_BIT 0 131 | 132 | /* Link local context number */ 133 | #define SICSLOWPAN_IPHC_ADDR_CONTEXT_LL 0 134 | /* 16-bit multicast addresses compression */ 135 | #define SICSLOWPAN_IPHC_MCAST_RANGE 0xA0 136 | /** @} */ 137 | 138 | /* NHC_EXT_HDR */ 139 | #define SICSLOWPAN_NHC_MASK 0xF0 140 | #define SICSLOWPAN_NHC_EXT_HDR 0xE0 141 | 142 | /** 143 | * \name LOWPAN_UDP encoding (works together with IPHC) 144 | * @{ 145 | */ 146 | /** 147 | * \name LOWPAN_UDP encoding (works together with IPHC) 148 | * @{ 149 | */ 150 | #define SICSLOWPAN_NHC_UDP_MASK 0xF8 151 | #define SICSLOWPAN_NHC_UDP_ID 0xF0 152 | #define SICSLOWPAN_NHC_UDP_CHECKSUMC 0x04 153 | #define SICSLOWPAN_NHC_UDP_CHECKSUMI 0x00 154 | /* values for port compression, _with checksum_ ie bit 5 set to 0 */ 155 | #define SICSLOWPAN_NHC_UDP_CS_P_00 0xF0 /* all inline */ 156 | #define SICSLOWPAN_NHC_UDP_CS_P_01 0xF1 /* source 16bit inline, dest = 0xF0 + 8 bit inline */ 157 | #define SICSLOWPAN_NHC_UDP_CS_P_10 0xF2 /* source = 0xF0 + 8bit inline, dest = 16 bit inline */ 158 | #define SICSLOWPAN_NHC_UDP_CS_P_11 0xF3 /* source & dest = 0xF0B + 4bit inline */ 159 | /** @} */ 160 | 161 | 162 | /** 163 | * \name The 6lowpan "headers" length 164 | * @{ 165 | */ 166 | 167 | #define SICSLOWPAN_IPV6_HDR_LEN 1 /*one byte*/ 168 | #define SICSLOWPAN_HC1_HDR_LEN 3 169 | #define SICSLOWPAN_HC1_HC_UDP_HDR_LEN 7 170 | #define SICSLOWPAN_FRAG1_HDR_LEN 4 171 | #define SICSLOWPAN_FRAGN_HDR_LEN 5 172 | /** @} */ 173 | 174 | /** 175 | * \brief The header for fragments 176 | * \note We do not define different structures for FRAG1 177 | * and FRAGN headers, which are different. For FRAG1, the 178 | * offset field is just not used 179 | */ 180 | /* struct sicslowpan_frag_hdr { */ 181 | /* u16_t dispatch_size; */ 182 | /* u16_t tag; */ 183 | /* u8_t offset; */ 184 | /* }; */ 185 | 186 | /** 187 | * \brief The HC1 header when HC_UDP is not used 188 | * 189 | * When all fields are compressed and HC_UDP is not used, 190 | * we use this structure. If HC_UDP is used, the ttl is 191 | * in another spot, and we use the sicslowpan_hc1_hc_udp 192 | * structure 193 | */ 194 | /* struct sicslowpan_hc1_hdr { */ 195 | /* u8_t dispatch; */ 196 | /* u8_t encoding; */ 197 | /* u8_t ttl; */ 198 | /* }; */ 199 | 200 | /** 201 | * \brief HC1 followed by HC_UDP 202 | */ 203 | /* struct sicslowpan_hc1_hc_udp_hdr { */ 204 | /* u8_t dispatch; */ 205 | /* u8_t hc1_encoding; */ 206 | /* u8_t hc_udp_encoding; */ 207 | /* u8_t ttl; */ 208 | /* u8_t ports; */ 209 | /* u16_t udpchksum; */ 210 | /* }; */ 211 | 212 | /** 213 | * \brief An address context for IPHC address compression 214 | * each context can have upto 8 bytes 215 | */ 216 | struct sicslowpan_addr_context { 217 | u8_t used; /* possibly use as prefix-length */ 218 | u8_t number; 219 | u8_t prefix[8]; 220 | }; 221 | 222 | /** 223 | * \name Address compressibility test functions 224 | * @{ 225 | */ 226 | 227 | /** 228 | * \brief check whether we can compress the IID in 229 | * address 'a' to 16 bits. 230 | * This is used for unicast addresses only, and is true 231 | * if the address is on the format ::0000:00ff:fe00:XXXX 232 | * NOTE: we currently assume 64-bits prefixes 233 | */ 234 | #define sicslowpan_is_iid_16_bit_compressable(a) \ 235 | ((((a)->u16[4]) == 0) && \ 236 | (((a)->u8[10]) == 0)&& \ 237 | (((a)->u8[11]) == 0xff)&& \ 238 | (((a)->u8[12]) == 0xfe)&& \ 239 | (((a)->u8[13]) == 0)) 240 | 241 | /** 242 | * \brief check whether the 9-bit group-id of the 243 | * compressed multicast address is known. It is true 244 | * if the 9-bit group is the all nodes or all routers 245 | * group. 246 | * \param a is typed u8_t * 247 | */ 248 | #define sicslowpan_is_mcast_addr_decompressable(a) \ 249 | (((*a & 0x01) == 0) && \ 250 | ((*(a + 1) == 0x01) || (*(a + 1) == 0x02))) 251 | 252 | /** 253 | * \brief check whether the 112-bit group-id of the 254 | * multicast address is mappable to a 9-bit group-id 255 | * It is true if the group is the all nodes or all 256 | * routers group. 257 | */ 258 | #define sicslowpan_is_mcast_addr_compressable(a) \ 259 | ((((a)->u16[1]) == 0) && \ 260 | (((a)->u16[2]) == 0) && \ 261 | (((a)->u16[3]) == 0) && \ 262 | (((a)->u16[4]) == 0) && \ 263 | (((a)->u16[5]) == 0) && \ 264 | (((a)->u16[6]) == 0) && \ 265 | (((a)->u8[14]) == 0) && \ 266 | ((((a)->u8[15]) == 1) || (((a)->u8[15]) == 2))) 267 | 268 | /* FFXX::00XX:XXXX:XXXX */ 269 | #define sicslowpan_is_mcast_addr_compressable48(a) \ 270 | ((((a)->u16[1]) == 0) && \ 271 | (((a)->u16[2]) == 0) && \ 272 | (((a)->u16[3]) == 0) && \ 273 | (((a)->u16[4]) == 0) && \ 274 | (((a)->u8[10]) == 0)) 275 | 276 | /* FFXX::00XX:XXXX */ 277 | #define sicslowpan_is_mcast_addr_compressable32(a) \ 278 | ((((a)->u16[1]) == 0) && \ 279 | (((a)->u16[2]) == 0) && \ 280 | (((a)->u16[3]) == 0) && \ 281 | (((a)->u16[4]) == 0) && \ 282 | (((a)->u16[5]) == 0) && \ 283 | (((a)->u8[12]) == 0)) 284 | 285 | /* FF02::00XX */ 286 | #define sicslowpan_is_mcast_addr_compressable8(a) \ 287 | ((((a)->u8[1]) == 2) && \ 288 | (((a)->u16[1]) == 0) && \ 289 | (((a)->u16[2]) == 0) && \ 290 | (((a)->u16[3]) == 0) && \ 291 | (((a)->u16[4]) == 0) && \ 292 | (((a)->u16[5]) == 0) && \ 293 | (((a)->u16[6]) == 0) && \ 294 | (((a)->u8[14]) == 0)) 295 | 296 | /*---FROM uip.h---*/ 297 | #define uip_is_addr_mac_addr_based(a, m) \ 298 | ((((a)->u8[8]) == (((m)->addr[0]) ^ 0x02)) && \ 299 | (((a)->u8[9]) == (m)->addr[1]) && \ 300 | (((a)->u8[10]) == (m)->addr[2]) && \ 301 | (((a)->u8[11]) == (m)->addr[3]) && \ 302 | (((a)->u8[12]) == (m)->addr[4]) && \ 303 | (((a)->u8[13]) == (m)->addr[5]) && \ 304 | (((a)->u8[14]) == (m)->addr[6]) && \ 305 | (((a)->u8[15]) == (m)->addr[7])) 306 | 307 | 308 | /** 309 | * \brief is addr (a) a link local unicast address, see RFC3513 310 | * i.e. is (a) on prefix FE80::/10 311 | * a is of type uip_ipaddr_t* 312 | */ 313 | #define uip_is_addr_link_local(a) \ 314 | ((((a)->u8[0]) == 0xFE) && \ 315 | (((a)->u8[1]) == 0x80)) 316 | 317 | /** 318 | * \brief is address a multicast address, see RFC 3513 319 | * a is of type uip_ipaddr_t* 320 | * */ 321 | #define uip_is_addr_mcast(a) \ 322 | (((a)->u8[0]) == 0xFF) 323 | 324 | /** 325 | * \brief Is IPv6 address a the unspecified address 326 | * a is of type uip_ipaddr_t 327 | */ 328 | #define uip_is_addr_unspecified(a) \ 329 | ((((a)->u16[0]) == 0) && \ 330 | (((a)->u16[1]) == 0) && \ 331 | (((a)->u16[2]) == 0) && \ 332 | (((a)->u16[3]) == 0) && \ 333 | (((a)->u16[4]) == 0) && \ 334 | (((a)->u16[5]) == 0) && \ 335 | (((a)->u16[6]) == 0) && \ 336 | (((a)->u16[7]) == 0)) 337 | 338 | 339 | #define uip_ipaddr_prefixcmp(addr1, addr2, length) (memcmp(addr1, addr2, length>>3) == 0) 340 | 341 | /** @} */ 342 | 343 | /*-----------------------------------------------------------------------------*/ 344 | /*------------------------------ API DESCRIPTION ------------------------------*/ 345 | /*-----------------------------------------------------------------------------*/ 346 | 347 | /* 348 | * This function initializes the 6loWPAN contexts for compression. 349 | * Must be called just once and before compressing or decompressing. 350 | */ 351 | void sicslowpan_init(uip_lladdr_t* myMac); 352 | 353 | /* 354 | * This is the function to call in order to compress an IPv6 packet into a 6loWPAN packet. 355 | * 356 | * Preconditions: 357 | * The 'uip_lladdr' global variable must have the value of the link (MAC) layer address of the source (sender). 358 | * The 'uip_buf' pointer must buffer the IPv6 packet that is willing to be compressed. 359 | * The 'uip_len' variable's value must correspond to the length of the IPv6 packet placed in 'uip_buf'. 360 | * 361 | * Postconditions: 362 | * The 'uip_6lp_buf' variable will point to the buffer that will contain the compressed IPv6 packet (the 6loWPAN packet) that must be sent by the link (MAC) layer. 363 | * The 'uip_6lp_len' variable will contain the length of the compressed IPv6 packet (the 6loWPAN packet) that must be sent by the link (MAC) layer. 364 | * 365 | * Returns: 0 if it fails, 1 in other case. 366 | * 367 | * localdest: This is a pointer to the data structure that contains the link layer (MAC) address of the destination to send the frame. 368 | * 369 | * IMPORTANT: The buffers containing the IPv6 packets and the compressed 6loWPAN packets consist in UINT16 positions where each contains only ONE byte represented by the 8 less significant bits. 370 | */ 371 | uint8_t output(uip_lladdr_t *localdest); 372 | 373 | 374 | /* 375 | * This is the function to call in order to decompress an incoming 6loWPAN packet into an IPv6 packet. 376 | * 377 | * Preconditions: 378 | * The 'uip_6lp_buf' variable must point to the buffer that contains the incoming compressed IPv6 packet (the 6loWPAN packet) that is willing to be decompressed. 379 | * The 'uip_6lp_len' variable must contain the length of the compressed IPv6 packet (the 6loWPAN packet) that is willing to be decompressed. 380 | * 381 | * Postconditions: 382 | * The 'uip_buf' pointer will buffer the IPv6 packet that was obtained by decompressing the 6loWPAN incoming packet pointed by the 'uip_6lp_buf'. 383 | * The 'uip_len' variable's value will correspond to the length of the IPv6 packet pointed by 'uip_buf', obtained by the decompression. 384 | * 385 | * Parameters: 386 | * uip_lladdr_source: This is a pointer to a data structure that contains the link layer (MAC) address of the source that sent the received frame. 387 | * uip_lladdr_destination: This is a pointer to a data structure that contains the link layer (MAC) address of the destination of the received frame. 388 | * 389 | * IMPORTANT: The buffers containing the IPv6 packets and the compressed 6loWPAN packets consist in UINT16 positions where each contains only ONE byte represented by the 8 less significant bits. 390 | */ 391 | void input(uip_lladdr_t *uip_lladdr_source, uip_lladdr_t *uip_lladdr_destination); 392 | 393 | //ADDED ALE 394 | typedef union { 395 | uint8_t u8[UIP_BUFSIZE]; 396 | } uip_ll_buf_t; 397 | 398 | //The buffer that will contain the compressed IPv6 packet (the 6loWPAN packet) that must be sent by the link (MAC) layer. 399 | //It is also the buffer the buffer that contains the incoming compressed IPv6 packet (the 6loWPAN packet) that is willing to be decompressed. 400 | extern uip_ll_buf_t uip_6lp_buf; 401 | 402 | //The variable that will contain the length of the compressed IPv6 packet (the 6loWPAN packet) that must be sent by the link (MAC) layer. 403 | //It is also the length of the compressed IPv6 packet (the 6loWPAN packet) that is willing to be decompressed. 404 | extern u16_t uip_6lp_len; 405 | 406 | //The pointer to the buffer where the decompressed ipv6 packet will be 407 | //This pointer has to be initialized by the user of output and input 6lowpan functions 408 | extern uint8_t* uip_buf; 409 | 410 | //The amount of valid data bytes in the uip_buf buffer 411 | extern uint16_t uip_length; 412 | 413 | extern uip_lladdr_t* uip_lladdr; 414 | 415 | #endif /*SICSLOWPAN_H_*/ 416 | -------------------------------------------------------------------------------- /timer.c: -------------------------------------------------------------------------------- 1 | /** 2 | * \addtogroup timer 3 | * @{ 4 | */ 5 | 6 | /** 7 | * \file 8 | * Timer library implementation. 9 | * \author 10 | * Adam Dunkels 11 | */ 12 | 13 | /* 14 | * Copyright (c) 2004, Swedish Institute of Computer Science. 15 | * All rights reserved. 16 | * 17 | * Redistribution and use in source and binary forms, with or without 18 | * modification, are permitted provided that the following conditions 19 | * are met: 20 | * 1. Redistributions of source code must retain the above copyright 21 | * notice, this list of conditions and the following disclaimer. 22 | * 2. Redistributions in binary form must reproduce the above copyright 23 | * notice, this list of conditions and the following disclaimer in the 24 | * documentation and/or other materials provided with the distribution. 25 | * 3. Neither the name of the Institute nor the names of its contributors 26 | * may be used to endorse or promote products derived from this software 27 | * without specific prior written permission. 28 | * 29 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 30 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 33 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | * SUCH DAMAGE. 40 | * 41 | * This file is part of the Contiki operating system. 42 | * 43 | * Author: Adam Dunkels 44 | * 45 | * $Id: timer.c,v 1.8 2010/06/21 19:07:24 joxe Exp $ 46 | */ 47 | 48 | #include "conf.h" 49 | //#include "sys/clock.h" 50 | //#include "sys/timer.h" 51 | #include "clock.h" 52 | #include "timer.h" 53 | 54 | /*---------------------------------------------------------------------------*/ 55 | /** 56 | * Set a timer. 57 | * 58 | * This function is used to set a timer for a time sometime in the 59 | * future. The function timer_expired() will evaluate to true after 60 | * the timer has expired. 61 | * 62 | * \param t A pointer to the timer 63 | * \param interval The interval before the timer expires. 64 | * 65 | */ 66 | void 67 | timer_set(struct timer *t, clock_time_t interval) 68 | { 69 | t->interval = interval; 70 | t->start = clock_time(); 71 | } 72 | /*---------------------------------------------------------------------------*/ 73 | /** 74 | * Reset the timer with the same interval. 75 | * 76 | * This function resets the timer with the same interval that was 77 | * given to the timer_set() function. The start point of the interval 78 | * is the exact time that the timer last expired. Therefore, this 79 | * function will cause the timer to be stable over time, unlike the 80 | * timer_restart() function. 81 | * 82 | * \param t A pointer to the timer. 83 | * 84 | * \sa timer_restart() 85 | */ 86 | void 87 | timer_reset(struct timer *t) 88 | { 89 | t->start += t->interval; 90 | } 91 | /*---------------------------------------------------------------------------*/ 92 | /** 93 | * Restart the timer from the current point in time 94 | * 95 | * This function restarts a timer with the same interval that was 96 | * given to the timer_set() function. The timer will start at the 97 | * current time. 98 | * 99 | * \note A periodic timer will drift if this function is used to reset 100 | * it. For preioric timers, use the timer_reset() function instead. 101 | * 102 | * \param t A pointer to the timer. 103 | * 104 | * \sa timer_reset() 105 | */ 106 | void 107 | timer_restart(struct timer *t) 108 | { 109 | t->start = clock_time(); 110 | } 111 | /*---------------------------------------------------------------------------*/ 112 | /** 113 | * Check if a timer has expired. 114 | * 115 | * This function tests if a timer has expired and returns true or 116 | * false depending on its status. 117 | * 118 | * \param t A pointer to the timer 119 | * 120 | * \return Non-zero if the timer has expired, zero otherwise. 121 | * 122 | */ 123 | int 124 | timer_expired(struct timer *t) 125 | { 126 | /* Note: Can not return diff >= t->interval so we add 1 to diff and return 127 | t->interval < diff - required to avoid an internal error in mspgcc. */ 128 | clock_time_t diff = (clock_time() - t->start) + 1; 129 | return t->interval < diff; 130 | 131 | } 132 | /*---------------------------------------------------------------------------*/ 133 | /** 134 | * The time until the timer expires 135 | * 136 | * This function returns the time until the timer expires. 137 | * 138 | * \param t A pointer to the timer 139 | * 140 | * \return The time until the timer expires 141 | * 142 | */ 143 | clock_time_t 144 | timer_remaining(struct timer *t) 145 | { 146 | return t->start + t->interval - clock_time(); 147 | } 148 | /*---------------------------------------------------------------------------*/ 149 | 150 | /** @} */ 151 | -------------------------------------------------------------------------------- /timer.h: -------------------------------------------------------------------------------- 1 | /** \addtogroup sys 2 | * @{ */ 3 | 4 | /** 5 | * \defgroup timer Timer library 6 | * 7 | * The Contiki kernel does not provide support for timed 8 | * events. Rather, an application that wants to use timers needs to 9 | * explicitly use the timer library. 10 | * 11 | * The timer library provides functions for setting, resetting and 12 | * restarting timers, and for checking if a timer has expired. An 13 | * application must "manually" check if its timers have expired; this 14 | * is not done automatically. 15 | * 16 | * A timer is declared as a \c struct \c timer and all access to the 17 | * timer is made by a pointer to the declared timer. 18 | * 19 | * \note The timer library is not able to post events when a timer 20 | * expires. The \ref etimer "Event timers" should be used for this 21 | * purpose. 22 | * 23 | * \note The timer library uses the \ref clock "Clock library" to 24 | * measure time. Intervals should be specified in the format used by 25 | * the clock library. 26 | * 27 | * \sa \ref etimer "Event timers" 28 | * 29 | * @{ 30 | */ 31 | 32 | 33 | /** 34 | * \file 35 | * Timer library header file. 36 | * \author 37 | * Adam Dunkels 38 | */ 39 | 40 | /* 41 | * Copyright (c) 2004, Swedish Institute of Computer Science. 42 | * All rights reserved. 43 | * 44 | * Redistribution and use in source and binary forms, with or without 45 | * modification, are permitted provided that the following conditions 46 | * are met: 47 | * 1. Redistributions of source code must retain the above copyright 48 | * notice, this list of conditions and the following disclaimer. 49 | * 2. Redistributions in binary form must reproduce the above copyright 50 | * notice, this list of conditions and the following disclaimer in the 51 | * documentation and/or other materials provided with the distribution. 52 | * 3. Neither the name of the Institute nor the names of its contributors 53 | * may be used to endorse or promote products derived from this software 54 | * without specific prior written permission. 55 | * 56 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 57 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 58 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 59 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 60 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 61 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 62 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 63 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 64 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 65 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 66 | * SUCH DAMAGE. 67 | * 68 | * This file is part of the Contiki operating system. 69 | * 70 | * Author: Adam Dunkels 71 | * 72 | * $Id: timer.h,v 1.2 2008/09/21 08:58:05 adamdunkels Exp $ 73 | */ 74 | #ifndef __TIMER_H__ 75 | #define __TIMER_H__ 76 | 77 | //#include "sys/clock.h" 78 | #include "clock.h" 79 | 80 | /** 81 | * A timer. 82 | * 83 | * This structure is used for declaring a timer. The timer must be set 84 | * with timer_set() before it can be used. 85 | * 86 | * \hideinitializer 87 | */ 88 | struct timer { 89 | clock_time_t start; 90 | clock_time_t interval; 91 | }; 92 | 93 | 94 | void timer_set(struct timer *t, clock_time_t interval); 95 | void timer_reset(struct timer *t); 96 | void timer_restart(struct timer *t); 97 | int timer_expired(struct timer *t); 98 | 99 | clock_time_t timer_remaining(struct timer *t); 100 | 101 | 102 | #endif /* __TIMER_H__ */ 103 | 104 | /** @} */ 105 | /** @} */ 106 | -------------------------------------------------------------------------------- /tutorial/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imt-atlantique/Arduino-pIPv6Stack/07a05a8be4c7b9f58714d8e410bfba70f5f62e0c/tutorial/.DS_Store -------------------------------------------------------------------------------- /tutorial/ipv6config_generic_comands.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imt-atlantique/Arduino-pIPv6Stack/07a05a8be4c7b9f58714d8e410bfba70f5f62e0c/tutorial/ipv6config_generic_comands.txt -------------------------------------------------------------------------------- /tutorial/nat66_linux_deployment.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imt-atlantique/Arduino-pIPv6Stack/07a05a8be4c7b9f58714d8e410bfba70f5f62e0c/tutorial/nat66_linux_deployment.zip -------------------------------------------------------------------------------- /tutorial/picoIPv6_tutorial.txt: -------------------------------------------------------------------------------- 1 | HOW TO RUN PICO IPv6 (SUPPRESS RA) EXAMPLE: 2 | ------------------------------- 3 | 4 | * NEEDED: 5 | - Linux machine (for NAT66 router) 6 | - Host machine (for receiving and sending UDP messages). Could be a machine using netcat. 7 | - Tmote Sky (to run contiki's rpl-border-router example code) 8 | - Arduino UNO + Shield + XBee module (for answering the received messages) 9 | - Connection to an ipv6 outside network (In this case Ethernet manual configured IPv6 Network, network prefix: bbbb::/64 .Old Case: the wireless RSM-B25 network, prefix: 2001:660:7301:51 /64) 10 | - A delegated prefix configured for that network -for usin on the sensor network- 11 | (This Case: manually configured to be aaaa::/64 is configured to be managed by the linux machine with the bbbb::xxxx:xxxx:xxxx:xxxx/64 address configured with the NAT66 12 | OLD USECASE: the 2001:660:7301:57 /64 prefix is configured to be managed by the linux machine with the 2001:660:7301:51:ae39:dffff:fefa:ada3 /64 address, configured with the NAT66) 13 | 14 | * INSTRUCTIONS: 15 | 16 | 1) Download the code located in https://svn.telecom-bretagne.eu/repository/arduino-development // replace by picoIPv6 17 | 18 | 2) Apply the following configuration to your XBee module: 19 | 20 | CH - CHANNEL = 0xE 21 | 22 | ID - PAN ID = 0xABCD 23 | 24 | DH - Destination Address High = 0x0 25 | 26 | DL - Destination Address Low = 0xFFFF 27 | 28 | MY - 16-bit Source Address = 0xFFFF 29 | 30 | AP - API Enable = 0x2 31 | 32 | MM - MacMode = 2 33 | 34 | Usage XBEE Conf Mode: 35 | Console (screen, CoolTerm realterm)connect to Ardiono with XBEE with empty sketch 36 | press +++ WITHOUT pressing ENTER, and Wait for "OK" 37 | Then enter each command+value and press ENTER 38 | Eg. ATCHE (sets channel E, E == 14) 39 | Then for write all configurations send command ATWR 40 | ATWR + ENTER 41 | 42 | 43 | 3) Copy the nat66_linux_deployment.tar.gz code to the linux machine. It is located in the picoIPv6/tutorial folder. Decompress it in that machine. 44 | 45 | 4) In the nat66.c file, change the value of the delegated prefix that is going to be used (this case aaaa::) on the sensor/INTERNAL/6LoWPAN network: 46 | 47 |     /* Computation of the src addr - ::/64 prefix must be replaced by cccc::/64 prefix*/ 48 |     ip6h->ip6_src.s6_addr[0]=0x20; 49 |     ip6h->ip6_src.s6_addr[1]=0x01; 50 |     ip6h->ip6_src.s6_addr[2]=0x06; 51 |     ip6h->ip6_src.s6_addr[3]=0x60; 52 |     ip6h->ip6_src.s6_addr[4]=0x73; 53 |     ip6h->ip6_src.s6_addr[5]=0x01; 54 |     ip6h->ip6_src.s6_addr[6]=0x00; 55 |     ip6h->ip6_src.s6_addr[7]=0x57; 56 | 57 | to 58 | 59 |     /* Computation of the src addr - ::/64 prefix must be replaced by cccc::/64 prefix*/ 60 |     ip6h->ip6_src.s6_addr[0]=0xaa; 61 |     ip6h->ip6_src.s6_addr[1]=0xaa; 62 |     ip6h->ip6_src.s6_addr[2]=0x00; 63 |     ip6h->ip6_src.s6_addr[3]=0x00; 64 |     ip6h->ip6_src.s6_addr[4]=0x00; 65 |     ip6h->ip6_src.s6_addr[5]=0x00; 66 |     ip6h->ip6_src.s6_addr[6]=0x00; 67 |     ip6h->ip6_src.s6_addr[7]=0x00; 68 | 69 | 5) In the launch.sh file, change the following line by specifying the delegated prefix again: 70 | 71 | # ROUTE CONFIGURATION FOR NATING FROM OUTSIDE TO SENSOR NETWORK 72 | # Add a route for packets that goes to sensor network in order to nat them thanks to tunnel tun_otos - Only cccc::/64 packets must be natted 73 | ip -6 route add 2001:660:7301:57::/64 dev tun_otos 74 | 75 | to 76 | 77 | # ROUTE CONFIGURATION FOR NATING FROM OUTSIDE TO SENSOR NETWORK 78 | # Add a route for packets that goes to sensor network in order to nat them thanks to tunnel tun_otos - Only cccc::/64 packets must be natted 79 | ip -6 route add aaaa::/64 dev tun_otos # generic case: ip -6 route add ****:****:****:****::/64 dev tun_otos 80 | 81 | 6) In the contiki code, do the following changes: 82 | 83 | - In the uipopt.h file, add the following line at the end (this will add the use of an ACK to the DAO messages sent): 84 | 85 | #define RPL_CONF_DAO_ACK 1 86 | 87 | - In the ~/contiki/platform/sky/contiki-conf.h file, make sure that the RF channel is 14 and do the specified change (this will disable the ContikiMAC specific protocol, not necessarily available for all 802.15.4 devices): 88 | 89 | #define RF_CHANNEL 14 90 | 91 | CHANGE 92 | 93 | #ifndef NETSTACK_CONF_RDC 94 | #define NETSTACK_CONF_RDC contikimac_driver 95 | #endif /* NETSTACK_CONF_RDC */ 96 | 97 | TO 98 | 99 | #ifndef NETSTACK_CONF_RDC 100 | #define NETSTACK_CONF_RDC nullrdc_driver//contikimac_driver 101 | #endif /* NETSTACK_CONF_RDC */ 102 | 103 | - Go to the ~/contiki/examples/ipv6:rpl-border-router.c file and change the following: 104 | 105 | static uip_ipaddr_t prefix; 106 | 107 | to 108 | 109 | //This is the delegated prefix 110 | static uip_ipaddr_t prefix = {0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0, 0, 0, 0, 0, 0, 0, 0}; //static uip_ipaddr_t prefix = {0x20, 0x01, 0x6, 0x60, 0x73, 0x01, 0x00, 0x57, 0, 0, 0, 0, 0, 0, 0, 0}; 111 | 112 | AND 113 | 114 | PRINTF("RPL-Border router started\n"); 115 | 116 | /* Request prefix until it has been received */ 117 | while(!prefix_set) { 118 | etimer_set(&et, CLOCK_SECOND); 119 | request_prefix(); 120 | PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); 121 | } 122 | 123 | to 124 | 125 | PRINTF("RPL-Border router started\n"); 126 | 127 | //This line is added to specify our delegated the prefix 128 | set_prefix_64(&prefix); 129 | 130 | /* Request prefix until it has been received */ 131 | while(!prefix_set) { 132 | etimer_set(&et, CLOCK_SECOND); 133 | request_prefix(); 134 | PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); 135 | } 136 | 137 | 7) Load the contiki rpl-border-router example in a Tmote Sky: 138 | 139 | $ make TARGET=sky MOTES=/dev/ttyUSB0 border-router.upload 140 | 141 | NOTE: normally it will be /dev/ttyUSB* where the value may change according to the number of devices connected 142 | NOTE2: can also check the sky motes connected with command $ sudo make TARGET=sky sky-motelist 143 | 144 | 8) Go to ~/contiki/tools and compile the tunslip6 tool: 145 | 146 | $ cc -o tunslip6 tunslip6.c 147 | 148 | 9) Copy the tunslip6 executable to the linux machine which will run the NAT66 149 | 150 | 10) Connect the linux machine (NAT66 router) to the ipv6 network where the delegated prefix is configured (RSM-B25 in this case) 151 | 152 | 11) Connect the Tmote Sky with the uploaded rpl-border-router code to the linux machine with the NAT66 and run the tunslip6 application: 153 | $ sudo ./tunslip6 -v -t tap0 aaaa::212:7400:115e:c49b 154 | ($ sudo ./tunslip6 -v -t tap0 2001:660:7301:57:0012:7400:10cf:c311 ) 155 | 156 | NOTE: the IP address entered should be the one of the Tmote Sky device. The first 8 bytes correspond to the prefix aaaa:0000:0000:0000. The other 8 bytes correspond to the EUI-64 deriverd of the MAC address 0212:7400:115e:c49b. Change these values in terms of the prefix and the device used. 157 | NOTE2: to effectively obtain the IP Address of the Tmote Sky we can do a $ sudo make TARGET=sky login MOTES=/dev/ttyUSB* 158 | to the mote and resent; and the complete IP address will be printed on the terminal 159 | 160 | 12) Run the launch.sh script in order to configure the NAT66 router in the linux machine: 161 | 162 | $ sudo ./launch.sh 163 | 164 | 12b) Also to manually configure the ethernet IPv6 network run $ sudo ./ipv6OutsideNetConfig.sh or manually 165 | ifconfig eth0 inet6 add bbbb::2/64 # Linux machine will have IP bbbb::2/64 over eth0 interface 166 | route -A inet6 add bbbb::1/128 dev eth0 # We add a direct troute to the Host Machine that will have IP bbbb::1 over the ethernet link. 167 | 168 | 169 | 13) Connect the Arduino UNO + Shield + XBee module to a computer where the arduino IDE is installed and load the pico IPv6 (suppressRA) code to it (Once loaded, open the Serial Monitor if you want to see some debugging) 170 | Several library use examples can be found on the examples folder. Add the picoIPv6 as a custom arduino library (copy to Arduino/libraries); and then run the examples on arduino IDE by opening file-->Examples-->PicoIPv6-->FooExample 171 | 172 | 14) Connect a Host machine by Ethernet to the linux machine running the NAT66. And configure IP address and Route of the outsiede network (IP bbbb::1/64 gateway the NAT66 linux machine with ip bbbb::2) 173 | Eg: On a MACOSX Host machine, use Network tool , choose "Configure IPv6 Manually" set IPv6 Address to bbbb::1 , Prefix Length to 64 and Roter/gateway as the IP address of the linux machine: bbbb::2 174 | 175 | 15) On the host machine Use a terminal to listen to received UDP messages using netcat in the 8765 port (The port used on the UDP examples): 176 | $ nc -6 -u -l -v 8765 177 | 178 | 16) Open another terminal in order to send messages to the device 179 | 180 | $ nc -6 -u -v aaaa::213:a200:95D0:2fbd 8765 ) 181 | (nc -6 -u -v 2001:660:7301:57:13:a200:a6c1:2f57 8765) 182 | 183 | NOTE: The specified ip address is formed by the delegated prefix + XBee module's MAC address AFTER being modified by the NATT66 machine, will not be the same IID of the device INSIDE the sensor network. 184 | To find out the IID of the XBEE after the nat66, we can send UDP message from Arduino/XBee to destination bbbb::1 (already UDPSendPeriodic Example), and on the linux machine that is running nat66, 185 | you can sniff the eth0 interface (or the tap0 interface) to see the IP source address of the UDP message 186 | 187 | 17) For UDPReceiveCallbackSendEchoInverted : Start writing messages (up to 50 bytes -TODO: Check for 112 bytes restriction-) in the last opened terminal. The messages will be answered backwards and can be visualized in the previously opened terminal that receives the packets. 188 | 189 | NOTE: It is likely that a message must be sent more that once to see the answer. This is due to UDP packet loss, communication failures between the NAT66 router and the contiki border router (USB serial communication) and communication between the contiki border router and the XBee module (normally bad UDP checksums) 190 | 191 | 192 | ----------------------- 193 | COAP/Emoncms/RaspberryPi 194 | CoapSendPeriodic Example 195 | 196 | The HOST Machine will be replaced by a CoAP server host machine, in our case a RaspberryPI 197 | 198 | Set Up the Raspberry PI IPv6 address and gateway 199 | 1) Need to login by SSH to the RaspberryPi,for a configuration with no router and link to link ethernet connection we need to find the Local Link IP Address 200 | of our RaspberryPI (in our case case fe80::ba27:ebff:fea6:b22f . Tutorial of how to find the LL IP of the raspberryPI? Wireshark over the link?), and specify the ethernet interfacte that is connected to it (MACOSX case is en0, linux should be eth0), 201 | then we login with user "pi": 202 | 203 | $ ssh pi@fe80::ba27:ebff:fea6:b22f%en0 204 | 205 | password is: raspberry 206 | 207 | #IPv6 configuration 208 | sudo ifconfig eth0 inet6 add bbbb::3/64 209 | route -A inet6 add bbbb::/64 dev eth0 210 | 211 | #Show routes and neighbours for debugging pourposes 212 | route -A inet6 213 | ip -6 neigh show 214 | 215 | ------ 216 | EmonCMS with CoAP on RaspberryPi: 217 | 218 | 219 | # input.php 220 | $socket = stream_socket_server("udp://[::]:5683", $errno, $errstr, STREAM_SERVER_BIND); 221 | Implments coap server 222 | 223 | # Activate CoAP on emoncms 224 | cd /var/www/emoncms/Modules/coap/ 225 | nohup php input.php > /dev/null & 226 | 227 | #Show ports to see if we are listening to udp 5683 228 | sudo netstat -lptu # --listen -tulpn -vaun 229 | 230 | #Set proper Date for emoncsms to show time info 231 | sudo date -s "Tue Apr 16 10:28:10 CEST 2013" 232 | 233 | #... change emoncms write API to be short, and not use too much payload of CoAP packet 234 | 235 | #... --------------------------------------------------------------------------------