HomePort
demo_adapter.c
Go to the documentation of this file.
1 /*
2  * Copyright 2011 Aalborg University. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification, are
5  * permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice, this list of
8  * conditions and the following disclaimer.
9  *
10  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11  * of conditions and the following disclaimer in the documentation and/or other materials
12  * provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY Aalborg University ''AS IS'' AND ANY EXPRESS OR IMPLIED
15  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Aalborg University OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  * The views and conclusions contained in the software and documentation are those of the
25  * authors and should not be interpreted as representing official policies, either expressed
26  */
27 
29 #include "demo_adapter.h"
30 #include <hpd/hpd_adapter_api.h>
31 #include <hpd/common/hpd_common.h>
33 
37 
38 struct demo_adapter {
39  int num_lamps;
40  const char *module_id;
43 };
44 
46  int state;
48 };
50 
52 static hpd_error_t demo_adapter_on_create(void **data, const hpd_module_t *context);
56 static hpd_error_t demo_adapter_on_parse_opt(void *data, const char *name, const char *arg);
57 
64 };
66 
69 {
70  hpd_error_t rc, rc2;
71 
72  // Allocate response
73  hpd_response_t *res;
74  if ((rc = hpd_response_alloc(&res, req, HPD_S_200))) goto error_return;
75 
76  // Create and set value
77  hpd_value_t *val;
78  if ((rc = hpd_value_allocf(&val, "%i", srv_data->state))) goto error_free_res;
79  if ((rc = hpd_response_set_value(res, val))) goto error_free_val;
80 
81  // Send response
82  if ((rc = hpd_respond(res))) goto error_free_res;
83 
84  return HPD_S_NONE;
85 
86  error_free_val:
87  if ((rc2 = hpd_value_free(val)))
88  HPD_LOG_ERROR(srv_data->demo_adapter->context, "Free function failed [code: %i].", rc2);
89 
90  error_free_res:
91  if ((rc2 = hpd_response_free(res)))
92  HPD_LOG_ERROR(srv_data->demo_adapter->context, "Free function failed [code: %i].", rc2);
93 
94  error_return:
95  HPD_LOG_ERROR(srv_data->demo_adapter->context, "%s() failed [code: %i].", __FUNCTION__, rc);
96  return HPD_S_500;
97 }
99 
102 {
103  hpd_error_t rc;
104 
106  if ((rc = hpd_value_allocf(&value, "%i", srv_data->state))) return rc;
107 
108  if ((rc = hpd_changed(service_id, value))) hpd_value_free(value);
109  return rc;
110 }
112 
115 {
116  hpd_error_t rc;
117 
118  // Get value
119  const hpd_value_t *val;
120  if ((rc = hpd_request_get_value(req, &val))) goto error_return;
121 
122  // Get body from value
123  const char *body;
124  size_t len;
125  if ((rc = hpd_value_get_body(val, &body, &len))) goto error_return;
126 
127  // Get service id
128  const hpd_service_id_t *service_id;
129  if ((rc = hpd_request_get_service(req, &service_id))) goto error_return;
130 
131  // Get new state
132  char *nul_term = NULL;
133  HPD_STR_N_CPY(nul_term, body, len);
134  int state = atoi(nul_term);
135  free(nul_term);
136 
137  if (state != srv_data->state) {
138  srv_data->state = state;
139  if ((rc = demo_adapter_send_changed(service_id, srv_data)))
140  HPD_LOG_ERROR(srv_data->demo_adapter->context, "Failed to send changed value [code: %i].", rc);
141  }
142 
143  return HPD_S_NONE;
144 
145  alloc_error:
146  HPD_LOG_ERROR(srv_data->demo_adapter->context, "%s() failed.", __FUNCTION__);
147  return HPD_S_500;
148 
149  error_return:
150  HPD_LOG_ERROR(srv_data->demo_adapter->context, "%s() failed [code: %i].", __FUNCTION__, rc);
151  return HPD_S_500;
152 }
154 
157 {
158  return demo_adapter_send_value(req, data);
159 }
161 
164 {
165  hpd_status_t status;
166  if ((status = demo_adapter_set_value(req, data)) != HPD_S_NONE) return status;
167  return demo_adapter_send_value(req, data);
168 }
170 
172 static hpd_error_t demo_adapter_on_create(void **data, const hpd_module_t *context)
173 {
174  hpd_error_t rc;
175 
176  // Create struct with custom data
178  HPD_CALLOC(demo_adapter, 1, demo_adapter_t);
179  demo_adapter->num_lamps = 1;
180  demo_adapter->context = context;
181  if ((rc = hpd_module_get_id(context, &demo_adapter->module_id)))
182  goto error_free;
183 
184  // Add supported options
185  if ((rc = hpd_module_add_option(context, "num-lamps", "count", 0, "Number of lamps to create. Default 1.")))
186  goto error_free;
187 
188  *data = demo_adapter;
189  return HPD_E_SUCCESS;
190 
191  alloc_error:
192  HPD_LOG_RETURN_E_ALLOC(context);
193 
194  error_free:
195  free(demo_adapter);
196  return rc;
197 }
199 
202 {
204  free(demo_adapter);
205  return HPD_E_SUCCESS;
206 }
208 
211 {
212  hpd_error_t rc, rc2;
213 
214  // Create id structure to reference our adapter
215  if ((rc = hpd_adapter_id_alloc(&demo_adapter->adapter_id, hpd, demo_adapter->module_id))) goto error_return;
216 
217  // Create adapter structure (using module_id as id)
218  hpd_adapter_t *adapter;
219  if ((rc = hpd_adapter_alloc(&adapter, demo_adapter->module_id))) goto error_free_id;
220  if ((rc = hpd_adapter_set_attr(adapter, HPD_ATTR_TYPE, "demo_adapter"))) goto error_free_adapter;
221  if ((rc = hpd_adapter_attach(hpd, adapter))) goto error_free_adapter;
222 
223  return HPD_E_SUCCESS;
224 
225  error_free_adapter:
226  if ((rc2 = hpd_adapter_free(adapter)))
227  HPD_LOG_ERROR(demo_adapter->context, "Free function failed [code: %i].", rc2);
228 
229  error_free_id:
230  if ((rc2 = hpd_adapter_id_free(demo_adapter->adapter_id)))
231  HPD_LOG_ERROR(demo_adapter->context, "Free function failed [code: %i].", rc2);
232  demo_adapter->adapter_id = NULL;
233 
234  error_return:
235  return rc;
236 }
238 
241 {
242  hpd_error_t rc, rc2;
243 
244  hpd_parameter_t *parameter;
245  if ((rc = hpd_parameter_alloc(&parameter, "param0"))) goto error_return;
246  if ((rc = hpd_parameter_attach(service, parameter))) goto error_free;
247 
248  return HPD_E_SUCCESS;
249 
250  error_free:
251  if ((rc2 = hpd_parameter_free(parameter)))
252  HPD_LOG_ERROR(demo_adapter->context, "Free function failed [code: %i].", rc2);
253 
254  error_return:
255  return rc;
256 }
258 
261 {
262  hpd_error_t rc, rc2;
263 
264  hpd_service_t *service;
265  if ((rc = hpd_service_alloc(&service, "srv0"))) goto error_return;
266  if ((rc = hpd_service_set_actions(service,
269  HPD_M_NONE))) goto error_free_service;
270 
271  demo_adapter_srv_t *srv_data;
272  HPD_CALLOC(srv_data, 1, demo_adapter_srv_t);
273  srv_data->state = 0;
274  srv_data->demo_adapter = demo_adapter;
275  if ((rc = hpd_service_set_data(service, srv_data, free))) goto error_free_data;
276 
277  if ((rc = demo_adapter_create_parameter(demo_adapter, service))) goto error_free_service;
278  if ((rc = hpd_service_attach(device, service))) goto error_free_service;
279 
280  return HPD_E_SUCCESS;
281 
282  alloc_error:
283  if ((rc2 = hpd_service_free(service)))
284  HPD_LOG_ERROR(demo_adapter->context, "Free function failed [code: %i].", rc2);
285  HPD_LOG_RETURN_E_ALLOC(demo_adapter->context);
286 
287  error_free_data:
288  free(srv_data);
289 
290  error_free_service:
291  if ((rc2 = hpd_service_free(service)))
292  HPD_LOG_ERROR(demo_adapter->context, "Free function failed [code: %i].", rc2);
293 
294  error_return:
295  return rc;
296 }
298 
301 {
302  hpd_error_t rc, rc2;
303 
304  hpd_device_t *device;
305  if ((rc = hpd_device_alloc(&device, id))) goto error_return;
306  if ((rc = hpd_device_set_attr(device, HPD_ATTR_TYPE, "demo_lamp"))) goto error_free;
307  if ((rc = demo_adapter_create_service(demo_adapter, device))) goto error_free;
308  if ((rc = hpd_device_attach(demo_adapter->adapter_id, device))) goto error_free;
309 
310  return HPD_E_SUCCESS;
311 
312  error_free:
313  if ((rc2 = hpd_device_free(device)))
314  HPD_LOG_ERROR(demo_adapter->context, "Free function failed [code: %i].", rc2);
315 
316  error_return:
317  return rc;
318 }
320 
323 {
325  hpd_error_t rc, rc2;
326 
327  HPD_LOG_INFO(demo_adapter->context, "Starting with %i lamps...", demo_adapter->num_lamps);
328 
329  if ((rc = demo_adapter_create_adapter(hpd, demo_adapter))) goto error_return;
330 
331  // Create device structures
332  char *id = NULL;
333  for (int i = 0; i < demo_adapter->num_lamps; i++) {
334  HPD_SPRINTF_ALLOC(id, "dev%i", i);
335  if ((rc = demo_adapter_create_lamp(demo_adapter, id))) goto error_free_id;
336  free(id);
337  }
338 
339  return HPD_E_SUCCESS;
340 
341  alloc_error:
342  free(id);
343  if ((rc2 = demo_adapter_on_stop(demo_adapter, hpd)))
344  HPD_LOG_ERROR(demo_adapter->context, "on_stop() failed [code: %i].", rc2);
345  HPD_LOG_RETURN_E_ALLOC(demo_adapter->context);
346 
347  snprintf_error:
348  free(id);
349  if ((rc2 = demo_adapter_on_stop(demo_adapter, hpd)))
350  HPD_LOG_ERROR(demo_adapter->context, "on_stop() failed [code: %i].", rc2);
351  HPD_LOG_RETURN_E_SNPRINTF(demo_adapter->context);
352 
353  error_free_id:
354  free(id);
355  if ((rc2 = demo_adapter_on_stop(demo_adapter, hpd)))
356  HPD_LOG_ERROR(demo_adapter->context, "on_stop() failed [code: %i].", rc2);
357 
358  error_return:
359  return rc;
360 }
362 
365 {
366  hpd_error_t rc, rc2;
367 
369 
370  HPD_LOG_INFO(demo_adapter->context, "Stopping...");
371 
372  // Detach adapter from hpd
373  hpd_adapter_t *adapter;
374  if ((rc = hpd_adapter_detach(demo_adapter->adapter_id, &adapter))) goto error_free_id;
375 
376  // Clean up nicely
377  if ((rc = hpd_adapter_free(adapter))) goto error_free_id;
378  if ((rc = hpd_adapter_id_free(demo_adapter->adapter_id))) goto error_return;
379 
380  return HPD_E_SUCCESS;
381 
382  error_free_id:
383  if ((rc2 = hpd_adapter_id_free(demo_adapter->adapter_id)))
384  HPD_LOG_ERROR(demo_adapter->context, "Free function failed [code: %i].", rc2);
385 
386  error_return:
387  return rc;
388 }
390 
392 static hpd_error_t demo_adapter_on_parse_opt(void *data, const char *name, const char *arg)
393 {
395 
396  if (strcmp(name, "num-lamps") == 0) {
397  demo_adapter->num_lamps = atoi(arg);
398  return HPD_E_SUCCESS;
399  }
400 
401  return HPD_E_ARGUMENT;
402 }
static hpd_status_t demo_adapter_set_value(hpd_request_t *req, demo_adapter_srv_t *srv_data)
[changed]
Definition: demo_adapter.c:114
enum hpd_status hpd_status_t
Definition: hpd_types.h:168
const hpd_module_t * context
Definition: demo_adapter.c:42
hpd_error_t hpd_service_set_actions(hpd_service_t *service,...)
static hpd_error_t demo_adapter_create_adapter(hpd_t *hpd, demo_adapter_t *demo_adapter)
[on_destroy]
Definition: demo_adapter.c:210
static hpd_error_t demo_adapter_on_stop(void *data, hpd_t *hpd)
[on_start]
Definition: demo_adapter.c:364
hpd_error_t hpd_response_alloc(hpd_response_t **response, hpd_request_t *request, hpd_status_t status)
[hpd_request_t functions]
Definition: request_api.c:87
#define HPD_SPRINTF_ALLOC(DST, FMT,...)
Definition: hpd_common.h:75
hpd_error_t hpd_adapter_attach(hpd_t *hpd, hpd_adapter_t *adapter)
static hpd_status_t demo_adapter_send_value(hpd_request_t *req, demo_adapter_srv_t *srv_data)
[definition]
Definition: demo_adapter.c:68
hpd_error_t hpd_parameter_attach(hpd_service_t *service, hpd_parameter_t *parameter)
data value
hpd_error_t hpd_device_free(hpd_device_t *device)
hpd_error_t hpd_module_add_option(const hpd_module_t *context, const char *name, const char *arg, int flags, const char *doc)
[hpd_t functions]
Definition: daemon_api.c:65
hpd_error_t hpd_value_get_body(const hpd_value_t *value, const char **body, size_t *len)
Definition: value_api.c:87
static hpd_status_t demo_adapter_on_put(void *data, hpd_request_t *req)
[on_get]
Definition: demo_adapter.c:163
const char * module_id
Definition: demo_adapter.c:40
hpd_error_t hpd_request_get_service(const hpd_request_t *req, const hpd_service_id_t **id)
[hpd_parameter_t functions]
Definition: request_api.c:69
static hpd_error_t demo_adapter_on_parse_opt(void *data, const char *name, const char *arg)
[on_stop]
Definition: demo_adapter.c:392
static hpd_error_t demo_adapter_on_create(void **data, const hpd_module_t *context)
[types]
Definition: demo_adapter.c:172
free(data.url)
hpd_error_t hpd_parameter_free(hpd_parameter_t *parameter)
hpd_error_t hpd_service_set_data(hpd_service_t *service, void *data, hpd_free_f on_free)
static hpd_error_t demo_adapter_create_parameter(demo_adapter_t *demo_adapter, hpd_service_t *service)
[create_adapter]
Definition: demo_adapter.c:240
struct hpd_module_def hpd_demo_adapter_def
[file]
Definition: demo_adapter.c:58
hpd_error_t hpd_adapter_detach(const hpd_adapter_id_t *id, hpd_adapter_t **adapter)
#define HPD_STR_N_CPY(DST, SRC, LEN)
Definition: hpd_common.h:69
static hpd_error_t demo_adapter_on_destroy(void *data)
[on_create]
Definition: demo_adapter.c:201
hpd_error_t hpd_adapter_id_alloc(hpd_adapter_id_t **id, hpd_t *hpd, const char *aid)
[log functions]
Definition: discovery_api.c:34
hpd_error_t hpd_device_alloc(hpd_device_t **device, const char *id)
[hpd_adapter_t functions]
hpd_error_t hpd_response_set_value(hpd_response_t *response, hpd_value_t *value)
Definition: request_api.c:144
#define HPD_LOG_INFO(CONTEXT, FMT,...)
#define HPD_CALLOC(PTR, NUM, CAST)
Allocates and zeros a structure.
Definition: hpd_common.h:44
demo_adapter_t * demo_adapter
Definition: demo_adapter.c:47
hpd_error_t hpd_module_get_id(const hpd_module_t *context, const char **id)
Definition: daemon_api.c:79
hpd_error_t hpd_adapter_alloc(hpd_adapter_t **adapter, const char *id)
[hpd_adapter_t functions]
Definition: comm.h:70
static hpd_error_t demo_adapter_on_start(void *data, hpd_t *hpd)
[create_lamp]
Definition: demo_adapter.c:322
hpd_error_t hpd_device_attach(const hpd_adapter_id_t *id, hpd_device_t *device)
enum hpd_error hpd_error_t
Definition: hpd_types.h:167
#define HPD_LOG_RETURN_E_ALLOC(CONTEXT)
hpd_error_t hpd_service_free(hpd_service_t *service)
static hpd_error_t demo_adapter_create_service(demo_adapter_t *demo_adapter, hpd_device_t *device)
[create_parameter]
Definition: demo_adapter.c:260
[Application API Callbacks]
Definition: hpd_types.h:200
#define HPD_LOG_RETURN_E_SNPRINTF(CONTEXT)
hpd_adapter_id_t * adapter_id
Definition: demo_adapter.c:41
hpd_error_t hpd_respond(hpd_response_t *response)
Definition: request_api.c:150
hpd_error_t hpd_device_set_attr(hpd_device_t *device, const char *key, const char *val)
static hpd_error_t demo_adapter_send_changed(const hpd_service_id_t *service_id, demo_adapter_srv_t *srv_data)
[send]
Definition: demo_adapter.c:101
struct data data
Definition: daemon.h:50
hpd_error_t hpd_value_free(hpd_value_t *value)
Definition: value_api.c:62
static const char *const HPD_ATTR_TYPE
Default attribute key for types.
Definition: hpd_types.h:266
state
The possible states of a request.
Definition: httpd_request.c:37
static hpd_error_t demo_adapter_create_lamp(demo_adapter_t *demo_adapter, const char *id)
[create_service]
Definition: demo_adapter.c:300
hpd_error_t hpd_adapter_id_free(hpd_adapter_id_t *id)
Definition: discovery_api.c:46
hpd_error_t hpd_adapter_free(hpd_adapter_t *adapter)
static hpd_status_t demo_adapter_on_get(void *data, hpd_request_t *req)
[set]
Definition: demo_adapter.c:156
hpd_error_t hpd_service_alloc(hpd_service_t **service, const char *id)
[hpd_device_t functions]
hpd_error_t hpd_service_attach(hpd_device_t *device, hpd_service_t *service)
hpd_error_t hpd_adapter_set_attr(hpd_adapter_t *adapter, const char *key, const char *val)
hpd_error_t hpd_value_allocf(hpd_value_t **value, const char *fmt,...)
Definition: value_api.c:41
hpd_error_t hpd_response_free(hpd_response_t *response)
Definition: request_api.c:138
hpd_error_t hpd_request_get_value(const hpd_request_t *req, const hpd_value_t **value)
Definition: request_api.c:81
#define HPD_LOG_ERROR(CONTEXT, FMT,...)
hpd_error_t hpd_parameter_alloc(hpd_parameter_t **parameter, const char *id)
[hpd_service_t functions]
hpd_error_t hpd_changed(const hpd_service_id_t *id, hpd_value_t *val)
[hpd_response_t functions]
Definition: event_api.c:35