This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
commit 3144c149479dd3f8310f86f9ad9bda307fe69a7c Author: likun17 <[email protected]> AuthorDate: Tue Nov 28 20:11:10 2023 +0800 listener.c: Support data saving to csv file. Signed-off-by: likun17 <[email protected]> --- system/uorb/listener.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 144 insertions(+), 9 deletions(-) diff --git a/system/uorb/listener.c b/system/uorb/listener.c index 4bbb1dbc4..6f4af7808 100644 --- a/system/uorb/listener.c +++ b/system/uorb/listener.c @@ -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) + { + if (listener_record(tmp->object.meta, fds[i].fd, + tmp->file) < 0) + { + uorberr("Listener record %s data failed!", + tmp->object.meta->o_name); + } + } + else { - uorberr("Listener callback failed"); + 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);
