// thread pin control routine, does timed PWM to control brightness and pulsing void *flasher(void *pptr) { bool waxing = true; pin_t *pin = (pin_t*)pptr; daemonLog("started thread for pin %d\n",pin->pin); while(keepRunning) // each run of the loop should take one duty cycle... i.e. 100Hz { if (!pin->flashPeriod && pin->brightness<FLT_EPSILON) { usleep(dutyCycle); if (pin->powerOn) { GPIO_SET = 1 << pin->pin; } else { GPIO_CLR = 1 << pin->pin; } } else { useconds_t flashRate = pin->flashPeriod; useconds_t flashSteps = flashRate / dutyCycle; if (flashSteps >= 10) { float flashStep = (maxBrightness - minBrightness) / flashSteps; pin->brightness += waxing ? flashStep : -flashStep; if (pin->brightness > maxBrightness) { waxing = false; pin->brightness = maxBrightness; } else if (pin->brightness < minBrightness) { waxing = true; pin->brightness = minBrightness; } } useconds_t mark = pin->brightness / maxBrightness * dutyCycle; if (mark) { GPIO_SET = 1 << pin->pin; usleep(mark); } float spacePct = maxBrightness - pin->brightness; useconds_t space = spacePct / maxBrightness * dutyCycle; if (space) { GPIO_CLR = 1 << pin->pin; usleep(space); } } } // turn off the lamp when we have been signalled to shut down GPIO_CLR = 1 << pin->pin; daemonLog("thread %d finished and pin reset\n",pin->pin); return NULL; }
void dumpStatsFile() { FILE * statsFile = fopen(statsFilePath, "w+"); if (statsFile) { daemonLog("created stats file\n"); for (unsigned char pin = MIN_PIN;pin<NUM_PINS;pin++) { if (pins[pin].thread) { fprintf(statsFile,"pin %d : flash = %lu, brightness = %.0f, power = %d\n",pin,pins[pin].flashPeriod,pins[pin].brightness,pins[pin].powerOn); } } fclose(statsFile); daemonLog("finished stats file and closed\n"); } else { perror("failed to create stats file"); } }
void Daemon::log(QString str) { qDebug() << str; if (m_daemonLogEnabled) { emit daemonLog(str); } #ifdef WRITE_LOG_TO_FILE str.append("\n"); m_outStream << str; m_outStream.flush(); #endif }
void doControlMessage(char * message) { bool steadyMsg=strncmp(message,"s:",2)==0; bool flashMsg=strncmp(message,"f:",2)==0; bool relayControlMsg=strncmp(message,"p:",2)==0; if (steadyMsg||flashMsg||relayControlMsg) { daemonLog("received control message %s\n",message); message+=2; message[6]=0; if (strnlen(message,6)<=6&&strnlen(message,6)>=4) { char pinBuf[3]={0}; strncpy(pinBuf,message,2); unsigned char pin = atoi(pinBuf); daemonLog("adjusting pin %d\n",pin); if (pin >= MIN_PIN && pin < NUM_PINS) { INP_GPIO(pin); OUT_GPIO(pin); // Define pin as output message+=3; unsigned char newParameter = atoi(message); if (steadyMsg) { pins[pin].flashPeriod=0; pins[pin].brightness=fmaxf(fminf((float)newParameter,maxBrightness),minBrightness); daemonLog("parameter is %s, interpreted as brightness %f\n",message,pins[pin].brightness); } else if (flashMsg) { if (newParameter<=0) newParameter = 1; pins[pin].flashPeriod=100000*newParameter; daemonLog("parameter is %s, interpreted as flash period %lu\n",message,pins[pin].flashPeriod); } else if (relayControlMsg) { newParameter=(bool)newParameter; pins[pin].powerOn=newParameter; pins[pin].flashPeriod=0; pins[pin].brightness=0; daemonLog("parameter is %s, interpreted as power on %d\n",message,pins[pin].powerOn); } if (!pins[pin].thread) { int pin_thread_success = pthread_create(&pins[pin].thread, NULL, flasher, (void*)&pins[pin]); assert(0 == pin_thread_success); daemonLog("created thread for pin %d\n",pin); } } else { daemonLog("invalid pin %d",pin); } } else { daemonLog("invalid length control message - should be _:XX:YYY was %d - %s\n",strnlen(message,6),message); } } }
// the main control function // print help, if needed, setup signal handling for clean daemon exit, setup GPIO // daemonize, setup fifo and wait for instructions int main(int argc,char **argv) { // emit help and exit cleanly if they specify any parameters if (argc>1) { showHelp(argv[0]); return 0; } // prepare signal handling for when we're a daemon (or not) struct sigaction new_action, old_action; new_action.sa_handler = sigInt; sigemptyset (&new_action.sa_mask); new_action.sa_flags = 0; sigaction (SIGINT, NULL, &old_action); if (old_action.sa_handler != SIG_IGN) { sigaction (SIGINT, &new_action, NULL); } sigaction (SIGHUP, NULL, &old_action); if (old_action.sa_handler != SIG_IGN) { sigaction (SIGHUP, &new_action, NULL); } sigaction (SIGTERM, NULL, &old_action); if (old_action.sa_handler != SIG_IGN) { sigaction (SIGTERM, &new_action, NULL); } // map the gpio area, if we can't do this, there's no point even trying to be a daemon if(map_peripheral(&gpio) == -1) { printf("Failed to map the physical GPIO registers into the virtual memory space.\n"); return -1; } // now the initial setup is done, attempt to make ourselves a daemon before continuing // all logging from now on goes to a dedicated log file // (from http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html) pid_t pid, sid; pid = fork(); if (pid < 0) { printf("failed to spawn a daemon (%s)\n",strerror(errno)); exit(EXIT_FAILURE); } if (pid > 0) { exit(EXIT_SUCCESS); } umask(0); debugFile = fopen(flasherLog, "w+"); if (!debugFile) { perror("failed to create debug log file"); } else { daemonLog("created log file\n"); } sid = setsid(); if (sid < 0) { daemonLog("%s failed to setsid\n",strerror(errno)); exit(EXIT_FAILURE); } if ((chdir(flasherPwd)) < 0) { daemonLog("%s failed to chdir\n",strerror(errno)); exit(EXIT_FAILURE); } close(STDIN_FILENO); // this is enough to stop the daemon from working close(STDOUT_FILENO); close(STDERR_FILENO); // we are now a daemon, logging to file daemonLog("daemon running\n"); // then create one flasher for each pin we will use for (unsigned char pin = MIN_PIN;pin<NUM_PINS;pin++) { pins[pin].pin = pin; } // main loop, open the fifo and wait for messages or for interrupt unlink(flasherPipe); char buf[CMD_BUF]; int fifo_create_success = mkfifo(flasherPipe,0777); if (fifo_create_success == 0 || errno == EEXIST) { daemonLog("Waiting for messages on %s...\n",flasherPipe); FILE * flasherfile = fopen(flasherPipe,"r"); if (flasherfile) { while (keepRunning) { if (fgets(buf,CMD_BUF,flasherfile)) { doControlMessage(buf); dumpStatsFile(); } usleep(dutyCycle); // reduce CPU load } if (fclose(flasherfile)) { daemonLog("%s failed to close fifo\n",strerror(errno)); } if (unlink(statsFilePath)) { daemonLog("%s failed to cleanup stats\n",strerror(errno)); } } else { daemonLog("%s failed to open fifo\n",strerror(errno)); } if (unlink(flasherPipe)) { daemonLog("%s failed to cleanup fifo\n",strerror(errno)); } } else { daemonLog("%s failed to create fifo\n",strerror(errno)); } // either we couldn't open the fifo or we opened it, ran for a bit and received a shutdown... daemonLog("preparing to shut down...\n"); // try to clean up all threads for (unsigned char pin = MIN_PIN;pin<NUM_PINS;pin++) { if (pins[pin].thread) { pthread_join(pins[pin].thread,NULL); daemonLog("thread %d done\n",pin); } } return 0; }