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

Reply via email to