diff -r 9c69d43bfb06 -r 1e0192b295b9 thermferm/mqtt.c --- a/thermferm/mqtt.c Thu Jan 10 16:33:42 2019 +0100 +++ b/thermferm/mqtt.c Mon Jan 14 22:46:27 2019 +0100 @@ -21,6 +21,7 @@ *****************************************************************************/ #include "thermferm.h" +#include "rdconfig.h" #include "logger.h" #include "devices.h" #include "xutil.h" @@ -152,7 +153,7 @@ void my_log_callback(struct mosquitto *my_mosq, void *obj, int level, const char *str) { - syslog(LOG_NOTICE, "MQTT: %s", str); +// syslog(LOG_NOTICE, "MQTT: %s", str); if (debug) fprintf(stdout, "MQTT: %s\n", str); } @@ -163,7 +164,8 @@ { char *message_type, *message_node, *message_alias; units_list *unit; - struct json_object *jobj, *metric, *val, *setpoint; + prof_step *step, *oldstep; + struct json_object *jobj, *metric, *val, *setpoint, *profile, *profile1, *steps, *step1; time_t timestamp; int timediff; @@ -205,13 +207,16 @@ return; } } + + /* + * DCMD, commands and configuration changes for a single fermenter. + */ if ((strcmp(message_type, "DCMD") == 0) && message_node && message_alias) { syslog(LOG_NOTICE, "%s", (char *)json_object_get_string(metric)); for (unit = Config.units ; unit; unit = unit->next) { if (strcmp(unit->alias, message_alias) == 0) { syslog(LOG_NOTICE, "MQTT: DCMD for %s/%s", (char *)message_node, (char *)message_alias); if (json_object_object_get_ex(metric, "stage", &val)) { - // syslog(LOG_NOTICE, "Change state %s", UNITSTAGE[unit->stage]); for (int i = 0; i < 4; i++) { if (strcmp((char *)json_object_get_string(val), UNITSTAGE[i]) == 0) { if (unit->stage != i) { @@ -223,7 +228,7 @@ } } } - printf("start mode\n"); + if (json_object_object_get_ex(metric, "mode", &val)) { for (int i = 0; i < 4; i++) { if (strcmp((char *)json_object_get_string(val), UNITMODE[i]) == 0) { @@ -255,7 +260,7 @@ */ unit->prof_target_lo = unit->prof_target_hi = 20.0; unit->prof_fridge_mode = 0; - if (unit->profile) { + if (unit->profile_uuid) { unit->mqtt_flag |= MQTT_FLAG_DATA; } } @@ -264,28 +269,25 @@ } } } - printf("start setpoint\n"); + if (json_object_object_get_ex(metric, "setpoint", &setpoint)) { if ((unit->mode == UNITMODE_FRIDGE) || (unit->mode == UNITMODE_BEER)) { /* - * Only set new setpoints if running as FRIDGE or in BEER mode. + * Only set new setpoints if running in FRIDGE or in BEER mode. */ - if (json_object_object_get_ex(setpoint, "low", &val)) { + if (json_object_object_get_ex(setpoint, "low", &val)) unit->PID_heat->SetP = json_object_get_double(val); - } - if (json_object_object_get_ex(setpoint, "high", &val)) { + if (json_object_object_get_ex(setpoint, "high", &val)) unit->PID_cool->SetP = json_object_get_double(val); - } - if (unit->mode == UNITMODE_FRIDGE) { + if (unit->mode == UNITMODE_FRIDGE) unit->fridge_set = unit->PID_heat->SetP + ((unit->PID_cool->SetP - unit->PID_heat->SetP) / 2); - } else { + else unit->beer_set = unit->PID_heat->SetP + ((unit->PID_cool->SetP - unit->PID_heat->SetP) / 2); - } unit->mqtt_flag |= MQTT_FLAG_DATA; syslog(LOG_NOTICE, "DCMD change fermenter %s: setpoints %.1f %.1f", message_alias, unit->PID_heat->SetP, unit->PID_cool->SetP); } } - printf("start heater\n"); + if ((json_object_object_get_ex(metric, "heater", &setpoint)) && (unit->mode == UNITMODE_NONE)) { if (json_object_object_get_ex(setpoint, "state", &val)) { if (json_object_get_int(val) != unit->heater_state) { @@ -297,6 +299,7 @@ } } } + if ((json_object_object_get_ex(metric, "cooler", &setpoint)) && (unit->mode == UNITMODE_NONE)) { if (json_object_object_get_ex(setpoint, "state", &val)) { if (json_object_get_int(val) != unit->cooler_state) { @@ -308,6 +311,7 @@ } } } + if ((json_object_object_get_ex(metric, "fan", &setpoint)) && (unit->mode == UNITMODE_NONE)) { if (json_object_object_get_ex(setpoint, "state", &val)) { if (json_object_get_int(val) != unit->fan_state) { @@ -317,6 +321,7 @@ } } } + if ((json_object_object_get_ex(metric, "light", &setpoint)) && (unit->mode == UNITMODE_NONE)) { if (json_object_object_get_ex(setpoint, "state", &val)) { if (json_object_get_int(val) != unit->light_state) { @@ -326,7 +331,7 @@ } } } - printf("start product\n"); + if ((json_object_object_get_ex(metric, "product", &setpoint)) && (unit->mode == UNITMODE_OFF)) { if (json_object_object_get_ex(setpoint, "code", &val)) { if (strcmp((char *)json_object_get_string(val), unit->product_code)) { @@ -345,11 +350,134 @@ } } } + + if (json_object_object_get_ex(metric, "profile", &profile)) { + if (json_object_object_get_ex(profile, "command", &profile1)) { + syslog(LOG_NOTICE, "profile command"); + + } else if (json_object_object_get_ex(profile, "uuid", &profile1)) { +// syslog(LOG_NOTICE, "profile new profile"); + if ((unit->prof_state == PROFILE_OFF) || (unit->prof_state == PROFILE_DONE) || (unit->prof_state == PROFILE_ABORT)) { + if (unit->profile_uuid) + free(unit->profile_uuid); + if (unit->profile_name) + free(unit->profile_name); + if (unit->profile_steps) { + for (step = unit->profile_steps; step; step = oldstep) { + if (step->name) + free(step->name); + oldstep = step->next; + free(step); + } + } + unit->profile_steps = NULL; + unit->profile_duration = unit->profile_totalsteps = 0; +// syslog(LOG_NOTICE, "profile new profile: old cleared"); + + unit->profile_uuid = xstrcpy((char *)json_object_get_string(profile1)); + if (json_object_object_get_ex(profile, "name", &val)) { + unit->profile_name = xstrcpy((char *)json_object_get_string(val)); + } + if (json_object_object_get_ex(profile, "inittemp", &setpoint)) { + if (json_object_object_get_ex(setpoint, "low", &val)) { + unit->profile_inittemp_lo = json_object_get_double(val); + } + if (json_object_object_get_ex(setpoint, "high", &val)) { + unit->profile_inittemp_hi = json_object_get_double(val); + } + } + if (json_object_object_get_ex(profile, "fridgemode", &val)) { + unit->profile_fridge_mode = json_object_get_int(val); + if (unit->profile_fridge_mode) + unit->profile_fridge_mode = 100; + } + if (json_object_object_get_ex(profile, "steps", &steps)) { + int arraylen = json_object_array_length(steps); + syslog(LOG_NOTICE, "profile new profile: start %d steps", arraylen); + for (int i = 0; i < arraylen; i++) { + /* + * Parse the array of steps + */ + step1 = json_object_array_get_idx(steps, i); + unit->profile_totalsteps++; + + step = (prof_step *)malloc(sizeof(prof_step)); + step->next = NULL; + step->name = NULL; + step->steptime = step->resttime = step->fridge_mode = 0; + step->target_lo = step->target_hi = 20.0; + + if (json_object_object_get_ex(step1, "name", &val)) { + step->name = xstrcpy((char *)json_object_get_string(val)); + } + if (json_object_object_get_ex(step1, "steptime", &val)) { + step->steptime = json_object_get_int(val); + unit->profile_duration += step->steptime; + } + if (json_object_object_get_ex(step1, "resttime", &val)) { + step->resttime = json_object_get_int(val); + unit->profile_duration += step->resttime; + } + if (json_object_object_get_ex(step1, "fridgemode", &val)) { + step->fridge_mode = json_object_get_int(val); + if (step->fridge_mode) + step->fridge_mode = 100; + } + if (json_object_object_get_ex(step1, "target_lo", &val)) { + step->target_lo = json_object_get_double(val); + } + if (json_object_object_get_ex(step1, "target_hi", &val)) { + step->target_hi = json_object_get_double(val); + } + + syslog(LOG_NOTICE, "profile new profile: add step %d", unit->profile_totalsteps); + if (unit->profile_steps == NULL) { + unit->profile_steps = step; + } else { + for (oldstep = unit->profile_steps; oldstep; oldstep = oldstep->next) { + if (oldstep->next == NULL) { + oldstep->next = step; + break; + } + } + } + } + } + unit->mqtt_flag |= MQTT_FLAG_DATA; + syslog(LOG_NOTICE, "DCMD change fermenter %s: install profile `%s'", message_alias, unit->profile_name); + wrconfig(); + } + } else { + if ((unit->prof_state == PROFILE_OFF) || (unit->prof_state == PROFILE_DONE) || (unit->prof_state == PROFILE_ABORT)) { + syslog(LOG_NOTICE, "DCMD change fermenter %s: delete profile `%s'", message_alias, unit->profile_name); + if (unit->profile_uuid) + free(unit->profile_uuid); + if (unit->profile_name) + free(unit->profile_name); + unit->profile_uuid = unit->profile_name = NULL; + if (unit->profile_steps) { + for (step = unit->profile_steps; step; step = oldstep) { + if (step->name) + free(step->name); + oldstep = step->next; + free(step); + } + } + unit->profile_steps = NULL; + unit->profile_inittemp_lo = unit->profile_inittemp_hi = 20.0; + unit->prof_percent = unit->profile_fridge_mode = 0; + unit->prof_state = PROFILE_OFF; + unit->profile_duration = unit->profile_totalsteps = 0; + unit->prof_started = unit->prof_paused = unit->prof_primary_done = (time_t)0; + unit->prof_peak_abs = unit->prof_peak_rel = 0.0; + unit->mqtt_flag |= MQTT_FLAG_DATA; + wrconfig(); + } + } + } } + if (unit->mqtt_flag) { - printf("do mqtt flag\n"); - if (debug) - fprintf(stdout, "flag value %d\n", unit->mqtt_flag); if (unit->mqtt_flag & MQTT_FLAG_BIRTH) { publishDBirth(unit); } else { @@ -360,12 +488,9 @@ } unit->mqtt_flag |= MQTT_FLAG_DLOG; // Something to log } - printf("einde unit %s\n", unit->alias); } - printf("return\n"); return; } - printf("metric: %s\n", (char *)json_object_get_string(metric)); syslog(LOG_NOTICE, "MQTT: %s payload not understood\n", (char *)message->payload); return; } @@ -447,7 +572,6 @@ char *payload = NULL; char buf[128]; bool comma = false; - profiles_list *profile; prof_step *pstep; payload = xstrcpy((char *)"{"); @@ -618,7 +742,7 @@ payload = xstrcat(payload, (char *)",\"door\":{\"address\":\""); payload = xstrcat(payload, unit->door_address); payload = xstrcat(payload, (char *)"\",\"state\":"); - sprintf(buf, "%d", unit->door_state); + sprintf(buf, "%d", (unit->door_state) ? 0:1); payload = xstrcat(payload, buf); payload = xstrcat(payload, (char *)"}"); } else { @@ -659,59 +783,59 @@ /* * Loaded profile and state */ - if (unit->profile) { - for (profile = Config.profiles; profile; profile = profile->next) { - if (strcmp(unit->profile, profile->uuid) == 0) { - payload = xstrcat(payload, (char *)",\"profile\":{\"uuid\":\""); - payload = xstrcat(payload, unit->profile); - payload = xstrcat(payload, (char *)"\",\"name\":\""); - payload = xstrcat(payload, profile->name); - payload = xstrcat(payload, (char *)"\",\"state\":\""); - payload = xstrcat(payload, (char *)PROFSTATE[unit->prof_state]); - payload = xstrcat(payload, (char *)"\",\"percent\":"); - sprintf(buf, "%d", unit->prof_percent); + if (unit->profile_uuid) { + payload = xstrcat(payload, (char *)",\"profile\":{\"uuid\":\""); + payload = xstrcat(payload, unit->profile_uuid); + payload = xstrcat(payload, (char *)"\",\"name\":\""); + payload = xstrcat(payload, unit->profile_name); + payload = xstrcat(payload, (char *)"\",\"state\":\""); + payload = xstrcat(payload, (char *)PROFSTATE[unit->prof_state]); + payload = xstrcat(payload, (char *)"\",\"percent\":"); + sprintf(buf, "%d", unit->prof_percent); + payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"inittemp\":{\"low\":"); + sprintf(buf, "%.1f", unit->profile_inittemp_lo); + payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"high\":"); + sprintf(buf, "%.1f", unit->profile_inittemp_hi); + payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)"},\"fridgemode\":"); + sprintf(buf, "%d", unit->profile_fridge_mode); + payload = xstrcat(payload, buf); + comma = false; + if (unit->profile_steps) { + payload = xstrcat(payload, (char *)",\"steps\":["); + for (pstep = unit->profile_steps; pstep; pstep = pstep->next) { + if (comma) + payload = xstrcat(payload, (char *)","); + payload = xstrcat(payload, (char *)"{\"resttime\":"); + sprintf(buf, "%d", pstep->resttime); payload = xstrcat(payload, buf); - payload = xstrcat(payload, (char *)",\"inittemp\":{\"low\":"); - sprintf(buf, "%.1f", profile->inittemp_lo); + payload = xstrcat(payload, (char *)",\"steptime\":"); + sprintf(buf, "%d", pstep->steptime); + payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"target\":{\"low\":"); + sprintf(buf, "%.1f", pstep->target_lo); payload = xstrcat(payload, buf); payload = xstrcat(payload, (char *)",\"high\":"); - sprintf(buf, "%.1f", profile->inittemp_hi); + sprintf(buf, "%.1f", pstep->target_hi); payload = xstrcat(payload, buf); payload = xstrcat(payload, (char *)"},\"fridgemode\":"); - sprintf(buf, "%d", profile->fridge_mode); + sprintf(buf, "%d", pstep->fridge_mode); payload = xstrcat(payload, buf); - comma = false; - if (profile->steps) { - payload = xstrcat(payload, (char *)",\"steps\":["); - for (pstep = profile->steps; pstep; pstep = pstep->next) { - if (comma) - payload = xstrcat(payload, (char *)","); - payload = xstrcat(payload, (char *)"{\"resttime\":"); - sprintf(buf, "%d", pstep->resttime); - payload = xstrcat(payload, buf); - payload = xstrcat(payload, (char *)",\"steptime\":"); - sprintf(buf, "%d", pstep->steptime); - payload = xstrcat(payload, buf); - payload = xstrcat(payload, (char *)",\"target\":{\"low\":"); - sprintf(buf, "%.1f", pstep->target_lo); - payload = xstrcat(payload, buf); - payload = xstrcat(payload, (char *)",\"high\":"); - sprintf(buf, "%.1f", pstep->target_hi); - payload = xstrcat(payload, buf); - payload = xstrcat(payload, (char *)"},\"fridgemode\":"); - sprintf(buf, "%d", pstep->fridge_mode); - payload = xstrcat(payload, buf); - payload = xstrcat(payload, (char *)"}"); - comma = true; - } - payload = xstrcat(payload, (char *)"]"); - } else { - payload = xstrcat(payload, (char *)",\"steps\":null"); + if (pstep->name) { + payload = xstrcat(payload, (char *)",\"name\":\""); + payload = xstrcat(payload, pstep->name); + payload = xstrcat(payload, (char *)"\""); } payload = xstrcat(payload, (char *)"}"); - break; + comma = true; } + payload = xstrcat(payload, (char *)"]"); + } else { + payload = xstrcat(payload, (char *)",\"steps\":null"); } + payload = xstrcat(payload, (char *)"}"); } else { payload = xstrcat(payload, (char *)",\"profile\":null"); }