diff -r 9c69d43bfb06 -r 1e0192b295b9 thermferm/thermferm.c --- a/thermferm/thermferm.c Thu Jan 10 16:33:42 2019 +0100 +++ b/thermferm/thermferm.c Mon Jan 14 22:46:27 2019 +0100 @@ -49,7 +49,6 @@ extern int slcdHandle; int setupmenu = MENU_NONE; units_list *current_unit = NULL; /* In panel editor this points to the current unit. */ -profiles_list *current_profile = NULL; float temp_temp = 20.0; #ifndef HAVE_WIRINGPI_H @@ -274,18 +273,7 @@ slcdPuts(slcdHandle, "New mode PROFILE"); break; - case MENU_PROFILE_SELECT: snprintf(buf, Config.lcd_cols, "%s", current_profile->name); -#ifdef HAVE_WIRINGPI_H - lcdPuts(lcdHandle, buf); - lcdPosition(lcdHandle, 0, 1); - lcdPuts(lcdHandle, "Select profile"); -#endif - slcdPuts(slcdHandle, buf); - slcdPosition(slcdHandle, 0, 1); - slcdPuts(slcdHandle, "Select profile"); - break; - - case MENU_PROFILE_START: snprintf(buf, Config.lcd_cols, "%s", current_profile->name); + case MENU_PROFILE_START: snprintf(buf, Config.lcd_cols, "%s", current_unit->profile_name); #ifdef HAVE_WIRINGPI_H lcdPuts(lcdHandle, buf); lcdPosition(lcdHandle, 0, 1); @@ -296,7 +284,7 @@ slcdPuts(slcdHandle, "Start profile"); break; - case MENU_PROFILE_PAUSE: snprintf(buf, Config.lcd_cols, "%s", current_profile->name); + case MENU_PROFILE_PAUSE: snprintf(buf, Config.lcd_cols, "%s", current_unit->profile_name); #ifdef HAVE_WIRINGPI_H lcdPuts(lcdHandle, buf); lcdPosition(lcdHandle, 0, 1); @@ -307,7 +295,7 @@ slcdPuts(slcdHandle, "Pause profile"); break; - case MENU_PROFILE_ABORT: snprintf(buf, Config.lcd_cols, "%s", current_profile->name); + case MENU_PROFILE_ABORT: snprintf(buf, Config.lcd_cols, "%s", current_unit->profile_name); #ifdef HAVE_WIRINGPI_H lcdPuts(lcdHandle, buf); lcdPosition(lcdHandle, 0, 1); @@ -318,7 +306,7 @@ slcdPuts(slcdHandle, "Abort profile"); break; - case MENU_PROFILE_RESUME: snprintf(buf, Config.lcd_cols, "%s", current_profile->name); + case MENU_PROFILE_RESUME: snprintf(buf, Config.lcd_cols, "%s", current_unit->profile_name); #ifdef HAVE_WIRINGPI_H lcdPuts(lcdHandle, buf); lcdPosition(lcdHandle, 0, 1); @@ -329,7 +317,7 @@ slcdPuts(slcdHandle, "Resume profile"); break; - case MENU_PROFILE_GOOFF: snprintf(buf, Config.lcd_cols, "%s", current_profile->name); + case MENU_PROFILE_GOOFF: snprintf(buf, Config.lcd_cols, "%s", current_unit->profile_name); #ifdef HAVE_WIRINGPI_H lcdPuts(lcdHandle, buf); lcdPosition(lcdHandle, 0, 1); @@ -342,10 +330,10 @@ case MENU_TOP_SYS: #ifdef HAVE_WIRINGPI_H - lcdPuts(lcdHandle, "System menu"); + lcdPuts(lcdHandle, "System menu"); #endif - slcdPuts(slcdHandle, "System menu"); - break; + slcdPuts(slcdHandle, "System menu"); + break; case MENU_SYS_HALT: #ifdef HAVE_WIRINGPI_H @@ -413,8 +401,8 @@ * Set a sane default until it will be overruled by the * main processing loop. */ - current_unit->prof_target_lo = 19.8; - current_unit->prof_target_hi = 20.2; + current_unit->prof_target_lo = 20.0; + current_unit->prof_target_hi = 20.0; current_unit->prof_fridge_mode = 0; } } @@ -427,7 +415,6 @@ void panel_key_events(int key) { units_list *unit; - profiles_list *profile; int rc; switch (setupmenu) { @@ -505,8 +492,12 @@ go_menu(MENU_UNITS); if (key == KEY_DOWN) go_menu(MENU_MODE_NONE); - if (key == KEY_UP) - go_menu(MENU_MODE_PROFILE); + if (key == KEY_UP) { + if (current_unit->profile_uuid) + go_menu(MENU_MODE_PROFILE); + else + go_menu(MENU_MODE_BEER); + } if (key == KEY_ENTER) { change_mode(UNITMODE_OFF); go_menu(MENU_MODE_OFF); @@ -622,8 +613,12 @@ case MENU_MODE_BEER: if (key == KEY_ESCAPE) go_menu(MENU_UNITS); - if (key == KEY_DOWN) - go_menu(MENU_MODE_PROFILE); + if (key == KEY_DOWN) { + if (current_unit->profile_uuid) + go_menu(MENU_MODE_PROFILE); + else + go_menu(MENU_MODE_OFF); + } if (key == KEY_UP) go_menu(MENU_MODE_FRIDGE); if (key == KEY_ENTER) { @@ -661,14 +656,6 @@ break; case MENU_MODE_PROFILE: - if (current_unit->profile) { - for (current_profile = Config.profiles; current_profile; current_profile = current_profile->next) { - if (strcmp(current_profile->uuid, current_unit->profile) == 0) - break; - } - } else { - current_profile = NULL; - } if (key == KEY_ESCAPE) go_menu(MENU_UNITS); if (key == KEY_DOWN) @@ -678,10 +665,7 @@ if (key == KEY_ENTER) { if (current_unit->mode == UNITMODE_PROFILE) { switch (current_unit->prof_state) { - case PROFILE_OFF: if (current_unit->profile) - go_menu(MENU_PROFILE_START); - else - go_menu(MENU_PROFILE_SELECT); + case PROFILE_OFF: go_menu(MENU_PROFILE_START); break; case PROFILE_PAUSE: go_menu(MENU_PROFILE_RESUME); break; @@ -697,39 +681,9 @@ } break; - case MENU_PROFILE_SELECT: - if (key == KEY_ESCAPE) - go_menu(MENU_MODE_PROFILE); - if (key == KEY_DOWN) { - if (current_profile->next) { - current_profile = current_profile->next; - go_menu(MENU_PROFILE_SELECT); - } else { - go_menu(MENU_PROFILE_START); - } - } - if (key == KEY_UP) { - for (profile = Config.profiles; profile; profile = profile->next) { - if (profile->next && profile->next == current_profile) { - current_profile = profile; - go_menu(MENU_PROFILE_SELECT); - break; - } - } - go_menu(MENU_PROFILE_START); - } - if (key == KEY_ENTER) { - current_unit->profile = current_profile->uuid; - syslog(LOG_NOTICE, "Profile %s selected from panel", current_profile->name); - go_menu(MENU_PROFILE_START); - } - break; - case MENU_PROFILE_START: if (key == KEY_ESCAPE) go_menu(MENU_MODE_PROFILE); - if ((key == KEY_DOWN) || (key == KEY_UP)) - go_menu(MENU_PROFILE_SELECT); if (key == KEY_ENTER) { current_unit->prof_state = PROFILE_RUN; current_unit->prof_started = time(NULL); @@ -981,7 +935,6 @@ char use_heater[40], use_cooler[40], use_fan[40], room_temp[40]; time_t now, last = (time_t)0, ndata = (time_t)0;; units_list *unit; - profiles_list *profile; prof_step *step; int row, rc, run = 1, seconds = 0, minutes = 0, temp, deviation; int run_seconds, run_minutes, run_hours, tot_minutes, key; @@ -1078,7 +1031,7 @@ unit->heater_state = unit->cooler_state = unit->fan_state = unit->door_state = unit->light_state = 0; unit->heater_wait = unit->cooler_wait = unit->fan_wait = unit->light_wait = 0; if (unit->mode == UNITMODE_PROFILE) { - if (!unit->profile) + if (!unit->profile_uuid) syslog(LOG_NOTICE, "Starting unit `%s' in profile mode, no profile defined.", unit->alias); else { syslog(LOG_NOTICE, "Starting unit `%s' in profile state %s.", unit->alias, PROFSTATE[unit->prof_state]); @@ -1390,9 +1343,8 @@ /* * Handle profile */ - if ((unit->mode == UNITMODE_PROFILE) && (unit->profile)) { + if ((unit->mode == UNITMODE_PROFILE) && (unit->profile_uuid)) { /* - * unit->profile - uuid of the selected profile. * unit->prof_started - start time or 0 if not yet running. * unit->prof_state - PROFILE_OFF|PROFILE_PAUSE|PROFILE_RUN|PROFILE_DONE * unit->prof_target - Calculated target temperature. @@ -1401,171 +1353,174 @@ * unit->prof_peak_rel - Peak temperature between beer and fridge. * unit->prof_primary_done - time when primary fermentation was over the peak. */ - for (profile = Config.profiles; profile; profile = profile->next) { - if (strcmp(unit->profile, profile->uuid) == 0) { - /* - * Safe defaults - */ - unit->prof_target_lo = profile->inittemp_lo; - unit->prof_target_hi = profile->inittemp_hi; - unit->prof_fridge_mode = 0; + /* + * Safe defaults + */ + unit->prof_target_lo = unit->profile_inittemp_lo; + unit->prof_target_hi = unit->profile_inittemp_hi; + unit->prof_fridge_mode = 0; - switch (unit->prof_state) { - case PROFILE_OFF: - unit->prof_percent = 0; - break; - case PROFILE_PAUSE: - /* - * Keep current temperature, measure pause time. For - * temperature fall thru. - */ - unit->prof_paused++; - case PROFILE_RUN: + switch (unit->prof_state) { + case PROFILE_OFF: + unit->prof_percent = 0; + break; + case PROFILE_PAUSE: + /* + * Keep current temperature, measure pause time. For + * temperature fall thru. + */ + unit->prof_paused++; + case PROFILE_RUN: + /* + * Calculate current profile step and desired temperature. + * When all steps are done, set state to PROFILE_DONE. + */ + previous_target_lo = unit->profile_inittemp_lo; + previous_target_hi = unit->profile_inittemp_hi; + previous_fridge_mode = unit->profile_fridge_mode; + time_until_now = current_step = 0; + run_seconds = (int)(now - unit->prof_started - unit->prof_paused); + run_minutes = run_seconds / 60; + run_hours = run_minutes / 60; + if (debug) + fprintf(stdout, "run_HMS=%d,%d,%d ", run_hours, run_minutes, run_seconds); + + /* + * Primary fermentation tests + */ + if ((unit->beer_temperature / 1000.0) > unit->prof_peak_abs) + unit->prof_peak_abs = unit->beer_temperature / 1000.0; + if (((unit->beer_temperature - unit->air_temperature) / 1000.0) > unit->prof_peak_rel) + unit->prof_peak_rel = (unit->beer_temperature - unit->air_temperature) / 1000.0; + if (unit->prof_primary_done == 0) { + if (unit->cooler_address) { /* - * Calculate current profile step and desired temperature. - * When all steps are done, set state to PROFILE_DONE. - */ - previous_target_lo = profile->inittemp_lo; - previous_target_hi = profile->inittemp_hi; - previous_fridge_mode = profile->fridge_mode; - time_until_now = current_step = 0; - run_seconds = (int)(now - unit->prof_started - unit->prof_paused); - run_minutes = run_seconds / 60; - run_hours = run_minutes / 60; - if (debug) - fprintf(stdout, "run_HMS=%d,%d,%d ", run_hours, run_minutes, run_seconds); - - /* - * Primary fermentation tests - */ - if ((unit->beer_temperature / 1000.0) > unit->prof_peak_abs) - unit->prof_peak_abs = unit->beer_temperature / 1000.0; - if (((unit->beer_temperature - unit->air_temperature) / 1000.0) > unit->prof_peak_rel) - unit->prof_peak_rel = (unit->beer_temperature - unit->air_temperature) / 1000.0; - if (unit->prof_primary_done == 0) { - if (unit->cooler_address) { - /* - * There is a cooler. If the difference between the beer and air temperature - * drops we assume the primary fermentation is done. - */ - if (((unit->beer_temperature - unit->air_temperature) / 1000.0) < (unit->prof_peak_rel - 0.5)) { - unit->prof_primary_done = time(NULL); - syslog(LOG_NOTICE, "Profile `%s' primary fermentation is ready (cooler mode)", profile->name); - } - } else { - /* - * This method works if the unit has no cooling or if the profile allowed the - * beer temperature to rise freely. - */ - if ((unit->beer_temperature / 1000.0) < (unit->prof_peak_abs - 0.5)) { - unit->prof_primary_done = time(NULL); - syslog(LOG_NOTICE, "Profile `%s' primary fermentation is ready (free rise mode)", profile->name); - } - } - } - - /* - * See how long this profile will take + * There is a cooler. If the difference between the beer and air temperature + * drops we assume the primary fermentation is done. */ - tot_minutes = 0; - for (step = profile->steps; step; step = step->next) { - tot_minutes += ((step->steptime + step->resttime) * 60); + if (((unit->beer_temperature - unit->air_temperature) / 1000.0) < (unit->prof_peak_rel - 0.5)) { + unit->prof_primary_done = time(NULL); + syslog(LOG_NOTICE, "Profile `%s' primary fermentation is ready (cooler mode)", unit->profile_name); } + } else { + /* + * This method works if the unit has no cooling or if the profile allowed the + * beer temperature to rise freely. + */ + if ((unit->beer_temperature / 1000.0) < (unit->prof_peak_abs - 0.5)) { + unit->prof_primary_done = time(NULL); + syslog(LOG_NOTICE, "Profile `%s' primary fermentation is ready (free rise mode)", unit->profile_name); + } + } + } + + /* + * See how long this profile will take + */ + tot_minutes = 0; + for (step = unit->profile_steps; step; step = step->next) { + tot_minutes += ((step->steptime + step->resttime) * 60); + } + if ((tot_minutes == 0) && unit->profile_totalsteps) { + syslog(LOG_NOTICE, "Profile `%s' steps disappeared", unit->profile_name); + unit->prof_state = PROFILE_OFF; + break; + } - valid_step = FALSE; - for (step = profile->steps; step; step = step->next) { - /* - * step->steptime - * step->resttime - * step->target - */ - current_step++; - if ((run_hours >= time_until_now) && (run_hours < (time_until_now + step->steptime + step->resttime))) { - /* - * This is our current step - */ - valid_step = TRUE; - if (debug) - fprintf(stdout, "step=%d step_pos=%d step=%d/%d target=%.1f..%.1f ", - current_step, run_hours - time_until_now, - step->steptime, step->resttime, step->target_lo, step->target_hi); - if ((run_hours - time_until_now) < step->steptime) { - unit->prof_target_lo = previous_target_lo + (((run_minutes - (time_until_now * 60.0)) / (step->steptime * 60.0)) * (step->target_lo - previous_target_lo)); - unit->prof_target_hi = previous_target_hi + (((run_minutes - (time_until_now * 60.0)) / (step->steptime * 60.0)) * (step->target_hi - previous_target_hi)); - if (step->fridge_mode > previous_fridge_mode) { - unit->prof_fridge_mode = (((run_minutes - (time_until_now * 60)) * 100) / (step->steptime * 60)); - } else if (step->fridge_mode < previous_fridge_mode) { - unit->prof_fridge_mode = 100 - (((run_minutes - (time_until_now * 60)) * 100) / (step->steptime * 60)); - } else { - unit->prof_fridge_mode = step->fridge_mode; - } - if (debug) - fprintf(stdout, "tempshift=%.1f..%.1f minutes=%d duration=%d temp_move=%.3f..%.3f ", - step->target_lo - previous_target_lo, - step->target_hi - previous_target_hi, - run_minutes - (time_until_now * 60), - step->steptime * 60, unit->prof_target_lo, unit->prof_target_hi); - } else { - unit->prof_target_lo = step->target_lo; - unit->prof_target_hi = step->target_hi; - unit->prof_fridge_mode = step->fridge_mode; - if (debug) - fprintf(stdout, "resting target=%.1f..%.1f ", step->target_lo, step->target_hi); - } - break; + valid_step = FALSE; + for (step = unit->profile_steps; step; step = step->next) { + /* + * step->steptime + * step->resttime + * step->target + */ + current_step++; + if ((run_hours >= time_until_now) && (run_hours < (time_until_now + step->steptime + step->resttime))) { + /* + * This is our current step + */ + valid_step = TRUE; + // if (debug) + // fprintf(stdout, "step=%d step_pos=%d step=%d/%d target=%.1f..%.1f ", + // current_step, run_hours - time_until_now, + // step->steptime, step->resttime, step->target_lo, step->target_hi); + if ((run_hours - time_until_now) < step->steptime) { + unit->prof_target_lo = previous_target_lo + (((run_minutes - (time_until_now * 60.0)) / (step->steptime * 60.0)) * (step->target_lo - previous_target_lo)); + unit->prof_target_hi = previous_target_hi + (((run_minutes - (time_until_now * 60.0)) / (step->steptime * 60.0)) * (step->target_hi - previous_target_hi)); + if (step->fridge_mode > previous_fridge_mode) { + unit->prof_fridge_mode = (((run_minutes - (time_until_now * 60)) * 100) / (step->steptime * 60)); + } else if (step->fridge_mode < previous_fridge_mode) { + unit->prof_fridge_mode = 100 - (((run_minutes - (time_until_now * 60)) * 100) / (step->steptime * 60)); + } else { + unit->prof_fridge_mode = step->fridge_mode; } - time_until_now += step->steptime + step->resttime; - previous_target_lo = step->target_lo; - previous_target_hi = step->target_hi; - previous_fridge_mode = step->fridge_mode; - } - if (debug) - fprintf(stdout, " %s %02d:%02d\n", valid_step ? "TRUE":"FALSE", minutes, seconds); - - if (valid_step == TRUE) { - unit->prof_percent = (100 * run_minutes) / tot_minutes; - if (((minutes == 10) || (minutes == 40)) && (seconds == 1)) { - syslog(LOG_NOTICE, "Profile `%s' running %dd %02d:%02d in step %d, %d%% done, target %s %.3f..%.3f degrees", - profile->name, run_hours / 24, run_hours % 24, run_minutes % 60, current_step, - unit->prof_percent, unit->prof_fridge_mode ? (char *)"air":(char *)"beer", - unit->prof_target_lo, unit->prof_target_hi); - unit->mqtt_flag |= MQTT_FLAG_DATA; - } + if (debug) + fprintf(stdout, "prof_fridge_mode=%d run_minutes=%d steptime=%d time_until_now=%d\n", + unit->prof_fridge_mode, run_minutes, step->steptime, time_until_now); + // if (debug) + // fprintf(stdout, "tempshift=%.1f..%.1f minutes=%d duration=%d temp_move=%.3f..%.3f ", + // step->target_lo - previous_target_lo, + // step->target_hi - previous_target_hi, + // run_minutes - (time_until_now * 60), + // step->steptime * 60, unit->prof_target_lo, unit->prof_target_hi); } else { - /* - * No more steps to do - */ - unit->prof_state = PROFILE_DONE; - unit->prof_percent = 100; - syslog(LOG_NOTICE, "Profile `%s' is done", profile->name); - unit->mqtt_flag |= MQTT_FLAG_DATA; + unit->prof_target_lo = step->target_lo; + unit->prof_target_hi = step->target_hi; + unit->prof_fridge_mode = step->fridge_mode; + // if (debug) + // fprintf(stdout, "resting target=%.1f..%.1f ", step->target_lo, step->target_hi); } break; + } + time_until_now += step->steptime + step->resttime; + previous_target_lo = step->target_lo; + previous_target_hi = step->target_hi; + previous_fridge_mode = step->fridge_mode; + } + // if (debug) + // fprintf(stdout, " %s %02d:%02d\n", valid_step ? "TRUE":"FALSE", minutes, seconds); - case PROFILE_DONE: - /* - * Keep this state, set target temperature to the last step. - */ - previous_target_lo = profile->inittemp_lo; - previous_target_hi = profile->inittemp_hi; - previous_fridge_mode = profile->fridge_mode; - for (step = profile->steps; step; step = step->next) { - if ((step->steptime + step->resttime) == 0) - break; - previous_target_lo = step->target_lo; - previous_target_hi = step->target_hi; - previous_fridge_mode = step->fridge_mode; + if (valid_step == TRUE) { + unit->prof_percent = (100 * run_minutes) / tot_minutes; + if (((minutes == 10) || (minutes == 40)) && (seconds == 1)) { + syslog(LOG_NOTICE, "Profile `%s' running %dd %02d:%02d in step %d, %d%% done, target %s %.3f..%.3f degrees", + unit->profile_name, run_hours / 24, run_hours % 24, run_minutes % 60, current_step, + unit->prof_percent, unit->prof_fridge_mode ? (char *)"air":(char *)"beer", + unit->prof_target_lo, unit->prof_target_hi); + unit->mqtt_flag |= MQTT_FLAG_DATA; + } + } else { + /* + * No more steps to do + */ + unit->prof_state = PROFILE_DONE; + unit->prof_percent = 100; + syslog(LOG_NOTICE, "Profile `%s' is done", unit->profile_name); + unit->mqtt_flag |= MQTT_FLAG_DATA; + } + break; - } - unit->prof_target_lo = previous_target_lo; - unit->prof_target_hi = previous_target_hi; - unit->prof_fridge_mode = previous_fridge_mode; - unit->prof_percent = 100; + case PROFILE_DONE: + /* + * Keep this state, set target temperature to the last step. + */ + previous_target_lo = unit->profile_inittemp_lo; + previous_target_hi = unit->profile_inittemp_hi; + previous_fridge_mode = unit->profile_fridge_mode; + for (step = unit->profile_steps; step; step = step->next) { + if ((step->steptime + step->resttime) == 0) break; - } /* switch */ - } - } + previous_target_lo = step->target_lo; + previous_target_hi = step->target_hi; + previous_fridge_mode = step->fridge_mode; + } + unit->prof_target_lo = previous_target_lo; + unit->prof_target_hi = previous_target_hi; + unit->prof_fridge_mode = previous_fridge_mode; + unit->prof_percent = 100; + break; + } /* switch */ } else { /* * Set some sane values @@ -1628,8 +1583,8 @@ */ unit->PID_cool->Mode = unit->PID_heat->Mode = PID_MODE_NONE; if (unit->mode == UNITMODE_FRIDGE) { - unit->PID_cool->SetP = unit->fridge_set; // + unit->PID_cool->idleRange; - unit->PID_heat->SetP = unit->fridge_set; // - unit->PID_heat->idleRange; + unit->PID_cool->SetP = unit->fridge_set; + unit->PID_heat->SetP = unit->fridge_set; unit->PID_cool->Input = unit->PID_heat->Input = unit->air_temperature / 1000.0; unit->PID_cool->Mode = unit->PID_heat->Mode = PID_MODE_BOO; } else if (unit->mode == UNITMODE_BEER) { @@ -1794,9 +1749,6 @@ device_out(unit->cooler_address, 0); } } -// if (debug) -// fprintf(stdout, "Final: PIDheat=%.2f PWRheat=%d PIDcool=%.2f PWRcool=%d\n", -// unit->PID_heat->OutP, unit->heater_state, unit->PID_cool->OutP, unit->cooler_state); /* * If there is a fan, and the unit door is closed, and the unit should be doing