├── .gitignore ├── .travis.yml ├── .vscode ├── extensions.json └── settings.json ├── LICENSE ├── README.md ├── images ├── camview.png └── devicelist.png ├── include └── README ├── lib └── README ├── platformio.ini ├── src ├── main.cpp ├── platformio.ini └── wifikeys_template.h └── test └── README /.gitignore: -------------------------------------------------------------------------------- 1 | .pio 2 | .vscode/.browse.c_cpp.db* 3 | .vscode/c_cpp_properties.json 4 | .vscode/launch.json 5 | .vscode/ipch 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - '2.7' 4 | sudo: false 5 | cache: 6 | directories: 7 | - "~/.platformio" 8 | install: 9 | - pip install -U platformio 10 | - platformio update 11 | script: 12 | - mkdir build 13 | - platformio ci --keep-build-dir --build-dir ./build --project-conf=platformio.ini 14 | src/main.cpp 15 | before_deploy: 16 | - platformio ci -h 17 | - ls -a 18 | - find . -name "*.bin" 19 | deploy: 20 | provider: releases 21 | api_key: 22 | secure: jGwDe9LIptWZeqoO0UtO8TpON/BWWItjM819PWdPBfXtLf5jOkbekUyg1U9MqWQt7/hIYKDaMHpLfalaPyEChNMDoEgicGKwtEGq09lIjrQZo9SwOHMU8xNK50OFCr5akqBSozuKoPEOW8nhG78wGbLkTpGbrzqKgVP65l+QfI8wZjNmM5sYWyvePffkP+Daxb6uk51yjdQ0QloOYdLW5XjHM9SHn6CSxBe3a1YpWMSZedfQNLAWxbEToTuIzXiK8CyyQH1Lno6AEjcLMLtE3Pm6SvGuxhindzrwQ2FBI/35cLYtclqcwSIJz1mMyhEzSpTRbDQzsoQDx0OokzZsVrBdVYSv3AbativSnUqw6/Z2l7Ei0vUchOPhDAwEvj54rvR2ylELeYC86agQ5d4kWCQBRSmU0sA0HOBq7rmHt5AmwHVbGYHmGuFmNqwlKKXE7RtXdLFZH4c04sfhPfNx2V4Z9rLyKtXsC1nbY8mcmvSaXu1HBUBVzekbI9gwHQaImUT4uql0uhcNF9AbSJC1pWL41i0g5WOIs/Hmem9ia+z2o8BDdES4qm46snp0U1lBDtCKtv9mB2TUV4W+i9qPA+DnZQZUHkClHxbhFEMlQGD3XtR9BG0fsxaLWw+mPul2/BgDk7QVygdy+WkUmWMj7MMDDZyFSELyzMkiqANDia0= 23 | file: "./build/.pio/build/esp32cam/firmware.bin" 24 | skip_cleanup: true 25 | on: 26 | repo: IoTDevice/ESP32-CAM 27 | tags: true 28 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "platformio.platformio-ide" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "terminal.integrated.env.windows": { 3 | "PATH": "C:\\Users\\Farry\\.platformio\\penv\\Scripts;C:\\Users\\Farry\\.platformio\\penv;C:\\ProgramData\\Oracle\\Java\\javapath;C:\\ProgramData\\DockerDesktop\\version-bin;C:\\Program Files\\Docker\\Docker\\Resources\\bin;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Windows\\System32\\OpenSSH\\;C:\\Go\\bin;C:\\Program Files\\Git\\cmd;C:\\Program Files\\Microsoft VS Code\\bin;C:\\git\\flutter\\bin;C:\\Users\\Farry\\AppData\\Local\\Android\\Sdk\\platform-tools;C:\\Python27;C:\\Python27\\Scripts;C:\\Program Files\\nodejs\\;C:\\Program Files\\dotnet\\;C:\\git\\flutter\\bin\\cache\\dart-sdk\\bin;C:\\git\\protoc\\bin;C:\\Program Files\\Java\\jdk1.8.0_131\\bin;C:\\Users\\Farry\\AppData\\Roaming\\Pub\\Cache\\bin;C:\\Program Files (x86)\\GnuWin32\\bin;C:\\Program Files\\PowerShell\\7-preview\\preview;C:\\Program Files (x86)\\NVIDIA Corporation\\PhysX\\Common;C:\\Program Files\\NVIDIA Corporation\\NVIDIA NvDLISR;C:\\Users\\Farry\\AppData\\Local\\Microsoft\\WindowsApps;C:\\Users\\Farry\\go\\bin;C:\\Users\\Farry\\AppData\\Roaming\\npm;C:\\ProgramData\\Oracle\\Java\\javapath;C:\\ProgramData\\DockerDesktop\\version-bin;C:\\Program Files\\Docker\\Docker\\Resources\\bin;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Windows\\System32\\OpenSSH\\;C:\\Go\\bin;C:\\Program Files\\Git\\cmd;C:\\Program Files\\Microsoft VS Code\\bin;C:\\git\\flutter\\bin;C:\\Users\\Farry\\AppData\\Local\\Android\\Sdk\\platform-tools;C:\\Python27;C:\\Python27\\Scripts;C:\\Program Files\\nodejs\\;C:\\Program Files\\dotnet\\;C:\\git\\flutter\\bin\\cache\\dart-sdk\\bin;C:\\git\\protoc\\bin;C:\\Program Files\\Java\\jdk1.8.0_131\\bin;C:\\Users\\Farry\\AppData\\Roaming\\Pub\\Cache\\bin;C:\\Program Files (x86)\\GnuWin32\\bin;C:\\Program Files\\PowerShell\\7-preview\\preview;C:\\Program Files (x86)\\NVIDIA Corporation\\PhysX\\Common;C:\\Program Files\\NVIDIA Corporation\\NVIDIA NvDLISR;C:\\Users\\Farry\\AppData\\Local\\Microsoft\\WindowsApps;C:\\Users\\Farry\\go\\bin;C:\\Users\\Farry\\AppData\\Roaming\\npm", 4 | "PLATFORMIO_CALLER": "vscode" 5 | } 6 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 IoTDevice 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESP32-CAM 2 | ESP32摄像头集成到app 3 | 4 | ## 手机APP 5 | - app下载地址:https://github.com/OpenIoTHub/OpenIoTHub/releases (安装好次程序就可以给刷好本固件程序的设备配网并发现控制了,如果想外网访问请使用下面的软件) 6 | - 如果你想外网访问请安装此软件配套的网关,地址:https://github.com/OpenIoTHub/gateway-go/releases 7 | - 程序安装和使用参考:https://www.jianshu.com/p/112c1583889f 8 | ### app操作界面 9 | ![image](./images/devicelist.png) 10 | ![image](./images/camview.png) 11 | -------------------------------------------------------------------------------- /images/camview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IoTDevice/ESP32-CAM/34fd5591cca36ccabb7d26bee70531ee431bc2c1/images/camview.png -------------------------------------------------------------------------------- /images/devicelist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IoTDevice/ESP32-CAM/34fd5591cca36ccabb7d26bee70531ee431bc2c1/images/devicelist.png -------------------------------------------------------------------------------- /include/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for project header files. 3 | 4 | A header file is a file containing C declarations and macro definitions 5 | to be shared between several project source files. You request the use of a 6 | header file in your project source file (C, C++, etc) located in `src` folder 7 | by including it, with the C preprocessing directive `#include'. 8 | 9 | ```src/main.c 10 | 11 | #include "header.h" 12 | 13 | int main (void) 14 | { 15 | ... 16 | } 17 | ``` 18 | 19 | Including a header file produces the same results as copying the header file 20 | into each source file that needs it. Such copying would be time-consuming 21 | and error-prone. With a header file, the related declarations appear 22 | in only one place. If they need to be changed, they can be changed in one 23 | place, and programs that include the header file will automatically use the 24 | new version when next recompiled. The header file eliminates the labor of 25 | finding and changing all the copies as well as the risk that a failure to 26 | find one copy will result in inconsistencies within a program. 27 | 28 | In C, the usual convention is to give header files names that end with `.h'. 29 | It is most portable to use only letters, digits, dashes, and underscores in 30 | header file names, and at most one dot. 31 | 32 | Read more about using header files in official GCC documentation: 33 | 34 | * Include Syntax 35 | * Include Operation 36 | * Once-Only Headers 37 | * Computed Includes 38 | 39 | https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html 40 | -------------------------------------------------------------------------------- /lib/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for project specific (private) libraries. 3 | PlatformIO will compile them to static libraries and link into executable file. 4 | 5 | The source code of each library should be placed in a an own separate directory 6 | ("lib/your_library_name/[here are source files]"). 7 | 8 | For example, see a structure of the following two libraries `Foo` and `Bar`: 9 | 10 | |--lib 11 | | | 12 | | |--Bar 13 | | | |--docs 14 | | | |--examples 15 | | | |--src 16 | | | |- Bar.c 17 | | | |- Bar.h 18 | | | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html 19 | | | 20 | | |--Foo 21 | | | |- Foo.c 22 | | | |- Foo.h 23 | | | 24 | | |- README --> THIS FILE 25 | | 26 | |- platformio.ini 27 | |--src 28 | |- main.c 29 | 30 | and a contents of `src/main.c`: 31 | ``` 32 | #include 33 | #include 34 | 35 | int main (void) 36 | { 37 | ... 38 | } 39 | 40 | ``` 41 | 42 | PlatformIO Library Dependency Finder will find automatically dependent 43 | libraries scanning project source files. 44 | 45 | More information about PlatformIO Library Dependency Finder 46 | - https://docs.platformio.org/page/librarymanager/ldf.html 47 | -------------------------------------------------------------------------------- /platformio.ini: -------------------------------------------------------------------------------- 1 | ;PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [env:esp32cam] 12 | platform = espressif32 13 | board = esp32cam 14 | framework = arduino 15 | upload_speed = 921600 16 | lib_deps = 17 | Micro-RTSP@^0.1.6 18 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "OV2640.h" 2 | #include 3 | #include 4 | #include 5 | 6 | #include "SimStreamer.h" 7 | #include "OV2640Streamer.h" 8 | #include "CRtspSession.h" 9 | 10 | #include 11 | 12 | // #define ENABLE_OLED //if want use oled ,turn on thi macro 13 | // #define SOFTAP_MODE // If you want to run our own softap turn this on 14 | #define ENABLE_WEBSERVER 15 | #define ENABLE_RTSPSERVER 16 | 17 | #ifdef ENABLE_OLED 18 | #include "SSD1306.h" 19 | #define OLED_ADDRESS 0x3c 20 | #define I2C_SDA 14 21 | #define I2C_SCL 13 22 | SSD1306Wire display(OLED_ADDRESS, I2C_SDA, I2C_SCL, GEOMETRY_128_32); 23 | bool hasDisplay; // we probe for the device at runtime 24 | #endif 25 | 26 | String version = "1.0"; 27 | String deviceName = "ESP32摄像头"; 28 | OV2640 cam; 29 | 30 | #ifdef ENABLE_WEBSERVER 31 | WebServer server(80); 32 | #endif 33 | 34 | #ifdef ENABLE_RTSPSERVER 35 | WiFiServer rtspServer(8554); 36 | #endif 37 | 38 | 39 | #ifdef SOFTAP_MODE 40 | IPAddress apIP = IPAddress(192, 168, 1, 1); 41 | #else 42 | // #include "wifikeys.h" 43 | #endif 44 | 45 | #ifdef ENABLE_WEBSERVER 46 | 47 | void handle_jpg_stream(void) 48 | { 49 | WiFiClient client = server.client(); 50 | String response = "HTTP/1.1 200 OK\r\n"; 51 | response += "Content-Type: multipart/x-mixed-replace; boundary=frame\r\n\r\n"; 52 | server.sendContent(response); 53 | 54 | while (1) 55 | { 56 | cam.run(); 57 | if (!client.connected()) 58 | break; 59 | response = "--frame\r\n"; 60 | response += "Content-Type: image/jpeg\r\n\r\n"; 61 | server.sendContent(response); 62 | 63 | client.write((char *)cam.getfb(), cam.getSize()); 64 | server.sendContent("\r\n"); 65 | if (!client.connected()) 66 | break; 67 | } 68 | } 69 | 70 | void handle_jpg(void) 71 | { 72 | WiFiClient client = server.client(); 73 | 74 | cam.run(); 75 | if (!client.connected()) 76 | { 77 | return; 78 | } 79 | String response = "HTTP/1.1 200 OK\r\n"; 80 | response += "Content-disposition: inline; filename=capture.jpg\r\n"; 81 | response += "Content-type: image/jpeg\r\n\r\n"; 82 | server.sendContent(response); 83 | client.write((char *)cam.getfb(), cam.getSize()); 84 | } 85 | 86 | void handleNotFound() 87 | { 88 | String message = "Server is running!\n\n"; 89 | message += "URI: "; 90 | message += server.uri(); 91 | message += "\nMethod: "; 92 | message += (server.method() == HTTP_GET) ? "GET" : "POST"; 93 | message += "\nArguments: "; 94 | message += server.args(); 95 | message += "\n"; 96 | server.send(200, "text/plain", message); 97 | } 98 | #endif 99 | 100 | void lcdMessage(String msg) 101 | { 102 | #ifdef ENABLE_OLED 103 | if(hasDisplay) { 104 | display.clear(); 105 | display.drawString(128 / 2, 32 / 2, msg); 106 | display.display(); 107 | } 108 | #endif 109 | } 110 | 111 | void setup() 112 | { 113 | #ifdef ENABLE_OLED 114 | hasDisplay = display.init(); 115 | if(hasDisplay) { 116 | display.flipScreenVertically(); 117 | display.setFont(ArialMT_Plain_16); 118 | display.setTextAlignment(TEXT_ALIGN_CENTER); 119 | } 120 | #endif 121 | lcdMessage("booting"); 122 | 123 | Serial.begin(115200); 124 | while (!Serial) 125 | { 126 | ; 127 | } 128 | cam.init(esp32cam_aithinker_config); 129 | 130 | IPAddress ip; 131 | 132 | 133 | #ifdef SOFTAP_MODE 134 | const char *hostname = "devcam"; 135 | // WiFi.hostname(hostname); // FIXME - find out why undefined 136 | lcdMessage("starting softAP"); 137 | WiFi.mode(WIFI_AP); 138 | WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); 139 | bool result = WiFi.softAP(hostname, "12345678", 1, 0); 140 | if (!result) 141 | { 142 | Serial.println("AP Config failed."); 143 | return; 144 | } 145 | else 146 | { 147 | Serial.println("AP Config Success."); 148 | Serial.print("AP MAC: "); 149 | Serial.println(WiFi.softAPmacAddress()); 150 | 151 | ip = WiFi.softAPIP(); 152 | } 153 | #else 154 | WiFi.mode(WIFI_STA); 155 | WiFi.beginSmartConfig(); 156 | while (WiFi.status() != WL_CONNECTED) 157 | { 158 | delay(500); 159 | Serial.print(F(".")); 160 | } 161 | ip = WiFi.localIP(); 162 | Serial.println(F("WiFi connected")); 163 | Serial.println(""); 164 | Serial.println(ip); 165 | #endif 166 | 167 | if (!MDNS.begin("ESP32-CAM")) { 168 | // Serial.println("MDNS responder started"); 169 | while(1) { 170 | delay(1000); 171 | } 172 | } 173 | MDNS.addService("iotdevice", "tcp", 80); 174 | MDNS.addServiceTxt("iotdevice", "tcp", "name", deviceName); 175 | MDNS.addServiceTxt("iotdevice", "tcp", "model", "com.iotserv.services.web"); 176 | MDNS.addServiceTxt("iotdevice", "tcp", "mac", WiFi.macAddress()); 177 | MDNS.addServiceTxt("iotdevice", "tcp", "id", ESP.getSketchMD5()); 178 | MDNS.addServiceTxt("iotdevice", "tcp", "author", "Farry"); 179 | MDNS.addServiceTxt("iotdevice", "tcp", "email", "newfarry@126.com"); 180 | MDNS.addServiceTxt("iotdevice", "tcp", "home-page", "https://github.com/iotdevice"); 181 | MDNS.addServiceTxt("iotdevice", "tcp", "firmware-respository", "https://github.com/iotdevice/ESP32-CAM"); 182 | MDNS.addServiceTxt("iotdevice", "tcp", "firmware-version", version); 183 | 184 | lcdMessage(ip.toString()); 185 | 186 | #ifdef ENABLE_WEBSERVER 187 | server.on("/", HTTP_GET, handle_jpg_stream); 188 | server.on("/jpg", HTTP_GET, handle_jpg); 189 | server.onNotFound(handleNotFound); 190 | server.begin(); 191 | #endif 192 | 193 | #ifdef ENABLE_RTSPSERVER 194 | rtspServer.begin(); 195 | #endif 196 | } 197 | 198 | CStreamer *streamer; 199 | CRtspSession *session; 200 | WiFiClient client; // FIXME, support multiple clients 201 | 202 | void loop() 203 | { 204 | #ifdef ENABLE_WEBSERVER 205 | server.handleClient(); 206 | #endif 207 | 208 | #ifdef ENABLE_RTSPSERVER 209 | uint32_t msecPerFrame = 100; 210 | static uint32_t lastimage = millis(); 211 | 212 | // If we have an active client connection, just service that until gone 213 | // (FIXME - support multiple simultaneous clients) 214 | if(session) { 215 | session->handleRequests(0); // we don't use a timeout here, 216 | // instead we send only if we have new enough frames 217 | 218 | uint32_t now = millis(); 219 | if(now > lastimage + msecPerFrame || now < lastimage) { // handle clock rollover 220 | session->broadcastCurrentFrame(now); 221 | lastimage = now; 222 | 223 | // check if we are overrunning our max frame rate 224 | now = millis(); 225 | if(now > lastimage + msecPerFrame) 226 | printf("warning exceeding max frame rate of %d ms\n", now - lastimage); 227 | } 228 | 229 | if(session->m_stopped) { 230 | delete session; 231 | delete streamer; 232 | session = NULL; 233 | streamer = NULL; 234 | } 235 | } 236 | else { 237 | client = rtspServer.accept(); 238 | 239 | if(client) { 240 | //streamer = new SimStreamer(&client, true); // our streamer for UDP/TCP based RTP transport 241 | streamer = new OV2640Streamer(&client, cam); // our streamer for UDP/TCP based RTP transport 242 | 243 | session = new CRtspSession(&client, streamer); // our threads RTSP session and state 244 | } 245 | } 246 | #endif 247 | } 248 | -------------------------------------------------------------------------------- /src/platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [env:m5stack-core-esp32] 12 | platform = espressif32@>=1.6.0 13 | board = m5stack-core-esp32 14 | framework = arduino 15 | lib_deps = Micro-RTSP 16 | -------------------------------------------------------------------------------- /src/wifikeys_template.h: -------------------------------------------------------------------------------- 1 | // copy this file to wifikeys.h and edit 2 | const char *ssid = "YOURNETHERE"; // Put your SSID here 3 | const char *password = "YOURPASSWORDHERE"; // Put your PASSWORD here 4 | -------------------------------------------------------------------------------- /test/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for PIO Unit Testing and project tests. 3 | 4 | Unit Testing is a software testing method by which individual units of 5 | source code, sets of one or more MCU program modules together with associated 6 | control data, usage procedures, and operating procedures, are tested to 7 | determine whether they are fit for use. Unit testing finds problems early 8 | in the development cycle. 9 | 10 | More information about PIO Unit Testing: 11 | - https://docs.platformio.org/page/plus/unit-testing.html 12 | --------------------------------------------------------------------------------