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_error_e error,
293 smartthings_resource_h handle,
294 smartthings_resource_connection_status_e status, void *user_data)
296 _D("result [%s], status=[%d]", __resource_error_to_str(error), status);
298 g_conn_status = status;
300 if (status == SMARTTHINGS_RESOURCE_CONNECTION_STATUS_CONNECTED) {
301 if (smartthings_resource_set_request_cb(handle, _request_cb, NULL)) {
302 _E("smartthings_resource_set_request_cb() is failed");
306 _E("connection failed");
311 static void __motion_changed(int value, void* user_data)
313 smartthings_resource_h handle = user_data;
314 smartthings_payload_h payload = NULL;
315 int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
319 _D("motion changed to - %d", value);
321 ret_if(g_conn_status != SMARTTHINGS_RESOURCE_CONNECTION_STATUS_CONNECTED);
323 smartthings_payload_create(&payload);
325 _E("failed to create payload is NULL");
329 smartthings_payload_set_bool(payload, KEY_MOTION, value ? true : false);
331 error = smartthings_resource_notify(handle, URI_MOTION, payload);
332 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
333 _E("smartthings_resource_notify() failed, [%s]",
334 __resource_error_to_str(error));
336 smartthings_payload_destroy(payload);
339 static void __switch_changed(switch_state_e state, void* user_data)
341 smartthings_resource_h handle = user_data;
342 smartthings_payload_h payload = NULL;
343 int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
344 const char *switch_state_name = NULL;
346 _D("switch changed to - %d", state);
348 ret_if(g_conn_status != SMARTTHINGS_RESOURCE_CONNECTION_STATUS_CONNECTED);
350 smartthings_payload_create(&payload);
352 _E("failed to create payload is NULL");
356 if (state == SWITCH_STATE_OFF)
357 switch_state_name = VALUE_SWITCH_OFF;
359 switch_state_name = VALUE_SWITCH_ON;
361 smartthings_payload_set_string(payload, KEY_SWITCH, switch_state_name);
363 error = smartthings_resource_notify(handle, URI_SWITCH, payload);
364 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
365 _E("smartthings_resource_notify() failed, [%s]",
366 __resource_error_to_str(error));
368 smartthings_payload_destroy(payload);
371 static void __servo_v_changed(double value, void* user_data)
373 smartthings_resource_h handle = user_data;
374 smartthings_payload_h payload = NULL;
375 int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
377 _D("servo_v changed to - %f", value);
379 ret_if(g_conn_status != SMARTTHINGS_RESOURCE_CONNECTION_STATUS_CONNECTED);
381 smartthings_payload_create(&payload);
383 _E("failed to create payload is NULL");
387 smartthings_payload_set_int(payload, KEY_VOLUME, (int)value);
389 error = smartthings_resource_notify(handle, URI_AUDIOVOLUME, payload);
390 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
391 _E("smartthings_resource_notify() failed, [%s]",
392 __resource_error_to_str(error));
394 smartthings_payload_destroy(payload);
397 static void __servo_h_changed(double value, void* user_data)
399 smartthings_resource_h handle = user_data;
400 smartthings_payload_h payload = NULL;
401 int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
403 _D("servo_h changed to - %f", value);
405 ret_if(g_conn_status != SMARTTHINGS_RESOURCE_CONNECTION_STATUS_CONNECTED);
407 smartthings_payload_create(&payload);
409 _E("failed to create payload is NULL");
413 smartthings_payload_set_int(payload, KEY_SWITCHLEVEL, (int)value);
415 error = smartthings_resource_notify(handle, URI_SWITCHLEVEL, payload);
416 if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
417 _E("smartthings_resource_notify() failed, [%s]",
418 __resource_error_to_str(error));
420 smartthings_payload_destroy(payload);
423 static int __device_interfaces_set_callbak(smartthings_resource_h handle)
425 retv_if(!handle, -1);
427 // Assume that, device interfaces are already initialized in controller.c
428 switch_state_changed_cb_set(RESOURCE_CALLBACK_KEY,
429 __switch_changed, handle);
430 servo_v_state_changed_cb_set(RESOURCE_CALLBACK_KEY,
431 __servo_v_changed, handle);
432 servo_h_state_changed_cb_set(RESOURCE_CALLBACK_KEY,
433 __servo_h_changed, handle);
434 motion_state_changed_cb_set(RESOURCE_CALLBACK_KEY,
435 __motion_changed, handle);
441 int st_thing_resource_init(void)
443 smartthings_resource_h st_res_h = NULL;
447 _I("Already initialized!");
451 error = smartthings_resource_initialize(&st_res_h,
452 _resource_connection_status_cb, NULL);
454 _E("smartthings_resource_initialize() is failed, [%s]",
455 __resource_error_to_str(error));
459 g_st_res_h = st_res_h;
460 g_conn_status = SMARTTHINGS_RESOURCE_CONNECTION_STATUS_DISCONNECTED;
462 __device_interfaces_set_callbak(g_st_res_h);
467 int st_thing_resource_fini(void)
472 smartthings_resource_unset_request_cb(g_st_res_h);
473 smartthings_resource_deinitialize(g_st_res_h);
475 g_conn_status = SMARTTHINGS_RESOURCE_CONNECTION_STATUS_DISCONNECTED;