2 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
4 * Contact: Jeonghoon Park <jh1979.park@samsung.com>
6 * Licensed under the Flora License, Version 1.1 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://floralicense.org/license/
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
24 #include <service_app.h>
29 #include "cloud/cloud_communication.h"
30 #include "messages/message_manager.h"
31 #include "controller_connection_manager.h"
32 #include "lap_counter/lap_counter.h"
34 #include "lap_counter/lap_counter.h"
36 #define ENABLE_MOTOR 1
37 #define STERING_SERVO_CENTER 340
38 #define STERING_SERVO_RANGE 125
40 #define MAX_UDP_INPUT 10000
42 #define CONFIG_GRP_CAR "Car"
43 #define CONFIG_KEY_ID "Id"
44 #define CONFIG_KEY_NAME "Name"
45 #define CLOUD_REQUESTS_FREQUENCY 15
46 #define AZIMUTH_SERVO_PIN 15
47 #define ELEVATION_SERVO_PIN 14
49 #define ELEVATION_MIN 200
50 #define ELEVATION_MAX 400
51 #define AZIMUTH_MIN 200
52 #define AZIMUTH_MAX 700
60 typedef struct app_data_s {
63 unsigned int dir_state;
64 const char *user_name;
68 static void _initialize_components(app_data *ad);
69 static void _initialize_config();
71 static void service_app_lang_changed(app_event_info_h event_info, void *user_data)
76 static void service_app_region_changed(app_event_info_h event_info, void *user_data)
81 static void service_app_low_battery(app_event_info_h event_info, void *user_data)
83 _E("low battery! exit app");
89 static void service_app_low_memory(app_event_info_h event_info, void *user_data)
94 static inline double __map_round(double val)
96 return floor(val + 0.5);
99 static int __map_range_val(int v_min, int v_max, int d_min, int d_max, int val)
103 slope = 1.0 * (d_max - d_min) / (v_max - v_min);
105 rval = d_min + __map_round(slope * (val - v_min));
110 static inline int ___map_speed_val(int speed)
112 return __map_range_val(-MAX_UDP_INPUT, MAX_UDP_INPUT, -4095, 4095, speed);
115 static inline int ___map_servo_val(int servo)
117 return __map_range_val(-MAX_UDP_INPUT, MAX_UDP_INPUT, STERING_SERVO_CENTER - STERING_SERVO_RANGE, STERING_SERVO_CENTER + STERING_SERVO_RANGE, servo);
120 static int __driving_motors(int servo, int speed)
125 val_servo = ___map_servo_val(servo);
126 val_speed = ___map_speed_val(speed);
128 _D("control motor - servo[%4d : %4d], speed[%4d : %4d]",
129 servo, val_servo, speed, val_speed);
131 resource_set_servo_motor_value(0, val_servo);
132 resource_set_motor_driver_L298N_speed(MOTOR_ID_1, val_speed);
133 resource_set_motor_driver_L298N_speed(MOTOR_ID_2, val_speed);
139 static void __camera(int azimuth, int elevation)
141 int val_azimuth = __map_range_val(-MAX_UDP_INPUT, MAX_UDP_INPUT, AZIMUTH_MIN, AZIMUTH_MAX, azimuth);
142 int val_elevation = __map_range_val(0, MAX_UDP_INPUT, ELEVATION_MIN, ELEVATION_MAX, elevation); // No need to look upside down
144 _D("camera - azimuth[%4d : %4d], elevation[%4d : %4d]", azimuth, val_azimuth, elevation, val_elevation);
146 resource_set_servo_motor_value(ELEVATION_SERVO_PIN, val_elevation);
147 resource_set_servo_motor_value(AZIMUTH_SERVO_PIN, val_azimuth);
151 static void __command_received_cb(command_s command) {
152 switch(command.type) {
153 case COMMAND_TYPE_DRIVE:
154 __driving_motors(command.data.steering.direction, command.data.steering.speed);
156 case COMMAND_TYPE_CAMERA:
157 __camera(command.data.camera_position.camera_azimuth, command.data.camera_position.camera_elevation);
159 case COMMAND_TYPE_DRIVE_AND_CAMERA:
160 __driving_motors(command.data.steering_and_camera.direction, command.data.steering_and_camera.speed);
161 __camera(command.data.steering_and_camera.camera_azimuth, command.data.steering_and_camera.camera_elevation);
163 case COMMAND_TYPE_NONE:
166 _E("Unknown command type");
171 static void __user_name_received_cb(const char *name) {
172 lap_counter_set_user_name(name);
175 static void _initialize_config()
183 gboolean modified = false;
184 if (config_get_string(CONFIG_GRP_CAR, CONFIG_KEY_ID, &id) != 0) {
185 char *uuid = g_uuid_string_random();
186 config_set_string(CONFIG_GRP_CAR, CONFIG_KEY_ID, uuid);
190 if (config_get_string(CONFIG_GRP_CAR, CONFIG_KEY_NAME, &id) != 0) {
191 config_set_string(CONFIG_GRP_CAR, CONFIG_KEY_NAME, "Passerati");
194 if (modified == true) {
201 static void _initialize_components(app_data *ad)
204 _initialize_config();
205 cloud_communication_init();
206 message_manager_init();
207 controller_connection_manager_listen();
211 static bool service_app_create(void *data)
216 _D("-----------------------=======================================================================-----------------------");
217 _D("-----------------------=======================================================================-----------------------");
218 _D("-----------------------============================== APP %s %s ==============================-----------------------", __DATE__, __TIME__);
219 _D("-----------------------=======================================================================-----------------------");
220 _D("-----------------------=======================================================================-----------------------");
223 * if you want to use default configuration,
224 * Do not need to call resource_set_motor_driver_L298N_configuration(),
228 ret = resource_set_motor_driver_L298N_configuration(MOTOR_ID_1, 19, 16, 5);
230 _E("resource_set_motor_driver_L298N_configuration()");
233 ret = resource_set_motor_driver_L298N_configuration(MOTOR_ID_2, 26, 20, 4);
235 _E("resource_set_motor_driver_L298N_configuration()");
240 resource_lap_counter_init();
242 _initialize_components(ad);
243 cloud_communication_start(CLOUD_REQUESTS_FREQUENCY);
245 controller_connection_manager_set_command_received_cb(__command_received_cb);
246 controller_connection_manager_set_user_name_received_cb(__user_name_received_cb);
252 static void service_app_control(app_control_h app_control, void *data)
256 /* set speed 0, to reduce delay of initializing motor driver */
257 resource_set_motor_driver_L298N_speed(MOTOR_ID_1, 0);
258 resource_set_motor_driver_L298N_speed(MOTOR_ID_2, 0);
259 resource_set_servo_motor_value(0, 450);
260 resource_set_servo_motor_value(ELEVATION_SERVO_PIN, ELEVATION_MIN);
261 resource_set_servo_motor_value(AZIMUTH_SERVO_PIN, (AZIMUTH_MIN + AZIMUTH_MAX) / 2);
267 static void service_app_terminate(void *data)
271 resource_set_servo_motor_value(0, STERING_SERVO_CENTER);
272 resource_set_servo_motor_value(ELEVATION_SERVO_PIN, ELEVATION_MIN);
273 resource_set_servo_motor_value(AZIMUTH_SERVO_PIN, (AZIMUTH_MIN + AZIMUTH_MAX) / 2);
275 resource_lap_counter_destroy();
278 g_source_remove(ad->idle_h);
280 lap_counter_shutdown();
281 controller_connection_manager_release();
282 message_manager_shutdown();
284 cloud_communication_stop();
285 cloud_communication_fini();
289 resource_close_all();
297 int main(int argc, char* argv[])
301 service_app_lifecycle_callback_s event_callback;
302 app_event_handler_h handlers[5] = {NULL, };
304 log_type_set(LOG_TYPE_DLOG);
306 ad = calloc(1, sizeof(app_data));
309 event_callback.create = service_app_create;
310 event_callback.terminate = service_app_terminate;
311 event_callback.app_control = service_app_control;
313 service_app_add_event_handler(&handlers[APP_EVENT_LOW_BATTERY],
314 APP_EVENT_LOW_BATTERY, service_app_low_battery, &ad);
315 service_app_add_event_handler(&handlers[APP_EVENT_LOW_MEMORY],
316 APP_EVENT_LOW_MEMORY, service_app_low_memory, &ad);
317 service_app_add_event_handler(&handlers[APP_EVENT_LANGUAGE_CHANGED],
318 APP_EVENT_LANGUAGE_CHANGED, service_app_lang_changed, &ad);
319 service_app_add_event_handler(&handlers[APP_EVENT_REGION_FORMAT_CHANGED],
320 APP_EVENT_REGION_FORMAT_CHANGED, service_app_region_changed, &ad);
322 ret = service_app_main(argc, argv, &event_callback, ad);
324 _E("failed to start app");