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 <smartthings_resource.h>
18 #include <smartthings_payload.h>
27 #define URI_SWITCH "/capability/switch/main/0"
28 #define KEY_SWITCH "power"
29 #define VALUE_SWITCH_ON "on"
30 #define VALUE_SWITCH_OFF "off"
33 #define URI_AUDIOVOLUME "/capability/audioVolume/main/0"
34 #define KEY_VOLUME "volume"
35 #define KEY_MUTE "mute"
37 // dim switch - servo h
38 #define URI_SWITCHLEVEL "/capability/switchLevel/main/0"
39 #define KEY_SWITCHLEVEL "dimmingSetting"
42 #define URI_MOTION "/capability/motionSensor/main/0"
43 #define KEY_MOTION "value"
45 #define RESOURCE_CALLBACK_KEY "st_thing_resource"
47 static smartthings_resource_h g_st_res_h;
48 static smartthings_resource_connection_status_e g_conn_status =
49 SMARTTHINGS_RESOURCE_CONNECTION_STATUS_DISCONNECTED;
53 __resource_error_to_str(smartthings_resource_error_e error)
55 const char *err_str = NULL;
58 case SMARTTHINGS_RESOURCE_ERROR_NONE:
59 err_str = "SMARTTHINGS_RESOURCE_ERROR_NONE";
61 case SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER:
62 err_str = "SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER";
64 case SMARTTHINGS_RESOURCE_ERROR_OUT_OF_MEMORY:
65 err_str = "SMARTTHINGS_RESOURCE_ERROR_OUT_OF_MEMORY";
67 case SMARTTHINGS_RESOURCE_ERROR_PERMISSION_DENIED:
68 err_str = "SMARTTHINGS_RESOURCE_ERROR_PERMISSION_DENIED";
70 case SMARTTHINGS_RESOURCE_ERROR_NO_DATA:
71 err_str = "SMARTTHINGS_RESOURCE_ERROR_NO_DATA";
73 case SMARTTHINGS_RESOURCE_ERROR_NOT_SUPPORTED:
74 err_str = "SMARTTHINGS_RESOURCE_ERROR_NOT_SUPPORTED";
76 case SMARTTHINGS_RESOURCE_ERROR_OPERATION_FAILED:
77 err_str = "SMARTTHINGS_RESOURCE_ERROR_NOT_SUPPORTED";
79 case SMARTTHINGS_RESOURCE_ERROR_SERVICE_UNAVAILABLE:
80 err_str = "SMARTTHINGS_RESOURCE_ERROR_SERVICE_UNAVAILABLE";
83 err_str = "Unknown error";
90 /* get and set request handlers */
92 handle_get_motion(smartthings_payload_h resp_payload, void *user_data)
96 motion_state_get(&state);
98 _D("GET request for motion : %d", state);
99 smartthings_payload_set_bool(resp_payload, KEY_MOTION, state ? true : false);
105 handle_set_motion(smartthings_payload_h payload,
106 smartthings_payload_h resp_payload, void *user_data)
110 if (smartthings_payload_get_bool(payload, KEY_MOTION, &bvalue) == 0) {
111 _D("requested volume: [%d]", bvalue);
112 motion_state_set((int)bvalue, RESOURCE_CALLBACK_KEY);
113 smartthings_payload_set_bool(resp_payload, KEY_MOTION, bvalue);
120 handle_get_switch(smartthings_payload_h resp_payload, void *user_data)
122 switch_state_e state = SWITCH_STATE_OFF;
123 const char *switch_state_name = NULL;
125 switch_state_get(&state);
127 if (state == SWITCH_STATE_OFF)
128 switch_state_name = VALUE_SWITCH_OFF;
130 switch_state_name = VALUE_SWITCH_ON;
132 _D("GET request for switch : %s", switch_state_name);
133 smartthings_payload_set_string(resp_payload, KEY_SWITCH, switch_state_name);
139 handle_set_switch(smartthings_payload_h payload,
140 smartthings_payload_h resp_payload, void *user_data)
142 char *str_value = NULL;
143 switch_state_e state = SWITCH_STATE_OFF;
145 if (smartthings_payload_get_string(payload, KEY_SWITCH, &str_value) != 0) {
146 _E("failed to smartthings_payload_get_string()");
149 retv_if(!str_value, false);
151 _D("SET request for switch: [%s]", str_value);
153 if (0 == g_strcmp0(str_value, VALUE_SWITCH_ON))
154 state = SWITCH_STATE_ON;
156 switch_state_set(state, RESOURCE_CALLBACK_KEY);
158 smartthings_payload_set_string(resp_payload, KEY_SWITCH, str_value);
165 handle_get_audiovolume(smartthings_payload_h resp_payload, void *user_data)
169 servo_v_state_get(&value);
171 _D("current volume: [%f]", value);
172 smartthings_payload_set_int(resp_payload, KEY_VOLUME, (int)value);
173 smartthings_payload_set_bool(resp_payload, KEY_MUTE, false);
179 handle_set_audiovolume(smartthings_payload_h payload,
180 smartthings_payload_h resp_payload, void *user_data)
184 if (smartthings_payload_get_int(payload, KEY_VOLUME, &ivalue) == 0) {
185 _D("requested volume: [%d]", ivalue);
186 servo_v_state_set((double)ivalue, RESOURCE_CALLBACK_KEY);
187 smartthings_payload_set_int(resp_payload, KEY_VOLUME, ivalue);
190 smartthings_payload_set_bool(resp_payload, KEY_MUTE, false);
196 handle_get_switchLevel(smartthings_payload_h resp_payload, void *user_data)
201 servo_h_state_get(&value);
203 _D("current switchLevel: [%f]", value);
204 smartthings_payload_set_int(resp_payload, KEY_SWITCHLEVEL, (int)value);
211 handle_set_switchLevel(smartthings_payload_h payload,
212 smartthings_payload_h resp_payload, void *user_data)
216 if (smartthings_payload_get_int(payload, KEY_SWITCHLEVEL, &ivalue) == 0) {
217 _D("requested dimming: [%d]", ivalue);
218 servo_h_state_set((double)ivalue, RESOURCE_CALLBACK_KEY);
219 smartthings_payload_set_int(resp_payload, KEY_SWITCHLEVEL, ivalue);
226 _request_cb(smartthings_resource_h handle, int req_id,
227 const char *uri, smartthings_resource_req_type_e req_type,
228 smartthings_payload_h payload, void *user_data)
230 smartthings_payload_h resp_payload = NULL;
232 int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
234 _D("request on %s, type[%d], id[%d]", uri, req_type, req_id);
236 smartthings_payload_create(&resp_payload);
238 _E("Response payload is NULL");
242 if (req_type == SMARTTHINGS_RESOURCE_REQUEST_GET) {
243 if (0 == g_strcmp0(uri, URI_SWITCH))
244 result = handle_get_switch(resp_payload, user_data);
245 else if (0 == g_strcmp0(uri, URI_AUDIOVOLUME))
246 result = handle_get_audiovolume(resp_payload, user_data);
247 else if (0 == g_strcmp0(uri, URI_SWITCHLEVEL))
248 result = handle_get_switchLevel(resp_payload, user_data);
249 else if (0 == g_strcmp0(uri, URI_MOTION))
250 result = handle_get_motion(resp_payload, user_data);
252 _E("No matching Resource uri");
253 } else if (req_type == SMARTTHINGS_RESOURCE_REQUEST_SET) {
254 if (0 == g_strcmp0(uri, URI_SWITCH))
255 result = handle_set_switch(payload, resp_payload, user_data);
256 else if (0 == g_strcmp0(uri, URI_AUDIOVOLUME))
257 result = handle_set_audiovolume(payload, resp_payload, user_data);
258 else if (0 == g_strcmp0(uri, URI_SWITCHLEVEL))
259 result = handle_set_switchLevel(payload, resp_payload, user_data);
260 else if (0 == g_strcmp0(uri, URI_MOTION))
261 result = handle_set_motion(payload, resp_payload, user_data);
263 _E("No matching Resource uri");
265 _E("Invalid request type - %d", req_type);
266 smartthings_payload_destroy(resp_payload);
270 error = smartthings_resource_send_response(handle, req_id, uri, resp_payload, result);
271 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE) {
272 smartthings_payload_destroy(resp_payload);
273 _E("smartthings_resource_send_response() failed, [%s]",
274 __resource_error_to_str(error));
278 if (req_type == SMARTTHINGS_RESOURCE_REQUEST_SET) {
279 error = smartthings_resource_notify(handle, uri, resp_payload);
280 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
281 _E("smartthings_resource_notify() failed, [%s]",
282 __resource_error_to_str(error));
285 if (smartthings_payload_destroy(resp_payload))
286 _E("smartthings_payload_destroy failed");
292 _resource_connection_status_cb(smartthings_resource_h handle,
293 smartthings_resource_connection_status_e status, void *user_data)
295 _D("status=[%d]", status);
297 g_conn_status = status;
299 if (status == SMARTTHINGS_RESOURCE_CONNECTION_STATUS_CONNECTED) {
300 if (smartthings_resource_set_request_cb(handle, _request_cb, NULL)) {
301 _E("smartthings_resource_set_request_cb() is failed");
305 _E("connection failed");
310 static void __motion_changed(int value, void* user_data)
312 smartthings_resource_h handle = user_data;
313 smartthings_payload_h payload = NULL;
314 int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
318 _D("motion changed to - %d", value);
320 ret_if(g_conn_status != SMARTTHINGS_RESOURCE_CONNECTION_STATUS_CONNECTED);
322 smartthings_payload_create(&payload);
324 _E("failed to create payload is NULL");
328 smartthings_payload_set_bool(payload, KEY_MOTION, value ? true : false);
330 error = smartthings_resource_notify(handle, URI_MOTION, payload);
331 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
332 _E("smartthings_resource_notify() failed, [%s]",
333 __resource_error_to_str(error));
335 smartthings_payload_destroy(payload);
338 static void __switch_changed(switch_state_e state, void* user_data)
340 smartthings_resource_h handle = user_data;
341 smartthings_payload_h payload = NULL;
342 int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
343 const char *switch_state_name = NULL;
345 _D("switch changed to - %d", state);
347 ret_if(g_conn_status != SMARTTHINGS_RESOURCE_CONNECTION_STATUS_CONNECTED);
349 smartthings_payload_create(&payload);
351 _E("failed to create payload is NULL");
355 if (state == SWITCH_STATE_OFF)
356 switch_state_name = VALUE_SWITCH_OFF;
358 switch_state_name = VALUE_SWITCH_ON;
360 smartthings_payload_set_string(payload, KEY_SWITCH, switch_state_name);
362 error = smartthings_resource_notify(handle, URI_SWITCH, payload);
363 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
364 _E("smartthings_resource_notify() failed, [%s]",
365 __resource_error_to_str(error));
367 smartthings_payload_destroy(payload);
370 static void __servo_v_changed(double value, void* user_data)
372 smartthings_resource_h handle = user_data;
373 smartthings_payload_h payload = NULL;
374 int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
376 _D("servo_v changed to - %f", value);
378 ret_if(g_conn_status != SMARTTHINGS_RESOURCE_CONNECTION_STATUS_CONNECTED);
380 smartthings_payload_create(&payload);
382 _E("failed to create payload is NULL");
386 smartthings_payload_set_int(payload, KEY_VOLUME, (int)value);
388 error = smartthings_resource_notify(handle, URI_AUDIOVOLUME, payload);
389 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
390 _E("smartthings_resource_notify() failed, [%s]",
391 __resource_error_to_str(error));
393 smartthings_payload_destroy(payload);
396 static void __servo_h_changed(double value, void* user_data)
398 smartthings_resource_h handle = user_data;
399 smartthings_payload_h payload = NULL;
400 int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
402 _D("servo_h changed to - %f", value);
404 ret_if(g_conn_status != SMARTTHINGS_RESOURCE_CONNECTION_STATUS_CONNECTED);
406 smartthings_payload_create(&payload);
408 _E("failed to create payload is NULL");
412 smartthings_payload_set_int(payload, KEY_SWITCHLEVEL, (int)value);
414 error = smartthings_resource_notify(handle, URI_SWITCHLEVEL, payload);
415 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
416 _E("smartthings_resource_notify() failed, [%s]",
417 __resource_error_to_str(error));
419 smartthings_payload_destroy(payload);
422 static int __device_interfaces_set_callbak(smartthings_resource_h handle)
424 retv_if(!handle, -1);
426 // Assume that, device interfaces are already initialized in controller.c
427 switch_state_changed_cb_set(RESOURCE_CALLBACK_KEY,
428 __switch_changed, handle);
429 servo_v_state_changed_cb_set(RESOURCE_CALLBACK_KEY,
430 __servo_v_changed, handle);
431 servo_h_state_changed_cb_set(RESOURCE_CALLBACK_KEY,
432 __servo_h_changed, handle);
433 motion_state_changed_cb_set(RESOURCE_CALLBACK_KEY,
434 __motion_changed, handle);
440 int st_thing_resource_init(void)
442 smartthings_resource_h st_res_h = NULL;
446 _I("Already initialized!");
450 error = smartthings_resource_initialize(&st_res_h,
451 _resource_connection_status_cb, NULL);
453 _E("smartthings_resource_initialize() is failed, [%s]",
454 __resource_error_to_str(error));
458 g_st_res_h = st_res_h;
459 g_conn_status = SMARTTHINGS_RESOURCE_CONNECTION_STATUS_DISCONNECTED;
461 __device_interfaces_set_callbak(g_st_res_h);
466 int st_thing_resource_fini(void)
471 smartthings_resource_unset_request_cb(g_st_res_h);
472 smartthings_resource_deinitialize(g_st_res_h);
474 g_conn_status = SMARTTHINGS_RESOURCE_CONNECTION_STATUS_DISCONNECTED;