3 * @brief Handles all client control requests (admin related)
10 typedef enum ControlState {
23 typedef struct ControlData {
25 pthread_mutex_t mutex;
26 struct timeval start_time;
29 ControlData g_controls = {STATE_STOPPED, PTHREAD_MUTEX_INITIALIZER, {0}};
31 static bool ExperimentExists(const char *experiment_name) {
32 FILE *fp = fopen(experiment_name, "r");
40 * System control handler. This covers high-level control, including
41 * admin related functions and starting/stopping experiments..
42 * @param context The context to work in
43 * @param params The input parameters
45 void Control_Handler(FCGIContext *context, char *params) {
46 const char *action, *key = "", *name = "";
50 FCGIValue values[4] = {
51 {"action", &action, FCGI_REQUIRED(FCGI_STRING_T)},
52 {"key", &key, FCGI_STRING_T},
53 {"force", &force, FCGI_BOOL_T},
54 {"name", &name, FCGI_STRING_T}
57 if (!FCGI_ParseRequest(context, params, values, 4))
60 if (!strcmp(action, "lock")) {
61 FCGI_LockControl(context, force);
63 } else if (FCGI_HasControl(context, key)) {
64 if (!strcmp(action, "release")) {
65 FCGI_ReleaseControl(context);
66 } else if (!strcmp(action, "start")) {
68 } else if (!strcmp(action, "pause")) {
70 } else if (!strcmp(action, "resume")) {
72 } else if (!strcmp(action, "stop")) {
75 FCGI_RejectJSON(context, "Unknown action specified.");
79 FCGI_RejectJSONEx(context, STATUS_UNAUTHORIZED,
80 "Invalid control key specified.");
87 FCGI_RejectJSON(context, "An experiment name must be provided");
88 } else if (ExperimentExists(name) && !force) {
89 FCGI_RejectJSONEx(context, STATUS_ALREADYEXISTS,
90 "An experiment with the specified name already exists.");
91 } else if (!Control_Start(name)) {
92 FCGI_RejectJSON(context, "An experiment is already running.");
94 FCGI_BeginJSON(context, STATUS_OK);
99 if (!Control_Pause()) {
100 FCGI_RejectJSON(context, "No experiment to pause.");
102 FCGI_BeginJSON(context, STATUS_OK);
107 if (!Control_Resume()) {
108 FCGI_RejectJSON(context, "No experiment to resume.");
110 FCGI_BeginJSON(context, STATUS_OK);
115 if (!Control_Stop()) {
116 FCGI_RejectJSON(context, "No experiment to stop.");
118 FCGI_BeginJSON(context, STATUS_OK);
125 bool Control_Start(const char *experiment_name) {
128 pthread_mutex_lock(&(g_controls.mutex));
129 if (g_controls.state == STATE_STOPPED) {
130 FILE *fp = fopen(experiment_name, "a");
133 gettimeofday(&(g_controls.start_time), NULL);
134 Sensor_StartAll(experiment_name);
135 Actuator_StartAll(experiment_name);
136 g_controls.state = STATE_RUNNING;
140 pthread_mutex_unlock(&(g_controls.mutex));
145 bool Control_Pause() {
147 pthread_mutex_lock(&(g_controls.mutex));
148 if (g_controls.state == STATE_RUNNING) {
151 g_controls.state = STATE_PAUSED;
154 pthread_mutex_unlock(&(g_controls.mutex));
158 bool Control_Resume() {
160 pthread_mutex_lock(&(g_controls.mutex));
161 if (g_controls.state == STATE_PAUSED) {
162 Actuator_ResumeAll();
164 g_controls.state = STATE_RUNNING;
167 pthread_mutex_unlock(&(g_controls.mutex));
171 bool Control_Stop() {
174 pthread_mutex_lock(&(g_controls.mutex));
175 if (g_controls.state != STATE_STOPPED) {
178 g_controls.state = STATE_STOPPED;
181 pthread_mutex_unlock(&(g_controls.mutex));
185 bool Control_Lock() {
186 pthread_mutex_lock(&(g_controls.mutex));
187 if (g_controls.state == STATE_RUNNING || g_controls.state == STATE_PAUSED)
189 pthread_mutex_unlock(&(g_controls.mutex));
193 void Control_Unlock() {
194 pthread_mutex_unlock(&(g_controls.mutex));
197 const struct timeval* Control_GetStartTime() {
198 return &g_controls.start_time;