329 lines
6.5 KiB
C++
329 lines
6.5 KiB
C++
#include "esp_camera.h"
|
|
#include <WiFi.h>
|
|
#include "esp_http_server.h"
|
|
|
|
#include <PubSubClient.h>
|
|
#include <Wire.h>
|
|
#include <BH1750.h>
|
|
|
|
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;
|
|
|
|
|
|
// 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_QQVGA;
|
|
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");
|
|
}
|
|
|
|
|
|
void connectMQTT() {
|
|
while (!client.connected()) {
|
|
String id = "ESP32CAM-" + String(WiFi.macAddress());
|
|
|
|
if (client.connect(id.c_str())) {
|
|
Serial.println("MQTT OK");
|
|
} else {
|
|
Serial.println("MQTT FAIL");
|
|
delay(2000);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
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);
|
|
} |