diff -r 24749c296a50 -r f5d85af156ab thermferm/simulator.c --- a/thermferm/simulator.c Tue Apr 30 17:26:41 2024 +0200 +++ b/thermferm/simulator.c Wed May 01 14:38:37 2024 +0200 @@ -20,7 +20,10 @@ * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *****************************************************************************/ +extern int debug; + #include "thermferm.h" +#include "statetbl.h" #include "delay.h" #include "xutil.h" #include "websocket.h" @@ -34,10 +37,9 @@ extern const char DEVPRESENT[4][6]; int my_simulator_shutdown = 0; -int SIMcooling = 0; -int SIMheating = 0; -int SIMfan = 0; -int SIMlight = 0; + + +static int simulate(void); /* @@ -193,14 +195,43 @@ void *my_simulator_loop(void *threadid) { + my_simulator_state = 1; + syslog(LOG_NOTICE, "Thread my_simulator_loop started"); + + /* + * Run the state machine + */ + simulate(); + + syslog(LOG_NOTICE, "Thread my_simulator_loop stopped"); + my_simulator_state = 0; + return 0; +} + + +SM_DECL(simulate, (char *)"simulator") +SM_STATES + Init, + Waiting, + Run, + Websocket +SM_NAMES + (char *)"Init", + (char *)"Waiting", + (char *)"run", + (char *)"Websocket" +SM_EDECL simulator_list *simulator; time_t now, last = (time_t)0; int seconds = 0; double k_room_air, sqm_room_air, thick_room_air, air_heat_transfer; double air_change, vhc_air = 0.00121; + double air_temp, beer_temp, chiller_temp; + bool changed = false; - my_simulator_state = 1; - syslog(LOG_NOTICE, "Thread my_simulator_loop started"); +SM_START(Init) + +SM_STATE(Init) for (simulator = Config.simulators; simulator; simulator = simulator->next) { /* @@ -208,86 +239,125 @@ */ simulator->s_heat_temp = simulator->s_cool_temp = simulator->room_temperature; } + SM_PROCEED(Waiting); - for (;;) { - if (my_simulator_shutdown) - break; +SM_STATE(Waiting) - now = time(NULL); - if (now != last) { - last = now; - /* - * Each second - */ - seconds++; + if (my_simulator_shutdown) { + SM_SUCCESS; + } + now = time(NULL); + if (now != last) { + last = now; + seconds++; + SM_PROCEED(Run); + } + mDelay(50L); + +SM_STATE(Run) - for (simulator = Config.simulators; simulator; simulator = simulator->next) { - if (my_simulator_shutdown) - break; + changed = false; + for (simulator = Config.simulators; simulator; simulator = simulator->next) { + if (my_simulator_shutdown) { + SM_SUCCESS; + } + + /* + * Copy to duplicates + */ + air_temp = simulator->air_temperature; + beer_temp = simulator->beer_temperature; + chiller_temp = simulator->chiller_temperature; - /* - * First, calculate temperature difference between the room and the air in the - * fridge. We use the volume air to roughly calculate the total area between - * the in and outside. Calculate the effect and shift the air temperature towards - * the room temperature. - */ - sqm_room_air = (cbrtl(simulator->volume_air) * cbrtl(simulator->volume_air) * 6) / 100; /* square meters all fridge sides */ - thick_room_air = 0.04; /* 4 cm walls */ - k_room_air = 0.03; /* Polystrene */ - air_heat_transfer=(k_room_air * sqm_room_air * (simulator->room_temperature - simulator->air_temperature)) / thick_room_air; - air_change = (air_heat_transfer / (vhc_air * ((simulator->volume_air - simulator->volume_beer) * 1000))) / 60.0; - simulator->air_temperature += air_change; + /* + * First, calculate temperature difference between the room and the air in the + * fridge. We use the volume air to roughly calculate the total area between + * the in and outside. Calculate the effect and shift the air temperature towards + * the room temperature. + */ + sqm_room_air = (cbrtl(simulator->volume_air) * cbrtl(simulator->volume_air) * 6) / 100; /* square meters all fridge sides */ + thick_room_air = 0.04; /* 4 cm walls */ + k_room_air = 0.03; /* Polystrene */ + air_heat_transfer=(k_room_air * sqm_room_air * (simulator->room_temperature - air_temp)) / thick_room_air; + air_change = (air_heat_transfer / (vhc_air * ((simulator->volume_air - simulator->volume_beer) * 1000))) / 60.0; + air_temp += air_change; - /* - * If heating, calculate temperature of the heating plate. If heating is off but - * the plate is warmer then the air, calculate the cooling down temperature. - * Finally, calculate the new air and plate temperature. - */ - if (SIMheating) { - if (simulator->s_heat_temp < simulator->heater_temp) { - simulator->s_heat_temp += 0.05; - if (simulator->s_heat_temp > simulator->air_temperature) - simulator->air_temperature += ((simulator->s_heat_temp - simulator->air_temperature) / 100.0); - } - } else { - /* - * Follow the air temperature - */ - simulator->s_heat_temp -= (simulator->s_heat_temp - simulator->air_temperature) / 25.0; - } + /* + * If heating, calculate temperature of the heating plate. If heating is off but + * the plate is warmer then the air, calculate the cooling down temperature. + * Finally, calculate the new air and plate temperature. + */ + if (simulator->heater_present == DEVPRESENT_YES && simulator->heater_power >= 50) { + if (simulator->s_heat_temp < simulator->heater_temp) { + simulator->s_heat_temp += 0.05; + if (simulator->s_heat_temp > simulator->air_temperature) + air_temp += ((simulator->s_heat_temp - air_temp) / 100.0); + } + } else { + /* + * Follow the air temperature + */ + simulator->s_heat_temp -= (simulator->s_heat_temp - air_temp) / 25.0; + } + + /* + * If cooling, calculate temperature of the cooling plate. If cooling is off but + * the plate is colder then the air, calculate the warming up temperature. + * Finsally, calculate the new air and plate temperature. + */ + if (simulator->cooler_present == DEVPRESENT_YES && simulator->cooler_power >= 50) { + if (simulator->s_cool_temp > simulator->cooler_temp) { + simulator->s_cool_temp -= 0.05; + if (simulator->s_cool_temp < air_temp) + air_temp -= ((air_temp - simulator->s_cool_temp) / 100.0); + } + } else { + simulator->s_cool_temp -= (simulator->s_cool_temp - air_temp) / 25.0; + } - /* - * If cooling, calculate temperature of the cooling plate. If cooling is off but - * the plate is colder then the air, calculate the warming up temperature. - * Finsally, calculate the new air and plate temperature. - */ - if (SIMcooling) { - if (simulator->s_cool_temp > simulator->cooler_temp) { - simulator->s_cool_temp -= 0.05; - if (simulator->s_cool_temp < simulator->air_temperature) - simulator->air_temperature -= ((simulator->air_temperature - simulator->s_cool_temp) / 100.0); - } - } else { - simulator->s_cool_temp -= (simulator->s_cool_temp - simulator->air_temperature) / 25.0; - } + /* + * Calculate final temperature of the beer and the air. + */ + // Cheap trick, just follow slowly the air temp. + beer_temp += ((air_temp - beer_temp) / 500.0); + air_temp += ((beer_temp - air_temp) / 2500.0); + chiller_temp = simulator->cooler_temp; // Link these - /* - * Calculate final temperature of the beer and the air. - */ - // Cheap trick, just follow slowly the air temp. - simulator->beer_temperature += ((simulator->air_temperature - simulator->beer_temperature) / 500.0); - simulator->air_temperature += ((simulator->beer_temperature - simulator->air_temperature) / 2500.0); - simulator->chiller_temperature = simulator->cooler_temp; // Libk these - } - mDelay(100L); + /* + * Finally update simulated sensors with the new values. + * The devices_loop will pickup the values and sets the resolution. + */ + if (air_temp != simulator->air_temperature) { +// syslog(LOG_NOTICE, "SIM %d: air %f to %f", simulator->simno, simulator->air_temperature, air_temp); + simulator->air_temperature = air_temp; + changed = true; + } + if (beer_temp != simulator->beer_temperature) { +// syslog(LOG_NOTICE, "SIM %d: beer %f to %f", simulator->simno, simulator->beer_temperature, beer_temp); + simulator->beer_temperature = beer_temp; + changed = true; } - mDelay(50L); + if (chiller_temp != simulator->chiller_temperature) { +// syslog(LOG_NOTICE, "SIM %d: chiller %f to %f", simulator->simno, simulator->chiller_temperature, chiller_temp); + simulator->chiller_temperature = chiller_temp; + changed = true; + } } + SM_PROCEED(Websocket); + +SM_STATE(Websocket) - syslog(LOG_NOTICE, "Thread my_simulator_loop stopped"); - my_simulator_state = 0; - return 0; -} + if (my_simulator_shutdown) { + SM_SUCCESS; + } + if (changed) { + simulator_ws(); + changed = false; + } + SM_PROCEED(Waiting); + +SM_END +SM_RETURN #endif