From 46c219c69676ea4e6f467692b7db6e48a708ab80 Mon Sep 17 00:00:00 2001 From: Jeremy Tan Date: Sat, 14 Sep 2013 14:03:27 +0800 Subject: [PATCH] Partial implementation of higher level control functions --- server/actuator.c | 44 ++++++++++++++++----------- server/control.c | 77 +++++++++++++++-------------------------------- server/control.h | 4 ++- server/data.c | 2 +- server/data.h | 2 +- server/fastcgi.c | 8 ++--- server/main.c | 11 ++++--- server/sensor.c | 33 ++++++++++++-------- 8 files changed, 89 insertions(+), 92 deletions(-) diff --git a/server/actuator.c b/server/actuator.c index ff51732..3c09d05 100644 --- a/server/actuator.c +++ b/server/actuator.c @@ -4,6 +4,7 @@ */ #include "actuator.h" +#include "control.h" #include "options.h" /** Array of Actuators (global to this file) initialised by Actuator_Init **/ @@ -255,24 +256,33 @@ void Actuator_Handler(FCGIContext * context, char * params) DataFormat format = Data_GetFormat(&(values[FORMAT])); - // Begin response - Actuator_BeginResponse(context, id, format); - - // Set? - if (FCGI_RECEIVED(values[SET].flags)) + if (Control_Lock()) { - if (format == JSON) - FCGI_JSONDouble("set", set); - - ActuatorControl c; - c.value = set; + // Begin response + Actuator_BeginResponse(context, id, format); - Actuator_SetControl(a, &c); - } + // Set? + if (FCGI_RECEIVED(values[SET].flags)) + { + if (format == JSON) + FCGI_JSONDouble("set", set); + + ActuatorControl c; + c.value = set; - // Print Data - Data_Handler(&(a->data_file), &(values[START_TIME]), &(values[END_TIME]), format, current_time); - - // Finish response - Actuator_EndResponse(context, id, format); + Actuator_SetControl(a, &c); + } + + // Print Data + Data_Handler(&(a->data_file), &(values[START_TIME]), &(values[END_TIME]), format, current_time); + + // Finish response + Actuator_EndResponse(context, id, format); + + Control_Unlock(); + } + else + { + FCGI_RejectJSON(context, "Experiment is not running."); + } } diff --git a/server/control.c b/server/control.c index 297cdd0..b12530f 100644 --- a/server/control.c +++ b/server/control.c @@ -4,50 +4,8 @@ */ #include "common.h" #include "control.h" - - -const char * g_actuator_names[NUMACTUATORS] = { - "Pressure regulator", "Solenoid 1" -}; - -/* -void ActuatorHandler(FCGIContext *context, ActuatorId id, const char *set_value) { - char *ptr; - - switch(id) { //Add new actuators here - case ACT_PRESSURE: //Suppose is pressure regulator. 0-700 input (kPa) - { - int value = strtol(set_value, &ptr, 10); - if (*ptr == '\0' && value >= 0 && value <= 700) { - FCGI_BeginJSON(context, STATUS_OK); - FCGI_JSONKey("description"); - FCGI_JSONValue("\"Set pressure to %d kPa!\"", value); - FCGI_EndJSON(); - } else { - FCGI_RejectJSONEx(context, - STATUS_ERROR, "Invalid pressure specified."); - } - } break; - case ACT_SOLENOID1: - { - int value = strtol(set_value, &ptr, 10); - if (*ptr == '\0') { - const char *state = "off"; - if (value) - state = "on"; - FCGI_BeginJSON(context, STATUS_OK); - FCGI_JSONKey("description"); - FCGI_JSONValue("\"Solenoid 1 turned %s!\"", state); - FCGI_EndJSON(); - } else { - FCGI_RejectJSON(context, "Invalid actuator value specified"); - } - } break; - default: - FCGI_RejectJSONEx(context, - STATUS_ERROR, "Invalid actuator id specified."); - } -}*/ +#include "sensor.h" +#include "actuator.h" typedef enum ControlState { STATE_STOPPED, @@ -110,33 +68,48 @@ void Control_Handler(FCGIContext *context, char *params) { } bool Control_Start(const char *experiment_name) { + bool ret = false; + pthread_mutex_lock(&(g_controls.mutex)); if (g_controls.state == STATE_STOPPED) { gettimeofday(&(g_controls.start_time), NULL); Sensor_StartAll(experiment_name); + Actuator_StartAll(experiment_name); g_controls.state = STATE_RUNNING; - - pthread_mutex_unlock(&(g_controls.mutex)); - return true; + ret = true; } - return false; pthread_mutex_unlock(&(g_controls.mutex)); + return ret; } + void Control_Pause() { pthread_mutex_lock(&(g_controls.mutex)); pthread_mutex_unlock(&(g_controls.mutex)); } -bool Control_End() { +bool Control_Stop() { + bool ret = false; + pthread_mutex_lock(&(g_controls.mutex)); if (g_controls.state != STATE_STOPPED) { + Actuator_StopAll(); Sensor_StopAll(); g_controls.state = STATE_STOPPED; - - pthread_mutex_unlock(&(g_controls.mutex)); - return true; + ret = true; } pthread_mutex_unlock(&(g_controls.mutex)); + return ret; +} + +bool Control_Lock() { + pthread_mutex_lock(&(g_controls.mutex)); + if (g_controls.state == STATE_RUNNING) + return true; + pthread_mutex_unlock(&(g_controls.mutex)); return false; } + +void Control_Unlock() { + pthread_mutex_unlock(&(g_controls.mutex)); +} \ No newline at end of file diff --git a/server/control.h b/server/control.h index 950aeaa..347465e 100644 --- a/server/control.h +++ b/server/control.h @@ -9,6 +9,8 @@ extern void Control_Handler(FCGIContext *context, char *params); extern bool Control_Start(const char *experiment_name); extern void Control_Pause(); -extern bool Control_End(); +extern bool Control_Stop(); +extern bool Control_Lock(); +extern void Control_Unlock(); #endif diff --git a/server/data.c b/server/data.c index add8d9f..ffd0b67 100644 --- a/server/data.c +++ b/server/data.c @@ -344,7 +344,7 @@ void Data_Handler(DataFile * df, FCGIValue * start, FCGIValue * end, DataFormat */ DataFormat Data_GetFormat(FCGIValue * fmt) { - char * fmt_str = *(char**)(fmt->value); + const char * fmt_str = *(const char**)(fmt->value); // Check if format type was specified if (FCGI_RECEIVED(fmt->flags)) { diff --git a/server/data.h b/server/data.h index 30d1253..07ede0b 100644 --- a/server/data.h +++ b/server/data.h @@ -1,5 +1,5 @@ /** - * @file datapoint.h + * @file data.h * @purpose Declaration of data handling functions; saving, loading, displaying, selecting. */ diff --git a/server/fastcgi.c b/server/fastcgi.c index b4b3587..05dae34 100644 --- a/server/fastcgi.c +++ b/server/fastcgi.c @@ -191,9 +191,9 @@ char *FCGI_KeyPair(char *in, const char **key, const char **value) } /** - * Aids in parsing request parameters. Expected keys along with their type - * and whether or not they're required are provided. This function will then - * parse the parameter string to find these keys. + * Aids in parsing request parameters. + * Input: The expected keys along with their type and whether or not + * they're required. * @param context The context to work in * @param params The parameter string to be parsed * @param values An array of FCGIValue's that specify expected keys @@ -237,7 +237,7 @@ bool FCGI_ParseRequest(FCGIContext *context, char *params, FCGIValue values[], s } if (FCGI_TYPE(val->flags) == FCGI_INT_T) - *((int*) val->value) = parsed; + *((int*) val->value) = (int) parsed; else *((long*) val->value) = parsed; } break; diff --git a/server/main.c b/server/main.c index 6ea256c..75dd628 100644 --- a/server/main.c +++ b/server/main.c @@ -8,6 +8,7 @@ #include "options.h" #include "sensor.h" #include "actuator.h" +#include "control.h" // --- Standard headers --- // #include // for signal handling @@ -78,14 +79,16 @@ int main(int argc, char ** argv) */ Sensor_Init(); Actuator_Init(); - Sensor_StartAll("test"); - Actuator_StartAll("test"); + //Sensor_StartAll("test"); + //Actuator_StartAll("test"); + Control_Start("test"); // run request thread in the main thread FCGI_RequestLoop(NULL); - Sensor_StopAll(); - Actuator_StopAll(); + Control_Stop(); + //Sensor_StopAll(); + //Actuator_StopAll(); Cleanup(); return 0; diff --git a/server/sensor.c b/server/sensor.c index b065708..f3860c9 100644 --- a/server/sensor.c +++ b/server/sensor.c @@ -5,6 +5,7 @@ */ #include "common.h" +#include "control.h" #include "sensor.h" #include "options.h" #include @@ -18,9 +19,9 @@ const SensorThreshold thresholds[NUMSENSORS]= { {1,-1,1,-1}, // ANALOG_TEST0 {500,0,499,0}, // ANALOG_TEST1 {5,-5,4,-4}, // ANALOG_FAIL0 - {1,0,1,0}, // DIGITAL_TEST0 - {1,0,1,0}, // DIGITAL_TEST1 - {1,0,1,0} // DIGITAL_FAIL0 + {1,0,1,0}, // DIGITAL_TEST0 + {1,0,1,0}, // DIGITAL_TEST1 + {1,0,1,0} // DIGITAL_FAIL0 }; /** Human readable names for the sensors **/ @@ -321,18 +322,26 @@ void Sensor_Handler(FCGIContext *context, char * params) return; } Sensor * s = g_sensors+id; - + DataFormat format = Data_GetFormat(&(values[FORMAT])); - // Begin response - Sensor_BeginResponse(context, id, format); + if (Control_Lock()) + { + // Begin response + Sensor_BeginResponse(context, id, format); - // Print Data - Data_Handler(&(s->data_file), &(values[START_TIME]), &(values[END_TIME]), format, current_time); - - // Finish response - Sensor_EndResponse(context, id, format); - + // Print Data + Data_Handler(&(s->data_file), &(values[START_TIME]), &(values[END_TIME]), format, current_time); + + // Finish response + Sensor_EndResponse(context, id, format); + + Control_Unlock(); + } + else + { + FCGI_RejectJSON(context, "Experiment is not running."); + } } -- 2.20.1