Skip to content

Instantly share code, notes, and snippets.

@diramazioni
Last active January 26, 2024 17:15
Show Gist options
  • Save diramazioni/723cca91e0ce780c13f0690a207d46a0 to your computer and use it in GitHub Desktop.
Save diramazioni/723cca91e0ce780c13f0690a207d46a0 to your computer and use it in GitHub Desktop.
esp32 send image with websocket
#include "esp_camera.h"
#include <WiFi.h>
#include <ArduinoWebsockets.h>
// #include <algorithm>
// #include "soc/soc.h" //disable brownout problems
// #include "soc/rtc_cntl_reg.h" //disable brownout problems
#define CAMERA_MODEL_ESP32S3_EYE
#include "camera_pins.h"
#define LED_BUILT_IN 2
using namespace websockets;
WebsocketsClient client;
const char* ssid_Router = "xxxxxxxxxx";
const char* password_Router = "xxxxxxxxxxxxxx";
const char* ws_server_address = "wss://greenlab.unibo.it:443/ws";
String deviceString = "eli";
String endOfStreamMessage = "END_OF_STREAM-" + deviceString;
/*
To get the SSL certificate run:
openssl s_client -showcerts -connect socketsbay.com:443
See https://github.com/gilmaimon/ArduinoWebsockets/issues/101 for details.
*/
const char ssl_cert[] = \
"-----BEGIN CERTIFICATE-----\n"\
"MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/\n"\
"MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n"\
"DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow\n"\
"TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh\n"\
"cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwggIiMA0GCSqGSIb3DQEB\n"\
"AQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1coHIe+3LffOJCMbjzmV6B493XC\n"\
"ov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZshftEzPLpI9d1537O4/xLxIZpL\n"\
"wYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+lAOf00eXfJlII1PoOK5PCm+D\n"\
"LtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vrFk/CjhFLfs8L6P+1dy70sntK\n"\
"4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6shweU9GNx7C7ib1uYgeGJXDR5\n"\
"bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98flAgeYjzYIlefiN5YNNnWe+w5y\n"\
"sR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81LygXbNKYwagJZHduRze6zqxZ\n"\
"Xmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1pzpRboY7nn1ypxIFeFntPlF4\n"\
"FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0544fAQjQMNRbcTa0B7rBMDBc\n"\
"SLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K28Kh8hjtGqEgqiNx2mna/H2ql\n"\
"PRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdwiK1O5tmLOsbdJ1Fu/7xk9TND\n"\
"TwIDAQABo4IBRjCCAUIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw\n"\
"SwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5pZGVudHJ1\n"\
"c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTEp7Gkeyxx\n"\
"+tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEB\n"\
"ATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQu\n"\
"b3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0LmNvbS9E\n"\
"U1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFHm0WeZ7tuXkAXOACIjIGlj26Ztu\n"\
"MA0GCSqGSIb3DQEBCwUAA4IBAQAKcwBslm7/DlLQrt2M51oGrS+o44+/yQoDFVDC\n"\
"5WxCu2+b9LRPwkSICHXM6webFGJueN7sJ7o5XPWioW5WlHAQU7G75K/QosMrAdSW\n"\
"9MUgNTP52GE24HGNtLi1qoJFlcDyqSMo59ahy2cI2qBDLKobkx/J3vWraV0T9VuG\n"\
"WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O\n"\
"he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC\n"\
"Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5\n"\
"-----END CERTIFICATE-----\n";
extern TaskHandle_t loopTaskHandle;
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
Serial.println();
pinMode(LED_BUILT_IN, OUTPUT);
cameraSetup();
init_wifi();
init_ws();
//disableCore0WDT();
// WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
xTaskCreateUniversal(loopTask_Cmd, "loopTask_Cmd", 8192, NULL, 1, &loopTaskHandle, 0); //loopTask_Cmd uses core 0.
//xTaskCreateUniversal(loopTask_Blink, "loopTask_Blink", 8192, NULL, 1, &loopTaskHandle, 0);//loopTask_Blink uses core 0.
}
//task loop uses core 1.
void loop() {
client.poll();
delay(1000);
}
void loopTask_Cmd(void *pvParameters) {
Serial.println("Task send image with websocket starting ... ");
while (1) {
if (client.available()) {
camera_fb_t * fb = NULL;
// camera_fb_t *fb = esp_camera_fb_get();
fb = esp_camera_fb_get();
if (fb != NULL) {
// Send binary frame header
// uint8_t header[4];
// header[0] = 0b10000000 | 0b00000010; // FIN + Binary Opcode
// header[1] = fb->len < 126 ? fb->len : 126; // Payload length (7 bits)
// header[2] = fb->len >= 126 ? (fb->len >> 8) & 0xFF : 0; // Extended payload length (16 bits)
// header[3] = fb->len >= 126 ? fb->len & 0xFF : 0; // Extended payload length (16 bits)
// // Send frame header
// client.sendBinary((const char*)header, sizeof(header));
// Send binary data in chunks
for (size_t i = 0; i < fb->len; i += 1024) {
size_t chunkSize = std::min(static_cast<size_t>(1024), static_cast<size_t>(fb->len - i));
client.sendBinary((const char*)(fb->buf + i), chunkSize);
}
// Signal the end of the stream as bytes
//client.sendBinary("END_OF_STREAM", 13);
// Send the combined message as text
client.send(endOfStreamMessage);
esp_camera_fb_return(fb);
Serial.println("MJPG sent");
delay(5000);
} else {
Serial.println("Camera capture failed");
esp_camera_fb_return(fb);
ESP.restart();
}
} else {
Serial.println("WS client not available");
ESP.restart();
}
client.poll();
delay(1000);
}
}
void loopTask_Blink(void *pvParameters) {
Serial.println("Task Blink is starting ... ");
while (1) {
digitalWrite(LED_BUILT_IN, !digitalRead(LED_BUILT_IN));
delay(1000);
}
}
void init_wifi() {
WiFi.begin(ssid_Router, password_Router);
Serial.print("Connecting ");
Serial.print(ssid_Router);
while (WiFi.isConnected() != true) {
delay(500);
Serial.print(".");
//WiFi.begin(ssid_Router, password_Router);
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void init_ws() {
client.setCACert(ssl_cert);
Serial.println("WebSocket: Connecting ");
bool connected = client.connect(ws_server_address);
if (connected) {
Serial.println("WebSocket connected");
} else {
Serial.println("WebSocket connection failed.");
}
client.onMessage([&](WebsocketsMessage message) {
Serial.print("Got Message: ");
Serial.println(message.data());
});
}
void cameraSetup() {
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.frame_size = FRAMESIZE_UXGA;
config.pixel_format = PIXFORMAT_JPEG; // for streaming
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
config.fb_location = CAMERA_FB_IN_PSRAM;
config.jpeg_quality = 12;
config.fb_count = 1;
// if PSRAM IC present, init with UXGA resolution and higher JPEG quality
// for larger pre-allocated frame buffer.
if(psramFound()){
config.jpeg_quality = 10;
config.fb_count = 2;
config.grab_mode = CAMERA_GRAB_LATEST;
} else {
// Limit the frame size when PSRAM is not available
config.frame_size = FRAMESIZE_SVGA;
config.fb_location = CAMERA_FB_IN_DRAM;
}
// camera init
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}
sensor_t * s = esp_camera_sensor_get();
// initial sensors are flipped vertically and colors are a bit saturated
s->set_vflip(s, 1); // flip it back
s->set_brightness(s, 1); // up the brightness just a bit
s->set_saturation(s, 0); // lower the saturation
Serial.println("Camera configuration complete!");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment