2 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
4 * Contact: Jin Yoon <jinny.yoon@samsung.com>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
20 #include <service_app.h>
27 #include "st_things.h"
29 #include "sensor-data.h"
32 #define JSON_PATH "device_def.json"
34 #define SENSOR_URI_ILLUMINANCE "/capability/illuminanceMeasurement/main/0"
35 #define SENSOR_KEY_ILLUMINANCE "illuminance"
36 #define SENSOR_KEY_RANGE "range"
38 #define SENSOR_URI_DOOR "/capability/doorControl/main/0"
39 #define SENSOR_KEY_DOOR "doorState"
40 #define SENSOR_POWER_INITIALIZING BLIND_DOWN
42 #define I2C_BUS_NUMBER (1)
43 #define SENSOR_GATHER_INTERVAL (5.0f)
45 // If you want to use SmartThings, Please uncomment this define */
48 typedef struct app_data_s {
49 Ecore_Timer *getter_illuminance;
50 sensor_data *illuminance_data;
51 sensor_data *power_data;
54 static app_data *g_ad = NULL;
56 #define ILLUMINATION_CRITERIA 1000
58 // HS-53 Servo Motor Duty Cycle : 0.54ms ~ 2.1ms
59 // Spec Duty Cycle : 0.553ms ~ 2.227ms(https://www.servocity.com/hitec-hs-53-servo)
60 #define SERVO_MOTOR_DUTY_CYCLE_COUNTER_CLOCKWISE 1.0
61 #define SERVO_MOTOR_DUTY_CYCLE_CLOCKWISE 2.0
63 #define BLIND_UP "opening"
64 #define BLIND_DOWN "closing"
66 static inline int __get_illuminance(void *data, unsigned int *illuminance_value)
72 retv_if(!ad->illuminance_data, -1);
74 ret = resource_read_illuminance_sensor(I2C_BUS_NUMBER, illuminance_value);
75 retv_if(ret != 0, -1);
77 sensor_data_set_uint(ad->illuminance_data, *illuminance_value);
78 _D("Illuminance value : %u", *illuminance_value);
81 st_things_notify_observers(SENSOR_URI_ILLUMINANCE);
87 static int __set_servo_motor(void *data, int on)
89 double duty_cycle = 0;
91 const char *power_value = NULL;
95 retv_if(!ad->illuminance_data, -1);
98 duty_cycle = SERVO_MOTOR_DUTY_CYCLE_CLOCKWISE;
99 power_value = BLIND_UP;
101 duty_cycle = SERVO_MOTOR_DUTY_CYCLE_COUNTER_CLOCKWISE;
102 power_value = BLIND_DOWN;
105 ret = resource_set_servo_motor_value(duty_cycle);
106 retv_if(ret != 0, -1);
108 sensor_data_set_string(ad->power_data, power_value, strlen(power_value));
111 st_things_notify_observers(SENSOR_URI_DOOR);
117 static Eina_Bool __illuminance_to_servo_motor(void *data)
120 unsigned int illuminance_value = 0;
125 _E("failed to get app_data");
129 if (!ad->illuminance_data) {
130 _E("failed to get illuminance_data");
134 ret = __get_illuminance(ad, &illuminance_value);
135 retv_if(ret != 0, ECORE_CALLBACK_RENEW);
137 #if 1 // If you want to control MOTOR from Cloud, please deactivate these codes.
140 if (illuminance_value < ILLUMINATION_CRITERIA) {
146 ret = __set_servo_motor(ad, on);
147 retv_if(ret != 0, ECORE_CALLBACK_RENEW);
150 return ECORE_CALLBACK_RENEW;
153 void gathering_stop(void *data)
159 if (ad->getter_illuminance)
160 ecore_timer_del(ad->getter_illuminance);
163 void gathering_start(void *data)
171 ad->getter_illuminance = ecore_timer_add(SENSOR_GATHER_INTERVAL, __illuminance_to_servo_motor, ad);
172 if (!ad->getter_illuminance)
173 _E("Failed to add getter_illuminance");
177 static bool handle_reset_request(void)
179 _D("Received a request for RESET.");
183 static void handle_reset_result(bool result)
185 _D("Reset %s.\n", result ? "succeeded" : "failed");
188 static bool handle_ownership_transfer_request(void)
190 _D("Received a request for Ownership-transfer.");
194 static void handle_things_status_change(st_things_status_e things_status)
196 _D("Things status is changed: %d", things_status);
198 if (things_status == ST_THINGS_STATUS_REGISTERED_TO_CLOUD) {
199 ecore_main_loop_thread_safe_call_async(gathering_start, g_ad);
203 static bool handle_get_request(st_things_get_request_message_s* req_msg, st_things_representation_s* resp_rep)
205 _D("resource_uri [%s]", req_msg->resource_uri);
206 retv_if(!g_ad, false);
208 if (0 == strcmp(req_msg->resource_uri, SENSOR_URI_ILLUMINANCE)) {
209 if (req_msg->has_property_key(req_msg, SENSOR_KEY_ILLUMINANCE)) {
210 unsigned int value = 0;
211 sensor_data_get_uint(g_ad->illuminance_data, &value);
212 resp_rep->set_int_value(resp_rep, SENSOR_KEY_ILLUMINANCE, value);
215 } else if (0 == strcmp(req_msg->resource_uri, SENSOR_URI_DOOR)) {
216 if (req_msg->has_property_key(req_msg, SENSOR_KEY_DOOR)) {
217 const char *str = NULL;
218 sensor_data_get_string(g_ad->power_data, &str);
220 str = SENSOR_POWER_INITIALIZING;
222 resp_rep->set_str_value(resp_rep, SENSOR_KEY_DOOR, str);
223 _D("Power : %s", str);
227 _E("not supported uri");
231 static bool handle_set_request(st_things_set_request_message_s* req_msg, st_things_representation_s* resp_rep)
233 _D("resource_uri [%s]", req_msg->resource_uri);
234 retv_if(!g_ad, false);
236 if (0 == strcmp(req_msg->resource_uri, SENSOR_URI_DOOR)) {
240 if (req_msg->rep->get_str_value(req_msg->rep, SENSOR_KEY_DOOR, &str)) {
241 retv_if(!str, false);
242 _D("set [%s:%s] == %s", SENSOR_URI_DOOR, SENSOR_KEY_DOOR, str);
244 sensor_data_set_string(g_ad->power_data, str, strlen(str));
245 resp_rep->set_str_value(resp_rep, SENSOR_KEY_DOOR, str);
247 if (0 == strcmp(str, "opening")) {
248 ret = __set_servo_motor(g_ad, 1);
250 ret = __set_servo_motor(g_ad, 0);
253 retv_if(ret != 0, false);
255 _E("cannot get a string value");
263 static int __st_things_init(void)
265 bool easysetup_complete = false;
266 char app_json_path[128] = {'\0', };
267 char *app_res_path = NULL;
268 char *app_data_path = NULL;
270 app_res_path = app_get_resource_path();
272 _E("app_res_path is NULL!!");
276 app_data_path = app_get_data_path();
277 if (!app_data_path) {
278 _E("app_data_path is NULL!!");
283 snprintf(app_json_path, sizeof(app_json_path), "%s%s", app_res_path, JSON_PATH);
285 if (0 != st_things_set_configuration_prefix_path(app_res_path, app_data_path)) {
286 _E("st_things_set_configuration_prefix_path() failed!!");
295 if (0 != st_things_initialize(app_json_path, &easysetup_complete)) {
296 _E("st_things_initialize() failed!!");
300 _D("easysetup_complete:[%d] ", easysetup_complete);
302 st_things_register_request_cb(handle_get_request, handle_set_request);
303 st_things_register_reset_cb(handle_reset_request, handle_reset_result);
304 st_things_register_user_confirm_cb(handle_ownership_transfer_request);
305 st_things_register_things_status_change_cb(handle_things_status_change);
310 static int __st_things_deinit(void)
312 st_things_deinitialize();
316 static int __st_things_start(void)
322 static int __st_things_stop(void)
327 #endif /* USE_ST_SDK */
329 static bool service_app_create(void *user_data)
331 app_data *ad = (app_data *)user_data;
333 ad->illuminance_data = sensor_data_new(SENSOR_DATA_TYPE_UINT);
334 if (!ad->illuminance_data)
337 ad->power_data = sensor_data_new(SENSOR_DATA_TYPE_STR);
340 sensor_data_set_string(g_ad->power_data, SENSOR_POWER_INITIALIZING, strlen(SENSOR_POWER_INITIALIZING));
343 if (__st_things_init())
350 static void service_app_control(app_control_h app_control, void *user_data)
355 gathering_start(user_data);
359 static void service_app_terminate(void *user_data)
361 app_data *ad = (app_data *)user_data;
363 resource_close_illuminance_sensor();
364 resource_close_servo_motor();
368 __st_things_deinit();
373 sensor_data_free(ad->illuminance_data);
377 int main(int argc, char *argv[])
380 service_app_lifecycle_callback_s event_callback;
382 ad = calloc(1, sizeof(app_data));
387 event_callback.create = service_app_create;
388 event_callback.terminate = service_app_terminate;
389 event_callback.app_control = service_app_control;
391 return service_app_main(argc, argv, &event_callback, ad);