/* * modbuslog * * Copyright (C) 2011 Jonathan McCrohan * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ // gcc modbuslog.c -o modbuslog `pkg-config --libs --cflags libmodbus libconfig` #ifndef VERSION_STRING #define VERSION_STRING "[undefined version]" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // handle SIGALRM by resetting it void minute_check(int signum) { alarm(60); } // get mac address of primary interface eth0 char *mac_address() { int s; struct ifreq ifr; s = socket(PF_INET, SOCK_DGRAM, 0); memset(&ifr, 0x00, sizeof(ifr)); strcpy(ifr.ifr_name, "eth0"); ioctl(s, SIOCGIFHWADDR, &ifr); close(s); static char mac_address[12]; sprintf(mac_address, "%.2X%.2X%.2X%.2X%.2X%.2X", (unsigned char) ifr.ifr_hwaddr.sa_data[0], (unsigned char) ifr.ifr_hwaddr.sa_data[1], (unsigned char) ifr.ifr_hwaddr.sa_data[2], (unsigned char) ifr.ifr_hwaddr.sa_data[3], (unsigned char) ifr.ifr_hwaddr.sa_data[4], (unsigned char) ifr.ifr_hwaddr.sa_data[5]); return mac_address; } int main(int argc, char *argv[]) { int DEBUG = 0; int SYSLOG_CONSOLE_OUTPUT = 0; int k; // check the argv array for strings matching -d for (k = 1; k < argc; k++) { if (strcmp(argv[k], "-d") == 0) { DEBUG = 1; SYSLOG_CONSOLE_OUTPUT = LOG_PERROR; } } openlog("modbuslog", SYSLOG_CONSOLE_OUTPUT | LOG_PID | LOG_CONS, LOG_USER); syslog(LOG_INFO, ""); syslog(LOG_INFO, "modbuslog [%s] starting", VERSION_STRING); syslog(LOG_INFO, ""); const char *configfile = "/etc/modbuslog.cfg"; config_t cfg; //config_setting_t *setting; const char *modbus_device_address; int modbus_baud_rate; int modbus_data_bits; const char *modbus_parity; int modbus_stop_bits; int modbus_retry; config_init(&cfg); // attempt to read config // loads entire file to memory and destroys file descriptor if (!config_read_file(&cfg, configfile)) { fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg)); config_destroy(&cfg); syslog(LOG_ERR, "Unable to find configfile"); return -1; } else { syslog(LOG_INFO, "configfile found successfully"); } // die if core config file options aren't there if (!(config_lookup_string(&cfg, "modbus.device", &modbus_device_address) && config_lookup_int(&cfg, "modbus.baud", &modbus_baud_rate) && config_lookup_int(&cfg, "modbus.data_bits", &modbus_data_bits) && config_lookup_string(&cfg, "modbus.parity", &modbus_parity) && config_lookup_int(&cfg, "modbus.stop_bits", &modbus_stop_bits) && config_lookup_int(&cfg, "modbus.retry", &modbus_retry))) { syslog(LOG_ERR, "Incomplete modbus configuration. Check configuration file"); closelog(); return -1; } syslog(LOG_INFO, "MAC=[%s]", mac_address()); syslog(LOG_INFO, "Serial Port=[%s]", modbus_device_address); syslog(LOG_INFO, "Serial Port Parameters=[%d %d %c %d]", modbus_baud_rate, modbus_data_bits, modbus_parity[0], modbus_stop_bits); modbus_t *ctx; uint16_t tab_reg[4]; uint8_t byte[8]; int rc; int i; // used to force a reading 2 mins after power on int firstrun; firstrun = 1; // SIGALRM used to wake for loop up every 60 secs // sleep puts whole thread to sleep which isn't what we want // other methods involve CPU spinlocks which are inefficient signal(SIGALRM, minute_check); alarm(60); for (;;) { // block until SIGARLM select(0, NULL, NULL, NULL, NULL); time_t t = time(NULL); time_t unixtime_min = (((int) t) / 60 * 60); //int unixtime = (int) t; //printf("%d\n", unixtime); config_setting_t *readings; readings = config_lookup(&cfg, "reading"); // find number of required readings unsigned int num_readings = config_setting_length(readings); int i; // cycle through each reading and pull info from config file for (i = 0; i < num_readings; ++i) { config_setting_t *register_element = config_setting_get_elem( readings, i); int slaveid; config_setting_lookup_int(register_element, "slaveid", &slaveid); int intervalvalue; config_setting_lookup_int(register_element, "intervalvalue", &intervalvalue); //printf("%d", intervalvalue); int registertype; config_setting_lookup_int(register_element, "registertype", ®istertype); int startaddress; config_setting_lookup_int(register_element, "startaddress", &startaddress); int numregisters; config_setting_lookup_int(register_element, "numregisters", &numregisters); const char *intervalunit; config_setting_lookup_string(register_element, "intervalunit", &intervalunit); //printf("%c", intervalunit[0]); int intervalduration; if (intervalunit[0] == 'h') intervalduration = intervalvalue * 3600; else intervalduration = intervalvalue * 60; // if we match the required time for the reading or first run if ((unixtime_min % intervalduration == 0) || firstrun) { //printf("specified minute. %d %d\n", unixtime_min, // intervalduration); // attempt to create new modbus connection ctx = modbus_new_rtu(modbus_device_address, modbus_baud_rate, modbus_parity[0], modbus_data_bits, modbus_stop_bits); if (ctx == NULL) { syslog(LOG_ERR, "Unable to create libmodbus object"); } modbus_set_slave(ctx, slaveid); modbus_set_debug(ctx, DEBUG); if (modbus_connect(ctx) == -1) { syslog(LOG_ERR, "libmodbus: Connection failed: [%s]", modbus_strerror(errno)); modbus_free(ctx); // if connection fails, skip rest of loop syslog( LOG_ERR, "Skipping read from slaveid=[%i], registertype=[%i], startaddress=[%i], numregisters=[%i]", slaveid, registertype, startaddress, numregisters); continue; } int retry = 0; // handle timeouts and retries do { switch (registertype) { case 3: rc = modbus_read_registers(ctx, startaddress, numregisters, tab_reg); break; case 4: rc = modbus_read_input_registers(ctx, startaddress, numregisters, tab_reg); break; default: rc = modbus_read_registers(ctx, startaddress, numregisters, tab_reg); break; } if (rc == -1) { syslog(LOG_ERR, "libmodbus error: [%s]", modbus_strerror(errno)); } retry++; } while ((rc != -1) && (retry < (modbus_retry + 1))); //MODBUS_GET_HIGH_BYTE(data); //MODBUS_GET_LOW_BYTE(data); //MODBUS_SET_INT16_TO_INT8(tab_int8, index, value); // round forward to next midnight time_t unixtime_day = ((((int) t) / 86400 * 86400) + 86400); struct tm midnight = *localtime(&unixtime_day); char log_filename[50]; //_YYYY_MM_DD_HH_MM_SS.log sprintf(log_filename, "/var/modbuslog/%s_%04i_%02i_%02i_%02i_%02i_%02i.log", mac_address(), midnight.tm_year + 1900, midnight.tm_mon + 1, midnight.tm_mday, midnight.tm_hour, midnight.tm_min, midnight.tm_sec); //printf("%s\n",filename); FILE *fp = fopen(log_filename, "r"); if (fp) { fclose(fp); } else { // file doesn't exist. create it. syslog(LOG_NOTICE, "logfile does not exist"); syslog(LOG_INFO, "creating file: [%s]", log_filename); FILE *fp = fopen(log_filename, "w"); fprintf( fp, "IntervalID|UTCDate|UTCTime|LOCALDate|LOCALTime|SensorID|RegisterID|Reading\n"); fclose(fp); } FILE *filehandle = fopen(log_filename, "a+"); syslog(LOG_DEBUG, "opening file for append: [%s]", log_filename); int32_t registervalue = 0; int p; // data arrives in words, split into bytes for (p = 0; p < numregisters; p++) { MODBUS_SET_INT16_TO_INT8(byte, p * 2, tab_reg[p]); //registervalue += tab_reg[i] + tab_reg[i + 1]; } // bitshifting magic switch (numregisters*2) { case 2: registervalue = ((byte[0]) << 8) + byte[1]; break; case 4: registervalue = ((byte[0]) << 24) + ((byte[1]) << 16) + ((byte[2]) << 8) + byte[3]; break; default: registervalue = ((byte[0]) << 8) + byte[1]; break; } struct tm utc = *gmtime(&unixtime_min); struct tm lc = *localtime(&unixtime_min); int intervalid; char interval_filename[50]; sprintf(interval_filename, "/var/modbuslog/interval/interval.txt"); syslog(LOG_DEBUG, "opening interval file: [%s]", interval_filename); FILE *intervalfile = fopen(interval_filename, "r+"); if (intervalfile) { fclose(intervalfile); } else { // file doesn't exist. create it. syslog(LOG_NOTICE, "interval file does not exist"); syslog(LOG_INFO, "attempting to create file: [%s]", interval_filename); intervalfile = fopen(interval_filename, "w"); fprintf(intervalfile, "0\n"); fclose(intervalfile); } // file now exists, try opening again intervalfile = fopen(interval_filename, "r+"); fscanf(intervalfile, "%d", &intervalid); //handle 32bit signed overflow if (intervalid >= 2147483647) { intervalid = 0; } else { intervalid++; } rewind(intervalfile); fprintf(intervalfile, "%d", intervalid); fclose(intervalfile); fprintf( filehandle, "%i|%04i%02i%02i|%02i%02i%02i|%04i%02i%02i|%02i%02i%02i|%i|%i|%i\n", intervalid, utc.tm_year + 1900, utc.tm_mon + 1, utc.tm_mday, utc.tm_hour, utc.tm_min, utc.tm_sec, lc.tm_year + 1900, lc.tm_mon + 1, lc.tm_mday, lc.tm_hour, lc.tm_min, lc.tm_sec, slaveid, startaddress, registervalue); fclose(filehandle); syslog( LOG_DEBUG, "[%i|%04i%02i%02i|%02i%02i%02i|%04i%02i%02i|%02i%02i%02i|%i|%i|%i]\n", intervalid, utc.tm_year + 1900, utc.tm_mon + 1, utc.tm_mday, utc.tm_hour, utc.tm_min, utc.tm_sec, lc.tm_year + 1900, lc.tm_mon + 1, lc.tm_mday, lc.tm_hour, lc.tm_min, lc.tm_sec, slaveid, startaddress, registervalue); modbus_close(ctx); modbus_free(ctx); sleep(1); //return 0; } //printf("%d ", slaveid); } // revert to normal timing firstrun = 0; //printf("%d\n", unixtime_min); } } ='deletions'>-2/+12 compile error in parport fixed (thanks to Andrew from FilmCan) git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@251 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-10-03[lcd4linux @ 2003-10-03 03:51:14 by reinelt]reinelt2-46/+92 start support for new MatrixOrbital MX2 displays git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@250 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-09-29[lcd4linux @ 2003-09-29 06:58:36 by reinelt]reinelt7-15/+381 new driver for Milford Instruments MI420 by Andy Baxter git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@249 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-09-29[lcd4linux @ 2003-09-29 06:12:56 by reinelt]reinelt3-15/+22 changed default HD44780 wiring: unused signals are GND git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@248 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-09-21[lcd4linux @ 2003-09-21 06:43:02 by reinelt]reinelt2-2/+71 MatrixOrbital: bidirectional communication HD44780: special handling for 16x1 displays (thanks to anonymous bug report on sf.net) git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@247 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-09-19[lcd4linux @ 2003-09-19 08:40:32 by reinelt]reinelt4-27/+54 increased version number to 0.9.12 port locking is done as /var/lock/LCK..usb_tts_0 for /dev/usb/tts/0 git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@246 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-09-19[lcd4linux @ 2003-09-19 03:51:29 by reinelt]reinelt6-17/+160 minor fixes, widget.c added git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@245 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-09-13[lcd4linux @ 2003-09-13 07:20:51 by reinelt]reinelt3-12/+32 Changelog git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@244 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-09-13[lcd4linux @ 2003-09-13 06:45:43 by reinelt]reinelt9-57/+188 icons for all remaining drivers git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@243 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-09-13[lcd4linux @ 2003-09-13 06:20:39 by reinelt]reinelt7-8673/+459 HD44780 timings changed; deactivated libtool git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@242 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-09-11[lcd4linux @ 2003-09-11 15:05:24 by reinelt]reinelt3-89/+1519 missing files for autoconf/automake/libtool git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@241 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-09-11[lcd4linux @ 2003-09-11 04:09:52 by reinelt]reinelt6-14/+46 minor cleanups git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@240 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-09-10[lcd4linux @ 2003-09-10 15:59:39 by reinelt]reinelt4-13/+391 minor cleanups git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@239 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-09-10[lcd4linux @ 2003-09-10 15:09:21 by reinelt]reinelt1-0/+28 ChangeLog git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@238 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-09-10[lcd4linux @ 2003-09-10 14:01:52 by reinelt]reinelt6-21/+110 icons nearly finished\! git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@237 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-09-10[lcd4linux @ 2003-09-10 08:37:09 by reinelt]reinelt2-50/+73 icons: reorganized tick_* again... git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@236 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-09-10[lcd4linux @ 2003-09-10 03:48:22 by reinelt]reinelt7-47/+130 Icons for M50530, new processing scheme (Ticks.Text...) git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@235 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-09-09[lcd4linux @ 2003-09-09 11:47:47 by reinelt]reinelt3-14/+37 basic icon support for HD44780 git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@234 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-09-09[lcd4linux @ 2003-09-09 06:54:43 by reinelt]reinelt15-135/+177 new function 'cfg_number()' git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@233 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-09-09[lcd4linux @ 2003-09-09 05:30:33 by reinelt]reinelt11-90/+243 even more icons stuff git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@232 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-09-01[lcd4linux @ 2003-09-01 07:07:03 by reinelt]reinelt8-402/+13825 shared liblcd4linux git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@231 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-09-01[lcd4linux @ 2003-09-01 04:09:34 by reinelt]reinelt9-28/+127 icons nearly finished, but MatrixOrbital only git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@230 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-08-24[lcd4linux @ 2003-08-24 05:28:31 by reinelt]reinelt1-119/+156 ChangeLog git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@229 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-08-24[lcd4linux @ 2003-08-24 05:17:58 by reinelt]reinelt25-131/+217 liblcd4linux patch from Patrick Schemitz git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@228 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-08-24[lcd4linux @ 2003-08-24 04:31:56 by reinelt]reinelt6-11/+154 icon.c icon.h added git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@227 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-08-22[lcd4linux @ 2003-08-22 03:45:08 by reinelt]reinelt3-8/+25 bug in parallel port code fixed, more icons stuff git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@226 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-08-20[lcd4linux @ 2003-08-20 05:26:43 by reinelt]reinelt1-9/+11 small bug in bar compaction fixed git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@225 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-08-19[lcd4linux @ 2003-08-19 05:23:55 by reinelt]reinelt2-62/+123 HD44780 dual-controller patch from Jesse Brook Kovach git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@224 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-08-19[lcd4linux @ 2003-08-19 04:28:41 by reinelt]reinelt4-19/+42 more Icon stuff, minor glitches fixed git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@223 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-08-17[lcd4linux @ 2003-08-17 16:37:39 by reinelt]reinelt5-23/+77 more icon framework git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@222 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-08-17[lcd4linux @ 2003-08-17 12:11:58 by reinelt]reinelt6-27/+118 framework for icons prepared git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@221 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-08-17[lcd4linux @ 2003-08-17 08:25:30 by reinelt]reinelt6-46/+185 preparations for liblcd4linux; minor bugs in SIN.c and Skeleton.c git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@220 3ae390bd-cb1e-0410-b409-cd5a39f66f1f 2003-08-17[lcd4linux @ 2003-08-17 06:57:04 by reinelt]reinelt5-544/+325 complete rewrite of the Crystalfontz driver git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@219 3ae390bd-cb1e-0410-b409-cd5a39f66f1f