#include #include #include #include #include #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; }