From c94dfec7b02f1fccb114d0d86be1d15907662715 Mon Sep 17 00:00:00 2001 From: Michal Skorupinski Date: Fri, 19 Oct 2018 15:21:46 +0200 Subject: [PATCH] Sending lap time to cloud Change-Id: I1868a69e6c0b4c520e0332736516b0d58797814e Signed-off-by: Michal Skorupinski --- CMakeLists.txt | 3 + inc/cloud/cloud_communication.h | 4 +- inc/cloud/cloud_lap_request.h | 30 +++++ inc/cloud/cloud_request.h | 2 +- inc/cloud/lap_info.h | 36 ++++++ inc/cloud/lap_info_serializer.h | 25 +++++ inc/lap_counter/lap_counter.h | 1 + src/cloud/car_info.c | 18 +-- src/cloud/cloud_communication.c | 17 +++ src/cloud/cloud_lap_request.c | 240 ++++++++++++++++++++++++++++++++++++++++ src/cloud/cloud_request.c | 4 +- src/cloud/http_request.c | 7 +- src/cloud/lap_info.c | 115 +++++++++++++++++++ src/cloud/lap_info_serializer.c | 127 +++++++++++++++++++++ src/lap_counter/lap_counter.c | 10 +- 15 files changed, 621 insertions(+), 18 deletions(-) create mode 100644 inc/cloud/cloud_lap_request.h create mode 100644 inc/cloud/lap_info.h create mode 100644 inc/cloud/lap_info_serializer.h create mode 100644 src/cloud/cloud_lap_request.c create mode 100644 src/cloud/lap_info.c create mode 100644 src/cloud/lap_info_serializer.c diff --git a/CMakeLists.txt b/CMakeLists.txt index c5fcd12..586093d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/inc/cloud/cloud_communication.h b/inc/cloud/cloud_communication.h index 44135d1..0866aea 100644 --- a/inc/cloud/cloud_communication.h +++ b/inc/cloud/cloud_communication.h @@ -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 index 0000000..6a4bfcb --- /dev/null +++ b/inc/cloud/cloud_lap_request.h @@ -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 +#include +#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 diff --git a/inc/cloud/cloud_request.h b/inc/cloud/cloud_request.h index 8137fed..e4e065f 100644 --- a/inc/cloud/cloud_request.h +++ b/inc/cloud/cloud_request.h @@ -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 index 0000000..c72c8cd --- /dev/null +++ b/inc/cloud/lap_info.h @@ -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 index 0000000..5b075e7 --- /dev/null +++ b/inc/cloud/lap_info_serializer.h @@ -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 diff --git a/inc/lap_counter/lap_counter.h b/inc/lap_counter/lap_counter.h index 9904c93..0fc3b0c 100644 --- a/inc/lap_counter/lap_counter.h +++ b/inc/lap_counter/lap_counter.h @@ -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(); diff --git a/src/cloud/car_info.c b/src/cloud/car_info.c index 7c977d7..508e086 100644 --- a/src/cloud/car_info.c +++ b/src/cloud/car_info.c @@ -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; } diff --git a/src/cloud/cloud_communication.c b/src/cloud/cloud_communication.c index a54ba35..634773e 100644 --- a/src/cloud/cloud_communication.c +++ b/src/cloud/cloud_communication.c @@ -20,6 +20,8 @@ #include #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 index 0000000..54ca712 --- /dev/null +++ b/src/cloud/cloud_lap_request.c @@ -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 +#include +#include +#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); +} diff --git a/src/cloud/cloud_request.c b/src/cloud/cloud_request.c index 1a46fa1..90777d1 100644 --- a/src/cloud/cloud_request.c +++ b/src/cloud/cloud_request.c @@ -22,7 +22,7 @@ #include #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 +} diff --git a/src/cloud/http_request.c b/src/cloud/http_request.c index b094227..1780698 100644 --- a/src/cloud/http_request.c +++ b/src/cloud/http_request.c @@ -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 index 0000000..cc27ce5 --- /dev/null +++ b/src/cloud/lap_info.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#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 index 0000000..ec85055 --- /dev/null +++ b/src/cloud/lap_info_serializer.c @@ -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 +#include +#include +#include +#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"); + } +} diff --git a/src/lap_counter/lap_counter.c b/src/lap_counter/lap_counter.c index dfbd299..0894a87 100644 --- a/src/lap_counter/lap_counter.c +++ b/src/lap_counter/lap_counter.c @@ -21,12 +21,13 @@ #include #include #include +#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; } -- 2.7.4