diff --git a/esphome/esp32-h2c-camera.yaml b/esphome/esp32-h2c-camera.yaml deleted file mode 100644 index 03e0e99..0000000 --- a/esphome/esp32-h2c-camera.yaml +++ /dev/null @@ -1,275 +0,0 @@ -substitutions: - device_name: esp32-h2c-camera - friendly_name: "H2C Camera" - -esphome: - name: ${device_name} - friendly_name: ${friendly_name} - -esp32: - board: esp32-s3-devkitc-1 - framework: - type: esp-idf - -# Required for ESP32 camera buffering. -psram: - mode: octal - -logger: - -api: - encryption: - key: !secret api_encryption_key - -ota: - - platform: esphome - password: !secret ota_password - -wifi: - ssid: !secret wifi_iot_ssid - password: !secret wifi_password - manual_ip: - static_ip: 192.168.69.90 - gateway: 192.168.69.1 - subnet: 255.255.255.0 - ap: - ssid: "${friendly_name} Fallback" - password: !secret fallback_password - # Prevents aggressive reconnection attempts - power_save_mode: none # Use 'light' for battery devices - - # Slower but more reliable connection - fast_connect: true - - # Handle connection failures gracefully - on_connect: - - logger.log: "Wi-Fi connected!" - on_disconnect: - - logger.log: "Wi-Fi disconnected!" - -# Reduce mDNS traffic -mdns: - disabled: true # Set to true if you use static IPs and don't need discovery - -# captive_portal: - -web_server: - port: 80 - -esp32_camera: - name: "${friendly_name}" - external_clock: - pin: GPIO5 - # 10MHz (half the usual 20MHz) slows the sensor's line rate, so each of the - # 1200 exposure lines below collects roughly twice the light. Costs - # framerate, which does not matter for chamber monitoring. - frequency: 10MHz - i2c_pins: - sda: GPIO8 - scl: GPIO9 - data_pins: [GPIO16, GPIO18, GPIO21, GPIO17, GPIO14, GPIO7, GPIO6, GPIO4] - vsync_pin: GPIO1 - href_pin: GPIO2 - pixel_clock_pin: GPIO15 - - # Resolution & quality (ESP32-S3 with Octal PSRAM handles XGA easily) - resolution: 1024X768 - jpeg_quality: 10 - max_framerate: 20 fps - idle_framerate: 0.2 fps - frame_buffer_count: 2 - - # Orientation - vertical_flip: true - horizontal_mirror: false - - # Image tuning for chamber monitoring through tinted door. - # Low contrast + high brightness lifts the shadows; the LED strips are - # allowed to blow out since the chamber is what matters. - brightness: 2 - contrast: -2 - saturation: 0 - - # Exposure & gain are MANUAL on purpose. The two LED strips in frame kept the - # auto-exposure meter satisfied, so AEC never lengthened the exposure and the - # tinted-door scene stayed black regardless of gain ceiling or AE level. - # Pinning both to max forces a bright chamber; the strips clip out entirely. - aec_mode: manual - aec_value: 1200 # max integration time (0-1200 lines) - aec2: true - ae_level: 2 # only consulted if AEC is flipped back to auto - agc_mode: manual - agc_value: 30 # max sensor gain (0-30) - agc_gain_ceiling: 128X # only consulted if AGC is flipped back to auto - wb_mode: auto - -# Camera endpoints: -# Stream: http://:8080 -# Snapshot: http://:8081 -esp32_camera_web_server: - - port: 8080 - mode: stream - - port: 8081 - mode: snapshot - -switch: - # DFRobot board IR illumination control pin. - - platform: gpio - name: "${friendly_name} IR LED" - pin: GPIO47 - restore_mode: ALWAYS_OFF - - # Flip exposure/gain back to automatic for A/B comparison without a reflash. - # Off (the default) = manual exposure per the esp32_camera block above. - - platform: template - name: "${friendly_name} Auto Exposure" - optimistic: true - restore_mode: ALWAYS_OFF - turn_on_action: - - lambda: |- - sensor_t *s = esp_camera_sensor_get(); - if (!s) return; - s->set_exposure_ctrl(s, 1); - s->set_gain_ctrl(s, 1); - turn_off_action: - - lambda: |- - sensor_t *s = esp_camera_sensor_get(); - if (!s) return; - s->set_exposure_ctrl(s, 0); - s->set_gain_ctrl(s, 0); - -sensor: - - platform: wifi_signal - name: "${friendly_name} WiFi Signal" - update_interval: 60s - - - platform: uptime - name: "${friendly_name} Uptime" - - - platform: wifi_signal - name: "${device_name} WiFi Signal" - update_interval: 60s - - - platform: uptime - name: "${device_name} Uptime" - update_interval: 60s - -button: - - platform: restart - name: "${friendly_name} Restart" - -text_sensor: - - platform: wifi_info - ip_address: - name: "${device_name} IP Address" - ssid: - name: "${device_name} Connected SSID" - bssid: - name: "${device_name} BSSID" - -# Watchdog to auto-reboot if things go wrong -interval: - - interval: 5min - then: - - if: - condition: - and: - - lambda: 'return millis() > 300000;' # >5 min uptime - - not: - wifi.connected: - then: - - logger.log: "Wi-Fi not connected for 5 min, rebooting..." - - delay: 10s - - lambda: 'App.safe_reboot();' - -# Dynamic controls exposed to Home Assistant for real-time camera tuning -number: - # The two that actually drive image brightness in manual mode. - - platform: template - name: "${friendly_name} Exposure" - min_value: 0 - max_value: 1200 - step: 25 - initial_value: 1200 - optimistic: true - set_action: - - lambda: |- - sensor_t *s = esp_camera_sensor_get(); - if (s) s->set_aec_value(s, (int)x); - - - platform: template - name: "${friendly_name} Gain" - min_value: 0 - max_value: 30 - step: 1 - initial_value: 30 - optimistic: true - set_action: - - lambda: |- - sensor_t *s = esp_camera_sensor_get(); - if (s) s->set_agc_gain(s, (int)x); - - - platform: template - name: "${friendly_name} Brightness" - min_value: -2 - max_value: 2 - step: 1 - initial_value: 2 - optimistic: true - set_action: - - lambda: |- - sensor_t *s = esp_camera_sensor_get(); - if (s) s->set_brightness(s, (int)x); - - - platform: template - name: "${friendly_name} Contrast" - min_value: -2 - max_value: 2 - step: 1 - initial_value: -2 - optimistic: true - set_action: - - lambda: |- - sensor_t *s = esp_camera_sensor_get(); - if (s) s->set_contrast(s, (int)x); - - - platform: template - name: "${friendly_name} AE Level" - min_value: -2 - max_value: 2 - step: 1 - initial_value: 2 - optimistic: true - set_action: - - lambda: |- - sensor_t *s = esp_camera_sensor_get(); - if (s) s->set_ae_level(s, (int)x); - -select: - # Caps how far AGC may amplify. Higher = brighter but noisier; back this off - # if the chamber image gets too grainy at 128X. - - platform: template - name: "${friendly_name} Gain Ceiling" - optimistic: true - initial_option: "128X" - options: - - "2X" - - "4X" - - "8X" - - "16X" - - "32X" - - "64X" - - "128X" - set_action: - - lambda: |- - sensor_t *s = esp_camera_sensor_get(); - if (!s) return; - int idx = 6; - if (x == "2X") idx = 0; - else if (x == "4X") idx = 1; - else if (x == "8X") idx = 2; - else if (x == "16X") idx = 3; - else if (x == "32X") idx = 4; - else if (x == "64X") idx = 5; - s->set_gainceiling(s, (gainceiling_t)idx); -