Skip to content

Commit

Permalink
Add integration for IDF Component Manager
Browse files Browse the repository at this point in the history
  • Loading branch information
me-no-dev authored and mathieucarbou committed Feb 6, 2025
1 parent cd3194d commit f2a2a4c
Show file tree
Hide file tree
Showing 20 changed files with 491 additions and 0 deletions.
50 changes: 50 additions & 0 deletions .github/workflows/upload-idf-component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Publish ESP-IDF Component

on:
workflow_dispatch:
inputs:
tag:
description: 'Component version (1.2.3, 1.2.3-rc1 or 1.2.3.4)'
required: true
git_ref:
description: 'Git ref with the source (branch, tag or commit)'
required: true

permissions:
contents: read

jobs:
upload_components:
runs-on: ubuntu-latest
steps:
- name: Get the release tag
env:
head_branch: ${{ inputs.tag || github.event.workflow_run.head_branch }}
run: |
# Read and sanitize the branch/tag name
branch=$(echo "$head_branch" | tr -cd '[:alnum:]/_.-')
if [[ $branch == refs/tags/* ]]; then
tag="${branch#refs/tags/}"
elif [[ $branch =~ ^[v]*[0-9]+\.[0-9]+\.[0-9]+.*$ ]]; then
tag=$branch
else
echo "Tag not found in $branch. Exiting..."
exit 1
fi
echo "Tag: $tag"
echo "RELEASE_TAG=$tag" >> $GITHUB_ENV
- uses: actions/checkout@v4
with:
ref: ${{ inputs.git_ref || env.RELEASE_TAG }}
submodules: "recursive"

- name: Upload components to the component registry
uses: espressif/upload-components-ci-action@v1
with:
name: espasyncwebserver
version: ${{ env.RELEASE_TAG }}
namespace: esp32async
api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }}
32 changes: 32 additions & 0 deletions idf_component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
description: "Async Web Server for ESP32 Arduino"
url: "https://github.com/ESP32Async/ESPAsyncWebServer"
license: "LGPL-3.0-or-later"
tags:
- arduino
files:
exclude:
- "idf_component_examples/"
- "idf_component_examples/**/*"
- "examples/"
- "examples/**/*"
- ".gitignore"
- ".clang-format"
- ".gitpod.Dockerfile"
- ".gitpod.yml"
- ".codespellrc"
- ".editorconfig"
- ".pre-commit-config.yaml"
- "CODE_OF_CONDUCT.md"
- "library.json"
- "library.properties"
- "partitions-4MB.csv"
- "platformio.ini"
- "pre-commit.requirements.txt"
dependencies:
esp32async/asynctcp:
version: "^3.3.5"
require: public
examples:
- path: ./idf_component_examples/catchall
- path: ./idf_component_examples/serversentevents
- path: ./idf_component_examples/websocket
8 changes: 8 additions & 0 deletions idf_component_examples/catchall/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# For more information about build system see
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(main)
1 change: 1 addition & 0 deletions idf_component_examples/catchall/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
### Basic example to show how to catch all requests and send a 404 Not Found response
2 changes: 2 additions & 0 deletions idf_component_examples/catchall/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
idf_component_register(SRCS "main.cpp"
INCLUDE_DIRS ".")
6 changes: 6 additions & 0 deletions idf_component_examples/catchall/main/idf_component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## IDF Component Manager Manifest File
dependencies:
esp32async/espasyncwebserver:
version: "*"
override_path: "../../../"
pre_release: true
125 changes: 125 additions & 0 deletions idf_component_examples/catchall/main/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright 2016-2025 Hristo Gochkov, Mathieu Carbou, Emil Muratov

//
// Shows how to catch all requests and send a 404 Not Found response
//

#include <Arduino.h>
#include <AsyncTCP.h>
#include <WiFi.h>

#include <ESPAsyncWebServer.h>

static AsyncWebServer server(80);

static const char *htmlContent PROGMEM = R"(
<!DOCTYPE html>
<html>
<head>
<title>Sample HTML</title>
</head>
<body>
<h1>Hello, World!</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod, purus a euismod
rhoncus, urna ipsum cursus massa, eu dictum tellus justo ac justo. Quisque ullamcorper
arcu nec tortor ullamcorper, vel fermentum justo fermentum. Vivamus sed velit ut elit
accumsan congue ut ut enim. Ut eu justo eu lacus varius gravida ut a tellus. Nulla facilisi.
Integer auctor consectetur ultricies. Fusce feugiat, mi sit amet bibendum viverra, orci leo
dapibus elit, id varius sem dui id lacus.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod, purus a euismod
rhoncus, urna ipsum cursus massa, eu dictum tellus justo ac justo. Quisque ullamcorper
arcu nec tortor ullamcorper, vel fermentum justo fermentum. Vivamus sed velit ut elit
accumsan congue ut ut enim. Ut eu justo eu lacus varius gravida ut a tellus. Nulla facilisi.
Integer auctor consectetur ultricies. Fusce feugiat, mi sit amet bibendum viverra, orci leo
dapibus elit, id varius sem dui id lacus.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod, purus a euismod
rhoncus, urna ipsum cursus massa, eu dictum tellus justo ac justo. Quisque ullamcorper
arcu nec tortor ullamcorper, vel fermentum justo fermentum. Vivamus sed velit ut elit
accumsan congue ut ut enim. Ut eu justo eu lacus varius gravida ut a tellus. Nulla facilisi.
Integer auctor consectetur ultricies. Fusce feugiat, mi sit amet bibendum viverra, orci leo
dapibus elit, id varius sem dui id lacus.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod, purus a euismod
rhoncus, urna ipsum cursus massa, eu dictum tellus justo ac justo. Quisque ullamcorper
arcu nec tortor ullamcorper, vel fermentum justo fermentum. Vivamus sed velit ut elit
accumsan congue ut ut enim. Ut eu justo eu lacus varius gravida ut a tellus. Nulla facilisi.
Integer auctor consectetur ultricies. Fusce feugiat, mi sit amet bibendum viverra, orci leo
dapibus elit, id varius sem dui id lacus.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod, purus a euismod
rhoncus, urna ipsum cursus massa, eu dictum tellus justo ac justo. Quisque ullamcorper
arcu nec tortor ullamcorper, vel fermentum justo fermentum. Vivamus sed velit ut elit
accumsan congue ut ut enim. Ut eu justo eu lacus varius gravida ut a tellus. Nulla facilisi.
Integer auctor consectetur ultricies. Fusce feugiat, mi sit amet bibendum viverra, orci leo
dapibus elit, id varius sem dui id lacus.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod, purus a euismod
rhoncus, urna ipsum cursus massa, eu dictum tellus justo ac justo. Quisque ullamcorper
arcu nec tortor ullamcorper, vel fermentum justo fermentum. Vivamus sed velit ut elit
accumsan congue ut ut enim. Ut eu justo eu lacus varius gravida ut a tellus. Nulla facilisi.
Integer auctor consectetur ultricies. Fusce feugiat, mi sit amet bibendum viverra, orci leo
dapibus elit, id varius sem dui id lacus.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod, purus a euismod
rhoncus, urna ipsum cursus massa, eu dictum tellus justo ac justo. Quisque ullamcorper
arcu nec tortor ullamcorper, vel fermentum justo fermentum. Vivamus sed velit ut elit
accumsan congue ut ut enim. Ut eu justo eu lacus varius gravida ut a tellus. Nulla facilisi.
Integer auctor consectetur ultricies. Fusce feugiat, mi sit amet bibendum viverra, orci leo
dapibus elit, id varius sem dui id lacus.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod, purus a euismod
rhoncus, urna ipsum cursus massa, eu dictum tellus justo ac justo. Quisque ullamcorper
arcu nec tortor ullamcorper, vel fermentum justo fermentum. Vivamus sed velit ut elit
accumsan congue ut ut enim. Ut eu justo eu lacus varius gravida ut a tellus. Nulla facilisi.
Integer auctor consectetur ultricies. Fusce feugiat, mi sit amet bibendum viverra, orci leo
dapibus elit, id varius sem dui id lacus.</p>
</body>
</html>
)";

static const size_t htmlContentLength = strlen_P(htmlContent);

void setup() {
Serial.begin(115200);

#ifndef CONFIG_IDF_TARGET_ESP32H2
WiFi.mode(WIFI_AP);
WiFi.softAP("esp-captive");
#endif

// curl -v http://192.168.4.1/
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
// need to cast to uint8_t*
// if you do not, the const char* will be copied in a temporary String buffer
request->send(200, "text/html", (uint8_t *)htmlContent, htmlContentLength);
});

// catch any request, and send a 404 Not Found response
// except for /game_log which is handled by onRequestBody
//
// curl -v http://192.168.4.1/foo
//
server.onNotFound([](AsyncWebServerRequest *request) {
if (request->url() == "/game_log") {
return; // response object already created by onRequestBody
}

request->send(404, "text/plain", "Not found");
});

// See: https://github.com/ESP32Async/ESPAsyncWebServer/issues/6
// catch any POST request and send a 200 OK response
//
// curl -v -X POST http://192.168.4.1/game_log -H "Content-Type: application/json" -d '{"game": "test"}'
//
server.onRequestBody([](AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) {
if (request->url() == "/game_log") {
request->send(200, "application/json", "{\"status\":\"OK\"}");
}
// note that there is no else here: the goal is only to prepare a response based on some body content
// onNotFound will always be called after this, and will not override the response object if `/game_log` is requested
});

server.begin();
}

// not needed
void loop() {
delay(100);
}
12 changes: 12 additions & 0 deletions idf_component_examples/catchall/sdkconfig.defaults
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#
# Arduino ESP32
#
CONFIG_AUTOSTART_ARDUINO=y
# end of Arduino ESP32

#
# FREERTOS
#
CONFIG_FREERTOS_HZ=1000
# end of FREERTOS
# end of Component config
8 changes: 8 additions & 0 deletions idf_component_examples/serversentevents/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# For more information about build system see
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(main)
1 change: 1 addition & 0 deletions idf_component_examples/serversentevents/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
### Basic example to show how to use ServerSentEvents
2 changes: 2 additions & 0 deletions idf_component_examples/serversentevents/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
idf_component_register(SRCS "main.cpp"
INCLUDE_DIRS ".")
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## IDF Component Manager Manifest File
dependencies:
esp32async/espasyncwebserver:
version: "*"
override_path: "../../../"
pre_release: true
95 changes: 95 additions & 0 deletions idf_component_examples/serversentevents/main/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright 2016-2025 Hristo Gochkov, Mathieu Carbou, Emil Muratov

//
// SSE example
//

#include <Arduino.h>
#include <AsyncTCP.h>
#include <WiFi.h>

#include <ESPAsyncWebServer.h>

static const char *htmlContent PROGMEM = R"(
<!DOCTYPE html>
<html>
<head>
<title>Server-Sent Events</title>
<script>
if (!!window.EventSource) {
var source = new EventSource('/events');
source.addEventListener('open', function(e) {
console.log("Events Connected");
}, false);
source.addEventListener('error', function(e) {
if (e.target.readyState != EventSource.OPEN) {
console.log("Events Disconnected");
}
}, false);
source.addEventListener('message', function(e) {
console.log("message", e.data);
}, false);
source.addEventListener('heartbeat', function(e) {
console.log("heartbeat", e.data);
}, false);
}
</script>
</head>
<body>
<h1>Open your browser console!</h1>
</body>
</html>
)";

static const size_t htmlContentLength = strlen_P(htmlContent);

static AsyncWebServer server(80);
static AsyncEventSource events("/events");

void setup() {
Serial.begin(115200);

#ifndef CONFIG_IDF_TARGET_ESP32H2
WiFi.mode(WIFI_AP);
WiFi.softAP("esp-captive");
#endif

// curl -v http://192.168.4.1/
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
// need to cast to uint8_t*
// if you do not, the const char* will be copied in a temporary String buffer
request->send(200, "text/html", (uint8_t *)htmlContent, htmlContentLength);
});

events.onConnect([](AsyncEventSourceClient *client) {
Serial.printf("SSE Client connected! ID: %" PRIu32 "\n", client->lastId());
client->send("hello!", NULL, millis(), 1000);
});

events.onDisconnect([](AsyncEventSourceClient *client) {
Serial.printf("SSE Client disconnected! ID: %" PRIu32 "\n", client->lastId());
});

server.addHandler(&events);

server.begin();
}

static uint32_t lastSSE = 0;
static uint32_t deltaSSE = 3000;

static uint32_t lastHeap = 0;

void loop() {
uint32_t now = millis();
if (now - lastSSE >= deltaSSE) {
events.send(String("ping-") + now, "heartbeat", now);
lastSSE = millis();
}

if (now - lastHeap >= 2000) {
Serial.printf("Free heap: %" PRIu32 "\n", ESP.getFreeHeap());
lastHeap = now;
}
}
12 changes: 12 additions & 0 deletions idf_component_examples/serversentevents/sdkconfig.defaults
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#
# Arduino ESP32
#
CONFIG_AUTOSTART_ARDUINO=y
# end of Arduino ESP32

#
# FREERTOS
#
CONFIG_FREERTOS_HZ=1000
# end of FREERTOS
# end of Component config
8 changes: 8 additions & 0 deletions idf_component_examples/websocket/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# For more information about build system see
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(main)
1 change: 1 addition & 0 deletions idf_component_examples/websocket/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
### Basic example to show how to use WebSockets
2 changes: 2 additions & 0 deletions idf_component_examples/websocket/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
idf_component_register(SRCS "main.cpp"
INCLUDE_DIRS ".")
6 changes: 6 additions & 0 deletions idf_component_examples/websocket/main/idf_component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## IDF Component Manager Manifest File
dependencies:
esp32async/espasyncwebserver:
version: "*"
override_path: "../../../"
pre_release: true
Loading

0 comments on commit f2a2a4c

Please sign in to comment.