// // Copyright(c) 2021 LIACS, Leiden University // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. // // Author: // // Richard M.K. van Dijk // Research sofware engineer // E: m.k.van.dijk@liacs.leidenuniv.nl // // Leiden University, // Faculty of Math and Natural Sciences, // Leiden Institute of Advanced Computer Science (LIACS) // Snellius building | Niels Bohrweg 1 | 2333 CA Leiden // The Netherlands // #include "sensorapplication.h" /** * * @brief All UI widgets used in the front-end. * */ typedef struct appdata { Evas_Object *win; Evas_Object *conform; Evas_Object *box; Evas_Object *spinner_person_id; Evas_Object *button_restart; Evas_Object *button_clean; } appdata_s; float g_person_id = 0; /** * * @brief Launch / terminate the sensor service in the background. * */ static void launch_sensor_service() { int result; app_control_h app_control; app_control_create(&app_control); app_control_set_operation(app_control, APP_CONTROL_OPERATION_DEFAULT); app_control_set_app_id(app_control, "liacs.sensorservice"); result = app_control_send_launch_request(app_control, NULL, NULL); if(result == APP_CONTROL_ERROR_NONE) dlog_print(DLOG_INFO, LOG_TAG, "SensorService launched %d", result); else dlog_print(DLOG_DEBUG, LOG_TAG, "SensorService not launched %d", result); app_control_destroy(app_control); return; } static void terminate_sensor_service() { int result; app_control_h app_control; app_control_create(&app_control); app_control_set_operation(app_control, APP_CONTROL_OPERATION_DEFAULT); app_control_set_app_id(app_control, "liacs.sensorservice"); result = app_control_send_terminate_request(app_control); if(result == APP_CONTROL_ERROR_NONE) dlog_print(DLOG_INFO, LOG_TAG, "SensorService terminated"); else dlog_print(DLOG_DEBUG, LOG_TAG, "SensorService not terminated"); app_control_destroy(app_control); return; } /** * * @brief The send_person_identifier_to_service() will sent the person id to * the sensor service. * * @details The service will stop the actual measurement and will start a new measurement. * This will also happen if the person identifier of the actual measurement is identical with the * new one. In that case new sensor files are created (and the older ones will stay in the folder). * * There will be no reply from the sensor service expected (fire-and-forget scenario). * * @param[in] person identifier is an unsigned int between 000 and 999 (3 digit number). * */ static void send_person_identifier_to_service(unsigned int personid) { int result = -1; app_control_h app_control; char personid_string[32]; app_control_create(&app_control); app_control_set_operation(app_control, APP_CONTROL_OPERATION_SEND); snprintf(personid_string, 32, "restart %03d", personid); app_control_set_uri(app_control, &personid_string); app_control_set_app_id(app_control, "liacs.sensorservice"); result = app_control_send_launch_request(app_control, NULL, NULL); if(result == APP_CONTROL_ERROR_NONE) dlog_print(DLOG_INFO, LOG_TAG, "Send person identifier %03d %d", personid, result); else dlog_print(DLOG_DEBUG, LOG_TAG, "Send person identifier %03d not send %d", personid, result); app_control_destroy(app_control); return; } /** * * @brief The send_delete_all_sensor_files_to_service() will send the command to delete all sensor files * created by the sensor service in its data folder, to the sensor service. * * @details The service will delete all the *aag.dat, *bar.dat, *con.dat and *gps.dat files found in its data folder. * In order to do this the service will stop measuring first before deleting all sensor files. So the last * sensor file created will also be deleted. So some measurements are lost in that case. * * There will be no reply from the sensor service expected (fire-and-forget scenario). * * Deleting files in the Tizen OS can only be done by the app / service which created the files. * */ static void send_delete_all_sensor_files_to_service() { int result = -1; app_control_h app_control; const char *delete_string = "clean"; app_control_create(&app_control); app_control_set_operation(app_control, APP_CONTROL_OPERATION_SEND); app_control_set_uri(app_control, delete_string); app_control_set_app_id(app_control, "liacs.sensorservice"); result = app_control_send_launch_request(app_control, NULL, NULL); if(result == APP_CONTROL_ERROR_NONE) dlog_print(DLOG_INFO, LOG_TAG, "Send delete all sensor files %d", result); else dlog_print(DLOG_DEBUG, LOG_TAG, "Send delete all sensor files not send %d", result); app_control_destroy(app_control); return; } /** * * @brief Here follows the callbacks of the UI. * */ static void win_delete_request_cb(void *data, Evas_Object *obj, void *event_info) { dlog_print(DLOG_INFO, LOG_TAG, "Delete request call back\n"); ui_app_exit(); } static void win_back_cb(void *data, Evas_Object *obj, void *event_info) { dlog_print(DLOG_INFO, LOG_TAG, "Back button pressed call back\n"); ui_app_exit(); } /** * * @brief Call back called if spinner changed value and is in focus. * */ static void spinner_value_change_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { g_person_id = elm_spinner_value_get(obj); dlog_print(DLOG_INFO, LOG_TAG, "Spinner in focus of %03d\n", (int)g_person_id); } /** * * @brief Here follows the call backs of the buttons restart and clean. * * The restart button will restart the measurement with a given person identifier. * It will stop the running measurement. * * The clean button must be pressed three times in order to have effect. * It will stop the running measurement, delete all sensor files * on the watch and then continue on with the measurement. * */ static void button_restart_clicked_cb(void *data, Evas_Object *obj, void *event_info) { dlog_print(DLOG_INFO, LOG_TAG, "Button restart clicked \n"); send_person_identifier_to_service(g_person_id); sleep(1); ui_app_exit(); } int g_clean_obstacle_counter = 0; static void button_clean_clicked_cb(void *data, Evas_Object *obj, void *event_info) { dlog_print(DLOG_INFO, LOG_TAG, "Button clean clicked %d\n", g_clean_obstacle_counter); if(g_clean_obstacle_counter < 2) { g_clean_obstacle_counter++; return; } g_clean_obstacle_counter = 0; send_delete_all_sensor_files_to_service(); sleep(1); ui_app_exit(); } static void create_base_gui(appdata_s *ad) { // Define Window and box ad->win = elm_win_util_standard_add(PACKAGE, PACKAGE); elm_win_autodel_set(ad->win, EINA_TRUE); if (elm_win_wm_rotation_supported_get(ad->win)) { int rots[4] = { 0, 90, 180, 270 }; elm_win_wm_rotation_available_rotations_set(ad->win, (const int *)(&rots), 4); } evas_object_smart_callback_add(ad->win, "delete,request", win_delete_request_cb, NULL); eext_object_event_callback_add(ad->win, EEXT_CALLBACK_BACK, win_back_cb, ad); ad->box = elm_box_add(ad->win); evas_object_show(ad->box); // Define a spinner component, part of the box ad->spinner_person_id = elm_spinner_add(ad->win); elm_object_style_set(ad->spinner_person_id, "vertical"); elm_spinner_interval_set(ad->spinner_person_id, 0.1); elm_spinner_step_set(ad->spinner_person_id, 1); elm_spinner_label_format_set(ad->spinner_person_id, "%03d"); elm_spinner_min_max_set(ad->spinner_person_id, 0, 999); evas_object_size_hint_weight_set(ad->spinner_person_id, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(ad->spinner_person_id, EVAS_HINT_FILL, 0.5); elm_spinner_editable_set(ad->spinner_person_id, EINA_TRUE); evas_object_smart_callback_add(ad->spinner_person_id, "unfocused", spinner_value_change_cb, NULL); elm_box_pack_start(ad->box, ad->spinner_person_id); evas_object_show(ad->spinner_person_id); // Define the start button ad->button_restart = elm_button_add(ad->win); elm_object_style_set(ad->button_restart, "vertical"); elm_object_part_text_set(ad->button_restart, NULL, "RESTART"); evas_object_size_hint_weight_set(ad->button_restart, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(ad->button_restart, EVAS_HINT_FILL, 0.5); elm_box_pack_end(ad->box, ad->button_restart); evas_object_smart_callback_add(ad->button_restart, "clicked", button_restart_clicked_cb, NULL); evas_object_show(ad->button_restart); // Define the stop button ad->button_clean = elm_button_add(ad->win); elm_object_style_set(ad->button_clean, "vertical"); elm_object_part_text_set(ad->button_clean, NULL, "CLEAN"); evas_object_size_hint_weight_set(ad->button_clean, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(ad->button_clean, EVAS_HINT_FILL, 0.5); elm_box_pack_end(ad->box, ad->button_clean); evas_object_smart_callback_add(ad->button_clean, "clicked", button_clean_clicked_cb, NULL); evas_object_show(ad->button_clean); /* Show window after base gui is set up */ evas_object_show(ad->win); } /** * * @brief Standard callbacks of the application in control of the Tizen framework. * */ static bool app_create(void *data) { dlog_print(DLOG_INFO, LOG_TAG, "SensorApplication created"); appdata_s *ad = data; create_base_gui(ad); return true; } static void app_control(app_control_h app_control, void *data) { dlog_print(DLOG_INFO, LOG_TAG, "SensorApplication controlled"); launch_sensor_service(); } static void app_pause(void *data) { dlog_print(DLOG_INFO, LOG_TAG, "SensorApplication paused"); } static void app_resume(void *data) { dlog_print(DLOG_INFO, LOG_TAG, "SensorApplication resumed"); } static void app_terminate(void *data) { dlog_print(DLOG_INFO, LOG_TAG, "SensorApplication terminated"); } static void ui_app_low_battery(app_event_info_h event_info, void *user_data) { dlog_print(DLOG_INFO, LOG_TAG, "SensorApplication low battery"); return; } static void ui_app_low_memory(app_event_info_h event_info, void *user_data) { dlog_print(DLOG_INFO, LOG_TAG, "SensorApplication low memory"); return; } /** * * main() * */ int main(int argc, char *argv[]) { appdata_s ad = {0,}; int ret = 0; ui_app_lifecycle_callback_s event_callback = {0,}; app_event_handler_h handlers[5] = {NULL, }; event_callback.create = app_create; event_callback.terminate = app_terminate; event_callback.pause = app_pause; event_callback.resume = app_resume; event_callback.app_control = app_control; ui_app_add_event_handler(&handlers[APP_EVENT_LOW_BATTERY], APP_EVENT_LOW_BATTERY, ui_app_low_battery, &ad); ui_app_add_event_handler(&handlers[APP_EVENT_LOW_MEMORY], APP_EVENT_LOW_MEMORY, ui_app_low_memory, &ad); ret = ui_app_main(argc, argv, &event_callback, &ad); if (ret != APP_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "app_main() is failed. err = %d", ret); } return ret; }