OVMS3-idf/examples/protocols/coap_server/main/coap_server_example_main.c
2019-03-18 12:33:52 +00:00

230 lines
7.1 KiB
C

/* 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 <string.h>
#include <sys/socket.h>
#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 "coap.h"
/* 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
/* Set this to 9 to get verbose logging from within libcoap */
#define COAP_LOGGING_LEVEL 0
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_server";
static char espressif_data[100];
static int espressif_data_len = 0;
/*
* The resource handler
*/
static void
hnd_espressif_get(coap_context_t *ctx, coap_resource_t *resource,
coap_session_t *session,
coap_pdu_t *request, coap_binary_t *token,
coap_string_t *query, coap_pdu_t *response)
{
coap_add_data_blocked_response(resource, session, request, response, token,
COAP_MEDIATYPE_TEXT_PLAIN, 0,
(size_t)espressif_data_len,
(const u_char *)espressif_data);
}
static void
hnd_espressif_put(coap_context_t *ctx,
coap_resource_t *resource,
coap_session_t *session,
coap_pdu_t *request,
coap_binary_t *token,
coap_string_t *query,
coap_pdu_t *response)
{
size_t size;
unsigned char *data;
coap_resource_notify_observers(resource, NULL);
if (strcmp (espressif_data, "no data") == 0) {
response->code = COAP_RESPONSE_CODE(201);
}
else {
response->code = COAP_RESPONSE_CODE(204);
}
/* coap_get_data() sets size to 0 on error */
(void)coap_get_data(request, &size, &data);
if (size == 0) { /* re-init */
snprintf(espressif_data, sizeof(espressif_data), "no data");
espressif_data_len = strlen(espressif_data);
} else {
espressif_data_len = size > sizeof (espressif_data) ? sizeof (espressif_data) : size;
memcpy (espressif_data, data, espressif_data_len);
}
}
static void
hnd_espressif_delete(coap_context_t *ctx,
coap_resource_t *resource,
coap_session_t *session,
coap_pdu_t *request,
coap_binary_t *token,
coap_string_t *query,
coap_pdu_t *response)
{
coap_resource_notify_observers(resource, NULL);
snprintf(espressif_data, sizeof(espressif_data), "no data");
espressif_data_len = strlen(espressif_data);
response->code = COAP_RESPONSE_CODE(202);
}
static void coap_example_thread(void *p)
{
coap_context_t *ctx = NULL;
coap_address_t serv_addr;
coap_resource_t *resource = NULL;
snprintf(espressif_data, sizeof(espressif_data), "no data");
espressif_data_len = strlen(espressif_data);
coap_set_log_level(COAP_LOGGING_LEVEL);
while (1) {
coap_endpoint_t *ep_udp = NULL;
coap_endpoint_t *ep_tcp = NULL;
unsigned wait_ms;
/* Wait for the callback to set the CONNECTED_BIT in the
event group.
*/
xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
false, true, portMAX_DELAY);
ESP_LOGI(TAG, "Connected to AP");
/* 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(NULL);
if (!ctx) {
continue;
}
ep_udp = coap_new_endpoint(ctx, &serv_addr, COAP_PROTO_UDP);
if (!ep_udp) {
goto clean_up;
}
ep_tcp = coap_new_endpoint(ctx, &serv_addr, COAP_PROTO_TCP);
if (!ep_tcp) {
goto clean_up;
}
resource = coap_resource_init(coap_make_str_const("Espressif"), 0);
if (!resource) {
goto clean_up;
}
coap_register_handler(resource, COAP_REQUEST_GET, hnd_espressif_get);
coap_register_handler(resource, COAP_REQUEST_PUT, hnd_espressif_put);
coap_register_handler(resource, COAP_REQUEST_DELETE, hnd_espressif_delete);
/* We possibly want to Observe the GETs */
coap_resource_set_get_observable(resource, 1);
coap_add_resource(ctx, resource);
wait_ms = COAP_RESOURCE_CHECK_TIME * 1000;
while (1) {
int result = coap_run_once(ctx, wait_ms);
if (result < 0) {
break;
} else if (result && (unsigned)result < wait_ms) {
/* decrement if there is a result wait time returned */
wait_ms -= result;
}
if (result) {
/* result must have been >= wait_ms, so reset wait_ms */
wait_ms = COAP_RESOURCE_CHECK_TIME * 1000;
}
}
}
clean_up:
coap_free_context(ctx);
coap_cleanup();
vTaskDelete(NULL);
}
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);
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)
{
ESP_ERROR_CHECK( nvs_flash_init() );
wifi_conn_init();
xTaskCreate(coap_example_thread, "coap", 1024 * 5, NULL, 5, NULL);
}