| /*********************************************************************************        | 
|  * Copyright:  (C) 2018 LingYun IoT Studio   | 
|  *                  All rights reserved.   | 
|  *       Filename:  iotd_main.c | 
|  *    Description:  This file is iotd (Internet of Things daemon) program main() entry point,  | 
|  * | 
|  *        Version:  1.0.0(2018/11/19) | 
|  *         Author:  Guo Wenxue <guowenxue@aliyun.com> | 
|  *      ChangeLog:  1, Release initial version on "2018/11/19 22:05:56 CST" | 
|  *                  | 
|  ********************************************************************************/ | 
| #include <stdio.h> | 
| #include <getopt.h> | 
| #include <sys/types.h> | 
| #include <sys/wait.h> | 
| #include <signal.h> | 
| #include <linux/input.h> | 
| #include <linux/kd.h> | 
| #include <linux/keyboard.h> | 
| #include <linux/watchdog.h> | 
| #include <libgen.h> | 
| #include <sys/types.h> | 
| #include <sys/stat.h> | 
| #include <fcntl.h> | 
|   | 
| #include "cp_proc.h" | 
| #include "iotd_conf.h" | 
|   | 
|   | 
| void *watchdog_worker(void *arg); | 
|   | 
|   | 
| typedef struct iotd_ctx_s  | 
| { | 
|     iotd_conf_t     conf; | 
| } iotd_ctx_t;   | 
|   | 
|   | 
| void banner(const char *program) | 
| { | 
|     printf("Copyright (C) 2018 LingYun IoT Studio.\n"); | 
|     printf("%s Version 1.0.0 Build on @ %s %s\n", program, __DATE__, __TIME__); | 
| } | 
|   | 
| static void program_usage(const char *progname) | 
| { | 
|     banner(progname);  | 
|      | 
|     printf("Usage: %s [OPTION]...\n", progname);  | 
|     printf(" %s is a daemon program running on the device, which used to \n", progname);  | 
|     printf("receive date from serial and transfer the data to remote server by socket\n");  | 
|   | 
|     printf("\nMandatory arguments to long options are mandatory for short options too:\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"); | 
|   | 
|     return; | 
| } | 
|   | 
| int main(int argc, char **argv) | 
| { | 
|     int                   opt; | 
|     int                   i = 0; | 
|     int                   rv = 0; | 
|     int                   debug = 0; | 
|     const char           *progname=NULL; | 
|   | 
|     char                  pid_file[64] = { 0 }; /*  The file used to record the PID */ | 
|     char                 *conf_file = "etc/iotd.conf"; | 
|     char                 *log_file = DEF_LOG_FILE; | 
|     int                   log_level = DEF_LOG_LEVEL; | 
|     iotd_ctx_t            iotd_ctx; | 
|   | 
| //    pthread_t             tid; | 
|     iotd_conf_t          *conf;  | 
|     logger_t             *logger; | 
|   | 
|     memset(&iotd_ctx, 0, sizeof(iotd_ctx)); | 
|     conf = &iotd_ctx.conf; | 
|     logger = &conf->logger; | 
|   | 
|     struct option long_options[] = { | 
|         {"conf", required_argument, NULL, 'c'}, | 
|         {"debug", no_argument, NULL, 'd'}, | 
|         {"level", required_argument, NULL, 'l'}, | 
|         {"version", no_argument, NULL, 'v'}, | 
|         {"help", no_argument, NULL, 'h'}, | 
|         {NULL, 0, NULL, 0} | 
|     }; | 
|   | 
|     progname = basename(argv[0]); | 
|     /*  Parser the command line parameters */ | 
|     while ((opt = getopt_long(argc, argv, "c:dl:vh", long_options, NULL)) != -1) | 
|     { | 
|         switch (opt) | 
|         { | 
|             case 'c':  /*  Set configure file */ | 
|                 conf_file = optarg; | 
|                 break; | 
|   | 
|             case 'd': /*  Set debug running */ | 
|                 debug = 1; | 
|                 log_file = DBG_LOG_FILE; | 
|                 break; | 
|   | 
|             case 'l': /*  Set the log level */ | 
|                 i = atoi(optarg); | 
|                 log_level = i>LOG_LEVEL_MAX ? LOG_LEVEL_MAX-1 : i; | 
|                 logger->flag |= CP_LOGGER_LEVEL_OPT; | 
|                 break; | 
|   | 
|             case 'v':  /*  Get software version */ | 
|                 banner(progname); /*  Defined in version.h */ | 
|                 return EXIT_SUCCESS; | 
|   | 
|             case 'h':  /*  Get help information */ | 
|                 program_usage(progname); | 
|                 return 0; | 
|   | 
|             default: | 
|                 break; | 
|         } /*   end of "switch(opt)" */ | 
|     } | 
|   | 
|     snprintf(pid_file, sizeof(pid_file), "/var/run/%s.pid", progname); | 
|     if( !debug ) | 
|     { | 
|         if( check_daemon_running(pid_file) ) | 
|         { | 
|             printf("Programe already running, exit now.\n"); | 
|             return -1; | 
|         } | 
|     } | 
|   | 
|     if ( !cp_log_init(logger, log_file, log_level, 1024/*KB*/) || cp_log_open() ) | 
|     { | 
|         printf("Logger initialize failure with file: %s\n", logger->file); | 
|         return -1; | 
|     } | 
|     log_nrml("Init default logger file \"%s\" ok\n", log_file); | 
|   | 
|     /*  Parser configure file and start the initialize log */ | 
|     rv = parser_iotd_conf(conf_file, conf); | 
|     if(rv < 0) | 
|     { | 
|         log_fatal("Parse configure file %s failure, rv=%d\n", conf_file, rv); | 
|         goto CleanUp; | 
|     } | 
|   | 
|     /* If configure file logger is not same as default one, then reopen the logger system */ | 
|     if(  !debug && strncmp(logger->file, DEF_LOG_FILE, strlen(DEF_LOG_FILE)) ) | 
|     { | 
|         log_warn("Reinitiase logger to [%s]\n", logger->file); | 
|         cp_log_close(); | 
|   | 
|         if( cp_log_open() ) | 
|         { | 
|             printf("Logger reopen failure with file: %s\n", logger->file); | 
|             return -1; | 
|         } | 
|     } | 
|   | 
|     if( !debug ) | 
|     { | 
|         if( set_daemon_running(pid_file) ) | 
|         { | 
|             log_fatal("Set program \"%s\" running as daemon failure.\n", progname); | 
|             goto CleanUp; | 
|         } | 
|     } | 
|   | 
|     cp_install_proc_signal(); | 
|   | 
|     /* start watchdog thread worker  */ | 
|     //thread_start(&tid, watchdog_worker, NULL); | 
|   | 
|     /* Start MQTT thread worker */ | 
|     if( conf->mqtt_conf.enable ) | 
|     { | 
|         log_nrml("start MQTT publish process thread\n");  | 
|         //thread_start(&tid, mqtt_worker, (void *)&iotd_ctx ); | 
|     } | 
|   | 
|     /* Start NB-IoT thread worker */ | 
|     if( conf->nbiot_conf.enable ) | 
|     { | 
|         log_nrml("start NB-IoT process thread\n"); | 
|         //thread_start(&tid, nbiot_worker, (void *)&iotd_ctx ); | 
|     } | 
|   | 
|     /* Start LoRa thread worker */ | 
|     if( conf->nbiot_conf.enable ) | 
|     { | 
|         log_nrml("start LoRa AP process thread\n"); | 
|         //thread_start(&tid, nbiot_worker, (void *)&iotd_ctx ); | 
|     } | 
|   | 
|     while( !g_cp_signal.stop ) | 
|     { | 
|         sleep(1); | 
|     } | 
|   | 
| CleanUp: | 
|     log_warn("Terminate main program \"%s\".\n", progname); | 
|     unlink(pid_file); | 
|     cp_log_term(); | 
|     return rv; | 
| } | 
|   | 
|   | 
| #define WTD_DEV          "/dev/watchdog" | 
| void *watchdog_worker(void *arg) | 
| { | 
|     int                      wtd_fd = -1; | 
|     int                      timeout = 120; /* 2 minutes */ | 
|     int                      times = 0; | 
|   | 
|     log_nrml("start watchdog thread\n"); | 
|   | 
|     if( (wtd_fd=open(WTD_DEV, O_RDWR)) < 0 ) | 
|     { | 
|         log_err("Open watchdog '%s' failure: %s\n", WTD_DEV, strerror(errno)); | 
|         return NULL; | 
|     } | 
|   | 
|     ioctl(wtd_fd, WDIOC_SETOPTIONS, WDIOS_ENABLECARD); | 
|     ioctl(wtd_fd, WDIOC_SETTIMEOUT, &timeout); | 
|     log_nrml("Start watchdog on timeout %d seconds\n", timeout); | 
|   | 
|     while( !g_cp_signal.stop ) | 
|     { | 
|         if( times++ > 20 ) | 
|         { | 
|             log_dbg("start feed watchdog now\n"); | 
|             ioctl(wtd_fd, WDIOC_KEEPALIVE, NULL);  | 
|             times = 0; | 
|         } | 
|   | 
|         sleep(1); | 
|     } | 
|   | 
|     close(wtd_fd); | 
|     log_warn("watchdog thread worker exit\n"); | 
|   | 
|     return NULL; | 
| } |