Contiki 3.x
shell-sendtest.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008, Swedish Institute of Computer Science.
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  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 
33 /**
34  * \file
35  * A small pogram to measure the communication performance between two nodes
36  * \author
37  * Adam Dunkels <adam@sics.se>
38  */
39 
40 #include "contiki.h"
41 #include "shell-ps.h"
42 #include "net/rime/rime.h"
43 
44 #include <stdio.h>
45 #include <string.h>
46 
47 #if CONTIKI_TARGET_NETSIM
48 #include "ether.h"
49 #endif /* CONTIKI_TARGET_NETSIM */
50 #ifndef HAVE_SNPRINTF
51 int snprintf(char *str, size_t size, const char *format, ...);
52 #endif /* HAVE_SNPRINTF */
53 
54 /*---------------------------------------------------------------------------*/
55 PROCESS(shell_sendtest_process, "sendtest");
56 SHELL_COMMAND(sendtest_command,
57  "sendtest",
58  "sendtest: measure single-hop throughput",
59  &shell_sendtest_process);
60 /*---------------------------------------------------------------------------*/
61 static clock_time_t start_time_rucb, end_time_rucb;
62 static unsigned long filesize, bytecount, packetsize;
63 static int download_complete;
64 static void
65 write_chunk(struct rucb_conn *c, int offset, int flag,
66  char *data, int datalen)
67 {
68 #if CONTIKI_TARGET_NETSIM
69  {
70  char buf[100];
71  printf("received %d; %d\n", offset, datalen);
72  sprintf(buf, "%lu%%", (100 * (offset + datalen)) / filesize);
73  ether_set_text(buf);
74  }
75 #endif /* CONTIKI_TARGET_NETSIM */
76  /* printf("+");*/
77 }
78 static int
79 read_chunk(struct rucb_conn *c, int offset, char *to, int maxsize)
80 {
81  int size;
82  /* printf("-");*/
83  size = maxsize;
84  if(bytecount + maxsize >= filesize) {
85  size = filesize - bytecount;
86  }
87  if(size > packetsize) {
88  size = packetsize;
89  }
90  bytecount += size;
91  if(bytecount == filesize) {
92  end_time_rucb = clock_time();
93  download_complete = 1;
94  process_post(&shell_sendtest_process, PROCESS_EVENT_CONTINUE, NULL);
95  /* profile_aggregates_print(); */
96 /* profile_print_stats(); */
97 // print_stats();
98  }
99 
100  /* printf("bytecount %lu\n", bytecount);*/
101  return size;
102 }
103 const static struct rucb_callbacks rucb_callbacks = {write_chunk,
104  read_chunk,
105  NULL};
106 static struct rucb_conn rucb;
107 /*---------------------------------------------------------------------------*/
108 static void
109 print_usage(void)
110 {
111  shell_output_str(&sendtest_command,
112  "sendtest <receiver> <size> [packetsize]: recevier must be specified", "");
113 
114 }
115 /*---------------------------------------------------------------------------*/
116 PROCESS_THREAD(shell_sendtest_process, ev, data)
117 {
118  static linkaddr_t receiver;
119  static unsigned long cpu, lpm, rx, tx;
120  const char *nextptr;
121  const char *args;
122  char buf[40];
123  unsigned long cpu2, lpm2, rx2, tx2;
124 
125  PROCESS_BEGIN();
126 
127  args = data;
128  receiver.u8[0] = shell_strtolong(args, &nextptr);
129  if(nextptr == data || *nextptr != '.') {
130  print_usage();
131  PROCESS_EXIT();
132  }
133  args = nextptr + 1;
134  receiver.u8[1] = shell_strtolong(args, &nextptr);
135 
136 
137  args = nextptr;
138  while(*args == ' ') {
139  ++args;
140  }
141  filesize = shell_strtolong(args, &nextptr);
142  if(nextptr == data || filesize == 0) {
143  print_usage();
144  PROCESS_EXIT();
145  }
146 
147  args = nextptr;
148  while(*args == ' ') {
149  ++args;
150  }
151  packetsize = 64;
152  packetsize = shell_strtolong(args, &nextptr);
153  if(packetsize == 0) {
154  print_usage();
155  PROCESS_EXIT();
156  }
157 
158  snprintf(buf, sizeof(buf), "%d.%d, %lu bytes, packetsize %lu",
159  receiver.u8[0], receiver.u8[1], filesize, packetsize);
160  shell_output_str(&sendtest_command, "Sending data to ", buf);
161 
162  bytecount = 0;
163  download_complete = 0;
164 
165  start_time_rucb = clock_time();
166  rucb_send(&rucb, &receiver);
167 
168  energest_flush();
169  lpm = energest_type_time(ENERGEST_TYPE_LPM);
170  cpu = energest_type_time(ENERGEST_TYPE_CPU);
171  rx = energest_type_time(ENERGEST_TYPE_LISTEN);
172  tx = energest_type_time(ENERGEST_TYPE_TRANSMIT);
173 
174  PROCESS_WAIT_UNTIL(download_complete);
175 
176  energest_flush();
177  lpm2 = energest_type_time(ENERGEST_TYPE_LPM);
178  cpu2 = energest_type_time(ENERGEST_TYPE_CPU);
179  rx2 = energest_type_time(ENERGEST_TYPE_LISTEN);
180  tx2 = energest_type_time(ENERGEST_TYPE_TRANSMIT);
181 
182  sprintf(buf, "%d seconds, %lu bytes/second",
183  (int)((end_time_rucb - start_time_rucb) / CLOCK_SECOND),
184  CLOCK_SECOND * filesize / (end_time_rucb - start_time_rucb));
185  shell_output_str(&sendtest_command, "Completed in ", buf);
186 
187  sprintf(buf, "%lu/%d rx %lu/%d tx (seconds)",
188  (rx2 - rx), RTIMER_ARCH_SECOND,
189  (tx2 - tx), RTIMER_ARCH_SECOND);
190  shell_output_str(&sendtest_command, "Radio total on time ", buf);
191 
192  sprintf(buf, "%lu/%lu = %lu%%",
193  (rx2 - rx),
194  (cpu2 + lpm2 - cpu - lpm),
195  100 * (rx2 - rx)/(cpu2 + lpm2 - cpu - lpm));
196  shell_output_str(&sendtest_command, "Radio rx duty cycle ", buf);
197 
198  sprintf(buf, "%lu/%lu = %lu%%",
199  (tx2 - tx),
200  (cpu2 + lpm2 - cpu - lpm),
201  100 * (tx2 - tx)/(cpu2 + lpm2 - cpu - lpm));
202  shell_output_str(&sendtest_command, "Radio tx duty cycle ", buf);
203 
204  PROCESS_END();
205 }
206 /*---------------------------------------------------------------------------*/
207 void
208 shell_sendtest_init(void)
209 {
210  rucb_open(&rucb, SHELL_RIME_CHANNEL_SENDTEST, &rucb_callbacks);
211  shell_register_command(&sendtest_command);
212 }
213 /*---------------------------------------------------------------------------*/
#define PROCESS_WAIT_UNTIL(c)
Wait for a condition to occur.
Definition: process.h:192
void shell_output_str(struct shell_command *c, char *text1, const char *text2)
Output strings from a shell command.
Definition: shell.c:383
#define PROCESS_EXIT()
Exit the currently running process.
Definition: process.h:200
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
#define NULL
The null pointer.
Header file for the Rime stack
int process_post(struct process *p, process_event_t ev, process_data_t data)
Post an asynchronous event.
Definition: process.c:322
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
Definition: process.h:273
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
CCIF clock_time_t clock_time(void)
Get the current clock time.
Definition: clock.c:41
unsigned long shell_strtolong(const char *str, const char **retstr)
Convert a string to a number.
Definition: shell.c:521
void shell_register_command(struct shell_command *c)
Register a command with the shell.
Definition: shell.c:413
Header file for process-related Contiki shell commands
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
#define SHELL_COMMAND(name, command, description, process)
Define a shell command.
Definition: shell.h:219
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82