tls handling and bug fixes
This commit is contained in:
@@ -2,16 +2,39 @@
|
||||
#include "esp_http_client.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "defines.h"
|
||||
#define httpSrv "http://192.168.1.190:3000/"
|
||||
#include "esp_crt_bundle.h"
|
||||
|
||||
std::string webToken;
|
||||
const std::string urlBase = std::string("http") + (secureSrv ? "s" : "") + "://" + srvAddr + "/";
|
||||
|
||||
esp_err_t _http_event_handler(esp_http_client_event_t *evt) {
|
||||
switch(evt->event_id) {
|
||||
case HTTP_EVENT_ON_DATA: {
|
||||
// Append received data to buffer (handles both chunked and non-chunked)
|
||||
if (evt->data_len > 0 && evt->user_data != NULL) {
|
||||
std::string* rxBuffer = (std::string*)evt->user_data;
|
||||
rxBuffer->append((char*)evt->data, evt->data_len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
bool httpGET(std::string endpoint, std::string token, cJSON* &JSONresponse) {
|
||||
std::string url = std::string(httpSrv) + endpoint;
|
||||
std::string url = urlBase + endpoint;
|
||||
std::string responseBuffer = "";
|
||||
|
||||
esp_http_client_config_t config = {};
|
||||
config.url = url.c_str();
|
||||
config.method = HTTP_METHOD_GET;
|
||||
config.event_handler = _http_event_handler; // Attach the bucket
|
||||
config.user_data = &responseBuffer; // Pass pointer to our string so the handler can write to it
|
||||
if (secureSrv) {
|
||||
config.transport_type = HTTP_TRANSPORT_OVER_SSL;
|
||||
config.crt_bundle_attach = esp_crt_bundle_attach;
|
||||
}
|
||||
|
||||
esp_http_client_handle_t client = esp_http_client_init(&config);
|
||||
|
||||
@@ -20,47 +43,21 @@ bool httpGET(std::string endpoint, std::string token, cJSON* &JSONresponse) {
|
||||
esp_http_client_set_header(client, "Authorization", authHeader.c_str());
|
||||
|
||||
// Open connection and fetch headers
|
||||
esp_err_t err = esp_http_client_open(client, 0);
|
||||
esp_err_t err = esp_http_client_perform(client);
|
||||
bool success = false;
|
||||
|
||||
if (err == ESP_OK) {
|
||||
int content_length = esp_http_client_fetch_headers(client);
|
||||
int status_code = esp_http_client_get_status_code(client);
|
||||
printf("Status = %d, Content Length = %d\n", status_code, esp_http_client_get_content_length(client));
|
||||
|
||||
printf("HTTP Status = %d, content_length = %d\n", status_code, content_length);
|
||||
|
||||
if (status_code == 200 && content_length > 0) {
|
||||
// Allocate buffer for the response
|
||||
char *buffer = (char *)malloc(content_length + 1);
|
||||
if (buffer) {
|
||||
int total_read = 0;
|
||||
int read_len;
|
||||
|
||||
// Read the response body
|
||||
while (total_read < content_length) {
|
||||
read_len = esp_http_client_read(client, buffer + total_read, content_length - total_read);
|
||||
if (read_len <= 0) break;
|
||||
total_read += read_len;
|
||||
if (status_code == 200) {
|
||||
printf("Response: %s\n", responseBuffer.c_str());
|
||||
JSONresponse = cJSON_Parse(responseBuffer.c_str());
|
||||
if (JSONresponse) success = true;
|
||||
}
|
||||
|
||||
buffer[total_read] = '\0';
|
||||
printf("Response body: %s\n", buffer);
|
||||
|
||||
JSONresponse = cJSON_Parse(buffer);
|
||||
success = (JSONresponse != NULL);
|
||||
|
||||
if (!success) {
|
||||
printf("Failed to parse JSON\n");
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
} else {
|
||||
printf("Failed to allocate buffer for response\n");
|
||||
printf("HTTP GET failed: %s\n", esp_err_to_name(err));
|
||||
}
|
||||
}
|
||||
|
||||
esp_http_client_close(client);
|
||||
} else printf("HTTP request failed: %s\n", esp_err_to_name(err));
|
||||
|
||||
esp_http_client_cleanup(client);
|
||||
return success;
|
||||
|
||||
@@ -27,14 +27,20 @@
|
||||
#define nvsServo "SERVO"
|
||||
#define posTag "POS"
|
||||
|
||||
#define ENCODER_PIN_A GPIO_NUM_23
|
||||
#define ENCODER_PIN_B GPIO_NUM_16
|
||||
#define secureSrv true
|
||||
// #define srvAddr "192.168.1.190:3000"
|
||||
#define srvAddr "wahwa.com"
|
||||
|
||||
#define InputEnc_PIN_A GPIO_NUM_1
|
||||
#define InputEnc_PIN_B GPIO_NUM_2
|
||||
#define ENCODER_PIN_A GPIO_NUM_23 // d5
|
||||
#define ENCODER_PIN_B GPIO_NUM_16 // d6
|
||||
|
||||
#define InputEnc_PIN_A GPIO_NUM_1 // d1
|
||||
#define InputEnc_PIN_B GPIO_NUM_2 // d2
|
||||
|
||||
#define servoPin GPIO_NUM_20
|
||||
#define servoLEDCChannel LEDC_CHANNEL_0
|
||||
#define servoSwitch GPIO_NUM_17
|
||||
|
||||
#define debugLED GPIO_NUM_22 // d4
|
||||
|
||||
#endif
|
||||
@@ -9,7 +9,8 @@ static const char *TAG = "ENCODER";
|
||||
// Constructor
|
||||
Encoder::Encoder(gpio_num_t pinA, gpio_num_t pinB)
|
||||
: pin_a(pinA), pin_b(pinB), count(0),
|
||||
last_state_a(0), last_state_b(0), last_count_base(0) {}
|
||||
last_state_a(0), last_state_b(0), last_count_base(0),
|
||||
watchdog_handle(nullptr) {}
|
||||
|
||||
// Static ISR - receives Encoder instance via arg
|
||||
void IRAM_ATTR Encoder::isr_handler(void* arg)
|
||||
@@ -48,7 +49,11 @@ void IRAM_ATTR Encoder::isr_handler(void* arg)
|
||||
encoder->count += 1;
|
||||
encoder->last_count_base -= 4;
|
||||
if (calibListen) servoCalibListen();
|
||||
if (encoder->feedWDog) esp_timer_restart(encoder->watchdog_handle, 500000);
|
||||
if (encoder->feedWDog) {
|
||||
esp_timer_stop(encoder->watchdog_handle);
|
||||
esp_timer_start_once(encoder->watchdog_handle, 500000);
|
||||
debugLEDTgl();
|
||||
}
|
||||
if (encoder->wandListen) servoWandListen();
|
||||
if (encoder->serverListen) servoServerListen();
|
||||
}
|
||||
@@ -56,7 +61,11 @@ void IRAM_ATTR Encoder::isr_handler(void* arg)
|
||||
encoder->count -= 1;
|
||||
encoder->last_count_base += 4;
|
||||
if (calibListen) servoCalibListen();
|
||||
if (encoder->feedWDog) esp_timer_restart(encoder->watchdog_handle, 500000);
|
||||
if (encoder->feedWDog) {
|
||||
esp_timer_stop(encoder->watchdog_handle);
|
||||
esp_timer_start_once(encoder->watchdog_handle, 500000);
|
||||
debugLEDTgl();
|
||||
}
|
||||
if (encoder->wandListen) servoWandListen();
|
||||
if (encoder->serverListen) servoServerListen();
|
||||
}
|
||||
@@ -107,9 +116,9 @@ void Encoder::setupWatchdog() {
|
||||
feedWDog = true;
|
||||
}
|
||||
|
||||
void Encoder::pauseWatchdog() {
|
||||
void IRAM_ATTR Encoder::pauseWatchdog() {
|
||||
if (watchdog_handle != nullptr) esp_timer_stop(watchdog_handle);
|
||||
feedWDog = false;
|
||||
if (watchdog_handle != NULL) esp_timer_stop(watchdog_handle);
|
||||
}
|
||||
|
||||
Encoder::~Encoder() {
|
||||
|
||||
@@ -41,8 +41,14 @@ void servoInit() {
|
||||
gpio_set_direction(servoSwitch, GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(servoSwitch, 0); // Start with servo power off
|
||||
|
||||
// Configure debug LED pin as output
|
||||
gpio_reset_pin(GPIO_NUM_22);
|
||||
gpio_set_direction(debugLED, GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(debugLED, 0); // Start with LED off
|
||||
|
||||
topEnc->count = servoReadPos();
|
||||
if (calib.getCalibrated()) initMainLoop();
|
||||
debugLEDSwitch(1);
|
||||
}
|
||||
|
||||
void servoOn(uint8_t dir, uint8_t manOrServer) {
|
||||
@@ -65,13 +71,22 @@ void servoMainSwitch(uint8_t onOff) {
|
||||
gpio_set_level(servoSwitch, onOff ? 1 : 0);
|
||||
}
|
||||
|
||||
void debugLEDSwitch(uint8_t onOff) {
|
||||
gpio_set_level(debugLED, onOff ? 1 : 0);
|
||||
}
|
||||
|
||||
void debugLEDTgl() {
|
||||
static bool onOff = false;
|
||||
gpio_set_level(debugLED, onOff);
|
||||
onOff = !onOff;
|
||||
}
|
||||
|
||||
bool servoInitCalib() {
|
||||
topEnc->pauseWatchdog();
|
||||
|
||||
// get ready for calibration by clearing all these listeners
|
||||
bottomEnc->wandListen = false;
|
||||
topEnc->wandListen = false;
|
||||
topEnc->serverListen = false;
|
||||
bottomEnc->wandListen.store(false, std::memory_order_release);
|
||||
topEnc->wandListen.store(false, std::memory_order_release);
|
||||
topEnc->serverListen.store(false, std::memory_order_release);
|
||||
if (!calib.clearCalibrated()) return false;
|
||||
if (topEnc == nullptr || bottomEnc == nullptr) {
|
||||
printf("ERROR: CALIBRATION STARTED BEFORE SERVO INITIALIZATION\n");
|
||||
@@ -82,11 +97,20 @@ bool servoInitCalib() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void servoCancelCalib() {
|
||||
calibListen = false;
|
||||
servoOff();
|
||||
}
|
||||
|
||||
void servoCalibListen() {
|
||||
int32_t effDiff = (bottomEnc->getCount() - topEnc->getCount()) - baseDiff;
|
||||
if (effDiff > 1) servoOn(CCW, manual);
|
||||
else if (effDiff < -1) servoOn(CW, manual);
|
||||
else servoOff();
|
||||
else if (effDiff < -1) {
|
||||
servoOn(CW, manual);
|
||||
}
|
||||
else {
|
||||
servoOff();
|
||||
}
|
||||
}
|
||||
|
||||
bool servoBeginDownwardCalib() {
|
||||
@@ -111,7 +135,7 @@ bool servoCompleteCalib() {
|
||||
void initMainLoop() {
|
||||
topEnc->setupWatchdog();
|
||||
servoSavePos();
|
||||
bottomEnc->wandListen = true;
|
||||
bottomEnc->wandListen.store(true, std::memory_order_release);
|
||||
}
|
||||
|
||||
void IRAM_ATTR watchdogCallback(void* arg) {
|
||||
@@ -121,9 +145,9 @@ void IRAM_ATTR watchdogCallback(void* arg) {
|
||||
topEnc->pauseWatchdog();
|
||||
|
||||
// get ready for recalibration by clearing all these listeners
|
||||
bottomEnc->wandListen = false;
|
||||
topEnc->wandListen = false;
|
||||
topEnc->serverListen = false;
|
||||
bottomEnc->wandListen.store(false, std::memory_order_release);
|
||||
topEnc->wandListen.store(false, std::memory_order_release);
|
||||
topEnc->serverListen.store(false, std::memory_order_release);
|
||||
servoOff();
|
||||
}
|
||||
else {
|
||||
@@ -170,7 +194,7 @@ int32_t servoReadPos() {
|
||||
|
||||
void stopServerRun() {
|
||||
// stop listener and stop running if serverRun is still active.
|
||||
topEnc->serverListen = false;
|
||||
topEnc->serverListen.store(false, std::memory_order_release);
|
||||
if (runningServer) servoOff();
|
||||
}
|
||||
|
||||
@@ -199,21 +223,27 @@ void servoWandListen() {
|
||||
// if effective difference is 0, stop servo and servo-listener
|
||||
// otherwise, run servo in whichever direction necessary and
|
||||
// ensure servo-listener is active.
|
||||
if (abs(topCount - upBound) <= 1 || abs(topCount - downBound) <= 1) {
|
||||
if (topCount >= (MAX(upBound, downBound) - 1)
|
||||
&& effDiff > 1) { // TODO: see whether these margins need to be removed.
|
||||
servoOff();
|
||||
topEnc->wandListen = false;
|
||||
topEnc->wandListen.store(false, std::memory_order_release);
|
||||
}
|
||||
else if (topCount <= (MIN(upBound, downBound) + 1)
|
||||
&& effDiff < -1) {
|
||||
servoOff();
|
||||
topEnc->wandListen.store(false, std::memory_order_release);
|
||||
}
|
||||
else if (effDiff > 1) {
|
||||
topEnc->wandListen = true;
|
||||
topEnc->wandListen.store(true, std::memory_order_release);
|
||||
servoOn(CCW, manual);
|
||||
}
|
||||
else if (effDiff < -1) {
|
||||
topEnc->wandListen = true;
|
||||
topEnc->wandListen.store(true, std::memory_order_release);
|
||||
servoOn(CW, manual);
|
||||
}
|
||||
else {
|
||||
servoOff();
|
||||
topEnc->wandListen = false;
|
||||
topEnc->wandListen.store(false, std::memory_order_release);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,14 +260,16 @@ void runToAppPos(uint8_t appPos) {
|
||||
if (runningManual || !calib.getCalibrated()) return;
|
||||
servoOff();
|
||||
|
||||
target = calib.convertToTicks(appPos); // calculate target encoder position
|
||||
printf("runToAppPos Called, running to %d from %d", target.load(), topEnc->getCount());
|
||||
|
||||
// allow servo position to settle
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
int32_t topCount = topEnc->getCount();
|
||||
target = calib.convertToTicks(appPos); // calculate target encoder position
|
||||
if (abs(topCount - target) <= 1) return;
|
||||
startLess = topCount < target;
|
||||
if (runningManual) return; // check again before starting remote control
|
||||
if (startLess) servoOn(CCW, server); // begin servo movement
|
||||
else servoOn(CW, server);
|
||||
topEnc->serverListen = true; // start listening for shutoff point
|
||||
topEnc->serverListen.store(true, std::memory_order_release); // start listening for shutoff point
|
||||
}
|
||||
@@ -25,6 +25,9 @@ void servoCalibListen();
|
||||
bool servoInitCalib();
|
||||
bool servoBeginDownwardCalib();
|
||||
bool servoCompleteCalib();
|
||||
void servoCancelCalib();
|
||||
void debugLEDSwitch(uint8_t onOff);
|
||||
void debugLEDTgl();
|
||||
|
||||
void initMainLoop();
|
||||
void watchdogCallback(void* arg);
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "cJSON.h"
|
||||
#include "calibration.hpp"
|
||||
#include "servo.hpp"
|
||||
#include "defines.h"
|
||||
#include "esp_crt_bundle.h"
|
||||
|
||||
static esp_socketio_client_handle_t io_client;
|
||||
static esp_socketio_packet_handle_t tx_packet = NULL;
|
||||
@@ -139,8 +141,15 @@ static void socketio_event_handler(void *handler_args, esp_event_base_t base,
|
||||
emitCalibError("Non-1 Port");
|
||||
}
|
||||
else {
|
||||
if (!servoInitCalib()) emitCalibError("Initialization failed");
|
||||
else emitCalibStage1Ready();
|
||||
printf("Running initCalib...\n");
|
||||
if (!servoInitCalib()) {
|
||||
printf("initCalib returned False\n");
|
||||
emitCalibError("Initialization failed");
|
||||
}
|
||||
else {
|
||||
printf("Ready to calibrate\n");
|
||||
emitCalibStage1Ready();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -185,6 +194,24 @@ static void socketio_event_handler(void *handler_args, esp_event_base_t base,
|
||||
}
|
||||
}
|
||||
|
||||
// Handle user_stage1_complete event
|
||||
else if (strcmp(eventName->valuestring, "cancel_calib") == 0) {
|
||||
printf("Canceling calibration process...\n");
|
||||
cJSON *data = cJSON_GetArrayItem(json, 1);
|
||||
if (data) {
|
||||
cJSON *port = cJSON_GetObjectItem(data, "port");
|
||||
if (port && cJSON_IsNumber(port)) {
|
||||
if (port->valueint != 1) {
|
||||
printf("Error, non-1 port received for calibration\n");
|
||||
emitCalibError("Non-1 Port");
|
||||
}
|
||||
else {
|
||||
servoCancelCalib();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle server position change (manual or scheduled)
|
||||
else if (strcmp(eventName->valuestring, "posUpdates") == 0) {
|
||||
printf("Received position update from server\n");
|
||||
@@ -225,18 +252,47 @@ static void socketio_event_handler(void *handler_args, esp_event_base_t base,
|
||||
|
||||
case SOCKETIO_EVENT_ERROR: {
|
||||
printf("Socket.IO Error!\n");
|
||||
|
||||
// Check WebSocket error details
|
||||
servoCancelCalib();
|
||||
esp_websocket_event_data_t *ws_event = data->websocket_event;
|
||||
if (ws_event && ws_event->error_handle.esp_ws_handshake_status_code != 0) {
|
||||
printf("HTTP Status: %d\n", ws_event->error_handle.esp_ws_handshake_status_code);
|
||||
if (ws_event->error_handle.esp_ws_handshake_status_code == 401 ||
|
||||
ws_event->error_handle.esp_ws_handshake_status_code == 403) {
|
||||
printf("Authentication failed - invalid token\n");
|
||||
|
||||
if (ws_event) {
|
||||
// 1. Check for TLS/SSL specific errors (Certificate issues)
|
||||
if (ws_event->error_handle.error_type == WEBSOCKET_ERROR_TYPE_TCP_TRANSPORT) {
|
||||
|
||||
// This prints the "MbedTLS" error code (The low-level crypto library)
|
||||
// Common codes: -0x2700 (CRT verify failed), -0x7200 (SSL handshake failed)
|
||||
if (ws_event->error_handle.esp_tls_stack_err != 0) {
|
||||
printf("TLS/SSL Stack Error: -0x%x\n", -ws_event->error_handle.esp_tls_stack_err);
|
||||
}
|
||||
|
||||
// 2. Check the Certificate Verification Flags
|
||||
// If this is non-zero, the certificate was rejected.
|
||||
if (ws_event->error_handle.esp_tls_cert_verify_flags != 0) {
|
||||
uint32_t flags = ws_event->error_handle.esp_tls_cert_verify_flags;
|
||||
printf("Certificate Verification FAILED. Flags: 0x%lx\n", flags);
|
||||
|
||||
// Simple decoder for common flags:
|
||||
if (flags & (1 << 0)) printf(" - CRT_NOT_TRUSTED (Root CA not found in bundle)\n");
|
||||
if (flags & (1 << 1)) printf(" - CRT_BAD_KEY_USAGE\n");
|
||||
if (flags & (1 << 2)) printf(" - CRT_EXPIRED (Check your ESP32 system time!)\n");
|
||||
if (flags & (1 << 3)) printf(" - CRT_CN_MISMATCH (Domain name doesn't match cert)\n");
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Check for HTTP Handshake errors (401/403/404)
|
||||
// This happens if SSL worked, but the server rejected your path or token
|
||||
else if (ws_event->error_handle.error_type == WEBSOCKET_ERROR_TYPE_HANDSHAKE) {
|
||||
int status = ws_event->error_handle.esp_ws_handshake_status_code;
|
||||
printf("HTTP Handshake Error: %d\n", status);
|
||||
|
||||
if (status == 401 || status == 403) {
|
||||
printf("Authentication failed - invalid token\n");
|
||||
} else if (status == 404) {
|
||||
printf("404 Not Found - Check your URI/Path\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set flags to indicate connection failure
|
||||
connected = false;
|
||||
statusResolved = true;
|
||||
break;
|
||||
@@ -251,6 +307,7 @@ static void socketio_event_handler(void *handler_args, esp_event_base_t base,
|
||||
}
|
||||
}
|
||||
|
||||
const std::string uriString = std::string("ws") + (secureSrv ? "s" : "") + "://" + srvAddr + "/socket.io/?EIO=4&transport=websocket";
|
||||
void initSocketIO() {
|
||||
// Prepare the Authorization Header (Bearer format)
|
||||
std::string authHeader = "Authorization: Bearer " + webToken + "\r\n";
|
||||
@@ -259,9 +316,14 @@ void initSocketIO() {
|
||||
connected = false;
|
||||
|
||||
esp_socketio_client_config_t config = {};
|
||||
config.websocket_config.uri = "ws://192.168.1.190:3000/socket.io/?EIO=4&transport=websocket";
|
||||
config.websocket_config.uri = uriString.c_str();
|
||||
config.websocket_config.headers = authHeader.c_str();
|
||||
|
||||
if (secureSrv) {
|
||||
config.websocket_config.transport = WEBSOCKET_TRANSPORT_OVER_SSL;
|
||||
config.websocket_config.crt_bundle_attach = esp_crt_bundle_attach;
|
||||
}
|
||||
|
||||
io_client = esp_socketio_client_init(&config);
|
||||
tx_packet = esp_socketio_client_get_tx_packet(io_client);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user