/* * main.cpp * * Created on: Nov 2, 2015 * Author: Philipp Hinz */ #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "timer.h" #include "database.h" #include "logger.h" #include "lcd.h" #include "hal.h" const int buildno = (1+(int)( #include "buildno" )); int lcd = 0; int verbose = 0; bool optDate = false; bool optPower = false; void *mainLoop(void *threadid); void terminationHandler(int signum); void usr1Handler(int signum); void hupHandler(int signum); void timeHandler(void); timer timeTimer(&timeHandler); pthread_t thread[3]; pthread_mutex_t mutex; int main(int argc, char *argv[]) { pthread_attr_t attr; pthread_mutexattr_t mutexattr; void *status; int rc; int opt; int prev_ind; logger(V_NONE, LOG_INFO, "CoffeePi by Philipp Hinz - " "Build number %d\n", buildno); // Argument handling while (prev_ind = optind, (opt = getopt(argc, argv, "vVdp")) != -1) { if (argc > 3) if (optind == prev_ind + 2 && *optarg == '-') { opt = '?'; --optind; } switch (opt) { case 'v': // be verbose /* Verbose levels: * 1 Basic debugging * 2 show CAN communication * 3 show CAN speed changes * 4 show SPI communication */ verbose++; break; case 'V': //printf("Build number %d\n", buildno); return EXIT_SUCCESS; break; case 'd': // Print timestamp in every line optDate = true; break; case 'p': // power machine on program start optPower = true; break; case '?': case 'h': printf("Usage: %s [-hvVdp]\n", argv[0]); printf("\t-h\t\tPrints this help\n"); printf("\t-v\t\tSets verbose output, can be used multiple times\n"); printf("\t-V\t\tPrints only the version and exits\n"); printf("\t-p\t\tPowers the machine on program start\n"); printf("Listening to the following signals:\n"); printf("\tSIGUSR1(%u)\tPrints monitor data of all nodes\n", SIGUSR1); printf("\tSIGHUP(%u)\tRuns a speedtest starting at default speed\n", SIGHUP); return EXIT_SUCCESS; default: fprintf(stderr, "Usage: %s [-hvVdp]\n", argv[0]); return EXIT_FAILURE; break; } } if (signal(SIGINT, terminationHandler)) { // Calls terminationHandler if SIGINT is received fprintf(stderr, "Unable to set signal handler for SIGINT: %s\n", strerror(errno)); } if (signal(SIGUSR1, usr1Handler)) { // Calls terminationHandler if SIGINT is received fprintf(stderr, "Unable to set signal handler for SIGUSR1: %s\n", strerror(errno)); } if (signal(SIGHUP, hupHandler)) { // Calls terminationHandler if SIGINT is received fprintf(stderr, "Unable to set signal handler for SIGHUP: %s\n", strerror(errno)); } // sets up the wiringPi library if (wiringPiSetup() < 0) { fprintf(stderr, "Unable to setup wiringPi: %s\n", strerror(errno)); return 1; } logger_reset(); initTimers(); halInit(); lcd = lcdInit(); if (lcd < 0) logger_error("Error: unable to init LCD (%d)\n", lcd); lcdClear(lcd); lcdHome(lcd); lcdPrintf(lcd," CoffeePi ", buildno); // http://www.tutorialspoint.com/cplusplus/cpp_multithreading.htm // Initialize and set thread joinable pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); rc = pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE_NP); if (rc != 0) throw(L"pthread_mutexattr_settype returns " + rc); pthread_mutex_init(&mutex, &mutexattr); rc = pthread_mutexattr_destroy(&mutexattr); if (rc != 0) throw(L"pthread_mutexattr_destroy returns " + rc); for (int i = 0; i < 1; i++) { if (i == THREAD_MAIN) rc = pthread_create(&thread[i], NULL, mainLoop, (void *) i); /*else if (i == THREAD_TEST) rc = pthread_create(&thread[i], NULL, testMain, (void *) i); else if (i == THREAD_CAN) rc = pthread_create(&thread[i], NULL, canThread, (void *) i);*/ if (rc) { logger_error("Error:unable to create thread, %d\n", rc); exit(-1); } } // free attribute and wait for the other threads pthread_attr_destroy(&attr); // Insert main stuff here. timeTimer.setDivider(20); timeTimer.start(); sleep(2); rc = pthread_join(thread[0], &status); if (rc) { logger_error("Error:unable to join, %d\n", rc); exit(-1); } logger(V_BASIC, "Completed thread with status %d\n", rc); pthread_exit(NULL); return EXIT_FAILURE; } /** * Handler for program termination caught via signal */ void terminationHandler(int signum) { logger(V_NONE, "Caught signal %d, exiting gracefully..\n", signum); timeTimer.stop(); logger(V_NONE, "Saving my state to the database..\n"); sqlExecute("begin"); // Save stuff here sqlExecute("end"); sqlClose(); // Closing DB connection exit(EXIT_SUCCESS); } /** * Handles the signal USR2 */ void usr1Handler(int signum) { // Do something here? logger_reset(); } /** * Handles the signal HUP and starts a speed test */ void hupHandler(int signum) { // Do something here? } /** * Sends a signal to a thread * @param threadid ID of the thread * @param sig Signal to send */ void killThread(int threadid, int sig) { //logger(V_BASIC, "pthread_kill on thread %d (%d)\n", threadid, sig); if (pthread_kill(thread[threadid], sig)) { logger_error("pthread_kill on thread %d failed (%d)\n", threadid, sig); } } /** * Main Thread, used for some initializations and error detection * @param threadid Thread ID */ void *mainLoop(void *threadid) { sqlOpen(); //sqlSetup(); // Do more stuff here logger(V_BASIC, "Thread goes Sleeping..\n"); while (1) { pause(); logger(V_NONE, LOG_ERROR, "Whoops. Something went wrong..\n"); } pthread_exit(NULL); } void timeHandler(void) { time_t rawtime; struct tm * timeinfo; time ( &rawtime ); timeinfo = localtime ( &rawtime ); lcdPosition(lcd, 0, 1); lcdPrintf(lcd, " %.2d:%.2d:%.2d ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); }