From 899f61f4a2496bb261e388a28b7d3d6e232b2832 Mon Sep 17 00:00:00 2001 From: Liu Han Date: Sat, 10 Dec 2016 13:48:38 +0800 Subject: [PATCH] examples: Add CoAP server demo Test CoAP protocol server --- examples/24_coap_server/Makefile | 9 + .../24_coap_server/main/Kconfig.projbuild | 22 ++ examples/24_coap_server/main/coap_server.c | 190 ++++++++++++++++++ examples/24_coap_server/main/coap_server.h | 38 ++++ examples/24_coap_server/main/component.mk | 5 + 5 files changed, 264 insertions(+) create mode 100644 examples/24_coap_server/Makefile create mode 100644 examples/24_coap_server/main/Kconfig.projbuild create mode 100644 examples/24_coap_server/main/coap_server.c create mode 100644 examples/24_coap_server/main/coap_server.h create mode 100644 examples/24_coap_server/main/component.mk diff --git a/examples/24_coap_server/Makefile b/examples/24_coap_server/Makefile new file mode 100644 index 0000000000..f82e5fc278 --- /dev/null +++ b/examples/24_coap_server/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := coap_server + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/24_coap_server/main/Kconfig.projbuild b/examples/24_coap_server/main/Kconfig.projbuild new file mode 100644 index 0000000000..4926bfb200 --- /dev/null +++ b/examples/24_coap_server/main/Kconfig.projbuild @@ -0,0 +1,22 @@ +menu "Example Configuration" + +config LOCAL_PORT_NUMBER + int "Local port number" + range 0 65535 + default 5683 + help + Local port number for the example to use. + +config WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. + +config WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. + +endmenu \ No newline at end of file diff --git a/examples/24_coap_server/main/coap_server.c b/examples/24_coap_server/main/coap_server.c new file mode 100644 index 0000000000..4e066689bb --- /dev/null +++ b/examples/24_coap_server/main/coap_server.c @@ -0,0 +1,190 @@ +/* CoAP server Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include "coap_server.h" + +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" + +#include "esp_log.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" + +#include "nvs_flash.h" +#include + +#include "coap_config.h" +#include "resource.h" +#include "coap.h" + + +static EventGroupHandle_t wifi_event_group; + +/* The event group allows multiple bits for each event, + but we only care about one event - are we connected + to the AP with an IP? */ +const static int CONNECTED_BIT = BIT0; + +const static char *TAG = "CoAP_demo"; + +static coap_async_state_t *async = NULL; + +static void +send_async_response(coap_context_t *ctx, const coap_endpoint_t *local_if) +{ + coap_pdu_t *response; + unsigned char buf[3]; + const char* response_data = "Hello World!"; + size_t size = sizeof(coap_hdr_t) + 20; + response = coap_pdu_init(async->flags & COAP_MESSAGE_CON, COAP_RESPONSE_CODE(205), 0, size); + response->hdr->id = coap_new_message_id(ctx); + if (async->tokenlen) + coap_add_token(response, async->tokenlen, async->token); + coap_add_option(response, COAP_OPTION_CONTENT_TYPE, coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf); + coap_add_data (response, strlen(response_data), (unsigned char *)response_data); + + if (coap_send(ctx, local_if, &async->peer, response) == COAP_INVALID_TID) { + + } + coap_delete_pdu(response); + coap_async_state_t *tmp; + coap_remove_async(ctx, async->id, &tmp); + coap_free_async(async); + async = NULL; +} + +/* + * The resource handler + */ +static void +async_handler(coap_context_t *ctx, struct coap_resource_t *resource, + const coap_endpoint_t *local_interface, coap_address_t *peer, + coap_pdu_t *request, str *token, coap_pdu_t *response) +{ + async = coap_register_async(ctx, peer, request, COAP_ASYNC_SEPARATE | COAP_ASYNC_CONFIRM, (void*)"no data"); +} + +static void coap_demo_thread(void *p) +{ + coap_context_t* ctx = NULL; + coap_address_t serv_addr; + coap_resource_t* resource = NULL; + fd_set readfds; + struct timeval tv; + int flags = 0; + /* Prepare the CoAP server socket */ + coap_address_init(&serv_addr); + serv_addr.addr.sin.sin_family = AF_INET; + serv_addr.addr.sin.sin_addr.s_addr = INADDR_ANY; + serv_addr.addr.sin.sin_port = htons(COAP_DEFAULT_PORT); + ctx = coap_new_context(&serv_addr); + if (ctx) { + flags = fcntl(ctx->sockfd, F_GETFL, 0); + fcntl(ctx->sockfd, F_SETFL, flags|O_NONBLOCK); + + tv.tv_usec = COAP_DEFAULT_TIME_USEC; + tv.tv_sec = COAP_DEFAULT_TIME_SEC; + /* Initialize the resource */ + resource = coap_resource_init((unsigned char *)"Espressif", 9, 0); + if (resource){ + coap_register_handler(resource, COAP_REQUEST_GET, async_handler); + coap_add_resource(ctx, resource); + /*For incoming connections*/ + for (;;) { + FD_ZERO(&readfds); + FD_CLR( ctx->sockfd, &readfds); + FD_SET( ctx->sockfd, &readfds); + + int result = select( FD_SETSIZE, &readfds, 0, 0, &tv ); + if (result > 0){ + if (FD_ISSET( ctx->sockfd, &readfds )) + coap_read(ctx); + } else if (result < 0){ + break; + } else { + printf("select timeout\n"); + } + + if (async) + send_async_response(ctx, ctx->endpoint); + } + } + + coap_free_context(ctx); + } + + vTaskDelete(NULL); +} + +static void coap_server_init(void) +{ + int ret = pdPASS; + xTaskHandle coap_handle = NULL; + + ret = xTaskCreate(coap_demo_thread, + COAP_DEMO_THREAD_NAME, + COAP_DEMO_THREAD_STACK_WORDS, + NULL, + COAP_DEMO_THREAD_PRORIOTY, + &coap_handle); + + if (ret != pdPASS) { + ESP_LOGI(TAG, "create thread %s failed", COAP_DEMO_THREAD_NAME); + } +} + +static esp_err_t wifi_event_handler(void *ctx, system_event_t *event) +{ + switch(event->event_id) { + case SYSTEM_EVENT_STA_START: + esp_wifi_connect(); + break; + case SYSTEM_EVENT_STA_GOT_IP: + xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); + coap_server_init(); + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + /* This is a workaround as ESP32 WiFi libs don't currently + auto-reassociate. */ + esp_wifi_connect(); + xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); + break; + default: + break; + } + return ESP_OK; +} + +static void wifi_conn_init(void) +{ + tcpip_adapter_init(); + wifi_event_group = xEventGroupCreate(); + ESP_ERROR_CHECK( esp_event_loop_init(wifi_event_handler, NULL) ); + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); + ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); + wifi_config_t wifi_config = { + .sta = { + .ssid = EXAMPLE_WIFI_SSID, + .password = EXAMPLE_WIFI_PASS, + }, + }; + ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); + ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); + + ESP_ERROR_CHECK( esp_wifi_start() ); +} + +void app_main(void) +{ + nvs_flash_init(); + wifi_conn_init(); +} diff --git a/examples/24_coap_server/main/coap_server.h b/examples/24_coap_server/main/coap_server.h new file mode 100644 index 0000000000..e9e8728fc3 --- /dev/null +++ b/examples/24_coap_server/main/coap_server.h @@ -0,0 +1,38 @@ +/* CoAP server Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#ifndef _COAP_SERVER_H_ +#define _COAP_SERVER_H_ + +#include + +/* The examples use simple WiFi configuration that you can set via + 'make menuconfig'. + + If you'd rather not, just change the below entries to strings with + the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" +*/ +#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID +#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD + +#define COAP_DEMO_THREAD_NAME "CoAP_demo" +#define COAP_DEMO_THREAD_STACK_WORDS 10240 +#define COAP_DEMO_THREAD_PRORIOTY 8 + +/* The examples use local port number of 5683 that you can set via 'make menuconfig'. + + If you'd rather not, just change the below entries to strings with + the config you want - ie #define OPENSSL_DEMO_TARGET_TCP_PORT 5683 +*/ +#define COAP_DEFAULT_PORT CONFIG_LOCAL_PORT_NUMBER +#define COAP_DEFAULT_TIME_SEC 5 +#define COAP_DEFAULT_TIME_USEC 0 + +#endif + diff --git a/examples/24_coap_server/main/component.mk b/examples/24_coap_server/main/component.mk new file mode 100644 index 0000000000..0b9d7585e7 --- /dev/null +++ b/examples/24_coap_server/main/component.mk @@ -0,0 +1,5 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) + -- 2.40.0