Change peripheral io APIs
[apps/native/position-finder-server.git] / src / connectivity.c
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
3  *
4  * Contact: Jin Yoon <jinny.yoon@samsung.com>
5  *          Geunsun Lee <gs86.lee@samsung.com>
6  *          Eunyoung Lee <ey928.lee@samsung.com>
7  *          Junkyu Han <junkyu.han@samsung.com>
8  *
9  * Licensed under the Flora License, Version 1.1 (the License);
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://floralicense.org/license/
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an AS IS BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stdbool.h>
25 #include <glib.h>
26 #include <Eina.h>
27 #include <app_common.h>
28
29 #include "log.h"
30 #include "connectivity.h"
31
32 #define ULTRASONIC_RESOURCE_TYPE "org.tizen.door"
33 #define BUFSIZE 1024
34 #define URI_PATH_LEN 64
35 #define URI_PATH "/door/1"
36 #define PATH "path"
37
38 static void _request_resource_handler(iotcon_resource_h resource, iotcon_request_h request, void *user_data);
39
40 static int _send_response(iotcon_request_h request, iotcon_representation_h representation, iotcon_response_result_e result)
41 {
42         int ret = -1;
43         iotcon_response_h response;
44
45         ret = iotcon_response_create(request, &response);
46         retv_if(IOTCON_ERROR_NONE != ret, -1);
47
48         ret = iotcon_response_set_result(response, result);
49         goto_if(IOTCON_ERROR_NONE != ret, error);
50
51         ret = iotcon_response_set_representation(response, representation);
52         goto_if(IOTCON_ERROR_NONE != ret, error);
53
54         ret = iotcon_response_send(response);
55         goto_if(IOTCON_ERROR_NONE != ret, error);
56
57         iotcon_response_destroy(response);
58
59         return 0;
60
61 error:
62         iotcon_response_destroy(response);
63         return -1;
64 }
65
66 static void _destroy_representation(iotcon_representation_h representation)
67 {
68         ret_if(!representation);
69         iotcon_representation_destroy(representation);
70 }
71
72 static iotcon_representation_h _create_representation_with_bool(connectivity_resource_s *resource_info, const char *key, bool value)
73 {
74         iotcon_attributes_h attributes = NULL;
75         iotcon_representation_h representation = NULL;
76         char *uri_path = NULL;
77         int ret = -1;
78
79         ret = iotcon_resource_get_uri_path(resource_info->res, &uri_path);
80         retv_if(IOTCON_ERROR_NONE != ret, NULL);
81
82         ret = iotcon_representation_create(&representation);
83         retv_if(IOTCON_ERROR_NONE != ret, NULL);
84
85         ret = iotcon_attributes_create(&attributes);
86         goto_if(IOTCON_ERROR_NONE != ret, error);
87
88         ret = iotcon_representation_set_uri_path(representation, uri_path);
89         goto_if(IOTCON_ERROR_NONE != ret, error);
90
91         ret = iotcon_attributes_add_str(attributes, PATH, resource_info->path);
92         goto_if(IOTCON_ERROR_NONE != ret, error);
93
94         ret = iotcon_attributes_add_bool(attributes, key, value);
95         goto_if(IOTCON_ERROR_NONE != ret, error);
96
97         ret = iotcon_representation_set_attributes(representation, attributes);
98         goto_if(IOTCON_ERROR_NONE != ret, error);
99
100         iotcon_attributes_destroy(attributes);
101
102         return representation;
103
104 error:
105         if (attributes) iotcon_attributes_destroy(attributes);
106         if (representation) iotcon_representation_destroy(representation);
107
108         return NULL;
109 }
110
111 static iotcon_representation_h _create_representation_with_int(connectivity_resource_s *resource_info, const char *key, int value)
112 {
113         iotcon_attributes_h attributes = NULL;
114         iotcon_representation_h representation = NULL;
115         char *uri_path = NULL;
116         int ret = -1;
117
118         ret = iotcon_resource_get_uri_path(resource_info->res, &uri_path);
119         retv_if(IOTCON_ERROR_NONE != ret, NULL);
120
121         ret = iotcon_representation_create(&representation);
122         retv_if(IOTCON_ERROR_NONE != ret, NULL);
123
124         ret = iotcon_attributes_create(&attributes);
125         goto_if(IOTCON_ERROR_NONE != ret, error);
126
127         ret = iotcon_representation_set_uri_path(representation, uri_path);
128         goto_if(IOTCON_ERROR_NONE != ret, error);
129
130         ret = iotcon_attributes_add_str(attributes, PATH, resource_info->path);
131         goto_if(IOTCON_ERROR_NONE != ret, error);
132
133         ret = iotcon_attributes_add_int(attributes, key, value);
134         goto_if(IOTCON_ERROR_NONE != ret, error);
135
136         ret = iotcon_representation_set_attributes(representation, attributes);
137         goto_if(IOTCON_ERROR_NONE != ret, error);
138
139         iotcon_attributes_destroy(attributes);
140
141         return representation;
142
143 error:
144         if (attributes) iotcon_attributes_destroy(attributes);
145         if (representation) iotcon_representation_destroy(representation);
146
147         return NULL;
148 }
149
150 static iotcon_representation_h _create_representation_with_double(connectivity_resource_s *resource_info, const char *key, double value)
151 {
152         iotcon_attributes_h attributes = NULL;
153         iotcon_representation_h representation = NULL;
154         char *uri_path = NULL;
155         int ret = -1;
156
157         ret = iotcon_resource_get_uri_path(resource_info->res, &uri_path);
158         retv_if(IOTCON_ERROR_NONE != ret, NULL);
159
160         ret = iotcon_representation_create(&representation);
161         retv_if(IOTCON_ERROR_NONE != ret, NULL);
162
163         ret = iotcon_attributes_create(&attributes);
164         goto_if(IOTCON_ERROR_NONE != ret, error);
165
166         ret = iotcon_representation_set_uri_path(representation, uri_path);
167         goto_if(IOTCON_ERROR_NONE != ret, error);
168
169         ret = iotcon_attributes_add_str(attributes, PATH, resource_info->path);
170         goto_if(IOTCON_ERROR_NONE != ret, error);
171
172         ret = iotcon_attributes_add_double(attributes, key, value);
173         goto_if(IOTCON_ERROR_NONE != ret, error);
174
175         ret = iotcon_representation_set_attributes(representation, attributes);
176         goto_if(IOTCON_ERROR_NONE != ret, error);
177
178         iotcon_attributes_destroy(attributes);
179
180         return representation;
181
182 error:
183         if (attributes) iotcon_attributes_destroy(attributes);
184         if (representation) iotcon_representation_destroy(representation);
185
186         return NULL;
187 }
188
189 static void _print_iotcon_error(int err_no)
190 {
191         switch (err_no) {
192         case IOTCON_ERROR_NOT_SUPPORTED:
193                 _E("IOTCON_ERROR_NOT_SUPPORTED");
194                 break;
195         case IOTCON_ERROR_PERMISSION_DENIED:
196                 _E("IOTCON_ERROR_PERMISSION_DENIED");
197                 break;
198         case IOTCON_ERROR_INVALID_PARAMETER:
199                 _E("IOTCON_ERROR_INVALID_PARAMETER");
200                 break;
201         default:
202                 _E("Error : [%d]", err_no);
203                 break;
204         }
205 }
206
207 int connectivity_notify_bool(connectivity_resource_s *resource_info, const char *key, bool value)
208 {
209         iotcon_representation_h representation;
210         int ret = -1;
211
212         retv_if(!resource_info, -1);
213         retv_if(!resource_info->observers, -1);
214
215         _D("Notify the value[%d]", value);
216
217         representation = _create_representation_with_bool(resource_info, key, value);
218         retv_if(!representation, -1);
219
220         ret = iotcon_resource_notify(resource_info->res, representation, resource_info->observers, IOTCON_QOS_LOW);
221         if (IOTCON_ERROR_NONE != ret) {
222                 _I("There are some troubles for notifying value[%d]", ret);
223                 _print_iotcon_error(ret);
224                 return -1;
225         }
226
227         _destroy_representation(representation);
228
229         return 0;
230 }
231
232 int connectivity_notify_int(connectivity_resource_s *resource_info, const char *key, int value)
233 {
234         iotcon_representation_h representation;
235         int ret = -1;
236
237         retv_if(!resource_info, -1);
238         retv_if(!resource_info->observers, -1);
239
240         _D("Notify the value[%d]", value);
241
242         representation = _create_representation_with_int(resource_info, key, value);
243         retv_if(!representation, -1);
244
245         ret = iotcon_resource_notify(resource_info->res, representation, resource_info->observers, IOTCON_QOS_LOW);
246         if (IOTCON_ERROR_NONE != ret) {
247                 _I("There are some troubles for notifying value[%d]", ret);
248                 _print_iotcon_error(ret);
249                 return -1;
250         }
251
252         _destroy_representation(representation);
253
254         return 0;
255 }
256
257 int connectivity_notify_double(connectivity_resource_s *resource_info, const char *key, double value)
258 {
259         iotcon_representation_h representation;
260         int ret = -1;
261
262         retv_if(!resource_info, -1);
263         retv_if(!resource_info->observers, -1);
264
265         _D("Notify the value[%f]", value);
266
267         representation = _create_representation_with_double(resource_info, key, value);
268         retv_if(!representation, -1);
269
270         ret = iotcon_resource_notify(resource_info->res, representation, resource_info->observers, IOTCON_QOS_LOW);
271         if (IOTCON_ERROR_NONE != ret) {
272                 _I("There are some troubles for notifying value[%d]", ret);
273                 _print_iotcon_error(ret);
274                 return -1;
275         }
276
277         _destroy_representation(representation);
278
279         return 0;
280 }
281
282 static bool _query_cb(const char *key, const char *value, void *user_data)
283 {
284         _D("Key : [%s], Value : [%s]", key, value);
285
286         return IOTCON_FUNC_CONTINUE;
287 }
288
289 static int _handle_query(iotcon_request_h request)
290 {
291         iotcon_query_h query = NULL;
292         int ret = -1;
293
294         ret = iotcon_request_get_query(request, &query);
295         retv_if(IOTCON_ERROR_NONE != ret, -1);
296
297         if (query) iotcon_query_foreach(query, _query_cb, NULL);
298
299         return 0;
300 }
301
302 static int _handle_request_by_crud_type(iotcon_request_h request, connectivity_resource_s *resource_info)
303 {
304         iotcon_request_type_e type;
305         int ret = -1;
306
307         ret = iotcon_request_get_request_type(request, &type);
308         retv_if(IOTCON_ERROR_NONE != ret, -1);
309
310         switch (type) {
311         case IOTCON_REQUEST_GET:
312                 _I("Do not support 'get' query");
313                 break;
314         case IOTCON_REQUEST_PUT:
315                 _I("Do not support 'put' query");
316                 break;
317         case IOTCON_REQUEST_POST:
318                 _I("Do not support 'post' query");
319                 break;
320         case IOTCON_REQUEST_DELETE:
321                 _I("Do not support 'delete' query");
322                 break;
323         default:
324                 _E("Cannot reach here");
325                 ret = -1;
326                 break;
327         }
328         retv_if(0 != ret, -1);
329
330         return 0;
331 }
332
333 static int _handle_observer(iotcon_request_h request, iotcon_observers_h observers)
334 {
335         iotcon_observe_type_e observe_type;
336         int ret = -1;
337         int observe_id = -1;
338
339         ret = iotcon_request_get_observe_type(request, &observe_type);
340         retv_if(IOTCON_ERROR_NONE != ret, -1);
341
342         if (IOTCON_OBSERVE_REGISTER == observe_type) {
343                 ret = iotcon_request_get_observe_id(request, &observe_id);
344                 retv_if(IOTCON_ERROR_NONE != ret, -1);
345
346                 _I("Add an observer : %d", observe_id);
347
348                 ret = iotcon_observers_add(observers, observe_id);
349                 retv_if(IOTCON_ERROR_NONE != ret, -1);
350         } else if (IOTCON_OBSERVE_DEREGISTER == observe_type) {
351                 ret = iotcon_request_get_observe_id(request, &observe_id);
352                 retv_if(IOTCON_ERROR_NONE != ret, -1);
353
354                 _I("Remove an observer : %d", observe_id);
355
356                 ret = iotcon_observers_remove(observers, observe_id);
357                 retv_if(IOTCON_ERROR_NONE != ret, -1);
358         }
359
360         return 0;
361 }
362
363 static void _request_resource_handler(iotcon_resource_h resource, iotcon_request_h request, void *user_data)
364 {
365         connectivity_resource_s *resource_info = user_data;
366         int ret = -1;
367         char *host_address = NULL;
368
369         ret_if(!request);
370
371         ret = iotcon_request_get_host_address(request, &host_address);
372         goto_if(IOTCON_ERROR_NONE != ret, error);
373
374         _D("Host address : %s", host_address);
375
376         ret = _handle_query(request);
377         goto_if(IOTCON_ERROR_NONE != ret, error);
378
379         ret = _handle_request_by_crud_type(request, resource_info);
380         goto_if(0 != ret, error);
381
382         ret = _handle_observer(request, resource_info->observers);
383         goto_if(0 != ret, error);
384
385         return;
386
387 error:
388         _send_response(request, NULL, IOTCON_RESPONSE_ERROR);
389 }
390
391 static void _copy_file(const char *in_filename, const char *out_filename)
392 {
393         char buf[BUFSIZE] = { 0, };
394         size_t nread = 0;
395         FILE *in = NULL;
396         FILE *out = NULL;
397
398         ret_if(!in_filename);
399         ret_if(!out_filename);
400
401         in = fopen(in_filename, "r");
402         ret_if(!in);
403
404         out = fopen(out_filename, "w");
405         goto_if(!out, error);
406
407         rewind(in);
408         while ((nread = fread(buf, 1, sizeof(buf), in)) > 0) {
409                 if (fwrite(buf, 1, nread, out) < nread) {
410                         _E("critical error to copy a file");
411                         break;
412                 }
413         }
414
415         fclose(in);
416         fclose(out);
417
418         return;
419
420 error:
421         fclose(out);
422 }
423
424 int connectivity_init(void)
425 {
426         int ret = -1;
427
428         _copy_file(CBOR_FILE_IN_RES, CBOR_FILE_IN_DATA);
429
430         ret = iotcon_initialize(CBOR_FILE_IN_DATA);
431         retv_if(IOTCON_ERROR_NONE != ret, -1);
432
433         ret = iotcon_set_device_name(ULTRASONIC_RESOURCE_TYPE);
434         goto_if(IOTCON_ERROR_NONE != ret, error);
435
436         return 0;
437
438 error:
439         iotcon_deinitialize();
440         return -1;
441 }
442
443 int connectivity_fini(void)
444 {
445         iotcon_deinitialize();
446         return 0;
447 }
448
449 void connectivity_unset_resource(connectivity_resource_s *resource_info)
450 {
451         ret_if(!resource_info);
452         if (resource_info->observers) iotcon_observers_destroy(resource_info->observers);
453         if (resource_info->res) iotcon_resource_destroy(resource_info->res);
454         if (resource_info->path) free(resource_info->path);
455         free(resource_info);
456 }
457
458 int connectivity_set_resource(const char *path, const char *type, connectivity_resource_s **out_resource_info)
459 {
460         iotcon_resource_types_h resource_types = NULL;
461         iotcon_resource_interfaces_h ifaces = NULL;
462         connectivity_resource_s *resource_info = NULL;
463         uint8_t policies;
464         int ret = -1;
465
466         retv_if(!path, -1);
467         retv_if(!type, -1);
468         retv_if(!out_resource_info, -1);
469
470         resource_info = calloc(1, sizeof(connectivity_resource_s));
471         retv_if(!resource_info, -1);
472
473         resource_info->path = strdup(path);
474         goto_if(!resource_info->path, error);
475
476         _D("Path : [%s]", resource_info->path);
477
478         ret = iotcon_resource_types_create(&resource_types);
479         goto_if(IOTCON_ERROR_NONE != ret, error);
480
481         ret = iotcon_resource_types_add(resource_types, type);
482         goto_if(IOTCON_ERROR_NONE != ret, error);
483
484         ret = iotcon_resource_interfaces_create(&ifaces);
485         goto_if(IOTCON_ERROR_NONE != ret, error);
486
487         ret = iotcon_resource_interfaces_add(ifaces, IOTCON_INTERFACE_DEFAULT);
488         goto_if(IOTCON_ERROR_NONE != ret, error);
489
490         ret = iotcon_resource_interfaces_add(ifaces, IOTCON_INTERFACE_BATCH);
491         goto_if(IOTCON_ERROR_NONE != ret, error);
492
493         policies =
494                 IOTCON_RESOURCE_DISCOVERABLE |
495                 IOTCON_RESOURCE_OBSERVABLE |
496                 IOTCON_RESOURCE_SECURE;
497
498         ret = iotcon_resource_create(URI_PATH,
499                         resource_types,
500                         ifaces,
501                         policies,
502                         _request_resource_handler,
503                         resource_info,
504                         &resource_info->res);
505         goto_if(IOTCON_ERROR_NONE != ret, error);
506
507         ret = iotcon_observers_create(&resource_info->observers);
508         goto_if(IOTCON_ERROR_NONE != ret, error);
509
510         iotcon_resource_types_destroy(resource_types);
511         iotcon_resource_interfaces_destroy(ifaces);
512         *out_resource_info = resource_info;
513
514         return 0;
515
516 error:
517         if (ifaces) iotcon_resource_interfaces_destroy(ifaces);
518         if (resource_types) iotcon_resource_types_destroy(resource_types);
519         if (resource_info->res) iotcon_resource_destroy(resource_info->res);
520         if (resource_info->path) free(resource_info->path);
521         if (resource_info) free(resource_info);
522
523         return -1;
524 }