sdm2mqtt/sdm2mqtt.c

164 lines
4.0 KiB
C

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <mosquitto.h>
#include <modbus/modbus.h>
#include "sdm.h"
#include "config.h"
int main(int argc, char **argv) {
int nmeters, i, err;
struct mosquitto *mosq;
modbus_t *mb;
sdm_t **sdms;
FILE **logfiles;
char *printme;
char buf[4096];
mosquitto_lib_init();
mosq = mosquitto_new(cfg.mosq_name, false, NULL);
if (mosq == NULL) {
//FIXME
return -1;
}
err = mosquitto_connect(mosq, cfg.mosq_host, cfg.mosq_port, cfg.mosq_keepalive);
if (err != MOSQ_ERR_SUCCESS) {
//FIXME
return -1;
}
mb = modbus_new_rtu(cfg.ser_device, cfg.ser_baud, cfg.ser_parity, cfg.ser_databits, cfg.ser_stopbits);
if (mb == NULL) {
fprintf(stderr, "%s:%d: failed to create Modbus Context\n", __FILE__, __LINE__);
return -1;
}
if (modbus_connect(mb) == -1) {
fprintf(stderr, "%s:%d: Modbus connection failed: %s\n", __FILE__, __LINE__, modbus_strerror(errno));
return -2;
}
nmeters = 0;
while (cfg.meters[nmeters].friendlyname != NULL) {
nmeters++;
}
sdms = (sdm_t **)calloc(sizeof(sdm_t *) * nmeters, 1);
logfiles = (FILE **)calloc(sizeof(FILE *) * nmeters, 1);
for (i = 0; i < nmeters; i++) {
err = 0;
sdms[i] = sdm_new(mb, cfg.meters[i].addr, cfg.meters[i].friendlyname, cfg.meters[i].type, &err);
if (sdms[i] == NULL) {
fprintf(stderr, "%s:%d: Failed to create meter %s\n", __FILE__, __LINE__, cfg.meters[i].friendlyname);
}
snprintf(buf, 4095, "logs/%s.log", sdms[i]->friendlyname);
logfiles[i] = fopen(buf, "r");
if (logfiles[i] == NULL) {
char *header;
logfiles[i] = fopen(buf, "a");
if (logfiles[i] == NULL) {
fprintf(stderr, "%s:%d: Failed to open logfile %s:\n", __FILE__, __LINE__, cfg.meters[i].friendlyname);
perror("");
}
if (sdm_print_csv_header(sdms[i], &header)) {
//FIXME
}
fprintf(logfiles[i], "%s\n", header);
free(header);
} else {
logfiles[i] = freopen(buf, "a", logfiles[i]);
}
if (logfiles[i] == NULL) {
fprintf(stderr, "%s:%d: Failed to open logfile %s:\n", __FILE__, __LINE__, cfg.meters[i].friendlyname);
perror("");
}
}
while (1) {
for (i = 0; i < nmeters; i++) {
if (sdm_update(sdms[i]) != SDM_OK) {
int errsv = errno;
fprintf(stderr, "%s:%d: %s: %s (%d)\n", __FILE__, __LINE__, modbus_strerror(errsv), sdms[i]->friendlyname, sdms[i]->address);
if (errsv == ECONNRESET || errsv == EBADF) {
// USB Connection failed?
// try to reconnect...
modbus_close(mb);
if (modbus_connect(mb) == -1) {
fprintf(stderr, "%s:%d: Modbus reconnect failed: %s\n", __FILE__, __LINE__, modbus_strerror(errno));
sleep(1);
}
}
}
if (sdm_print_csv(sdms[i], &printme) != SDM_OK) {
fprintf(stderr, "%s:%d: error in sdm_print_csv!\n", __FILE__, __LINE__);
} else {
fprintf(logfiles[i], "%s\n", printme);
fflush(logfiles[i]);
free(printme);
}
if (sdm_print_json(sdms[i], &printme) != SDM_OK) {
fprintf(stderr, "%s:%d: error in sdm_print_json!\n", __FILE__, __LINE__);
} else {
int err;
//FIXME
char topic[256];
snprintf(topic, 255, "%s/%s", cfg.mosq_topicprefix, sdms[i]->friendlyname);
err = mosquitto_publish(mosq, NULL, topic, strlen(printme), printme, 0, false);
if (err != MOSQ_ERR_SUCCESS) {
fprintf(stderr, "%s:%d: mosquitto error! (%d)\n", __FILE__, __LINE__, err);
err = mosquitto_reconnect(mosq);
if (err != MOSQ_ERR_SUCCESS) {
//FIXME
fprintf(stderr, "%s:%d: Mosquitto reconnect failed.\n", __FILE__, __LINE__);
}
err = mosquitto_publish(mosq, NULL, topic, strlen(printme), printme, 0, false);
if (err != MOSQ_ERR_SUCCESS) {
//FIXME
fprintf(stderr, "%s:%d: publish failed after reconnect.\n", __FILE__, __LINE__);
}
}
free(printme);
}
usleep(10000);
}
}
for (i = 0; i < nmeters; i++) {
sdm_free(sdms[i]);
fclose(logfiles[i]);
}
free(logfiles);
free(sdms);
modbus_close(mb);
//broken: "free(): double free detected in tcache 2"
//modbus_free(mb);
mosquitto_lib_cleanup();
return 0;
}