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