listener.c: Support data saving to csv file.

Signed-off-by: likun17 <likun17@xiaomi.com>
This commit is contained in:
likun17 2023-11-28 20:11:10 +08:00 committed by Xiang Xiao
parent b428af2cad
commit 3144c14947

View file

@ -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);