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