applys message and connection manager modules
[apps/native/gear-racing-car.git] / src / app.c
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
3  *
4  * Contact: Jeonghoon Park <jh1979.park@samsung.com>
5  *
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
9  *
10  * http://floralicense.org/license/
11  *
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.
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <math.h>
23 #include <glib.h>
24 #include <service_app.h>
25 #include "log.h"
26 #include "resource.h"
27 #include "receiver.h"
28 #include "message.h"
29 #include "connection_manager.h"
30
31 #define ENABLE_MOTOR 1
32
33 enum {
34         DIR_STATE_S,
35         DIR_STATE_F,
36         DIR_STATE_B,
37 };
38
39 typedef struct app_data_s {
40         unsigned int f_value;
41         unsigned int r_value;
42         unsigned int dir_state;
43         guint idle_h;
44 } app_data;
45
46 static void service_app_lang_changed(app_event_info_h event_info, void *user_data)
47 {
48         return;
49 }
50
51 static void service_app_region_changed(app_event_info_h event_info, void *user_data)
52 {
53         return;
54 }
55
56 static void service_app_low_battery(app_event_info_h event_info, void *user_data)
57 {
58         _E("low battery! exit app");
59         service_app_exit();
60
61         return;
62 }
63
64 static void service_app_low_memory(app_event_info_h event_info, void *user_data)
65 {
66         return;
67 }
68
69 static inline double __map_round(double val)
70 {
71         return floor(val + 0.5);
72 }
73
74 static int __map_range_val(int d_max, int d_min, int v_max, int v_min, int val)
75 {
76         int rval = 0;
77         double slope = 0;
78         slope = 1.0 * (d_max - d_min) / (v_max - v_min);
79
80         rval = d_min + round(slope * (val - v_min));
81
82         return rval;
83 }
84
85 static int ___map_speed_val(int speed)
86 {
87         static const int motor_max = 4095;
88         static const int motor_min = -4095;
89         static const int speed_max = 1000;
90         static const int speed_min = -1000;
91
92         return __map_range_val(motor_max, motor_min,
93                 speed_max, speed_min, speed);
94 }
95
96 static int ___map_servo_val(int servo)
97 {
98         static const int motor_max = 500;
99         static const int motor_min = 400;
100         static const int servo_max = 1000;
101         static const int servo_min = -1000;
102
103         return __map_range_val(motor_max, motor_min,
104                 servo_max, servo_min, servo);
105 }
106
107
108 static int __driving_motors(int servo, int speed)
109 {
110         int val_speed;
111         int val_servo;
112
113         val_servo = ___map_servo_val(servo);
114         val_speed = ___map_speed_val(speed);
115
116         _D("control motor - servo[%4d : %4d], speed[%4d : %4d]",
117                 servo, val_servo, speed, val_speed);
118 #if ENABLE_MOTOR
119         resource_set_servo_motor_value(0, val_servo);
120         resource_set_motor_driver_L298N_speed(MOTOR_ID_1, val_speed);
121         resource_set_motor_driver_L298N_speed(MOTOR_ID_2, val_speed);
122 #endif
123
124         return 0;
125 }
126
127 static gboolean __message_dispatcher(gpointer user_data)
128 {
129         message_s *msg = NULL;
130
131         do {
132                 msg = message_pop_from_inqueue();
133                 if (msg) {
134                         switch (msg->cmd) {
135                         case MESSAGE_CMD_HELLO:
136                                 /* TODO : say hello to sender */
137                                 break;
138                         case MESSAGE_CMD_CALIBRATION:
139                                 /* TODO : set calibration mode */
140                                 break;
141                         case MESSAGE_CMD_DRIVE:
142                         /* TODO : driving car */
143                                 __driving_motors(msg->servo, msg->speed);
144                                 break;
145                         case MESSAGE_CMD_BYE:
146                                 __driving_motors(0, 0);
147                                 break;
148                         }
149                 }
150                 free(msg);
151         } while (msg);
152
153         return TRUE;
154 }
155
156 static void __recv_state_change(receiver_type_e type,
157         receiver_state_e state, void* user_data)
158 {
159         app_data *ad = user_data;
160         ret_if(!ad);
161
162         _D("receiver type[%d] state changed[%d]", type, state);
163
164         if (state == RECEIVER_STATE_CONNECTED) {
165                 if (!ad->idle_h)
166                         ad->idle_h = g_idle_add(__message_dispatcher, ad);
167         } else {
168                 if (ad->idle_h) {
169                         g_source_remove(ad->idle_h);
170                         ad->idle_h = 0;
171                 }
172                 __driving_motors(0, 0);
173         }
174
175         return;
176 }
177
178 static void __conn_state_changed_cb(connection_state_e state,
179         const char *ip, void* user_data)
180 {
181         app_data *ad = user_data;
182
183         _D("connection state changed : %d", state);
184
185         if (state == CONNECTION_STATE_CONNECTED) {
186                 receiver_start(RECEIVER_TYPE_UDP);
187
188         } else {
189                 receiver_stop(RECEIVER_TYPE_UDP);
190
191                 if (ad->idle_h) {
192                         g_source_remove(ad->idle_h);
193                         ad->idle_h = 0;
194                 }
195
196                 __driving_motors(0, 0);
197         }
198         return;
199 }
200
201 static bool service_app_create(void *data)
202 {
203         int ret = 0;
204         app_data *ad = data;
205
206         receiver_init(RECEIVER_TYPE_UDP);
207         receiver_set_state_changed_cb(RECEIVER_TYPE_UDP, __recv_state_change, ad);
208
209         connection_manager_init();
210         connection_manager_set_state_changed_cb(__conn_state_changed_cb, ad);
211
212         message_queue_new();
213
214         /*
215          * if you want to use default configuration,
216          * Do not need to call resource_set_motor_driver_L298N_configuration(),
217          *
218         */
219 #if ENABLE_MOTOR
220         ret = resource_set_motor_driver_L298N_configuration(MOTOR_ID_1, 19, 16, 5);
221         if (ret) {
222                 _E("resource_set_motor_driver_L298N_configuration()");
223                 service_app_exit();
224         }
225         ret = resource_set_motor_driver_L298N_configuration(MOTOR_ID_2, 26, 20, 4);
226         if (ret) {
227                 _E("resource_set_motor_driver_L298N_configuration()");
228                 service_app_exit();
229         }
230 #endif
231
232         return true;
233 }
234
235 static void service_app_control(app_control_h app_control, void *data)
236 {
237
238 #if ENABLE_MOTOR
239         /* set speed 0, to reduce delay of initializing motor driver */
240         resource_set_motor_driver_L298N_speed(MOTOR_ID_1, 0);
241         resource_set_motor_driver_L298N_speed(MOTOR_ID_2, 0);
242         resource_set_servo_motor_value(0, 450);
243 #endif
244
245         return;
246 }
247
248 static void service_app_terminate(void *data)
249 {
250         app_data *ad = data;
251
252         if (ad->idle_h)
253                 g_source_remove(ad->idle_h);
254
255
256         connection_manager_fini();
257         receiver_fini(RECEIVER_TYPE_UDP);
258
259         resource_close_all();
260         log_file_close();
261
262         _D("Bye ~");
263
264         return;
265 }
266
267 int main(int argc, char* argv[])
268 {
269         app_data *ad = NULL;
270         int ret = 0;
271         service_app_lifecycle_callback_s event_callback;
272         app_event_handler_h handlers[5] = {NULL, };
273
274         log_type_set(LOG_TYPE_DLOG);
275
276         ad = calloc(1, sizeof(app_data));
277         retv_if(!ad, -1);
278
279         event_callback.create = service_app_create;
280         event_callback.terminate = service_app_terminate;
281         event_callback.app_control = service_app_control;
282
283         service_app_add_event_handler(&handlers[APP_EVENT_LOW_BATTERY],
284                 APP_EVENT_LOW_BATTERY, service_app_low_battery, &ad);
285         service_app_add_event_handler(&handlers[APP_EVENT_LOW_MEMORY],
286                 APP_EVENT_LOW_MEMORY, service_app_low_memory, &ad);
287         service_app_add_event_handler(&handlers[APP_EVENT_LANGUAGE_CHANGED],
288                 APP_EVENT_LANGUAGE_CHANGED, service_app_lang_changed, &ad);
289         service_app_add_event_handler(&handlers[APP_EVENT_REGION_FORMAT_CHANGED],
290                 APP_EVENT_REGION_FORMAT_CHANGED, service_app_region_changed, &ad);
291
292         ret = service_app_main(argc, argv, &event_callback, ad);
293         if (ret)
294                 _E("failed to start app");
295
296         return 0;
297 }