Initial commit

This commit is contained in:
Skye
2026-06-06 13:52:56 +01:00
commit 40ef749621
2 changed files with 238 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
.theia/
+237
View File
@@ -0,0 +1,237 @@
#include "esp_task_wdt.h" // watchdogs
#include <WiFi.h> // WiFi connection
#include <ESPAsyncWebServer.h>
#include <stdio.h>
#include "driver/gpio.h"
#include <ESPmDNS.h>
///////////////////////////////////////////////////////////////////////////////
/// Watchdogs Settings
#define WDT_TIMEOUT 60000
#define WDT_CONFIG_FREERTOS_NUMBER_OF_CORES 1 // If one core doesn't work, try 2
esp_task_wdt_config_t twdt_config = {
.timeout_ms = WDT_TIMEOUT,
.idle_core_mask = (1 << WDT_CONFIG_FREERTOS_NUMBER_OF_CORES) - 1, // Bitmask of all cores
.trigger_panic = true,
}; // Bugfixes for hardware watchdog on arduino-esp32 3.x
///////////////////////////////////////////////////////////////////////////////
/// WiFi Settings
//#define WIFI_SSID "FlannelFlat1"
//#define WIFI_PASSWORD "CosySquares4Life:3"
#define WIFI_SSID "Hacklab"
#define WIFI_PASSWORD "piranhas"
#define WIFI_HOSTNAME "MediaServerSwitch"
///////////////////////////////////////////////////////////////////////////////
/// HTTP Server Setup
AsyncWebServer server(80);
///////////////////////////////////////////////////////////////////////////////
/// Pin Setup
#define PIN_POWER_RELAY 23
#define PIN_RESTART_RELAY 19
#define PIN_STATUS_LED 35
#define PIN_POWER_BTN 27
const char* WiFiCodeToString(int code) {
const char* status;
switch (code) {
case 0: status = "IDLE STATUS"; break;
case 1: status = "NO SSID AVAILABLE"; break;
case 2: status = "SCAN COMPLETE"; break;
case 3: status = "CONNECTED"; break;
case 4: status = "CONNECT FAILED"; break;
case 5: status = "CONNECTION L\sOST"; break;
case 6: status = "DISCONNECTED"; break;
case 255: status = "NO SHIELD"; break;
default: status = "UNKNOWN"; break;
}
return status;
}
void setup() {
Serial.begin(9600);
///////////////////////////////////////////////////////////////////////////
/// Watchdog Setup
Serial.print("Configuring WDT... ");
esp_task_wdt_deinit(); // WDT is enabled by default, deinit
esp_task_wdt_init(&twdt_config); // Enable panic so ESP32 restarts
esp_task_wdt_add(NULL); // Add current thread to WDT watch
Serial.println("Success");
///////////////////////////////////////////////////////////////////////////
/// Pin Setup
pinMode(PIN_POWER_RELAY, OUTPUT); // Power Button
pinMode(PIN_RESTART_RELAY, OUTPUT); // Restart Button
pinMode(PIN_STATUS_LED, INPUT); // Status LED
pinMode(PIN_POWER_BTN, INPUT); // Power Button Passthrough
///////////////////////////////////////////////////////////////////////////
/// WiFi Setup
esp_task_wdt_reset(); // Feed the watchdog
Serial.print("Setting up WiFi... ");
WiFi.mode(WIFI_STA);
WiFi.setHostname(WIFI_HOSTNAME);
MDNS.begin(WIFI_HOSTNAME);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.print("Connecting to Network... ");
unsigned short count = 0;
unsigned long last = millis();
while (WiFi.status() != WL_CONNECTED) {
if (count > 60) {
Serial.println("Failed to connect, restarting");
ESP.restart();
} else if (millis() - last > 1000) {
Serial.print(".");
last = millis();
count++;
}
}
WiFi.persistent(false);
Serial.print(" Connected with IP: ");
Serial.print(WiFi.localIP());
Serial.print(" and Hostname: ");
Serial.println(WIFI_HOSTNAME);
esp_task_wdt_reset(); // Feed the watchdog
int ch = WiFi.channel();
bool is5GHz = (ch >= 36);
Serial.printf("Channel: %d (%s GHz), RSSI: %d dBm\n", ch, is5GHz ? "5" : "2.4", WiFi.RSSI());
///////////////////////////////////////////////////////////////////////////
/// Web Server
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(200, "text/plain",
"/ping Pong\n"
"/status Get ESP and PC status\n"
"/power Press the power button\n"
"/power-long Hold down the power button (for force stops)\n"
"/restart-pc Press the restart button on the PC\n"
"/restart-ESP Shut down the server and restart the whole ESP\n");
});
server.on("/ping", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(200, "text/plain", "pong");
});
server.on("/status", HTTP_GET, [ch, is5GHz](AsyncWebServerRequest *request) {
char* result;
asprintf(&result, "IP: %s, Hostname: %s, Status: %s, Channel: %d (%s GHz), RSSI: %d dBm\n", WiFi.localIP().toString().c_str(), WIFI_HOSTNAME, WiFiCodeToString(WiFi.status()), ch, is5GHz ? "5" : "2.4", WiFi.RSSI());
request->send(200, "text/plain", result);
free(result);
});
server.on("/power", HTTP_POST, [](AsyncWebServerRequest *request) {
digitalWrite(PIN_POWER_RELAY, HIGH);
delay(500);
digitalWrite(PIN_POWER_RELAY, LOW);
request->send(200, "text/plain", "200 OK");
});
server.on("/power-long", HTTP_POST, [](AsyncWebServerRequest *request) {
digitalWrite(PIN_POWER_RELAY, HIGH);
delay(5000);
digitalWrite(PIN_POWER_RELAY, LOW);
request->send(200, "text/plain", "200 OK");
});
server.on("/restart-pc", HTTP_POST, [](AsyncWebServerRequest *request) {
digitalWrite(PIN_RESTART_RELAY, HIGH);
delay(1000);
digitalWrite(PIN_RESTART_RELAY, LOW);
request->send(200, "text/plain", "200 OK");
});
server.on("/restart-ESP", HTTP_POST, [](AsyncWebServerRequest *request) {
request->send(202, "text/plain", "202 Accepted. Good Night.");
delay(500);
server.end();
ESP.restart();
});
server.on("/activate", HTTP_POST, [](AsyncWebServerRequest *request) {
if (!request->hasParam("pin", true) || !request->hasParam("duration", true)) {
request->send(400, "text/plain", "400 Bad Request. Missing 'pin' or 'duration' parameter");
return;
}
int pin = request->getParam("pin", true)->value().toInt();
long duration = strtol(request->getParam("duration", true)->value().c_str(), NULL, 10);
if (!GPIO_IS_VALID_GPIO((gpio_num_t)pin)) {
request->send(400, "text/plain", "Invalid pin for this ESP32");
return;
}
if (duration <= 0 || duration > 3600000) {
request->send(400, "text/plain", "400 Bad Request. Duration must be between 1ms and 3600000ms");
return;
}
gpio_io_config_t* pin_mode;
gpio_get_io_config((gpio_num_t)pin, pin_mode);
if (pin_mode->oe == true) {
if (pin_mode->ie != true) {
request->send(400, "text/plain", "Pin is configured as input");
return;
}
// Configure pin as output
gpio_config_t config = {};
config.pin_bit_mask = (1ULL << pin);
config.mode = GPIO_MODE_OUTPUT;
config.pull_up_en = GPIO_PULLUP_DISABLE;
config.pull_down_en = GPIO_PULLDOWN_DISABLE;
config.intr_type = GPIO_INTR_DISABLE;
if (gpio_config(&config) != ESP_OK) {
request->send(400, "text/plain", "Bad Request. Cannot configure pin as output");
return;
}
}
gpio_set_level((gpio_num_t)pin, HIGH);
delay(duration);
gpio_set_level((gpio_num_t)pin, LOW);
delay(10); // allow change to propagate
// unconfigure pin
gpio_reset_pin((gpio_num_t)pin);
request->send(200, "text/plain", "OK");
});
server.begin();
}
unsigned long last = millis();
void loop() {
if (millis() - last > 10000) {
Serial.print("Heartbeat. WiFi Status: ");
Serial.println(WiFiCodeToString(WiFi.status()));
esp_task_wdt_reset(); // Feed the watchdog
last = millis();
}
if (WiFi.status() != WL_CONNECTED) { // you can use WiFi.setAutoReconnect(true); but i rather this for custom behaviour.
Serial.println("Disconnected from network, restarting.");
ESP.restart();
}
}