Contiki 3.x
shell-time.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 brief description of what this file is.
36  * \author
37  * Adam Dunkels <adam@sics.se>
38  */
39 
40 #include "contiki.h"
41 #include "sys/cc.h"
42 #include "shell-time.h"
43 
44 #include "sys/clock.h"
45 #include "net/rime/timesynch.h"
46 
47 #include "lib/random.h"
48 
49 #include <stdio.h>
50 #include <string.h>
51 
52 #define MAX_COMMANDLENGTH 64
53 #define PERIOD_INTERVAL 60
54 
55 /*---------------------------------------------------------------------------*/
56 PROCESS(shell_time_process, "time");
57 SHELL_COMMAND(time_command,
58  "time",
59  "time [seconds]: output time in binary format, or set time in seconds since 1970",
60  &shell_time_process);
61 PROCESS(shell_timestamp_process, "timestamp");
62 SHELL_COMMAND(timestamp_command,
63  "timestamp",
64  "timestamp: prepend a timestamp to data",
65  &shell_timestamp_process);
66 PROCESS(shell_repeat_process, "repeat");
67 PROCESS(shell_repeat_server_process, "repeat server");
68 SHELL_COMMAND(repeat_command,
69  "repeat",
70  "repeat <num> <time> <command>: run a command every <time> seconds",
71  &shell_repeat_process);
72 PROCESS(shell_randwait_process, "randwait");
73 SHELL_COMMAND(randwait_command,
74  "randwait",
75  "randwait <maxtime> <command>: wait for a random time before running a command",
76  &shell_randwait_process);
77 /*---------------------------------------------------------------------------*/
78 PROCESS_THREAD(shell_time_process, ev, data)
79 {
80  struct {
81  uint16_t len;
82  uint16_t clock;
83  uint16_t rtimer;
84  uint16_t timesynch;
85  uint16_t timesynch_authority;
86  uint16_t time[2];
87  } msg;
88  unsigned long newtime;
89  const char *nextptr;
90 
91  PROCESS_BEGIN();
92 
93  if(data != NULL) {
94  newtime = shell_strtolong(data, &nextptr);
95  if(data != nextptr) {
96  shell_set_time(newtime);
97  }
98  }
99 
100  msg.clock = (uint16_t)clock_time();
101  msg.rtimer = (uint16_t)RTIMER_NOW();
102 #if TIMESYNCH_CONF_ENABLED
103  msg.timesynch = timesynch_time();
104  msg.timesynch_authority = timesynch_authority_level();
105 #else
106  msg.timesynch = 0;
107  msg.timesynch_authority = -1;
108 #endif
109  msg.time[0] = (uint16_t)(shell_time() >> 16);
110  msg.time[1] = (uint16_t)(shell_time());
111  msg.len = 6;
112 
113  shell_output(&time_command, &msg, sizeof(msg), "", 0);
114 
115  PROCESS_END();
116 }
117 /*---------------------------------------------------------------------------*/
118 PROCESS_THREAD(shell_timestamp_process, ev, data)
119 {
120  struct shell_input *input;
121  struct msg {
122  uint16_t len;
123  uint16_t time[2];
124  uint16_t timesynch;
125  uint8_t data[MAX_COMMANDLENGTH];
126  } msg;
127 
128  PROCESS_BEGIN();
129 
130  while(1) {
132  input = data;
133  if(input->len1 + input->len2 == 0) {
134  PROCESS_EXIT();
135  }
136 
137  msg.len = 3 + *(uint16_t *)input->data1;
138  msg.time[0] = (uint16_t)(shell_time() >> 16);
139  msg.time[1] = (uint16_t)(shell_time());
140 #if TIMESYNCH_CONF_ENABLED
141  msg.timesynch = timesynch_time();
142 #else /* TIMESYNCH_CONF_ENABLED */
143  msg.timesynch = 0;
144 #endif /* TIMESYNCH_CONF_ENABLED */
145  memcpy(msg.data, input->data1 + 2,
146  input->len1 - 2 > MAX_COMMANDLENGTH?
147  MAX_COMMANDLENGTH: input->len1 - 2);
148 
149  shell_output(&timestamp_command, &msg, 6 + input->len1,
150  input->data2, input->len2);
151  }
152 
153  PROCESS_END();
154 }
155 /*---------------------------------------------------------------------------*/
156 PROCESS_THREAD(shell_repeat_server_process, ev, data)
157 {
158  static char *command;
159  static struct process *started_process;
160  char command_copy[MAX_COMMANDLENGTH];
161 
162  if(ev == shell_event_input) {
163  goto exit;
164  }
165 
166  PROCESS_BEGIN();
167 
168  command = data;
169 
170  PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_CONTINUE &&
171  data == &shell_repeat_process);
172  {
173  strncpy(command_copy, command, MAX_COMMANDLENGTH);
174  shell_start_command(command_copy, (int)strlen(command_copy),
175  &repeat_command, &started_process);
176 
177  if(started_process != NULL &&
178  process_is_running(started_process)) {
179  PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_EXITED &&
180  data == started_process);
181  }
182  }
183 
184  /* PROCESS_WAIT_EVENT_UNTIL(ev == shell_event_input);
185 
186  printf("haha \n");
187  if(repeat_command.child != NULL &&
188  process_is_running(repeat_command.child->process)) {
189  process_post_synch(repeat_command.child->process, ev, data);
190  }*/
191  exit:
192  ;
193  PROCESS_END();
194 }
195 /*---------------------------------------------------------------------------*/
196 static void
197 repeat_print_usage(void)
198 {
199  shell_output_str(&repeat_command, "usage: ", repeat_command.description);
200 }
201 /*---------------------------------------------------------------------------*/
202 PROCESS_THREAD(shell_repeat_process, ev, data)
203 {
204  static int reps, period;
205  static char command[MAX_COMMANDLENGTH];
206  static struct etimer etimer;
207  static int i;
208  const char *args, *next;
209 
210  if(ev == shell_event_input) {
211  struct shell_input *input;
212  input = data;
213  /* printf("shell repeat input %d %d\n", input->len1, input->len2);*/
214  if(input->len1 + input->len2 != 0) {
215  shell_output(&repeat_command, input->data1, input->len1,
216  input->data2, input->len2);
217  }
218  }
219 
220  PROCESS_BEGIN();
221 
222  /* printf("data '%s'\n", data);*/
223 
224  args = data;
225 
226  if(args == NULL) {
227  repeat_print_usage();
228  PROCESS_EXIT();
229  }
230 
231  reps = shell_strtolong(args, &next);
232  if(next == args) {
233  repeat_print_usage();
234  PROCESS_EXIT();
235  }
236 
237  args = next;
238  period = shell_strtolong(args, &next);
239  if(next == args) {
240  repeat_print_usage();
241  PROCESS_EXIT();
242  }
243 
244  args = next;
245 
246  while(*args == ' ') {
247  args++;
248  }
249 
250  strncpy(command, args, MAX_COMMANDLENGTH);
251  if(strlen(command) == 0) {
252  repeat_print_usage();
253  PROCESS_EXIT();
254  }
255 
256  /* printf("repeats %d period %d command '%s'\n",
257  reps, period, command);*/
258 
259  etimer_set(&etimer, CLOCK_SECOND * period);
260  for(i = 0; reps == 0 || i < reps; ++i) {
261 
262  process_start(&shell_repeat_server_process, (void *)command);
263  process_post(&shell_repeat_server_process,
264  PROCESS_EVENT_CONTINUE,
265  &shell_repeat_process);
266  PROCESS_WAIT_UNTIL(ev == PROCESS_EVENT_EXITED &&
267  data == &shell_repeat_server_process);
270  /* PROCESS_PAUSE();
271 
272  for(period_left = period;
273  period_left > 0;
274  period_left -= MIN(PERIOD_INTERVAL, period_left)) {
275  etimer_set(&etimer, CLOCK_SECOND * MIN(PERIOD_INTERVAL, period_left));
276  PROCESS_WAIT_UNTIL(etimer_expired(&etimer));
277  }*/
278  }
279 
280 
281  PROCESS_END();
282 }
283 /*---------------------------------------------------------------------------*/
284 PROCESS_THREAD(shell_randwait_process, ev, data)
285 {
286  static int maxwait;
287  static char command[MAX_COMMANDLENGTH];
288  static struct etimer etimer;
289  static struct process *started_process;
290  const char *args, *next;
291 
292  /* if(ev == shell_event_input) {
293  struct shell_input *input;
294  input = data;
295  printf("shell randwait input %d %d\n", input->len1, input->len2);
296  if(input->len1 + input->len2 != 0) {
297  shell_output(&randwait_command, input->data1, input->len1,
298  input->data2, input->len2);
299  }
300  }*/
301 
302 
303  PROCESS_BEGIN();
304 
305  args = data;
306 
307  if(args == NULL) {
308  shell_output_str(&randwait_command, "usage 0", "");
309  PROCESS_EXIT();
310  }
311 
312  maxwait = shell_strtolong(args, &next);
313  if(next == args) {
314  shell_output_str(&randwait_command, "usage 1", "");
315  PROCESS_EXIT();
316  }
317  args = next;
318 
319  while(*args == ' ') {
320  args++;
321  }
322 
323  strncpy(command, args, MAX_COMMANDLENGTH);
324  if(strlen(command) == 0) {
325  shell_output_str(&repeat_command, "usage 3", "");
326  PROCESS_EXIT();
327  }
328 
329  /* printf("randwait %d command '%s'\n",
330  maxwait, command);*/
331 
332  etimer_set(&etimer, random_rand() % (CLOCK_SECOND * maxwait));
334 
335 /* printf("Starting '%s' child %p (%s)\n", command, randwait_command.child, */
336 /* randwait_command.child == NULL? "null": randwait_command.child->command); */
337 
338  shell_start_command(command, (int)strlen(command),
339  randwait_command.child, &started_process);
340 
341  if(started_process != NULL &&
342  process_is_running(started_process)) {
343  PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_EXITED &&
344  data == started_process);
345  }
346 
347  PROCESS_END();
348 }
349 /*---------------------------------------------------------------------------*/
350 void
351 shell_time_init(void)
352 {
353  shell_register_command(&time_command);
354  shell_register_command(&timestamp_command);
355  shell_register_command(&repeat_command);
356  shell_register_command(&randwait_command);
357 }
358 /*---------------------------------------------------------------------------*/
A brief description of what this file is.
#define RTIMER_NOW()
Get the current clock time.
Definition: rtimer.h:135
rtimer_clock_t timesynch_time(void)
Get the current time-synchronized time.
CCIF clock_time_t clock_time(void)
Get the current clock time.
Definition: clock.c:41
Default definitions of C compiler quirk work-arounds.
void shell_output_str(struct shell_command *c, char *text1, const char *text2)
Output strings from a shell command.
Definition: shell.c:383
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
Definition: etimer.c:177
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
static void input(void)
Process a received 6lowpan packet.
Definition: sicslowpan.c:1503
unsigned long shell_strtolong(const char *str, const char **retstr)
Convert a string to a number.
Definition: shell.c:521
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
Definition: process.h:273
A timer.
Definition: etimer.h:76
#define PROCESS_EXIT()
Exit the currently running process.
Definition: process.h:200
void shell_output(struct shell_command *c, void *data1, int len1, const void *data2, int len2)
Output data from a shell command.
Definition: shell.c:395
int shell_start_command(char *commandline, int commandline_len, struct shell_command *child, struct process **started_process)
Start a shell command from another shell command.
Definition: shell.c:308
#define SHELL_COMMAND(name, command, description, process)
Define a shell command.
Definition: shell.h:219
int shell_event_input
The event number for shell input data.
Definition: shell.c:70
#define PROCESS_WAIT_EVENT_UNTIL(c)
Wait for an event to be posted to the process, with an extra condition.
Definition: process.h:157
int process_post(struct process *p, process_event_t ev, process_data_t data)
Post an asynchronous event.
Definition: process.c:322
void shell_register_command(struct shell_command *c)
Register a command with the shell.
Definition: shell.c:413
int process_is_running(struct process *p)
Check if a process is running.
Definition: process.c:383
#define NULL
The null pointer.
unsigned short random_rand(void)
Generates a new random number using the cc2538 RNG.
Definition: random.c:47
int etimer_expired(struct etimer *et)
Check if an event timer has expired.
Definition: etimer.c:213
Structure for shell input data.
Definition: shell.h:365
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99
#define PROCESS_WAIT_UNTIL(c)
Wait for a condition to occur.
Definition: process.h:192
Representation of a real-time task.
Definition: rtimer.h:86
Header file for a simple time synchronization mechanism
void etimer_reset(struct etimer *et)
Reset an event timer with the same interval as was previously set.
Definition: etimer.c:192
int timesynch_authority_level(void)
Get the current authority level of the time-synchronized time.
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120