Files
Arduino/uno-stats-monitor/unomond/monitor_daemon.c
2024-01-16 19:32:29 -05:00

800 lines
24 KiB
C

/*
* UNO Monitor Daemon v.0.1.0
* Kidacro <kidacro@archamedis.net>
* https://kidacro.archamedis.net/git/kidacro/Arduino/src/branch/main/uno-stats-monitor
*
* monitor_daemon.c - Sends and Receives commands to UNO Monitor over serial connection
*
* Input Schema:
* Start char is: '#'
* End char is: '@'
* 2nd char denotes which line number/mode to use
*
* Setting Schema:
* LCDLength:LCDRows:LCDDelay:LEDBrightness:LEDDelay
* 16:2:5:0:3
*
* Example:
* Line 1: #1Archamedis Status@
* Line 2: #299% free / etc.@
* LAVG -: #324@
* LSET 0: #16:2:5:0:3@
*
* Output Schema:
* Multimedia Controls use single characters to denote which button was pressed
* P power
* M mute
* m mode
* p pause/play
* b back
* f forward
* e eq
* - vol down
* + vol up
* r return
* u usb scan
* 0 number 0
* 1 number 1
* 2 number 2
* 3 number 3
* 4 number 4
* 5 number 5
* 6 number 6
* 7 number 7
* 8 number 8
* 9 number 9
* R repeat
* Z other button pressed
*/
// C library
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <syslog.h>
#include <signal.h>
#include <getopt.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <errno.h>
#include <termios.h>
#include <time.h>
// external libs
#include <libconfig.h>
#define MAX_ENTRIES 10
// global variables
int debug = 0;
int running = 0;
char *conf_file_name = "unomond.conf";
char *pid_file_name = "/tmp/unomond.pid";
int pid_fd = -1;
const char *app_name = "UnomonD v.0.1.0";
FILE *log_stream;
char *log_file_name = NULL;
int serial_port;
struct termios tty;
struct timeval __millis_start;
// config file settings
int delay = 5000;
int line_length = 16;
int line_count = 2;
int lcd_delay = 5;
int led_brightness = 5;
int led_delay = 3;
const char *cpu_temp_file = "";
const char *cpu_fanspeed_file = "";
char *drive_free_space[MAX_ENTRIES];
int drive_free_space_count;
const char *ttydevice = "/dev/ttyACM0";
const char *ircmd_P = ""; // power
const char *ircmd_M = ""; // mute
const char *ircmd_m = ""; // mode
const char *ircmd_p = ""; // pause/play
const char *ircmd_b = ""; // back
const char *ircmd_f = ""; // forward
const char *ircmd_e = ""; // eq
const char *ircmd_minus = ""; // vol down
const char *ircmd_plus = ""; // vol up
const char *ircmd_r = ""; // return
const char *ircmd_u = ""; // usb scan
const char *ircmd_0 = ""; // number 0
const char *ircmd_1 = ""; // number 1
const char *ircmd_2 = ""; // number 2
const char *ircmd_3 = ""; // number 3
const char *ircmd_4 = ""; // number 4
const char *ircmd_5 = ""; // number 5
const char *ircmd_6 = ""; // number 6
const char *ircmd_7 = ""; // number 7
const char *ircmd_8 = ""; // number 8
const char *ircmd_9 = ""; // number 9
const char *ircmd_R = ""; // repeat
const char *ircmd_Z = ""; // other button pressed
// function prototypes
void init_millis();
unsigned long int millis();
char* timestamp();
bool file_exists(const char *filename);
int read_conf_file(int reload);
void handle_signal(int sig);
static void daemonize();
void print_help(void);
int serial_open_port();
int listen_server();
void send_stats();
void send_settings();
void log_method();
// from gather_stats.c
void get_stats();
// local functions
void init_millis()
{
gettimeofday(&__millis_start, NULL);
}
unsigned long int millis()
{
long mtime, seconds, useconds;
struct timeval end;
gettimeofday(&end, NULL);
seconds = end.tv_sec - __millis_start.tv_sec;
useconds = end.tv_usec - __millis_start.tv_usec;
mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5;
return mtime;
}
char* timestamp()
{
unsigned size = 300;
char* buffer = malloc(size);
//char time_s;
time_t ltime; /* calendar time */
ltime=time(NULL); /* get current cal time */
//time_s = sprintf("%s",asctime( localtime(&ltime) ) );
snprintf(buffer, size, "%s", asctime( localtime(&ltime) ));
return buffer;
}
bool file_exists(const char *filename)
{
FILE *fp = fopen(filename, "r");
bool is_exist = false;
if(fp != NULL) {
is_exist = true;
fclose(fp); // close the file
}
return is_exist;
}
// read from config file
int read_conf_file(int reload)
{
int ret = -1, n = 0;
config_t cfg;
config_setting_t *drive_free_space_entries;
char *mydrive;
const char *myttydevice;
const char *mylogfile;
const char *mycpu_temp_file;
const char *mycpu_fanspeed_file;
const char *myircmd_P;
const char *myircmd_M;
const char *myircmd_m;
const char *myircmd_p;
const char *myircmd_b;
const char *myircmd_f;
const char *myircmd_e;
const char *myircmd_minus;
const char *myircmd_plus;
const char *myircmd_r;
const char *myircmd_u;
const char *myircmd_0;
const char *myircmd_1;
const char *myircmd_2;
const char *myircmd_3;
const char *myircmd_4;
const char *myircmd_5;
const char *myircmd_6;
const char *myircmd_7;
const char *myircmd_8;
const char *myircmd_9;
const char *myircmd_R;
const char *myircmd_Z;
if(conf_file_name == NULL) {
syslog(LOG_INFO, "Configuration file: %s is empty or not valid.\n",conf_file_name);
return(EXIT_FAILURE);
}
// check if conf file exists
if(!file_exists(conf_file_name)) {
return(EXIT_FAILURE);
}
// read the file
config_init(&cfg);
if(!config_read_file(&cfg, conf_file_name)) {
syslog(LOG_INFO, "%s:%d - %s\n", config_error_file(&cfg),
config_error_line(&cfg), config_error_text(&cfg));
config_destroy(&cfg);
syslog(LOG_INFO, "Can not open configuration file: %s.\n",conf_file_name);
return(EXIT_FAILURE);
}
// logfile (lookup logfile first and if found do a log_method to reload it)
if(config_lookup_string(&cfg, "logfile", &mylogfile)) {
log_file_name = strdup(mylogfile);
log_method();
fprintf(log_stream, "Config: Using 'logfile': %s\n", mylogfile);
}
else {
syslog(LOG_INFO, "No 'logfile' setting in configuration file, using default stderr output.\n");
}
// load the base config
// delay
if(config_lookup_int(&cfg, "delay", &delay)) {
fprintf(log_stream, "Config: Using 'delay': %i\n",delay);
}
else {
fprintf(log_stream, "No 'delay' setting in configuration file, using default delay of %i.\n",delay);
}
// ttydevice
if(config_lookup_string(&cfg, "tty", &myttydevice)) {
ttydevice = strdup(myttydevice);
fprintf(log_stream, "Config: Using 'TTY': %s\n",ttydevice);
}
else {
fprintf(log_stream, "No 'tty' setting in configuration file, using default tty of %s.\n",ttydevice);
}
// line_length
if(config_lookup_int(&cfg, "line_length", &line_length)) {
fprintf(log_stream, "Config: Using 'line_length': %i\n",line_length);
}
else {
fprintf(log_stream, "No 'line_length' setting in configuration file, using default line_length of %i.\n",line_length);
}
// line_count
if(config_lookup_int(&cfg, "line_count", &line_count)) {
fprintf(log_stream, "Config: Using 'line_count': %i\n",line_count);
}
else {
fprintf(log_stream, "No 'line_count' setting in configuration file, using default line_count of %i.\n",line_count);
}
// led_brightness
if(config_lookup_int(&cfg, "led_brightness", &led_brightness)) {
fprintf(log_stream, "Config: Using 'led_brightness': %i\n",led_brightness);
}
else {
fprintf(log_stream, "No 'led_brightness' setting in configuration file, using default led_brightness of %i.\n",led_brightness);
}
// led_delay
if(config_lookup_int(&cfg, "led_delay", &led_delay)) {
fprintf(log_stream, "Config: Using 'led_delay': %i\n",led_delay);
}
else {
fprintf(log_stream, "No 'led_delay' setting in configuration file, using default led_delay of %i.\n",led_delay);
}
// lcd_delay
if(config_lookup_int(&cfg, "lcd_delay", &lcd_delay)) {
fprintf(log_stream, "Config: Using 'lcd_delay': %i\n",lcd_delay);
}
else {
fprintf(log_stream, "No 'lcd_delay' setting in configuration file, using default lcd_delay of %i.\n",lcd_delay);
}
// cpu stats settings
if(config_lookup_string(&cfg, "cpu_temp_file", &mycpu_temp_file)) {
cpu_temp_file = strdup(mycpu_temp_file);
}
if(config_lookup_string(&cfg, "cpu_fanspeed_file", &mycpu_fanspeed_file)) {
cpu_fanspeed_file = strdup(mycpu_fanspeed_file);
}
// IR commands
if(config_lookup_string(&cfg, "ircmd_P", &myircmd_P)) { ircmd_P = strdup(myircmd_P); }
if(config_lookup_string(&cfg, "ircmd_M", &myircmd_M)) { ircmd_M = strdup(myircmd_M); }
if(config_lookup_string(&cfg, "ircmd_m", &myircmd_m)) { ircmd_m = strdup(myircmd_m); }
if(config_lookup_string(&cfg, "ircmd_p", &myircmd_p)) { ircmd_p = strdup(myircmd_p); }
if(config_lookup_string(&cfg, "ircmd_b", &myircmd_b)) { ircmd_b = strdup(myircmd_b); }
if(config_lookup_string(&cfg, "ircmd_f", &myircmd_f)) { ircmd_f = strdup(myircmd_f); }
if(config_lookup_string(&cfg, "ircmd_e", &myircmd_e)) { ircmd_e = strdup(myircmd_e); }
if(config_lookup_string(&cfg, "ircmd_minus", &myircmd_minus)) { ircmd_minus = strdup(myircmd_minus); }
if(config_lookup_string(&cfg, "ircmd_plus", &myircmd_plus)) { ircmd_plus = strdup(myircmd_plus); }
if(config_lookup_string(&cfg, "ircmd_r", &myircmd_r)) { ircmd_r = strdup(myircmd_r); }
if(config_lookup_string(&cfg, "ircmd_u", &myircmd_u)) { ircmd_u = strdup(myircmd_u); }
if(config_lookup_string(&cfg, "ircmd_0", &myircmd_0)) { ircmd_0 = strdup(myircmd_0); }
if(config_lookup_string(&cfg, "ircmd_1", &myircmd_1)) { ircmd_1 = strdup(myircmd_1); }
if(config_lookup_string(&cfg, "ircmd_2", &myircmd_2)) { ircmd_2 = strdup(myircmd_2); }
if(config_lookup_string(&cfg, "ircmd_3", &myircmd_3)) { ircmd_3 = strdup(myircmd_3); }
if(config_lookup_string(&cfg, "ircmd_4", &myircmd_4)) { ircmd_4 = strdup(myircmd_4); }
if(config_lookup_string(&cfg, "ircmd_5", &myircmd_5)) { ircmd_5 = strdup(myircmd_5); }
if(config_lookup_string(&cfg, "ircmd_6", &myircmd_6)) { ircmd_6 = strdup(myircmd_6); }
if(config_lookup_string(&cfg, "ircmd_7", &myircmd_7)) { ircmd_7 = strdup(myircmd_7); }
if(config_lookup_string(&cfg, "ircmd_8", &myircmd_8)) { ircmd_8 = strdup(myircmd_8); }
if(config_lookup_string(&cfg, "ircmd_9", &myircmd_9)) { ircmd_9 = strdup(myircmd_9); }
if(config_lookup_string(&cfg, "ircmd_0", &myircmd_0)) { ircmd_0 = strdup(myircmd_0); }
if(config_lookup_string(&cfg, "ircmd_R", &myircmd_R)) { ircmd_R = strdup(myircmd_R); }
if(config_lookup_string(&cfg, "ircmd_Z", &myircmd_Z)) { ircmd_Z = strdup(myircmd_Z); }
// free drive space settings
drive_free_space_entries = config_lookup(&cfg, "drive_free_space");
drive_free_space_count = config_setting_length(drive_free_space_entries);
fprintf(log_stream,"Config: I have %d free drive space entries:\n", drive_free_space_count);
for(n = 0; n < drive_free_space_count; n++) {
mydrive = strdup(config_setting_get_string_elem(drive_free_space_entries, n));
drive_free_space[n] = strdup(mydrive);
fprintf(log_stream,"\t#%d. %s\n", n + 1,
config_setting_get_string_elem(drive_free_space_entries, n));
}
// report to syslog
if(reload == 1) {
syslog(LOG_INFO, "Reloaded configuration file %s of %s", conf_file_name, app_name);
}
else {
syslog(LOG_INFO, "Configuration of %s read from file %s", app_name, conf_file_name);
}
config_destroy(&cfg);
return ret;
}
void handle_signal(int sig)
{
int lock_result = 0;
if(sig == SIGINT) {
syslog(LOG_INFO, "Received INT signal, Stopping daemon ...");
/* Unlock and close lockfile */
if(pid_fd != -1) {
lock_result = lockf(pid_fd, F_ULOCK, 0);
if(lock_result < 0) {
syslog(LOG_INFO, "Lockfile could not be unlocked.");
}
close(pid_fd);
}
/* Try to delete lockfile */
if(pid_file_name != NULL) {
unlink(pid_file_name);
}
running = 0;
/* Reset signal handling to default behavior */
signal(SIGINT, SIG_DFL);
running = 0;
return;
}
else if (sig == SIGHUP) {
syslog(LOG_INFO, "Received HUP signal, Reloading daemon config file ...");
read_conf_file(1);
}
else if (sig == SIGCHLD) {
syslog(LOG_INFO, "Received SIGCHLD signal... but I have no kids!.");
return;
}
}
static void daemonize()
{
pid_t pid = 0;
int myfd = -1;
int chdir_result = 0;
int write_result = 0;
/* Fork off the parent process */
pid = fork();
/* An error occurred */
if(pid < 0) {
exit(EXIT_FAILURE);
}
/* Success: Let the parent terminate */
if(pid > 0) {
exit(EXIT_SUCCESS);
}
/* On success: The child process becomes session leader */
if(setsid() < 0) {
exit(EXIT_FAILURE);
}
/* Ignore signal sent from child to parent process */
signal(SIGCHLD, SIG_IGN);
/* Fork off for the second time*/
pid = fork();
/* An error occurred */
if(pid < 0) {
exit(EXIT_FAILURE);
}
/* Success: Let the parent terminate */
if(pid > 0) {
exit(EXIT_SUCCESS);
}
/* Set new file permissions */
umask(0);
/* Change the working directory to the root directory */
/* or another appropriated directory */
chdir_result = chdir("/");
if(chdir_result <0) {
syslog(LOG_INFO, "Could not change to our working directory.");
}
/* Close all open file descriptors */
for(myfd = sysconf(_SC_OPEN_MAX); myfd > 0; myfd--) {
close(myfd);
}
/* Reopen stdin (myfd = 0), stdout (myfd = 1), stderr (myfd = 2) */
stdin = fopen("/dev/null", "r");
stdout = fopen("/dev/null", "w+");
stderr = fopen("/dev/null", "w+");
/* Try to write PID of daemon to lockfile */
if(pid_file_name != NULL) {
char str[256];
pid_fd = open(pid_file_name, O_RDWR|O_CREAT, 0640);
if(pid_fd < 0) {
/* Can't open lockfile */
exit(EXIT_FAILURE);
}
if(lockf(pid_fd, F_TLOCK, 0) < 0) {
/* Can't lock file */
exit(EXIT_FAILURE);
}
/* Get current PID */
sprintf(str, "%d\n", getpid());
/* Write PID to lockfile */
write_result = write(pid_fd, str, strlen(str));
if(write_result < 0) {
syslog(LOG_INFO, "PID could not be written to lockfile.");
}
}
}
void print_help(void)
{
printf("\n Usage: %s [OPTIONS]\n\n", app_name);
printf(" Options:\n");
printf(" -h --help Print this help\n");
printf(" -c --conf_file filename Read configuration from the file\n");
printf(" -l --log_file filename Write logs to the file\n");
printf(" -d --daemon Daemonize this application\n");
printf(" -D --debug Debug this application\n");
printf(" -n --tty /dev/tty* TTY device to connect to\n");
printf(" -p --pid_file filename PID file used by daemonized app\n");
printf("\n");
}
/* Open Serial Port */
int serial_open_port()
{
serial_port = open(ttydevice, O_RDWR);
// Read in existing settings, and handle any error
if(tcgetattr(serial_port, &tty) != 0) {
fprintf(log_stream, "Error %i from tcgetattr in open ttydevice: %s\n", errno, strerror(errno));
syslog(LOG_INFO, "Could not open serial port! Exiting.");
exit(EXIT_FAILURE);
}
tty.c_cflag &= ~PARENB; // Clear parity bit, disabling parity (most common)
tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication (most common)
tty.c_cflag &= ~CSIZE; // Clear all bits that set the data size
tty.c_cflag |= CS8; // 8 bits per byte (most common)
tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control (most common)
tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1)
tty.c_lflag &= ~ICANON;
tty.c_lflag &= ~ECHO; // Disable echo
tty.c_lflag &= ~ECHOE; // Disable erasure
tty.c_lflag &= ~ECHONL; // Disable new-line echo
tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // Disable any special handling of received bytes
tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
// tty.c_oflag &= ~OXTABS; // Prevent conversion of tabs to spaces (NOT PRESENT ON LINUX)
// tty.c_oflag &= ~ONOEOT; // Prevent removal of C-d chars (0x004) in output (NOT PRESENT ON LINUX)
tty.c_cc[VTIME] = 10; // Wait for up to 1s (10 deciseconds), returning as soon as any data is received.
tty.c_cc[VMIN] = 0;
// Set in/out baud rate to 9600
cfsetispeed(&tty, B9600);
cfsetospeed(&tty, B9600);
// Save tty settings, also checking for error
if(tcsetattr(serial_port, TCSANOW, &tty) != 0) {
fprintf(log_stream, "Error %i from tcsetattr in save tty settings: %s\n", errno, strerror(errno));
syslog(LOG_INFO, "Could not save serial port settings! Exiting.");
exit(EXIT_FAILURE);
}
return 1;
}
/* Server */
int listen_server()
{
char read_buf [2];
int exec_result = 0;
memset(&read_buf, '\0', sizeof(read_buf));
int num_bytes = read(serial_port, &read_buf, sizeof(read_buf));
// may be 0 if no bytes were received, and can also be -1 to signal an error.
if(num_bytes < 0) {
fprintf(log_stream, "Error reading: %s\n", strerror(errno));
return 1;
}
// do stuff goes here
// switch on read_buf
// input proto: PMmpbfe-+ru0123456789RZ
if(strcmp(read_buf,"P") == 0) { exec_result = system(ircmd_P); }
if(strcmp(read_buf,"M") == 0) { exec_result = system(ircmd_M); }
if(strcmp(read_buf,"m") == 0) { exec_result = system(ircmd_m); }
if(strcmp(read_buf,"p") == 0) { exec_result = system(ircmd_p); }
if(strcmp(read_buf,"b") == 0) { exec_result = system(ircmd_b); }
if(strcmp(read_buf,"f") == 0) { exec_result = system(ircmd_f); }
if(strcmp(read_buf,"e") == 0) { exec_result = system(ircmd_e); }
if(strcmp(read_buf,"-") == 0) { exec_result = system(ircmd_minus); }
if(strcmp(read_buf,"+") == 0) { exec_result = system(ircmd_plus); }
if(strcmp(read_buf,"r") == 0) { exec_result = system(ircmd_r); }
if(strcmp(read_buf,"u") == 0) { exec_result = system(ircmd_u); }
if(strcmp(read_buf,"0") == 0) { exec_result = system(ircmd_0); }
if(strcmp(read_buf,"1") == 0) { exec_result = system(ircmd_1); }
if(strcmp(read_buf,"2") == 0) { exec_result = system(ircmd_2); }
if(strcmp(read_buf,"3") == 0) { exec_result = system(ircmd_3); }
if(strcmp(read_buf,"4") == 0) { exec_result = system(ircmd_4); }
if(strcmp(read_buf,"5") == 0) { exec_result = system(ircmd_5); }
if(strcmp(read_buf,"6") == 0) { exec_result = system(ircmd_6); }
if(strcmp(read_buf,"7") == 0) { exec_result = system(ircmd_7); }
if(strcmp(read_buf,"8") == 0) { exec_result = system(ircmd_8); }
if(strcmp(read_buf,"9") == 0) { exec_result = system(ircmd_9); }
if(strcmp(read_buf,"R") == 0) { exec_result = system(ircmd_R); }
if(strcmp(read_buf,"Z") == 0) { exec_result = system(ircmd_Z); }
if(exec_result != 0) {
fprintf(log_stream, "Command for %s failed with %i bytes. Received message: %s\n", read_buf, num_bytes, read_buf);
syslog(LOG_INFO, "Command for %s failed.",read_buf);
}
if(debug) {
fprintf(log_stream, "Read %i bytes. Received message: %s\n", num_bytes, read_buf);
}
return 0;
}
// send stats
void send_stats(char *line_1, char *line_2, char *line_3)
{
int write_result = 0;
unsigned int mylen_1 = 0;
unsigned int mylen_2 = 0;
unsigned int mylen_3 = 0;
// Line 1
mylen_1 = strlen(line_1);
write_result = write(serial_port, line_1, mylen_1);
if(write_result < 0) {
fprintf(log_stream, "Writing stats to serial report resulted in %i error. Size of message: %i\n", write_result, mylen_1);
syslog(LOG_INFO, "Writing stats to serial report resulted in %i error.",write_result);
}
// Line 2
mylen_2 = strlen(line_2);
write_result = write(serial_port, line_2, mylen_2);
if(write_result < 0) {
fprintf(log_stream, "Writing stats to serial report resulted in %i error. Size of message: %i\n", write_result, mylen_2);
syslog(LOG_INFO, "Writing stats to serial report resulted in %i error.",write_result);
}
// Line 3
mylen_3 = strlen(line_3);
write_result = write(serial_port, line_3, mylen_3);
if(write_result < 0) {
fprintf(log_stream, "Writing stats to serial report resulted in %i error. Size of message: %i\n", write_result, mylen_3);
syslog(LOG_INFO, "Writing stats to serial report resulted in %i error.",write_result);
}
return;
}
/* Send settings to receiver */
// Setting Schema:
// LCDLength:LCDRows:LCDDelay:LEDBrightness:LEDDelay
// 16:2:5:0:3
void send_settings() {
char myline[16];
unsigned int mylen = 0;
int write_result = 0;
sprintf(myline,"#0%i:%i:%i:%i:%i@",line_length,line_count,lcd_delay,led_brightness,led_delay);
mylen = strlen(myline);
write_result = write(serial_port, myline, mylen);
if(write_result < 0) {
fprintf(log_stream, "Writing settings to serial report resulted in %i error. Size of message: %i\n", write_result, mylen);
syslog(LOG_INFO, "Writing settings to serial report resulted in %i error.",write_result);
}
return;
}
/* Daemon log method */
void log_method() {
// close log file, if its open
if(log_stream != stderr && log_stream != NULL) {
fclose(log_stream);
}
// command line logfile takes precedence
if(log_file_name != NULL && file_exists(log_file_name)) {
log_stream = fopen(log_file_name, "a+");
if(log_stream == NULL) {
syslog(LOG_ERR, "Can not open log file: %s, error: %s", log_file_name, strerror(errno));
log_stream = stderr; // stdout;
return;
}
syslog(LOG_INFO, "Using logfile: %s\n",log_file_name);
}
// use stderr as failback
else {
log_stream = stderr; // stdout;
}
return;
}
/* Main function */
int main(int argc, char *argv[])
{
static struct option long_options[] = {
{"conf_file", required_argument, 0, 'c'},
{"log_file", required_argument, 0, 'l'},
{"help", no_argument, 0, 'h'},
{"debug", no_argument, 0, 'D'},
{"daemon", no_argument, 0, 'd'},
{"pid_file", required_argument, 0, 'p'},
{"tty", required_argument, 0, 'n'},
{NULL, 0, 0, 0}
};
int value, option_index = 0;
char *mytty = NULL;
int start_daemonized = 0;
// TODO: fix timestamps for logfile
//fprintf(log_stream,"Timestamp %s\n",timestamp());
/* Open system log and write startup message to it */
openlog(argv[0], LOG_PID|LOG_CONS, LOG_DAEMON);
syslog(LOG_INFO, "Started %s", app_name);
/* Daemon will handle two signals */
signal(SIGINT, handle_signal);
signal(SIGHUP, handle_signal);
/* Set default log method */
log_method();
/* Read configuration from config file
* dev: keep this b4 command line arguments so below takes precedence
*/
read_conf_file(0);
/* Try to process all command line arguments */
while((value = getopt_long(argc, argv, "c:l:p:n:dDh", long_options, &option_index)) != -1) {
switch (value) {
case 'c':
conf_file_name = strdup(optarg);
fprintf(log_stream, "Reloading configuation from command line...\n");
read_conf_file(0);
fprintf(log_stream, "Command Line: Using 'conffile': %s\n",conf_file_name);
break;
case 'l':
log_file_name = strdup(optarg);
log_method();
fprintf(log_stream, "Command Line: Using 'logfile': %s\n",log_file_name);
break;
case 'p':
pid_file_name = strdup(optarg);
fprintf(log_stream, "Command Line: Using 'pidfile': %s\n",pid_file_name);
break;
case 'n':
mytty = strdup(optarg);
ttydevice = mytty;
fprintf(log_stream, "Command Line: Using 'TTY': %s\n",ttydevice);
break;
case 'd':
start_daemonized = 1;
fprintf(log_stream, "Command Line: Daemonizing...\n");
break;
case 'D':
debug = 1;
fprintf(log_stream, "Command Line: Using Debugging\n");
break;
case 'h':
print_help();
return EXIT_SUCCESS;
default:
break;
}
}
/* When daemonizing is requested at command line. */
if(start_daemonized == 1) {
daemonize();
}
/* This global variable can be changed in function handling signal */
running = 1;
/* Main loop */
serial_open_port();
send_settings();
send_settings(); // yes twice due to the arduino getting reset on 1st access on linux (if not modified)
init_millis();
while(running == 1) {
listen_server(); // listen for IR events (blocks for ~1 second at a time)
if(debug) {
fprintf(log_stream,"Elapsed time: %ld milliseconds\n", millis());
}
if(millis() >= (unsigned long)delay) {
get_stats(); // get and send stats if its time to do so (non blocking timer)
init_millis(); // reset timer
}
}
close(serial_port);
/* Close log file, when it is used. */
if(log_stream != stderr && log_stream != NULL) {
fclose(log_stream);
}
/* Write system log and close it. */
syslog(LOG_INFO, "Stopped %s.\n", app_name);
closelog();
return EXIT_SUCCESS;
}