aboutsummaryrefslogtreecommitdiffstats
path: root/src/modbuslog.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/modbuslog.c')
-rw-r--r--src/modbuslog.c316
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",
+ &registertype);
+
+ 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);
+ }
+}