sdm2mqtt/sdm.c

334 lines
5.6 KiB
C

#include "sdm.h"
#include "sdm230m_registers.h"
#include "sdm630m_registers.h"
#include "sdm72dm_registers.h"
static char *sdm_typenames[] = {
"none",
"SDM230M",
"SDM630M",
"SDM72DM"
};
static void swap(sdm_values_t *value) {
uint16_t tmp;
tmp = value->v16[0];
value->v16[0] = value->v16[1];
value->v16[1] = tmp;
}
const char *sdm_gettypename(sdm_t *sdm) {
return sdm_typenames[sdm->type];
}
sdm_t *sdm_new(modbus_t *mb, int address, char *friendlyname, enum sdm_types type, int *error) {
sdm_t *sdm;
if (mb == NULL) {
*error = SDM_MB_ERR;
return NULL;
}
if (address <= 0 || address > 247) {
*error = SDM_ADDR_ERR;
return NULL;
}
if (friendlyname == NULL) {
*error = SDM_NAME_ERR;
return NULL;
}
sdm = (sdm_t *)calloc(sizeof(sdm_t), 1);
if (sdm == NULL) {
*error = SDM_MEM_ERR;
return NULL;
}
sdm->mb = mb;
sdm->address = address;
sdm->friendlyname = strdup(friendlyname);
if (sdm->friendlyname == NULL) {
free(sdm);
*error = SDM_MEM_ERR;
return NULL;
}
sdm->type = type;
switch (type) {
case SDM230M:
sdm->values = (sdm_values_t *)calloc(sizeof(sdm_values_t) * SMD230M_NRVAL, 1);
break;
case SDM630M:
sdm->values = (sdm_values_t *)calloc(sizeof(sdm_values_t) * SMD630M_NRVAL, 1);
break;
case SDM72DM:
sdm->values = (sdm_values_t *)calloc(sizeof(sdm_values_t) * SMD72DM_NRVAL, 1);
break;
default:
free(sdm->friendlyname);
free(sdm);
*error = SDM_MEM_ERR;
return NULL;
}
if (sdm->values == NULL) {
free(sdm->friendlyname);
free(sdm);
*error = SDM_MEM_ERR;
return NULL;
}
sdm->valid = false;
return sdm;
}
int sdm_free(sdm_t *sdm) {
if (sdm == NULL) {
return SDM_EMPTY;
}
free(sdm->friendlyname);
free(sdm->values);
free(sdm);
return SDM_OK;
}
int sdm_update(sdm_t *sdm) {
sdm_registers_t *regs;
sdm_values_t *value = sdm->values;
sdm->valid = false;
switch (sdm->type) {
case SDM230M:
regs = sdm230m_registers;
break;
case SDM630M:
regs = sdm630m_registers;
break;
case SDM72DM:
regs = sdm72dm_registers;
break;
case SDMNONE:
regs = NULL;
break;
}
modbus_flush(sdm->mb);
modbus_set_slave(sdm->mb, sdm->address);
while (regs->name != NULL) {
if (-1 == modbus_read_input_registers(sdm->mb, regs->regno, 2, value->v16)) {
return SDM_COMM_ERR;
}
swap(value);
regs++;
value++;
}
sdm->valid = true;
return SDM_OK;
}
int sdm_print_csv_header(sdm_t *sdm, char **header) {
char tmp[4096], *ret;
int free = 4095, used = 0, count = 0;
sdm_registers_t *regs;
sdm_values_t *value = sdm->values;
switch (sdm->type) {
case SDM230M:
regs = sdm230m_registers;
break;
case SDM630M:
regs = sdm630m_registers;
break;
case SDM72DM:
regs = sdm72dm_registers;
break;
case SDMNONE:
regs = NULL;
break;
}
count = snprintf(tmp, free, "time;friendlyname;address;typename;valid;");
if (count < 0 || count >= free) {
//FIXME ERRORHANDLING
return SDM_MEM_ERR;
}
free -= count;
used += count;
count = 0;
while (regs->name != NULL) {
count = snprintf(tmp + used, free, "%s;", regs->name);
if (count < 0 || count >= free) {
//FIXME ERRORHANDLING
return SDM_MEM_ERR;
}
free -= count;
used += count;
count = 0;
regs++;
value++;
}
ret = strdup(tmp);
if (ret == NULL) {
return SDM_MB_ERR;
}
*header = ret;
return SDM_OK;
return 0;
}
int sdm_print_csv(sdm_t *sdm, char **csv) {
char tmp[4096], *ret;
int free = 4095, used = 0, count = 0;
time_t now;
sdm_registers_t *regs;
sdm_values_t *value = sdm->values;
time(&now);
tmp[4095] = 0;
switch (sdm->type) {
case SDM230M:
regs = sdm230m_registers;
break;
case SDM630M:
regs = sdm630m_registers;
break;
case SDM72DM:
regs = sdm72dm_registers;
break;
case SDMNONE:
regs = NULL;
break;
}
count = strftime(tmp, free, "%FT%TZ;", gmtime(&now));
count += snprintf(tmp + count, free, "%s;%03d;%s;%s;", sdm->friendlyname, sdm->address, sdm_gettypename(sdm), sdm->valid?"true":"false");
if (count < 0 || count >= free) {
//FIXME ERRORHANDLING
return SDM_MEM_ERR;
}
free -= count;
used += count;
count = 0;
while (regs->name != NULL && sdm->valid == true) {
count = snprintf(tmp + used, free, "%f;", value->vf);
if (count < 0 || count >= free) {
//FIXME ERRORHANDLING
return SDM_MEM_ERR;
}
free -= count;
used += count;
count = 0;
regs++;
value++;
}
ret = strdup(tmp);
if (ret == NULL) {
return SDM_MB_ERR;
}
*csv = ret;
return SDM_OK;
}
int sdm_print_json(sdm_t *sdm, char **json) {
char tmp[4096], *ret;
int free = 4095, used = 0, count = 0;
sdm_registers_t *regs;
sdm_values_t *value = sdm->values;
tmp[4095] = 0;
switch (sdm->type) {
case SDM230M:
regs = sdm230m_registers;
break;
case SDM630M:
regs = sdm630m_registers;
break;
case SDM72DM:
regs = sdm72dm_registers;
break;
case SDMNONE:
regs = NULL;
break;
}
count = snprintf(tmp, free, "{\"name\":\"%s\",\"address\":%d,\"type\":\"%s\",\"valid\":%s", sdm->friendlyname, sdm->address, sdm_gettypename(sdm), sdm->valid?"true":"false");
if (count < 0 || count >= free) {
//FIXME ERRORHANDLING
return SDM_MEM_ERR;
}
free -= count;
used += count;
count = 0;
while (regs->name != NULL && sdm->valid == true) {
count = snprintf(tmp + used, free, ",\"%s\":%f", regs->name, value->vf);
if (count < 0 || count >= free) {
//FIXME ERRORHANDLING
return SDM_MEM_ERR;
}
free -= count;
used += count;
count = 0;
regs++;
value++;
}
count = snprintf(tmp + used, free, "}");
if (count < 0 || count >= free) {
//FIXME ERRORHANDLING
return SDM_MEM_ERR;
}
ret = strdup(tmp);
if (ret == NULL) {
return SDM_MB_ERR;
}
*json = ret;
return SDM_OK;
}