334 lines
5.6 KiB
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;
|
||
|
}
|
||
|
|