mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/CoAP' into 'master'
Add CoAP feature Add CoAP protocol, support client and server test demo. See merge request !303
This commit is contained in:
commit
c943fabcda
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -10,3 +10,6 @@
|
|||||||
[submodule "components/micro-ecc/micro-ecc"]
|
[submodule "components/micro-ecc/micro-ecc"]
|
||||||
path = components/micro-ecc/micro-ecc
|
path = components/micro-ecc/micro-ecc
|
||||||
url = https://github.com/kmackay/micro-ecc.git
|
url = https://github.com/kmackay/micro-ecc.git
|
||||||
|
[submodule "components/coap/libcoap"]
|
||||||
|
path = components/coap/libcoap
|
||||||
|
url = https://github.com/obgm/libcoap.git
|
||||||
|
1
components/coap/Makefile.projbuild
Normal file
1
components/coap/Makefile.projbuild
Normal file
@ -0,0 +1 @@
|
|||||||
|
CFLAGS += -DWITH_POSIX
|
9
components/coap/component.mk
Normal file
9
components/coap/component.mk
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#
|
||||||
|
# Component Makefile
|
||||||
|
#
|
||||||
|
|
||||||
|
COMPONENT_ADD_INCLUDEDIRS := port/include port/include/coap libcoap/include libcoap/include/coap
|
||||||
|
|
||||||
|
COMPONENT_OBJS = libcoap/src/address.o libcoap/src/async.o libcoap/src/block.o libcoap/src/coap_time.o libcoap/src/debug.o libcoap/src/encode.o libcoap/src/hashkey.o libcoap/src/mem.o libcoap/src/net.o libcoap/src/option.o libcoap/src/pdu.o libcoap/src/resource.o libcoap/src/str.o libcoap/src/subscribe.o libcoap/src/uri.o port/coap_io_socket.o
|
||||||
|
|
||||||
|
COMPONENT_SRCDIRS := libcoap/src libcoap port
|
1
components/coap/libcoap
Submodule
1
components/coap/libcoap
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 6468887a12666f88b8704d797fc176cd4f40ee4c
|
468
components/coap/port/coap_io_socket.c
Normal file
468
components/coap/port/coap_io_socket.c
Normal file
@ -0,0 +1,468 @@
|
|||||||
|
/*
|
||||||
|
* Network function implementation with socket for ESP32 platform.
|
||||||
|
*
|
||||||
|
* Uses libcoap software implementation for failover when concurrent
|
||||||
|
* network operations are in use.
|
||||||
|
*
|
||||||
|
* coap_io.h -- Default network I/O functions for libcoap
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012,2014 Olaf Bergmann <bergmann@tzi.org>
|
||||||
|
*
|
||||||
|
* Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
*
|
||||||
|
* This file is part of the CoAP library libcoap. Please see
|
||||||
|
* README for terms of use.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "coap_config.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_STDIO_H
|
||||||
|
# include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_SELECT_H
|
||||||
|
# include <sys/select.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
# include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
|
# include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_UIO_H
|
||||||
|
# include <sys/uio.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifdef WITH_CONTIKI
|
||||||
|
# include "uip.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "pdu.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "mem.h"
|
||||||
|
#include "coap_io.h"
|
||||||
|
|
||||||
|
#ifdef WITH_POSIX
|
||||||
|
/* define generic PKTINFO for IPv4 */
|
||||||
|
#if defined(IP_PKTINFO)
|
||||||
|
# define GEN_IP_PKTINFO IP_PKTINFO
|
||||||
|
#elif defined(IP_RECVDSTADDR)
|
||||||
|
# define GEN_IP_PKTINFO IP_RECVDSTADDR
|
||||||
|
#else
|
||||||
|
# error "Need IP_PKTINFO or IP_RECVDSTADDR to request ancillary data from OS."
|
||||||
|
#endif /* IP_PKTINFO */
|
||||||
|
|
||||||
|
/* define generic KTINFO for IPv6 */
|
||||||
|
#ifdef IPV6_RECVPKTINFO
|
||||||
|
# define GEN_IPV6_PKTINFO IPV6_RECVPKTINFO
|
||||||
|
#elif defined(IPV6_PKTINFO)
|
||||||
|
# define GEN_IPV6_PKTINFO IPV6_PKTINFO
|
||||||
|
#else
|
||||||
|
# error "Need IPV6_PKTINFO or IPV6_RECVPKTINFO to request ancillary data from OS."
|
||||||
|
#endif /* IPV6_RECVPKTINFO */
|
||||||
|
|
||||||
|
struct coap_packet_t {
|
||||||
|
coap_if_handle_t hnd; /**< the interface handle */
|
||||||
|
coap_address_t src; /**< the packet's source address */
|
||||||
|
coap_address_t dst; /**< the packet's destination address */
|
||||||
|
const coap_endpoint_t *interface;
|
||||||
|
|
||||||
|
int ifindex;
|
||||||
|
void *session; /**< opaque session data */
|
||||||
|
|
||||||
|
size_t length; /**< length of payload */
|
||||||
|
unsigned char payload[]; /**< payload */
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CUSTOM_COAP_NETWORK_ENDPOINT
|
||||||
|
|
||||||
|
#ifdef WITH_CONTIKI
|
||||||
|
static int ep_initialized = 0;
|
||||||
|
|
||||||
|
static inline struct coap_endpoint_t *
|
||||||
|
coap_malloc_contiki_endpoint() {
|
||||||
|
static struct coap_endpoint_t ep;
|
||||||
|
|
||||||
|
if (ep_initialized) {
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
ep_initialized = 1;
|
||||||
|
return &ep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
coap_free_contiki_endpoint(struct coap_endpoint_t *ep) {
|
||||||
|
ep_initialized = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
coap_endpoint_t *
|
||||||
|
coap_new_endpoint(const coap_address_t *addr, int flags) {
|
||||||
|
struct coap_endpoint_t *ep = coap_malloc_contiki_endpoint();
|
||||||
|
|
||||||
|
if (ep) {
|
||||||
|
memset(ep, 0, sizeof(struct coap_endpoint_t));
|
||||||
|
ep->handle.conn = udp_new(NULL, 0, NULL);
|
||||||
|
|
||||||
|
if (!ep->handle.conn) {
|
||||||
|
coap_free_endpoint(ep);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
coap_address_init(&ep->addr);
|
||||||
|
uip_ipaddr_copy(&ep->addr.addr, &addr->addr);
|
||||||
|
ep->addr.port = addr->port;
|
||||||
|
udp_bind((struct uip_udp_conn *)ep->handle.conn, addr->port);
|
||||||
|
}
|
||||||
|
return ep;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
coap_free_endpoint(coap_endpoint_t *ep) {
|
||||||
|
if (ep) {
|
||||||
|
if (ep->handle.conn) {
|
||||||
|
uip_udp_remove((struct uip_udp_conn *)ep->handle.conn);
|
||||||
|
}
|
||||||
|
coap_free_contiki_endpoint(ep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* WITH_CONTIKI */
|
||||||
|
static inline struct coap_endpoint_t *
|
||||||
|
coap_malloc_posix_endpoint(void) {
|
||||||
|
return (struct coap_endpoint_t *)coap_malloc(sizeof(struct coap_endpoint_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
coap_free_posix_endpoint(struct coap_endpoint_t *ep) {
|
||||||
|
coap_free(ep);
|
||||||
|
}
|
||||||
|
|
||||||
|
coap_endpoint_t *
|
||||||
|
coap_new_endpoint(const coap_address_t *addr, int flags) {
|
||||||
|
int sockfd = socket(addr->addr.sa.sa_family, SOCK_DGRAM, 0);
|
||||||
|
int on = 1;
|
||||||
|
struct coap_endpoint_t *ep;
|
||||||
|
|
||||||
|
if (sockfd < 0) {
|
||||||
|
coap_log(LOG_WARNING, "coap_new_endpoint: socket");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
|
||||||
|
coap_log(LOG_WARNING, "coap_new_endpoint: setsockopt SO_REUSEADDR");
|
||||||
|
|
||||||
|
if (bind(sockfd, &addr->addr.sa, addr->size) < 0) {
|
||||||
|
coap_log(LOG_WARNING, "coap_new_endpoint: bind");
|
||||||
|
close (sockfd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ep = coap_malloc_posix_endpoint();
|
||||||
|
if (!ep) {
|
||||||
|
coap_log(LOG_WARNING, "coap_new_endpoint: malloc");
|
||||||
|
close(sockfd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(ep, 0, sizeof(struct coap_endpoint_t));
|
||||||
|
ep->handle.fd = sockfd;
|
||||||
|
ep->flags = flags;
|
||||||
|
|
||||||
|
ep->addr.size = addr->size;
|
||||||
|
if (getsockname(sockfd, &ep->addr.addr.sa, &ep->addr.size) < 0) {
|
||||||
|
coap_log(LOG_WARNING, "coap_new_endpoint: cannot determine local address");
|
||||||
|
close (sockfd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
if (LOG_DEBUG <= coap_get_log_level()) {
|
||||||
|
#ifndef INET6_ADDRSTRLEN
|
||||||
|
#define INET6_ADDRSTRLEN 40
|
||||||
|
#endif
|
||||||
|
unsigned char addr_str[INET6_ADDRSTRLEN+8];
|
||||||
|
|
||||||
|
if (coap_print_addr(&ep->addr, addr_str, INET6_ADDRSTRLEN+8)) {
|
||||||
|
debug("created %sendpoint %s\n",
|
||||||
|
ep->flags & COAP_ENDPOINT_DTLS ? "DTLS " : "",
|
||||||
|
addr_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* NDEBUG */
|
||||||
|
|
||||||
|
return (coap_endpoint_t *)ep;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
coap_free_endpoint(coap_endpoint_t *ep) {
|
||||||
|
if(ep) {
|
||||||
|
if (ep->handle.fd >= 0)
|
||||||
|
close(ep->handle.fd);
|
||||||
|
coap_free_posix_endpoint((struct coap_endpoint_t *)ep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WITH_CONTIKI */
|
||||||
|
#endif /* CUSTOM_COAP_NETWORK_ENDPOINT */
|
||||||
|
|
||||||
|
#ifdef CUSTOM_COAP_NETWORK_SEND
|
||||||
|
|
||||||
|
#if defined(WITH_POSIX) != defined(HAVE_NETINET_IN_H)
|
||||||
|
/* define struct in6_pktinfo and struct in_pktinfo if not available
|
||||||
|
FIXME: check with configure
|
||||||
|
*/
|
||||||
|
struct in6_pktinfo {
|
||||||
|
struct in6_addr ipi6_addr; /* src/dst IPv6 address */
|
||||||
|
unsigned int ipi6_ifindex; /* send/recv interface index */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct in_pktinfo {
|
||||||
|
int ipi_ifindex;
|
||||||
|
struct in_addr ipi_spec_dst;
|
||||||
|
struct in_addr ipi_addr;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WITH_POSIX) && !defined(SOL_IP)
|
||||||
|
/* Solaris expects level IPPROTO_IP for ancillary data. */
|
||||||
|
#define SOL_IP IPPROTO_IP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define UNUSED_PARAM __attribute__ ((unused))
|
||||||
|
#else /* not a GCC */
|
||||||
|
#define UNUSED_PARAM
|
||||||
|
#endif /* GCC */
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
coap_network_send(struct coap_context_t *context UNUSED_PARAM,
|
||||||
|
const coap_endpoint_t *local_interface,
|
||||||
|
const coap_address_t *dst,
|
||||||
|
unsigned char *data,
|
||||||
|
size_t datalen) {
|
||||||
|
|
||||||
|
struct coap_endpoint_t *ep =
|
||||||
|
(struct coap_endpoint_t *)local_interface;
|
||||||
|
|
||||||
|
#ifndef WITH_CONTIKI
|
||||||
|
return sendto(ep->handle.fd, data, datalen, 0, (struct sockaddr*)&dst->addr.sa, sizeof(struct sockaddr));
|
||||||
|
#else /* WITH_CONTIKI */
|
||||||
|
/* FIXME: untested */
|
||||||
|
/* FIXME: is there a way to check if send was successful? */
|
||||||
|
uip_udp_packet_sendto((struct uip_udp_conn *)ep->handle.conn, data, datalen,
|
||||||
|
&dst->addr, dst->port);
|
||||||
|
return datalen;
|
||||||
|
#endif /* WITH_CONTIKI */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CUSTOM_COAP_NETWORK_SEND */
|
||||||
|
|
||||||
|
#ifdef CUSTOM_COAP_NETWORK_READ
|
||||||
|
|
||||||
|
#define SIN6(A) ((struct sockaddr_in6 *)(A))
|
||||||
|
|
||||||
|
#ifdef WITH_POSIX
|
||||||
|
static coap_packet_t *
|
||||||
|
coap_malloc_packet(void) {
|
||||||
|
coap_packet_t *packet;
|
||||||
|
const size_t need = sizeof(coap_packet_t) + COAP_MAX_PDU_SIZE;
|
||||||
|
|
||||||
|
packet = (coap_packet_t *)coap_malloc(need);
|
||||||
|
if (packet) {
|
||||||
|
memset(packet, 0, need);
|
||||||
|
}
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
coap_free_packet(coap_packet_t *packet) {
|
||||||
|
coap_free(packet);
|
||||||
|
}
|
||||||
|
#endif /* WITH_POSIX */
|
||||||
|
#ifdef WITH_CONTIKI
|
||||||
|
static inline coap_packet_t *
|
||||||
|
coap_malloc_packet(void) {
|
||||||
|
return (coap_packet_t *)coap_malloc_type(COAP_PACKET, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
coap_free_packet(coap_packet_t *packet) {
|
||||||
|
coap_free_type(COAP_PACKET, packet);
|
||||||
|
}
|
||||||
|
#endif /* WITH_CONTIKI */
|
||||||
|
|
||||||
|
static inline size_t
|
||||||
|
coap_get_max_packetlength(const coap_packet_t *packet UNUSED_PARAM) {
|
||||||
|
return COAP_MAX_PDU_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
coap_packet_populate_endpoint(coap_packet_t *packet, coap_endpoint_t *target)
|
||||||
|
{
|
||||||
|
target->handle = packet->interface->handle;
|
||||||
|
memcpy(&target->addr, &packet->dst, sizeof(target->addr));
|
||||||
|
target->ifindex = packet->ifindex;
|
||||||
|
target->flags = 0; /* FIXME */
|
||||||
|
}
|
||||||
|
void
|
||||||
|
coap_packet_copy_source(coap_packet_t *packet, coap_address_t *target)
|
||||||
|
{
|
||||||
|
memcpy(target, &packet->src, sizeof(coap_address_t));
|
||||||
|
}
|
||||||
|
void
|
||||||
|
coap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t *length)
|
||||||
|
{
|
||||||
|
*address = packet->payload;
|
||||||
|
*length = packet->length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a message with destination address @p dst matches the
|
||||||
|
* local interface with address @p local. This function returns @c 1
|
||||||
|
* if @p dst is a valid match, and @c 0 otherwise.
|
||||||
|
*/
|
||||||
|
static inline int
|
||||||
|
is_local_if(const coap_address_t *local, const coap_address_t *dst) {
|
||||||
|
return coap_address_isany(local) || coap_address_equals(dst, local) ||
|
||||||
|
coap_is_mcast(dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
coap_network_read(coap_endpoint_t *ep, coap_packet_t **packet) {
|
||||||
|
ssize_t len = -1;
|
||||||
|
|
||||||
|
#ifdef WITH_POSIX
|
||||||
|
#define SOC_APPDATA_LEN 1460
|
||||||
|
char *soc_appdata = NULL;
|
||||||
|
struct sockaddr_in soc_srcipaddr;
|
||||||
|
socklen_t soc_srcsize = sizeof(struct sockaddr_in);
|
||||||
|
#endif /* WITH_POSIX */
|
||||||
|
|
||||||
|
assert(ep);
|
||||||
|
assert(packet);
|
||||||
|
|
||||||
|
*packet = coap_malloc_packet();
|
||||||
|
|
||||||
|
if (!*packet) {
|
||||||
|
warn("coap_network_read: insufficient memory, drop packet\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
coap_address_init(&(*packet)->dst); /* the local interface address */
|
||||||
|
coap_address_init(&(*packet)->src); /* the remote peer */
|
||||||
|
|
||||||
|
#ifdef WITH_POSIX
|
||||||
|
soc_appdata = coap_malloc(SOC_APPDATA_LEN);
|
||||||
|
if (soc_appdata){
|
||||||
|
len = recvfrom(ep->handle.fd, soc_appdata, SOC_APPDATA_LEN, 0, (struct sockaddr *)&soc_srcipaddr, (socklen_t *)&soc_srcsize);
|
||||||
|
|
||||||
|
if (len < 0){
|
||||||
|
coap_log(LOG_WARNING, "coap_network_read: %s\n", strerror(errno));
|
||||||
|
goto error;
|
||||||
|
} else {
|
||||||
|
/* use getsockname() to get the local port */
|
||||||
|
(*packet)->dst.size = sizeof((*packet)->dst.addr);
|
||||||
|
if (getsockname(ep->handle.fd, &(*packet)->dst.addr.sa, &(*packet)->dst.size) < 0) {
|
||||||
|
coap_log(LOG_DEBUG, "cannot determine local port\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* local interface for IPv4 */
|
||||||
|
(*packet)->src.size = sizeof((*packet)->src.addr);
|
||||||
|
memcpy(&(*packet)->src.addr.sa, &soc_srcipaddr, (*packet)->src.size);
|
||||||
|
|
||||||
|
if (len > coap_get_max_packetlength(*packet)) {
|
||||||
|
/* FIXME: we might want to send back a response */
|
||||||
|
warn("discarded oversized packet\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_local_if(&ep->addr, &(*packet)->dst)) {
|
||||||
|
coap_log(LOG_DEBUG, "packet received on wrong interface, dropped\n");
|
||||||
|
printf("error 3\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*packet)->length = len;
|
||||||
|
|
||||||
|
memcpy(&(*packet)->payload, soc_appdata, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
coap_free(soc_appdata);
|
||||||
|
soc_appdata = NULL;
|
||||||
|
} else {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
#endif /* WITH_POSIX */
|
||||||
|
#ifdef WITH_CONTIKI
|
||||||
|
/* FIXME: untested, make this work */
|
||||||
|
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
|
||||||
|
#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN])
|
||||||
|
|
||||||
|
if(uip_newdata()) {
|
||||||
|
uip_ipaddr_copy(&(*packet)->src.addr, &UIP_IP_BUF->srcipaddr);
|
||||||
|
(*packet)->src.port = UIP_UDP_BUF->srcport;
|
||||||
|
uip_ipaddr_copy(&(*packet)->dst.addr, &UIP_IP_BUF->destipaddr);
|
||||||
|
(*packet)->dst.port = UIP_UDP_BUF->destport;
|
||||||
|
|
||||||
|
if (!is_local_if(&ep->addr, &(*packet)->dst)) {
|
||||||
|
coap_log(LOG_DEBUG, "packet received on wrong interface, dropped\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = uip_datalen();
|
||||||
|
|
||||||
|
if (len > coap_get_max_packetlength(*packet)) {
|
||||||
|
/* FIXME: we might want to send back a response */
|
||||||
|
warn("discarded oversized packet\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
((char *)uip_appdata)[len] = 0;
|
||||||
|
#ifndef NDEBUG
|
||||||
|
if (LOG_DEBUG <= coap_get_log_level()) {
|
||||||
|
#ifndef INET6_ADDRSTRLEN
|
||||||
|
#define INET6_ADDRSTRLEN 40
|
||||||
|
#endif
|
||||||
|
unsigned char addr_str[INET6_ADDRSTRLEN+8];
|
||||||
|
|
||||||
|
if (coap_print_addr(&(*packet)->src, addr_str, INET6_ADDRSTRLEN+8)) {
|
||||||
|
debug("received %zd bytes from %s\n", len, addr_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* NDEBUG */
|
||||||
|
|
||||||
|
(*packet)->length = len;
|
||||||
|
memcpy(&(*packet)->payload, uip_appdata, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef UIP_IP_BUF
|
||||||
|
#undef UIP_UDP_BUF
|
||||||
|
#endif /* WITH_CONTIKI */
|
||||||
|
#ifdef WITH_LWIP
|
||||||
|
#error "coap_network_read() not implemented on this platform"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
(*packet)->interface = ep;
|
||||||
|
|
||||||
|
return len;
|
||||||
|
error:
|
||||||
|
#ifdef WITH_POSIX
|
||||||
|
if (soc_appdata)
|
||||||
|
coap_free(soc_appdata);
|
||||||
|
soc_appdata = NULL;
|
||||||
|
#endif
|
||||||
|
coap_free_packet(*packet);
|
||||||
|
*packet = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef SIN6
|
||||||
|
|
||||||
|
#endif /* CUSTOM_COAP_NETWORK_READ */
|
50
components/coap/port/include/coap/coap.h
Normal file
50
components/coap/port/include/coap/coap.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/* Modify head file implementation for ESP32 platform.
|
||||||
|
*
|
||||||
|
* Uses libcoap software implementation for failover when concurrent
|
||||||
|
* define operations are in use.
|
||||||
|
*
|
||||||
|
* coap.h -- main header file for CoAP stack of libcoap
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2012,2015-2016 Olaf Bergmann <bergmann@tzi.org>
|
||||||
|
* 2015 Carsten Schoenert <c.schoenert@t-online.de>
|
||||||
|
*
|
||||||
|
* Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
*
|
||||||
|
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||||
|
* of use.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _COAP_H_
|
||||||
|
#define _COAP_H_
|
||||||
|
|
||||||
|
#include "libcoap.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "address.h"
|
||||||
|
#include "async.h"
|
||||||
|
#include "bits.h"
|
||||||
|
#include "block.h"
|
||||||
|
#include "coap_io.h"
|
||||||
|
#include "coap_time.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "encode.h"
|
||||||
|
#include "mem.h"
|
||||||
|
#include "net.h"
|
||||||
|
#include "option.h"
|
||||||
|
#include "pdu.h"
|
||||||
|
#include "prng.h"
|
||||||
|
#include "resource.h"
|
||||||
|
#include "str.h"
|
||||||
|
#include "subscribe.h"
|
||||||
|
#include "uri.h"
|
||||||
|
#include "uthash.h"
|
||||||
|
#include "utlist.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _COAP_H_ */
|
39
components/coap/port/include/coap_config.h
Normal file
39
components/coap/port/include/coap_config.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* libcoap configure implementation for ESP32 platform.
|
||||||
|
*
|
||||||
|
* Uses libcoap software implementation for failover when concurrent
|
||||||
|
* configure operations are in use.
|
||||||
|
*
|
||||||
|
* coap.h -- main header file for CoAP stack of libcoap
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2012,2015-2016 Olaf Bergmann <bergmann@tzi.org>
|
||||||
|
* 2015 Carsten Schoenert <c.schoenert@t-online.de>
|
||||||
|
*
|
||||||
|
* Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
*
|
||||||
|
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||||
|
* of use.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CONFIG_H_
|
||||||
|
#define _CONFIG_H_
|
||||||
|
|
||||||
|
#ifdef WITH_POSIX
|
||||||
|
#include "coap_config_posix.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define HAVE_STDIO_H
|
||||||
|
#define HAVE_ASSERT_H
|
||||||
|
|
||||||
|
#define PACKAGE_STRING PACKAGE_NAME PACKAGE_VERSION
|
||||||
|
|
||||||
|
/* it's just provided by libc. i hope we don't get too many of those, as
|
||||||
|
* actually we'd need autotools again to find out what environment we're
|
||||||
|
* building in */
|
||||||
|
#define HAVE_STRNLEN 1
|
||||||
|
|
||||||
|
#define HAVE_LIMITS_H
|
||||||
|
|
||||||
|
#define COAP_RESOURCES_NOHASH
|
||||||
|
|
||||||
|
#endif /* _CONFIG_H_ */
|
41
components/coap/port/include/coap_config_posix.h
Normal file
41
components/coap/port/include/coap_config_posix.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* libcoap configure implementation for ESP32 platform.
|
||||||
|
*
|
||||||
|
* Uses libcoap software implementation for failover when concurrent
|
||||||
|
* configure operations are in use.
|
||||||
|
*
|
||||||
|
* coap.h -- main header file for CoAP stack of libcoap
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2012,2015-2016 Olaf Bergmann <bergmann@tzi.org>
|
||||||
|
* 2015 Carsten Schoenert <c.schoenert@t-online.de>
|
||||||
|
*
|
||||||
|
* Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
*
|
||||||
|
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||||
|
* of use.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COAP_CONFIG_POSIX_H_
|
||||||
|
#define COAP_CONFIG_POSIX_H_
|
||||||
|
|
||||||
|
#ifdef WITH_POSIX
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#define HAVE_SYS_SOCKET_H
|
||||||
|
#define HAVE_MALLOC
|
||||||
|
#define HAVE_ARPA_INET_H
|
||||||
|
|
||||||
|
#define IP_PKTINFO IP_MULTICAST_IF
|
||||||
|
#define IPV6_PKTINFO IPV6_V6ONLY
|
||||||
|
|
||||||
|
#define PACKAGE_NAME "libcoap-posix"
|
||||||
|
#define PACKAGE_VERSION "?"
|
||||||
|
|
||||||
|
#define CUSTOM_COAP_NETWORK_ENDPOINT
|
||||||
|
#define CUSTOM_COAP_NETWORK_SEND
|
||||||
|
#define CUSTOM_COAP_NETWORK_READ
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* COAP_CONFIG_POSIX_H_ */
|
20
components/lwip/include/lwip/port/arpa/inet.h
Normal file
20
components/lwip/include/lwip/port/arpa/inet.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef INET_H_
|
||||||
|
#define INET_H_
|
||||||
|
|
||||||
|
#include "lwip/inet.h"
|
||||||
|
|
||||||
|
#endif /* INET_H_ */
|
22
components/lwip/include/lwip/port/netinet/in.h
Normal file
22
components/lwip/include/lwip/port/netinet/in.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef IN_H_
|
||||||
|
#define IN_H_
|
||||||
|
|
||||||
|
#include "lwip/inet.h"
|
||||||
|
|
||||||
|
#define IN6_IS_ADDR_MULTICAST(a) IN_MULTICAST(a)
|
||||||
|
|
||||||
|
#endif /* IN_H_ */
|
@ -1,4 +1 @@
|
|||||||
# Anyone compiling mbedTLS code needs the name of the
|
|
||||||
# alternative config file
|
|
||||||
|
|
||||||
CFLAGS += -DHAVE_CONFIG_H
|
CFLAGS += -DHAVE_CONFIG_H
|
||||||
|
9
examples/23_coap_client/Makefile
Normal file
9
examples/23_coap_client/Makefile
Normal file
@ -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_client
|
||||||
|
|
||||||
|
include $(IDF_PATH)/make/project.mk
|
||||||
|
|
34
examples/23_coap_client/main/Kconfig.projbuild
Normal file
34
examples/23_coap_client/main/Kconfig.projbuild
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
menu "Example Configuration"
|
||||||
|
|
||||||
|
config TARGET_DOMAIN
|
||||||
|
string "Target Domain"
|
||||||
|
default "californium.eclipse.org"
|
||||||
|
help
|
||||||
|
Target domain for the example to connect to.
|
||||||
|
|
||||||
|
config TARGET_DOMAIN_URI
|
||||||
|
string "Target Uri"
|
||||||
|
default "coap://californium.eclipse.org"
|
||||||
|
help
|
||||||
|
Target uri for the example to use.
|
||||||
|
|
||||||
|
config TARGET_PORT_NUMBER
|
||||||
|
int "Target port number"
|
||||||
|
range 0 65535
|
||||||
|
default 5683
|
||||||
|
help
|
||||||
|
Target port number for the example to connect to.
|
||||||
|
|
||||||
|
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
|
176
examples/23_coap_client/main/coap_client.c
Normal file
176
examples/23_coap_client/main/coap_client.c
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
/* CoAP client 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_client.h"
|
||||||
|
|
||||||
|
#include <string.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 <sys/socket.h>
|
||||||
|
|
||||||
|
#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 void message_handler(struct coap_context_t *ctx, const coap_endpoint_t *local_interface, const coap_address_t *remote,
|
||||||
|
coap_pdu_t *sent, coap_pdu_t *received,
|
||||||
|
const coap_tid_t id)
|
||||||
|
{
|
||||||
|
unsigned char* data = NULL;
|
||||||
|
size_t data_len;
|
||||||
|
if (COAP_RESPONSE_CLASS(received->hdr->code) == 2) {
|
||||||
|
if (coap_get_data(received, &data_len, &data)) {
|
||||||
|
printf("Received: %s\n", data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void coap_demo_thread(void *p)
|
||||||
|
{
|
||||||
|
coap_context_t* ctx = NULL;
|
||||||
|
coap_address_t dst_addr, src_addr;
|
||||||
|
static coap_uri_t uri;
|
||||||
|
fd_set readfds;
|
||||||
|
struct timeval tv;
|
||||||
|
int flags, result;
|
||||||
|
coap_pdu_t* request = NULL;
|
||||||
|
const char* server_uri = COAP_DEFAULT_DEMO_URI;
|
||||||
|
uint8_t get_method = 1;
|
||||||
|
|
||||||
|
coap_address_init(&src_addr);
|
||||||
|
src_addr.addr.sin.sin_family = AF_INET;
|
||||||
|
src_addr.addr.sin.sin_port = htons(0);
|
||||||
|
src_addr.addr.sin.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
|
||||||
|
ctx = coap_new_context(&src_addr);
|
||||||
|
if (ctx) {
|
||||||
|
coap_address_init(&dst_addr);
|
||||||
|
dst_addr.addr.sin.sin_family = AF_INET;
|
||||||
|
dst_addr.addr.sin.sin_port = htons(COAP_DEFAULT_PORT);
|
||||||
|
dst_addr.addr.sin.sin_addr.s_addr = inet_addr(COAP_DEFAULT_DEMO_ADDR);
|
||||||
|
|
||||||
|
coap_split_uri((const uint8_t *)server_uri, strlen(server_uri), &uri);
|
||||||
|
request = coap_new_pdu();
|
||||||
|
if (request){
|
||||||
|
request->hdr->type = COAP_MESSAGE_CON;
|
||||||
|
request->hdr->id = coap_new_message_id(ctx);
|
||||||
|
request->hdr->code = get_method;
|
||||||
|
coap_add_option(request, COAP_OPTION_URI_PATH, uri.path.length, uri.path.s);
|
||||||
|
|
||||||
|
coap_register_response_handler(ctx, message_handler);
|
||||||
|
coap_send_confirmed(ctx, ctx->endpoint, &dst_addr, request);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
FD_ZERO(&readfds);
|
||||||
|
FD_CLR( ctx->sockfd, &readfds );
|
||||||
|
FD_SET( ctx->sockfd, &readfds );
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
}
|
43
examples/23_coap_client/main/coap_client.h
Normal file
43
examples/23_coap_client/main/coap_client.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/* CoAP client 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_CLIENT_H_
|
||||||
|
#define _COAP_CLIENT_H_
|
||||||
|
|
||||||
|
#include <sdkconfig.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
|
||||||
|
|
||||||
|
#define COAP_DEMO_THREAD_NAME "CoAP_demo"
|
||||||
|
#define COAP_DEMO_THREAD_STACK_WORDS 10240
|
||||||
|
#define COAP_DEMO_THREAD_PRORIOTY 8
|
||||||
|
|
||||||
|
#define COAP_DEFAULT_TIME_SEC 5
|
||||||
|
#define COAP_DEFAULT_TIME_USEC 0
|
||||||
|
|
||||||
|
/* The examples use domain of "californium.eclipse.org",uri "coap://californium.eclipse.org" and 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 COAP_DEFAULT_DEMO_ADDR "californium.eclipse.org"
|
||||||
|
, ie #define COAP_DEFAULT_DEMO_URI "coap://californium.eclipse.org" and ie #define COAP_DEFAULT_PORT 5683
|
||||||
|
*/
|
||||||
|
#define COAP_DEFAULT_PORT CONFIG_TARGET_PORT_NUMBER
|
||||||
|
#define COAP_DEFAULT_DEMO_ADDR CONFIG_TARGET_DOMAIN
|
||||||
|
#define COAP_DEFAULT_DEMO_URI CONFIG_TARGET_DOMAIN_URI
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
5
examples/23_coap_client/main/component.mk
Normal file
5
examples/23_coap_client/main/component.mk
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#
|
||||||
|
# "main" pseudo-component makefile.
|
||||||
|
#
|
||||||
|
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||||
|
|
9
examples/24_coap_server/Makefile
Normal file
9
examples/24_coap_server/Makefile
Normal file
@ -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
|
||||||
|
|
22
examples/24_coap_server/main/Kconfig.projbuild
Normal file
22
examples/24_coap_server/main/Kconfig.projbuild
Normal file
@ -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
|
190
examples/24_coap_server/main/coap_server.c
Normal file
190
examples/24_coap_server/main/coap_server.c
Normal file
@ -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 <string.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 <sys/socket.h>
|
||||||
|
|
||||||
|
#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();
|
||||||
|
}
|
38
examples/24_coap_server/main/coap_server.h
Normal file
38
examples/24_coap_server/main/coap_server.h
Normal file
@ -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 <sdkconfig.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
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
5
examples/24_coap_server/main/component.mk
Normal file
5
examples/24_coap_server/main/component.mk
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#
|
||||||
|
# "main" pseudo-component makefile.
|
||||||
|
#
|
||||||
|
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user