tizen 5.0 migration
[apps/native/blind-motor.git] / src / lux_blind_sensor.c
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <service_app.h>
18 #include "log.h"
19 #include <Ecore.h>
20
21 #include "smartthings.h"
22 #include "smartthings_resource.h"
23 #include "smartthings_payload.h"
24
25 // Duration for a timer
26 #define TIMER_SENSOR_INTERVAL (.250f)
27 Ecore_Timer *sensor_event_timer = NULL;
28 pthread_mutex_t  mutex = PTHREAD_MUTEX_INITIALIZER;
29
30 #define THING_RESOURCE_FILE_NAME        "resource.json"
31
32 #define MUTEX_LOCK              pthread_mutex_lock(&mutex)
33 #define MUTEX_UNLOCK    pthread_mutex_unlock(&mutex)
34
35 smartthings_resource_h st_handle = NULL;
36 static bool is_init = false;
37 static bool is_resource_init = false;
38 static smartthings_h st_h;
39
40 smartthings_status_e st_things_status = -1;
41
42 static int g_lux_value = 0;
43 static bool g_switch_status = false;
44 static bool g_auto_operation_status = false;
45
46 static const char *RES_CAPABILITY_SWITCH_MAIN_0 = "/capability/switch/main/0";
47 static const char* RES_CAPABILITY_DOORCONTROL_MAIN_0 = "/capability/doorControl/main/0";
48 static const char *RES_CAPABILITY_ILLUMINANCEMEASUREMENT_MAIN_0 = "/capability/illuminanceMeasurement/main/0";
49 static const char *PROP_ILLUMINANCE = "illuminance";
50
51 /* get and set request handlers */
52 extern bool handle_get_request_on_resource_capability_switch_main_0(smartthings_payload_h resp_payload, void *user_data);
53 extern bool handle_set_request_on_resource_capability_switch_main_0(smartthings_payload_h payload, smartthings_payload_h resp_payload, void *user_data);
54 extern bool handle_get_request_on_resource_capability_doorcontrol_main_0(smartthings_payload_h resp_payload, void *user_data);
55 extern bool handle_set_request_on_resource_capability_doorcontrol_main_0(smartthings_payload_h payload, smartthings_payload_h resp_payload, void *user_data);
56 extern bool handle_get_request_on_resource_capability_illuminancemeasurement_main_0(smartthings_payload_h resp_payload, void *user_data);
57
58 extern int resource_read_illuminance_sensor(uint16_t *out_value);
59 extern int resource_close_illuminance_sensor(void);
60
61 bool get_switch_status(void)
62 {
63         bool status = false;
64
65         MUTEX_LOCK;
66         status = g_switch_status;
67         MUTEX_UNLOCK;
68
69         return status;
70 }
71
72 void set_switch_status(bool status)
73 {
74         MUTEX_LOCK;
75         g_switch_status = status;
76         MUTEX_UNLOCK;
77
78 }
79 bool get_auto_operation_status(void)
80 {
81         bool status = false;
82
83         MUTEX_LOCK;
84         status = g_auto_operation_status;
85         MUTEX_UNLOCK;
86
87         return status;
88 }
89
90 void set_auto_operation_status(bool status)
91 {
92         MUTEX_LOCK;
93         g_auto_operation_status = status;
94         MUTEX_UNLOCK;
95 }
96
97 uint16_t get_sensor_value(void)
98 {
99         uint16_t value = 0;
100
101         MUTEX_LOCK;
102         value = g_lux_value;
103         MUTEX_UNLOCK;
104
105         return value;
106 }
107
108 static void set_sensor_value(uint16_t value)
109 {
110         MUTEX_LOCK;
111         g_lux_value = value;
112         MUTEX_UNLOCK;
113 }
114
115 static Eina_Bool _get_sensor_interval_event_cb(void *user_data)
116 {
117         uint16_t sensor_value = 0;
118         int ret = 0;
119         bool switch_status = false;
120
121         int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
122         smartthings_payload_h resp_payload = NULL;
123
124         if (st_things_status != SMARTTHINGS_STATUS_REGISTERED_TO_CLOUD)
125                 return ECORE_CALLBACK_RENEW;
126
127         if (!st_handle) {
128                 _E("st_handle is NULL");
129                 return ECORE_CALLBACK_RENEW;
130         }
131
132         ret = resource_read_illuminance_sensor(&sensor_value);
133         if (ret != 0) {
134                 _E("cannot read data from the sensor");
135                 return ECORE_CALLBACK_CANCEL;
136         } else {
137                 // save sensor value to global variable
138                 set_sensor_value(sensor_value);
139
140                 #ifdef _DEBUG_PRINT_
141                 struct timeval __tv;
142                 gettimeofday(&__tv, NULL);
143                 INFO("[%d.%06d] Lux=[%d]Lux", __tv.tv_sec, __tv.tv_usec, sensor_value);
144                 #endif
145
146                 // send notification when switch is on state.
147                 switch_status = get_switch_status();
148                 if (switch_status) {
149                         // send notification to cloud server
150                         error = smartthings_payload_create(&resp_payload);
151                         if (error != SMARTTHINGS_RESOURCE_ERROR_NONE || !resp_payload) {
152                                 _E("smartthings_payload_create() failed, [%d]", error);
153                                 return ECORE_CALLBACK_CANCEL;
154                         }
155
156                         error = smartthings_payload_set_int(resp_payload, PROP_ILLUMINANCE, sensor_value);
157                         if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
158                                 _E("smartthings_payload_set_int() failed, [%d]", error);
159
160                         error = smartthings_resource_notify(st_handle, RES_CAPABILITY_ILLUMINANCEMEASUREMENT_MAIN_0, resp_payload);
161                         if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
162                                 _E("smartthings_resource_notify() failed, [%d]", error);
163
164                         if (smartthings_payload_destroy(resp_payload))
165                                 _E("smartthings_payload_destroy() failed");
166                 }
167         }
168
169         return ECORE_CALLBACK_RENEW;
170 }
171
172 void _send_response_result_cb(smartthings_resource_error_e result, void *user_data)
173 {
174         _D("app_control reply callback for send_response : result=[%d]", result);
175 }
176
177 void _notify_result_cb(smartthings_resource_error_e result, void *user_data)
178 {
179         _D("app_control reply callback for notify : result=[%d]", result);
180 }
181
182 void _request_cb(smartthings_resource_h st_h, int req_id, const char *uri, smartthings_resource_req_type_e req_type,
183                                 smartthings_payload_h payload, void *user_data)
184 {
185         START;
186
187         smartthings_payload_h resp_payload = NULL;
188
189         smartthings_payload_create(&resp_payload);
190         if (!resp_payload) {
191                 _E("Response payload is NULL");
192                 return;
193         }
194
195         bool result = false;
196
197         if (req_type == SMARTTHINGS_RESOURCE_REQUEST_GET) {
198                 if (0 == strncmp(uri, RES_CAPABILITY_SWITCH_MAIN_0, strlen(RES_CAPABILITY_SWITCH_MAIN_0))) {
199                         result = handle_get_request_on_resource_capability_switch_main_0(resp_payload, user_data);
200                 }
201                 if (0 == strncmp(uri, RES_CAPABILITY_DOORCONTROL_MAIN_0, strlen(RES_CAPABILITY_DOORCONTROL_MAIN_0))) {
202                         result = handle_get_request_on_resource_capability_doorcontrol_main_0(resp_payload, user_data);
203                 }
204                 if (0 == strncmp(uri, RES_CAPABILITY_ILLUMINANCEMEASUREMENT_MAIN_0, strlen(RES_CAPABILITY_ILLUMINANCEMEASUREMENT_MAIN_0))) {
205                         result = handle_get_request_on_resource_capability_illuminancemeasurement_main_0(resp_payload, user_data);
206                 }
207         } else if (req_type == SMARTTHINGS_RESOURCE_REQUEST_SET) {
208                 if (0 == strncmp(uri, RES_CAPABILITY_SWITCH_MAIN_0, strlen(RES_CAPABILITY_SWITCH_MAIN_0))) {
209                         result = handle_set_request_on_resource_capability_switch_main_0(payload, resp_payload, user_data);
210                 }
211                 if (0 == strncmp(uri, RES_CAPABILITY_DOORCONTROL_MAIN_0, strlen(RES_CAPABILITY_DOORCONTROL_MAIN_0))) {
212                         result = handle_set_request_on_resource_capability_doorcontrol_main_0(payload, resp_payload, user_data);
213                 }
214         } else {
215                 _E("Invalid request type");
216                 smartthings_payload_destroy(resp_payload);
217                 END;
218                 return;
219         }
220
221         int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
222
223         error = smartthings_resource_send_response(st_h, req_id, uri, resp_payload, result);
224         if (error != SMARTTHINGS_RESOURCE_ERROR_NONE) {
225                         smartthings_payload_destroy(resp_payload);
226                         _E("smartthings_resource_send_response() failed, err=[%d]", error);
227                         END;
228                         return;
229         }
230
231         if (req_type == SMARTTHINGS_RESOURCE_REQUEST_SET) {
232                         error = smartthings_resource_notify(st_h, uri, resp_payload);
233                         if (error != SMARTTHINGS_RESOURCE_ERROR_NONE) {
234                                 _E("smartthings_resource_notify() failed, err=[%d]", error);
235                         }
236         }
237
238         if (smartthings_payload_destroy(resp_payload) != 0) {
239                 _E("smartthings_payload_destroy failed");
240         }
241
242         END;
243         return;
244 }
245
246 static void _resource_connection_status_cb(smartthings_resource_h handle, smartthings_resource_connection_status_e status, void *user_data)
247 {
248         START;
249
250         if (status == SMARTTHINGS_RESOURCE_CONNECTION_STATUS_CONNECTED) {
251                 if (smartthings_resource_set_request_cb(st_handle, _request_cb, NULL) != 0) {
252                         _E("smartthings_resource_set_request_cb() is failed");
253                         return;
254                 }
255         } else {
256                 _I("connection failed, status=[%d]", status);
257         }
258
259         END;
260         return;
261 }
262
263 int init_resource_app()
264 {
265         START;
266
267         if (is_resource_init) {
268                 _I("Already initialized!");
269                 return 0;
270         }
271
272         if (smartthings_resource_initialize(&st_handle, _resource_connection_status_cb, NULL) != 0) {
273                 _E("smartthings_resource_initialize() is failed");
274                 goto _out;
275         }
276
277         is_resource_init = true;
278
279         END;
280         return 0;
281
282 _out :
283         END;
284         return -1;
285 }
286
287 int deinit_resource_app()
288 {
289         START;
290
291         if (!st_handle)
292                 return 0;
293
294         smartthings_resource_unset_request_cb(st_handle);
295
296         if (smartthings_resource_deinitialize(st_handle) != 0)
297                 return -1;
298
299         is_resource_init = false;
300
301         END;
302         return 0;
303 }
304
305
306 void _user_confirm_cb(smartthings_h handle, void *user_data)
307 {
308         START;
309
310         if (smartthings_send_user_confirm(handle, true) != 0)
311                 _E("smartthings_send_user_confirm() is failed");
312
313         END;
314         return;
315 }
316
317 void _reset_confirm_cb(smartthings_h handle, void *user_data)
318 {
319         START;
320
321         if (smartthings_send_reset_confirm(handle, true) != 0)
322                 _E("smartthings_send_reset_confirm() is failed");
323
324         END;
325         return;
326 }
327
328 static void _reset_result_cb(smartthings_h handle, bool result, void *user_data)
329 {
330         START;
331
332         _I("reset result = [%d]", result);
333
334         END;
335         return;
336 }
337
338 static void _thing_status_cb(smartthings_h handle, smartthings_status_e status, void *user_data)
339 {
340         START;
341
342         _D("Received status changed cb : status = [%d]", status);
343         st_things_status = status;
344
345         switch (status) {
346         case SMARTTHINGS_STATUS_NOT_READY:
347                         _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_NOT_READY");
348                         break;
349         case SMARTTHINGS_STATUS_INIT:
350                         _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_INIT");
351                         break;
352         case SMARTTHINGS_STATUS_ES_STARTED:
353                         _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_ES_STARTED");
354                         break;
355         case SMARTTHINGS_STATUS_ES_DONE:
356                         _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_ES_DONE");
357                         break;
358         case SMARTTHINGS_STATUS_ES_FAILED_ON_OWNERSHIP_TRANSFER:
359                         _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_ES_FAILED_ON_OWNERSHIP_TRANSFER");
360                         break;
361         case SMARTTHINGS_STATUS_CONNECTING_TO_AP:
362                         _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_CONNECTING_TO_AP");
363                         break;
364         case SMARTTHINGS_STATUS_CONNECTED_TO_AP:
365                         _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_CONNECTED_TO_AP");
366                         break;
367         case SMARTTHINGS_STATUS_CONNECTING_TO_AP_FAILED:
368                         _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_CONNECTING_TO_AP_FAILED");
369                         break;
370         case SMARTTHINGS_STATUS_REGISTERING_TO_CLOUD:
371                         _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_REGISTERING_TO_CLOUD");
372                         break;
373         case SMARTTHINGS_STATUS_REGISTERED_TO_CLOUD:
374                         _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_REGISTERED_TO_CLOUD");
375                         break;
376         case SMARTTHINGS_STATUS_REGISTERING_FAILED_ON_SIGN_IN:
377                         _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_REGISTERING_FAILED_ON_SIGN_IN");
378                         break;
379         case SMARTTHINGS_STATUS_REGISTERING_FAILED_ON_PUB_RES:
380                         _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_REGISTERING_FAILED_ON_PUB_RES");
381                         break;
382         default:
383                         _E("status: [%d][%s]", status, "Unknown Status");
384                         break;
385         }
386         END;
387         return;
388 }
389
390 static void _things_connection_status_cb(smartthings_h handle, smartthings_connection_status_e status, void *user_data)
391 {
392         START;
393
394         _D("Received connection status changed cb : status = [%d]", status);
395
396         if (status == SMARTTHINGS_CONNECTION_STATUS_CONNECTED) {
397                 const char* dev_name = "IoT Test Device";
398                 int wifi_mode = SMARTTHINGS_WIFI_MODE_11B | SMARTTHINGS_WIFI_MODE_11G | SMARTTHINGS_WIFI_MODE_11N;
399                 int wifi_freq = SMARTTHINGS_WIFI_FREQ_24G | SMARTTHINGS_WIFI_FREQ_5G;
400
401                 if (smartthings_set_device_property(handle, dev_name, wifi_mode, wifi_freq) != 0) {
402                         _E("smartthings_initialize() is failed");
403                         return;
404                 }
405
406                 if (smartthings_set_certificate_file(handle, "certificate.pem", "privatekey.der") != 0) {
407                         _E("smartthings_set_certificate_file() is failed");
408                         return;
409                 }
410
411                 if (smartthings_set_user_confirm_cb(st_h, _user_confirm_cb, NULL) != 0) {
412                         _E("smartthings_set_user_confirm_cb() is failed");
413                         return;
414                 }
415
416                 if (smartthings_set_reset_confirm_cb(handle, _reset_confirm_cb, NULL) != 0) {
417                         _E("smartthings_set_reset_confirm_cb() is failed");
418                         return;
419                 }
420
421                 if (smartthings_set_reset_result_cb(handle, _reset_result_cb, NULL) != 0) {
422                         _E("smartthings_set_reset_confirm_cb() is failed");
423                         return;
424                 }
425
426                 if (smartthings_set_status_changed_cb(handle, _thing_status_cb, NULL) != 0) {
427                         _E("smartthings_set_status_changed_callback() is failed");
428                         return;
429                 }
430
431                 if (smartthings_start(handle) != 0) {
432                         _E("smartthings_start() is failed");
433                         return;
434                 }
435
436                 bool is_es_completed = false;
437                 if (smartthings_get_easysetup_status(handle, &is_es_completed) != 0) {
438                         _E("smartthings_get_easysetup_status() is failed");
439                         return;
440                 }
441
442                 if (is_es_completed == true) {
443                         _I("Easysetup is already done");
444                         return;
445                 }
446
447                 if (smartthings_start_easysetup(handle) != 0) {
448                         _E("smartthings_start_easysetup() is failed");
449                         return;
450                 }
451         } else {
452                         _E("connection failed, status=[%d]", status);
453         }
454
455         END;
456         return;
457 }
458
459 int init_master_app()
460 {
461         START;
462
463         if (is_init) {
464                 _I("Already initialized!");
465                 END;
466                 return 0;
467         }
468
469         if (smartthings_initialize(&st_h, _things_connection_status_cb, NULL) != 0) {
470                 _E("smartthings_initialize() is failed");
471                 goto _out;
472         }
473
474         is_init = true;
475
476         END;
477         return 0;
478
479 _out :
480         END;
481         return -1;
482 }
483
484 int deinit_master_app()
485 {
486         START;
487
488         is_init = false;
489
490         if (!st_h) {
491                 _I("handle is already NULL");
492                 END;
493                 return 0;
494         }
495
496         smartthings_unset_user_confirm_cb(st_h);
497         smartthings_unset_reset_confirm_cb(st_h);
498         smartthings_unset_reset_result_cb(st_h);
499         smartthings_unset_status_changed_cb(st_h);
500
501         if (smartthings_deinitialize(st_h) != 0)  {
502                 _E("smartthings_deinitialize() is failed");
503                 END;
504                 return -1;
505         }
506
507         END;
508         return 0;
509 }
510
511 static bool service_app_create(void *user_data)
512 {
513         // initialize mutex
514         pthread_mutex_init(&mutex, NULL);
515
516         if (sensor_event_timer)
517                 ecore_timer_del(sensor_event_timer);
518
519         sensor_event_timer = ecore_timer_add(TIMER_SENSOR_INTERVAL, _get_sensor_interval_event_cb, NULL);
520         if (!sensor_event_timer)
521                 _E("Failed to add a timer");
522
523         return true;
524 }
525
526 static void service_app_terminate(void *user_data)
527 {
528         // clear timer resource
529         if (sensor_event_timer) {
530                 ecore_timer_del(sensor_event_timer);
531                 sensor_event_timer = NULL;
532         }
533
534         // close sensor resource
535         resource_close_illuminance_sensor();
536
537         pthread_mutex_destroy(&mutex);
538
539         /*terminate resource*/
540         if (deinit_resource_app() != 0) {
541                 _E("deinit_resource_app failed");
542         }
543
544         /*terminate master*/
545         if (deinit_master_app() != 0) {
546                 _E("deinit_master_app failed");
547         }
548
549         return;
550 }
551
552 static void service_app_control(app_control_h app_control, void *user_data)
553 {
554         if (app_control == NULL) {
555                 _E("app_control is NULL");
556                 return;
557         }
558
559         init_master_app();
560         init_resource_app();
561
562         return;
563 }
564
565 int main(int argc, char *argv[])
566 {
567         service_app_lifecycle_callback_s event_callback;
568
569         event_callback.create = service_app_create;
570         event_callback.terminate = service_app_terminate;
571         event_callback.app_control = service_app_control;
572
573         return service_app_main(argc, argv, &event_callback, NULL);
574 }