From 716344659847fd869a89e31168c600ae432b7c0c Mon Sep 17 00:00:00 2001 From: Sam Moore Date: Mon, 14 Oct 2013 15:47:31 +0800 Subject: [PATCH] Tweak Actuators/Sensors code Actuators stores an extra data point. Actuators must be initialised to a value. Replaced thresholds with a sanity function for sensors. --- server/actuator.c | 35 ++++++++++++++++++++++----------- server/actuator.h | 4 +++- server/main.c | 8 ++++---- server/sensor.c | 50 ++++++++++++++--------------------------------- server/sensor.h | 8 ++++---- 5 files changed, 50 insertions(+), 55 deletions(-) diff --git a/server/actuator.c b/server/actuator.c index 3e26e37..04938ba 100644 --- a/server/actuator.c +++ b/server/actuator.c @@ -23,7 +23,7 @@ static Actuator g_actuators[ACTUATORS_MAX]; * @param init - Function to call to initialise the actuator (may be NULL) * @returns Number of actuators added so far */ -int Actuator_Add(const char * name, int user_id, SetFn set, InitFn init, CleanFn cleanup, SanityFn sanity) +int Actuator_Add(const char * name, int user_id, SetFn set, InitFn init, CleanFn cleanup, SanityFn sanity, double initial_value) { if (++g_num_actuators > ACTUATORS_MAX) { @@ -42,6 +42,8 @@ int Actuator_Add(const char * name, int user_id, SetFn set, InitFn init, CleanFn pthread_mutex_init(&(a->mutex), NULL); + Actuator_SetValue(a, initial_value, false); + return g_num_actuators; } @@ -54,7 +56,7 @@ int Actuator_Add(const char * name, int user_id, SetFn set, InitFn init, CleanFn void Actuator_Init() { //Actuator_Add("ledtest",0, Ledtest_Set, NULL,NULL,NULL); - Actuator_Add("filetest", 0, Filetest_Set, Filetest_Init, Filetest_Cleanup, Filetest_Sanity); + Actuator_Add("filetest", 0, Filetest_Set, Filetest_Init, Filetest_Cleanup, Filetest_Sanity, 0); } /** @@ -160,16 +162,18 @@ void * Actuator_Loop(void * arg) if (!a->activated) break; - Actuator_SetValue(a, a->control.start); + Actuator_SetValue(a, a->control.start, true); // Currently does discrete steps after specified time intervals - while (a->control.steps > 0 && a->activated) + while (!a->control_changed && a->control.steps > 0 && a->activated) { usleep(1e6*(a->control.stepwait)); a->control.start += a->control.stepsize; - Actuator_SetValue(a, a->control.start); + Actuator_SetValue(a, a->control.start, true); a->control.steps--; } + if (a->control_changed) + continue; usleep(1e6*(a->control.stepwait)); //TODO: @@ -206,12 +210,13 @@ void Actuator_SetControl(Actuator * a, ActuatorControl * c) * @param a - The Actuator * @param value - The value to set */ -void Actuator_SetValue(Actuator * a, double value) +void Actuator_SetValue(Actuator * a, double value, bool record) { if (a->sanity != NULL && !a->sanity(a->user_id, value)) { //ARE YOU INSANE? - Fatal("Insane value %lf for actuator %s", value, a->name); + Log(LOGERR,"Insane value %lf for actuator %s", value, a->name); + return; } if (!(a->set(a->user_id, value))) { @@ -221,9 +226,17 @@ void Actuator_SetValue(Actuator * a, double value) // Set time stamp struct timeval t; gettimeofday(&t, NULL); - // Record and save DataPoint - DataPoint d = {TIMEVAL_DIFF(t, *Control_GetStartTime()), value}; - Data_Save(&(a->data_file), &d, 1); + DataPoint d = {TIMEVAL_DIFF(t, *Control_GetStartTime()), a->last_setting.value}; + // Record value change + if (record) + { + d.time_stamp -= 1e-6; + Data_Save(&(a->data_file), &d, 1); + d.value = value; + d.time_stamp += 1e-6; + Data_Save(&(a->data_file), &d, 1); + } + a->last_setting = d; } /** @@ -364,7 +377,7 @@ void Actuator_Handler(FCGIContext * context, char * params) // If the user doesn't provide all 4 values, the Actuator will get set *once* using the first of the provided values // (see Actuator_Loop) // Not really a problem if n = 1, but maybe generate a warning for 2 <= n < 4 ? - Log(LOGDEBUG, "Only provided %d values (expect %d) for Actuator setting", n); + Log(LOGDEBUG, "Only provided %d values (expect %d) for Actuator setting", n, 4); } // SANITY CHECKS if (c.stepwait < 0 || c.steps < 0 || (a->sanity != NULL && !a->sanity(a->user_id, c.start))) diff --git a/server/actuator.h b/server/actuator.h index de81eea..f818526 100644 --- a/server/actuator.h +++ b/server/actuator.h @@ -68,6 +68,8 @@ typedef struct SanityFn sanity; /** Cleanup function **/ CleanFn clean; + /** Last setting **/ + DataPoint last_setting; } Actuator; @@ -77,7 +79,7 @@ extern void Actuator_SetModeAll(ControlModes mode, void *arg); extern void Actuator_SetMode(Actuator * a, ControlModes mode, void *arg); extern void * Actuator_Loop(void * args); // Main loop for a thread that handles an Actuator -extern void Actuator_SetValue(Actuator * a, double value); // Set an actuator by value +extern void Actuator_SetValue(Actuator * a, double value, bool record); // Set an actuator by value extern void Actuator_SetControl(Actuator * a, ActuatorControl * c); // Set the control for an Actuator extern Actuator * Actuator_Identify(const char * str); // Identify a Sensor from a string Id diff --git a/server/main.c b/server/main.c index c2e5161..a48c223 100644 --- a/server/main.c +++ b/server/main.c @@ -128,19 +128,19 @@ int main(int argc, char ** argv) Pin_Init(); // Try and start things - /* + const char *ret; if ((ret = Control_SetMode(CONTROL_START, "test")) != NULL) Fatal("Control_SetMode failed with '%s'", ret); - */ + // run request thread in the main thread FCGI_RequestLoop(NULL); - /* + if ((ret = Control_SetMode(CONTROL_STOP, "test")) != NULL) Fatal("Control_SetMode failed with '%s'", ret); - */ + //Sensor_StopAll(); //Actuator_StopAll(); diff --git a/server/sensor.c b/server/sensor.c index fd477c9..9c3d2b4 100644 --- a/server/sensor.c +++ b/server/sensor.c @@ -29,7 +29,7 @@ int g_num_sensors = 0; * @param min_warn - Minimum warning threshold; program will log warnings if the value falls below this threshold * @returns Number of actuators added so far */ -int Sensor_Add(const char * name, int user_id, ReadFn read, InitFn init, CleanFn cleanup, double max_error, double min_error, double max_warn, double min_warn) +int Sensor_Add(const char * name, int user_id, ReadFn read, InitFn init, CleanFn cleanup, SanityFn sanity) { if (++g_num_sensors > SENSORS_MAX) { @@ -52,12 +52,8 @@ int Sensor_Add(const char * name, int user_id, ReadFn read, InitFn init, CleanFn s->sample_us = 1e6; s->averages = 1; - // Set warning/error thresholds - s->thresholds.max_error = max_error; - s->thresholds.min_error = min_error; - s->thresholds.max_warn = max_warn; - s->thresholds.min_warn = min_warn; - + // Set sanity function + s->sanity = sanity; return g_num_sensors; } @@ -71,11 +67,11 @@ int Sensor_Add(const char * name, int user_id, ReadFn read, InitFn init, CleanFn #include "sensors/pressure.h" void Sensor_Init() { - Sensor_Add("cpu_stime", RESOURCE_CPU_SYS, Resource_Read, NULL, NULL, 1e50,-1e50,1e50,-1e50); - Sensor_Add("cpu_utime", RESOURCE_CPU_USER, Resource_Read, NULL, NULL, 1e50,-1e50,1e50,-1e50); - Sensor_Add("pressure_high0", PRES_HIGH0, Pressure_Read, Pressure_Init, Pressure_Cleanup, 800, 110, 800, 110); - Sensor_Add("pressure_high1", PRES_HIGH1, Pressure_Read, Pressure_Init, Pressure_Cleanup, 800, 110, 800, 110); - Sensor_Add("pressure_low0", PRES_LOW0, Pressure_Read, Pressure_Init, Pressure_Cleanup, 250, 110, 250, 110); + Sensor_Add("cpu_stime", RESOURCE_CPU_SYS, Resource_Read, NULL, NULL, NULL); + Sensor_Add("cpu_utime", RESOURCE_CPU_USER, Resource_Read, NULL, NULL, NULL); + Sensor_Add("pressure_high0", PRES_HIGH0, Pressure_Read, Pressure_Init, Pressure_Cleanup, NULL); + Sensor_Add("pressure_high1", PRES_HIGH1, Pressure_Read, Pressure_Init, Pressure_Cleanup, NULL); + Sensor_Add("pressure_low0", PRES_LOW0, Pressure_Read, Pressure_Init, Pressure_Cleanup, NULL); //Sensor_Add("../testing/count.py", 0, Piped_Read, Piped_Init, Piped_Cleanup, 1e50,-1e50,1e50,-1e50); //Sensor_Add("strain0", STRAIN0, Strain_Read, Strain_Init, 5000,0,5000,0); //Sensor_Add("strain1", STRAIN1, Strain_Read, Strain_Init, 5000,0,5000,0); @@ -180,26 +176,6 @@ void Sensor_SetModeAll(ControlModes mode, void * arg) } -/** - * Checks the sensor data for unsafe or unexpected results - * @param sensor_id - The ID of the sensor - * @param value - The value from the sensor to test - */ -void Sensor_CheckData(Sensor * s, double value) -{ - if( value > s->thresholds.max_error || value < s->thresholds.min_error) - { - Log(LOGERR, "Sensor %s at %f is above or below its safety value of %f or %f\n",s->name,value, s->thresholds.max_error, s->thresholds.min_error); - //new function that stops actuators? - //Control_SetMode(CONTROL_EMERGENCY, NULL) - } - else if( value > s->thresholds.max_warn || value < s->thresholds.min_warn) - { - Log(LOGWARN, "Sensor %s at %f is above or below its warning value of %f or %f\n", s->name,value,s->thresholds.max_warn, s->thresholds.min_warn); - } -} - - /** * Record data from a single Sensor; to be run in a seperate thread * @param arg - Cast to Sensor* - Sensor that the thread will handle @@ -223,9 +199,13 @@ void * Sensor_Loop(void * arg) if (success) { - - - Sensor_CheckData(s, d.value); + if (s->sanity != NULL) + { + if (!s->sanity(s->user_id, d.value)) + { + Fatal("Sensor %s (%d,%d) reads unsafe value", s->name, s->id, s->user_id); + } + } Data_Save(&(s->data_file), &d, 1); // Record it } else diff --git a/server/sensor.h b/server/sensor.h index bb2fb9e..0285252 100644 --- a/server/sensor.h +++ b/server/sensor.h @@ -51,15 +51,16 @@ typedef struct InitFn init; /** Function to cleanup the sensor **/ CleanFn cleanup; + /** Function to sanity check the sensor readings **/ + SanityFn sanity; /** Human readable name of the sensor **/ const char * name; - /** Thresholds on the sensor **/ - SensorThreshold thresholds; /** Sampling rate **/ int sample_us; - /** Averages per DataPoint **/ + /** Number of averages per sample **/ int averages; + } Sensor; @@ -73,7 +74,6 @@ extern void Sensor_SetMode(Sensor * s, ControlModes mode, void * arg); extern void * Sensor_Loop(void * args); // Main loop for a thread that handles a Sensor extern bool Sensor_Read(Sensor * s, DataPoint * d); // Read a single DataPoint, indicating if it has changed since the last one -extern void Sensor_CheckData(Sensor * s, double value); // Check a DataPoint extern Sensor * Sensor_Identify(const char * str); // Identify a Sensor from a string extern void Sensor_Handler(FCGIContext *context, char * params); // Handle a FCGI request for Sensor data -- 2.20.1