| | |
| | | |
| | | #include "logger.h" |
| | | #include "proc.h" |
| | | #include "ds18b20.h" |
| | | #include "socket.h" |
| | | #include "tlv_pack.h" |
| | | #include "sqlite_cli.h" |
| | | |
| | | #define PROG_VERSION "1.0.0" |
| | | #define RPI_SN "RPI00001" |
| | | |
| | | #define DEF_LOG_FILE "tlv_client.log" |
| | | |
| | | #define DEF_ACK_TIMEOUT 2 /* wait for ACK timeout value */ |
| | | #define DEF_RETRYTIMES 3 /* receive ACK timeout or get NAK, retry to send times */ |
| | | int socket_send_tlv_pack(socket_t *sock, tlv_buf_t *tlv, int timeout, int retry_times); |
| | | |
| | | int packtlv_msg(tlv_buf_t *tlv, char *sn, uint16_t temp, struct tm *tm); |
| | | |
| | | static void banner(void) |
| | | { |
| | |
| | | printf("This program used to connect to server and send RPi's temperature by TLV protocal.\n"); |
| | | |
| | | printf("\nMandatory arguments to long options are mandatory for short options too:\n"); |
| | | printf(" -H[Host ] Specify host server address and port, foramt as \"127.0.0.1:9000\"\n"); |
| | | printf(" -d[debug ] Running in debug mode\n"); |
| | | printf(" -l[level ] Set the log level as [0..%d]\n", LOG_LEVEL_MAX-1); |
| | | printf(" -h[help ] Display this help information\n"); |
| | |
| | | { |
| | | int opt; |
| | | int i = 0; |
| | | //int rv = 0; |
| | | int rv = 0; |
| | | int debug = 0; |
| | | |
| | | char pid_file[64] = { 0 }; /* The file used to record the PID */ |
| | | const char *progname=NULL; |
| | | |
| | | char *host = "127.0.0.1:10086"; |
| | | //char *host = "baidu.com:10086"; |
| | | int log_level = LOG_LEVEL_NRML; |
| | | char *log_file = DEF_LOG_FILE; |
| | | |
| | | logger_t logger; |
| | | socket_t sock; |
| | | tlv_buf_t tlv; |
| | | |
| | | uint16_t temp; |
| | | struct tm *tm; |
| | | time_t cur_time, last_time = 0; |
| | | |
| | | struct option long_options[] = { |
| | | {"Host", required_argument, NULL, 'H'}, |
| | | {"debug", no_argument, NULL, 'd'}, |
| | | {"level", required_argument, NULL, 'l'}, |
| | | {"version", no_argument, NULL, 'v'}, |
| | |
| | | {NULL, 0, NULL, 0} |
| | | }; |
| | | |
| | | memset(&sock, 0, sizeof(sock)); |
| | | memset(&logger, 0, sizeof(logger)); |
| | | |
| | | progname = basename(argv[0]); /* get program name */ |
| | | |
| | | /* parser the command line parameters */ |
| | | while ((opt = getopt_long(argc, argv, "c:dl:vh", long_options, NULL)) != -1) |
| | | while ((opt = getopt_long(argc, argv, "H:dl:vh", long_options, NULL)) != -1) |
| | | { |
| | | switch (opt) |
| | | { |
| | | case 'H': |
| | | host=optarg; |
| | | break; |
| | | |
| | | case 'd': /* set debug running */ |
| | | debug = 1; |
| | |
| | | } |
| | | } |
| | | |
| | | if( !host ) |
| | | { |
| | | printf("ERROR: No argument specify host server address and port, please refer to usage\n"); |
| | | return 1; |
| | | } |
| | | |
| | | /* check program already running or not, if already running then exit, or set running as daemon */ |
| | | snprintf(pid_file, sizeof(pid_file), "/var/run/%s.pid", progname); |
| | | snprintf(pid_file, sizeof(pid_file), "/tmp/%s.pid", progname); |
| | | if( !debug ) |
| | | { |
| | | if( check_daemon_running(pid_file) ) |
| | |
| | | printf("Programe already running, exit now.\n"); |
| | | return -1; |
| | | } |
| | | |
| | | set_daemon_running(pid_file); |
| | | } |
| | | |
| | | record_daemon_pid(pid_file); |
| | | |
| | | /* initial and open logger system */ |
| | | if( logger_init(&logger, log_file, log_level, 512)<0 || logger_open()<0 ) |
| | | { |
| | | printf("ERROR: Initialise logger system failure\n"); |
| | | return -1; |
| | | return 2; |
| | | } |
| | | |
| | | log_nrml("Program start running\n"); |
| | | |
| | | /* install signal proc handler */ |
| | | install_proc_signal(); |
| | | |
| | | log_nrml("Program start running\n"); |
| | | if( clidb_init("./tlv_client.db")< 0) |
| | | { |
| | | log_err("initial sqlite database failure\n"); |
| | | return 3; |
| | | } |
| | | |
| | | last_time = 0; |
| | | |
| | | /* g_signal.stop defined in proc.c, and will be set when catch stop signal */ |
| | | while( !g_signal.stop ) |
| | | { |
| | | log_dbg("Program still running\n"); |
| | | sleep(3); |
| | | time(&cur_time); |
| | | if( cur_time-last_time > 10) |
| | | { |
| | | log_nrml("start sample temperature now.\n"); |
| | | rv = 0; |
| | | temp = 0x1122; |
| | | //rv = ds18b20_get_temperature(&temp); |
| | | if( 0 == rv ) |
| | | { |
| | | /* convert time_t to tm format */ |
| | | tm=localtime(&cur_time); |
| | | last_time = cur_time; |
| | | |
| | | packtlv_msg(&tlv, RPI_SN, temp, tm); |
| | | logger_dump(LOG_LEVEL_DEBUG, tlv.buf, tlv.len); |
| | | |
| | | /* this message need to be transmit and saved in database if send failure */ |
| | | tlv.flag = TLV_FLAG_TX | TLV_FLAG_DB; |
| | | } |
| | | else |
| | | { |
| | | log_err("DS18B20 get temperature failure\n"); |
| | | } |
| | | } |
| | | |
| | | if( SOCK_STAT_CONNECTED != sock.status ) |
| | | { |
| | | if( socket_connect(&sock, -1, host, MODE_NONBLOCK) < 0) |
| | | { |
| | | log_err("connect to server [%s:%d] failure\n", sock.raddr, sock.rport); |
| | | } |
| | | } |
| | | |
| | | if( SOCK_STAT_CONNECTED == sock.status ) |
| | | { |
| | | /* 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; |
| | | } |
| | | } |
| | | |
| | | /* get TLV apcket from database and send it by socket, maxim 5 records */ |
| | | for(i=0; i<5; i++) |
| | | { |
| | | 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); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | if( tlv.flag & TLV_FLAG_DB ) |
| | | { |
| | | clidb_push_tlvpack(&tlv); |
| | | tlv.flag = 0; |
| | | } |
| | | |
| | | sleep(1); |
| | | } |
| | | |
| | | logger_term(); |
| | | clidb_term(); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | /* Packet 3 TLV message together: with SN, temperature, date&time */ |
| | | int packtlv_msg(tlv_buf_t *tlv, char *sn, uint16_t temp, struct tm *tm) |
| | | { |
| | | int rv; |
| | | |
| | | if( !tlv ) |
| | | { |
| | | log_err("Invalid input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | memset(tlv->buf, 0, sizeof(tlv->buf)); /* clear data in buffer */ |
| | | tlv->size = sizeof(tlv->buf); /* buffer free space size */ |
| | | tlv->len = 0; /* buffer data length */ |
| | | |
| | | if( sn ) |
| | | { |
| | | rv = packtlv_sn(&tlv->buf[tlv->len], tlv->size, sn); |
| | | if( rv > 0 ) |
| | | { |
| | | tlv->len += rv; |
| | | tlv->size -= rv; |
| | | } |
| | | } |
| | | |
| | | if( temp ) |
| | | { |
| | | rv = packtlv_temp(&tlv->buf[tlv->len], tlv->size, temp); |
| | | if( rv > 0 ) |
| | | { |
| | | tlv->len += rv; |
| | | tlv->size -= rv; |
| | | } |
| | | } |
| | | |
| | | if( tm ) |
| | | { |
| | | rv = packtlv_time(&tlv->buf[tlv->len], tlv->size, tm); |
| | | if( rv > 0 ) |
| | | { |
| | | tlv->len += rv; |
| | | tlv->size -= rv; |
| | | } |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int socket_send_tlv_pack(socket_t *sock, tlv_buf_t *tlv, int timeout, int retry_times) |
| | | { |
| | | int i; |
| | | 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++) |
| | | { |
| | | if( (rv=socket_send(sock, tlv->buf, tlv->len)) < 0 ) |
| | | { |
| | | log_err("send tlv packet failure, rv=%d\n", rv); |
| | | return -1; |
| | | } |
| | | |
| | | if( (rv=socket_recv(sock, buf, sizeof(buf), timeout)) < 0 ) |
| | | { |
| | | log_err("read ACK from server failure, rv=%d\n", rv); |
| | | return 0; |
| | | } |
| | | |
| | | /* todo: parser ACK from buf */ |
| | | if( ACK ) |
| | | break; |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | |