thermferm/simulator.c

changeset 715
f5d85af156ab
parent 714
24749c296a50
child 716
5c30c8ef83a8
--- 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

mercurial