void Image_Handler(FCGIContext * context, char * params) { int num = 0, width = 800, height = 600; FCGIValue val[] = { {"num", &num, FCGI_INT_T}, {"width", &width, FCGI_INT_T}, {"height", &height, FCGI_INT_T} }; if (!FCGI_ParseRequest(context, params, val, 3)) return; else if (num < 0 || num > 1) { FCGI_RejectJSON(context, "Invalid capture number"); return; } else if (width <= 0 || height <= 0) { FCGI_RejectJSON(context, "Invalid width/height"); return; } if (captureID != num) { if (captureID >= 0) { cvReleaseCapture(&capture); } capture = cvCreateCameraCapture(num); captureID = num; } cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, width); cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, height); static int p[] = {CV_IMWRITE_JPEG_QUALITY, 100, 0}; IplImage * frame = cvQueryFrame(capture); assert(frame != NULL); // CvMat stub; // CvMat * background = cvGetMat(frame, &stub, 0, 0); // CvMat *cv8u = cvCreateMat(frame->width, frame->height, CV_8U); // double min, max; // CvPoint a,b; // cvMinMaxLoc(background, &min, &max, &a, &b, 0); // double ccscale = 255.0/(max-min); // double ccshift = -min; //cvCvtScale(frame, cv8u, ccscale, ccshift); CvMat * jpg = cvEncodeImage(".jpg", frame, p); // Will this work? Log(LOGNOTE, "Sending image!"); FCGI_PrintRaw("Content-type: image/jpg\r\n"); FCGI_PrintRaw("Cache-Control: no-cache, no-store, must-revalidate\r\n\r\n"); //FCGI_PrintRaw("Content-Length: %d", jpg->rows*jpg->cols); FCGI_WriteBinary(jpg->data.ptr,1,jpg->rows*jpg->cols); cvReleaseMat(&jpg); cvReleaseImageHeader(&frame); }
/** * 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); }