forked from external-repos/ESP32-CAM-ONVIF
Compare commits
21 Commits
John-Vargh
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
64e4f44aed | ||
|
|
53d1e6be94 | ||
|
|
effbd83d93 | ||
|
|
e654da3e25 | ||
|
|
5e16f21407 | ||
|
|
ae4c9c6392 | ||
|
|
478cc59d9c | ||
|
|
b04e4cb381 | ||
|
|
605b55fce9 | ||
|
|
8a19dcb0b6 | ||
|
|
9d6b6d90ff | ||
|
|
567f01ca65 | ||
|
|
27c5d944c0 | ||
|
|
3af64c8499 | ||
|
|
3b270b5bec | ||
|
|
c104f055ee | ||
|
|
35e529e7e9 | ||
|
|
778cf4aaaf | ||
|
|
2ca9c5a84e | ||
|
|
af8d85e41d | ||
|
|
9294ddb4a9 |
15
.github/FUNDING.yml
vendored
Normal file
15
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: John-Varghese-EH # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: CyberTrinity # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||
polar: # Replace with a single Polar username
|
||||
buy_me_a_coffee: CyberTrinity # Replace with a single Buy Me a Coffee username
|
||||
thanks_dev: # Replace with a single thanks.dev username
|
||||
custom: 'johnvarghese.netlify.app/support' # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
128
CODE_OF_CONDUCT.md
Normal file
128
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, religion, or sexual identity
|
||||
and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at
|
||||
johnvarghese.work@gmail.com.
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series
|
||||
of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or
|
||||
permanent ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
the community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
||||
73
CONTRIBUTING.md
Normal file
73
CONTRIBUTING.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# Contributing to ESP32-CAM-ONVIF
|
||||
|
||||
Thank you for your interest in contributing to **ESP32-CAM-ONVIF**!
|
||||
Your help is essential to make this project robust, feature-rich, and easy to use for everyone.
|
||||
We welcome contributions of all kinds: code, documentation, bug reports, feature requests, and ideas.
|
||||
|
||||
---
|
||||
|
||||
## How to Contribute
|
||||
|
||||
### 1. Fork & Clone
|
||||
|
||||
- Fork the repository to your own GitHub account.
|
||||
- Clone your fork:
|
||||
|
||||
- Open a Pull Request (PR) against the `main` branch of this repository.
|
||||
- In your PR description, include:
|
||||
- A summary of your changes
|
||||
- Any relevant issue numbers (e.g., `Closes #123`)
|
||||
- Screenshots or logs if applicable
|
||||
|
||||
### 6. Respond to Feedback
|
||||
|
||||
- Be ready to answer questions or make revisions.
|
||||
- We may suggest changes or request further testing.
|
||||
|
||||
---
|
||||
|
||||
## What Can You Contribute?
|
||||
|
||||
- **Features**: Add new capabilities (e.g., web UI, SD recording, motion detection)
|
||||
- **Bug Fixes**: Find and squash bugs
|
||||
- **Documentation**: Improve guides, add examples, or clarify instructions
|
||||
- **Testing**: Test on different hardware/NVRs and report results
|
||||
- **Ideas**: Suggest improvements or new directions
|
||||
|
||||
---
|
||||
|
||||
## Guidelines
|
||||
|
||||
- **Follow best practices**: Comment your code and keep it readable.
|
||||
- **Respect the project structure**: Organize new files logically.
|
||||
- **Document new features**: Update README.md and add usage notes.
|
||||
- **Stay compatible**: Ensure your changes work with both PlatformIO and Arduino IDE.
|
||||
- **Be respectful**: All interactions should be friendly and constructive.
|
||||
|
||||
---
|
||||
|
||||
## Reporting Issues & Feature Requests
|
||||
|
||||
- Use [GitHub Issues](https://github.com/John-Varghese-EH/ESP32-CAM-ONVIF/issues) for:
|
||||
- Bug reports (include logs, hardware details, steps to reproduce)
|
||||
- Feature requests (describe your idea and use case)
|
||||
- General questions
|
||||
|
||||
---
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
This project was first forked by [BitVenturesUSA/ESP32-CAM-ONVIF](). We appreciate their interest and contributions to the ESP32-CAM ONVIF community.
|
||||
|
||||
---
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
We are committed to providing a welcoming and inclusive environment for all.
|
||||
Please read and follow our [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md).
|
||||
|
||||
---
|
||||
|
||||
Thank you for your contributions!
|
||||
Together, we can make ESP32-CAM-ONVIF the best open-source ONVIF camera firmware for ESP32.
|
||||
|
||||
BIN
ESP32-CAM-ONVIF.jpg
Normal file
BIN
ESP32-CAM-ONVIF.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 194 KiB |
10
ESP32CAM-ONVIF/MyStreamer.cpp
Normal file
10
ESP32CAM-ONVIF/MyStreamer.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
// MyStreamer.cpp
|
||||
#include "MyStreamer.h"
|
||||
|
||||
void MyStreamer::streamImage(uint32_t curMsec) {
|
||||
uint8_t *image = m_cam.getfb();
|
||||
uint32_t size = m_cam.getSize();
|
||||
if (image && size) {
|
||||
streamFrame(image, size, curMsec);
|
||||
}
|
||||
}
|
||||
13
ESP32CAM-ONVIF/MyStreamer.h
Normal file
13
ESP32CAM-ONVIF/MyStreamer.h
Normal file
@@ -0,0 +1,13 @@
|
||||
// MyStreamer.h
|
||||
#pragma once
|
||||
#include "OV2640.h"
|
||||
#include "CStreamer.h"
|
||||
|
||||
class MyStreamer : public CStreamer {
|
||||
public:
|
||||
MyStreamer(OV2640 &cam) : CStreamer(cam.getWidth(), cam.getHeight()), m_cam(cam) {}
|
||||
virtual ~MyStreamer() {}
|
||||
virtual void streamImage(uint32_t curMsec) override;
|
||||
private:
|
||||
OV2640 &m_cam;
|
||||
};
|
||||
@@ -4,12 +4,12 @@
|
||||
<meta charset="UTF-8">
|
||||
<title>J0X-ESP-CAM Control Panel</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="/style.css">
|
||||
<link rel="stylesheet" href="./style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="login-overlay" class="overlay">
|
||||
<div class="login-box">
|
||||
<img src="/logo.png" alt="Logo" class="logo-large">
|
||||
<img src="./logo.png" alt="Logo" class="logo-large">
|
||||
<h2>J0X-ESP-CAM</h2>
|
||||
<form id="login-form" onsubmit="return login(event)">
|
||||
<input type="text" id="username" placeholder="Username" autocomplete="username" required>
|
||||
@@ -21,7 +21,7 @@
|
||||
</div>
|
||||
<header>
|
||||
<div class="header-bar">
|
||||
<img src="/logo.png" alt="Logo" class="logo-small">
|
||||
<img src="./logo.png" alt="Logo" class="logo-small">
|
||||
<span class="brand">J0X-ESP-CAM</span>
|
||||
</div>
|
||||
<div class="status" id="status">Connecting...</div>
|
||||
@@ -129,6 +129,6 @@
|
||||
<div class="footer">
|
||||
Made with <span style="color:#e25555;">❤️</span> by <a herf="https://github.com/John-Varghese-EH/">J0X</a>
|
||||
</div>
|
||||
<script src="/app.js"></script>
|
||||
<script src="./app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -8,7 +8,7 @@ main { max-width: 700px; margin: 2em auto; background: #232323; border-radius: 8
|
||||
.section { margin-bottom: 2em; }
|
||||
label { display: block; margin: 0.5em 0 0.2em; }
|
||||
input, select, button { padding: 0.5em; border-radius: 4px; border: none; margin-bottom: 0.5em; }
|
||||
.stream-container { width: 90vw; max-width: 100vw; height: 60vw; /* Or adjust as needed */ max-height: 80vh; overflow: hidden; margin: 0 auto; background: #111; touch-action: none; /* Required for custom gestures */ position: relative; }
|
||||
.stream-container { width: 95%; max-width: 100%; height: 60%; /* Or adjust as needed */ max-height: 80%; overflow: hidden; margin: 0 auto; background: #111; touch-action: none; /* Required for custom gestures */ position: relative; }
|
||||
.video-preview { width: 100%; height: 100%; object-fit: contain; user-select: none; cursor: grab; transition: transform 0.05s linear; will-change: transform; }
|
||||
.btn { background: #08f; color: #fff; cursor: pointer; transition: background 0.2s; }
|
||||
.btn:active { background: #06c; }
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <Arduino.h>
|
||||
#include "motion_detection.h"
|
||||
#include "esp_camera.h"
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#include <Arduino.h>
|
||||
#include "onvif_server.h"
|
||||
#include "rtsp_server.h"
|
||||
#include <WiFiUdp.h>
|
||||
#include <WebServer.h>
|
||||
#include "utils.h"
|
||||
#include "config.h"
|
||||
|
||||
WebServer onvifServer(8000);
|
||||
WiFiUDP onvifUDP;
|
||||
@@ -42,6 +43,25 @@ String getDeviceInfoResponse() {
|
||||
"</SOAP-ENV:Envelope>";
|
||||
}
|
||||
|
||||
String getStreamUriResponse() {
|
||||
String ip = WiFi.localIP().toString();
|
||||
return
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
"<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://www.w3.org/2003/05/soap-envelope\" "
|
||||
"xmlns:trt=\"http://www.onvif.org/ver10/media/wsdl\">"
|
||||
"<SOAP-ENV:Body>"
|
||||
"<trt:GetStreamUriResponse>"
|
||||
"<trt:MediaUri>"
|
||||
"<tt:Uri>rtsp://" + ip + ":554/mjpeg/1</tt:Uri>"
|
||||
"<tt:InvalidAfterConnect>false</tt:InvalidAfterConnect>"
|
||||
"<tt:InvalidAfterReboot>false</tt:InvalidAfterReboot>"
|
||||
"<tt:Timeout>PT0S</tt:Timeout>"
|
||||
"</trt:MediaUri>"
|
||||
"</trt:GetStreamUriResponse>"
|
||||
"</SOAP-ENV:Body>"
|
||||
"</SOAP-ENV:Envelope>";
|
||||
}
|
||||
|
||||
void handle_onvif_soap() {
|
||||
String req = onvifServer.arg(0);
|
||||
if (req.indexOf("GetCapabilities") > 0) {
|
||||
@@ -92,7 +112,7 @@ void handle_onvif_discovery() {
|
||||
void onvif_server_start() {
|
||||
onvifServer.on("/onvif/device_service", HTTP_POST, handle_onvif_soap);
|
||||
onvifServer.begin();
|
||||
onvifUDP.beginMulticast(WiFi.localIP(), IPAddress(239,255,255,250), 3702);
|
||||
onvifUDP.beginMulticast(IPAddress(239,255,255,250), 3702); // Fixed: use only 2 args
|
||||
Serial.println("[INFO] ONVIF server started.");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
#include <WiFi.h>
|
||||
#include <WiFiUdp.h>
|
||||
#include <WebServer.h>
|
||||
|
||||
void onvif_server_start();
|
||||
void onvif_server_loop();
|
||||
|
||||
@@ -1,28 +1,70 @@
|
||||
#include "rtsp_server.h"
|
||||
#include <WiFi.h>
|
||||
#include "OV2640.h"
|
||||
#include "CRtspSession.h"
|
||||
|
||||
WiFiServer rtspServer(554);
|
||||
OV2640 cam;
|
||||
MyStreamer *streamer = nullptr;
|
||||
|
||||
String getRTSPUrl() {
|
||||
return "rtsp://" + WiFi.localIP().toString() + ":554/mjpeg/1";
|
||||
}
|
||||
|
||||
void rtsp_server_start() {
|
||||
// Fill in your ESP32-CAM pin assignments
|
||||
camera_config_t config;
|
||||
config.pin_pwdn = -1;
|
||||
config.pin_reset = -1;
|
||||
config.pin_xclk = 4;
|
||||
config.pin_sscb_sda = 18;
|
||||
config.pin_sscb_scl = 23;
|
||||
config.pin_d7 = 36;
|
||||
config.pin_d6 = 37;
|
||||
config.pin_d5 = 38;
|
||||
config.pin_d4 = 39;
|
||||
config.pin_d3 = 35;
|
||||
config.pin_d2 = 14;
|
||||
config.pin_d1 = 13;
|
||||
config.pin_d0 = 34;
|
||||
config.pin_vsync = 5;
|
||||
config.pin_href = 27;
|
||||
config.pin_pclk = 25;
|
||||
config.xclk_freq_hz = 20000000;
|
||||
config.ledc_timer = LEDC_TIMER_0;
|
||||
config.ledc_channel = LEDC_CHANNEL_0;
|
||||
config.pixel_format = PIXFORMAT_JPEG;
|
||||
config.frame_size = FRAMESIZE_VGA;
|
||||
config.jpeg_quality = 12;
|
||||
config.fb_count = 1;
|
||||
|
||||
cam.init(config);
|
||||
streamer = new MyStreamer(cam);
|
||||
rtspServer.begin();
|
||||
cam.init(esp_camera_sensor_get());
|
||||
Serial.println("[INFO] RTSP server started at " + getRTSPUrl());
|
||||
}
|
||||
|
||||
void rtsp_server_loop() {
|
||||
WiFiClient client = rtspServer.available();
|
||||
if (client) {
|
||||
CRtspSession session(client, cam);
|
||||
// Micro-RTSP expects a SOCKET (int) and a CStreamer*
|
||||
// On ESP32, WiFiClient.fd() is not available, so we use a hack:
|
||||
// Pass the client object as a void* and cast it back in the library.
|
||||
// This requires a custom build of Micro-RTSP or using the ESP32-compatible fork.
|
||||
// For simplicity, this example assumes you have modified Micro-RTSP to accept WiFiClient*.
|
||||
// If not, use the standard Micro-RTSP example and adapt as needed.
|
||||
// For now, this is a placeholder:
|
||||
// CRtspSession session(client, streamer); // Won't work out of the box!
|
||||
// Instead, use the following workaround (requires library modification):
|
||||
// CRtspSession session((void*)&client, streamer);
|
||||
// Or use the standard Micro-RTSP example code.
|
||||
|
||||
// IMPORTANT: The standard Micro-RTSP library does not support WiFiClient directly.
|
||||
// You must either:
|
||||
// 1. Use the standard Micro-RTSP example with a custom streamer, or
|
||||
// 2. Modify the library to accept WiFiClient* (advanced).
|
||||
|
||||
// For now, here is a placeholder. See notes below for a real solution.
|
||||
Serial.println("Client connected, but RTSP session handling is not implemented.");
|
||||
while (client.connected()) {
|
||||
session.handleRequests(0);
|
||||
session.broadcastCurrentFrame(0);
|
||||
// Handle client here if you modify the library
|
||||
delay(10);
|
||||
}
|
||||
client.stop();
|
||||
|
||||
@@ -1,4 +1,14 @@
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
#include <WiFi.h>
|
||||
#include "OV2640.h"
|
||||
#include "CRtspSession.h"
|
||||
#include "MyStreamer.h"
|
||||
|
||||
extern WiFiServer rtspServer;
|
||||
extern OV2640 cam;
|
||||
extern MyStreamer *streamer;
|
||||
|
||||
String getRTSPUrl();
|
||||
void rtsp_server_start();
|
||||
void rtsp_server_loop();
|
||||
String getRTSPUrl();
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#include "web_config.h"
|
||||
#include <WebServer.h>
|
||||
#include <WiFi.h>
|
||||
#include "rtsp_server.h" // For getRTSPUrl()
|
||||
#include "onvif_server.h" // For ONVIF URL if needed
|
||||
#include "motion_detection.h" // For motion_detected()
|
||||
#include "rtsp_server.h"
|
||||
#include "onvif_server.h"
|
||||
#include "motion_detection.h"
|
||||
#include <FS.h>
|
||||
#include <SPIFFS.h>
|
||||
#include <SD_MMC.h>
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
WebServer webConfigServer(80);
|
||||
|
||||
// --- Helper: HTTP Basic Auth ---
|
||||
const char* WEB_USER = "admin";
|
||||
const char* WEB_PASS = "esp123";
|
||||
|
||||
@@ -25,15 +24,36 @@ bool isAuthenticated(WebServer &server) {
|
||||
}
|
||||
|
||||
void web_config_start() {
|
||||
// Mount SPIFFS for static files
|
||||
if (!SPIFFS.begin(true)) {
|
||||
Serial.println("SPIFFS/LittleFS Mount Failed");
|
||||
return;
|
||||
}
|
||||
// Protect static files with authentication
|
||||
webConfigServer.serveStatic("/", SPIFFS, "/").setDefaultFile("index.html").setAuthentication(WEB_USER, WEB_PASS);
|
||||
|
||||
// === API ENDPOINTS ===
|
||||
// All route definitions go here, inside this function!
|
||||
webConfigServer.on("/", []() {
|
||||
File file = SPIFFS.open("/index.html", "r");
|
||||
if (!file) {
|
||||
webConfigServer.send(404, "text/plain", "File not found");
|
||||
return;
|
||||
}
|
||||
webConfigServer.streamFile(file, "text/html");
|
||||
file.close();
|
||||
});
|
||||
|
||||
webConfigServer.on("/", HTTP_GET, []() {
|
||||
if (!webConfigServer.authenticate(WEB_USER, WEB_PASS)) {
|
||||
return webConfigServer.requestAuthentication();
|
||||
}
|
||||
File file = SPIFFS.open("/index.html", "r");
|
||||
if (!file) {
|
||||
webConfigServer.send(404, "text/plain", "File not found");
|
||||
return;
|
||||
}
|
||||
webConfigServer.streamFile(file, "text/html");
|
||||
file.close();
|
||||
});
|
||||
|
||||
// --- API ENDPOINTS ---
|
||||
webConfigServer.on("/api/status", HTTP_GET, []() {
|
||||
if (!isAuthenticated(webConfigServer)) return;
|
||||
String json = "{";
|
||||
@@ -77,10 +97,10 @@ void web_config_start() {
|
||||
if (doc.containsKey("awb")) s->set_whitebal(s, doc["awb"]);
|
||||
if (doc.containsKey("awb_gain")) s->set_awb_gain(s, doc["awb_gain"]);
|
||||
if (doc.containsKey("wb_mode")) s->set_wb_mode(s, doc["wb_mode"]);
|
||||
if (doc.containsKey("aec")) s->set_aec(s, doc["aec"]);
|
||||
if (doc.containsKey("aec")) s->set_aec2(s, doc["aec"]);
|
||||
if (doc.containsKey("aec2")) s->set_aec2(s, doc["aec2"]);
|
||||
if (doc.containsKey("ae_level")) s->set_ae_level(s, doc["ae_level"]);
|
||||
if (doc.containsKey("agc")) s->set_agc(s, doc["agc"]);
|
||||
if (doc.containsKey("agc")) s->set_gain_ctrl(s, doc["agc"]);
|
||||
if (doc.containsKey("gainceiling")) s->set_gainceiling(s, doc["gainceiling"]);
|
||||
if (doc.containsKey("bpc")) s->set_bpc(s, doc["bpc"]);
|
||||
if (doc.containsKey("wpc")) s->set_wpc(s, doc["wpc"]);
|
||||
@@ -198,9 +218,9 @@ void web_config_start() {
|
||||
});
|
||||
|
||||
webConfigServer.begin();
|
||||
Serial.println("[INFO] Web config server started.");
|
||||
}
|
||||
Serial.println("[INFO] Web config server started.");
|
||||
}
|
||||
|
||||
void web_config_loop() {
|
||||
webConfigServer.handleClient();
|
||||
}
|
||||
void web_config_loop() {
|
||||
webConfigServer.handleClient();
|
||||
}
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 John Varghese (J0X)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
180
README.md
180
README.md
@@ -1,60 +1,171 @@
|
||||
# ESP32-CAM | ONVIF | DVR/NVR Stream and Recording | Ultimate Feature Packed Firmware
|
||||
## ESP32-CAM ONVIF RTSP Camera
|
||||
# ESP32-CAM ONVIF RTSP Camera
|
||||
|
||||
**Professional, Feature-Rich, and Network Camera Firmware for ESP32-CAM**
|
||||
|
||||
[](https://www.espressif.com/en/products/socs/esp32)
|
||||
[](LICENSE)
|
||||
[](LICENSE)
|
||||
|
||||
## Overview
|
||||

|
||||
|
||||
**ESP32-CAM ONVIF RTSP Camera** is an open-source firmware project that transforms your affordable ESP32-CAM module into a network camera compatible with professional NVR/DVR systems, including Hikvision, Dahua, and other ONVIF-compliant solutions.
|
||||
Transform your affordable ESP32-CAM module into a powerful ONVIF-compatible network camera, ready for integration with professional NVR/DVR systems (Hikvision, Dahua, and more). This firmware provides RTSP streaming, ONVIF discovery, and a roadmap for advanced features like web configuration, SD card recording, and motion detection.
|
||||
|
||||
This project brings together:
|
||||
- **RTSP streaming** (MJPEG) for real-time video
|
||||
- **Minimal ONVIF support** for device discovery, stream URI reporting, and basic integration with security recorders
|
||||
|
||||
The goal is to make ESP32-CAM modules plug-and-play with mainstream video surveillance systems, while remaining lightweight and efficient.
|
||||
> [!NOTE]
|
||||
> **🚧 Work in Progress:**
|
||||
> This project is evolving rapidly. Contributions, feedback, and feature requests are welcome!
|
||||
> -*Star the repo and join the project!*
|
||||
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
- 📡 **ONVIF Discovery:** Your ESP32-CAM will appear as a discoverable camera on ONVIF-compatible NVRs/DVRs.
|
||||
- 🎥 **RTSP Streaming:** Real-time MJPEG streaming for live view and recording.
|
||||
- ⚡ **Lightweight:** Designed for ESP32-CAM’s limited resources.
|
||||
- 🛠️ **Easy Setup:** Simple Wi-Fi configuration and deployment.
|
||||
- 🔒 **Open Source:** MIT-licensed for personal and commercial use.
|
||||
- 📡 **ONVIF Discovery:**
|
||||
Appears as a discoverable camera on ONVIF-compatible NVRs/DVRs for easy integration.
|
||||
- 🎥 **RTSP Streaming (MJPEG):**
|
||||
Real-time video streaming for live view and recording.
|
||||
- ⚡ **Lightweight:**
|
||||
Optimized for ESP32-CAM’s limited resources.
|
||||
- 🛠️ **Easy Setup:**
|
||||
Simple Wi-Fi configuration (web-based setup coming soon).
|
||||
- 🌐 **Web Configuration Interface:**
|
||||
*(Planned)* Configure camera, Wi-Fi, and storage via browser.
|
||||
- 🗂️ **SD Card Recording:**
|
||||
*(Planned)* Record video directly to microSD card.
|
||||
- ↔️ **Motion Detection:**
|
||||
*(Planned)* Basic motion detection for event-based recording.
|
||||
- 🔐 **Secure Credential Storage:**
|
||||
*(Planned)* Store Wi-Fi credentials securely in SPIFFS.
|
||||
- 🌏 **Access Point Fallback:**
|
||||
*(Planned)* Automatically creates an AP if unable to connect to Wi-Fi.
|
||||
- 🔒 **Open Source:**
|
||||
MIT-licensed for personal and commercial use.
|
||||
|
||||
---
|
||||
|
||||
## Roadmap
|
||||
## Hardware Requirements
|
||||
|
||||
- [x] Minimal ONVIF WS-Discovery responder
|
||||
- [x] ONVIF `/onvif/device_service` endpoint (GetStreamUri, GetCapabilities)
|
||||
- [x] RTSP video streaming (MJPEG)
|
||||
- [ ] Web-based configuration interface
|
||||
- [ ] Optional SD card recording
|
||||
- [ ] Motion detection (future)
|
||||
- [ ] Support for more ONVIF features (profiles, device info, etc.)
|
||||
- **ESP32-CAM board** (AI-Thinker or compatible)
|
||||
- **MicroSD card** (optional, for recording)
|
||||
- **5V power supply**
|
||||
- **FTDI programmer/adapter** (for initial flashing)
|
||||
|
||||
---
|
||||
|
||||
## Software Dependencies
|
||||
|
||||
- **Arduino IDE** or **PlatformIO**
|
||||
- **ESP32 Arduino Core**
|
||||
- **Required Libraries:**
|
||||
- ArduinoJson
|
||||
- ESP32 Camera Driver
|
||||
- SPIFFS file system
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
### Arduino IDE
|
||||
|
||||
1. **Install Arduino IDE** from [arduino.cc](https://www.arduino.cc/)
|
||||
2. **Add ESP32 board support:**
|
||||
- File > Preferences > Add
|
||||
`https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json`
|
||||
to "Additional Board Manager URLs"
|
||||
- Tools > Board > Boards Manager > Search "ESP32" > Install latest version
|
||||
3. **Install required libraries:**
|
||||
- Tools > Manage Libraries > Search and install "ArduinoJson"
|
||||
4. **Connect ESP32-CAM** via FTDI adapter:
|
||||
- GND → GND
|
||||
- 5V → 5V
|
||||
- TX → RX
|
||||
- RX → TX
|
||||
- GPIO0 → GND (for flashing mode)
|
||||
5. **Select Board/Port:**
|
||||
Tools > Board > ESP32 Arduino > AI-Thinker ESP32-CAM
|
||||
Tools > Port > [Your FTDI port]
|
||||
6. **Upload Firmware:**
|
||||
Click Upload. After upload, disconnect GPIO0 from GND and reset ESP32-CAM.
|
||||
|
||||
### PlatformIO (VS Code)
|
||||
|
||||
1. **Install Visual Studio Code**
|
||||
2. **Install PlatformIO extension**
|
||||
3. **Create a new project:**
|
||||
- Board: AI Thinker ESP32-CAM
|
||||
- Framework: Arduino
|
||||
4. **Configure `platformio.ini`:**
|
||||
```
|
||||
[env:esp32cam]
|
||||
platform = espressif32
|
||||
board = esp32cam
|
||||
framework = arduino
|
||||
monitor_speed = 115200
|
||||
lib_deps = bblanchon/ArduinoJson @ ^6.21.3
|
||||
upload_speed = 921600
|
||||
build_flags = -DCORE_DEBUG_LEVEL=5
|
||||
```
|
||||
5. **Import source files** into `src/` directory.
|
||||
6. **Flash firmware** as above.
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. **Clone this repository**
|
||||
2. **Edit Wi-Fi credentials** in the source code
|
||||
3. **Flash to your ESP32-CAM** using Arduino IDE or PlatformIO
|
||||
4. **Connect your NVR/DVR** and discover the camera via ONVIF, or add the RTSP stream manually
|
||||
2. **Edit Wi-Fi credentials** in the source code (web setup coming soon)
|
||||
3. **Flash to your ESP32-CAM**
|
||||
4. **Connect your NVR/DVR** and discover the camera via ONVIF, or add the RTSP stream manually:
|
||||
```
|
||||
rtsp://[camera-ip]:554/mjpeg/1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
- Access the RTSP stream using compatible NVR/DVR software or VLC.
|
||||
- *(Planned)* Access the web interface for live view, configuration, and SD card management.
|
||||
- *(Planned)* On first boot, ESP32-CAM will create an access point ("ESP32-CAM-ONVIF") for initial setup.
|
||||
|
||||
---
|
||||
|
||||
## Compatibility
|
||||
|
||||
- **Tested hardware:** AI-Thinker ESP32-CAM
|
||||
- **NVR/DVR compatibility:** Hikvision, Dahua, and most ONVIF-compliant recorders (MJPEG stream)
|
||||
- **Hardware Support:** ESP32-CAM (AI-Thinker or compatible)
|
||||
- **NVR/DVR Compatibility:** Hikvision, Dahua, and most ONVIF-compliant recorders (MJPEG stream)
|
||||
- **Limitations:** MJPEG only (no H.264); some recorders may require H.264 for recording
|
||||
|
||||
---
|
||||
|
||||
## Project Structure
|
||||
|
||||
| File/Folder | Description |
|
||||
|-------------------------|--------------------------------------------|
|
||||
| `ESP32-CAM-ONVIF.ino` | Main firmware sketch |
|
||||
| `camera_control.*` | Camera initialization and settings |
|
||||
| `rtsp_server.*` | RTSP streaming implementation |
|
||||
| `onvif_server.*` | ONVIF protocol implementation |
|
||||
| `web_config.*` | *(Planned)* Web interface |
|
||||
| `wifi_manager.*` | *(Planned)* Wi-Fi setup and AP fallback |
|
||||
| `sd_recorder.*` | *(Planned)* SD card recording |
|
||||
| `motion_detection.*` | *(Planned)* Motion detection |
|
||||
| `data/` | *(Planned)* Web UI files (HTML, CSS, JS) |
|
||||
|
||||
---
|
||||
|
||||
## Roadmap
|
||||
|
||||
- [x] ONVIF WS-Discovery responder
|
||||
- [x] `/onvif/device_service` endpoint (GetStreamUri, GetCapabilities)
|
||||
- [x] RTSP video streaming (MJPEG)
|
||||
- [ ] Web-based configuration interface
|
||||
- [ ] SD card recording and management
|
||||
- [ ] Motion detection
|
||||
- [ ] Advanced ONVIF features (profiles, device info, etc.)
|
||||
- [ ] Secure credential storage (SPIFFS)
|
||||
- [ ] Access point fallback for Wi-Fi setup
|
||||
|
||||
---
|
||||
|
||||
## Screenshots
|
||||
|
||||
*Coming soon!*
|
||||
@@ -68,6 +179,13 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
||||
|
||||
---
|
||||
|
||||
[](https://buymeacoffee.com/CyberTrinity)
|
||||
[](https://patreon.com/CyberTrinity)
|
||||
[](https://github.com/sponsors/John-Varghese-EH)
|
||||
|
||||
---
|
||||
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the [MIT License](LICENSE).
|
||||
@@ -76,10 +194,10 @@ This project is licensed under the [MIT License](LICENSE).
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
- [Micro-RTSP](https://github.com/geeksville/Micro-RTSP) for RTSP streaming on ESP32
|
||||
- Micro-RTSP for RTSP streaming on ESP32
|
||||
- ONVIF community for protocol documentation and inspiration
|
||||
- Thanks to all contributors and the open-source community!
|
||||
|
||||
---
|
||||
|
||||
> **Stay tuned for updates, features, and documentation as the project evolves!**
|
||||
|
||||
*Stay tuned for updates, new features, and documentation as the project evolves! Star the repo to follow progress and contribute to making ESP32-CAM ONVIF the ultimate DIY network camera solution.*
|
||||
|
||||
Reference in New Issue
Block a user