+
+ const char *ret;
+ if ((ret = Control_SetMode(desired_mode, arg)) != NULL) {
+ FCGI_RejectJSON(context, ret);
+ } else {
+ if (desired_mode == CONTROL_STOP) {
+ g_controls.user_name[0] = '\0';
+ g_controls.experiment_dir[0] = '\0';
+ g_controls.experiment_name[0] = '\0';
+ } else if (desired_mode == CONTROL_START) {
+ snprintf(g_controls.user_name, sizeof(g_controls.user_name),
+ "%s", context->user_name);
+ snprintf(g_controls.experiment_dir, sizeof(g_controls.experiment_dir),
+ "%s", experiment_dir);
+ snprintf(g_controls.experiment_name, sizeof(g_controls.experiment_name),
+ "%s", name);
+ }
+
+ FCGI_AcceptJSON(context, "Ok", NULL);
+ }
+}
+
+/**
+ * Sets the mode to the desired mode, if possible.
+ * @param desired_mode The mode to be set to
+ * @param arg An argument specific to the mode to be set.
+ * @return NULL on success, an error message on failure.
+ */
+const char* Control_SetMode(ControlModes desired_mode, void * arg)
+{
+ const char *ret = NULL;
+
+ pthread_mutex_lock(&(g_controls.mutex));
+ if (g_controls.current_mode == desired_mode)
+ ret = "Already in the desired mode.";
+ else if (g_controls.current_mode == CONTROL_EMERGENCY && desired_mode != CONTROL_STOP)
+ ret = "In emergency mode. You must stop before continuing.";
+ else switch (desired_mode) {
+ case CONTROL_START:
+ if (g_controls.current_mode == CONTROL_STOP) {
+ const char * path = arg;
+ if (mkdir(path, 0777) != 0 && errno != EEXIST) {
+ Log(LOGERR, "Couldn't create experiment directory %s - %s",
+ path, strerror(errno));
+ ret = "Couldn't create experiment directory.";
+ } else {
+ clock_gettime(CLOCK_MONOTONIC, &(g_controls.start_time));
+ }
+ } else
+ ret = "Cannot start when not in a stopped state.";
+ break;
+ case CONTROL_PAUSE:
+ if (g_controls.current_mode != CONTROL_START)
+ ret = "Cannot pause when not in a running state.";
+ break;
+ case CONTROL_RESUME:
+ if (g_controls.current_mode != CONTROL_PAUSE)
+ ret = "Cannot resume when not in a paused state.";
+ break;
+ case CONTROL_EMERGENCY:
+ if (g_controls.current_mode != CONTROL_START) //pfft
+ ret = "Not running so how can there be an emergency?";
+ break;
+ default:
+ break;
+ }
+
+ if (ret == NULL) {
+ Actuator_SetModeAll(desired_mode, arg);
+ Sensor_SetModeAll(desired_mode, arg);
+ if (desired_mode != CONTROL_RESUME)
+ g_controls.current_mode = desired_mode;
+ else
+ g_controls.current_mode = CONTROL_START;
+ }
+ pthread_mutex_unlock(&(g_controls.mutex));
+ return ret;
+}
+
+/**
+ * Gets a string representation of the current mode
+ * @param mode The mode to get a string representation of
+ * @return The string representation of the mode
+ */
+const char * Control_GetModeName() {
+ const char * ret = "Unknown";
+
+ switch (g_controls.current_mode) {
+ case CONTROL_START: ret = "Running"; break;
+ case CONTROL_PAUSE: ret = "Paused"; break;
+ case CONTROL_RESUME: ret = "Resumed"; break;
+ case CONTROL_STOP: ret = "Stopped"; break;
+ case CONTROL_EMERGENCY: ret = "Emergency mode"; break;
+ }
+ return ret;
+}
+
+/**
+ * Gets the start time for the current experiment
+ * @return the start time
+ */
+const struct timespec * Control_GetStartTime() {
+ return &g_controls.start_time;