mirror of
https://github.com/apache/nuttx-apps.git
synced 2026-08-01 20:29:00 +00:00
listener.c: Support data saving to csv file.
Signed-off-by: likun17 <likun17@xiaomi.com>
This commit is contained in:
parent
b428af2cad
commit
3144c14947
1 changed files with 144 additions and 9 deletions
|
|
@ -32,6 +32,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
|
@ -44,6 +45,7 @@
|
|||
|
||||
#define ORB_MAX_PRINT_NAME 32
|
||||
#define ORB_TOP_WAIT_TIME 1000
|
||||
#define ORB_DATA_DIR "/data/uorb/"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
|
|
@ -55,6 +57,7 @@ struct listen_object_s
|
|||
struct orb_object object; /* Object id */
|
||||
orb_abstime timestamp; /* Time of lastest generation */
|
||||
unsigned long generation; /* Latest generation */
|
||||
FAR FILE *file;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -71,12 +74,15 @@ static int listener_generate_object_list(FAR struct list_node *objlist,
|
|||
static int listener_print(FAR const struct orb_metadata *meta, int fd);
|
||||
static void listener_monitor(FAR struct list_node *objlist, int nb_objects,
|
||||
float topic_rate, int topic_latency,
|
||||
int nb_msgs, int timeout);
|
||||
int nb_msgs, int timeout, bool record);
|
||||
static int listener_update(FAR struct list_node *objlist,
|
||||
FAR struct orb_object *object);
|
||||
static void listener_top(FAR struct list_node *objlist,
|
||||
FAR const char *filter,
|
||||
bool only_once);
|
||||
static int listener_create_dir(FAR char *dir, size_t size);
|
||||
static int listener_record(FAR const struct orb_metadata *meta, int fd,
|
||||
FAR FILE *file);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
|
|
@ -114,6 +120,7 @@ listener <command> [arguments...]\n\
|
|||
Commands:\n\
|
||||
\t<topics_name> Topic name. Multi name are separated by ','\n\
|
||||
\t[-h ] Listener commands help\n\
|
||||
\t[-f ] Record uorb data to file\n\
|
||||
\t[-n <val> ] Number of messages, default: 0\n\
|
||||
\t[-r <val> ] Subscription rate (unlimited if 0), default: 0\n\
|
||||
\t[-b <val> ] Subscription maximum report latency in us(unlimited if 0),\n\
|
||||
|
|
@ -124,6 +131,45 @@ listener <command> [arguments...]\n\
|
|||
");
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: creat_record_path
|
||||
*
|
||||
* Input Parameters:
|
||||
* path The path of the storage file.
|
||||
*
|
||||
* Description:
|
||||
* Create the path where files are stored by default.
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 on success, otherwise negative errno.
|
||||
****************************************************************************/
|
||||
|
||||
static int listener_create_dir(FAR char *dir, size_t size)
|
||||
{
|
||||
FAR struct tm *tm_info;
|
||||
time_t t;
|
||||
|
||||
time(&t);
|
||||
tm_info = gmtime(&t);
|
||||
|
||||
if (0 == strftime(dir, size, ORB_DATA_DIR "%Y%m%d%H%M%S/", tm_info))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (access(ORB_DATA_DIR, F_OK) != 0)
|
||||
{
|
||||
mkdir(ORB_DATA_DIR, 0777);
|
||||
}
|
||||
|
||||
if (access(dir, F_OK) != 0)
|
||||
{
|
||||
mkdir(dir, 0777);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: listener_get_state
|
||||
*
|
||||
|
|
@ -187,6 +233,7 @@ static int listener_add_object(FAR struct list_node *objlist,
|
|||
tmp->object.instance = object->instance;
|
||||
tmp->timestamp = orb_absolute_time();
|
||||
tmp->generation = ret < 0 ? 0 : state.generation;
|
||||
tmp->file = NULL;
|
||||
list_add_tail(objlist, &tmp->node);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -464,9 +511,41 @@ static int listener_print(FAR const struct orb_metadata *meta, int fd)
|
|||
|
||||
ret = orb_copy(meta, fd, buffer);
|
||||
#ifdef CONFIG_DEBUG_UORB
|
||||
if (ret == OK && meta->o_cb != NULL)
|
||||
if (ret == OK && meta->o_format != NULL)
|
||||
{
|
||||
meta->o_cb(meta, buffer);
|
||||
orb_info(meta->o_format, meta->o_name, buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: listener_record
|
||||
*
|
||||
* Description:
|
||||
* record topic data.
|
||||
*
|
||||
* Input Parameters:
|
||||
* meta The uORB metadata.
|
||||
* fd Subscriber handle.
|
||||
* file Save file handle.
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 on success copy, otherwise -1
|
||||
****************************************************************************/
|
||||
|
||||
static int listener_record(FAR const struct orb_metadata *meta, int fd,
|
||||
FAR FILE *file)
|
||||
{
|
||||
char buffer[meta->o_size];
|
||||
int ret;
|
||||
|
||||
ret = orb_copy(meta, fd, buffer);
|
||||
#ifdef CONFIG_DEBUG_UORB
|
||||
if (ret == OK && meta->o_format != NULL)
|
||||
{
|
||||
ret = orb_fprintf(file, meta->o_format, buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -493,15 +572,17 @@ static int listener_print(FAR const struct orb_metadata *meta, int fd)
|
|||
|
||||
static void listener_monitor(FAR struct list_node *objlist, int nb_objects,
|
||||
float topic_rate, int topic_latency,
|
||||
int nb_msgs, int timeout)
|
||||
int nb_msgs, int timeout, bool record)
|
||||
{
|
||||
FAR struct pollfd *fds;
|
||||
char path[PATH_MAX];
|
||||
FAR int *recv_msgs;
|
||||
float interval = topic_rate ? (1000000 / topic_rate) : 0;
|
||||
int nb_recv_msgs = 0;
|
||||
FAR char *dir;
|
||||
int i = 0;
|
||||
|
||||
struct listen_object_s *tmp;
|
||||
FAR struct listen_object_s *tmp;
|
||||
|
||||
fds = malloc(nb_objects * sizeof(struct pollfd));
|
||||
if (!fds)
|
||||
|
|
@ -548,6 +629,34 @@ static void listener_monitor(FAR struct list_node *objlist, int nb_objects,
|
|||
i++;
|
||||
}
|
||||
|
||||
if (record)
|
||||
{
|
||||
listener_create_dir(path, sizeof(path));
|
||||
dir = path + strlen(path);
|
||||
|
||||
list_for_every_entry(objlist, tmp, struct listen_object_s, node)
|
||||
{
|
||||
sprintf(dir, "%s%d.csv", tmp->object.meta->o_name,
|
||||
tmp->object.instance);
|
||||
tmp->file = fopen(path, "w");
|
||||
if (tmp->file != NULL)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_UORB
|
||||
fprintf(tmp->file, "%s,%d,%d,%s\n", tmp->object.meta->o_format,
|
||||
tmp->object.meta->o_size, tmp->object.instance,
|
||||
tmp->object.meta->o_name);
|
||||
#endif
|
||||
|
||||
uorbinfo_raw("creat file:[%s]", path);
|
||||
}
|
||||
else
|
||||
{
|
||||
uorbinfo_raw("file creat failed!meta name:%s,instance:%d",
|
||||
tmp->object.meta->o_name, tmp->object.instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop poll and print recieved messages */
|
||||
|
||||
while ((!nb_msgs || nb_recv_msgs < nb_msgs) && !g_should_exit)
|
||||
|
|
@ -561,9 +670,22 @@ static void listener_monitor(FAR struct list_node *objlist, int nb_objects,
|
|||
{
|
||||
nb_recv_msgs++;
|
||||
recv_msgs[i]++;
|
||||
if (listener_print(tmp->object.meta, fds[i].fd) != 0)
|
||||
|
||||
if (tmp->file != NULL)
|
||||
{
|
||||
uorberr("Listener callback failed");
|
||||
if (listener_record(tmp->object.meta, fds[i].fd,
|
||||
tmp->file) < 0)
|
||||
{
|
||||
uorberr("Listener record %s data failed!",
|
||||
tmp->object.meta->o_name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (listener_print(tmp->object.meta, fds[i].fd) != 0)
|
||||
{
|
||||
uorberr("Listener callback failed");
|
||||
}
|
||||
}
|
||||
|
||||
if (nb_msgs && nb_recv_msgs >= nb_msgs)
|
||||
|
|
@ -604,6 +726,12 @@ static void listener_monitor(FAR struct list_node *objlist, int nb_objects,
|
|||
recv_msgs[i]);
|
||||
}
|
||||
|
||||
if (tmp->file != NULL)
|
||||
{
|
||||
fflush(tmp->file);
|
||||
fclose(tmp->file);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
|
|
@ -699,6 +827,7 @@ int main(int argc, FAR char *argv[])
|
|||
int nb_msgs = 0;
|
||||
int timeout = 5;
|
||||
bool top = false;
|
||||
bool record = false;
|
||||
bool only_once = false;
|
||||
FAR char *filter = NULL;
|
||||
int ret;
|
||||
|
|
@ -712,7 +841,7 @@ int main(int argc, FAR char *argv[])
|
|||
|
||||
/* Pasrse Argument */
|
||||
|
||||
while ((ch = getopt(argc, argv, "r:b:n:t:Tlh")) != EOF)
|
||||
while ((ch = getopt(argc, argv, "r:b:n:t:Tflh")) != EOF)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
|
|
@ -748,6 +877,12 @@ int main(int argc, FAR char *argv[])
|
|||
}
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_DEBUG_UORB
|
||||
case 'f':
|
||||
record = true;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 'T':
|
||||
top = true;
|
||||
break;
|
||||
|
|
@ -791,7 +926,7 @@ int main(int argc, FAR char *argv[])
|
|||
}
|
||||
|
||||
listener_monitor(&objlist, ret, topic_rate, topic_latency,
|
||||
nb_msgs, timeout);
|
||||
nb_msgs, timeout, record);
|
||||
}
|
||||
|
||||
listener_delete_object_list(&objlist);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue