2 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <service_app.h>
21 #include "smartthings.h"
22 #include "smartthings_resource.h"
23 #include "smartthings_payload.h"
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;
30 #define THING_RESOURCE_FILE_NAME "resource.json"
32 #define MUTEX_LOCK pthread_mutex_lock(&mutex)
33 #define MUTEX_UNLOCK pthread_mutex_unlock(&mutex)
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;
40 smartthings_status_e st_things_status = -1;
42 static int g_lux_value = 0;
43 static bool g_switch_status = false;
44 static bool g_auto_operation_status = false;
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";
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);
58 extern int resource_read_illuminance_sensor(uint16_t *out_value);
59 extern int resource_close_illuminance_sensor(void);
61 bool get_switch_status(void)
66 status = g_switch_status;
72 void set_switch_status(bool status)
75 g_switch_status = status;
79 bool get_auto_operation_status(void)
84 status = g_auto_operation_status;
90 void set_auto_operation_status(bool status)
93 g_auto_operation_status = status;
97 uint16_t get_sensor_value(void)
108 static void set_sensor_value(uint16_t value)
115 static Eina_Bool _get_sensor_interval_event_cb(void *user_data)
117 uint16_t sensor_value = 0;
119 bool switch_status = false;
121 int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
122 smartthings_payload_h resp_payload = NULL;
124 if (st_things_status != SMARTTHINGS_STATUS_REGISTERED_TO_CLOUD)
125 return ECORE_CALLBACK_RENEW;
128 _E("st_handle is NULL");
129 return ECORE_CALLBACK_RENEW;
132 ret = resource_read_illuminance_sensor(&sensor_value);
134 _E("cannot read data from the sensor");
135 return ECORE_CALLBACK_CANCEL;
137 // save sensor value to global variable
138 set_sensor_value(sensor_value);
142 gettimeofday(&__tv, NULL);
143 INFO("[%d.%06d] Lux=[%d]Lux", __tv.tv_sec, __tv.tv_usec, sensor_value);
146 // send notification when switch is on state.
147 switch_status = get_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;
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);
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);
164 if (smartthings_payload_destroy(resp_payload))
165 _E("smartthings_payload_destroy() failed");
169 return ECORE_CALLBACK_RENEW;
172 void _send_response_result_cb(smartthings_resource_error_e result, void *user_data)
174 _D("app_control reply callback for send_response : result=[%d]", result);
177 void _notify_result_cb(smartthings_resource_error_e result, void *user_data)
179 _D("app_control reply callback for notify : result=[%d]", result);
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)
187 smartthings_payload_h resp_payload = NULL;
189 smartthings_payload_create(&resp_payload);
191 _E("Response payload is NULL");
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);
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);
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);
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);
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);
215 _E("Invalid request type");
216 smartthings_payload_destroy(resp_payload);
221 int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
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);
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);
238 if (smartthings_payload_destroy(resp_payload) != 0) {
239 _E("smartthings_payload_destroy failed");
246 static void _resource_connection_status_cb(smartthings_resource_h handle, smartthings_resource_connection_status_e status, void *user_data)
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");
256 _I("connection failed, status=[%d]", status);
263 int init_resource_app()
267 if (is_resource_init) {
268 _I("Already initialized!");
272 if (smartthings_resource_initialize(&st_handle, _resource_connection_status_cb, NULL) != 0) {
273 _E("smartthings_resource_initialize() is failed");
277 is_resource_init = true;
287 int deinit_resource_app()
294 smartthings_resource_unset_request_cb(st_handle);
296 if (smartthings_resource_deinitialize(st_handle) != 0)
299 is_resource_init = false;
306 void _user_confirm_cb(smartthings_h handle, void *user_data)
310 if (smartthings_send_user_confirm(handle, true) != 0)
311 _E("smartthings_send_user_confirm() is failed");
317 void _reset_confirm_cb(smartthings_h handle, void *user_data)
321 if (smartthings_send_reset_confirm(handle, true) != 0)
322 _E("smartthings_send_reset_confirm() is failed");
328 static void _reset_result_cb(smartthings_h handle, bool result, void *user_data)
332 _I("reset result = [%d]", result);
338 static void _thing_status_cb(smartthings_h handle, smartthings_status_e status, void *user_data)
342 _D("Received status changed cb : status = [%d]", status);
343 st_things_status = status;
346 case SMARTTHINGS_STATUS_NOT_READY:
347 _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_NOT_READY");
349 case SMARTTHINGS_STATUS_INIT:
350 _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_INIT");
352 case SMARTTHINGS_STATUS_ES_STARTED:
353 _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_ES_STARTED");
355 case SMARTTHINGS_STATUS_ES_DONE:
356 _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_ES_DONE");
358 case SMARTTHINGS_STATUS_ES_FAILED_ON_OWNERSHIP_TRANSFER:
359 _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_ES_FAILED_ON_OWNERSHIP_TRANSFER");
361 case SMARTTHINGS_STATUS_CONNECTING_TO_AP:
362 _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_CONNECTING_TO_AP");
364 case SMARTTHINGS_STATUS_CONNECTED_TO_AP:
365 _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_CONNECTED_TO_AP");
367 case SMARTTHINGS_STATUS_CONNECTING_TO_AP_FAILED:
368 _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_CONNECTING_TO_AP_FAILED");
370 case SMARTTHINGS_STATUS_REGISTERING_TO_CLOUD:
371 _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_REGISTERING_TO_CLOUD");
373 case SMARTTHINGS_STATUS_REGISTERED_TO_CLOUD:
374 _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_REGISTERED_TO_CLOUD");
376 case SMARTTHINGS_STATUS_REGISTERING_FAILED_ON_SIGN_IN:
377 _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_REGISTERING_FAILED_ON_SIGN_IN");
379 case SMARTTHINGS_STATUS_REGISTERING_FAILED_ON_PUB_RES:
380 _I("status: [%d] [%s]", status, "SMARTTHINGS_STATUS_REGISTERING_FAILED_ON_PUB_RES");
383 _E("status: [%d][%s]", status, "Unknown Status");
390 static void _things_connection_status_cb(smartthings_h handle, smartthings_connection_status_e status, void *user_data)
394 _D("Received connection status changed cb : status = [%d]", status);
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;
401 if (smartthings_set_device_property(handle, dev_name, wifi_mode, wifi_freq) != 0) {
402 _E("smartthings_initialize() is failed");
406 if (smartthings_set_certificate_file(handle, "certificate.pem", "privatekey.der") != 0) {
407 _E("smartthings_set_certificate_file() is failed");
411 if (smartthings_set_user_confirm_cb(st_h, _user_confirm_cb, NULL) != 0) {
412 _E("smartthings_set_user_confirm_cb() is failed");
416 if (smartthings_set_reset_confirm_cb(handle, _reset_confirm_cb, NULL) != 0) {
417 _E("smartthings_set_reset_confirm_cb() is failed");
421 if (smartthings_set_reset_result_cb(handle, _reset_result_cb, NULL) != 0) {
422 _E("smartthings_set_reset_confirm_cb() is failed");
426 if (smartthings_set_status_changed_cb(handle, _thing_status_cb, NULL) != 0) {
427 _E("smartthings_set_status_changed_callback() is failed");
431 if (smartthings_start(handle) != 0) {
432 _E("smartthings_start() is failed");
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");
442 if (is_es_completed == true) {
443 _I("Easysetup is already done");
447 if (smartthings_start_easysetup(handle) != 0) {
448 _E("smartthings_start_easysetup() is failed");
452 _E("connection failed, status=[%d]", status);
459 int init_master_app()
464 _I("Already initialized!");
469 if (smartthings_initialize(&st_h, _things_connection_status_cb, NULL) != 0) {
470 _E("smartthings_initialize() is failed");
484 int deinit_master_app()
491 _I("handle is already NULL");
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);
501 if (smartthings_deinitialize(st_h) != 0) {
502 _E("smartthings_deinitialize() is failed");
511 static bool service_app_create(void *user_data)
514 pthread_mutex_init(&mutex, NULL);
516 if (sensor_event_timer)
517 ecore_timer_del(sensor_event_timer);
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");
526 static void service_app_terminate(void *user_data)
528 // clear timer resource
529 if (sensor_event_timer) {
530 ecore_timer_del(sensor_event_timer);
531 sensor_event_timer = NULL;
534 // close sensor resource
535 resource_close_illuminance_sensor();
537 pthread_mutex_destroy(&mutex);
539 /*terminate resource*/
540 if (deinit_resource_app() != 0) {
541 _E("deinit_resource_app failed");
545 if (deinit_master_app() != 0) {
546 _E("deinit_master_app failed");
552 static void service_app_control(app_control_h app_control, void *user_data)
554 if (app_control == NULL) {
555 _E("app_control is NULL");
565 int main(int argc, char *argv[])
567 service_app_lifecycle_callback_s event_callback;
569 event_callback.create = service_app_create;
570 event_callback.terminate = service_app_terminate;
571 event_callback.app_control = service_app_control;
573 return service_app_main(argc, argv, &event_callback, NULL);