Skip to content

Commit f510710

Browse files
committed
feat: Update to espp 1.0.10 and use CLI + WiFi STA menu to allow runtime WiFi configuration
1 parent a4633fc commit f510710

File tree

3 files changed

+125
-87
lines changed

3 files changed

+125
-87
lines changed

main/Kconfig.projbuild

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ menu "Camera Streamer Configuration"
88

99
config ESP_WIFI_SSID
1010
string "WiFi SSID"
11-
default "myssid"
11+
default ""
1212
help
1313
SSID (network name) for the camera streamer to connect to.
1414

1515
config ESP_WIFI_PASSWORD
1616
string "WiFi Password"
17-
default "mypassword"
17+
default ""
1818
help
1919
WiFi password (WPA or WPA2) for the camera streamer to use.
2020

main/main.cpp

Lines changed: 120 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,32 @@
88
#include <esp_heap_caps.h>
99
#include <mdns.h>
1010

11+
#include "cli.hpp"
1112
#include "esp32-timer-cam.hpp"
1213
#include "nvs.hpp"
1314
#include "task.hpp"
1415
#include "tcp_socket.hpp"
1516
#include "udp_socket.hpp"
1617
#include "wifi_sta.hpp"
18+
#include "wifi_sta_menu.hpp"
1719

1820
#include "esp_camera.h"
1921

2022
#include "rtsp_server.hpp"
2123

2224
using namespace std::chrono_literals;
2325

26+
static espp::Logger logger({.tag = "Camera Streamer", .level = espp::Logger::Verbosity::INFO});
27+
28+
std::unique_ptr<espp::Task> camera_task;
29+
std::shared_ptr<espp::RtspServer> rtsp_server;
30+
31+
esp_err_t initialize_camera(void);
32+
void start_rtsp_server(std::string_view server_address, int server_port);
33+
bool camera_task_fn(const std::mutex &m, const std::condition_variable &cv);
34+
2435
extern "C" void app_main(void) {
2536
esp_err_t err;
26-
espp::Logger logger({.tag = "Camera Streamer", .level = espp::Logger::Verbosity::INFO});
2737
logger.info("Bootup");
2838

2939
#if CONFIG_ESP32_WIFI_NVS_ENABLED
@@ -35,38 +45,90 @@ extern "C" void app_main(void) {
3545

3646
auto &timer_cam = espp::EspTimerCam::get();
3747

48+
// initialize RTC
49+
if (!timer_cam.initialize_rtc()) {
50+
logger.error("Could not initialize RTC");
51+
return;
52+
}
53+
3854
// initialize LED
39-
static constexpr float led_breathing_period = 3.5f;
40-
if (!timer_cam.initialize_led(led_breathing_period)) {
55+
static constexpr float disconnected_led_breathing_period = 1.0f;
56+
static constexpr float connected_led_breathing_period = 3.5f;
57+
if (!timer_cam.initialize_led(disconnected_led_breathing_period)) {
4158
logger.error("Could not initialize LED");
4259
return;
4360
}
61+
timer_cam.start_led_breathing();
62+
63+
// initialize camera
64+
logger.info("Initializing camera");
65+
err = initialize_camera();
66+
if (err != ESP_OK) {
67+
logger.error("Could not initialize camera: {} '{}'", err, esp_err_to_name(err));
68+
}
4469

4570
// initialize WiFi
4671
logger.info("Initializing WiFi");
47-
std::string server_address;
48-
espp::WifiSta wifi_sta({.ssid = CONFIG_ESP_WIFI_SSID,
49-
.password = CONFIG_ESP_WIFI_PASSWORD,
50-
.num_connect_retries = CONFIG_ESP_MAXIMUM_RETRY,
51-
.on_connected = nullptr,
52-
.on_disconnected = nullptr,
53-
.on_got_ip = [&logger, &server_address](ip_event_got_ip_t *eventdata) {
54-
server_address =
55-
fmt::format("{}.{}.{}.{}", IP2STR(&eventdata->ip_info.ip));
56-
logger.info("got IP: {}", server_address);
57-
}});
58-
// wait for network
59-
float duty = 0.0f;
60-
while (!wifi_sta.is_connected()) {
61-
logger.info("waiting for wifi connection...");
62-
logger.move_up();
63-
logger.clear_line();
64-
timer_cam.set_led_brightness(duty);
65-
duty = duty == 0.0f ? 0.5f : 0.0f;
66-
std::this_thread::sleep_for(1s);
67-
}
72+
espp::WifiSta wifi_sta(
73+
{.ssid = CONFIG_ESP_WIFI_SSID,
74+
.password = CONFIG_ESP_WIFI_PASSWORD,
75+
.num_connect_retries = CONFIG_ESP_MAXIMUM_RETRY,
76+
.on_connected =
77+
[]() {
78+
static auto &timer_cam = espp::EspTimerCam::get();
79+
timer_cam.set_led_breathing_period(connected_led_breathing_period);
80+
},
81+
.on_disconnected =
82+
[]() {
83+
static auto &timer_cam = espp::EspTimerCam::get();
84+
timer_cam.set_led_breathing_period(disconnected_led_breathing_period);
85+
logger.info("Stopping camera task");
86+
camera_task.reset();
87+
logger.info("Stopping RTSP server");
88+
rtsp_server.reset();
89+
},
90+
.on_got_ip =
91+
[](ip_event_got_ip_t *eventdata) {
92+
auto server_address = fmt::format("{}.{}.{}.{}", IP2STR(&eventdata->ip_info.ip));
93+
logger.info("got IP: {}", server_address);
94+
// create the camera and rtsp server, and the cv/m
95+
// they'll use to communicate
96+
start_rtsp_server(server_address, CONFIG_RTSP_SERVER_PORT);
97+
// initialize the camera
98+
logger.info("Creating camera task");
99+
camera_task = espp::Task::make_unique(
100+
espp::Task::Config{.callback = camera_task_fn,
101+
.task_config = {.name = "Camera Task", .priority = 10}});
102+
camera_task->start();
103+
}});
104+
105+
espp::WifiStaMenu sta_menu(wifi_sta);
106+
auto root_menu = sta_menu.get();
107+
root_menu->Insert(
108+
"memory",
109+
[](std::ostream &out) {
110+
out << "Minimum free memory: " << heap_caps_get_minimum_free_size(MALLOC_CAP_DEFAULT)
111+
<< std::endl;
112+
},
113+
"Display minimum free memory.");
114+
root_menu->Insert(
115+
"battery",
116+
[](std::ostream &out) {
117+
static auto &timer_cam = espp::EspTimerCam::get();
118+
out << fmt::format("Battery voltage: {:.2f}\n", timer_cam.get_battery_voltage());
119+
},
120+
"Display the current battery voltage.");
121+
122+
cli::Cli cli(std::move(root_menu));
123+
cli::SetColor();
124+
cli.ExitAction([](auto &out) { out << "Goodbye and thanks for all the fish.\n"; });
125+
126+
espp::Cli input(cli);
127+
input.SetInputHistorySize(10);
128+
input.Start();
129+
}
68130

69-
// initialize camera
131+
esp_err_t initialize_camera(void) {
70132
/**
71133
* @note display sizes supported:
72134
* * QVGA: 320x240
@@ -85,7 +147,7 @@ extern "C" void app_main(void) {
85147
* * UXGA: 1600x1200
86148
*/
87149

88-
logger.info("Initializing camera");
150+
auto &timer_cam = espp::EspTimerCam::get();
89151
static camera_config_t camera_config = {
90152
.pin_pwdn = -1,
91153
.pin_reset = timer_cam.get_camera_reset_pin(),
@@ -121,33 +183,22 @@ extern "C" void app_main(void) {
121183
.grab_mode =
122184
CAMERA_GRAB_LATEST // CAMERA_GRAB_WHEN_EMPTY // . Sets when buffers should be filled
123185
};
124-
err = esp_camera_init(&camera_config);
125-
if (err != ESP_OK) {
126-
logger.error("Could not initialize camera: {} '{}'", err, esp_err_to_name(err));
127-
}
128-
129-
timer_cam.start_led_breathing();
130-
131-
// initialize RTC
132-
if (!timer_cam.initialize_rtc()) {
133-
logger.error("Could not initialize RTC");
134-
return;
135-
}
186+
return esp_camera_init(&camera_config);
187+
}
136188

137-
// create the camera and rtsp server, and the cv/m they'll use to
138-
// communicate
139-
int server_port = CONFIG_RTSP_SERVER_PORT;
189+
void start_rtsp_server(std::string_view server_address, int server_port) {
140190
logger.info("Creating RTSP server at {}:{}", server_address, server_port);
141-
espp::RtspServer rtsp_server({.server_address = server_address,
142-
.port = server_port,
143-
.path = "mjpeg/1",
144-
.log_level = espp::Logger::Verbosity::WARN});
145-
rtsp_server.set_session_log_level(espp::Logger::Verbosity::WARN);
146-
rtsp_server.start();
191+
rtsp_server = std::make_shared<espp::RtspServer>(
192+
espp::RtspServer::Config{.server_address = std::string(server_address),
193+
.port = server_port,
194+
.path = "mjpeg/1",
195+
.log_level = espp::Logger::Verbosity::WARN});
196+
rtsp_server->set_session_log_level(espp::Logger::Verbosity::WARN);
197+
rtsp_server->start();
147198

148199
// initialize mDNS
149200
logger.info("Initializing mDNS");
150-
err = mdns_init();
201+
esp_err_t err = mdns_init();
151202
if (err != ESP_OK) {
152203
logger.error("Could not initialize mDNS: {}", err);
153204
return;
@@ -173,47 +224,31 @@ extern "C" void app_main(void) {
173224
return;
174225
}
175226
logger.info("mDNS initialized");
227+
}
176228

177-
// initialize the camera
178-
logger.info("Creating camera task");
179-
auto camera_task_fn = [&rtsp_server, &logger](const auto &m, const auto &cv) -> bool {
180-
// take image
181-
static camera_fb_t *fb = NULL;
182-
static size_t _jpg_buf_len;
183-
static uint8_t *_jpg_buf;
184-
185-
fb = esp_camera_fb_get();
186-
if (!fb) {
187-
logger.error("Camera capture failed");
188-
return false;
189-
}
190-
191-
_jpg_buf_len = fb->len;
192-
_jpg_buf = fb->buf;
229+
bool camera_task_fn(const std::mutex &m, const std::condition_variable &cv) {
230+
// take image
231+
static camera_fb_t *fb = NULL;
232+
static size_t _jpg_buf_len;
233+
static uint8_t *_jpg_buf;
193234

194-
if (!(_jpg_buf[_jpg_buf_len - 1] != 0xd9 || _jpg_buf[_jpg_buf_len - 2] != 0xd9)) {
195-
esp_camera_fb_return(fb);
196-
return false;
197-
}
235+
fb = esp_camera_fb_get();
236+
if (!fb) {
237+
logger.error("Camera capture failed");
238+
return false;
239+
}
198240

199-
espp::JpegFrame image(reinterpret_cast<const char *>(_jpg_buf), _jpg_buf_len);
200-
rtsp_server.send_frame(image);
241+
_jpg_buf_len = fb->len;
242+
_jpg_buf = fb->buf;
201243

244+
if (!(_jpg_buf[_jpg_buf_len - 1] != 0xd9 || _jpg_buf[_jpg_buf_len - 2] != 0xd9)) {
202245
esp_camera_fb_return(fb);
203246
return false;
204-
};
205-
206-
auto camera_task = espp::Task::make_unique(
207-
{.callback = camera_task_fn, .task_config = {.name = "Camera Task", .priority = 10}});
208-
camera_task->start();
209-
210-
while (true) {
211-
std::this_thread::sleep_for(100ms);
212-
// print out some stats (battery, framerate)
213-
logger.info("Minimum free memory: {}, Battery voltage: {:.2f}",
214-
heap_caps_get_minimum_free_size(MALLOC_CAP_DEFAULT),
215-
timer_cam.get_battery_voltage());
216-
logger.move_up();
217-
logger.clear_line();
218247
}
219-
}
248+
249+
espp::JpegFrame image(reinterpret_cast<const char *>(_jpg_buf), _jpg_buf_len);
250+
rtsp_server->send_frame(image);
251+
252+
esp_camera_fb_return(fb);
253+
return false;
254+
};

sdkconfig.defaults

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,6 @@ CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=240
3333

3434
# ESP32-Camera specific
3535
CONFIG_SCCB_HARDWARE_I2C_DRIVER_LEGACY=y
36+
37+
# the cli library requires exceptions right now...
38+
CONFIG_COMPILER_CXX_EXCEPTIONS=y

0 commit comments

Comments
 (0)