/********************************************************************************* * Copyright: (C) 2020 LingYun IoT System Studio * All rights reserved. * * Filename: tlv_client.c * Description: This is a socket client program used to report RPi's temperature * to socket server by TLV protocal. * * Version: 1.0.0(2020年04月14日) * Author: Guo Wenxue * ChangeLog: 1, Release initial version on "2020年04月14日 00时52分56秒" * ********************************************************************************/ #include #include #include #include #include #include "logger.h" #include "proc.h" #include "ds18b20.h" #include "socket.h" #include "tlv_pack.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("Version %s build on %s %s\n", PROG_VERSION, __DATE__, __TIME__); printf("Copyright (C) 2020 LingYun IoT System Studio.\n\n"); return ; } static void program_usage(const char *progname) { printf("Usage: %s [OPTION]...\n", progname); 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"); printf(" -v[version ] Display the program version\n"); printf("\n"); banner(); return ; } int main (int argc, char *argv[]) { int opt; int i = 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'}, {"help", no_argument, NULL, 'h'}, {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, "H:dl:vh", long_options, NULL)) != -1) { switch (opt) { case 'H': host=optarg; break; case 'd': /* set debug running */ debug = 1; log_level= LOG_LEVEL_DEBUG; log_file = NULL; /* use standard output */ break; case 'l': /* set the log level */ i = atoi(optarg); log_level = i>LOG_LEVEL_MAX ? LOG_LEVEL_MAX-1 : i; logger.flag |= FLAG_LOGGER_LEVEL_OPT; break; case 'v': /* print software version */ banner(); return EXIT_SUCCESS; case 'h': /* print help information */ program_usage(progname); return 0; default: break; } } #if 1 if( !host ) { printf("ERROR: No argument specify host server address and port, please refer to usage\n"); // 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); 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 2; } /* install signal proc handler */ install_proc_signal(); log_nrml("Program start running\n"); #if 0 if( initial_db(&sqldb, db_file) < 0) { log_err("initialise sqlite database failure\n"); return 3; } #endif last_time = 0; /* g_signal.stop defined in proc.c, and will be set when catch stop signal */ while( !g_signal.stop ) { time(&cur_time); if( cur_time-last_time > 3) { 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( (tlv.flag&TLV_FLAG_TX) && SOCK_STAT_CONNECTED==sock.status ) { 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() ) { /* delete the record from DB */ del_db_tlv_pack(); } } SAVE_DB: if( tlv_buf.flag & TLV_FLAG_DB) { record_db_tlv(sqldb, tlv_buf, tlv_len); } #endif sleep(1); } logger_term(); //db_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]; log_info("start to send tlv packet from socket now\n"); for(i=0; ibuf, 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 -2; } } return 0; }