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 "connection_manager.h"
32 #include "cloud/cloud_communication.h"
33 #include "messages/message_manager.h"
34 #include "controller_connection_manager.h"
37 #define ENABLE_MOTOR 1
39 #define CONFIG_GRP_CAR "Car"
40 #define CONFIG_KEY_ID "Id"
41 #define CONFIG_KEY_NAME "Name"
42 #define CLOUD_REQUESTS_FREQUENCY 15
50 typedef struct app_data_s {
53 unsigned int dir_state;
57 static void _initialize_components(app_data *ad);
58 static void _initialize_config();
60 static void service_app_lang_changed(app_event_info_h event_info, void *user_data)
65 static void service_app_region_changed(app_event_info_h event_info, void *user_data)
70 static void service_app_low_battery(app_event_info_h event_info, void *user_data)
72 _E("low battery! exit app");
78 static void service_app_low_memory(app_event_info_h event_info, void *user_data)
83 static inline double __map_round(double val)
85 return floor(val + 0.5);
88 static int __map_range_val(int d_max, int d_min, int v_max, int v_min, int val)
92 slope = 1.0 * (d_max - d_min) / (v_max - v_min);
94 rval = d_min + __map_round(slope * (val - v_min));
99 static int ___map_speed_val(int speed)
101 static const int motor_max = 4095;
102 static const int motor_min = -4095;
103 static const int speed_max = 1000;
104 static const int speed_min = -1000;
106 return __map_range_val(motor_max, motor_min,
107 speed_max, speed_min, speed);
110 static int ___map_servo_val(int servo)
112 static const int motor_max = 500;
113 static const int motor_min = 400;
114 static const int servo_max = 1000;
115 static const int servo_min = -1000;
117 return __map_range_val(motor_max, motor_min,
118 servo_max, servo_min, servo);
122 static int __driving_motors(int servo, int speed)
127 val_servo = ___map_servo_val(servo);
128 val_speed = ___map_speed_val(speed);
130 _D("control motor - servo[%4d : %4d], speed[%4d : %4d]",
131 servo, val_servo, speed, val_speed);
133 resource_set_servo_motor_value(0, val_servo);
134 resource_set_motor_driver_L298N_speed(MOTOR_ID_1, val_speed);
135 resource_set_motor_driver_L298N_speed(MOTOR_ID_2, val_speed);
141 static gboolean __message_dispatcher(gpointer user_data)
143 message_s *msg = NULL;
146 msg = message_pop_from_inqueue();
149 case MESSAGE_CMD_HELLO:
150 /* TODO : say hello to sender */
152 case MESSAGE_CMD_CALIBRATION:
153 /* TODO : set calibration mode */
155 case MESSAGE_CMD_DRIVE:
156 /* TODO : driving car */
157 __driving_motors(msg->servo, msg->speed);
159 case MESSAGE_CMD_BYE:
160 __driving_motors(0, 0);
170 static void __camera(int azimuth, int elevation)
172 //TODO: Camera steering
175 static void __command_received_cb(command_s command) {
176 switch(command.type) {
177 case COMMAND_TYPE_DRIVE:
178 __driving_motors(command.data.steering.direction, command.data.steering.speed);
180 case COMMAND_TYPE_CAMERA:
181 __camera(command.data.camera_position.camera_azimuth, command.data.camera_position.camera_elevation);
183 case COMMAND_TYPE_DRIVE_AND_CAMERA:
184 __driving_motors(command.data.steering_and_camera.direction, command.data.steering_and_camera.speed);
185 __camera(command.data.steering_and_camera.camera_azimuth, command.data.steering_and_camera.camera_elevation);
187 case COMMAND_TYPE_NONE:
190 _E("Unknown command type");
195 static void __conn_state_changed_cb(connection_state_e state,
196 const char *ip, void* user_data)
198 app_data *ad = user_data;
200 _D("connection state changed : %d", state);
202 if (state == CONNECTION_STATE_CONNECTED) {
203 receiver_start(RECEIVER_TYPE_UDP);
206 receiver_stop(RECEIVER_TYPE_UDP);
209 g_source_remove(ad->idle_h);
213 __driving_motors(0, 0);
218 static void _initialize_config()
223 gboolean modified = false;
224 if (config_get_string(CONFIG_GRP_CAR, CONFIG_KEY_ID, &id) != 0) {
225 char *uuid = g_uuid_string_random();
226 config_set_string(CONFIG_GRP_CAR, CONFIG_KEY_ID, uuid);
230 if (config_get_string(CONFIG_GRP_CAR, CONFIG_KEY_NAME, &id) != 0) {
231 config_set_string(CONFIG_GRP_CAR, CONFIG_KEY_NAME, "Passerati");
234 if (modified == true) {
241 static void _initialize_components(app_data *ad)
244 _initialize_config();
245 cloud_communication_init();
246 message_manager_init();
247 controller_connection_manager_listen();
250 static bool service_app_create(void *data)
256 * if you want to use default configuration,
257 * Do not need to call resource_set_motor_driver_L298N_configuration(),
261 ret = resource_set_motor_driver_L298N_configuration(MOTOR_ID_1, 19, 16, 5);
263 _E("resource_set_motor_driver_L298N_configuration()");
266 ret = resource_set_motor_driver_L298N_configuration(MOTOR_ID_2, 26, 20, 4);
268 _E("resource_set_motor_driver_L298N_configuration()");
273 _initialize_components(ad);
274 cloud_communication_start(CLOUD_REQUESTS_FREQUENCY);
276 controller_connection_manager_set_command_received_cb(__command_received_cb);
281 static void service_app_control(app_control_h app_control, void *data)
285 /* set speed 0, to reduce delay of initializing motor driver */
286 resource_set_motor_driver_L298N_speed(MOTOR_ID_1, 0);
287 resource_set_motor_driver_L298N_speed(MOTOR_ID_2, 0);
288 resource_set_servo_motor_value(0, 450);
294 static void service_app_terminate(void *data)
299 g_source_remove(ad->idle_h);
302 controller_connection_manager_release();
303 message_manager_shutdown();
305 cloud_communication_stop();
306 cloud_communication_fini();
310 resource_close_all();
318 int main(int argc, char* argv[])
322 service_app_lifecycle_callback_s event_callback;
323 app_event_handler_h handlers[5] = {NULL, };
325 log_type_set(LOG_TYPE_DLOG);
327 ad = calloc(1, sizeof(app_data));
330 event_callback.create = service_app_create;
331 event_callback.terminate = service_app_terminate;
332 event_callback.app_control = service_app_control;
334 service_app_add_event_handler(&handlers[APP_EVENT_LOW_BATTERY],
335 APP_EVENT_LOW_BATTERY, service_app_low_battery, &ad);
336 service_app_add_event_handler(&handlers[APP_EVENT_LOW_MEMORY],
337 APP_EVENT_LOW_MEMORY, service_app_low_memory, &ad);
338 service_app_add_event_handler(&handlers[APP_EVENT_LANGUAGE_CHANGED],
339 APP_EVENT_LANGUAGE_CHANGED, service_app_lang_changed, &ad);
340 service_app_add_event_handler(&handlers[APP_EVENT_REGION_FORMAT_CHANGED],
341 APP_EVENT_REGION_FORMAT_CHANGED, service_app_region_changed, &ad);
343 ret = service_app_main(argc, argv, &event_callback, ad);
345 _E("failed to start app");