1 /* ****************************************************************
3 * Copyright 2017 Samsung Electronics All Rights Reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 ******************************************************************/
20 #include <service_app.h>
26 #include "sensor-data.h"
27 #include "co2-sensor.h"
29 #define SENSOR_CH_CO2 (0)
30 #define SENSOR_GATHER_INTERVAL (50) //50ms
31 #define SENSOR_GATHER_COUNT (60)
37 #include "smartthings.h"
38 #include "smartthings_resource.h"
39 #include "smartthings_payload.h"
41 /* You have to FIX IT !!! */
42 #define CERT_FILE "certificate.pem" // cert file name in 'res' directory
43 #define PRIV_FILE "privatekey.der" // private key file name in 'res' directory
46 #define SENSOR_URI_CO2 "/capability/airQualitySensor/main/0"
47 #define SENSOR_KEY_CO2 "airQuality"
49 #endif /* USE_ST_SDK */
51 typedef struct app_data_s {
53 sensor_data *co2_data;
55 smartthings_h st_master_h;
56 smartthings_resource_h st_res_h;
57 smartthings_resource_connection_status_e st_res_conn_status;
58 #endif /* USE_ST_SDK */
61 static app_data *g_ad = NULL;
65 /* smartthings resource functions */
67 __resource_error_to_str(smartthings_resource_error_e error)
69 const char *err_str = NULL;
72 case SMARTTHINGS_RESOURCE_ERROR_NONE:
73 err_str = "SMARTTHINGS_RESOURCE_ERROR_NONE";
75 case SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER:
76 err_str = "SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER";
78 case SMARTTHINGS_RESOURCE_ERROR_OUT_OF_MEMORY:
79 err_str = "SMARTTHINGS_RESOURCE_ERROR_OUT_OF_MEMORY";
81 case SMARTTHINGS_RESOURCE_ERROR_PERMISSION_DENIED:
82 err_str = "SMARTTHINGS_RESOURCE_ERROR_PERMISSION_DENIED";
84 case SMARTTHINGS_RESOURCE_ERROR_NO_DATA:
85 err_str = "SMARTTHINGS_RESOURCE_ERROR_NO_DATA";
87 case SMARTTHINGS_RESOURCE_ERROR_NOT_SUPPORTED:
88 err_str = "SMARTTHINGS_RESOURCE_ERROR_NOT_SUPPORTED";
90 case SMARTTHINGS_RESOURCE_ERROR_OPERATION_FAILED:
91 err_str = "SMARTTHINGS_RESOURCE_ERROR_NOT_SUPPORTED";
93 case SMARTTHINGS_RESOURCE_ERROR_SERVICE_UNAVAILABLE:
94 err_str = "SMARTTHINGS_RESOURCE_ERROR_SERVICE_UNAVAILABLE";
97 err_str = "Unknown error";
105 handle_get_co2(smartthings_payload_h resp_payload, void *user_data)
107 app_data *ad = user_data;
108 unsigned int value = 0;
112 sensor_data_get_uint(ad->co2_data, &value);
113 smartthings_payload_set_int(resp_payload, SENSOR_KEY_CO2, (int)value);
119 _request_cb(smartthings_resource_h handle, int req_id,
120 const char *uri, smartthings_resource_req_type_e req_type,
121 smartthings_payload_h payload, void *user_data)
123 smartthings_payload_h resp_payload = NULL;
125 int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
127 _D("request on %s, type[%d], id[%d]", uri, req_type, req_id);
129 smartthings_payload_create(&resp_payload);
131 _E("Response payload is NULL");
135 if (req_type == SMARTTHINGS_RESOURCE_REQUEST_GET) {
136 if (0 == g_strcmp0(uri, SENSOR_URI_CO2))
137 result = handle_get_co2(resp_payload, user_data);
139 _E("No matching Resource uri to get");
140 } else if (req_type == SMARTTHINGS_RESOURCE_REQUEST_SET) {
141 _E("No matching Resource uri to set");
143 _E("Invalid request type - %d", req_type);
144 smartthings_payload_destroy(resp_payload);
148 error = smartthings_resource_send_response(handle, req_id, uri, resp_payload, result);
149 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE) {
150 smartthings_payload_destroy(resp_payload);
151 _E("smartthings_resource_send_response() failed, [%s]",
152 __resource_error_to_str(error));
156 if (req_type == SMARTTHINGS_RESOURCE_REQUEST_SET) {
157 error = smartthings_resource_notify(handle, uri, resp_payload);
158 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
159 _E("smartthings_resource_notify() failed, [%s]",
160 __resource_error_to_str(error));
163 if (smartthings_payload_destroy(resp_payload))
164 _E("smartthings_payload_destroy failed");
170 _resource_connection_status_cb(smartthings_resource_h handle,
171 smartthings_resource_connection_status_e status, void *user_data)
173 app_data *ad = user_data;
175 _D("status=[%d]", status);
179 ad->st_res_conn_status = status;
181 if (status == SMARTTHINGS_RESOURCE_CONNECTION_STATUS_CONNECTED) {
182 if (smartthings_resource_set_request_cb(handle, _request_cb, ad)) {
183 _E("smartthings_resource_set_request_cb() is failed");
187 _E("connection failed");
193 st_thing_notify_resource(app_data *ad, const char *uri, const char *key, sensor_data *data)
195 smartthings_resource_h handle = NULL;
196 smartthings_payload_h payload = NULL;
197 int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
198 sensor_data_type_e data_type = SENSOR_DATA_TYPE_NONE;
201 retv_if(!ad->st_res_h, -1);
202 retv_if(ad->st_res_conn_status != SMARTTHINGS_RESOURCE_CONNECTION_STATUS_CONNECTED, -1);
207 handle = ad->st_res_h;
209 data_type = sensor_data_get_type(data);
210 retv_if(data_type == SENSOR_DATA_TYPE_NONE, -1);
212 smartthings_payload_create(&payload);
214 _E("failed to create payload is NULL");
219 case SENSOR_DATA_TYPE_INT:
222 sensor_data_get_int(data, &value);
223 smartthings_payload_set_int(payload, key, value);
226 case SENSOR_DATA_TYPE_UINT:
228 unsigned int value = 0;
229 sensor_data_get_uint(data, &value);
230 smartthings_payload_set_int(payload, key, (int)value);
233 case SENSOR_DATA_TYPE_BOOL:
236 sensor_data_get_bool(data, &value);
237 smartthings_payload_set_bool(payload, key, value);
240 case SENSOR_DATA_TYPE_DOUBLE:
243 sensor_data_get_double(data, &value);
244 smartthings_payload_set_double(payload, key, value);
247 case SENSOR_DATA_TYPE_STR:
249 const char *value = NULL;
250 sensor_data_get_string(data, &value);
251 smartthings_payload_set_string(payload, key, value);
254 case SENSOR_DATA_TYPE_NONE:
256 _E("unsupport data type");
260 error = smartthings_resource_notify(handle, uri, payload);
261 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
262 _E("smartthings_resource_notify() failed, [%s]",
263 __resource_error_to_str(error));
265 smartthings_payload_destroy(payload);
270 static int st_thing_resource_init(app_data *ad)
272 smartthings_resource_h st_res_h = NULL;
277 _I("Already initialized!");
281 error = smartthings_resource_initialize(&st_res_h,
282 _resource_connection_status_cb, ad);
284 _E("smartthings_resource_initialize() is failed, [%s]",
285 __resource_error_to_str(error));
289 ad->st_res_h = st_res_h;
290 ad->st_res_conn_status = SMARTTHINGS_RESOURCE_CONNECTION_STATUS_DISCONNECTED;
295 static int st_thing_resource_fini(app_data *ad)
302 smartthings_resource_unset_request_cb(ad->st_res_h);
303 smartthings_resource_deinitialize(ad->st_res_h);
306 ad->st_res_conn_status = SMARTTHINGS_RESOURCE_CONNECTION_STATUS_DISCONNECTED;
311 /* smartthings master functions */
312 static const char *__master_error_to_str(smartthings_error_e error)
314 const char *err_str = NULL;
317 case SMARTTHINGS_ERROR_NONE:
318 err_str = "SMARTTHINGS_ERROR_NONE";
320 case SMARTTHINGS_ERROR_INVALID_PARAMETER:
321 err_str = "SMARTTHINGS_ERROR_INVALID_PARAMETER";
323 case SMARTTHINGS_ERROR_OUT_OF_MEMORY:
324 err_str = "SMARTTHINGS_ERROR_OUT_OF_MEMORY";
326 case SMARTTHINGS_ERROR_PERMISSION_DENIED:
327 err_str = "SMARTTHINGS_ERROR_PERMISSION_DENIED";
329 case SMARTTHINGS_ERROR_NO_DATA:
330 err_str = "SMARTTHINGS_ERROR_NO_DATA";
332 case SMARTTHINGS_ERROR_NOT_SUPPORTED:
333 err_str = "SMARTTHINGS_ERROR_NOT_SUPPORTED";
335 case SMARTTHINGS_ERROR_OPERATION_FAILED:
336 err_str = "SMARTTHINGS_ERROR_OPERATION_FAILED";
338 case SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE:
339 err_str = "SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE";
342 err_str = "Unknown error";
349 static void _user_confirm_cb(smartthings_h handle, void *user_data)
351 if (smartthings_send_user_confirm(handle, true) != 0)
352 _E("smartthings_send_user_confirm() is failed");
355 static void _reset_confirm_cb(smartthings_h handle, void *user_data)
357 if (smartthings_send_reset_confirm(handle, true) != 0)
358 _E("smartthings_send_reset_confirm() is failed");
361 static void _reset_result_cb(smartthings_h handle, bool result, void *user_data)
363 _I("reset result = [%d]", result);
368 smartthings_h handle, smartthings_status_e status, void *user_data)
370 _D("status: [%d]", status);
374 _things_connection_status_cb(smartthings_h handle, smartthings_connection_status_e status,
377 _D("status = [%d]", status);
379 if (status == SMARTTHINGS_CONNECTION_STATUS_CONNECTED) {
381 bool is_es_completed = false;
382 const char* dev_name = "co2-app";
383 int wifi_mode = SMARTTHINGS_WIFI_MODE_11B
384 | SMARTTHINGS_WIFI_MODE_11G
385 | SMARTTHINGS_WIFI_MODE_11N;
387 int wifi_freq = SMARTTHINGS_WIFI_FREQ_24G | SMARTTHINGS_WIFI_FREQ_5G;
389 err = smartthings_set_device_property(
390 handle, dev_name, wifi_mode, wifi_freq);
392 _E("smartthings_initialize() is failed, [%s]",
393 __master_error_to_str(err));
397 err = smartthings_set_certificate_file(handle, CERT_FILE, PRIV_FILE);
399 _E("smartthings_set_certificate_file() is failed, [%s]",
400 __master_error_to_str(err));
404 err = smartthings_set_user_confirm_cb(handle, _user_confirm_cb, NULL);
406 _E("smartthings_set_user_confirm_cb() is failed, [%s]",
407 __master_error_to_str(err));
411 err = smartthings_set_reset_confirm_cb(handle, _reset_confirm_cb, NULL);
413 _E("smartthings_set_reset_confirm_cb() is failed, [%s]",
414 __master_error_to_str(err));
418 err = smartthings_set_reset_result_cb(handle, _reset_result_cb, NULL);
420 _E("smartthings_set_reset_confirm_cb() is failed, [%s]",
421 __master_error_to_str(err));
425 err = smartthings_set_status_changed_cb(handle, _thing_status_cb, NULL);
427 _E("smartthings_set_status_changed_callback() is failed, [%s]",
428 __master_error_to_str(err));
432 err = smartthings_start(handle);
434 _E("smartthings_start() is failed, [%s]",
435 __master_error_to_str(err));
439 err = smartthings_get_easysetup_status(handle, &is_es_completed);
441 _E("smartthings_get_easysetup_status() is failed, [%s]",
442 __master_error_to_str(err));
446 if (is_es_completed == true) {
447 _I("Easysetup is already done");
451 err = smartthings_start_easysetup(handle);
453 _E("smartthings_start_easysetup() is failed, [%s]",
454 __master_error_to_str(err));
455 smartthings_stop(handle);
459 _E("connection failed");
464 static int st_thing_master_init(app_data *ad)
467 smartthings_h st_handle = NULL;
471 if (ad->st_master_h) {
472 _I("Already initialized!");
476 err = smartthings_initialize(&st_handle, _things_connection_status_cb, NULL);
478 _E("smartthings_initialize() is failed, [%s]",
479 __master_error_to_str(err));
483 ad->st_master_h = st_handle;
488 int st_thing_master_fini(app_data *ad)
492 if (!ad->st_master_h) {
493 _I("handle is already NULL");
497 smartthings_unset_user_confirm_cb(ad->st_master_h);
498 smartthings_unset_reset_confirm_cb(ad->st_master_h);
499 smartthings_unset_reset_result_cb(ad->st_master_h);
500 smartthings_unset_status_changed_cb(ad->st_master_h);
502 smartthings_stop_easysetup(ad->st_master_h);
503 smartthings_stop(ad->st_master_h);
505 if (smartthings_deinitialize(ad->st_master_h) != 0) {
506 _E("smartthings_deinitialize() is failed");
509 ad->st_master_h = NULL;
514 #endif /* USE_ST_SDK */
516 static gboolean __get_co2(gpointer user_data)
519 unsigned int value = 0;
520 static unsigned int sum = 0;
521 static unsigned int count = 0;
523 app_data *ad = user_data;
526 _E("failed to get app_data");
532 _E("failed to get co2_data");
538 ret = co2_sensor_read(SENSOR_CH_CO2, &value);
539 retv_if(ret != 0, TRUE);
544 if (count == SENSOR_GATHER_COUNT) {
545 unsigned int avg = 0;
546 avg = sum/SENSOR_GATHER_COUNT;
548 _D("co2 avg - [%u], [%u ppm]", avg, co2_sensor_value_to_ppm(avg));
550 sensor_data_set_uint(ad->co2_data, avg);
553 st_thing_notify_resource(ad, SENSOR_URI_CO2, SENSOR_KEY_CO2, ad->co2_data);
562 static void gathering_stop(void *data)
567 if (ad->getter_co2) {
568 g_source_remove(ad->getter_co2);
573 static void gathering_start(void *data)
577 ad->getter_co2 = g_timeout_add(SENSOR_GATHER_INTERVAL, __get_co2, ad);
579 _E("Failed to add getter_co2");
582 static bool service_app_create(void *user_data)
584 app_data *ad = (app_data *)user_data;
586 ad->co2_data = sensor_data_new(SENSOR_DATA_TYPE_UINT);
591 if (st_thing_master_init(ad))
594 if (st_thing_resource_init(ad)) {
595 st_thing_master_fini(ad);
603 static void service_app_control(app_control_h app_control, void *user_data)
605 gathering_stop(user_data);
606 gathering_start(user_data);
609 static void service_app_terminate(void *user_data)
611 app_data *ad = (app_data *)user_data;
617 st_thing_resource_fini(ad);
618 st_thing_master_fini(ad);
621 sensor_data_free(ad->co2_data);
628 int main(int argc, char *argv[])
631 service_app_lifecycle_callback_s event_callback;
633 ad = calloc(1, sizeof(app_data));
638 event_callback.create = service_app_create;
639 event_callback.terminate = service_app_terminate;
640 event_callback.app_control = service_app_control;
642 return service_app_main(argc, argv, &event_callback, ad);