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