#include <telldus-core.h> #include <sys/time.h> #include <stdio.h> #include <time.h> #include <unistd.h> #include <signal.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <sys/wait.h> #include <sys/types.h> #include <sys/stat.h> #include <syslog.h> #define TIMEOUT_US 500000L #define TIMEOUT_S 1 #define event_wrapper "/root/bin/event_wrapper.pl" #define DUMMYDEVICE 10 //used for testing communication with telldusd int volatile last_id = -1; // Last recieved id and method int volatile last_method = -1; int volatile report_id = -1; // id and method reported to child int volatile report_method = -1; int volatile do_report = 0; // Set by signal handler int volatile do_reload = 0; int volatile do_exit = 0; pid_t volatile pID = -1; // pID of forked child int debug = 0; // Debug mode, console output and no deamonize // Tellstick events int callbacksensorId = 0; int callbackdeviceId = 1; int callbackchangeId = 2; void WINAPI deviceEvent(int deviceId, int method, const char *data, int callbackId, void *context); void WINAPI deviceChange(int deviceId, int method, const char *data, int callbackId, void *context); void WINAPI sensorEvent(const char *protocol, const char *model, int sensorId, int dataType, const char *value, int ts, int callbackId, void *context); void unregister_telldusd() { tdUnregisterCallback( callbacksensorId ); tdUnregisterCallback( callbackdeviceId ); tdUnregisterCallback( callbackchangeId ); // tdClose(); } void register_telldusd() { // tdInit(); callbacksensorId = tdRegisterSensorEvent( (TDSensorEvent)&sensorEvent, 0 ); callbackdeviceId = tdRegisterDeviceEvent( (TDDeviceEvent)&deviceEvent, 0 ); callbackchangeId = tdRegisterDeviceChangeEvent( (TDDeviceChangeEvent)&deviceChange, 0 ); if (tdTurnOff(DUMMYDEVICE)) { syslog (LOG_NOTICE, "telldusd error, exiting"); tdClose(); exit(1); } } /* Fork off and let child call event_wrrapper */ void report_event(int id, int method) { char s1[60]; char timeBuf[80]; time_t timestamp; if (id > 0) { // fork process and let child handle event pID = fork(); if (pID == 0) { // child unregister_telldusd(); tdClose(); timestamp = time(NULL); strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); if (method == TELLSTICK_TURNON) { sprintf (s1, "ON event from device %i\n", id); if (id != DUMMYDEVICE) syslog (LOG_NOTICE, s1); if (debug) printf("%s: %s", timeBuf, s1); sprintf(s1, "%s %d %d", event_wrapper, id, TELLSTICK_TURNON); system(s1); } else if (method == TELLSTICK_TURNOFF) { sprintf(s1, "OFF event from device %i\n", id); if (id != DUMMYDEVICE) syslog (LOG_NOTICE, s1); if (debug) printf("%s: %s", timeBuf, s1); sprintf(s1, "%s %d %d", event_wrapper, id, TELLSTICK_TURNOFF); system(s1); } else if (method == TELLSTICK_BELL) { sprintf(s1, "BELL event from device %i\n", id); if (id != DUMMYDEVICE) syslog (LOG_NOTICE, s1); if (debug) printf("%s: %s", timeBuf, s1); sprintf(s1, "%s %d %d", event_wrapper, id, TELLSTICK_BELL); system(s1); } else { sprintf(s1, "Unknown event from device %i\n", id); syslog (LOG_NOTICE, s1); if (debug) printf("%s: %s", timeBuf, s1); } closelog(); exit(0); } // child exit } } // Signal handlers for timeout and kill void timeout_handler(int signum) { do_report = 1; report_id = last_id; report_method = last_method; last_id = -1; last_method = -1; } void exit_handler(int signum) { do_exit = signum; } void reload_handler(int signum) { do_reload = 1; } void start_timer(int id, int method) { struct itimerval value; struct sigaction sa; // Report old if new event if ((id != last_id) || (method != last_method) ) { do_report = 1; report_id = last_id; report_method = last_method; } last_id = id; last_method = method; value.it_value.tv_sec = TIMEOUT_S; value.it_value.tv_usec = TIMEOUT_US; value.it_interval.tv_sec = 0; value.it_interval.tv_usec = 0; memset (&sa, 0, sizeof (sa)); sa.sa_handler = &timeout_handler; sigaction (SIGALRM, &sa, NULL); setitimer (ITIMER_REAL, &value, NULL); } // Signal handlers for Tellstick void WINAPI deviceEvent(int deviceId, int method, const char *data, int callbackId, void *context) { if (pID) start_timer(deviceId, method); // Ignore if child } void WINAPI deviceChange(int deviceId, int method, const char *data, int callbackId, void *context) { if (pID) start_timer(deviceId, method); // Ignore if child } void WINAPI sensorEvent(const char *protocol, const char *model, int sensorId, int dataType, const char *value, int ts, int callbackId, void *context) { char timeBuf[80]; time_t timestamp = ts; char s1[60]; strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); if (pID) { // Ignore if child // Print the sensor sprintf(s1, "%s, %s, %i\n", protocol, model, sensorId); syslog (LOG_NOTICE, s1); if (debug) printf(s1); // Retrieve the values the sensor supports if (dataType == TELLSTICK_TEMPERATURE) { sprintf(s1, "Temperature: %s", value); syslog (LOG_NOTICE, s1); sprintf(s1, "%s: Temperature: %s\n", timeBuf, value); if (debug) printf(s1); } else if (dataType == TELLSTICK_HUMIDITY) { sprintf(s1, "Humidity: %s", value); syslog (LOG_NOTICE, s1); sprintf(s1, "%s: Humidity: %s\n", timeBuf, value); if (debug) printf(s1); } } } int main(int argc, char *argv[]) { debug = argc -1; pid_t deamon_pid, sid; //syslog setlogmask (LOG_UPTO (LOG_NOTICE)); openlog ("eventd", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); syslog (LOG_NOTICE, "Program started"); if (!debug) { //syslog(LOG_NOTICE, "daemonizing..."); deamon_pid = fork(); if (deamon_pid < 0) { exit(EXIT_FAILURE); } if (deamon_pid > 0) { exit(EXIT_SUCCESS); } umask(0); sid = setsid(); if (sid < 0) { exit(EXIT_FAILURE); } if ((chdir("/")) < 0) { exit(EXIT_FAILURE); } close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); syslog(LOG_NOTICE, "Running as deamon"); } tdInit(); register_telldusd(); // trap POSIX exit signals signal(SIGHUP, reload_handler); signal(SIGINT, exit_handler); signal(SIGTERM, exit_handler); while(1) { sleep(1); waitpid(-1, NULL, WNOHANG); if (do_reload) { char s1[60]; sprintf (s1, "Recieved SIGHUP, reloading telldusd...\n"); syslog (LOG_NOTICE, s1); if (debug) printf(s1); unregister_telldusd(); register_telldusd(); do_reload = 0; } if (do_report) { do_report = 0; report_event(report_id, report_method); report_id = -1; report_method = -1; } if (do_exit) { char s1[60]; sprintf (s1, "Recieved signal %d, exiting...\n", do_exit); syslog (LOG_NOTICE, s1); if (debug) printf(s1); unregister_telldusd(); closelog(); waitpid(-1, NULL, WNOHANG); tdClose(); exit(do_exit); } } }