dc623f66ba54ef0f4f3e730bb7137ec021913b1d
[apps/native/st-things-co2-meter.git] / src / co2.c
1 /* ****************************************************************
2  *
3  * Copyright 2017 Samsung Electronics All Rights Reserved.
4  *
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
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  *
17  ******************************************************************/
18
19 #include <tizen.h>
20 #include <service_app.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <Ecore.h>
24
25 #include "st_things.h"
26 #include "log.h"
27 #include "sensor-data.h"
28 #include "co2-sensor.h"
29
30 //#define TEST_RANDOM_VAL_GEN
31 #ifdef TEST_RANDOM_VAL_GEN
32 #include <time.h>
33 #include <stdlib.h>
34 #define RAND_VAL_MIN 0
35 #define RAND_VAL_MAX_CO2 1023
36 #endif /* TEST_RANDOM_VAL_GEN */
37
38 #define JSON_NAME "device_def.json"
39 #define SENSOR_URI_CO2 "/capability/airQualitySensor/main/0"
40 #define SENSOR_KEY_CO2 "airQuality"
41 #define SENSOR_KEY_RANGE "range"
42
43 #define SENSOR_CH_CO2 (0)
44 #define SENSOR_THRESHOLD_CO2 (650)
45
46 #define SENSOR_GATHER_INTERVAL (0.05f)
47 #define SENSOR_GATHER_COUNT (60)
48
49 //#define USE_ST_SDK
50
51 typedef struct app_data_s {
52         Ecore_Timer *getter_co2;
53         sensor_data *co2_data;
54 } app_data;
55
56 static app_data *g_ad = NULL;
57
58 #ifdef TEST_RANDOM_VAL_GEN
59 static int rand_read_co2_sensor(unsigned int *out_value)
60 {
61         unsigned int val = 0;
62
63         val = RAND_VAL_MIN + rand() / (RAND_MAX / (RAND_VAL_MAX_CO2 - RAND_VAL_MIN + 1) + 1);
64         *out_value = val;
65
66         return 0;
67 }
68 #endif
69
70 static int read_sensor(unsigned int *out_value)
71 {
72         int ret = 0;
73         retv_if(!out_value, -1);
74
75 #ifdef TEST_RANDOM_VAL_GEN
76         ret = rand_read_co2_sensor(out_value);
77 #else /* TEST_RANDOM_VAL_GEN */
78         ret = co2_sensor_read(SENSOR_CH_CO2, out_value);
79 #endif /* TEST_RANDOM_VAL_GEN */
80
81         return ret;
82 }
83
84 static Eina_Bool __get_co2(void *data)
85 {
86         int ret = 0;
87         unsigned int value = 0;
88         static unsigned int sum = 0;
89         static unsigned int count = 0;
90
91         app_data *ad = data;
92
93         if (!ad) {
94                 _E("failed to get app_data");
95                 service_app_exit();
96         }
97
98         if (!ad->co2_data) {
99                 _E("failed to get co2_data");
100                 service_app_exit();
101         }
102
103         ret = read_sensor(&value);
104         retv_if(ret != 0, ECORE_CALLBACK_RENEW);
105
106         count++;
107         sum += value;
108
109         if (count == SENSOR_GATHER_COUNT) {
110                 unsigned int avg = 0;
111                 avg = sum/SENSOR_GATHER_COUNT;
112
113                 _D("co2 avg - [%u], [%u ppm]", avg, co2_sensor_value_to_ppm(avg));
114
115                 sensor_data_set_uint(ad->co2_data, avg);
116
117                 if (avg <= SENSOR_THRESHOLD_CO2) {
118         #ifdef USE_ST_SDK
119                         st_things_notify_observers(SENSOR_URI_CO2);
120         #endif
121                 }
122
123                 count = 0;
124                 sum = 0;
125         }
126
127         return ECORE_CALLBACK_RENEW;
128 }
129
130 void gathering_start(void *data)
131 {
132         app_data *ad = data;
133         ret_if(!ad);
134
135         if (ad->getter_co2)
136                 ecore_timer_del(ad->getter_co2);
137
138         ad->getter_co2 = ecore_timer_add(SENSOR_GATHER_INTERVAL, __get_co2, ad);
139         if (!ad->getter_co2)
140                 _E("Failed to add getter_co2");
141
142         return;
143 }
144
145 #ifdef USE_ST_SDK
146 static bool handle_reset_request(void)
147 {
148         _D("Received a request for RESET.");
149         return false;
150 }
151
152 static void handle_reset_result(bool result)
153 {
154         _D("Reset %s.\n", result ? "succeeded" : "failed");
155 }
156
157 static bool handle_ownership_transfer_request(void)
158 {
159         _D("Received a request for Ownership-transfer.");
160         return true;
161 }
162
163 static void handle_things_status_change(st_things_status_e things_status)
164 {
165         _D("Things status is changed: %d\n", things_status);
166
167         if (things_status == ST_THINGS_STATUS_REGISTERED_TO_CLOUD)
168                 ecore_main_loop_thread_safe_call_async(gathering_start, g_ad);
169 }
170
171 static bool handle_get_request(st_things_get_request_message_s* req_msg, st_things_representation_s* resp_rep)
172 {
173         _D("resource_uri [%s]", req_msg->resource_uri);
174         retv_if(!g_ad, false);
175
176         if (0 == strcmp(req_msg->resource_uri, SENSOR_URI_CO2)) {
177                 _D("query : %s, property: %s", req_msg->query, req_msg->property_key);
178
179                 if (req_msg->has_property_key(req_msg, SENSOR_KEY_CO2)) {
180                         unsigned int value = 0;
181                         sensor_data_get_uint(g_ad->co2_data, &value);
182                         resp_rep->set_int_value(resp_rep, SENSOR_KEY_CO2, value);
183                 }
184                 if (req_msg->has_property_key(req_msg, SENSOR_KEY_RANGE)) {
185                         const double range[2] = { 0.0, 1024.0 };
186                         resp_rep->set_double_array_value(resp_rep, SENSOR_KEY_RANGE, range, 2);
187                 }
188                 return true;
189         }
190         _E("not supported uri");
191         return false;
192 }
193
194 static bool handle_set_request(st_things_set_request_message_s* req_msg, st_things_representation_s* resp_rep)
195 {
196         _D("resource_uri [%s]", req_msg->resource_uri);
197         return false;
198 }
199
200 static int __things_init(void)
201 {
202         bool easysetup_complete = false;
203         char app_json_path[128] = {'\0', };
204         char *app_res_path = NULL;
205         char *app_data_path = NULL;
206
207         app_res_path = app_get_resource_path();
208         if (!app_res_path) {
209                 _E("app_res_path is NULL!!");
210                 return -1;
211         }
212
213         app_data_path = app_get_data_path();
214         if (!app_data_path) {
215                 _E("app_data_path is NULL!!");
216                 free(app_res_path);
217                 return -1;
218         }
219
220         if (0 != st_things_set_configuration_prefix_path(app_res_path, app_data_path)) {
221                 _E("st_things_set_configuration_prefix_path() failed!!");
222                 free(app_res_path);
223                 free(app_data_path);
224                 return -1;
225         }
226         free(app_data_path);
227
228         snprintf(app_json_path, sizeof(app_json_path), "%s%s", app_res_path, JSON_NAME);
229         free(app_res_path);
230
231         if (0 != st_things_initialize(app_json_path, &easysetup_complete)) {
232                 _E("st_things_initialize() failed!!");
233                 return -1;
234         }
235
236         _D("easysetup_complete:[%d] ", easysetup_complete);
237
238         st_things_register_request_cb(handle_get_request, handle_set_request);
239         st_things_register_reset_cb(handle_reset_request, handle_reset_result);
240         st_things_register_user_confirm_cb(handle_ownership_transfer_request);
241         st_things_register_things_status_change_cb(handle_things_status_change);
242
243         return 0;
244 }
245
246 static int __things_deinit(void)
247 {
248         st_things_deinitialize();
249         return 0;
250 }
251
252 static int __things_start(void)
253 {
254         st_things_start();
255         return 0;
256 }
257
258 static int __things_stop(void)
259 {
260         st_things_stop();
261         return 0;
262 }
263 #endif /* USE_ST_SDK */
264
265 static bool service_app_create(void *user_data)
266 {
267         app_data *ad = (app_data *)user_data;
268
269         ad->co2_data = sensor_data_new(SENSOR_DATA_TYPE_UINT);
270         if (!ad->co2_data)
271                 return false;
272
273 #ifdef USE_ST_SDK
274         if (__things_init())
275                 return false;
276 #endif
277
278         return true;
279 }
280
281 static void service_app_control(app_control_h app_control, void *user_data)
282 {
283 #ifdef USE_ST_SDK
284         __things_start();
285 #else
286         gathering_start(user_data);
287 #endif
288 }
289
290 static void service_app_terminate(void *user_data)
291 {
292         app_data *ad = (app_data *)user_data;
293
294         if (ad->getter_co2)
295                 ecore_timer_del(ad->getter_co2);
296
297 #ifdef USE_ST_SDK
298         __things_stop();
299         __things_deinit();
300 #endif
301
302         sensor_data_free(ad->co2_data);
303         co2_sensor_close();
304         free(ad);
305
306         FN_END;
307 }
308
309 int main(int argc, char *argv[])
310 {
311         app_data *ad = NULL;
312         service_app_lifecycle_callback_s event_callback;
313
314         ad = calloc(1, sizeof(app_data));
315         retv_if(!ad, -1);
316
317         g_ad = ad;
318
319         event_callback.create = service_app_create;
320         event_callback.terminate = service_app_terminate;
321         event_callback.app_control = service_app_control;
322
323         return service_app_main(argc, argv, &event_callback, ad);
324 }
325