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.
18 #include <service_app.h>
25 #include "resource/resource_infrared_motion_sensor.h"
26 #include "resource/resource_led.h"
29 #define TIMER_GATHER_INTERVAL (5.0f)
31 // Motion sensor information
32 #define SENSOR_MOTION_GPIO_NUMBER (46)
34 // LED sensor information
35 #define SENSOR_LED_GPIO_NUMBER (130)
36 #define SENSOR_LED_ON "on"
37 #define SENSOR_LED_OFF "off"
39 // For using SmartThings SDK
42 #include "smartthings.h"
43 #include "smartthings_resource.h"
44 #include "smartthings_payload.h"
46 // Certification file and private key file stored in the resource directory
47 #define CERT_FILE "certificate.pem"
48 #define PRIV_FILE "privatekey.der"
50 // URI and key information
51 #define SENSOR_MOTION_URI "/capability/motionSensor/main/0"
52 #define SENSOR_MOTION_KEY "value"
53 #define SENSOR_LED_URI "/capability/switch/main/0"
54 #define SENSOR_LED_KEY "power"
55 #endif /* USE_ST_SDK */
57 typedef struct app_data_s {
58 Ecore_Timer *getter_timer;
62 smartthings_h st_master_h;
63 smartthings_resource_h st_res_h;
64 smartthings_status_e status;
65 #endif /* USE_ST_SDK */
68 static app_data *g_ad = NULL;
71 static const char * _resource_error_to_str(smartthings_resource_error_e error)
73 const char *err_str = NULL;
76 case SMARTTHINGS_RESOURCE_ERROR_NONE:
77 err_str = "SMARTTHINGS_RESOURCE_ERROR_NONE";
79 case SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER:
80 err_str = "SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER";
82 case SMARTTHINGS_RESOURCE_ERROR_OUT_OF_MEMORY:
83 err_str = "SMARTTHINGS_RESOURCE_ERROR_OUT_OF_MEMORY";
85 case SMARTTHINGS_RESOURCE_ERROR_PERMISSION_DENIED:
86 err_str = "SMARTTHINGS_RESOURCE_ERROR_PERMISSION_DENIED";
88 case SMARTTHINGS_RESOURCE_ERROR_NO_DATA:
89 err_str = "SMARTTHINGS_RESOURCE_ERROR_NO_DATA";
91 case SMARTTHINGS_RESOURCE_ERROR_NOT_SUPPORTED:
92 err_str = "SMARTTHINGS_RESOURCE_ERROR_NOT_SUPPORTED";
94 case SMARTTHINGS_RESOURCE_ERROR_OPERATION_FAILED:
95 err_str = "SMARTTHINGS_RESOURCE_ERROR_NOT_SUPPORTED";
97 case SMARTTHINGS_RESOURCE_ERROR_SERVICE_UNAVAILABLE:
98 err_str = "SMARTTHINGS_RESOURCE_ERROR_SERVICE_UNAVAILABLE";
101 err_str = "Unknown error";
109 static Eina_Bool _get_motion_sensor_data(void *user_data)
113 app_data *ad = user_data;
116 _E("failed to get app_data");
117 return ECORE_CALLBACK_CANCEL;
120 ret = resource_read_infrared_motion_sensor(SENSOR_MOTION_GPIO_NUMBER, &value);
122 _E("cannot read data from the infrared motion sensor");
123 return ECORE_CALLBACK_CANCEL;
125 ad->motion_data = value;
127 _D("Detected motion value is: %u", value);
130 int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
131 smartthings_payload_h resp_payload = NULL;
133 if (ad->status != SMARTTHINGS_STATUS_REGISTERED_TO_CLOUD)
134 return ECORE_CALLBACK_RENEW;
136 error = smartthings_payload_create(&resp_payload);
137 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE || !resp_payload) {
138 _E("smartthings_payload_create() failed, [%s]",
139 _resource_error_to_str(error));
140 return ECORE_CALLBACK_CANCEL;
143 error = smartthings_payload_set_bool(resp_payload, SENSOR_MOTION_KEY, (bool)ad->motion_data);
144 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
145 _E("smartthings_payload_set_bool() failed, [%s]",
146 _resource_error_to_str(error));
148 error = smartthings_resource_notify(ad->st_res_h, SENSOR_MOTION_URI, resp_payload);
149 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
150 _E("smartthings_resource_notify() failed, [%s]",
151 _resource_error_to_str(error));
153 if (smartthings_payload_destroy(resp_payload))
154 _E("smartthings_payload_destroy() failed");
157 return ECORE_CALLBACK_RENEW;
160 static int _set_led_data(app_data *ad, int state) {
163 ad->led_data = state;
164 ret = resource_write_led(SENSOR_LED_GPIO_NUMBER, state);
166 _E("cannot write led data");
169 _I("LED : %d",state);
175 /* SmartThings resource functions */
176 static bool _handle_get_motion(smartthings_payload_h resp_payload, void *user_data)
178 int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
179 app_data *ad = user_data;
183 _D("Received a GET request for MOTION");
185 error = smartthings_payload_set_bool(resp_payload, SENSOR_MOTION_KEY, (bool)ad->motion_data);
186 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
187 _E("smartthings_payload_set_bool() failed, [%s]",
188 _resource_error_to_str(error));
193 static bool _handle_get_led(smartthings_payload_h resp_payload, void *user_data)
195 app_data *ad = user_data;
196 int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
201 _D("Received a GET request for LED");
206 str = SENSOR_LED_OFF;
208 error = smartthings_payload_set_string(resp_payload, SENSOR_LED_KEY, str);
209 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
210 _E("smartthings_payload_set_string() failed, [%s]",
211 _resource_error_to_str(error));
213 _D("Power : %s", str);
218 static bool _handle_set_led(smartthings_payload_h payload, smartthings_payload_h resp_payload, void *user_data)
220 app_data *ad = user_data;
222 char *res_str = NULL;
224 int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
228 _D("Received a SET request");
230 error = smartthings_payload_get_string(payload, SENSOR_LED_KEY, &str);
231 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
232 _E("smartthings_payload_get_string() failed, [%s]",
233 _resource_error_to_str(error));
235 if (strncmp(str, SENSOR_LED_ON, strlen(SENSOR_LED_ON))) {
236 ret = _set_led_data(ad, 0);
237 res_str = SENSOR_LED_OFF;
239 ret = _set_led_data(ad, 1);
240 res_str = SENSOR_LED_ON;
245 _E("cannot set LED");
249 error = smartthings_payload_set_string(resp_payload, SENSOR_LED_KEY, res_str);
250 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
251 _E("smartthings_payload_set_string() failed, [%s]",
252 _resource_error_to_str(error));
257 static void _request_cb(smartthings_resource_h handle, int req_id,
258 const char *uri, smartthings_resource_req_type_e req_type,
259 smartthings_payload_h payload, void *user_data)
261 smartthings_payload_h resp_payload = NULL;
263 int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
265 _D("request on %s, type[%d], id[%d]", uri, req_type, req_id);
267 error = smartthings_payload_create(&resp_payload);
268 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE || ! resp_payload)
269 _E("smartthings_payload_create() failed, [%s]",
270 _resource_error_to_str(error));
272 if (req_type == SMARTTHINGS_RESOURCE_REQUEST_GET) {
273 if (!strncmp(uri, SENSOR_MOTION_URI, strlen(SENSOR_MOTION_URI)))
274 result = _handle_get_motion(resp_payload, user_data);
275 else if (!strncmp(uri, SENSOR_LED_URI, strlen(SENSOR_LED_URI)))
276 result = _handle_get_led(resp_payload, user_data);
278 _E("No matching Resource uri to get");
279 } else if (req_type == SMARTTHINGS_RESOURCE_REQUEST_SET) {
280 if (!strncmp(uri, SENSOR_LED_URI, strlen(SENSOR_LED_URI)))
281 result = _handle_set_led(payload, resp_payload, user_data);
283 _E("No matching Resource uri to get");
285 _E("Invalid request type - %d", req_type);
286 smartthings_payload_destroy(resp_payload);
290 error = smartthings_resource_send_response(handle, req_id, uri, resp_payload, result);
291 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE) {
292 _E("smartthings_resource_send_response() failed, [%s]",
293 _resource_error_to_str(error));
294 smartthings_payload_destroy(resp_payload);
298 if (req_type == SMARTTHINGS_RESOURCE_REQUEST_SET) {
299 error = smartthings_resource_notify(handle, uri, resp_payload);
300 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
301 _E("smartthings_resource_notify() failed, [%s]",
302 _resource_error_to_str(error));
305 if (smartthings_payload_destroy(resp_payload))
306 _E("smartthings_payload_destroy() failed");
311 static void _resource_connection_status_cb(
312 smartthings_resource_h handle,
313 smartthings_resource_connection_status_e status, void *user_data)
315 app_data *ad = user_data;
317 _D("status=[%d]", status);
321 if (status == SMARTTHINGS_RESOURCE_CONNECTION_STATUS_CONNECTED) {
322 int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
323 error = smartthings_resource_set_request_cb(handle, _request_cb, ad);
324 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE) {
325 _E("smartthings_resource_set_request_cb() is failed");
329 _E("connection failed");
333 static int _init_resource(app_data *ad)
335 smartthings_resource_h st_res_h = NULL;
340 _I("Already initialized!");
344 error = smartthings_resource_initialize(&st_res_h,
345 _resource_connection_status_cb, ad);
347 _E("smartthings_resource_initialize() is failed, [%s]",
348 _resource_error_to_str(error));
352 ad->st_res_h = st_res_h;
357 static int _fini_resource(app_data *ad)
364 smartthings_resource_unset_request_cb(ad->st_res_h);
365 smartthings_resource_deinitialize(ad->st_res_h);
372 /* SmartThings master functions */
373 static const char *__master_error_to_str(smartthings_error_e error)
375 const char *err_str = NULL;
378 case SMARTTHINGS_ERROR_NONE:
379 err_str = "SMARTTHINGS_ERROR_NONE";
381 case SMARTTHINGS_ERROR_INVALID_PARAMETER:
382 err_str = "SMARTTHINGS_ERROR_INVALID_PARAMETER";
384 case SMARTTHINGS_ERROR_OUT_OF_MEMORY:
385 err_str = "SMARTTHINGS_ERROR_OUT_OF_MEMORY";
387 case SMARTTHINGS_ERROR_PERMISSION_DENIED:
388 err_str = "SMARTTHINGS_ERROR_PERMISSION_DENIED";
390 case SMARTTHINGS_ERROR_NO_DATA:
391 err_str = "SMARTTHINGS_ERROR_NO_DATA";
393 case SMARTTHINGS_ERROR_NOT_SUPPORTED:
394 err_str = "SMARTTHINGS_ERROR_NOT_SUPPORTED";
396 case SMARTTHINGS_ERROR_OPERATION_FAILED:
397 err_str = "SMARTTHINGS_ERROR_OPERATION_FAILED";
399 case SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE:
400 err_str = "SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE";
403 err_str = "Unknown error";
410 static void _user_confirm_cb(smartthings_h handle, void *user_data)
412 if (smartthings_send_user_confirm(handle, true) != 0)
413 _E("smartthings_send_user_confirm() is failed");
416 static void _reset_confirm_cb(smartthings_h handle, void *user_data)
418 if (smartthings_send_reset_confirm(handle, true) != 0)
419 _E("smartthings_send_reset_confirm() is failed");
422 static void _reset_result_cb(smartthings_h handle, bool result, void *user_data)
424 _I("reset result = [%d]", result);
427 static void _thing_status_cb(
428 smartthings_h handle, smartthings_status_e status, void *user_data)
430 app_data *ad = user_data;
431 _D("status: [%d]", status);
435 static void _things_connection_status_cb(
436 smartthings_h handle, smartthings_connection_status_e status,
439 _D("status = [%d]", status);
441 if (status == SMARTTHINGS_CONNECTION_STATUS_CONNECTED) {
443 bool is_es_completed = false;
444 const char* dev_name = "motion-light-app";
445 int wifi_mode = SMARTTHINGS_WIFI_MODE_11B
446 | SMARTTHINGS_WIFI_MODE_11G
447 | SMARTTHINGS_WIFI_MODE_11N;
449 int wifi_freq = SMARTTHINGS_WIFI_FREQ_24G | SMARTTHINGS_WIFI_FREQ_5G;
451 err = smartthings_set_device_property(
452 handle, dev_name, wifi_mode, wifi_freq);
454 _E("smartthings_set_device_property() is failed, [%s]",
455 __master_error_to_str(err));
459 err = smartthings_set_certificate_file(handle, CERT_FILE, PRIV_FILE);
461 _E("smartthings_set_certificate_file() is failed, [%s]",
462 __master_error_to_str(err));
466 err = smartthings_set_user_confirm_cb(handle, _user_confirm_cb, NULL);
468 _E("smartthings_set_user_confirm_cb() is failed, [%s]",
469 __master_error_to_str(err));
473 err = smartthings_set_reset_confirm_cb(handle, _reset_confirm_cb, NULL);
475 _E("smartthings_set_reset_confirm_cb() is failed, [%s]",
476 __master_error_to_str(err));
480 err = smartthings_set_reset_result_cb(handle, _reset_result_cb, NULL);
482 _E("smartthings_set_reset_result_cb() is failed, [%s]",
483 __master_error_to_str(err));
487 err = smartthings_set_status_changed_cb(handle, _thing_status_cb, user_data);
489 _E("smartthings_set_status_changed_callback() is failed, [%s]",
490 __master_error_to_str(err));
494 err = smartthings_start(handle);
496 _E("smartthings_start() is failed, [%s]",
497 __master_error_to_str(err));
501 err = smartthings_get_easysetup_status(handle, &is_es_completed);
503 _E("smartthings_get_easysetup_status() is failed, [%s]",
504 __master_error_to_str(err));
508 if (is_es_completed == true) {
509 _I("Easysetup is already done");
513 _I("Easysetup is starting now");
514 err = smartthings_start_easysetup(handle);
516 _E("smartthings_start_easysetup() is failed, [%s]",
517 __master_error_to_str(err));
518 smartthings_stop(handle);
522 _E("connection failed");
526 static int _init_master(app_data *ad)
529 smartthings_h st_handle = NULL;
533 if (ad->st_master_h) {
534 _I("Already initialized!");
538 err = smartthings_initialize(&st_handle, _things_connection_status_cb, ad);
540 _E("smartthings_initialize() is failed, [%s]",
541 __master_error_to_str(err));
545 ad->st_master_h = st_handle;
550 int _fini_master(app_data *ad)
554 if (!ad->st_master_h) {
555 _I("handle is already NULL");
559 smartthings_unset_user_confirm_cb(ad->st_master_h);
560 smartthings_unset_reset_confirm_cb(ad->st_master_h);
561 smartthings_unset_reset_result_cb(ad->st_master_h);
562 smartthings_unset_status_changed_cb(ad->st_master_h);
564 smartthings_stop_easysetup(ad->st_master_h);
565 smartthings_stop(ad->st_master_h);
567 if (smartthings_deinitialize(ad->st_master_h) != 0) {
568 _E("smartthings_deinitialize() is failed");
571 ad->st_master_h = NULL;
575 #endif /* USE_ST_SDK */
577 static void _stop_gathering(void *data)
582 if (ad->getter_timer) {
583 ecore_timer_del(ad->getter_timer);
584 ad->getter_timer = NULL;
588 static void _start_gathering(void *data)
593 if (ad->getter_timer)
594 ecore_timer_del(ad->getter_timer);
596 ad->getter_timer = ecore_timer_add(TIMER_GATHER_INTERVAL, _get_motion_sensor_data, ad);
597 if (!ad->getter_timer)
598 _E("Failed to add a timer");
601 static bool service_app_create(void *user_data)
604 app_data *ad = user_data;
606 if (_init_master(ad))
609 if (_init_resource(ad)) {
618 static void service_app_control(app_control_h app_control, void *user_data)
620 _stop_gathering(user_data);
621 _start_gathering(user_data);
624 static void service_app_terminate(void *user_data)
626 app_data *ad = user_data;
633 // Turn off LED light with __set_led()
634 _set_led_data(ad, 0);
636 // Close Motion and LED resources
637 resource_close_infrared_motion_sensor();
638 resource_close_led();
646 int main(int argc, char *argv[])
649 service_app_lifecycle_callback_s event_callback;
651 ad = calloc(1, sizeof(app_data));
656 event_callback.create = service_app_create;
657 event_callback.terminate = service_app_terminate;
658 event_callback.app_control = service_app_control;
660 return service_app_main(argc, argv, &event_callback, ad);