mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-18 12:52:44 +01:00
252 lines
6.1 KiB
C
252 lines
6.1 KiB
C
|
/*
|
||
|
* Copyright (C) 2016 CREATE-NET
|
||
|
*
|
||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||
|
* directory for more details.
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @ingroup Examples
|
||
|
* @{
|
||
|
*
|
||
|
* @file client_switch.c
|
||
|
* @brief This is an Iotivity client. It sends a PUT when the
|
||
|
* User button is pressed.
|
||
|
*
|
||
|
* @author Mattia Antonini <mattia.antonini1@studenti.unipr.it>
|
||
|
* <m.antonini@create-net.org>
|
||
|
*
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
#include "oc_api.h"
|
||
|
#include "pthread_cond.h"
|
||
|
#include "thread.h"
|
||
|
#include "xtimer.h"
|
||
|
#include "periph/gpio.h"
|
||
|
|
||
|
#define MAX_URI_LENGTH (30)
|
||
|
|
||
|
static void observe_light(oc_client_response_t *data);
|
||
|
extern int _netif_config(int argc, char **argv);
|
||
|
|
||
|
static int quit;
|
||
|
static mutex_t mutex;
|
||
|
static pthread_cond_t cv;
|
||
|
static struct timespec ts;
|
||
|
static bool got_discovery_response = false;
|
||
|
static char light_1[MAX_URI_LENGTH];
|
||
|
static oc_server_handle_t light_server;
|
||
|
static bool light_state = false;
|
||
|
static bool led_state = false;
|
||
|
|
||
|
static char _oc_main_stack[THREAD_STACKSIZE_MAIN];
|
||
|
|
||
|
static void
|
||
|
set_led_state(bool led_state)
|
||
|
{
|
||
|
if (led_state) {
|
||
|
LED0_ON;
|
||
|
}
|
||
|
else {
|
||
|
LED0_OFF;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
set_device_custom_property(void *data)
|
||
|
{
|
||
|
oc_set_custom_device_property(purpose, "operate lamp");
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
app_init(void)
|
||
|
{
|
||
|
oc_init_platform("RIOT-OS", NULL, NULL);
|
||
|
oc_add_device("/oic/d", "oic.d.switch", "RIOT switch", "1.0", "1.0",
|
||
|
set_device_custom_property, NULL);
|
||
|
}
|
||
|
|
||
|
static oc_event_callback_retval_t
|
||
|
stop_observe(void *data)
|
||
|
{
|
||
|
PRINT("client_oic: Stopping OBSERVE\n");
|
||
|
oc_stop_observe(light_1, &light_server);
|
||
|
return DONE;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
put_light(oc_client_response_t *data)
|
||
|
{
|
||
|
PRINT("client_oic: PUT_light:\n");
|
||
|
if (data->code == OC_STATUS_CHANGED) {
|
||
|
PRINT("client_oic: PUT response OK\n");
|
||
|
}
|
||
|
else {
|
||
|
PRINT("client_oic: PUT response code %d\n", data->code);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
observe_light(oc_client_response_t *data)
|
||
|
{
|
||
|
PRINT("client_oic: OBSERVE_light: ");
|
||
|
oc_rep_t *rep = data->payload;
|
||
|
while (rep != NULL) {
|
||
|
PRINT("key %s, value ", oc_string(rep->name));
|
||
|
switch (rep->type) {
|
||
|
case BOOL:
|
||
|
PRINT("%d\n", rep->value_boolean);
|
||
|
light_state = rep->value_boolean;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
rep = rep->next;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static oc_discovery_flags_t
|
||
|
discovery(const char *di, const char *uri, oc_string_array_t types,
|
||
|
oc_interface_mask_t interfaces, oc_server_handle_t *server,
|
||
|
void *user_data)
|
||
|
{
|
||
|
int i;
|
||
|
int uri_len = strlen(uri);
|
||
|
|
||
|
uri_len = (uri_len >= MAX_URI_LENGTH) ? MAX_URI_LENGTH - 1 : uri_len;
|
||
|
|
||
|
for (i = 0; i < oc_string_array_get_allocated_size(types); i++) {
|
||
|
char *t = oc_string_array_get_item(types, i);
|
||
|
if (strlen(t) == 11 && strncmp(t, "oic.r.light", 11) == 0) {
|
||
|
memcpy(&light_server, server, sizeof(oc_server_handle_t));
|
||
|
|
||
|
strncpy(light_1, uri, uri_len);
|
||
|
light_1[uri_len] = '\0';
|
||
|
|
||
|
got_discovery_response = true;
|
||
|
|
||
|
return OC_STOP_DISCOVERY;
|
||
|
}
|
||
|
}
|
||
|
return OC_CONTINUE_DISCOVERY;
|
||
|
}
|
||
|
|
||
|
#ifdef BUTTON_GPIO
|
||
|
void button_callback(void)
|
||
|
{
|
||
|
gpio_irq_disable(BUTTON_GPIO);
|
||
|
if (oc_init_put(light_1, &light_server, NULL, &put_light, HIGH_QOS, NULL)) {
|
||
|
oc_rep_start_root_object();
|
||
|
oc_rep_set_boolean(root, state, !light_state);
|
||
|
oc_rep_end_root_object();
|
||
|
if (oc_do_put()) {
|
||
|
PRINT("client_oic: Sent PUT request\n");
|
||
|
}
|
||
|
else {
|
||
|
PRINT("client_oic: Could not send PUT\n");
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
PRINT("client_oic: Could not init PUT\n");
|
||
|
}
|
||
|
xtimer_usleep(140000);
|
||
|
gpio_irq_enable(BUTTON_GPIO);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
static oc_event_callback_retval_t
|
||
|
operate(void *data)
|
||
|
{
|
||
|
PRINT("client_oic: Ready...\n");
|
||
|
set_led_state(true);
|
||
|
oc_do_observe(light_1, &light_server, NULL, &observe_light, LOW_QOS, NULL);
|
||
|
#ifdef BUTTON_GPIO
|
||
|
gpio_init_int(BUTTON_GPIO, GPIO_IN_PU, GPIO_RISING, (gpio_cb_t)button_callback, NULL);
|
||
|
#endif
|
||
|
oc_set_delayed_callback(NULL, &stop_observe, 10000);
|
||
|
return DONE;
|
||
|
}
|
||
|
|
||
|
static oc_event_callback_retval_t
|
||
|
do_discovery(void *data)
|
||
|
{
|
||
|
if (got_discovery_response) {
|
||
|
PRINT("client_oic: Discovery done\n");
|
||
|
oc_set_delayed_callback(NULL, &operate, 1);
|
||
|
return DONE;
|
||
|
}
|
||
|
oc_do_ip_discovery("oic.r.light", &discovery, NULL);
|
||
|
PRINT("client_oic: continue discovery\n");
|
||
|
return CONTINUE;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
issue_requests(void)
|
||
|
{
|
||
|
oc_set_delayed_callback(NULL, &do_discovery, 1);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
signal_event_loop_func(void)
|
||
|
{
|
||
|
mutex_lock(&mutex);
|
||
|
pthread_cond_signal(&cv);
|
||
|
mutex_unlock(&mutex);
|
||
|
}
|
||
|
|
||
|
void *
|
||
|
oc_main_thread(void *arg)
|
||
|
{
|
||
|
(void)arg;
|
||
|
|
||
|
pthread_cond_init(&cv, NULL);
|
||
|
|
||
|
static const oc_handler_t handler = { .init = app_init,
|
||
|
.signal_event_loop = signal_event_loop_func,
|
||
|
.requests_entry = issue_requests };
|
||
|
if (oc_main_init(&handler) < 0) {
|
||
|
PRINT("client_oic: failed to initialize stack\n");
|
||
|
return NULL;
|
||
|
}
|
||
|
PRINT("client_oic: Configured network interfaces:");
|
||
|
_netif_config(0, NULL);
|
||
|
|
||
|
oc_clock_time_t next_event;
|
||
|
while (quit == 0) {
|
||
|
next_event = oc_main_poll();
|
||
|
mutex_lock(&mutex);
|
||
|
if (next_event == 0) {
|
||
|
pthread_cond_wait(&cv, &mutex);
|
||
|
}
|
||
|
else if (oc_clock_time() < next_event) {
|
||
|
ts.tv_sec = (next_event / OC_CLOCK_SECOND);
|
||
|
ts.tv_nsec = (next_event % OC_CLOCK_SECOND) * 1.e09 / OC_CLOCK_SECOND;
|
||
|
pthread_cond_timedwait(&cv, &mutex, &ts);
|
||
|
}
|
||
|
mutex_unlock(&mutex);
|
||
|
}
|
||
|
|
||
|
oc_main_shutdown();
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
main(void)
|
||
|
{
|
||
|
set_led_state(led_state);
|
||
|
PRINT("client_oic: Waiting for address autoconfiguration...");
|
||
|
xtimer_sleep(10);
|
||
|
thread_create(_oc_main_stack, sizeof(_oc_main_stack), 2, 0, oc_main_thread,
|
||
|
NULL, "OCF event thread");
|
||
|
|
||
|
fgetc(stdin);
|
||
|
|
||
|
quit = 1;
|
||
|
signal_event_loop_func();
|
||
|
|
||
|
return 0;
|
||
|
}
|