Hello, I have a project about processing and using a telegram bot to notify, but when I want to view the camera in real time (livecam) and process that command via the telegram bot, it still responds but the link it provides connection refused or "Not found: /stream" message when I click on that link, and on the serial it shows an error "E (828) httpd: httpd_server_init: error in listen (112)", I also don't know right how to fix it because I tried every port (except port 80 because I used it for image processing and then sent it via telegram), please help me fix this, I really appreciate it!!!, here are my 2 codes:
code esp32:
#include <WebServer.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
#include <UniversalTelegramBot.h>
#include <ArduinoJson.h>
#include "esp_camera.h"
#include "esp_http_server.h"
const char* WIFI_SSID = "CA HA";
const char* WIFI_PASS = "khongmuoncho";
String BOTtoken = "8066448351:AAHGjtfdoWEfD2C93OD-zrcN-ZtUasEscGk";
String CHAT_ID = "7638387914";
#define CAMERA_MODEL_AI_THINKER
#include "camera_pins.h"
WiFiClientSecure clientTCP;
UniversalTelegramBot bot(BOTtoken, clientTCP);
WebServer server(3000);
#define FLASH_LED_PIN 4
bool flashState = LOW;
bool liveStreamActive = false;
httpd_handle_t stream_httpd = NULL;
void configInitCamera() {
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_sccb_sda = SIOD_GPIO_NUM;
config.pin_sccb_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;
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 12;
config.fb_count = 1;
if (esp_camera_init(&config) != ESP_OK) {
Serial.println("Camera init failed");
return;
}
}
void startCameraServer() {
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.server_port = 3000;
httpd_uri_t stream_uri = {
.uri = "/stream",
.method = HTTP_GET,
.handler = [](httpd_req_t *req) -> esp_err_t {
camera_fb_t *fb = NULL;
esp_err_t res = ESP_OK;
res = httpd_resp_set_type(req, "multipart/x-mixed-replace; boundary=frame");
while (liveStreamActive) {
fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Camera capture failed");
res = ESP_FAIL;
break;
} else {
httpd_resp_send_chunk(req, (const char*)fb->buf, fb->len);
esp_camera_fb_return(fb);
}
}
return res;
},
.user_ctx = NULL
};
if (httpd_start(&stream_httpd, &config) == ESP_OK) {
httpd_register_uri_handler(stream_httpd, &stream_uri);
}
}
void stopCameraServer() {
if (stream_httpd) {
httpd_stop(stream_httpd);
stream_httpd = NULL;
Serial.println("Live stream server stopped");
}
}
void sendPhotoTelegram(String detectedObject) {
const char* myDomain = "api.telegram.org";
camera_fb_t *fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Camera capture failed");
return;
}
if (clientTCP.connect(myDomain, 443)) {
String head = "--boundary\r\nContent-Disposition: form-data; name=\"chat_id\"; \r\n\r\n" + CHAT_ID + "\r\n--boundary\r\nContent-Disposition: form-data; name=\"photo\"; filename=\"esp32-cam.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n";
String tail = "\r\n--boundary--\r\n";
clientTCP.println("POST /bot" + BOTtoken + "/sendPhoto HTTP/1.1");
clientTCP.println("Host: " + String(myDomain));
clientTCP.println("Content-Length: " + String(fb->len + head.length() + tail.length()));
clientTCP.println("Content-Type: multipart/form-data; boundary=boundary");
clientTCP.println();
clientTCP.print(head);
clientTCP.write(fb->buf, fb->len);
clientTCP.print(tail);
String msg = "Detected " + detectedObject + " in the area!";
bot.sendMessage(CHAT_ID, msg, "");
esp_camera_fb_return(fb);
clientTCP.stop();
}
}
void handleTelegramCommands(int numNewMessages) {
for (int i = 0; i < numNewMessages; i++) {
String chat_id = String(bot.messages[i].chat_id);
if (chat_id != CHAT_ID){
bot.sendMessage(chat_id, "Unauthorized user", "");
continue;
}
String text = bot.messages[i].text;
Serial.println(text);
String from_name = bot.messages[i].from_name;
if (text == "/adminmode") {
String welcome = "Welcome, " + from_name + "\n";
welcome += " <CHẾ ĐỘ CHO QUẢN TRỊ VIÊN>, Xin chào: ADMIN! \n";
welcome += "/flash : Bật đèn LED \n";
welcome += "/livecam : xem cam ở chế độ thời gian thực \n";
bot.sendMessage(CHAT_ID, welcome, "");
}
if (text == "/livecam") {
if (!liveStreamActive) {
liveStreamActive = true;
bot.sendMessage(chat_id, "View live stream at: http://" + WiFi.localIP().toString() + "/stream", "");
} else {
liveStreamActive = false;
bot.sendMessage(chat_id, "Live stream stopped. Resuming object detection.", "");
}
}
if (text == "/flash") {
flashState = !flashState;
digitalWrite(FLASH_LED_PIN, flashState);
Serial.println("Flash state toggled");
}
}
}
void detectObject() {
if (liveStreamActive) return; // Bỏ qua phát hiện khi live stream đang bật
camera_fb_t *fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Camera capture failed");
return;
}
const char* serverUrl = "http://192.168.1.11:80/detect_objects";
HTTPClient http;
http.begin(serverUrl);
http.addHeader("Content-Type", "image/jpeg");
int httpResponseCode = http.POST(fb->buf, fb->len);
if (httpResponseCode > 0) {
String response = http.getString();
Serial.println(response);
DynamicJsonDocument doc(1024);
deserializeJson(doc, response);
if (doc.containsKey("object")) {
String detectedObject = doc["object"].as<String>();
sendPhotoTelegram(detectedObject);
}
} else {
Serial.println("Error on HTTP request");
}
esp_camera_fb_return(fb);
http.end();
}
void setup() {
Serial.begin(115200);
pinMode(FLASH_LED_PIN, OUTPUT);
digitalWrite(FLASH_LED_PIN, flashState);
WiFi.begin(WIFI_SSID, WIFI_PASS);
clientTCP.setCACert(TELEGRAM_CERTIFICATE_ROOT);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
configInitCamera();
server.begin();
startCameraServer();
}
void loop() {
static unsigned long lastDetectTime = 0;
static unsigned long lastMessageCheckTime = 0;
unsigned long currentMillis = millis();
server.handleClient();
if (!liveStreamActive && (currentMillis - lastDetectTime >= 200)) {
detectObject();
lastDetectTime = currentMillis;
}
if (currentMillis - lastMessageCheckTime >= 100) {
int numNewMessages = bot.getUpdates(bot.last_message_received + 1);
if (numNewMessages > 0) {
handleTelegramCommands(numNewMessages);
}
lastMessageCheckTime = currentMillis;
}
}
serverpython code:
import requests
from flask import Flask, request, jsonify
import cv2
import numpy as np
import os
app = Flask(__name__)
net = cv2.dnn.readNet("yolov3.weights", "yolov3.cfg")
with open("coco.names", "r") as f:
classes = [line.strip() for line in f.readlines()]
layer_names = net.getLayerNames()
output_layers = [layer_names[i - 1] for i in net.getUnconnectedOutLayers().flatten()]
target_labels = ["knife", "scissors", "cell phone", "baseball bat"]
TELEGRAM_TOKEN = "8066448351:AAHGjtfdoWEfD2C93OD-zrcN-ZtUasEscGk"
CHAT_ID = "7638387914"
def send_telegram_notification(detected_objects, img):
url = f"https://api.telegram.org/bot{TELEGRAM_TOKEN}/sendPhoto"
message = "Phat hien vat the:\n" + "\n".join([f"{obj['label']} (voi do chinh xac: {obj['confidence']:.2f})" for obj in detected_objects])
temp_image_path = "detected_image.jpg"
cv2.imwrite(temp_image_path, img)
with open(temp_image_path, "rb") as image_file:
data = {
"chat_id": CHAT_ID,
"caption": message
}
files = {
"photo": image_file
}
response = requests.post(url, data=data, files=files)
if response.status_code == 200:
print("Notification sent successfully.")
else:
print("Failed to send notification:", response.text)
@app.route('/detect_objects', methods=['POST'])
def detect_objects():
if request.method == 'POST':
file = request.data
np_array = np.frombuffer(file, np.uint8)
img = cv2.imdecode(np_array, cv2.IMREAD_COLOR)
if img is None:
return jsonify({"error": "Could not decode the image."}), 400
height, width = img.shape[:2]
blob = cv2.dnn.blobFromImage(img, 0.00392, (416, 416), (0, 0, 0), True, crop=False)
net.setInput(blob)
outs = net.forward(output_layers)
class_ids = []
confidences = []
boxes = []
for out in outs:
for detection in out:
scores = detection[5:]
class_id = np.argmax(scores)
confidence = scores[class_id]
label = classes[class_id]
if confidence > 0.5 and label in target_labels:
center_x = int(detection[0] * width)
center_y = int(detection[1] * height)
w = int(detection[2] * width)
h = int(detection[3] * height)
x = int(center_x - w / 2)
y = int(center_y - h / 2)
boxes.append([x, y, w, h])
confidences.append(float(confidence))
class_ids.append(class_id)
indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4)
detected_objects = []
if len(indexes) > 0:
for i in indexes.flatten():
x, y, w, h = boxes[i]
label = classes[class_ids[i]]
detected_objects.append({"label": label, "confidence": confidences[i], "box": [x, y, w, h]})
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 255, 255), 2)
cv2.putText(img, label, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
if detected_objects:
send_telegram_notification(detected_objects, img)
return jsonify({"detected_objects": detected_objects})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)