From cd10eef059e9d9c34c927f3ac53ac43f4a9716c1 Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Sat, 06 Jun 2020 18:20:40 +0800
Subject: [PATCH] add TLV client database save and send support

---
 prj1_tlv/lylib/sqlite_cli.c |  268 ++++++++++++++++++++++++++++++++++++++
 prj1_tlv/lylib/sqlite_cli.h |   60 ++++++++
 prj1_tlv/tlv_client.c       |   81 ++++++-----
 prj1_tlv/makefile           |    2 
 4 files changed, 373 insertions(+), 38 deletions(-)

diff --git a/prj1_tlv/lylib/sqlite_cli.c b/prj1_tlv/lylib/sqlite_cli.c
new file mode 100644
index 0000000..be0bedf
--- /dev/null
+++ b/prj1_tlv/lylib/sqlite_cli.c
@@ -0,0 +1,268 @@
+/********************************************************************************
+ *      Copyright:  (C) 2020 LingYun IoT System Studio
+ *                  All rights reserved.
+ *
+ *       Filename:  sqlite_cli.c
+ *    Description:  This head file is for client to save TLV packet in sqlite.
+ *
+ *        Version:  1.0.0(2020年05月13日)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "2020年05月13日 12时14分23秒"
+ *                 
+ ********************************************************************************/
+
+#include "sqlite_cli.h"
+#include "logger.h"
+
+static sqlite3         *s_clidb = NULL;
+
+/*  description: open or create sqlite database if not exist 
+ *   input args: 
+ *               $db_file: sqlite database file name
+ * return value: <0: failure   0:ok
+ * */
+int clidb_init(const char *db_file)
+{
+    char               sql[256];
+    char              *errmsg = NULL;
+
+    if( !db_file )
+    {
+        log_err("Invalid input arguments\n");
+        return -1;
+    }
+
+    /*+-------------------------------------------------+
+     *| TLV packet database already exist, just open it |
+     *+-------------------------------------------------+*/
+    if( 0==access(db_file, F_OK) )
+    {
+        if( SQLITE_OK != sqlite3_open(db_file, &s_clidb) )
+        {
+            log_err("open TLV packet database file '%s' failure\n", db_file);
+            return -2;
+        }
+        log_nrml("open TLV packet database file '%s' ok\n", db_file);
+        return 0;
+    }
+
+    /*+---------------------------------------------------+
+     *| TLV packet database not exist, create and init it |
+     *+---------------------------------------------------+*/
+
+    if( SQLITE_OK != sqlite3_open(db_file, &s_clidb) ) 
+    {
+        log_err("create TLV packet database file '%s' failure\n", db_file);
+        return -2;
+    }
+
+    /* SQLite continues without syncing as soon as it has handed data off to the operating system */
+    sqlite3_exec(s_clidb, "pragma synchronous = OFF; ", NULL, NULL, NULL);
+
+    /* enable full auto vacuum, Auto increase/decrease  */
+    sqlite3_exec(s_clidb, "pragma auto_vacuum = 2 ; ", NULL, NULL, NULL);
+
+    /*   Create firehost table in the database */
+    strncpy(sql, "create table tlvpack(packet blob);", sizeof(sql));
+    if( SQLITE_OK != sqlite3_exec(s_clidb, sql, NULL, NULL, &errmsg) )
+    {
+        log_err("create table in tlv packet database file '%s' failure: %s\n", db_file, errmsg);
+        sqlite3_free(errmsg); /* free errmsg  */
+        sqlite3_close(s_clidb);   /* close databse */
+        unlink(db_file);      /* remove database file */
+    }
+
+    log_nrml("create and init TLV packet database file '%s' ok\n", db_file);
+    return 0;
+}
+
+
+/*  description: close sqlite database handler
+ * return value: none
+ */
+void clidb_term(void)
+{
+    log_warn("close tlv client sqlite database now\n");
+    sqlite3_close(s_clidb);
+
+    return ;
+
+}
+
+
+/*  description: push TLV packet into database
+ *   input args: 
+ *               $pack:  tlv packet pointer 
+ * return value: <0: failure   0:ok
+ */
+int clidb_push_tlvpack(tlv_buf_t *pack)
+{
+    int                rv = 0;
+    char              *errmsg = NULL;
+    sqlite3_stmt      *stat = NULL;
+
+    if( !pack )
+    {
+        log_err("Invalid input arguments\n");
+        return -1;
+    }
+
+    if( ! s_clidb )
+    {
+        log_err("client tlv packet database not opened\n");
+        return -2;
+    }
+
+    rv = sqlite3_prepare_v2(s_clidb, "insert into tlvpack(packet) values(?)", -1, &stat, NULL);
+    if(SQLITE_OK!=rv || !stat)
+    {
+        log_err("blob add sqlite3_prepare_v2 failure\n");
+        rv = -2;
+        goto OUT;
+    }
+
+    if( SQLITE_OK != sqlite3_bind_blob(stat, 1, pack, sizeof(*pack), NULL) )
+    {
+        log_err("blob add sqlite3_bind_blob failure\n");
+        rv = -3;
+        goto OUT;
+    }
+
+    rv = sqlite3_step(stat);
+    if( SQLITE_DONE!=rv && SQLITE_ROW!=rv )
+    {
+        log_err("blob add sqlite3_step failure\n");
+        rv = -4;
+        goto OUT;
+    }
+
+OUT:
+    sqlite3_finalize(stat);
+
+    if( rv < 0 )
+        log_nrml("add new TLV packet report data into database failure, rv=%d\n", rv);
+    else
+        log_nrml("add new TLV packet report data into database ok\n");
+
+    return rv;
+}
+
+
+/*  description: push TLV packet into database
+ *   input args: 
+ *               $pack:  tlv packet pointer 
+ *               $id:    item ID pointer, which can be used as key when remove
+ * return value: <0: failure   0:ok
+ */
+int clidb_pop_tlvpack(tlv_buf_t *pack, int *id)
+{
+    int                      rv = 0;
+    sqlite3_stmt             *stat = NULL;
+    const tlv_buf_t          *blob_ptr;
+
+    if( !id || ! pack )
+    {
+        log_err("invalid input arguments\n");
+        return -1;
+    }
+
+    if( ! s_clidb )
+    {
+        log_err("client tlv packet database not opened\n");
+        return -2;
+    }
+
+    /* Only query the first packet record */ 
+    rv = sqlite3_prepare_v2(s_clidb, "select rowid,packet from tlvpack limit 0,1;", -1, &stat, NULL); 
+    if(SQLITE_OK!=rv || !stat) 
+    {
+        log_err("firehost sqlite3_prepare_v2 failure\n");
+        rv = -3;
+        goto out;
+    }
+
+    rv = sqlite3_step(stat);
+    if( SQLITE_DONE!=rv && SQLITE_ROW!=rv )
+    {
+        log_err("firehost sqlite3_step failure\n");
+        rv = -5;
+        goto out;
+    }
+
+    /* 2rd argument<0> means first segement is rowid */
+    *id = sqlite3_column_int(stat, 0);
+    if(*id <= 0)
+    {
+        rv = 0;
+        goto out;
+    }
+
+    /* 2rd argument<1> means first segement is packet  */
+    blob_ptr = sqlite3_column_blob(stat, 1);
+    if( !blob_ptr )
+    {
+        rv = 0;
+        goto out;
+    }
+
+    memcpy(pack, blob_ptr, sizeof(*pack));
+
+    log_trace("Read TLV packet from database:\n");
+    logger_dump(LOG_LEVEL_TRACE, (char *)pack->buf, pack->len);
+
+    rv = 1;
+
+out:
+    sqlite3_finalize(stat);
+
+    if( rv < 0)
+        log_err("query TLV packet from database failure, rv=%d\n", rv);
+    else if( rv > 0 )
+        log_nrml("query TLV packet from database ok\n");
+
+    return rv;
+
+}
+
+
+/*  description: remove sepcified TLV packet from database
+ *   input args: 
+ *               $id:    remove item ID
+ * return value: <0: failure   0:ok
+ */
+int clidb_del_tlvpack(int id)
+{
+    char                     sql[SQL_COMMAND_LEN];                                                                                  
+    char                    *errmsg = NULL; 
+
+    if( !id )
+    {
+        log_err("invalid input arguments\n");
+        return -1;
+    }
+
+    if( ! s_clidb )
+    {
+        log_err("client tlv packet database not opened\n");
+        return -2;
+    }
+
+    /*  remove packet from db */
+    memset(sql, 0, sizeof(sql));
+    snprintf(sql, sizeof(sql), "delete from tlvpack where rowid=%d;", id);                                        
+    if( SQLITE_OK != sqlite3_exec(s_clidb, sql, NULL, 0, &errmsg) ) 
+    { 
+        log_err("delete TLV packet ID[%d] from database failure: %s\n", id, errmsg);
+        sqlite3_free(errmsg);
+        return -2;
+    }
+    log_warn("delete TLV packet ID[%d] from database ok\n", id);
+
+    /*  Vacuum the database */
+    sqlite3_exec(s_clidb, "VACUUM;", NULL, 0, NULL);
+
+    return 0;
+}
+
+
+
diff --git a/prj1_tlv/lylib/sqlite_cli.h b/prj1_tlv/lylib/sqlite_cli.h
new file mode 100644
index 0000000..9476752
--- /dev/null
+++ b/prj1_tlv/lylib/sqlite_cli.h
@@ -0,0 +1,60 @@
+/********************************************************************************
+ *      Copyright:  (C) 2020 LingYun IoT System Studio
+ *                  All rights reserved.
+ *
+ *       Filename:  sqlite_cli.h
+ *    Description:  This head file is for client to save TLV packet in sqlite.
+ *
+ *        Version:  1.0.0(2020年05月13日)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "2020年05月13日 12时14分23秒"
+ *                 
+ ********************************************************************************/
+#ifndef  _SQLITE_CLI_H_
+#define  _SQLITE_CLI_H_
+
+#include "sqlite3.h"
+#include "tlv_pack.h"
+
+#define SQL_COMMAND_LEN        256
+
+/*  description: open or create sqlite database if not exist 
+ *   input args:  
+ *              $db_file: sqlite database file name
+ * return value: <0: failure   0:ok
+ * */
+extern int clidb_init(const char *db_file);
+
+
+/*  description: close sqlite database handler
+ * return value: none
+ */
+extern void clidb_term(void);
+
+
+/*  description: push TLV packet into database
+ *   input args:
+ *               $pack:  tlv packet pointer 
+ * return value: <0: failure   0:ok
+ */
+extern int clidb_push_tlvpack(tlv_buf_t *pack);
+
+
+/*  description: pop one TLV packet from database
+ *   input args: 
+ *               $pack:  tlv packet pointer 
+ *               $id:    item ID pointer, which can be used as key when remove
+ * return value: <0: failure   0:ok
+ */
+extern int clidb_pop_tlvpack(tlv_buf_t *pack, int *id);
+
+
+/*  description: remove sepcified TLV packet from database
+ *   input args: 
+ *               $id:    remove item ID
+ * return value: <0: failure   0:ok
+ */
+extern int clidb_del_tlvpack(int id);
+
+
+#endif   /* ----- #ifndef _SQLITE_CLI_H_  ----- */
diff --git a/prj1_tlv/makefile b/prj1_tlv/makefile
index 1246642..53bd854 100644
--- a/prj1_tlv/makefile
+++ b/prj1_tlv/makefile
@@ -17,7 +17,7 @@
 
 # Linker flags
 LDFLAGS=-L${SUBDIR1} -l${SUBDIR1} 
-LDFLAGS+=-lpthread
+LDFLAGS+=-lpthread -lsqlite3
 
 
 all: banner lib${SUBDIR1}
diff --git a/prj1_tlv/tlv_client.c b/prj1_tlv/tlv_client.c
index d3a307c..a8108bc 100644
--- a/prj1_tlv/tlv_client.c
+++ b/prj1_tlv/tlv_client.c
@@ -22,6 +22,7 @@
 #include "ds18b20.h"
 #include "socket.h"
 #include "tlv_pack.h"
+#include "sqlite_cli.h"
 
 #define PROG_VERSION     "1.0.0"
 #define RPI_SN           "RPI00001"
@@ -130,15 +131,11 @@
         } 
     }
 
-#if 1
     if( !host )
     {
         printf("ERROR: No argument specify host server address and port, please refer to usage\n");
-    //    return 1;
+        return 1;
     }
-
-
-#endif
 
     /* check program already running or not, if already running then exit, or set running as daemon */
     snprintf(pid_file, sizeof(pid_file), "/tmp/%s.pid", progname);
@@ -162,18 +159,16 @@
         return 2;
     }
 
+    log_nrml("Program start running\n");
+
     /* install signal proc handler */
     install_proc_signal();
 
-    log_nrml("Program start running\n");
-
-#if 0
-    if( initial_db(&sqldb, db_file) < 0)
+    if( clidb_init("./tlv_client.db")< 0) 
     {
-        log_err("initialise sqlite database failure\n");
+        log_err("initial sqlite database failure\n");
         return 3;
     }
-#endif
 
     last_time = 0;
 
@@ -181,7 +176,7 @@
     while( !g_signal.stop )
     {
         time(&cur_time);
-        if( cur_time-last_time > 3)
+        if( cur_time-last_time > 10)
         {
             log_nrml("start sample temperature now.\n");
             rv = 0;
@@ -213,44 +208,49 @@
             }
         }
 
-        if( (tlv.flag&TLV_FLAG_TX) && SOCK_STAT_CONNECTED==sock.status )
+        if( SOCK_STAT_CONNECTED == sock.status )
         {
-            if(0 == socket_send_tlv_pack(&sock, &tlv, DEF_ACK_TIMEOUT, DEF_RETRYTIMES) )
-            {
-                tlv.flag = 0;
+            /* send current new sample TLV packet  */
+            if( tlv.flag&TLV_FLAG_TX )
+            { 
+                if(0 == socket_send_tlv_pack(&sock, &tlv, DEF_ACK_TIMEOUT, DEF_RETRYTIMES) ) 
+                {
+                    tlv.flag = 0;
+                }
             }
-        }
 
-#if 0
-        /* need to send TLV packet in database now  */ 
-        for(i=0; i<5; i++)
-        {
-            /* get a TLV record from DB and send it by socket  */ 
-            /* rv<0: Erorr  rv=0: No record  >0: record count  */
-            rv = get_db_tlv_pack(sqldb, tlv, size) ; 
-            if( rv <= 0)
-                break;
-
-            if( 0 == socket_send_tlv_pack() ) 
+            /* get TLV apcket from database and send it by socket, maxim 5 records  */ 
+            for(i=0; i<5; i++)
             {
-                /* delete the record from DB */
-                del_db_tlv_pack();
+                int            id;
+                tlv_buf_t      tmp;
+
+                if( clidb_pop_tlvpack(&tmp, &id) <= 0 ) 
+                {
+                    break;
+                }
+
+                /* send the TLV packet from database */
+                if(0 == socket_send_tlv_pack(&sock, &tmp, DEF_ACK_TIMEOUT, DEF_RETRYTIMES) ) 
+                {
+                    /* delete the record from DB */
+                    clidb_del_tlvpack(id);
+                }
             }
+
         }
 
-SAVE_DB:
-        if( tlv_buf.flag & TLV_FLAG_DB)
+        if( tlv.flag & TLV_FLAG_DB )
         {
-            record_db_tlv(sqldb, tlv_buf, tlv_len);
+            clidb_push_tlvpack(&tlv);
+            tlv.flag = 0;
         }
-#endif
 
         sleep(1);
     }
 
     logger_term();
-
-    //db_term();
+    clidb_term();
 
     return 0;
 } 
@@ -309,6 +309,9 @@
     int            rv = 0; 
     char           buf[128];
 
+    if( sock->status != SOCK_STAT_CONNECTED )
+        return -1;
+
     log_info("start to send tlv packet from socket now\n");
 
     for(i=0; i<retry_times; i++)
@@ -322,8 +325,12 @@
         if( (rv=socket_recv(sock, buf, sizeof(buf), timeout)) < 0 )
         {
             log_err("read ACK from server failure, rv=%d\n", rv);
-            return -2;
+            return 0;
         }
+
+        /* todo: parser ACK from buf  */
+        if( ACK )
+            break;
     }
 
     return 0;

--
Gitblit v1.9.1