Sending lap time to cloud 54/191654/3
authorMichal Skorupinski <m.skorupinsk@samsung.com>
Fri, 19 Oct 2018 13:21:46 +0000 (15:21 +0200)
committerMichal Skorupinski <m.skorupinsk@samsung.com>
Fri, 26 Oct 2018 13:13:37 +0000 (15:13 +0200)
Change-Id: I1868a69e6c0b4c520e0332736516b0d58797814e
Signed-off-by: Michal Skorupinski <m.skorupinsk@samsung.com>
15 files changed:
CMakeLists.txt
inc/cloud/cloud_communication.h
inc/cloud/cloud_lap_request.h [new file with mode: 0644]
inc/cloud/cloud_request.h
inc/cloud/lap_info.h [new file with mode: 0644]
inc/cloud/lap_info_serializer.h [new file with mode: 0644]
inc/lap_counter/lap_counter.h
src/cloud/car_info.c
src/cloud/cloud_communication.c
src/cloud/cloud_lap_request.c [new file with mode: 0644]
src/cloud/cloud_request.c
src/cloud/http_request.c
src/cloud/lap_info.c [new file with mode: 0644]
src/cloud/lap_info_serializer.c [new file with mode: 0644]
src/lap_counter/lap_counter.c

index c5fcd12..586093d 100644 (file)
@@ -60,8 +60,11 @@ ADD_EXECUTABLE(${PROJECT_NAME}
        ${PROJECT_ROOT_DIR}/src/resource/resource_lap_counter.c
        ${PROJECT_ROOT_DIR}/src/cloud/car_info.c
        ${PROJECT_ROOT_DIR}/src/cloud/car_info_serializer.c
+       ${PROJECT_ROOT_DIR}/src/cloud/lap_info.c
        ${PROJECT_ROOT_DIR}/src/cloud/cloud_request.c
        ${PROJECT_ROOT_DIR}/src/cloud/http_request.c
+       ${PROJECT_ROOT_DIR}/src/cloud/cloud_lap_request.c
+       ${PROJECT_ROOT_DIR}/src/cloud/lap_info_serializer.c
        ${PROJECT_ROOT_DIR}/src/net-util.c
        ${PROJECT_ROOT_DIR}/src/cloud/cloud_communication.c
        ${PROJECT_ROOT_DIR}/src/lap_counter/lap_counter.c
index 44135d1..0866aea 100644 (file)
@@ -34,4 +34,6 @@ void cloud_communication_stop();
 /**
  * @brief Finalize all resources used by cloud communication.
 */
-void cloud_communication_fini();
\ No newline at end of file
+void cloud_communication_fini();
+
+void cloud_communication_post_lap(const long laptime, const char *driver_name);
diff --git a/inc/cloud/cloud_lap_request.h b/inc/cloud/cloud_lap_request.h
new file mode 100644 (file)
index 0000000..6a4bfcb
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef __CLOUD_LAP_REQUEST_H_
+#define __CLOUD_LAP_REQUEST_H_
+
+#include <stdbool.h>
+#include <gio/gio.h>
+#include "lap_info.h"
+
+typedef void(*cloud_request_lap_list_data_cb)(bool result, lap_info_t **car_info, int size, void *user_data);
+typedef void(*cloud_request_lap_post_finish_cb)(bool result, void *user_data);
+
+GCancellable *cloud_lap_request_api_racing_get(const char *ap_mac, cloud_request_lap_list_data_cb callback, void *user_data);
+GCancellable *cloud_lap_request_api_racing_post(const lap_info_t *lap_info, cloud_request_lap_post_finish_cb callback, void *user_data);
+
+#endif
index 8137fed..e4e065f 100644 (file)
@@ -69,4 +69,4 @@ GCancellable *cloud_request_api_racing_get(const char *ap_mac, cloud_request_car
  */
 GCancellable *cloud_request_api_racing_post(const car_info_t *car_info, cloud_request_car_post_finish_cb callback, void *user_data);
 
-#endif
\ No newline at end of file
+#endif
diff --git a/inc/cloud/lap_info.h b/inc/cloud/lap_info.h
new file mode 100644 (file)
index 0000000..c72c8cd
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+* Copyright (c) 2018 Samsung Electronics Co., Ltd.
+*
+* 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.
+*/
+
+
+#ifndef _LAP_INFO_H_
+#define _LAP_INFO_H_
+
+typedef struct lap_info lap_info_t;
+
+lap_info_t *lap_info_create(void);
+lap_info_t *lap_info_copy(const lap_info_t *lap_info);
+void lap_info_destroy(lap_info_t *lap_info);
+
+const char *lap_info_get_car_id(lap_info_t *lap_info);
+int lap_info_set_car_id(lap_info_t *lap_info, const char *car_id);
+
+const char *lap_info_get_user_name(lap_info_t *lap_info);
+int lap_info_set_user_name(lap_info_t *lap_info, const char *user_name);
+
+long lap_info_get_lap_time(lap_info_t *lap_info);
+int lap_info_set_lap_time(lap_info_t *lap_info, long lap_time);
+
+#endif /* _LAP_INFO_H_ */
diff --git a/inc/cloud/lap_info_serializer.h b/inc/cloud/lap_info_serializer.h
new file mode 100644 (file)
index 0000000..5b075e7
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef __LAP_INFO_SERIALIZER_H_
+#define __LAP_INFO_SERIALIZER_H_
+
+#include "lap_info.h"
+
+char *lap_info_serializer_serialize(lap_info_t *lap_info);
+lap_info_t **lap_info_serializer_deserialize_array(const char *json_data, int *size);
+
+#endif
index 9904c93..0fc3b0c 100644 (file)
@@ -19,6 +19,7 @@
 
 void lap_counter_init();
 void lap_counter_set_user_name(const char *user_name);
+const char *lap_counter_get_user_name(void);
 void lap_counter_get_lap_time();
 void lap_counter_shutdown();
 
index 7c977d7..508e086 100644 (file)
@@ -24,7 +24,7 @@
 #include "cloud/car_info.h"
 #include "log.h"
 
-#define MAX_LENGTH 256
+#define MAX_CAR_ID_LENGTH 256
 #define MAX_LENGTH_IP 16
 #define MAX_LENGTH_MAC 18
 #define MAX_LENGTH_SSID 33
@@ -60,8 +60,8 @@ car_info_t *car_info_copy(const car_info_t *car_info)
     retv_if(!car_info, NULL);
 
     struct car_info *car_info_cpy = g_new0(struct car_info, 1);
-    SAFE_STR_CPY(car_info_cpy->id, car_info->id, MAX_LENGTH);
-    SAFE_STR_CPY(car_info_cpy->name, car_info->name, MAX_LENGTH);
+    SAFE_STR_CPY(car_info_cpy->id, car_info->id, MAX_CAR_ID_LENGTH);
+    SAFE_STR_CPY(car_info_cpy->name, car_info->name, MAX_CAR_ID_LENGTH);
     SAFE_STR_CPY(car_info_cpy->ip, car_info->ip, MAX_LENGTH_IP);
     SAFE_STR_CPY(car_info_cpy->ap_mac, car_info->ap_mac, MAX_LENGTH_MAC);
     SAFE_STR_CPY(car_info_cpy->ap_ssid, car_info->ap_ssid, MAX_LENGTH_SSID);
@@ -98,12 +98,12 @@ int car_info_set_car_id(car_info_t *car_info, const char *car_id)
 {
     retv_if(!car_info, -1);
     retv_if(car_id == NULL, -1);
-    retv_if(strlen(car_id) >= MAX_LENGTH, -1);
+    retv_if(strlen(car_id) >= MAX_CAR_ID_LENGTH, -1);
 
     if (!car_info->id)
-        car_info->id = (char *)g_malloc(MAX_LENGTH * sizeof(char));
+        car_info->id = (char *)g_malloc(MAX_CAR_ID_LENGTH * sizeof(char));
 
-    snprintf(car_info->id, MAX_LENGTH, "%s", car_id);
+    snprintf(car_info->id, MAX_CAR_ID_LENGTH, "%s", car_id);
     return 0;
 }
 
@@ -117,12 +117,12 @@ int car_info_set_car_name(car_info_t *car_info, const char *car_name)
 {
     retv_if(!car_info, -1);
     retv_if(car_name == NULL, -1);
-    retv_if(strlen(car_name) >= MAX_LENGTH, -1);
+    retv_if(strlen(car_name) >= MAX_CAR_ID_LENGTH, -1);
 
     if (!car_info->name)
-        car_info->name = (char *)g_malloc(MAX_LENGTH * sizeof(char));
+        car_info->name = (char *)g_malloc(MAX_CAR_ID_LENGTH * sizeof(char));
 
-    snprintf(car_info->name, MAX_LENGTH, "%s", car_name);
+    snprintf(car_info->name, MAX_CAR_ID_LENGTH, "%s", car_name);
     return 0;
 }
 
index a54ba35..634773e 100644 (file)
@@ -20,6 +20,8 @@
 #include <stdlib.h>
 #include "cloud/car_info.h"
 #include "cloud/cloud_request.h"
+#include "cloud/cloud_lap_request.h"
+#include "cloud/lap_info.h"
 #include "log.h"
 #include "config.h"
 #include "net-util.h"
@@ -96,6 +98,21 @@ void cloud_communication_fini()
     car_info_destroy(_communication.car_info);
 }
 
+
+void cloud_communication_post_lap(const long laptime, const char *driver_name)
+{
+       lap_info_t *lap = lap_info_create();
+
+       lap_info_set_car_id(lap, car_info_get_car_id(_communication.car_info));
+       lap_info_set_user_name(lap, driver_name);
+       lap_info_set_lap_time(lap,  laptime);
+
+       _D("POST lap");
+       cloud_lap_request_api_racing_post(lap, (cloud_request_lap_post_finish_cb)post_response_cb, NULL);
+
+       lap_info_destroy(lap);
+}
+
 static void post_response_cb(request_result_e result, void *user_data)
 {
     if (result == SUCCESS) {
diff --git a/src/cloud/cloud_lap_request.c b/src/cloud/cloud_lap_request.c
new file mode 100644 (file)
index 0000000..54ca712
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 "cloud/cloud_lap_request.h"
+#include "cloud/http_request.h"
+#include "cloud/lap_info_serializer.h"
+#include "cloud/lap_info.h"
+#include <glib.h>
+#include <gio/gio.h>
+#include <string.h>
+#include "log.h"
+
+#define BASE_URL "http://son.tizen.online"
+#define PATH_API_LAP "/api/lap"
+
+typedef struct {
+       char *ap_mac;
+       cloud_request_lap_list_data_cb cb;
+       void *user_data;
+} lap_api_get_request_context_t;
+
+typedef struct {
+       lap_info_t *lap;
+       cloud_request_lap_post_finish_cb cb;
+       void *user_data;
+} lap_api_post_request_context_t;
+
+typedef struct {
+       long response_code;
+       char *response_msg;
+} lap_api_post_request_response_t;
+
+typedef struct {
+       long response_code;
+       lap_info_t **laps;
+       int size;
+} lap_api_get_request_response_t;
+
+static void lap_api_post_task_thread_cb(GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable);
+static void lap_api_post_task_ready_cb(GObject *source_object, GAsyncResult *res, gpointer user_data);
+static void lap_api_post_task_context_free(lap_api_post_request_context_t *context);
+static void lap_api_post_request_response_free(lap_api_post_request_response_t *response);
+
+static void lap_api_get_task_context_free(lap_api_get_request_context_t *context);
+static void lap_api_get_request_response_free(lap_api_get_request_response_t *response);
+static void lap_api_get_task_thread_cb(GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable);
+static void lap_api_get_task_ready_cb(GObject *source_object, GAsyncResult *res, gpointer user_data);
+
+#define G_ERROR_DOMAIN g_quark_from_static_string("cloud_lap_request")
+
+GCancellable *cloud_lap_request_api_racing_get(const char *ap_mac, cloud_request_lap_list_data_cb cb, void *user_data)
+{
+       GCancellable *cancellable = g_cancellable_new();
+
+       GTask *task = g_task_new(NULL, cancellable, lap_api_get_task_ready_cb, NULL);
+       g_task_set_source_tag(task, cloud_lap_request_api_racing_get);
+       g_task_set_return_on_cancel(task, FALSE);
+
+       lap_api_get_request_context_t *context = g_new0(lap_api_get_request_context_t, 1);
+       context->ap_mac = strndup(ap_mac, strlen(ap_mac));
+       context->cb = cb;
+       context->user_data = user_data;
+
+       g_task_set_task_data(task, context, (GDestroyNotify)lap_api_get_task_context_free);
+       g_task_run_in_thread(task, lap_api_get_task_thread_cb);
+
+       g_object_unref(task);
+
+       return cancellable;
+}
+
+GCancellable *cloud_lap_request_api_racing_post(const lap_info_t *lap_info, cloud_request_lap_post_finish_cb cb, void *user_data)
+{
+       GCancellable *cancellable = g_cancellable_new();
+
+       GTask *task = g_task_new(NULL, cancellable, lap_api_post_task_ready_cb, NULL);
+       g_task_set_source_tag(task, cloud_lap_request_api_racing_post);
+       g_task_set_return_on_cancel(task, FALSE);
+
+       lap_api_post_request_context_t *context = g_new0(lap_api_post_request_context_t, 1);
+       context->lap = lap_info_copy(lap_info);
+       context->cb = cb;
+       context->user_data = user_data;
+
+       g_task_set_task_data(task, context, (GDestroyNotify)lap_api_post_task_context_free);
+       g_task_run_in_thread(task, lap_api_post_task_thread_cb);
+
+       g_object_unref(task);
+
+       return cancellable;
+}
+
+static void lap_api_post_task_context_free(lap_api_post_request_context_t *context)
+{
+       ret_if(!context);
+
+       lap_info_destroy(context->lap);
+       g_free(context);
+}
+
+static void lap_api_post_request_response_free(lap_api_post_request_response_t *response)
+{
+       ret_if(!response);
+
+       g_free(response->response_msg);
+       g_free(response);
+}
+
+static void lap_api_post_task_thread_cb(GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable)
+{
+       lap_api_post_request_context_t *context = (lap_api_post_request_context_t *)task_data;
+
+       if (g_task_return_error_if_cancelled(task)) {
+               return;
+       }
+
+       lap_api_post_request_response_t *response = g_new0(lap_api_post_request_response_t, 1);
+
+       char *json = lap_info_serializer_serialize(context->lap);
+       int retval = http_request_post(BASE_URL""PATH_API_LAP, json, &(response->response_msg), &(response->response_code));
+       g_free(json);
+
+       if (retval != 0) {
+               GError *err = g_error_new(G_ERROR_DOMAIN, retval, "http_request_post failed!");
+               g_task_return_error(task, err);
+       }
+
+       g_task_return_pointer(task, response, (GDestroyNotify)lap_api_post_request_response_free);
+}
+
+static void lap_api_post_task_ready_cb(GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+       GTask *task = G_TASK(res);
+       GError *error = NULL;
+
+       //If no error occurred g_task_propagate_pointer transfers ownership, so later response have to be freed.
+       lap_api_post_request_response_t *response = g_task_propagate_pointer(task, &error);
+       if (error != NULL) {
+               _E("POST async task failed with msg: %s", error->message);
+               g_error_free(error);
+               return;
+       }
+       lap_api_post_request_context_t *context = g_task_get_task_data(task);
+
+       bool result = (response->response_code == 200 && (strncmp(response->response_msg, "Success", strlen("Success")) == 0)) ?
+               true :
+               false;
+
+       if (context->cb) {
+               context->cb(result, context->user_data);
+       }
+
+       lap_api_post_request_response_free(response);
+}
+
+static void lap_api_get_task_context_free(lap_api_get_request_context_t *context)
+{
+       ret_if(!context);
+
+       g_free(context->ap_mac);
+       g_free(context);
+}
+
+static void lap_api_get_request_response_free(lap_api_get_request_response_t *response)
+{
+       ret_if(!response);
+       ret_if(response->size <= 0);
+
+       for (int i = 0; i < response->size; i++)
+       {
+               lap_info_destroy(response->laps[i]);
+       }
+       g_free(response->laps);
+       g_free(response);
+}
+
+static void lap_api_get_task_thread_cb(GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable)
+{
+       lap_api_get_request_context_t *context = (lap_api_get_request_context_t *)task_data;
+
+       if (g_task_return_error_if_cancelled(task)) {
+               return;
+       }
+
+       lap_api_get_request_response_t *response = g_new0(lap_api_get_request_response_t, 1);
+       char *response_json = NULL;
+
+       GString *url = g_string_new(BASE_URL""PATH_API_LAP"?apMac=");
+       g_string_append(url, context->ap_mac);
+
+       int retval = http_request_get(url->str, &response_json, &(response->response_code));
+       g_string_free(url, TRUE);
+
+       if (retval != 0) {
+               GError *err = g_error_new(G_ERROR_DOMAIN, retval, "http_request_get failed!");
+               g_task_return_error(task, err);
+       }
+       else {
+               response->laps = lap_info_serializer_deserialize_array(response_json, &(response->size));
+       }
+
+       g_free(response_json);
+       g_task_return_pointer(task, response, (GDestroyNotify)lap_api_get_request_response_free);
+}
+
+static void lap_api_get_task_ready_cb(GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+       GTask *task = G_TASK(res);
+       GError *error = NULL;
+
+       //If no error occurred g_task_propagate_pointer transfers ownership, so later response have to be freed.
+       lap_api_get_request_response_t *response = g_task_propagate_pointer(task, &error);
+       if (error != NULL) {
+               _E("GET async task failed with msg: %s", error->message);
+               g_error_free(error);
+               return;
+       }
+       lap_api_get_request_context_t *context = g_task_get_task_data(task);
+
+       bool result = (response->response_code == 200) ? true : false;
+
+       if (context->cb) {
+               context->cb(result, response->laps, response->size, context->user_data);
+       }
+
+       lap_api_get_request_response_free(response);
+}
index 1a46fa1..90777d1 100644 (file)
@@ -22,7 +22,7 @@
 #include <string.h>
 #include "log.h"
 
-#define BASE_URL "https://son.tizen.online"
+#define BASE_URL "http://son.tizen.online"
 #define PATH_API_RACING "/api/racing"
 
 typedef struct {
@@ -242,4 +242,4 @@ static void car_api_get_task_ready_cb(GObject *source_object, GAsyncResult *res,
     }
 
     car_api_get_request_response_free(response);
-}
\ No newline at end of file
+}
index b094227..1780698 100644 (file)
@@ -35,6 +35,11 @@ int http_request_get(const char *url, char **response, long *response_code)
     retvm_if(!curl, -1, "Failed to initialize curl!");
 
     curl_easy_setopt(curl, CURLOPT_URL, url);
+
+    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER , 1);
+    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST , 1);
+    curl_easy_setopt(curl, CURLOPT_CAINFO, "ca-bundle.crt");
+
     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, _response_write);
     curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)response);
 
@@ -127,4 +132,4 @@ static size_t _response_write(void *ptr, size_t size, size_t nmemb, void *data)
     }
 
     return real_size;
-}
\ No newline at end of file
+}
diff --git a/src/cloud/lap_info.c b/src/cloud/lap_info.c
new file mode 100644 (file)
index 0000000..cc27ce5
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+* Copyright (c) 2018 Samsung Electronics Co., Ltd.
+*
+* 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 <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <glib.h>
+#include <string.h>
+#include <regex.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+#include "log.h"
+#include "cloud/lap_info.h"
+
+#define MAX_CAR_ID_LENGTH 256
+
+struct lap_info
+{
+       char *user_name;
+       char *car_id;
+       long lap_time;
+};
+
+lap_info_t *lap_info_create(void)
+{
+       struct lap_info *lap_info = g_new0(struct lap_info, 1);
+       retvm_if(!lap_info, NULL, "Could not allocate memory!");
+
+       return lap_info;
+}
+
+lap_info_t *lap_info_copy(const lap_info_t *lap_info)
+{
+       retv_if(!lap_info, NULL);
+
+       struct lap_info *lap_info_cpy = g_new0(struct lap_info, 1);
+       lap_info_cpy->user_name = strndup(lap_info->user_name, MAX_CAR_ID_LENGTH);
+       lap_info_cpy->car_id = strndup(lap_info->car_id, MAX_CAR_ID_LENGTH);
+       lap_info_cpy->lap_time = lap_info->lap_time;
+
+       return lap_info_cpy;
+}
+
+void lap_info_destroy(lap_info_t *lap_info)
+{
+       ret_if(!lap_info);
+
+       free(lap_info->user_name);
+       free(lap_info->car_id);
+       g_free(lap_info);
+}
+
+const char *lap_info_get_car_id(lap_info_t *lap_info)
+{
+       retv_if(!lap_info, NULL);
+       return lap_info->car_id;
+}
+
+int lap_info_set_car_id(lap_info_t *lap_info, const char *car_id)
+{
+       retv_if(!lap_info, -1);
+       retv_if(car_id == NULL, -1);
+       retv_if(strlen(car_id) >= MAX_CAR_ID_LENGTH, -1);
+
+       if (!lap_info->car_id)
+               lap_info->car_id = (char *)g_malloc(MAX_CAR_ID_LENGTH * sizeof(char));
+
+       snprintf(lap_info->car_id, MAX_CAR_ID_LENGTH, "%s", car_id);
+       return 0;
+}
+
+const char *lap_info_get_user_name(lap_info_t *lap_info)
+{
+       retv_if(!lap_info, NULL);
+       return lap_info->user_name;
+}
+
+int lap_info_set_user_name(lap_info_t *lap_info, const char *user_name)
+{
+       retv_if(!lap_info, -1);
+       retv_if(user_name == NULL, -1);
+       retv_if(strlen(user_name) >= MAX_CAR_ID_LENGTH, -1);
+
+       if (!lap_info->user_name)
+               lap_info->user_name = (char *)g_malloc(MAX_CAR_ID_LENGTH * sizeof(char));
+
+       snprintf(lap_info->user_name, MAX_CAR_ID_LENGTH, "%s", user_name);
+       return 0;
+}
+
+long lap_info_get_lap_time(lap_info_t *lap_info)
+{
+       retv_if(!lap_info, 0);
+       return lap_info->lap_time;
+}
+
+int lap_info_set_lap_time(lap_info_t *lap_info, long lap_time)
+{
+       retv_if(!lap_info, -1);
+       lap_info->lap_time = lap_time;
+       return 0;
+}
diff --git a/src/cloud/lap_info_serializer.c b/src/cloud/lap_info_serializer.c
new file mode 100644 (file)
index 0000000..ec85055
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 "cloud/lap_info_serializer.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <json-glib/json-glib.h>
+#include "log.h"
+#include "cloud/lap_info.h"
+#include "string.h"
+
+#define JSON_SCHEMA_RESPONSE_CAR_ID "id"
+#define JSON_SCHEMA_CAR_ID "carId"
+#define JSON_SCHEMA_USER_NAME "driver"
+#define JSON_SCHEMA_LAP_TIME "laptime"
+
+static JsonNode *_json_get_root(JsonParser *parser, const char *config_json);
+static void _lap_info_array_iterate_cb(JsonArray *array, guint index, JsonNode *element, gpointer user_data);
+
+char *lap_info_serializer_serialize(lap_info_t *lap_info)
+{
+       JsonGenerator *generator = json_generator_new();
+       JsonBuilder *builder = json_builder_new();
+       json_builder_begin_object(builder);
+
+       json_builder_set_member_name(builder, JSON_SCHEMA_USER_NAME);
+       json_builder_add_string_value(builder, lap_info_get_user_name(lap_info));
+
+       json_builder_set_member_name(builder, JSON_SCHEMA_CAR_ID);
+       json_builder_add_string_value(builder, lap_info_get_car_id(lap_info));
+
+       json_builder_set_member_name(builder, JSON_SCHEMA_LAP_TIME);
+       json_builder_add_int_value(builder, lap_info_get_lap_time(lap_info));
+
+       json_builder_end_object(builder);
+
+       JsonNode *root = json_builder_get_root(builder);
+       json_generator_set_root(generator, root);
+
+       char *json_data = json_generator_to_data(generator, NULL);
+
+       g_object_unref(builder);
+       g_object_unref(generator);
+       return json_data;
+}
+
+lap_info_t **lap_info_serializer_deserialize_array(const char *json_data, int *size)
+{
+       JsonParser *parser = json_parser_new();
+
+       JsonNode *root = _json_get_root(parser, json_data);
+       JsonArray *array = json_node_get_array(root);
+       if (!array)
+       {
+               _E("Json is invalid!");
+               g_object_unref(parser);
+               return NULL;
+       }
+
+       *size = json_array_get_length(array);
+
+       if (*size == 0) {
+               return NULL;
+       }
+
+       lap_info_t **lap_info_array = g_malloc(*size * sizeof(lap_info_t *));
+
+       json_array_foreach_element(array, _lap_info_array_iterate_cb, lap_info_array);
+
+       g_object_unref(parser);
+       return lap_info_array;
+}
+
+static JsonNode *_json_get_root(JsonParser *parser, const char *json)
+{
+       GError *err = NULL;
+
+       if (!json_parser_load_from_data(parser, json, -1, &err))
+       {
+               _E("Function \"json_parser_load_from_data()\" failed with message: %s", err->message);
+               g_error_free(err);
+               return NULL;
+       }
+
+       return json_parser_get_root(parser);
+}
+
+static void _lap_info_array_iterate_cb(JsonArray *array, guint index, JsonNode *element, gpointer user_data)
+{
+       lap_info_t **lap_info_array = (lap_info_t **)user_data;
+
+       JsonObject *entry = json_node_get_object(element);
+
+       lap_info_array[index] = lap_info_create();
+
+       if (json_object_has_member(entry, JSON_SCHEMA_RESPONSE_CAR_ID) &&
+               lap_info_set_car_id(lap_info_array[index], json_object_get_string_member(entry, JSON_SCHEMA_RESPONSE_CAR_ID)) != 0)
+       {
+               _E("Couldn't set car id");
+       }
+
+       if (json_object_has_member(entry, JSON_SCHEMA_USER_NAME) &&
+               lap_info_set_user_name(lap_info_array[index], json_object_get_string_member(entry, JSON_SCHEMA_USER_NAME)) != 0)
+       {
+               _E("Couldn't set user name");
+       }
+
+       if (json_object_has_member(entry, JSON_SCHEMA_LAP_TIME) &&
+               lap_info_set_lap_time(lap_info_array[index], json_object_get_int_member(entry, JSON_SCHEMA_LAP_TIME)) != 0)
+       {
+               _E("Couldn't set lap time");
+       }
+}
index dfbd299..0894a87 100644 (file)
 #include <limits.h>
 #include <stdlib.h>
 #include <time.h>
+#include "cloud/cloud_communication.h"
 
 #define MIN_LAP_TIME 5
 #define MAX_NAME_LENGTH 256
 
 typedef struct lap_counter_data {
-       const char *user_name;
+       char *user_name;
        struct timespec last_timestamp;
 } lap_counter_data_t;
 
@@ -42,11 +43,11 @@ void lap_counter_init()
 
 void lap_counter_set_user_name(const char *user_name)
 {
+       retm_if(!user_name, "New user name is NULL");
+
        free((void*)s_info.user_name);
        s_info.user_name = strdup(user_name);
-       if(!s_info.user_name) {
-               return;
-       }
+
        _D("User name set to %s", s_info.user_name);
 }
 
@@ -96,6 +97,7 @@ static inline struct timespec _calculate_lap_time(struct timespec *prev, struct
        }
        _D("----------------------------------------------");
 
+       cloud_communication_post_lap(lap.tv_sec * 1e3 + lap.tv_nsec / 1e6, s_info.user_name);
        return lap;
 }