diff options
Diffstat (limited to 'src/modbuslog.c')
-rw-r--r-- | src/modbuslog.c | 316 |
1 files changed, 316 insertions, 0 deletions
diff --git a/src/modbuslog.c b/src/modbuslog.c new file mode 100644 index 0000000..be7a4d1 --- /dev/null +++ b/src/modbuslog.c @@ -0,0 +1,316 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + */ + +// gcc modbuslog.c -o modbuslog `pkg-config --libs --cflags libmodbus libconfig` + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> +#include <time.h> +#include <unistd.h> +#include <sys/select.h> +#include <signal.h> +#include <fcntl.h> + +#include <libconfig.h> +#include <modbus.h> + +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <net/if.h> +#include <string.h> + +#define SLAVE_ID 1 +#define START_ADDRESS 0 +#define NUMBER_REGISTERS 14 + +void minute_check(int signum) { + alarm(60); +} + +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[]) { + + const char *configfile = "/etc/modbuslog.cfg"; + + int DEBUG = 0; + int k; + for (k = 1; k < argc; k++) { + if (strcmp(argv[k], "-d") == 0) { + DEBUG = 1; + } + } + + 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); + + 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); + fprintf(stderr, "Unable to find configfile.\n"); + return -1; + } + + 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))) { + fprintf(stderr, + "Incomplete modbus configuration. Check configuration file.\n"); + return -1; + } + + if (DEBUG) { + printf("%s %s %d %c %d %d\n", mac_address(), modbus_device_address, + modbus_baud_rate, modbus_parity[0], modbus_data_bits, + modbus_stop_bits); + } + + modbus_t *ctx; + uint16_t tab_reg[4]; + uint8_t byte[8]; + int rc; + int i; + + signal(SIGALRM, minute_check); + alarm(60); + + for (;;) { + 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"); + + unsigned int num_readings = config_setting_length(readings); + + int i; + 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 (unixtime_min % intervalduration == 0) { + //printf("specified minute. %d %d\n", unixtime_min, + // intervalduration); + + ctx = modbus_new_rtu(modbus_device_address, modbus_baud_rate, + modbus_parity[0], modbus_data_bits, modbus_stop_bits); + + modbus_set_slave(ctx, slaveid); + modbus_set_debug(ctx, DEBUG); + + if (ctx == NULL) { + fprintf(stderr, "Unable to create libmodbus object.\n"); + //return -1; + } + + if (modbus_connect(ctx) == -1) { + fprintf(stderr, "Connection failed: %s\n", + modbus_strerror(errno)); + modbus_free(ctx); + //return -1; + } + + int retry = 0; + 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) { + fprintf(stderr, "ERROR: %s\n", 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); + + //<mac address>_YYYY_MM_DD_HH_MM_SS.log + time_t unixtime_day = ((((int) t) / 86400 * 86400) + 86400); + + struct tm midnight = *localtime(&unixtime_day); + + char filename[50]; + + sprintf(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(filename, "r"); + if (fp) { + fclose(fp); + } else { + // file doesn't exist. create it. + FILE *fp = fopen(filename, "w"); + fprintf( + fp, + "IntervalID|UTCDate|UTCTime|LOCALDate|LOCALTime|SensorID|RegisterID|Reading\n"); + fclose(fp); + } + + FILE *filehandle = fopen(filename, "a+"); + + int16_t registervalue = 0; + + int p; + 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]; + } + + switch (numregisters) { + case 1: + registervalue = byte[0]; + break; + 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]; + break; + } + + struct tm utc = *gmtime(&unixtime_min); + struct tm lc = *localtime(&unixtime_min); + + int intervalid; + FILE *intervalfile = fopen("/var/modbuslog/interval.txt", "r+"); + fscanf(intervalfile, "%d", &intervalid); + 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); + + modbus_close(ctx); + modbus_free(ctx); + + sleep(1); + //return 0; + + } + + //printf("%d ", slaveid); + } + //printf("%d\n", unixtime_min); + } +} |