Add Camera Module 27/168327/1
authorjunkyu han <junkyu.han@samsung.com>
Thu, 25 Jan 2018 07:56:29 +0000 (16:56 +0900)
committerjunkyu han <junkyu.han@samsung.com>
Fri, 26 Jan 2018 00:18:31 +0000 (00:18 +0000)
Change-Id: Ied88305155686af7ed9f89d464bbe3c77a746394
(cherry picked from commit 7620cf9b6c5af514c1883789092ac4761891f715)

13 files changed:
CMakeLists.txt
inc/controller_util.h
inc/resource.h
inc/resource/resource_camera.h [new file with mode: 0644]
inc/webutil.h
packaging/org.tizen.position-finder-server.spec
res/pi.conf
src/connection_manager.c
src/controller.c
src/controller_util.c
src/resource/resource_camera.c [new file with mode: 0644]
src/webutil.c
tizen-manifest.xml.in

index 4d2914d..49fd759 100755 (executable)
@@ -22,6 +22,8 @@ pkg_check_modules(APP_PKGS REQUIRED
        glib-2.0
        json-glib-1.0
        capi-system-info
+       capi-network-connection
+       capi-media-camera
 )
 
 ADD_DEFINITIONS(-DCBOR_FILE_IN_RES="${INSTALL_RESDIR}/${CBOR_FILE}")
@@ -60,6 +62,7 @@ ADD_EXECUTABLE(${PROJECT_NAME}
        ${PROJECT_ROOT_DIR}/src/resource/resource_gas_detection_sensor.c
        ${PROJECT_ROOT_DIR}/src/resource/resource_sound_level_sensor.c
        ${PROJECT_ROOT_DIR}/src/resource/resource_adc_mcp3008.c
+       ${PROJECT_ROOT_DIR}/src/resource/resource_camera.c
 )
 
 TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} -lm)
index 29b5e46..f36973a 100644 (file)
@@ -24,6 +24,7 @@
 
 int controller_util_get_path(const char **path);
 int controller_util_get_address(const char **address);
+int controller_util_get_image_address(const char **image_upload);
 void controller_util_free(void);
 
 #endif /* __POSITION_FINDER_CONTROLLER_UTIL_H__ */
index 783fd8f..f3ffe3c 100755 (executable)
@@ -38,5 +38,6 @@
 #include "resource/resource_tilt_sensor.h"
 #include "resource/resource_gas_detection_sensor.h"
 #include "resource/resource_sound_level_sensor.h"
+#include "resource/resource_camera.h"
 
 #endif /* __POSITION_FINDER_RESOURCE_H__ */
diff --git a/inc/resource/resource_camera.h b/inc/resource/resource_camera.h
new file mode 100644 (file)
index 0000000..545e9b9
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * Contact: Jin Yoon <jinny.yoon@samsung.com>
+ *          Geunsun Lee <gs86.lee@samsung.com>
+ *          Eunyoung Lee <ey928.lee@samsung.com>
+ *          Junkyu Han <junkyu.han@samsung.com>
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <camera.h>
+
+#define MAX_IMAGE_FILE_LEN 256
+#define DEFAULT_FILE_PATH "/home/owner/media"
+
+typedef void (*capture_completed_cb)(const void *image, unsigned int size, void *user_data);
+
+int resource_capture_camera(capture_completed_cb capture_completed_cb, void *data);
+void resource_close_camera(void);
index 8947bc2..a229e07 100644 (file)
@@ -68,6 +68,8 @@ struct _web_util_sensor_data_s {
 int web_util_noti_init(void);
 void web_util_noti_fini(void);
 int web_util_noti_post(const char *resource, const char *json_data);
+int web_util_noti_post_image_data(const char *url, const char *device_id,
+       const void *image_data, unsigned int image_size);
 int web_util_noti_get(const char *resource, char **res);
 
 int web_util_json_init(void);
index dd4e98a..8f50c9b 100644 (file)
@@ -28,6 +28,7 @@ BuildRequires:  pkgconfig(glib-2.0)
 BuildRequires:  pkgconfig(json-glib-1.0)
 BuildRequires:  pkgconfig(capi-system-info)
 BuildRequires:  pkgconfig(capi-network-connection)
+BuildRequires:  pkgconfig(capi-media-camera)
 
 %description
 Server for Position Finder
index b55530e..b7e63e9 100644 (file)
@@ -1,3 +1,4 @@
 [default]
-path=/door/1
+path=sensor-pi-1
 address=http://showiot.xyz/api/tt/data
+image_address=http://test.showiot.xyz/api/image/
index ef5fd7e..443cd1f 100644 (file)
@@ -1,23 +1,3 @@
-/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
- *
- * Contact: Jin Yoon <jinny.yoon@samsung.com>
- *          Geunsun Lee <gs86.lee@samsung.com>
- *          Eunyoung Lee <ey928.lee@samsung.com>
- *          Junkyu Han <junkyu.han@samsung.com>
- *
- * Licensed under the Flora License, Version 1.1 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://floralicense.org/license/
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
  /*
  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
  *
index a442f82..7b35e9f 100644 (file)
 
 #define CONNECTIVITY_KEY "opened"
 #define SENSORING_TIME_INTERVAL 5.0f
+#define CAMERA_TIME_INTERVAL 2
+#define TEST_CAMERA_SAVE 0
+#define CAMERA_ENABLED 0
 
 typedef struct app_data_s {
        Ecore_Timer *getter_timer;
        connectivity_resource_s *resource_info;
 } app_data;
 
+static void __resource_camera_capture_completed_cb(const void *image, unsigned int size, void *user_data)
+{
+       /* TODO */
+       const char *path = NULL;
+       const char *url = NULL;
+
+       controller_util_get_path(&path);
+
+       controller_util_get_image_address(&url);
+
+       web_util_noti_post_image_data(url, path, image, size);
+
+#if TEST_CAMERA_SAVE
+       FILE *fp = NULL;
+       char *data_path = NULL;
+       char file[256];
+
+       data_path = app_get_data_path();
+
+       snprintf(file, sizeof(file), "%sjjoggoba.jpg", data_path);
+       free(data_path);
+       _D("File : %s", file);
+
+       fp = fopen(file, "w");
+       if (!fp) {
+               _E("Failed to open file: %s", file);
+               return;
+       }
+
+       if (fwrite(image, size, 1, fp) != 1) {
+               _E("Failed to write image to file");
+               return;
+       }
+
+       fclose(fp);
+#endif
+}
+
 static Eina_Bool control_sensors_cb(void *data)
 {
        app_data *ad = data;
        int value = 1;
+       int ret = 0;
+#if CAMERA_ENABLED
+       static unsigned int count = 0;
+
+       if (count % CAMERA_TIME_INTERVAL == 0) {
+               ret = resource_capture_camera(__resource_camera_capture_completed_cb, NULL);
+               if (ret < 0)
+                       _E("Failed to capture camera");
+       }
+
+       count++;
+#endif
 
        /* This is example, get value from sensors first */
        if (connectivity_notify_int(ad->resource_info, "Motion", value) == -1)
index 3bba0d5..5bb65dc 100644 (file)
 #define CONF_GROUP_DEFAULT_NAME "default"
 #define CONF_KEY_PATH_NAME "path"
 #define CONF_KEY_ADDRESS_NAME "address"
+#define CONF_KEY_IMAGE_UPLOAD_NAME "image_address"
 #define CONF_FILE_NAME "pi.conf"
 
 struct controller_util_s {
        char *path;
        char *address;
+       char *image_upload;
 };
 
 struct controller_util_s controller_util = { 0, };
@@ -71,6 +73,13 @@ static int _read_conf_file(void)
        if (!controller_util.address)
                _E("could not get the key string");
 
+       controller_util.image_upload = g_key_file_get_string(gkf,
+                       CONF_GROUP_DEFAULT_NAME,
+                       CONF_KEY_IMAGE_UPLOAD_NAME,
+                       NULL);
+       if (!controller_util.image_upload)
+               _E("could not get the key string");
+
        g_key_file_free(gkf);
 
        return 0;
@@ -106,6 +115,21 @@ int controller_util_get_address(const char **address)
        return 0;
 }
 
+int controller_util_get_image_address(const char **image_upload)
+{
+       retv_if(!image_upload, -1);
+
+       if (!controller_util.image_upload) {
+               int ret = -1;
+               ret = _read_conf_file();
+               retv_if(-1 == ret, -1);
+       }
+
+       *image_upload = controller_util.image_upload;
+
+       return 0;
+}
+
 void controller_util_free(void)
 {
        if (controller_util.path) {
diff --git a/src/resource/resource_camera.c b/src/resource/resource_camera.c
new file mode 100644 (file)
index 0000000..64ae611
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * Contact: Jin Yoon <jinny.yoon@samsung.com>
+ *          Geunsun Lee <gs86.lee@samsung.com>
+ *          Eunyoung Lee <ey928.lee@samsung.com>
+ *          Junkyu Han <junkyu.han@samsung.com>
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <camera.h>
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <tizen.h>
+
+#include "log.h"
+#include "resource/resource_camera.h"
+
+#define RESOLUTION_W 320
+#define RESOLUTION_H 240
+
+static int __init(void);
+static void __completed_cb(void *user_data);
+static bool __resolution_list_cb(int width, int height, void *user_data);
+static void __capturing_cb(camera_image_data_s *image, camera_image_data_s *postview,
+               camera_image_data_s *thumbnail, void *user_data);
+
+struct __camera_data {
+       camera_h cam_handle;
+       int resolution_w;
+       int resolution_h;
+       void *captured_file;
+       unsigned int image_size;
+       capture_completed_cb completed_cb;
+       void *completed_cb_data;
+};
+
+static struct __camera_data *camera_data = NULL;
+
+int resource_capture_camera(capture_completed_cb capture_completed, void *user_data)
+{
+       camera_state_e state;
+       int ret = CAMERA_ERROR_NONE;
+
+       if (camera_data == NULL) {
+               _I("Camera is not initialized");
+               ret = __init();
+               if (ret < 0) {
+                       _E("Failed to initialize camera");
+                       return -1;
+               }
+       }
+
+       ret = camera_get_state(camera_data->cam_handle, &state);
+       if (ret != CAMERA_ERROR_NONE) {
+               _E("Failed to get camera state");
+               return -1;
+       }
+
+       if (state >= CAMERA_STATE_CAPTURING) {
+               _D("Camera is now capturing");
+               return 0;
+       }
+
+       if (state != CAMERA_STATE_PREVIEW) {
+               _I("Preview is not started");
+               ret = camera_start_preview(camera_data->cam_handle);
+               if (ret != CAMERA_ERROR_NONE) {
+                       _E("Failed to start preview");
+                       return -1;
+               }
+       }
+
+       ret = camera_start_capture(camera_data->cam_handle, __capturing_cb, __completed_cb, camera_data);
+       if (ret != CAMERA_ERROR_NONE) {
+               _E("Failed to start capturing");
+               return -1;
+       }
+
+       camera_data->completed_cb = capture_completed;
+       camera_data->completed_cb_data = user_data;
+
+       return 0;
+}
+
+void resource_close_camera(void)
+{
+       if (camera_data == NULL)
+               return;
+
+       camera_stop_preview(camera_data->cam_handle);
+
+       camera_destroy(camera_data->cam_handle);
+       camera_data->cam_handle = NULL;
+
+       free(camera_data);
+       camera_data = NULL;
+}
+
+static void __capturing_cb(camera_image_data_s *image, camera_image_data_s *postview,
+               camera_image_data_s *thumbnail, void *user_data)
+{
+       struct __camera_data *camera_data = user_data;
+       if (image == NULL) {
+               _E("Image is NULL");
+               return;
+       }
+
+       camera_data->captured_file = malloc(image->size);
+       if (camera_data->captured_file == NULL)
+               return;
+
+       _D("Now is on Capturing: Image size[%d x %d]", image->width, image->height);
+
+       memcpy(camera_data->captured_file, image->data, image->size);
+       camera_data->image_size = image->size;
+
+       return;
+}
+
+static void __completed_cb(void *user_data)
+{
+       struct __camera_data *camera_data = user_data;
+       int ret = CAMERA_ERROR_NONE;
+
+       if (camera_data->completed_cb)
+               camera_data->completed_cb(camera_data->captured_file, camera_data->image_size, camera_data->completed_cb_data);
+
+       free(camera_data->captured_file);
+       camera_data->captured_file = NULL;
+
+       if (!camera_data->cam_handle) {
+               _E("Camera is NULL");
+               return;
+       }
+       _D("Capture is completed");
+
+       ret = camera_start_preview(camera_data->cam_handle);
+       if (ret != CAMERA_ERROR_NONE) {
+               _E("Failed to start preview");
+               return;
+       }
+
+       ret = camera_stop_preview(camera_data->cam_handle);
+       if (ret != CAMERA_ERROR_NONE) {
+               _E("Failed to stop preview");
+               return;
+       }
+
+       return;
+}
+
+static bool __resolution_list_cb(int width, int height, void *user_data)
+{
+       _D("Supported resolution - Width[%d], Height[%d]", width, height);
+
+       if (width > camera_data->resolution_w && width <= RESOLUTION_W &&
+                       height > camera_data->resolution_h && height <= RESOLUTION_H) {
+               camera_data->resolution_w = width;
+               camera_data->resolution_h = height;
+       }
+       _D("Fixed Resolution is Width[%d], Height[%d]", camera_data->resolution_w, camera_data->resolution_h);
+
+       return true;
+}
+
+static int __init(void)
+{
+       int ret = CAMERA_ERROR_NONE;
+
+       camera_data = malloc(sizeof(struct __camera_data));
+       if (camera_data == NULL) {
+               _E("Failed to allocate Camera data");
+               return -1;
+       }
+       memset(camera_data, 0, sizeof(struct __camera_data));
+
+       ret = camera_create(CAMERA_DEVICE_CAMERA0, &(camera_data->cam_handle));
+       if (ret != CAMERA_ERROR_NONE) {
+               _E("Failed to create camera");
+               goto ERROR;
+       }
+
+       ret = camera_foreach_supported_capture_resolution(camera_data->cam_handle, __resolution_list_cb, NULL);
+       if (ret != CAMERA_ERROR_NONE) {
+               _E("Failed to foreach supported capture resolution");
+               goto ERROR;
+       }
+
+       ret = camera_set_preview_resolution(camera_data->cam_handle, camera_data->resolution_w, camera_data->resolution_h);
+       if (ret != CAMERA_ERROR_NONE) {
+               _E("Failed to set preview resolution");
+               goto ERROR;
+       }
+
+       ret = camera_set_capture_resolution(camera_data->cam_handle, camera_data->resolution_w, camera_data->resolution_h);
+       if (ret != CAMERA_ERROR_NONE) {
+               _E("Failed to set capture resolution");
+               goto ERROR;
+       }
+
+       ret = camera_set_capture_format(camera_data->cam_handle, CAMERA_PIXEL_FORMAT_JPEG);
+       if (ret != CAMERA_ERROR_NONE) {
+               _E("Failed to set capture resolution");
+               goto ERROR;
+       }
+
+       ret = camera_start_preview(camera_data->cam_handle);
+       if (ret != CAMERA_ERROR_NONE) {
+               _E("Failed to start preview[%d]", ret);
+               goto ERROR;
+       }
+
+       return 0;
+
+ERROR:
+       camera_destroy(camera_data->cam_handle);
+       free(camera_data);
+       return -1;
+}
+
index 27f8a37..7afde87 100644 (file)
@@ -22,7 +22,7 @@
 
 #include <stdbool.h>
 #include <curl/curl.h>
-#include <glib-object.h>
+#include <glib.h>
 #include <json-glib/json-glib.h>
 #include "log.h"
 #include "webutil.h"
@@ -67,6 +67,62 @@ static size_t _get_response_write_callback(void *ptr, size_t size, size_t nmemb,
        return res_size;
 }
 
+static int __curl_debug(CURL *handle, curl_infotype type,
+       char *data, size_t size, void *userptr)
+{
+       const char *prefix = NULL;
+       char *message = NULL;
+
+       switch (type) {
+       case CURLINFO_END:
+               return 0;
+       case CURLINFO_TEXT:
+               _D("== text Info: %s", data);
+               return 0;
+       case CURLINFO_HEADER_OUT:
+               prefix = "=> Send header:";
+               break;
+       case CURLINFO_DATA_OUT:
+               prefix = "=> Send data:";
+               break;
+       case CURLINFO_SSL_DATA_OUT:
+               prefix = "=> Send SSL data:";
+               break;
+       case CURLINFO_HEADER_IN:
+               prefix = "<= Recv header:";
+               break;
+       case CURLINFO_DATA_IN:
+               prefix = "<= Recv data:";
+               break;
+       case CURLINFO_SSL_DATA_IN:
+               prefix = "<= Recv SSL data:";
+               break;
+       }
+       message = g_strndup(data, size);
+       _D("%s %s", prefix, message);
+       g_free(message);
+       return 0;
+}
+
+static const char *_get_time_str(void)
+{
+       struct timeval val;
+       struct tm *ptm;
+       static char res_time[40] = {0, };
+
+       gettimeofday(&val, NULL);
+       ptm = localtime(&val.tv_sec);
+
+       // format : YY-MM-DD_hh:mm:ss:uuuuuu
+       snprintf(res_time, sizeof(res_time), "%04d-%02d-%02d_%02d:%02d:%02d:%06ld"
+               , ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday
+               , ptm->tm_hour, ptm->tm_min, ptm->tm_sec
+               , val.tv_usec);
+
+       return (const char *)res_time;
+}
+
+
 int web_util_noti_init(void)
 {
        int ret = 0;
@@ -86,6 +142,71 @@ void web_util_noti_fini(void)
        return;
 }
 
+int web_util_noti_post_image_data(const char *url, const char *device_id,
+       const void *image_data, unsigned int image_size)
+{
+       int ret = 0;
+       CURL *curl = NULL;
+       CURLcode response = CURLE_OK;
+       struct curl_httppost *formpost = NULL;
+       struct curl_httppost *lastptr = NULL;
+       char *filename = NULL;
+       char *post_url = NULL;
+
+       retv_if(url == NULL, -1);
+       retv_if(device_id == NULL, -1);
+       retv_if(image_data == NULL, -1);
+       retv_if(image_size == 0, -1);
+
+       curl = curl_easy_init();
+
+       if (!curl) {
+               _E("fail to init curl");
+               return -1;
+       }
+
+       filename = g_strdup_printf("%s_%s.jpg", device_id, _get_time_str());
+       post_url = g_strdup_printf("%s?id=%s", url, device_id);
+       _D("FileName: [%s], PostUrl: [%s]", filename, post_url);
+
+       curl_formadd(&formpost, &lastptr,
+               CURLFORM_COPYNAME, "content-type:",
+               CURLFORM_COPYCONTENTS, "multipart/form-data",
+               CURLFORM_END);
+
+       curl_formadd(&formpost, &lastptr,
+               CURLFORM_COPYNAME, "imageFile",
+               CURLFORM_BUFFER, filename,
+               CURLFORM_BUFFERPTR, image_data,
+               CURLFORM_BUFFERLENGTH, image_size,
+               CURLFORM_END);
+
+       curl_easy_setopt(curl, CURLOPT_URL, post_url);
+       curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
+
+       /* if CURLOPT_VERBOSE is enabled, __curl_debug() function will be called */
+       // curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+       curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, __curl_debug);
+
+       // curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, REQ_CON_TIMEOUT);
+       // curl_easy_setopt(curl, CURLOPT_TIMEOUT, REQ_TIMEOUT);
+
+       response = curl_easy_perform(curl);
+
+       if (response != CURLE_OK) {
+               _E("curl_easy_perform() failed: %s",
+                       curl_easy_strerror(response));
+               ret = -1;
+       }
+
+       curl_easy_cleanup(curl);
+       curl_formfree(formpost);
+       g_free(post_url);
+       g_free(filename);
+
+       return ret;
+}
+
 int web_util_noti_post(const char *resource, const char *json_data)
 {
        int ret = 0;
@@ -399,7 +520,6 @@ int web_util_json_add_sensor_data(const char* sensorpi_id, web_util_sensor_data_
        }
        */
 
-
        json_builder_begin_object(Json_h.builder);
 
        json_builder_set_member_name(Json_h.builder, n_id);
index 2ea5ef4..e014ce2 100644 (file)
@@ -5,7 +5,7 @@
     <author email="gs86.lee@samsung.com" href="www.samsung.com">Geunsun Lee</author>
     <author email="ey928.lee@samsung.com" href="www.samsung.com">Eunyoung Lee</author>
     <author email="junkyu.han@samsung.com" href="www.samsung.com">Junkyu Han</author>
-    <service-application appid="@ORG_PREFIX@.@PROJECT_NAME@" auto-restart="true" exec="@PROJECT_NAME@" multiple="false" nodisplay="true" on-boot="true" taskmanage="false" type="capp">
+    <service-application appid="@ORG_PREFIX@.@PROJECT_NAME@" auto-restart="false" exec="@PROJECT_NAME@" multiple="false" nodisplay="true" on-boot="false" taskmanage="false" type="capp">
         <label>@APP_LABEL@</label>
         <icon>@PROJECT_NAME@.png</icon>
     </service-application>
@@ -13,5 +13,6 @@
                <privilege>http://tizen.org/privilege/network.get</privilege>
                <privilege>http://tizen.org/privilege/internet</privilege>
                <privilege>http://tizen.org/privilege/peripheralio</privilege>
+               <privilege>http://tizen.org/privilege/camera</privilege>
     </privileges>
 </manifest>