367 lines
10 KiB
C
367 lines
10 KiB
C
/*
|
|
* Copyright (c) 2008, Swedish Institute of Computer Science.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. Neither the name of the Institute nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*
|
|
* This file is part of the Contiki operating system.
|
|
*
|
|
* $Id: shell-time.c,v 1.9 2010/10/20 15:18:49 adamdunkels Exp $
|
|
*/
|
|
|
|
/**
|
|
* \file
|
|
* A brief description of what this file is.
|
|
* \author
|
|
* Adam Dunkels <adam@sics.se>
|
|
*/
|
|
|
|
#include "contiki.h"
|
|
#include "shell-time.h"
|
|
|
|
#include "sys/clock.h"
|
|
#include "net/rime/timesynch.h"
|
|
|
|
#include "lib/random.h"
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#define MAX_COMMANDLENGTH 64
|
|
#define PERIOD_INTERVAL 60
|
|
|
|
#ifndef MIN
|
|
#define MIN(a, b) ((a) < (b)? (a) : (b))
|
|
#endif /* MIN */
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
PROCESS(shell_time_process, "time");
|
|
SHELL_COMMAND(time_command,
|
|
"time",
|
|
"time [seconds]: output time in binary format, or set time in seconds since 1970",
|
|
&shell_time_process);
|
|
PROCESS(shell_timestamp_process, "timestamp");
|
|
SHELL_COMMAND(timestamp_command,
|
|
"timestamp",
|
|
"timestamp: prepend a timestamp to data",
|
|
&shell_timestamp_process);
|
|
PROCESS(shell_repeat_process, "repeat");
|
|
PROCESS(shell_repeat_server_process, "repeat server");
|
|
SHELL_COMMAND(repeat_command,
|
|
"repeat",
|
|
"repeat <num> <time> <command>: run a command every <time> seconds",
|
|
&shell_repeat_process);
|
|
PROCESS(shell_randwait_process, "randwait");
|
|
SHELL_COMMAND(randwait_command,
|
|
"randwait",
|
|
"randwait <maxtime> <command>: wait for a random time before running a command",
|
|
&shell_randwait_process);
|
|
/*---------------------------------------------------------------------------*/
|
|
PROCESS_THREAD(shell_time_process, ev, data)
|
|
{
|
|
struct {
|
|
uint16_t len;
|
|
uint16_t clock;
|
|
uint16_t rtimer;
|
|
uint16_t timesynch;
|
|
uint16_t timesynch_authority;
|
|
uint16_t time[2];
|
|
} msg;
|
|
unsigned long newtime;
|
|
|
|
PROCESS_BEGIN();
|
|
|
|
if(data != NULL) {
|
|
const char *nextptr;
|
|
newtime = shell_strtolong(data, &nextptr);
|
|
if(data != nextptr) {
|
|
shell_set_time(newtime);
|
|
}
|
|
}
|
|
|
|
msg.clock = (uint16_t)clock_time();
|
|
msg.rtimer = (uint16_t)RTIMER_NOW();
|
|
#if TIMESYNCH_CONF_ENABLED
|
|
msg.timesynch = timesynch_time();
|
|
msg.timesynch_authority = timesynch_authority_level();
|
|
#else
|
|
msg.timesynch = 0;
|
|
msg.timesynch_authority = -1;
|
|
#endif
|
|
msg.time[0] = (uint16_t)(shell_time() >> 16);
|
|
msg.time[1] = (uint16_t)(shell_time());
|
|
msg.len = 6;
|
|
|
|
shell_output(&time_command, &msg, sizeof(msg), "", 0);
|
|
|
|
PROCESS_END();
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
PROCESS_THREAD(shell_timestamp_process, ev, data)
|
|
{
|
|
struct msg {
|
|
uint16_t len;
|
|
uint16_t time[2];
|
|
uint16_t timesynch;
|
|
uint8_t data[MAX_COMMANDLENGTH];
|
|
} msg;
|
|
|
|
PROCESS_BEGIN();
|
|
|
|
while(1) {
|
|
struct shell_input *input;
|
|
PROCESS_WAIT_EVENT_UNTIL(ev == shell_event_input);
|
|
input = data;
|
|
if(input->len1 + input->len2 == 0) {
|
|
PROCESS_EXIT();
|
|
}
|
|
|
|
msg.len = 3 + *(uint16_t *)input->data1;
|
|
msg.time[0] = (uint16_t)(shell_time() >> 16);
|
|
msg.time[1] = (uint16_t)(shell_time());
|
|
#if TIMESYNCH_CONF_ENABLED
|
|
msg.timesynch = timesynch_time();
|
|
#else /* TIMESYNCH_CONF_ENABLED */
|
|
msg.timesynch = 0;
|
|
#endif /* TIMESYNCH_CONF_ENABLED */
|
|
memcpy(msg.data, input->data1 + 2,
|
|
input->len1 - 2 > MAX_COMMANDLENGTH?
|
|
MAX_COMMANDLENGTH: input->len1 - 2);
|
|
|
|
shell_output(×tamp_command, &msg, 6 + input->len1,
|
|
input->data2, input->len2);
|
|
}
|
|
|
|
PROCESS_END();
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
PROCESS_THREAD(shell_repeat_server_process, ev, data)
|
|
{
|
|
static char *command;
|
|
char command_copy[MAX_COMMANDLENGTH];
|
|
|
|
if(ev == shell_event_input) {
|
|
goto exit;
|
|
}
|
|
|
|
PROCESS_BEGIN();
|
|
|
|
command = data;
|
|
|
|
PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_CONTINUE &&
|
|
data == &shell_repeat_process);
|
|
{
|
|
int ret;
|
|
static struct process *started_process;
|
|
strncpy(command_copy, command, MAX_COMMANDLENGTH);
|
|
ret = shell_start_command(command_copy, (int)strlen(command_copy),
|
|
&repeat_command, &started_process);
|
|
|
|
if(started_process != NULL &&
|
|
process_is_running(started_process)) {
|
|
PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_EXITED &&
|
|
data == started_process);
|
|
}
|
|
}
|
|
|
|
/* PROCESS_WAIT_EVENT_UNTIL(ev == shell_event_input);
|
|
|
|
printf("haha \n");
|
|
if(repeat_command.child != NULL &&
|
|
process_is_running(repeat_command.child->process)) {
|
|
process_post_synch(repeat_command.child->process, ev, data);
|
|
}*/
|
|
exit:
|
|
;
|
|
PROCESS_END();
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
repeat_print_usage(void)
|
|
{
|
|
shell_output_str(&repeat_command, "usage: ", repeat_command.description);
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
PROCESS_THREAD(shell_repeat_process, ev, data)
|
|
{
|
|
static int reps, period, period_left;
|
|
static char command[MAX_COMMANDLENGTH];
|
|
static struct etimer etimer;
|
|
static int i;
|
|
static clock_time_t start_time;
|
|
const char *args, *next;
|
|
|
|
if(ev == shell_event_input) {
|
|
struct shell_input *input;
|
|
input = data;
|
|
/* printf("shell repeat input %d %d\n", input->len1, input->len2);*/
|
|
if(input->len1 + input->len2 != 0) {
|
|
shell_output(&repeat_command, input->data1, input->len1,
|
|
input->data2, input->len2);
|
|
}
|
|
}
|
|
|
|
PROCESS_BEGIN();
|
|
|
|
/* printf("data '%s'\n", data);*/
|
|
|
|
args = data;
|
|
|
|
if(args == NULL) {
|
|
repeat_print_usage();
|
|
PROCESS_EXIT();
|
|
}
|
|
|
|
reps = shell_strtolong(args, &next);
|
|
if(next == args) {
|
|
repeat_print_usage();
|
|
PROCESS_EXIT();
|
|
}
|
|
|
|
args = next;
|
|
period = shell_strtolong(args, &next);
|
|
if(next == args) {
|
|
repeat_print_usage();
|
|
PROCESS_EXIT();
|
|
}
|
|
|
|
args = next;
|
|
|
|
while(*args == ' ') {
|
|
args++;
|
|
}
|
|
|
|
strncpy(command, args, MAX_COMMANDLENGTH);
|
|
if(strlen(command) == 0) {
|
|
repeat_print_usage();
|
|
PROCESS_EXIT();
|
|
}
|
|
|
|
/* printf("repeats %d period %d command '%s'\n",
|
|
reps, period, command);*/
|
|
|
|
start_time = clock_time();
|
|
etimer_set(&etimer, CLOCK_SECOND * period);
|
|
for(i = 0; reps == 0 || i < reps; ++i) {
|
|
|
|
process_start(&shell_repeat_server_process, command);
|
|
process_post(&shell_repeat_server_process,
|
|
PROCESS_EVENT_CONTINUE,
|
|
&shell_repeat_process);
|
|
PROCESS_WAIT_UNTIL(ev == PROCESS_EVENT_EXITED &&
|
|
data == &shell_repeat_server_process);
|
|
PROCESS_WAIT_UNTIL(etimer_expired(&etimer));
|
|
etimer_reset(&etimer);
|
|
/* PROCESS_PAUSE();
|
|
|
|
for(period_left = period;
|
|
period_left > 0;
|
|
period_left -= MIN(PERIOD_INTERVAL, period_left)) {
|
|
etimer_set(&etimer, CLOCK_SECOND * MIN(PERIOD_INTERVAL, period_left));
|
|
PROCESS_WAIT_UNTIL(etimer_expired(&etimer));
|
|
}*/
|
|
}
|
|
|
|
|
|
PROCESS_END();
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
PROCESS_THREAD(shell_randwait_process, ev, data)
|
|
{
|
|
static int maxwait;
|
|
static char command[MAX_COMMANDLENGTH];
|
|
static struct etimer etimer;
|
|
static struct process *started_process;
|
|
const char *args, *next;
|
|
int ret;
|
|
|
|
/* if(ev == shell_event_input) {
|
|
struct shell_input *input;
|
|
input = data;
|
|
printf("shell randwait input %d %d\n", input->len1, input->len2);
|
|
if(input->len1 + input->len2 != 0) {
|
|
shell_output(&randwait_command, input->data1, input->len1,
|
|
input->data2, input->len2);
|
|
}
|
|
}*/
|
|
|
|
|
|
PROCESS_BEGIN();
|
|
|
|
args = data;
|
|
|
|
if(args == NULL) {
|
|
shell_output_str(&randwait_command, "usage 0", "");
|
|
PROCESS_EXIT();
|
|
}
|
|
|
|
maxwait = shell_strtolong(args, &next);
|
|
if(next == args) {
|
|
shell_output_str(&randwait_command, "usage 1", "");
|
|
PROCESS_EXIT();
|
|
}
|
|
args = next;
|
|
|
|
while(*args == ' ') {
|
|
args++;
|
|
}
|
|
|
|
strncpy(command, args, MAX_COMMANDLENGTH);
|
|
if(strlen(command) == 0) {
|
|
shell_output_str(&repeat_command, "usage 3", "");
|
|
PROCESS_EXIT();
|
|
}
|
|
|
|
/* printf("randwait %d command '%s'\n",
|
|
maxwait, command);*/
|
|
|
|
etimer_set(&etimer, random_rand() % (CLOCK_SECOND * maxwait));
|
|
PROCESS_WAIT_UNTIL(etimer_expired(&etimer));
|
|
|
|
/* printf("Starting '%s' child %p (%s)\n", command, randwait_command.child, */
|
|
/* randwait_command.child == NULL? "null": randwait_command.child->command); */
|
|
|
|
ret = shell_start_command(command, (int)strlen(command),
|
|
randwait_command.child, &started_process);
|
|
|
|
if(started_process != NULL &&
|
|
process_is_running(started_process)) {
|
|
PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_EXITED &&
|
|
data == started_process);
|
|
}
|
|
|
|
PROCESS_END();
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
void
|
|
shell_time_init(void)
|
|
{
|
|
shell_register_command(&time_command);
|
|
shell_register_command(×tamp_command);
|
|
shell_register_command(&repeat_command);
|
|
shell_register_command(&randwait_command);
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|