Collect-view Example for Contiki OS

In this article, I will explain the collect-view example that I added today. A few days ago I had the opportunity to explain this in detail. I will only show the changes on makefile and udp-server, udp-client. The letters in red indicate the additions on the Makefile.

hello friends in this video I will show you the use of collect-view on cooja. First of all, let me state that, measurements are made using the samples available on the internet and the files udp-sender.c udp-sink.c.

I will prepare a new project that works on udp-server udp-client from scratch. I received a lot of questions on this subject via e-mail, so I decided to shoot this video. I hope it helps you all. Thank you from now.

DEFINES+=PROJECT_CONF_H=\”project-conf.h\”
CONTIKI_PROJECT=udp-client udp-server
PROJECT_SOURCEFILES += collect-common.c

all: $(CONTIKI_PROJECT)
CONTIKI=../../../..

#linker optimizations
SMALL=1

# battery consumption I added
APPS += serial-shell collect-view

Now let’s look at the libraries that will be added to the udp-server and udp-client instances.

/**/
#include “collect-common.h”
#include “collect-view.h”
#include “dev/serial-line.h”
/**/

The above plug-ins will be added to the server and client. We can use the include files together with other files. We came to the most important part: First, we need to call collect_common_process. The added part is written in red. Those who know the subject understood that processes can be used in this way.

PROCESS(udp_server_process, “UDP server process”);
AUTOSTART_PROCESSES(&udp_server_process, &collect_common_process);

PROCESS_NAME (collect_common_process) to access collect_common_process; in collect-common.h in PROCESS_NAME.

/**
* \file
* Common code between collect client and server
* \author
* Niclas Finne <nfi@sics.se>
*/

#ifndef COLLECT_COMMON_H_
#define COLLECT_COMMON_H_

#include “contiki.h”
#include “net/linkaddr.h”

void collect_common_net_init(void);
void collect_common_net_print(void);
void collect_common_set_sink(void);
void collect_common_send(void);
void collect_common_recv(const linkaddr_t *originator, uint8_t seqno,
uint8_t hops,
uint8_t *payload,
uint16_t payload_len);
void collect_common_set_send_active(int active);

PROCESS_NAME(collect_common_process);

#endif /* COLLECT_COMMON_H_ */

Let’s not forget; The collect-common.c and collect-common.h files must be added under the rpl-udp folder. If not, Cooja will give a compile error and tell you that the file cannot be found.
Now let’s make some changes in server and client. Let’s not forget that if the results are not obtained after the changes, try to find solutions to the problems by reading the radio messages provided by Cooja.
Screenshot 2019-10-19 13:46:40.png
Add-on for udp-server.c;
PROCESS(udp_server_process, “UDP server process”);
AUTOSTART_PROCESSES(&udp_server_process, &collect_common_process);

#if 1
/*—————————————————————————*/
void
collect_common_set_sink(void)
{
}
/*—————————————————————————*/
void
collect_common_net_print(void)
{
PRINTF(“I am sink!\n”);
}
/*—————————————————————————*/
void
collect_common_send(void)
{
/* Server never sends */
}
/*—————————————————————————*/
void
collect_common_net_init(void)
{

uart1_set_input(serial_line_input_byte);
serial_line_init();

PRINTF(“I am sink!\n”);
}
#endif

I have made tcpip_handler compatible with us. The new code snippet is written in red. #If 0 means that it is no longer compiled.

static void
tcpip_handler(void)
{

#if 0

char *appdata;

if(uip_newdata()) {
appdata = (char *)uip_appdata;
appdata[uip_datalen()] = 0;
PRINTF(“DATA recv from “);
PRINTF(“%d”,
UIP_IP_BUF->srcipaddr.u8[sizeof(UIP_IP_BUF->srcipaddr.u8) – 1]);
#if RPL_ADD_ROUTE_ENABLED
uint16_t seq_no = (uint16_t)(appdata[34] << 8 | appdata[33]); PRINTF(” Seq No: %u\n”, seq_no); #else PRINTF(” ‘%s’\n”, appdata); #endif //PRINTF(“RSSI : %d\n”, packetbuf_attr(PACKETBUF_ATTR_RSSI)); #if SERVER_REPLY PRINTF(“DATA sending reply\n”); uip_ipaddr_copy(&server_conn->ripaddr, &UIP_IP_BUF->srcipaddr);
uip_udp_packet_send(server_conn, “Reply”, sizeof(“Reply”));
uip_create_unspecified(&server_conn->ripaddr);
#endif
}
#endif

#if 1
uint8_t *appdata;
linkaddr_t sender;
uint8_t seqno;
uint8_t hops;

if(uip_newdata()) {
appdata = (uint8_t *)uip_appdata;

appdata[uip_datalen()] = 0;
//PRINTF(“%d”,
// UIP_IP_BUF->srcipaddr.u8[sizeof(UIP_IP_BUF->srcipaddr.u8) – 1]);
//PRINTF(” ‘%s’\n”, appdata);

sender.u8[0] = UIP_IP_BUF->srcipaddr.u8[15];
sender.u8[1] = UIP_IP_BUF->srcipaddr.u8[14];
seqno = *appdata;
hops = uip_ds6_if.cur_hop_limit – UIP_IP_BUF->ttl + 1;
collect_common_recv(&sender, seqno, hops,
appdata + 2, uip_datalen() – 2);
}
#endif

}

Let’s go to the udp-client.c section here, the changes are similar to the server side.

/*—————————————————————————*/
PROCESS(udp_client_process, “UDP client process”);
AUTOSTART_PROCESSES(&udp_client_process, &collect_common_process);

#if 1
/*—————————————————————————*/
void
collect_common_set_sink(void)
{
/* A udp client can never become sink */
}

/*—————————————————————————*/
void
collect_common_net_print(void)
{
rpl_dag_t *dag;
uip_ds6_route_t *r;

/* Let’s suppose we have only one instance */
dag = rpl_get_any_dag();
if(dag->preferred_parent != NULL) {
PRINTF(“Preferred parent: “);
PRINT6ADDR(rpl_get_parent_ipaddr(dag->preferred_parent));
PRINTF(“\n”);
}
for(r = uip_ds6_route_head();
r != NULL;
r = uip_ds6_route_next(r)) {
PRINT6ADDR(&r->ipaddr);
}
PRINTF(“—\n”);
}

/*—————————————————————————*/
void
collect_common_net_init(void)
{
uart1_set_input(serial_line_input_byte);
serial_line_init();
}

/*—————————————————————————*/
void
collect_common_send(void)
{
static uip_ipaddr_t server_ipaddr;
uip_ip6addr(&server_ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0x200, 0, 0, 1); // parent ip adress

printf(“collect_common_send\n”);
static uint8_t seqno;
struct {
uint8_t seqno;
uint8_t for_alignment;
struct collect_view_data_msg msg;
} msg;
/* struct collect_neighbor *n; */
uint16_t parent_etx;
uint16_t rtmetric;
uint16_t num_neighbors;
uint16_t beacon_interval;
rpl_parent_t *preferred_parent;
linkaddr_t parent;
rpl_dag_t *dag;

if(client_conn == NULL) {
/* Not setup yet */
return;
}
memset(&msg, 0, sizeof(msg));
seqno++;
if(seqno == 0) {
/* Wrap to 128 to identify restarts */
seqno = 128;
}
msg.seqno = seqno;

linkaddr_copy(&parent, &linkaddr_null);
parent_etx = 0;

/* Let’s suppose we have only one instance */
dag = rpl_get_any_dag();
if(dag != NULL) {
preferred_parent = dag->preferred_parent;
if(preferred_parent != NULL) {
uip_ds6_nbr_t *nbr;
nbr = uip_ds6_nbr_lookup(rpl_get_parent_ipaddr(preferred_parent));
if(nbr != NULL) {
/* Use parts of the IPv6 address as the parent address, in reversed byte order. */
parent.u8[LINKADDR_SIZE – 1] = nbr->ipaddr.u8[sizeof(uip_ipaddr_t) – 2];
parent.u8[LINKADDR_SIZE – 2] = nbr->ipaddr.u8[sizeof(uip_ipaddr_t) – 1];
parent_etx = rpl_get_parent_rank((uip_lladdr_t *) uip_ds6_nbr_get_ll(nbr)) / 2;
}
}
rtmetric = dag->rank;
beacon_interval = (uint16_t) ((2L << dag->instance->dio_intcurrent) / 1000);
num_neighbors = uip_ds6_nbr_num();
} else {
rtmetric = 0;
beacon_interval = 0;
num_neighbors = 0;
}

/* num_neighbors = collect_neighbor_list_num(&tc.neighbor_list); */
collect_view_construct_message(&msg.msg, &parent,
parent_etx, rtmetric,
num_neighbors, beacon_interval);

uip_udp_packet_sendto(client_conn, &msg, sizeof(msg),
&server_ipaddr, UIP_HTONS(JOIN_PORT));
}
#endif

#define JOIN_PORT 5678

general information.

if UDP_CLIENT_PORT = 3000, UDP_SERVER_PORT = 3001, thus


udp-server.c
server_conn = udp_new(NULL, UIP_HTONS(3000), NULL);  <<== listening to port 3000

udp_bind(server_conn, UIP_HTONS(3001));



udp-client.c

client_conn = udp_new(NULL, UIP_HTONS(3001), NULL);   <<== send packet to port 3001

udp_bind(client_conn, UIP_HTONS(3000)); 

Screenshot 2019-10-19 14:18:30.png
Screenshot 2019-10-19 15:13:14

(fd) 16 = (253) 10

(fe) 16 = (254) 10

31 node powerview screenshots:

31 node31nodeaveragepower