/** * Handle a request for an Actuator * @param context - FCGI context * @param params - Parameters passed */ void Actuator_Handler(FCGIContext * context, char * params) { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); double current_time = TIMEVAL_DIFF(now, *Control_GetStartTime()); int id = 0; char * name = ""; char * set = ""; double start_time = 0; double end_time = current_time; char * fmt_str; // key/value pairs FCGIValue values[] = { {"id", &id, FCGI_INT_T}, {"name", &name, FCGI_STRING_T}, {"set", &set, FCGI_STRING_T}, {"start_time", &start_time, FCGI_DOUBLE_T}, {"end_time", &end_time, FCGI_DOUBLE_T}, {"format", &fmt_str, FCGI_STRING_T} }; // enum to avoid the use of magic numbers typedef enum { ID, NAME, SET, START_TIME, END_TIME, FORMAT } ActuatorParams; // Fill values appropriately if (!FCGI_ParseRequest(context, params, values, sizeof(values)/sizeof(FCGIValue))) { // Error occured; FCGI_RejectJSON already called return; } // Get the Actuator identified Actuator * a = NULL; if (FCGI_RECEIVED(values[NAME].flags)) { if (FCGI_RECEIVED(values[ID].flags)) { FCGI_RejectJSON(context, "Can't supply both id and name"); return; } a = Actuator_Identify(name); if (a == NULL) { FCGI_RejectJSON(context, "Unknown actuator name"); return; } } else if (!FCGI_RECEIVED(values[ID].flags)) { FCGI_RejectJSON(context, "No id or name supplied"); return; } else if (id < 0 || id >= g_num_actuators) { FCGI_RejectJSON(context, "Invalid Actuator id"); return; } else { a = &(g_actuators[id]); } DataFormat format = Data_GetFormat(&(values[FORMAT])); if (FCGI_RECEIVED(values[SET].flags)) { ActuatorControl c = {0.0, 0.0, 0.0, 0}; // Need to set default values (since we don't require them all) // sscanf returns the number of fields successfully read... int n = sscanf(set, "%lf,%lf,%lf,%d", &(c.start), &(c.stepwait), &(c.stepsize), &(c.steps)); // Set provided values in order if (n != 4) { // 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, 4); } // SANITY CHECKS if (c.stepwait < 0 || c.steps < 0 || (a->sanity != NULL && !a->sanity(a->user_id, c.start))) { FCGI_RejectJSON(context, "Bad Actuator setting"); return; } Actuator_SetControl(a, &c); } // Begin response Actuator_BeginResponse(context, a, format); if (format == JSON) FCGI_JSONPair("set", set); // Print Data Data_Handler(&(a->data_file), &(values[START_TIME]), &(values[END_TIME]), format, current_time); // Finish response Actuator_EndResponse(context, a, format); }
/** * Handle a request to the sensor module * @param context - The context to work in * @param params - Parameters passed */ void Sensor_Handler(FCGIContext *context, char * params) { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); double current_time = TIMEVAL_DIFF(now, *Control_GetStartTime()); int id = 0; const char * name = ""; double start_time = 0; double end_time = current_time; const char * fmt_str; double sample_s = 0; // key/value pairs FCGIValue values[] = { {"id", &id, FCGI_INT_T}, {"name", &name, FCGI_STRING_T}, {"format", &fmt_str, FCGI_STRING_T}, {"start_time", &start_time, FCGI_DOUBLE_T}, {"end_time", &end_time, FCGI_DOUBLE_T}, {"sample_s", &sample_s, FCGI_DOUBLE_T} }; // enum to avoid the use of magic numbers typedef enum { ID, NAME, FORMAT, START_TIME, END_TIME, SAMPLE_S } SensorParams; // Fill values appropriately if (!FCGI_ParseRequest(context, params, values, sizeof(values)/sizeof(FCGIValue))) { // Error occured; FCGI_RejectJSON already called return; } Sensor * s = NULL; if (FCGI_RECEIVED(values[NAME].flags)) { if (FCGI_RECEIVED(values[ID].flags)) { FCGI_RejectJSON(context, "Can't supply both sensor id and name"); return; } s = Sensor_Identify(name); if (s == NULL) { FCGI_RejectJSON(context, "Unknown sensor name"); return; } } else if (!FCGI_RECEIVED(values[ID].flags)) { FCGI_RejectJSON(context, "No sensor id or name supplied"); return; } else if (id < 0 || id >= g_num_sensors) { FCGI_RejectJSON(context, "Invalid sensor id"); return; } else { s = &(g_sensors[id]); } // Adjust sample rate if necessary if (FCGI_RECEIVED(values[SAMPLE_S].flags)) { if (sample_s < 0) { FCGI_RejectJSON(context, "Negative sampling speed!"); return; } DOUBLE_TO_TIMEVAL(sample_s, &(s->sample_time)); } DataFormat format = Data_GetFormat(&(values[FORMAT])); // Begin response Sensor_BeginResponse(context, s, format); // Print Data Data_Handler(&(s->data_file), &(values[START_TIME]), &(values[END_TIME]), format, current_time); // Finish response Sensor_EndResponse(context, s, format); }