mirror of
https://github.com/easytarget/esp32-cam-webserver.git
synced 2024-02-16 18:18:24 +08:00
Multi wifi (#64)
* Multi-Wifi with best signal scanning and retry when disconnected * AP mode; can work (optionally) as a fallback when no network found * Captive portal * Dump output tweaks * Config file comments
This commit is contained in:
@ -40,6 +40,9 @@ extern char streamURL[];
|
||||
extern int8_t detection_enabled;
|
||||
extern int8_t recognition_enabled;
|
||||
extern bool filesystem;
|
||||
extern bool accesspoint;
|
||||
extern bool captivePortal;
|
||||
extern char apName[];
|
||||
extern int httpPort;
|
||||
extern int streamPort;
|
||||
extern IPAddress ip;
|
||||
@ -180,7 +183,7 @@ static void draw_face_boxes(dl_matrix3du_t *image_matrix, box_array_t *boxes, in
|
||||
fb_gfx_drawFastHLine(&fb, x, y+h-1, w, color);
|
||||
fb_gfx_drawFastVLine(&fb, x, y, h, color);
|
||||
fb_gfx_drawFastVLine(&fb, x+w-1, y, h, color);
|
||||
#if 0
|
||||
#if 0
|
||||
// landmark
|
||||
int x0, y0, j;
|
||||
for (j = 0; j < 10; j+=2) {
|
||||
@ -188,7 +191,7 @@ static void draw_face_boxes(dl_matrix3du_t *image_matrix, box_array_t *boxes, in
|
||||
y0 = (int)boxes->landmark[i].landmark_p[j+1];
|
||||
fb_gfx_fillRect(&fb, x0, y0, 3, 3, color);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -602,10 +605,10 @@ static esp_err_t cmd_handler(httpd_req_t *req){
|
||||
Serial.print("REBOOT requested");
|
||||
for (int i=0; i<20; i++) {
|
||||
flashLED(50);
|
||||
delay(50);
|
||||
delay(150);
|
||||
Serial.print('.');
|
||||
}
|
||||
Serial.printf("\nThats all folks...\n\n");
|
||||
Serial.printf(" Thats all folks!\n\n");
|
||||
ESP.restart();
|
||||
}
|
||||
else {
|
||||
@ -725,19 +728,43 @@ static esp_err_t dump_handler(httpd_req_t *req){
|
||||
Serial.printf("ESP sdk: %s\n", ESP.getSdkVersion());
|
||||
// Network
|
||||
d+= sprintf(d,"<h2>WiFi</h2>\n");
|
||||
String ssidName = WiFi.SSID();
|
||||
d+= sprintf(d,"SSID: %s<br>\n", ssidName.c_str());
|
||||
Serial.printf("Ssid: %s\n", ssidName.c_str());
|
||||
d+= sprintf(d,"Rssi: %i<br>\n", WiFi.RSSI());
|
||||
Serial.printf("Rssi: %i\n", WiFi.RSSI());
|
||||
d+= sprintf(d,"Http port: %i, Stream port: %i<br>\n", httpPort, streamPort);
|
||||
Serial.printf("Http port: %i, Stream port: %i\n", httpPort, streamPort);
|
||||
if (accesspoint) {
|
||||
if (captivePortal) {
|
||||
d+= sprintf(d,"Mode: AccessPoint with captive portal<br>\n");
|
||||
Serial.printf("Mode: AccessPoint with captive portal\n");
|
||||
} else {
|
||||
d+= sprintf(d,"Mode: AccessPoint<br>\n");
|
||||
Serial.printf("Mode: AccessPoint\n");
|
||||
}
|
||||
d+= sprintf(d,"SSID: %s<br>\n", apName);
|
||||
Serial.printf("SSID: %s\n", apName);
|
||||
} else {
|
||||
d+= sprintf(d,"Mode: Client<br>\n");
|
||||
Serial.printf("Mode: Client\n");
|
||||
String ssidName = WiFi.SSID();
|
||||
d+= sprintf(d,"SSID: %s<br>\n", ssidName.c_str());
|
||||
Serial.printf("Ssid: %s\n", ssidName.c_str());
|
||||
d+= sprintf(d,"Rssi: %i<br>\n", WiFi.RSSI());
|
||||
Serial.printf("Rssi: %i\n", WiFi.RSSI());
|
||||
String bssid = WiFi.BSSIDstr();
|
||||
d+= sprintf(d,"BSSID: %s<br>\n", bssid.c_str());
|
||||
Serial.printf("BSSID: %s\n", bssid.c_str());
|
||||
}
|
||||
d+= sprintf(d,"IP address: %d.%d.%d.%d<br>\n", ip[0], ip[1], ip[2], ip[3]);
|
||||
Serial.printf("IP address: %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
|
||||
d+= sprintf(d,"Netmask: %d.%d.%d.%d<br>\n", net[0], net[1], net[2], net[3]);
|
||||
Serial.printf("Netmask: %d.%d.%d.%d\n", net[0], net[1], net[2], net[3]);
|
||||
d+= sprintf(d,"Gateway: %d.%d.%d.%d<br>\n", gw[0], gw[1], gw[2], gw[3]);
|
||||
Serial.printf("Gateway: %d.%d.%d.%d\n", gw[0], gw[1], gw[2], gw[3]);
|
||||
if (!accesspoint) {
|
||||
d+= sprintf(d,"Netmask: %d.%d.%d.%d<br>\n", net[0], net[1], net[2], net[3]);
|
||||
Serial.printf("Netmask: %d.%d.%d.%d\n", net[0], net[1], net[2], net[3]);
|
||||
d+= sprintf(d,"Gateway: %d.%d.%d.%d<br>\n", gw[0], gw[1], gw[2], gw[3]);
|
||||
Serial.printf("Gateway: %d.%d.%d.%d\n", gw[0], gw[1], gw[2], gw[3]);
|
||||
}
|
||||
d+= sprintf(d,"Http port: %i, Stream port: %i<br>\n", httpPort, streamPort);
|
||||
Serial.printf("Http port: %i, Stream port: %i\n", httpPort, streamPort);
|
||||
byte mac[6];
|
||||
WiFi.macAddress(mac);
|
||||
d+= sprintf(d,"MAC: %02X:%02X:%02X:%02X:%02X:%02X<br>\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
Serial.printf("MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
|
||||
// System
|
||||
d+= sprintf(d,"<h2>System</h2>\n");
|
||||
int64_t sec = esp_timer_get_time() / 1000000;
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "esp_camera.h"
|
||||
#include <WiFi.h>
|
||||
#include <DNSServer.h>
|
||||
|
||||
/* This sketch is a extension/expansion/reork of the 'official' ESP32 Camera example
|
||||
* sketch from Expressif:
|
||||
@ -22,25 +23,20 @@
|
||||
/*
|
||||
* FOR NETWORK AND HARDWARE SETTINGS COPY OR RENAME 'myconfig.sample.h' TO 'myconfig.h' AND EDIT THAT.
|
||||
*
|
||||
* By default this sketch will assume an AI-THINKER ESP-CAM and create
|
||||
* By default this sketch will assume an AI-THINKER ESP-CAM and create
|
||||
* an accesspoint called "ESP32-CAM-CONNECT" (password: "InsecurePassword")
|
||||
*
|
||||
*/
|
||||
|
||||
// Primary config, or defaults.
|
||||
#if __has_include("myconfig.h")
|
||||
// I keep my settings in a seperate header file
|
||||
#include "myconfig.h"
|
||||
#include "myconfig.h"
|
||||
#else
|
||||
#warning "Using Default Settings: Copy myconfig.sample.h to myconfig.h and edit that to set your personal defaults"
|
||||
// These are the defaults.. dont edit these.
|
||||
// copy myconfig.sample.h to myconfig.h and edit that instead
|
||||
// SSID, Password and Mode
|
||||
const char* ssid = "ESP32-CAM-CONNECT";
|
||||
const char* password = "InsecurePassword";
|
||||
#define WIFI_AP_ENABLE
|
||||
// Default Board and Camera:
|
||||
#define CAMERA_MODEL_AI_THINKER
|
||||
#warning "Using Defaults: Copy myconfig.sample.h to myconfig.h and edit that to use your own settings"
|
||||
#define WIFI_AP_ENABLE
|
||||
#define CAMERA_MODEL_AI_THINKER
|
||||
struct station { const char ssid[64]; const char password[64]; const bool dhcp;}
|
||||
stationList[] = {{"ESP32-CAM-CONNECT","InsecurePassword", true}};
|
||||
#endif
|
||||
|
||||
// Pin Mappings
|
||||
@ -55,7 +51,11 @@ int sketchSize;
|
||||
int sketchSpace;
|
||||
String sketchMD5;
|
||||
|
||||
// IP address, netmask and gateway
|
||||
// Start with accesspoint mode disabled, wifi setup will activate it if
|
||||
// no known networks are found, and WIFI_AP_ENABLE has been defined
|
||||
bool accesspoint = false;
|
||||
|
||||
// IP address, Netmask and Gateway, populated when connected
|
||||
IPAddress ip;
|
||||
IPAddress net;
|
||||
IPAddress gw;
|
||||
@ -65,28 +65,44 @@ extern void startCameraServer(int hPort, int sPort);
|
||||
|
||||
// A Name for the Camera. (set in myconfig.h)
|
||||
#if defined(CAM_NAME)
|
||||
char myName[] = CAM_NAME;
|
||||
char myName[] = CAM_NAME;
|
||||
#else
|
||||
char myName[] = "ESP32 camera server";
|
||||
char myName[] = "ESP32 camera server";
|
||||
#endif
|
||||
|
||||
// Ports for http and stream (override in myconfig.h)
|
||||
#if defined(HTTP_PORT)
|
||||
int httpPort = HTTP_PORT;
|
||||
int httpPort = HTTP_PORT;
|
||||
#else
|
||||
int httpPort = 80;
|
||||
int httpPort = 80;
|
||||
#endif
|
||||
|
||||
#if defined(STREAM_PORT)
|
||||
int streamPort = STREAM_PORT;
|
||||
int streamPort = STREAM_PORT;
|
||||
#else
|
||||
int streamPort = 81;
|
||||
int streamPort = 81;
|
||||
#endif
|
||||
|
||||
#if !defined(WIFI_WATCHDOG)
|
||||
#define WIFI_WATCHDOG 5000
|
||||
#define WIFI_WATCHDOG 5000
|
||||
#endif
|
||||
|
||||
// Number of known networks in stationList[]
|
||||
int stationCount = sizeof(stationList)/sizeof(stationList[0]);
|
||||
|
||||
// If we have AP mode enabled, ignore first entry in the stationList[]
|
||||
#if defined(WIFI_AP_ENABLE)
|
||||
int firstStation = 1;
|
||||
#else
|
||||
int firstStation = 0;
|
||||
#endif
|
||||
|
||||
// DNS server
|
||||
const byte DNS_PORT = 53;
|
||||
DNSServer dnsServer;
|
||||
bool captivePortal = false;
|
||||
char apName[64] = "Undefined";
|
||||
|
||||
// The stream URL
|
||||
char streamURL[64] = {"Undefined"}; // Stream URL to pass to the app.
|
||||
|
||||
@ -96,21 +112,21 @@ char myVer[] PROGMEM = __DATE__ " @ " __TIME__;
|
||||
// initial rotation
|
||||
// can be set in myconfig.h
|
||||
#if !defined(CAM_ROTATION)
|
||||
#define CAM_ROTATION 0
|
||||
#define CAM_ROTATION 0
|
||||
#endif
|
||||
int myRotation = CAM_ROTATION;
|
||||
|
||||
// Illumination LAMP/LED
|
||||
#if defined(LAMP_DISABLE)
|
||||
int lampVal = -1; // lamp is disabled in config
|
||||
int lampVal = -1; // lamp is disabled in config
|
||||
#elif defined(LAMP_PIN)
|
||||
#if defined(LAMP_DEFAULT)
|
||||
int lampVal = constrain(LAMP_DEFAULT,0,100); // initial lamp value, range 0-100
|
||||
#else
|
||||
int lampVal = 0; //default to off
|
||||
#endif
|
||||
#if defined(LAMP_DEFAULT)
|
||||
int lampVal = constrain(LAMP_DEFAULT,0,100); // initial lamp value, range 0-100
|
||||
#else
|
||||
int lampVal = 0; //default to off
|
||||
#endif
|
||||
#else
|
||||
int lampVal = -1; // no lamp pin assigned
|
||||
int lampVal = -1; // no lamp pin assigned
|
||||
#endif
|
||||
|
||||
int lampChannel = 7; // a free PWM channel (some channels used by camera)
|
||||
@ -118,336 +134,428 @@ const int pwmfreq = 50000; // 50K pwm frequency
|
||||
const int pwmresolution = 9; // duty cycle bit range
|
||||
const int pwmMax = pow(2,pwmresolution)-1;
|
||||
|
||||
#if defined(HAS_FS)
|
||||
bool filesystem = true;
|
||||
#if defined(NO_FS)
|
||||
bool filesystem = false;
|
||||
#else
|
||||
bool filesystem = false;
|
||||
bool filesystem = true;
|
||||
#endif
|
||||
|
||||
#if defined(FACE_DETECTION)
|
||||
int8_t detection_enabled = 1;
|
||||
#if defined(FACE_RECOGNITION)
|
||||
int8_t recognition_enabled = 1;
|
||||
#else
|
||||
int8_t recognition_enabled = 0;
|
||||
#endif
|
||||
int8_t detection_enabled = 1;
|
||||
#if defined(FACE_RECOGNITION)
|
||||
int8_t recognition_enabled = 1;
|
||||
#else
|
||||
int8_t recognition_enabled = 0;
|
||||
#endif
|
||||
#else
|
||||
int8_t detection_enabled = 0;
|
||||
int8_t recognition_enabled = 0;
|
||||
int8_t detection_enabled = 0;
|
||||
int8_t recognition_enabled = 0;
|
||||
#endif
|
||||
|
||||
// Notification LED
|
||||
void flashLED(int flashtime) {
|
||||
#ifdef LED_PIN // If we have it; flash it.
|
||||
digitalWrite(LED_PIN, LED_ON); // On at full power.
|
||||
delay(flashtime); // delay
|
||||
digitalWrite(LED_PIN, LED_OFF); // turn Off
|
||||
digitalWrite(LED_PIN, LED_ON); // On at full power.
|
||||
delay(flashtime); // delay
|
||||
digitalWrite(LED_PIN, LED_OFF); // turn Off
|
||||
#else
|
||||
return; // No notifcation LED, do nothing, no delay
|
||||
return; // No notifcation LED, do nothing, no delay
|
||||
#endif
|
||||
}
|
||||
|
||||
// Lamp Control
|
||||
void setLamp(int newVal) {
|
||||
if (newVal != -1) {
|
||||
// Apply a logarithmic function to the scale.
|
||||
int brightness = round((pow(2,(1+(newVal*0.02)))-2)/6*pwmMax);
|
||||
ledcWrite(lampChannel, brightness);
|
||||
Serial.print("Lamp: ");
|
||||
Serial.print(newVal);
|
||||
Serial.print("%, pwm = ");
|
||||
Serial.println(brightness);
|
||||
}
|
||||
if (newVal != -1) {
|
||||
// Apply a logarithmic function to the scale.
|
||||
int brightness = round((pow(2,(1+(newVal*0.02)))-2)/6*pwmMax);
|
||||
ledcWrite(lampChannel, brightness);
|
||||
Serial.print("Lamp: ");
|
||||
Serial.print(newVal);
|
||||
Serial.print("%, pwm = ");
|
||||
Serial.println(brightness);
|
||||
}
|
||||
}
|
||||
|
||||
void WifiSetup(){
|
||||
// Feedback that we are now attempting to connect
|
||||
flashLED(300);
|
||||
delay(100);
|
||||
flashLED(300);
|
||||
void WifiSetup() {
|
||||
// Feedback that we are now attempting to connect
|
||||
flashLED(300);
|
||||
delay(100);
|
||||
flashLED(300);
|
||||
|
||||
#if defined(WIFI_AP_ENABLE)
|
||||
#if defined(AP_ADDRESS)
|
||||
// User has specified the AP details, pre-configure AP
|
||||
IPAddress local_IP(AP_ADDRESS);
|
||||
IPAddress gateway(AP_ADDRESS);
|
||||
IPAddress subnet(255,255,255,0);
|
||||
WiFi.softAPConfig(local_IP, gateway, subnet);
|
||||
#endif
|
||||
#if defined(AP_CHAN)
|
||||
WiFi.softAP(ssid, password, AP_CHAN);
|
||||
Serial.println("Setting up Fixed Channel AccessPoint");
|
||||
Serial.print("SSID : ");
|
||||
Serial.println(ssid);
|
||||
Serial.print("Password : ");
|
||||
Serial.println(password);
|
||||
Serial.print("Channel : ");
|
||||
Serial.println(AP_CHAN);
|
||||
# else
|
||||
WiFi.softAP(ssid, password);
|
||||
Serial.println("Setting up AccessPoint");
|
||||
Serial.print("SSID : ");
|
||||
Serial.println(ssid);
|
||||
Serial.print("Password : ");
|
||||
Serial.println(password);
|
||||
#endif
|
||||
#else
|
||||
Serial.printf("Connecting to Wifi Network: %s ", ssid);
|
||||
#if defined(ST_IP)
|
||||
#if !defined (ST_GATEWAY) || !defined (ST_NETMASK)
|
||||
#error "You must supply both Gateway and NetMask when specifying a static IP address"
|
||||
#endif
|
||||
IPAddress staticIP(ST_IP);
|
||||
IPAddress gateway(ST_GATEWAY);
|
||||
IPAddress subnet(ST_NETMASK);
|
||||
#if !defined(ST_DNS1)
|
||||
WiFi.config(staticIP, gateway, subnet);
|
||||
#else
|
||||
IPAddress dns1(ST_DNS1);
|
||||
#if !defined(ST_DNS2)
|
||||
WiFi.config(staticIP, gateway, subnet, dns1);
|
||||
#else
|
||||
IPAddress dns2(ST_DNS2);
|
||||
WiFi.config(staticIP, gateway, subnet, dns1, dns2);
|
||||
int bestStation = -1;
|
||||
long bestRSSI = -1024;
|
||||
Serial.printf("Scanning local Wifi Networks\n");
|
||||
int stationsFound = WiFi.scanNetworks();
|
||||
Serial.printf("%i networks found\n", stationsFound);
|
||||
if (stationsFound > 0) {
|
||||
for (int i = 0; i < stationsFound; ++i) {
|
||||
// Print SSID and RSSI for each network found
|
||||
String thisSSID = WiFi.SSID(i);
|
||||
int thisRSSI = WiFi.RSSI(i);
|
||||
Serial.printf("%3i : %s (%i)", i + 1, thisSSID.c_str(), thisRSSI);
|
||||
// Scan our list of known external stations, if any
|
||||
if (stationCount > firstStation) {
|
||||
for (int sta = firstStation; sta < stationCount; sta++) {
|
||||
if (strcmp(stationList[sta].ssid, thisSSID.c_str()) == 0) {
|
||||
Serial.print(" - Known!");
|
||||
// Chose the strongest RSSI seen
|
||||
if (thisRSSI > bestRSSI) {
|
||||
bestStation = sta;
|
||||
bestRSSI = thisRSSI;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
if (bestStation == -1) {
|
||||
Serial.println("\nNo known networks found");
|
||||
#if defined(WIFI_AP_ENABLE)
|
||||
// Failover to accesspoint mode if no known networks are visible
|
||||
accesspoint = true;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Initiate network connection request
|
||||
WiFi.begin(ssid, password);
|
||||
|
||||
// Wait to connect, or timeout
|
||||
unsigned long start = millis();
|
||||
while ((millis() - start <= WIFI_WATCHDOG) && (WiFi.status() != WL_CONNECTED)) {
|
||||
delay(WIFI_WATCHDOG / 10);
|
||||
Serial.print('.');
|
||||
}
|
||||
|
||||
// If we have connected, show details
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
Serial.println(" Succeeded");
|
||||
// Burst flash the LED to show we are connected
|
||||
for (int i = 0; i < 5; i++) {
|
||||
flashLED(80);
|
||||
delay(120);
|
||||
}
|
||||
} else {
|
||||
Serial.println(" Failed");
|
||||
Serial.printf("Connecting to Wifi Network: %s\n", stationList[bestStation].ssid);
|
||||
if (stationList[bestStation].dhcp == false) {
|
||||
#if defined(ST_IP)
|
||||
Serial.println("Applying static IP settings");
|
||||
#if !defined (ST_GATEWAY) || !defined (ST_NETMASK)
|
||||
#error "You must supply both Gateway and NetMask when specifying a static IP address"
|
||||
#endif
|
||||
IPAddress staticIP(ST_IP);
|
||||
IPAddress gateway(ST_GATEWAY);
|
||||
IPAddress subnet(ST_NETMASK);
|
||||
#if !defined(ST_DNS1)
|
||||
WiFi.config(staticIP, gateway, subnet);
|
||||
#else
|
||||
IPAddress dns1(ST_DNS1);
|
||||
#if !defined(ST_DNS2)
|
||||
WiFi.config(staticIP, gateway, subnet, dns1);
|
||||
#else
|
||||
IPAddress dns2(ST_DNS2);
|
||||
WiFi.config(staticIP, gateway, subnet, dns1, dns2);
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
Serial.println("Static IP settings requested but not defined in config, falling back to dhcp");
|
||||
#endif
|
||||
}
|
||||
// Initiate network connection request
|
||||
WiFi.begin(stationList[bestStation].ssid, stationList[bestStation].password);
|
||||
|
||||
// Wait to connect, or timeout
|
||||
unsigned long start = millis();
|
||||
while ((millis() - start <= WIFI_WATCHDOG) && (WiFi.status() != WL_CONNECTED)) {
|
||||
delay(500);
|
||||
Serial.print('.');
|
||||
}
|
||||
// If we have connected, inform user
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
Serial.println("Client connection succeeded");
|
||||
accesspoint = false;
|
||||
// Note IP details
|
||||
ip = WiFi.localIP();
|
||||
net = WiFi.subnetMask();
|
||||
gw = WiFi.gatewayIP();
|
||||
Serial.printf("IP address: %d.%d.%d.%d\n",ip[0],ip[1],ip[2],ip[3]);
|
||||
Serial.printf("Netmask : %d.%d.%d.%d\n",net[0],net[1],net[2],net[3]);
|
||||
Serial.printf("Gateway : %d.%d.%d.%d\n",gw[0],gw[1],gw[2],gw[3]);
|
||||
// Flash the LED to show we are connected
|
||||
for (int i = 0; i < 5; i++) {
|
||||
flashLED(50);
|
||||
delay(150);
|
||||
}
|
||||
} else {
|
||||
Serial.println("Client connection Failed");
|
||||
WiFi.disconnect(); // (resets the WiFi scan)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (accesspoint && (WiFi.status() != WL_CONNECTED)) {
|
||||
// The accesspoint has been enabled
|
||||
#if defined(AP_CHAN)
|
||||
Serial.println("Setting up Fixed Channel AccessPoint");
|
||||
Serial.print(" SSID : ");
|
||||
Serial.println(stationList[0].ssid);
|
||||
Serial.print(" Password : ");
|
||||
Serial.println(stationList[0].password);
|
||||
Serial.print(" Channel : ");
|
||||
Serial.println(AP_CHAN);
|
||||
WiFi.softAP(stationList[0].ssid, stationList[0].password, AP_CHAN);
|
||||
# else
|
||||
Serial.println("Setting up AccessPoint");
|
||||
Serial.print(" SSID : ");
|
||||
Serial.println(stationList[0].ssid);
|
||||
Serial.print(" Password : ");
|
||||
Serial.println(stationList[0].password);
|
||||
WiFi.softAP(stationList[0].ssid, stationList[0].password);
|
||||
#endif
|
||||
#if defined(AP_ADDRESS)
|
||||
// User has specified the AP details; apply them after a short delay
|
||||
// (https://github.com/espressif/arduino-esp32/issues/985#issuecomment-359157428)
|
||||
delay(100);
|
||||
IPAddress local_IP(AP_ADDRESS);
|
||||
IPAddress gateway(AP_ADDRESS);
|
||||
IPAddress subnet(255,255,255,0);
|
||||
WiFi.softAPConfig(local_IP, gateway, subnet);
|
||||
#endif
|
||||
// Note AP details
|
||||
ip = WiFi.softAPIP();
|
||||
net = WiFi.subnetMask();
|
||||
gw = WiFi.gatewayIP();
|
||||
strcpy(apName, stationList[0].ssid);
|
||||
Serial.printf("IP address: %d.%d.%d.%d\n",ip[0],ip[1],ip[2],ip[3]);
|
||||
// Flash the LED to show we are connected
|
||||
for (int i = 0; i < 5; i++) {
|
||||
flashLED(150);
|
||||
delay(50);
|
||||
}
|
||||
// Start the DNS captive portal if requested
|
||||
if (stationList[0].dhcp == true) {
|
||||
Serial.println("Starting Captive Portal");
|
||||
dnsServer.start(DNS_PORT, "*", ip);
|
||||
captivePortal = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.setDebugOutput(true);
|
||||
Serial.println();
|
||||
Serial.println("====");
|
||||
Serial.print("esp32-cam-webserver: ");
|
||||
Serial.println(myName);
|
||||
Serial.print("Code Built: ");
|
||||
Serial.println(myVer);
|
||||
Serial.begin(115200);
|
||||
Serial.setDebugOutput(true);
|
||||
Serial.println();
|
||||
Serial.println("====");
|
||||
Serial.print("esp32-cam-webserver: ");
|
||||
Serial.println(myName);
|
||||
Serial.print("Code Built: ");
|
||||
Serial.println(myVer);
|
||||
|
||||
#if defined(LED_PIN) // If we have a notification LED, set it to output
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
digitalWrite(LED_PIN, LED_OFF);
|
||||
#endif
|
||||
|
||||
// Create camera config structure; and populate with hardware and other defaults
|
||||
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.pixel_format = PIXFORMAT_JPEG;
|
||||
//init with highest supported specs to pre-allocate large buffers
|
||||
if(psramFound()){
|
||||
config.frame_size = FRAMESIZE_UXGA;
|
||||
config.jpeg_quality = 10;
|
||||
config.fb_count = 2;
|
||||
} else {
|
||||
config.frame_size = FRAMESIZE_SVGA;
|
||||
config.jpeg_quality = 12;
|
||||
config.fb_count = 1;
|
||||
}
|
||||
|
||||
#if defined(CAMERA_MODEL_ESP_EYE)
|
||||
pinMode(13, INPUT_PULLUP);
|
||||
pinMode(14, INPUT_PULLUP);
|
||||
#endif
|
||||
|
||||
// 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();
|
||||
// Dump camera module, warn for unsupported modules.
|
||||
switch (s->id.PID) {
|
||||
case OV9650_PID: Serial.println("WARNING: OV9650 camera module is not properly supported, will fallback to OV2640 operation"); break;
|
||||
case OV7725_PID: Serial.println("WARNING: OV7725 camera module is not properly supported, will fallback to OV2640 operation"); break;
|
||||
case OV2640_PID: Serial.println("OV2640 camera module detected"); break;
|
||||
case OV3660_PID: Serial.println("OV3660 camera module detected"); break;
|
||||
// case OV5640_PID: Serial.println("WARNING: OV5640 camera module is not properly supported, will fallback to OV2640 operation"); break;
|
||||
default: Serial.println("WARNING: Camera module is unknown and not properly supported, will fallback to OV2640 operation");
|
||||
}
|
||||
|
||||
// OV3660 initial sensors are flipped vertically and colors are a bit saturated
|
||||
if (s->id.PID == OV3660_PID) {
|
||||
s->set_vflip(s, 1);//flip it back
|
||||
s->set_brightness(s, 1);//up the blightness just a bit
|
||||
s->set_saturation(s, -2);//lower the saturation
|
||||
}
|
||||
|
||||
// M5 Stack Wide has special needs
|
||||
#if defined(CAMERA_MODEL_M5STACK_WIDE)
|
||||
s->set_vflip(s, 1);
|
||||
s->set_hmirror(s, 1);
|
||||
#endif
|
||||
|
||||
// Config can override mirror and flip
|
||||
#if defined(H_MIRROR)
|
||||
s->set_hmirror(s, H_MIRROR);
|
||||
#endif
|
||||
#if defined(V_FLIP)
|
||||
s->set_vflip(s, V_FLIP);
|
||||
#endif
|
||||
|
||||
// set initial frame rate
|
||||
#if defined(DEFAULT_RESOLUTION)
|
||||
s->set_framesize(s, DEFAULT_RESOLUTION);
|
||||
#else
|
||||
s->set_framesize(s, FRAMESIZE_SVGA);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Add any other defaults you want to apply at startup here:
|
||||
* uncomment the line and set the value as desired (see the comments)
|
||||
*/
|
||||
//s->set_brightness(s, 0); // -2 to 2
|
||||
//s->set_contrast(s, 0); // -2 to 2
|
||||
//s->set_saturation(s, 0); // -2 to 2
|
||||
//s->set_special_effect(s, 0); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
|
||||
//s->set_whitebal(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_awb_gain(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_wb_mode(s, 0); // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
|
||||
//s->set_exposure_ctrl(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_aec2(s, 0); // 0 = disable , 1 = enable
|
||||
//s->set_ae_level(s, 0); // -2 to 2
|
||||
//s->set_aec_value(s, 300); // 0 to 1200
|
||||
//s->set_gain_ctrl(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_agc_gain(s, 0); // 0 to 30
|
||||
//s->set_gainceiling(s, (gainceiling_t)0); // 0 to 6
|
||||
//s->set_bpc(s, 0); // 0 = disable , 1 = enable
|
||||
//s->set_wpc(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_raw_gma(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_lenc(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_hmirror(s, 0); // 0 = disable , 1 = enable
|
||||
//s->set_vflip(s, 0); // 0 = disable , 1 = enable
|
||||
//s->set_dcw(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_colorbar(s, 0); // 0 = disable , 1 = enable
|
||||
|
||||
// We now have camera with default init
|
||||
// check for saved preferences and apply them
|
||||
|
||||
if (filesystem) {
|
||||
filesystemStart();
|
||||
loadPrefs(SPIFFS);
|
||||
loadFaceDB(SPIFFS);
|
||||
} else {
|
||||
Serial.println("No Internal Filesystem, cannot save preferences or face DB");
|
||||
}
|
||||
|
||||
/*
|
||||
* Camera setup complete; initialise the rest of the hardware.
|
||||
*/
|
||||
|
||||
// Initialise and set the lamp
|
||||
if (lampVal != -1) {
|
||||
ledcSetup(lampChannel, pwmfreq, pwmresolution); // configure LED PWM channel
|
||||
setLamp(lampVal); // set default value
|
||||
ledcAttachPin(LAMP_PIN, lampChannel); // attach the GPIO pin to the channel
|
||||
} else {
|
||||
Serial.println("No lamp, or lamp disabled in config");
|
||||
}
|
||||
|
||||
// We need a working Wifi before we can start the http handlers
|
||||
Serial.println("Starting WiFi");
|
||||
#if defined(WIFI_AP_ENABLE)
|
||||
WifiSetup();
|
||||
#else
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
WifiSetup();
|
||||
if (stationCount == 0) {
|
||||
Serial.println("\nFatal Error; Halting");
|
||||
Serial.println("No wifi ssid details have been configured; we cannot connect to WiFi or start our own AccessPoint");
|
||||
while (true) delay(1000);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(LED_PIN) // If we have a notification LED, set it to output
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
digitalWrite(LED_PIN, LED_ON);
|
||||
#endif
|
||||
|
||||
// Start the two http handlers for the HTTP UI and Stream.
|
||||
startCameraServer(httpPort, streamPort);
|
||||
// Create camera config structure; and populate with hardware and other defaults
|
||||
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.pixel_format = PIXFORMAT_JPEG;
|
||||
//init with highest supported specs to pre-allocate large buffers
|
||||
if(psramFound()){
|
||||
config.frame_size = FRAMESIZE_UXGA;
|
||||
config.jpeg_quality = 10;
|
||||
config.fb_count = 2;
|
||||
} else {
|
||||
config.frame_size = FRAMESIZE_SVGA;
|
||||
config.jpeg_quality = 12;
|
||||
config.fb_count = 1;
|
||||
}
|
||||
|
||||
// find our IP address
|
||||
char httpURL[64] = {"Unknown"};
|
||||
#if defined(WIFI_AP_ENABLE)
|
||||
ip = WiFi.softAPIP();
|
||||
#else
|
||||
ip = WiFi.localIP();
|
||||
#endif
|
||||
net = WiFi.subnetMask();
|
||||
gw = WiFi.gatewayIP();
|
||||
// Construct the App URL
|
||||
if (httpPort != 80) {
|
||||
sprintf(httpURL, "http://%d.%d.%d.%d:%d/", ip[0], ip[1], ip[2], ip[3], httpPort);
|
||||
} else {
|
||||
sprintf(httpURL, "http://%d.%d.%d.%d/", ip[0], ip[1], ip[2], ip[3]);
|
||||
}
|
||||
Serial.printf("\nCamera Ready!\nUse '%s' to connect\n", httpURL);
|
||||
// Construct the Stream URL
|
||||
sprintf(streamURL, "http://%d.%d.%d.%d:%d/", ip[0], ip[1], ip[2], ip[3], streamPort);
|
||||
Serial.printf("Stream viewer available at '%s/view'\n", streamURL);
|
||||
Serial.printf("Raw stream URL is '%s'\n", streamURL);
|
||||
#if defined(CAMERA_MODEL_ESP_EYE)
|
||||
pinMode(13, INPUT_PULLUP);
|
||||
pinMode(14, INPUT_PULLUP);
|
||||
#endif
|
||||
|
||||
// Used when dumpung status; slow functions, so do them here
|
||||
sketchSize = ESP.getSketchSize();
|
||||
sketchSpace = ESP.getFreeSketchSpace();
|
||||
sketchMD5 = ESP.getSketchMD5();
|
||||
// camera init
|
||||
esp_err_t err = esp_camera_init(&config);
|
||||
if (err == ESP_OK) {
|
||||
Serial.println("Camera init succeeded");
|
||||
} else {
|
||||
delay(100); // need a delay here or the next serial o/p gets missed
|
||||
Serial.println("Halted: Camera sensor failed to initialise");
|
||||
Serial.println("Will reboot to try again in 10s\n");
|
||||
delay(10000);
|
||||
ESP.restart();
|
||||
}
|
||||
sensor_t * s = esp_camera_sensor_get();
|
||||
|
||||
// Dump camera module, warn for unsupported modules.
|
||||
switch (s->id.PID) {
|
||||
case OV9650_PID: Serial.println("WARNING: OV9650 camera module is not properly supported, will fallback to OV2640 operation"); break;
|
||||
case OV7725_PID: Serial.println("WARNING: OV7725 camera module is not properly supported, will fallback to OV2640 operation"); break;
|
||||
case OV2640_PID: Serial.println("OV2640 camera module detected"); break;
|
||||
case OV3660_PID: Serial.println("OV3660 camera module detected"); break;
|
||||
default: Serial.println("WARNING: Camera module is unknown and not properly supported, will fallback to OV2640 operation");
|
||||
}
|
||||
|
||||
// OV3660 initial sensors are flipped vertically and colors are a bit saturated
|
||||
if (s->id.PID == OV3660_PID) {
|
||||
s->set_vflip(s, 1); //flip it back
|
||||
s->set_brightness(s, 1); //up the blightness just a bit
|
||||
s->set_saturation(s, -2); //lower the saturation
|
||||
}
|
||||
|
||||
// M5 Stack Wide has special needs
|
||||
#if defined(CAMERA_MODEL_M5STACK_WIDE)
|
||||
s->set_vflip(s, 1);
|
||||
s->set_hmirror(s, 1);
|
||||
#endif
|
||||
|
||||
// Config can override mirror and flip
|
||||
#if defined(H_MIRROR)
|
||||
s->set_hmirror(s, H_MIRROR);
|
||||
#endif
|
||||
#if defined(V_FLIP)
|
||||
s->set_vflip(s, V_FLIP);
|
||||
#endif
|
||||
|
||||
// set initial frame rate
|
||||
#if defined(DEFAULT_RESOLUTION)
|
||||
s->set_framesize(s, DEFAULT_RESOLUTION);
|
||||
#else
|
||||
s->set_framesize(s, FRAMESIZE_SVGA);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Add any other defaults you want to apply at startup here:
|
||||
* uncomment the line and set the value as desired (see the comments)
|
||||
*/
|
||||
|
||||
//s->set_framesize(s, FRAMESIZE_SVGA); // FRAMESIZE_[QQVGA|HQVGA|QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA|QXGA(ov3660)]);
|
||||
//s->set_quality(s, val); // 10 to 63
|
||||
//s->set_brightness(s, 0); // -2 to 2
|
||||
//s->set_contrast(s, 0); // -2 to 2
|
||||
//s->set_saturation(s, 0); // -2 to 2
|
||||
//s->set_special_effect(s, 0); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
|
||||
//s->set_whitebal(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_awb_gain(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_wb_mode(s, 0); // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
|
||||
//s->set_exposure_ctrl(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_aec2(s, 0); // 0 = disable , 1 = enable
|
||||
//s->set_ae_level(s, 0); // -2 to 2
|
||||
//s->set_aec_value(s, 300); // 0 to 1200
|
||||
//s->set_gain_ctrl(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_agc_gain(s, 0); // 0 to 30
|
||||
//s->set_gainceiling(s, (gainceiling_t)0); // 0 to 6
|
||||
//s->set_bpc(s, 0); // 0 = disable , 1 = enable
|
||||
//s->set_wpc(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_raw_gma(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_lenc(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_hmirror(s, 0); // 0 = disable , 1 = enable
|
||||
//s->set_vflip(s, 0); // 0 = disable , 1 = enable
|
||||
//s->set_dcw(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_colorbar(s, 0); // 0 = disable , 1 = enable
|
||||
|
||||
// We now have camera with default init
|
||||
// check for saved preferences and apply them
|
||||
|
||||
if (filesystem) {
|
||||
filesystemStart();
|
||||
loadPrefs(SPIFFS);
|
||||
loadFaceDB(SPIFFS);
|
||||
} else {
|
||||
Serial.println("No Internal Filesystem, cannot save preferences or face DB");
|
||||
}
|
||||
|
||||
/*
|
||||
* Camera setup complete; initialise the rest of the hardware.
|
||||
*/
|
||||
|
||||
// Initialise and set the lamp
|
||||
if (lampVal != -1) {
|
||||
ledcSetup(lampChannel, pwmfreq, pwmresolution); // configure LED PWM channel
|
||||
setLamp(lampVal); // set default value
|
||||
ledcAttachPin(LAMP_PIN, lampChannel); // attach the GPIO pin to the channel
|
||||
} else {
|
||||
Serial.println("No lamp, or lamp disabled in config");
|
||||
}
|
||||
|
||||
// We need a working Wifi before we can start the http handlers
|
||||
Serial.println("Starting WiFi");
|
||||
Serial.print("Known external SSIDs: ");
|
||||
if (firstStation < stationCount) {
|
||||
for (int i=firstStation; i < stationCount; i++) Serial.printf(" '%s'", stationList[i].ssid);
|
||||
} else {
|
||||
Serial.print("None");
|
||||
}
|
||||
Serial.println();
|
||||
byte mac[6];
|
||||
WiFi.macAddress(mac);
|
||||
Serial.printf("MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
|
||||
// Having got this far; start Wifi and loop until we are connected or have started an AccessPoint
|
||||
while ((WiFi.status() != WL_CONNECTED) && !accesspoint) {
|
||||
WifiSetup();
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
// Now we have a network we can start the two http handlers for the UI and Stream.
|
||||
startCameraServer(httpPort, streamPort);
|
||||
|
||||
// Construct the app and stream URLs
|
||||
char httpURL[64] = {"Unknown"};
|
||||
if (httpPort != 80) {
|
||||
sprintf(httpURL, "http://%d.%d.%d.%d:%d/", ip[0], ip[1], ip[2], ip[3], httpPort);
|
||||
} else {
|
||||
sprintf(httpURL, "http://%d.%d.%d.%d/", ip[0], ip[1], ip[2], ip[3]);
|
||||
}
|
||||
Serial.printf("\nCamera Ready!\nUse '%s' to connect\n", httpURL);
|
||||
// Construct the Stream URL
|
||||
sprintf(streamURL, "http://%d.%d.%d.%d:%d/", ip[0], ip[1], ip[2], ip[3], streamPort);
|
||||
Serial.printf("Stream viewer available at '%sview'\n", streamURL);
|
||||
Serial.printf("Raw stream URL is '%s'\n", streamURL);
|
||||
|
||||
// Used when dumpung status; slow functions, so do them here during startup
|
||||
sketchSize = ESP.getSketchSize();
|
||||
sketchSpace = ESP.getFreeSketchSpace();
|
||||
sketchMD5 = ESP.getSketchMD5();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Just loop forever, reconnecting Wifi As necesscary.
|
||||
// The stream and URI handler processes initiated by the startCameraServer() call at the
|
||||
// end of setup() will handle the camera and UI processing from now on.
|
||||
#if defined(WIFI_AP_ENABLE)
|
||||
delay(WIFI_WATCHDOG);
|
||||
#else
|
||||
static bool warned = false;
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
// We are connected, wait a bit and re-check
|
||||
if (warned) {
|
||||
Serial.println("WiFi reconnected");
|
||||
warned = false;
|
||||
}
|
||||
delay(WIFI_WATCHDOG);
|
||||
/*
|
||||
* Just loop forever, reconnecting Wifi As necesscary in client mode
|
||||
* The stream and URI handler processes initiated by the startCameraServer() call at the
|
||||
* end of setup() will handle the camera and UI processing from now on.
|
||||
*/
|
||||
if (accesspoint) {
|
||||
// Accespoint is permanently up, so just loop, servicing the captive portal as needed
|
||||
unsigned long start = millis();
|
||||
while (millis() - start < WIFI_WATCHDOG ) {
|
||||
delay(100);
|
||||
if (captivePortal) dnsServer.processNextRequest();
|
||||
}
|
||||
} else {
|
||||
if (!warned) {
|
||||
Serial.println("WiFi disconnected, retrying");
|
||||
warned = true;
|
||||
}
|
||||
WifiSetup();
|
||||
// client mode can fail; so reconnect as appropriate
|
||||
static bool warned = false;
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
// We are connected, wait a bit and re-check
|
||||
if (warned) {
|
||||
// Tell the user if we have just reconnected
|
||||
Serial.println("WiFi reconnected");
|
||||
warned = false;
|
||||
}
|
||||
delay(WIFI_WATCHDOG);
|
||||
} else {
|
||||
// disconnected; attempt to reconnect
|
||||
if (!warned) {
|
||||
// Tell the user if we just disconnected
|
||||
WiFi.disconnect(); // ensures disconnect is complete, wifi scan cleared
|
||||
Serial.println("WiFi disconnected, retrying");
|
||||
warned = true;
|
||||
}
|
||||
WifiSetup();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -16,44 +16,87 @@
|
||||
* Note the the use of commas as seperators in IP addresses!
|
||||
*/
|
||||
|
||||
// Credentials
|
||||
const char* ssid = "my-ssid";
|
||||
const char* password = "my-password";
|
||||
// WiFi Credentials
|
||||
// A structure for each WiFi network entry
|
||||
struct station
|
||||
{
|
||||
const char ssid[64]; // ssid (max 64 chars)
|
||||
const char password[64]; // password (max 64 chars)
|
||||
const bool dhcp; // dhcp
|
||||
};
|
||||
|
||||
/*
|
||||
* Extend the list below with additional SSID+Password pairs like this:
|
||||
|
||||
struct station stationList[] = {{"ssid1", "pass1", true},
|
||||
{"ssid2", "pass2", true},
|
||||
{"ssid3", "pass3", false}};
|
||||
|
||||
* The first entry will be used for the AccessPoint ssid and password when it is enabled
|
||||
* The 'dhcp' setting controls wether the station uses static IP settings (if in doubt leave 'true')
|
||||
* Note the use of nested braces '{' and '}' to group each entry, and commas ',' to seperate them.
|
||||
*/
|
||||
struct station stationList[] = {{"my_ssid","my_password", false}};
|
||||
|
||||
|
||||
// AccessPoint; uncomment to enable AP mode,
|
||||
// otherwise we will attempt to connect to an existing network.
|
||||
// #define WIFI_AP_ENABLE
|
||||
/*
|
||||
* Static network settings for client mode
|
||||
*
|
||||
* Note: The same settings will be applied to all client connections where the dhcp setting is 'false'
|
||||
* You must define all three: IP, Gateway and NetMask
|
||||
*/
|
||||
// warning - IP addresses must be seperated with commas (,) and not decimals (.)
|
||||
// #define ST_IP 192,168,0,16
|
||||
// #define ST_GATEWAY 192,168,0,2
|
||||
// #define ST_NETMASK 255,255,255,0
|
||||
// One or two optional DNS servers can be supplied, but the current firmware never uses them ;-)
|
||||
// #define ST_DNS1 192,168,0,2
|
||||
// #define ST_DNS2 8,8,8,8
|
||||
|
||||
// AccessPoint; change the ip address (optional, default = 192.168.4.1)
|
||||
/*
|
||||
* AccessPoint;
|
||||
*
|
||||
* Uncomment to enable AP mode;
|
||||
*
|
||||
*/
|
||||
#define WIFI_AP_ENABLE
|
||||
|
||||
/* AP Mode Notes:
|
||||
*
|
||||
* Once enabled the AP ssid and password will be taken from the 1st entry in the stationList[] above.
|
||||
*
|
||||
* If there are further entries listed they will be scanned at startup and connected to if they are found.
|
||||
* Making the AP a fallback mode that happens only when there are no 'real' networks available
|
||||
*
|
||||
* Setting the dhcp field to true for the AP enables a captive portal and attempts to send
|
||||
* all incoming pages to the webcam page, with varying degrees of success depending on the visitors
|
||||
* browser and other settings.
|
||||
* - The Captive Portal really needs a seperate landing page instead of using the 'main' page.
|
||||
* Browsers and OS's restrict landing page functions, since they have been abused by marketing types
|
||||
* and other low quality people. Video/Audio playback and Javascript are commonly disabled as a result.
|
||||
*/
|
||||
|
||||
// AccessPoint; optionally change the ip address (default = 192.168.4.1)
|
||||
// warning - IP addresses must be seperated with commas (,) and not decimals (.)
|
||||
// #define AP_ADDRESS 192,168,4,1
|
||||
|
||||
// AccessPoint; Uncomment this to force the channel number, default = 1
|
||||
// #define AP_CHAN 1
|
||||
|
||||
// Static network settings for use when connected to existing network when DHCP is unavailable/unreliable
|
||||
// You must define all three: IP, Gateway and NetMask
|
||||
// #define ST_IP 192,168,0,16
|
||||
// #define ST_GATEWAY 192,168,0,2
|
||||
// #define ST_NETMASK 255,255,255,0
|
||||
// one or two optional DNS servers can be supplied, but these are not used by current code.
|
||||
// #define ST_DNS1 192,168,0,2
|
||||
// #define ST_DNS2 8,8,8,8
|
||||
|
||||
// Wifi Watchdog defines how long we spend waiting for a connection before retrying,
|
||||
// and how often we check to see if we are still connected, milliseconds
|
||||
// You may wish to increase this if your WiFi is slow at conencting,
|
||||
// #define WIFI_WATCHDOG = 5000
|
||||
|
||||
|
||||
/*
|
||||
* Port numbers for WebUI and Stream, defaults to 80 and 81.
|
||||
* Uncomment and edit as appropriate
|
||||
*/
|
||||
|
||||
// #define HTTP_PORT 80
|
||||
// #define STREAM_PORT 81
|
||||
|
||||
/*
|
||||
* Wifi Watchdog defines how long we spend waiting for a connection before retrying,
|
||||
* and how often we check to see if we are still connected, milliseconds
|
||||
* You may wish to increase this if your WiFi is slow at conencting,
|
||||
*/
|
||||
//#define WIFI_WATCHDOG 5000
|
||||
|
||||
/*
|
||||
* Camera Hardware Settings
|
||||
*
|
||||
@ -61,7 +104,6 @@ const char* password = "my-password";
|
||||
* Remember to also select the board in the Boards Manager
|
||||
* This is not optional
|
||||
*/
|
||||
|
||||
#define CAMERA_MODEL_AI_THINKER // default
|
||||
// #define CAMERA_MODEL_WROVER_KIT
|
||||
// #define CAMERA_MODEL_ESP_EYE
|
||||
@ -95,6 +137,9 @@ const char* password = "my-password";
|
||||
// Define a initial lamp setting as a percentage, defaults to 0%
|
||||
// #define LAMP_DEFAULT 0
|
||||
|
||||
// Assume we have SPIFFS/LittleFS partition, uncomment if not
|
||||
// #define NO_FS
|
||||
|
||||
// Uncomment to enable Face Detection (+ Recognition if desired) by default
|
||||
// Notes: You must set DEFAULT_RESOLUTION, above, to FRAMESIZE_CIF or lower
|
||||
// Face recognition enrolements will be lost between reboots.
|
||||
|
Reference in New Issue
Block a user