/* * main.cpp * * Created on: Nov 2, 2015 * Author: Philipp Hinz */ #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "led.h" #include "timer.h" #include "database.h" #include "logger.h" #include "lcd.h" const int buildno = (1+(int)( #include "buildno" )); int verbose = 0; int optPoll = 0; int optRes = 0; bool optInc = false; bool optEcho = false; bool optLom = false; bool optForce = false; bool optTerm = false; bool optAdd = false; bool optDate = false; bool optSuppress = false; void *mainLoop(void *threadid); void terminationHandler(int signum); void usr1Handler(int signum); void hupHandler(int signum); 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, "vV:r:teilfhads")) != -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 'r': // set start resistance optRes = atoi(optarg); printf("Starting Poti with %d Ohms\n", optRes); break; case 'V': //printf("Build number %d\n", buildno); return EXIT_SUCCESS; break; case 't': printf( "I'm counting myself as a terminal node and terminate the CAN bus.\n"); optTerm = true; break; case 'e': printf("Echoing all CAN messages\n"); optEcho = true; break; case 'i': printf("Increasing Wiper step every second.\n"); optInc = true; break; case 'l': printf("Setting MCP2510 to listen only mode on shutdown.\n"); optLom = true; break; case 'f': printf("I'm forcing a speedtest.\n"); optForce = true; break; case 'a': printf( "I will add new nodes if they don't appear in the nodes file.\n"); optAdd = true; break; case 'd': optDate = true; break; case 's': printf("I will suppress a speedtest due to many RX/TX errors.\n"); optSuppress = true; break; case '?': case 'h': printf("Usage: %s [-hvVteilfads] [-r ohms]\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-r ohms\t\tSets the start resistance of the digital potentiometer\n"); printf("\t-V\t\tPrints only the version and exits\n"); printf("\t-t\t\tTerminates the CAN Bus with a connected DiPoti\n"); printf("\t-e\t\tEchoes all incoming CAN messages (Debugging)\n"); printf("\t-i\t\tIncreases the Wiper of the DigiPot every second\n"); printf( "\t-l\t\tSets the MCP2515 to listen only mode on shutdown\n"); printf("\t-f\t\tForces a speedtest after startup\n"); printf("\t-s\t\tSuppress a speedtest in case of errors\n"); printf("\t-a\t\tAdd new nodes if not known in file nodes\n"); printf("\t-d\t\tPrints a timestamp in front of every message\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 [-hvVteilfads] [-r ohms]\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(); //initLed(); // timer statusT = timer(&printStatus); // statusT.setDivider(40); // statusT.start(); // statusT.call(); // 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. int lcd = lcdInit(); if (lcd < 0) logger_error("Error: unable to init LCD (%d)\n", lcd); lcdClear(lcd); lcdHome(lcd); lcdPrintf(lcd,"Wer das liest ist doof."); 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); logger(V_NONE, "Saving my state to the database..\n"); sqlExecute("begin"); // Save stuff here sqlExecute("end"); sqlClose(); // Closing DB connection initLed(); // Turning all LEDs off 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(); /*sqlInsertNode((uint8_t*)"123 1", true, true); sqlInsertNode((uint8_t*)"3525 2", false, false); sqlInsertNode((uint8_t*)"sbw452 3", false, false); sqlInsertNode((uint8_t*)"s4t4 4", true, true); sqlInsertNode((uint8_t*)"te456 5", true, false);*/ 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); }