Using AutoConnect, Blynk, and Camera on ESP32-CAM board

I have created a sketch which using AutoConnect, Blynk and an OV2640 on a ESP32-CAM board.
I have everything compiling and loading onto the board ( set to AI Thinker ESP32-CAM) and I can sign into the AudoConnect portal to configure my local wifi SSID and Password and save them.
I also can open my Blynk app and see that the board is connected and I can press a Switch Widget set to button mode and light up an LED on the Board.
I also get a message saying the Camera is ready at http://10.0.1.76.
The problem is that this is the same address that is used by the AutoConnect portal.
So if I put 10.0.1.76 on my web browser I get the portal but when I put 10.0.1.76 in the Blynk app on the videoStreaming Widget and press play arrow it buffers for a while then reads error.

This is what I get on the Serial monitor when the Board starts up.

10:22:57.528 -> WiFi connected
10:22:57.528 -> Starting web server on port: '80'
10:22:57.528 -> E (5104) httpd: httpd_server_init: error in bind (112)
10:22:57.528 -> Starting stream server on port: '81'
10:22:57.528 -> Camera Ready! Use 'http://10.0.1.76' to connect

I have seen that there seems to be a problem with the error in bind (112) but I am not sure how to get rid of this.
The main problem I think is that the access point is constantly open and so putting in the address 10.0.1.76 takes me to that instead of the camera.
If this is true is there anyway to shut off the access point until I want to have it active by pushing a button or only when the configured SSID and Password are not available?
That way if it is not active maybe putting in the address 10.0.1.76 will open the camera.

Is this a solution, or is this configuration not possible at all. and if it is a solution could someone help me configure my code to do this.

I can post my total code if needed.

Thanks

The main problem I think is that the access point is constantly open and so putting in the address 10.0.1.76 takes me to that instead of the camera.
If this is true is there anyway to shut off the access point until I want to have it active by pushing a button or only when the configured SSID and Password are not available?
That way if it is not active maybe putting in the address 10.0.1.76 will open the camera.

No the AP is open, that is true, but that is not the problem. The server is taking you to the connection portal when you go to the root page, which is at the IP address that your router has assigned to the ESP32. You can still connect to the AP, and after you do you can either use the original IP (192.168.4.1) or the newly assigned IP. Through you router only the assigned IP will take you to the server.
We don't have you code, and i don't know how the Camera works on an ESP32 (i don't have one, haven't played with it) but i suspect that you should be able to open the camera if you give it a specific location and then go there. Doesn't it have a specific webpage location ? like 10.0.1.76/camera anyway without your sketch it is going to be hard to to tell you what to do.

When I had set the camera up just by itself all I had to put in the address was 10.0.1.75 and it took me to a page with a still camera image with a bunch of settings and a start streaming button. When the Start Streaming button was pushed the video started playing and the button changed names to stop streaming. However the address at that time was 10.0.1.75 port 80 not 81 as shown on the above printout. I will post my code here;

#include "esp_camera.h"
#include <WiFi.h>
#define CAMERA_MODEL_AI_THINKER

#include "camera_pins.h"
#include <Esp32WifiManager.h>
#include <SPI.h>
#include <WebServer.h>
#include <time.h>
#include <AutoConnect.h>
#include <WiFiClient.h>
//#include <BlynkSimpleEsp32_WM.h>
#include <BlynkSimpleEsp32.h>

int pinValue4;
int pinValue8;
int LED;
int pin_d0;
//Blynk

//CAMERA


static const char AUX_TIMEZONE[] PROGMEM = R"(
{
  "title": "TimeZone",
  "uri": "/timezone",
  "menu": true,
  "element": [
    {
      "name": "caption",
      "type": "ACText",
      "value": "Sets the time zone to get the current local time.",
      "style": "font-family:Arial;font-weight:bold;text-align:center;margin-bottom:10px;color:DarkSlateBlue"
    },
    {
      "name": "timezone",
      "type": "ACSelect",
      "label": "Select TZ name",
      "option": [],
      "selected": 10
    },
    {
      "name": "newline",
      "type": "ACElement",
      "value": "
"
    },
    {
      "name": "start",
      "type": "ACSubmit",
      "value": "OK",
      "uri": "/start"
    }
  ]
}
)";

typedef struct {
  const char* zone;
  const char* ntpServer;
  int8_t      tzoff;
} Timezone_t;

static const Timezone_t TZ[] = {
  { "Europe/London", "europe.pool.ntp.org", 0 },
  { "Europe/Berlin", "europe.pool.ntp.org", 1 },
  { "Europe/Helsinki", "europe.pool.ntp.org", 2 },
  { "Europe/Moscow", "europe.pool.ntp.org", 3 },
  { "Asia/Dubai", "asia.pool.ntp.org", 4 },
  { "Asia/Karachi", "asia.pool.ntp.org", 5 },
  { "Asia/Dhaka", "asia.pool.ntp.org", 6 },
  { "Asia/Jakarta", "asia.pool.ntp.org", 7 },
  { "Asia/Manila", "asia.pool.ntp.org", 8 },
  { "Asia/Tokyo", "asia.pool.ntp.org", 9 },
  { "Australia/Brisbane", "oceania.pool.ntp.org", 10 },
  { "Pacific/Noumea", "oceania.pool.ntp.org", 11 },
  { "Pacific/Auckland", "oceania.pool.ntp.org", 12 },
  { "Atlantic/Azores", "europe.pool.ntp.org", -1 },
  { "America/Noronha", "south-america.pool.ntp.org", -2 },
  { "America/Araguaina", "south-america.pool.ntp.org", -3 },
  { "America/Blanc-Sablon", "north-america.pool.ntp.org", -4},
  { "America/New_York", "north-america.pool.ntp.org", -5 },
  { "America/Chicago", "north-america.pool.ntp.org", -6 },
  { "America/Denver", "north-america.pool.ntp.org", -7 },
  { "America/Los_Angeles", "north-america.pool.ntp.org", -8 },
  { "America/Anchorage", "north-america.pool.ntp.org", -9 },
  { "Pacific/Honolulu", "north-america.pool.ntp.org", -10 },
  { "Pacific/Samoa", "oceania.pool.ntp.org", -11 }
};

#if defined(ARDUINO_ARCH_ESP8266)
ESP8266WebServer Server;
#elif defined(ARDUINO_ARCH_ESP32)
WebServer Server;
#endif

AutoConnect       Portal(Server);
AutoConnectConfig Config;       // Enable autoReconnect supported on v0.9.4
AutoConnectAux    Timezone;

void rootPage() {
  String  content =
    "<html>"
    "<head>"
    "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"
    "<script type=\"text/javascript\">"
    "setTimeout(\"location.reload()\", 1000);"
    "</script>"
    "</head>"
    "<body>"
    "<h2 align=\"center\" style=\"color:blue;margin:20px;\">Hello, world</h2>"
    "<h3 align=\"center\" style=\"color:gray;margin:10px;\">{{DateTime}}</h3>"
    "<p style=\"text-align:center;\">Reload the page to update the time.</p>"
    "<p></p><p style=\"padding-top:15px;text-align:center\">" AUTOCONNECT_LINK(COG_24) "</p>"
    "</body>"
    "</html>";
  static const char *wd[7] = { "Sun","Mon","Tue","Wed","Thr","Fri","Sat" };
  struct tm *tm;
  time_t  t;
  char    dateTime[26];

  t = time(NULL);
  tm = localtime(&t);
  sprintf(dateTime, "%04d/%02d/%02d(%s) %02d:%02d:%02d.",
    tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
    wd[tm->tm_wday],
    tm->tm_hour, tm->tm_min, tm->tm_sec);
  content.replace("{{DateTime}}", String(dateTime));
  Server.send(200, "text/html", content);
}

void startPage() {
  // Retrieve the value of AutoConnectElement with arg function of WebServer class.
  // Values are accessible with the element name.
  String  tz = Server.arg("timezone");

  for (uint8_t n = 0; n < sizeof(TZ) / sizeof(Timezone_t); n++) {
    String  tzName = String(TZ[n].zone);
    if (tz.equalsIgnoreCase(tzName)) {
      configTime(TZ[n].tzoff * 3600, 0, TZ[n].ntpServer);
      Serial.println("Time zone: " + tz);
      Serial.println("ntp server: " + String(TZ[n].ntpServer));
      break;
    }
  }

  // The /start page just constitutes timezone,
  // it redirects to the root page without the content response.
  Server.sendHeader("Location", String("http://") + Server.client().localIP().toString() + String("/"));
  Server.send(302, "text/plain", "");
  Server.client().flush();
  Server.client().stop();
}
void startCameraServer();

void setup() {
  Serial.begin(115200);
  Serial.setDebugOutput(true);
  Serial.println();



  
String Label;
char auth[] = "un0EpGjDyoekUrLHey8P9JTL9K6ukC-G";
byte pinState = LOW;
pinMode(14,OUTPUT);
digitalWrite(14,LOW);
int LED = 14;
pinMode(LED,OUTPUT);
digitalWrite (LED,LOW);
WidgetLED led1(V6);
led1.off();
led1.setValue(0);


//String pinValue9 = "g";

  // Enable saved past credential by autoReconnect option,
  // even once it is disconnected.
  Config.autoReconnect = true;
  Config.hostName = "FloWT2";
  
  Portal.config(Config);

  // Load aux. page
  Timezone.load(AUX_TIMEZONE);
  // Retrieve the select element that holds the time zone code and
  // register the zone mnemonic in advance.
  AutoConnectSelect&  tz = Timezone["timezone"].as<AutoConnectSelect>();
  for (uint8_t n = 0; n < sizeof(TZ) / sizeof(Timezone_t); n++) {
    tz.add(String(TZ[n].zone));
  }

  Portal.join({ Timezone });        // Register aux. page

  // Behavior a root path of ESP8266WebServer.
  Server.on("/", rootPage);
  Server.on("/start", startPage);   // Set NTP server trigger handler

  Serial.println("Creating portal and trying to connect...");
  // Establish a connection with an autoReconnect option.
  if (Portal.begin()) {
    Serial.println("WiFi connected: " + WiFi.localIP().toString());
    #if defined(ARDUINO_ARCH_ESP8266)
    Serial.println(WiFi.hostname());
    #elif defined(ARDUINO_ARCH_ESP32)
    Serial.println(WiFi.getHostname());
    #endif
  }



  camera_config_t config;
 //pin configuration is here but took out because of limited character length.

  // 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
  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
  }
  //drop down frame size for higher initial frame rate
  s->set_framesize(s, FRAMESIZE_QVGA);

#if defined(CAMERA_MODEL_M5STACK_WIDE)
  s->set_vflip(s, 1);
  s->set_hmirror(s, 1);
#endif

 

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  delay(3000);
  startCameraServer();
  delay(2000);
   Blynk.syncAll();
Blynk.config("un0EpGjDyoekUrLHey8P9JTL9K6ukC-G");



  Serial.print("Camera Ready! Use 'http://");
  Serial.print(WiFi.localIP());
  Serial.println("' to connect");
}

void loop() {
  // put your main code here, to run repeatedly:
    Portal.handleClient();
Blynk.run();
  
}

I am powering the ESP32-CAm with 5v FIDI as didn’t work too well at 3.3v. I also tried it connected to power source at 500mA 3.3v. Still didn’t work. I could try 500mA at 5v to see it that helps.
Anyway I hope someone can help with this last step.

If you’re still looking…
Use “http://10.0.1.75:81/stream” to go to the Camera Stream directly. (Where “10.0.1.75” is your ESP32’s local IP address.)