diff -r eee0f52170e8 -r 9c69d43bfb06 thermferm/mqtt.c --- a/thermferm/mqtt.c Mon Jan 07 13:23:17 2019 +0100 +++ b/thermferm/mqtt.c Thu Jan 10 16:33:42 2019 +0100 @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (C) 2016-2018 + * Copyright (C) 2016-2019 * * Michiel Broek * @@ -21,6 +21,8 @@ *****************************************************************************/ #include "thermferm.h" +#include "logger.h" +#include "devices.h" #include "xutil.h" #include "mqtt.h" @@ -159,8 +161,9 @@ void my_message_callback(struct mosquitto *my_mosq, void *userdata, const struct mosquitto_message *message) { - char *message_type; - struct json_object *jobj, *metric, *val; + char *message_type, *message_node, *message_alias; + units_list *unit; + struct json_object *jobj, *metric, *val, *setpoint; time_t timestamp; int timediff; @@ -171,6 +174,8 @@ strtok(message->topic, "/"); // Ignore mbv1.0 strtok(NULL, "/"); // Ignore group_id message_type = strtok(NULL, "/"); + message_node = strtok(NULL, "/\0"); + message_alias = strtok(NULL, "\0"); jobj = json_tokener_parse(message->payload); if (json_object_object_get_ex(jobj, "timestamp", &val)) { @@ -200,6 +205,166 @@ return; } } + 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) { + syslog(LOG_NOTICE, "DCMD change fermenter %s: stage to %s", message_alias, UNITSTAGE[i]); + unit->mqtt_flag |= MQTT_FLAG_DATA; + unit->stage = i; + } + break; + } + } + } + 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) { + if (unit->mode != i) { + syslog(LOG_NOTICE, "DCMD change fermenter %s: mode to %s", message_alias, UNITMODE[i]); + unit->mqtt_flag |= MQTT_FLAG_DATA; + /* Initialize log if the unit is turned on */ + if ((unit->mode == UNITMODE_OFF) && (i != UNITMODE_OFF)) { + initlog(unit->product_code, unit->product_name); + unit->mqtt_flag |= MQTT_FLAG_BIRTH; + } else if ((unit->mode != UNITMODE_OFF) && (i == UNITMODE_OFF)) { + unit->mqtt_flag |= MQTT_FLAG_DEATH; + } + syslog(LOG_NOTICE, "Fermenter unit %s mode %s to %s", unit->uuid, UNITMODE[unit->mode], UNITMODE[i]); + unit->mode = i; + /* Allways turn everything off after a mode change */ + unit->PID_cool->OutP = unit->PID_heat->OutP = 0.0; + unit->PID_cool->Mode = unit->PID_heat->Mode = PID_MODE_NONE; + unit->heater_state = unit->cooler_state = unit->fan_state = unit->light_state = 0; + unit->heater_wait = unit->cooler_wait = unit->fan_wait = unit->light_wait = 0; + device_out(unit->heater_address, unit->heater_state); + device_out(unit->cooler_address, unit->cooler_state); + device_out(unit->fan_address, unit->fan_state); + device_out(unit->light_address, unit->light_state); + if (unit->mode == UNITMODE_PROFILE) { + /* + * Set a sane default until it will be overruled by the + * main processing loop. + */ + unit->prof_target_lo = unit->prof_target_hi = 20.0; + unit->prof_fridge_mode = 0; + if (unit->profile) { + unit->mqtt_flag |= MQTT_FLAG_DATA; + } + } + } + break; + } + } + } + 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. + */ + 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)) { + unit->PID_cool->SetP = json_object_get_double(val); + } + if (unit->mode == UNITMODE_FRIDGE) { + unit->fridge_set = unit->PID_heat->SetP + ((unit->PID_cool->SetP - unit->PID_heat->SetP) / 2); + } 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) { + unit->heater_state = json_object_get_int(val); + if (unit->heater_state) // Safety + unit->cooler_state = 0; + unit->mqtt_flag |= MQTT_FLAG_DATA; + syslog(LOG_NOTICE, "DCMD change fermenter %s: heater_state to %d", message_alias, unit->heater_state); + } + } + } + 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) { + unit->cooler_state = json_object_get_int(val); + if (unit->cooler_state) + unit->heater_state = 0; + unit->mqtt_flag |= MQTT_FLAG_DATA; + syslog(LOG_NOTICE, "DCMD change fermenter %s: cooler_state to %d", message_alias, unit->cooler_state); + } + } + } + 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) { + unit->fan_state = json_object_get_int(val); + unit->mqtt_flag |= MQTT_FLAG_DATA; + syslog(LOG_NOTICE, "DCMD change fermenter %s: fan_state to %d", message_alias, unit->fan_state); + } + } + } + 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) { + unit->light_state = json_object_get_int(val); + unit->mqtt_flag |= MQTT_FLAG_DATA; + syslog(LOG_NOTICE, "DCMD change fermenter %s: light_state to %d", message_alias, unit->light_state); + } + } + } + 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)) { + free(unit->product_code); + unit->product_code = xstrcpy((char *)json_object_get_string(val)); + unit->mqtt_flag |= MQTT_FLAG_DATA; + syslog(LOG_NOTICE, "DCMD change fermenter %s: product_code to `%s'", message_alias, unit->product_code); + } + } + if (json_object_object_get_ex(setpoint, "name", &val)) { + if (strcmp((char *)json_object_get_string(val), unit->product_name)) { + free(unit->product_name); + unit->product_name = xstrcpy((char *)json_object_get_string(val)); + unit->mqtt_flag |= MQTT_FLAG_DATA; + syslog(LOG_NOTICE, "DCMD change fermenter %s: product_name to `%s'", message_alias, unit->product_name); + } + } + } + } + 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 { + publishDData(unit); + } + if (unit->mqtt_flag & MQTT_FLAG_DEATH) { + publishDDeath(unit); + } + 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;