#include "esp_camera.h" #include #include "esp_http_server.h" #include #include #include #include #include BH1750 lightMeter; #define AHT20_ADDR 0x38 float temperature = 0; float humidity = 0; WiFiClient espClient; PubSubClient client(espClient); const char* mqtt_server = "192.168.31.78"; // WIFI const char* ssid = "Cathouse"; const char* password = "88888888"; IPAddress local_IP(192,168,31,235); IPAddress gateway(192,168,31,1); IPAddress subnet(255,255,255,0); IPAddress dns(192,168,31,1); // CAMERA PINS #define PWDN_GPIO_NUM -1 #define RESET_GPIO_NUM -1 #define XCLK_GPIO_NUM 15 #define SIOD_GPIO_NUM 4 #define SIOC_GPIO_NUM 5 #define Y9_GPIO_NUM 16 #define Y8_GPIO_NUM 17 #define Y7_GPIO_NUM 18 #define Y6_GPIO_NUM 12 #define Y5_GPIO_NUM 10 #define Y4_GPIO_NUM 8 #define Y3_GPIO_NUM 9 #define Y2_GPIO_NUM 11 #define VSYNC_GPIO_NUM 6 #define HREF_GPIO_NUM 7 #define PCLK_GPIO_NUM 13 // HTTP SERVER httpd_handle_t server = NULL; #define LED_PIN 21 #define LED_COUNT 8 #define SERVO_PIN 47 Servo myServo; Adafruit_NeoPixel strip( LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800 ); // STREAM HANDLER static esp_err_t stream_handler(httpd_req_t *req) { camera_fb_t *fb = NULL; static const char* boundary = "--frame\r\n"; static const char* header = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n"; httpd_resp_set_type(req, "multipart/x-mixed-replace; boundary=frame"); uint32_t start = millis(); while (true) { if (millis() - start > 60000) { break; } fb = esp_camera_fb_get(); if (!fb) { vTaskDelay(2); continue; } char part[64]; int hlen = snprintf(part, sizeof(part), header, fb->len); if (httpd_resp_send_chunk(req, boundary, strlen(boundary)) != ESP_OK) { esp_camera_fb_return(fb); break; } if (httpd_resp_send_chunk(req, part, hlen) != ESP_OK) { esp_camera_fb_return(fb); break; } if (httpd_resp_send_chunk(req, (const char*)fb->buf, fb->len) != ESP_OK) { esp_camera_fb_return(fb); break; } esp_camera_fb_return(fb); vTaskDelay(2); } return ESP_OK; } // START SERVER void startServer() { httpd_config_t config = HTTPD_DEFAULT_CONFIG(); config.server_port = 80; config.stack_size = 8192; config.max_uri_handlers = 8; config.recv_wait_timeout = 10; config.send_wait_timeout = 10; if (httpd_start(&server, &config) == ESP_OK) { httpd_uri_t uri = { .uri = "/stream", .method = HTTP_GET, .handler = stream_handler, .user_ctx = NULL }; httpd_register_uri_handler(server, &uri); Serial.println("HTTP STREAM READY"); } } bool initCamera() { 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_QVGA; config.jpeg_quality = 20; config.grab_mode = CAMERA_GRAB_LATEST; config.fb_count = 1; config.fb_location = CAMERA_FB_IN_DRAM; esp_err_t err = esp_camera_init(&config); if (err != ESP_OK) { Serial.printf("Camera init FAIL: 0x%x\n", err); return false; } sensor_t *s = esp_camera_sensor_get(); s->set_vflip(s, 1); s->set_brightness(s, 1); s->set_whitebal(s, 1); s->set_awb_gain(s, 1); s->set_exposure_ctrl(s, 1); s->set_gain_ctrl(s, 1); Serial.println("CAMERA OK"); return true; } bool readAHT20(float &temp, float &hum) { uint8_t cmd[3] = {0xAC, 0x33, 0x00}; Wire.beginTransmission(AHT20_ADDR); Wire.write(cmd, 3); if (Wire.endTransmission() != 0) return false; delay(80); Wire.requestFrom(AHT20_ADDR, 6); if (Wire.available() < 6) return false; uint8_t data[6]; for (int i = 0; i < 6; i++) data[i] = Wire.read(); uint32_t h = ((data[1] << 12) | (data[2] << 4) | (data[3] >> 4)); uint32_t t = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5]; hum = (h * 100.0) / 1048576.0; temp = (t * 200.0 / 1048576.0) - 50; return true; } void setup() { Serial.begin(115200); delay(1500); if (!initCamera()) { delay(3000); ESP.restart(); } WiFi.config(local_IP, gateway, subnet, dns); WiFi.begin(ssid, password); WiFi.setSleep(false); while (WiFi.status() != WL_CONNECTED) { delay(300); Serial.print("."); } Serial.println("\nWIFI OK"); Serial.println(WiFi.localIP()); Wire.begin(1, 2); Wire.setClock(100000); lightMeter.begin(); client.setServer(mqtt_server, 1883); startServer(); Serial.println("STREAM READY:"); Serial.println("http://192.168.31.235/stream"); strip.begin(); strip.show(); strip.setBrightness(80); client.setCallback(callback); myServo.attach(SERVO_PIN); servoStop(); } void connectMQTT() { while (!client.connected()) { String id = "ESP32CAM-" + String(WiFi.macAddress()); if (client.connect(id.c_str())) { Serial.println("MQTT OK"); client.subscribe("esp32/led"); client.subscribe("esp32/servo"); } else { Serial.println("MQTT FAIL"); delay(2000); } } } void setColor(int r, int g, int b) { for (int i = 0; i < LED_COUNT; i++){ strip.setPixelColor(i, strip.Color(r, g, b)); } strip.show(); } void servoStop() { myServo.write(92); } void servoLeft(int ms) { myServo.write(30); unsigned long start = millis(); while (millis() - start < ms) { client.loop(); delay(10); } servoStop(); } void servoRight(int ms) { myServo.write(150); unsigned long start = millis(); while (millis() - start < ms) { client.loop(); delay(10); } servoStop(); } void callback(char* topic, byte* payload, unsigned int length) { String msg; for (int i = 0; i < length; i++){ msg += (char)payload[i]; } Serial.print("MQTT: "); Serial.println(msg); if (String(topic) == "esp32/led"){ if (msg == "OFF"){ setColor(0,0,0); return; } int r,g,b; sscanf(msg.c_str(), "%d,%d,%d", &r,&g,&b); setColor(r,g,b); } if (String(topic) == "esp32/servo") { // ДЕНЬ if (msg == "DAY"){ servoRight(10000); } // НОЧЬ if (msg == "NIGHT"){ servoLeft(10000); } // ПОЛДЕНЬ if (msg == "MID"){ servoRight(5000); } } } void loop() { if (!client.connected()) connectMQTT(); client.loop(); static unsigned long lastMQTT = 0; if (millis() - lastMQTT > 5000) { lastMQTT = millis(); float lux = lightMeter.readLightLevel(); readAHT20(temperature, humidity); char buf[32]; snprintf(buf, sizeof(buf), "%.2f", lux); client.publish("esp32/sensors/light", buf); snprintf(buf, sizeof(buf), "%.2f", temperature); client.publish("esp32/sensors/temp", buf); snprintf(buf, sizeof(buf), "%.2f", humidity); client.publish("esp32/sensors/humidity", buf); Serial.println("MQTT SEND"); Serial.print("Lux: "); Serial.println(lux); Serial.print("Temp: "); Serial.println(temperature); Serial.print("Hum: "); Serial.println(humidity); } vTaskDelay(2); }