forked from project-chip/connectedhomeip
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a WiFi Echo example for the ESP32 (project-chip#519)
* Add a WiFi Echo example for the ESP32 * Add missing newline * Restyled by clang-format * Move module include to the top * Fix typo * Retry if bind fails * Fix nits Co-authored-by: Restyled.io <commits@restyled.io>
- Loading branch information
1 parent
d953631
commit 05897f4
Showing
17 changed files
with
744 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# | ||
# This is a project Makefile. It is assumed the directory this Makefile resides in is a | ||
# project subdirectory. | ||
# | ||
|
||
PROJECT_NAME := chip-wifi-echo | ||
|
||
EXTRA_COMPONENT_DIRS += $(PROJECT_PATH)/third_party/connectedhomeip/config/esp32/components | ||
|
||
include $(IDF_PATH)/make/project.mk |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
# CHIP WiFi Echo Server Example | ||
|
||
A prototype appplication that uses CHIP to setup WiFi on the ESP32 and runs an | ||
Echo Server on a configured port. This example will evolve as more complex | ||
messaging is supported in CHIP. | ||
|
||
--- | ||
|
||
- [CHIP WiFi Echo Server Example](#chip-wifi-echo-server-example) | ||
- [Supported Devices](#supported-devices) | ||
- [Building the Example Application](#building-the-example-application) | ||
- [Using the Echo Server](#using-the-echo-server) | ||
|
||
--- | ||
|
||
## Supported Devices | ||
|
||
The CHIP demo application is intended to work on two categories of ESP32 | ||
devices: the | ||
[ESP32-DevKitC](https://www.espressif.com/en/products/hardware/esp32-devkitc/overview), | ||
and the [M5Stack](http://m5stack.com). Support for the | ||
[M5Stack](http://m5stack.com) is still a Work in Progress. | ||
|
||
## Building the Example Application | ||
|
||
Building the example application requires the use of the Espressif ESP32 IoT | ||
Development Framework and the xtensa-esp32-elf toolchain. | ||
|
||
The VSCode devcontainer has these components pre-installed, so you can skip this | ||
step. To install these components manually, follow these steps: | ||
|
||
- Clone the Expressif ESP-IDF and checkout version 4.0 | ||
|
||
$ mkdir ${HOME}/tools | ||
$ cd ${HOME}/tools | ||
$ git clone https://github.com/espressif/esp-idf.git | ||
$ cd esp-idf | ||
$ git checkout release/v4.0 | ||
$ git submodule update --init | ||
$ export IDF_PATH=${HOME}/tools/esp-idf | ||
$ ./install.sh | ||
|
||
To build the application, follow these steps: | ||
|
||
Currently building in VSCode _and_ deploying from native is not supported, so | ||
make sure the IDF_PATH has been exported(See the manual setup steps above). | ||
|
||
- In the root of the example directory, use the `defconfig` make target to | ||
configure the application with defaults. | ||
|
||
$ idf make defconfig | ||
|
||
- Run make to build the demo application | ||
|
||
$ idf make | ||
|
||
- After building the application, to flash it outside of VSCode, connect your | ||
device via USB. Then run the following command to flash the demo application | ||
onto the device and then monitor its output. If necessary, replace | ||
`/dev/tty.SLAB_USBtoUART`(MacOS) with the correct USB device name for your | ||
system(like `/dev/ttyUSB0` on Linux). Note that sometimes you might have to | ||
press and hold the `boot` button on the device while it's trying to connect | ||
before flashing. | ||
|
||
$ make flash monitor ESPPORT=/dev/tty.SLAB_USBtoUART | ||
|
||
Note: Some users might have to install the | ||
[VCP driver](https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers) | ||
before the device shows up on `/dev/tty`. | ||
|
||
## Using the Echo Server | ||
|
||
After the application has been flashed, connect the ESP32's Soft-AP. It's | ||
usually something like `CHIP_DEMO-XXXX` where the last 4 digits are from the | ||
device's MAC address. | ||
|
||
Once you're connected, the server's IP can be found at the gateway address and | ||
at the listed port number(Default: `8000`). | ||
|
||
Then running the following command will ping the ESP32 and cause it to echo. If | ||
necessary replace the `192.168.4.1` with the address printed by the device in | ||
the monitor. | ||
|
||
$ echo "Hello over IP" | nc -w1 -u 192.168.4.1 8000 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#!/usr/bin/env bash | ||
# | ||
# Copyright (c) 2020 Project CHIP Authors | ||
# All rights reserved. | ||
# | ||
# 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. | ||
|
||
# If this file is sourced, it exports a function called "idf" that initializes | ||
# the espressif environment via the espressive export.sh script and runs | ||
# a command presented as arguments | ||
# | ||
# This file can also be used as an executable | ||
me=${0##*/} | ||
die() { | ||
echo "$me: *** ERROR: " "${*}" | ||
exit 1 | ||
} | ||
idf() { | ||
[[ -d $IDF_PATH && -r $IDF_PATH/export.sh ]] || die "can't find IDF's export.sh" | ||
. "$IDF_PATH/export.sh" | ||
"$@" | ||
} | ||
if [[ ${0} == ${BASH_SOURCE[0]} ]]; then | ||
idf "${@}" | ||
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
/* | ||
* | ||
* Copyright (c) 2020 Project CHIP Authors | ||
* | ||
* 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. | ||
*/ | ||
|
||
#include <string.h> | ||
#include <sys/param.h> | ||
#include "freertos/FreeRTOS.h" | ||
#include "freertos/task.h" | ||
#include "esp_system.h" | ||
#include "esp_wifi.h" | ||
#include "esp_event.h" | ||
#include "esp_log.h" | ||
#include "nvs_flash.h" | ||
#include "tcpip_adapter.h" | ||
|
||
#include "lwip/err.h" | ||
#include "lwip/sockets.h" | ||
#include "lwip/sys.h" | ||
#include <lwip/netdb.h> | ||
|
||
#define PORT CONFIG_ECHO_PORT | ||
#define RX_LEN 128 | ||
#define ADDR_LEN 128 | ||
|
||
static const char * TAG = "echo server"; | ||
|
||
static void udp_server_task(void * pvParameters) | ||
{ | ||
char rx_buffer[RX_LEN]; | ||
char addr_str[ADDR_LEN]; | ||
int addr_family = (int) pvParameters; | ||
int ip_protocol = 0; | ||
struct sockaddr_in6 dest_addr; | ||
|
||
while (1) | ||
{ | ||
|
||
if (addr_family == AF_INET) | ||
{ | ||
struct sockaddr_in * dest_addr_ip4 = (struct sockaddr_in *) &dest_addr; | ||
dest_addr_ip4->sin_addr.s_addr = htonl(INADDR_ANY); | ||
dest_addr_ip4->sin_family = AF_INET; | ||
dest_addr_ip4->sin_port = htons(PORT); | ||
ip_protocol = IPPROTO_IP; | ||
} | ||
else if (addr_family == AF_INET6) | ||
{ | ||
bzero(&dest_addr.sin6_addr.un, sizeof(dest_addr.sin6_addr.un)); | ||
dest_addr.sin6_family = AF_INET6; | ||
dest_addr.sin6_port = htons(PORT); | ||
ip_protocol = IPPROTO_IPV6; | ||
} | ||
|
||
int sock = socket(addr_family, SOCK_DGRAM, ip_protocol); | ||
if (sock < 0) | ||
{ | ||
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); | ||
break; | ||
} | ||
ESP_LOGI(TAG, "Socket created"); | ||
|
||
#if defined(CONFIG_ECHO_IPV4) && defined(CONFIG_ECHO_IPV6) | ||
if (addr_family == AF_INET6) | ||
{ | ||
// Note that by default IPV6 binds to both protocols, it is must be disabled | ||
// if both protocols used at the same time (used in CI) | ||
int opt = 1; | ||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); | ||
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)); | ||
} | ||
#endif | ||
|
||
int err = bind(sock, (struct sockaddr *) &dest_addr, sizeof(dest_addr)); | ||
if (err < 0) | ||
{ | ||
ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno); | ||
// Avoid looping hard if binding fails continuously | ||
vTaskDelay(50 / portTICK_PERIOD_MS); | ||
continue; | ||
} | ||
ESP_LOGI(TAG, "Socket bound, port %d", PORT); | ||
|
||
while (1) | ||
{ | ||
|
||
ESP_LOGI(TAG, "Waiting for data"); | ||
struct sockaddr_in6 source_addr; // Large enough for both IPv4 or IPv6 | ||
socklen_t socklen = sizeof(source_addr); | ||
int len = recvfrom(sock, rx_buffer, sizeof(rx_buffer) - 1, 0, (struct sockaddr *) &source_addr, &socklen); | ||
|
||
// Error occurred during receiving | ||
if (len < 0) | ||
{ | ||
ESP_LOGE(TAG, "recvfrom failed: errno %d", errno); | ||
break; | ||
} | ||
// Data received | ||
else | ||
{ | ||
// Get the sender's ip address as string | ||
if (source_addr.sin6_family == PF_INET) | ||
{ | ||
inet_ntoa_r(((struct sockaddr_in *) &source_addr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); | ||
} | ||
else if (source_addr.sin6_family == PF_INET6) | ||
{ | ||
inet6_ntoa_r(source_addr.sin6_addr, addr_str, sizeof(addr_str) - 1); | ||
} | ||
|
||
rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string... | ||
ESP_LOGI(TAG, "Received %d bytes from %s:", len, addr_str); | ||
ESP_LOGI(TAG, "%s", rx_buffer); | ||
|
||
int err = sendto(sock, rx_buffer, len, 0, (struct sockaddr *) &source_addr, sizeof(source_addr)); | ||
if (err < 0) | ||
{ | ||
ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
if (sock != -1) | ||
{ | ||
ESP_LOGE(TAG, "Shutting down socket and restarting..."); | ||
shutdown(sock, 0); | ||
close(sock); | ||
} | ||
} | ||
vTaskDelete(NULL); | ||
} | ||
|
||
// The echo server assumes the platform's networking has been setup already | ||
void startServer(void) | ||
{ | ||
#ifdef CONFIG_ECHO_IPV4 | ||
xTaskCreate(udp_server_task, "udp_server", 4096, (void *) AF_INET, 5, NULL); | ||
#endif | ||
#ifdef CONFIG_ECHO_IPV6 | ||
xTaskCreate(udp_server_task, "udp_server", 4096, (void *) AF_INET6, 5, NULL); | ||
#endif | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# | ||
# Copyright (c) 2020 Project CHIP Authors | ||
# All rights reserved. | ||
# | ||
# 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. | ||
# | ||
# Description: | ||
# Configuration options CHIP ESP32 demo application. | ||
# | ||
|
||
menu "WiFi Echo Demo" | ||
|
||
choice | ||
prompt "Device Type" | ||
default DEVICE_TYPE_ESP32_DEVKITC | ||
help | ||
Specifies the type of ESP32 device. | ||
|
||
Note that the "ESP32-DevKitC" choice is compatible with a number of clone devices | ||
available from third-party manufacturers. | ||
|
||
config DEVICE_TYPE_ESP32_DEVKITC | ||
bool "ESP32-DevKitC" | ||
config DEVICE_TYPE_M5STACK | ||
bool "M5Stack" | ||
endchoice | ||
|
||
config ECHO_IPV4 | ||
bool "IPV4" | ||
default y | ||
|
||
config ECHO_IPV6 | ||
bool "IPV6" | ||
default n | ||
select EXAMPLE_CONNECT_IPV6 | ||
|
||
config ECHO_PORT | ||
int "Port" | ||
range 0 65535 | ||
default 8000 | ||
help | ||
Local port the example server will listen on. | ||
|
||
endmenu |
Oops, something went wrong.