Compare commits

...
5 Commits
4 changed files with 0 additions and 729 deletions
-275
View File
@@ -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://<ip>:8080
# Snapshot: http://<ip>: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);
-128
View File
@@ -1,128 +0,0 @@
# Lights-only first version for the Family Room remote.
# Entity IDs came from the project's HA snapshot; verify them in live HA.
substitutions:
device_name: family-room-remote
friendly_name: Family Room Remote
esphome:
name: ${device_name}
friendly_name: ${friendly_name}
packages:
hardware: !include panel-remote-common.yaml
binary_sensor:
- platform: homeassistant
id: standing_lamp_state
entity_id: light.living_room_lamp_1
trigger_on_initial_state: true
on_state:
- lvgl.widget.update:
id: standing_lamp_button
state:
checked: !lambda return x;
- platform: homeassistant
id: small_lamp_state
entity_id: light.small_family_room_lamp
trigger_on_initial_state: true
on_state:
- lvgl.widget.update:
id: small_lamp_button
state:
checked: !lambda return x;
- platform: homeassistant
id: tv_stand_state
entity_id: light.family_room_tv_stand
trigger_on_initial_state: true
on_state:
- lvgl.widget.update:
id: tv_stand_button
state:
checked: !lambda return x;
lvgl:
rotation: 90
on_idle:
- timeout: 45s
then:
- light.turn_on:
id: panel_backlight
brightness: 15%
pages:
- id: room_page
widgets:
- label:
x: 12
y: 8
text: Family Room
- button:
id: standing_lamp_button
x: 10
y: 45
width: 145
height: 75
checkable: true
widgets:
- label:
align: CENTER
text: Standing Lamp
on_click:
- homeassistant.action:
action: light.toggle
data:
entity_id: light.living_room_lamp_1
- button:
id: small_lamp_button
x: 165
y: 45
width: 145
height: 75
checkable: true
widgets:
- label:
align: CENTER
text: Small Lamp
on_click:
- homeassistant.action:
action: light.toggle
data:
entity_id: light.small_family_room_lamp
- button:
id: tv_stand_button
x: 10
y: 135
width: 145
height: 75
checkable: true
widgets:
- label:
align: CENTER
text: TV Stand
on_click:
- homeassistant.action:
action: light.toggle
data:
entity_id: light.family_room_tv_stand
- button:
x: 165
y: 135
width: 145
height: 75
widgets:
- label:
align: CENTER
text: All Off
on_click:
- homeassistant.action:
action: light.turn_off
data:
entity_id: light.living_room_lamp_1
- homeassistant.action:
action: light.turn_off
data:
entity_id: light.small_family_room_lamp
- homeassistant.action:
action: light.turn_off
data:
entity_id: light.family_room_tv_stand
-198
View File
@@ -1,198 +0,0 @@
substitutions:
device_name: led-controller-polly-a1m
friendly_name: "Polly's LED Controller"
esphome:
name: ${device_name}
friendly_name: ${friendly_name}
esp32:
board: esp32-c3-devkitm-1
framework:
type: esp-idf
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: !secret api_encryption_key
# Enable over-the-air updates
ota:
- platform: esphome
password: !secret ota_password
wifi:
ssid: !secret wifi_iot_ssid
password: !secret wifi_password
manual_ip:
static_ip: 192.168.69.181
gateway: 192.168.69.1
subnet: 255.255.255.0
# Enable fallback hotspot (captive portal) in case wifi connection fails
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: false # Set to true if you use static IPs and don't need discovery
#captive_portal:
web_server:
port: 80
# LED Light configuration
light:
- platform: esp32_rmt_led_strip
rgb_order: GRB
chipset: WS2812
pin: GPIO7
num_leds: 10
name: "${friendly_name}"
id: led_strip
# Default color on boot
restore_mode: RESTORE_DEFAULT_OFF
# Effects - you can enable these for more features!
effects:
# Basic effects
- random:
name: "Random"
transition_length: 5s
update_interval: 7s
- strobe:
name: "Strobe"
colors:
- state: true
brightness: 100%
red: 100%
green: 100%
blue: 100%
duration: 500ms
- state: false
duration: 250ms
- flicker:
name: "Flicker"
alpha: 95%
intensity: 1.5%
# Rainbow effects
- addressable_rainbow:
name: "Rainbow"
speed: 10
width: 50
- addressable_color_wipe:
name: "Color Wipe"
colors:
- red: 100%
green: 0%
blue: 0%
num_leds: 1
- red: 0%
green: 100%
blue: 0%
num_leds: 1
- red: 0%
green: 0%
blue: 100%
num_leds: 1
add_led_interval: 100ms
reverse: false
- addressable_scan:
name: "Scan"
move_interval: 100ms
scan_width: 3
- addressable_twinkle:
name: "Twinkle"
twinkle_probability: 5%
progress_interval: 4ms
- addressable_fireworks:
name: "Fireworks"
update_interval: 32ms
spark_probability: 10%
use_random_color: true
fade_out_rate: 120
# Pulse effect
- pulse:
name: "Pulse"
transition_length: 1s
update_interval: 1s
# Sensors for monitoring
sensor:
# WiFi Signal Strength
- platform: wifi_signal
name: "${friendly_name} WiFi Signal"
update_interval: 60s
# Uptime
- platform: uptime
name: "${friendly_name} Uptime"
# Diagnostic sensors
- platform: wifi_signal
name: "${device_name} WiFi Signal"
update_interval: 60s
- platform: uptime
name: "${device_name} Uptime"
update_interval: 60s
# Text sensors
text_sensor:
# ESPHome version
- platform: version
name: "${friendly_name} ESPHome Version"
# WiFi info
- platform: wifi_info
ip_address:
name: "${device_name} IP Address"
ssid:
name: "${device_name} Connected SSID"
bssid:
name: "${device_name} BSSID"
# Button to restart ESP32
button:
- platform: restart
name: "${friendly_name} Restart"
# 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();'
-128
View File
@@ -1,128 +0,0 @@
# Lights-only first version for the Living Room remote.
# Entity IDs came from the project's HA snapshot; verify them in live HA.
substitutions:
device_name: living-room-remote
friendly_name: Living Room Remote
esphome:
name: ${device_name}
friendly_name: ${friendly_name}
packages:
hardware: !include panel-remote-common.yaml
binary_sensor:
- platform: homeassistant
id: ceiling_light_state
entity_id: light.living_room_light_2
trigger_on_initial_state: true
on_state:
- lvgl.widget.update:
id: ceiling_light_button
state:
checked: !lambda return x;
- platform: homeassistant
id: small_lamp_state
entity_id: light.small_living_room_lamp
trigger_on_initial_state: true
on_state:
- lvgl.widget.update:
id: small_lamp_button
state:
checked: !lambda return x;
- platform: homeassistant
id: lampstand_state
entity_id: light.studio_bulb_1
trigger_on_initial_state: true
on_state:
- lvgl.widget.update:
id: lampstand_button
state:
checked: !lambda return x;
lvgl:
rotation: 90
on_idle:
- timeout: 45s
then:
- light.turn_on:
id: panel_backlight
brightness: 15%
pages:
- id: room_page
widgets:
- label:
x: 12
y: 8
text: Living Room
- button:
id: ceiling_light_button
x: 10
y: 45
width: 145
height: 75
checkable: true
widgets:
- label:
align: CENTER
text: Main Light
on_click:
- homeassistant.action:
action: light.toggle
data:
entity_id: light.living_room_light_2
- button:
id: small_lamp_button
x: 165
y: 45
width: 145
height: 75
checkable: true
widgets:
- label:
align: CENTER
text: Small Lamp
on_click:
- homeassistant.action:
action: light.toggle
data:
entity_id: light.small_living_room_lamp
- button:
id: lampstand_button
x: 10
y: 135
width: 145
height: 75
checkable: true
widgets:
- label:
align: CENTER
text: Lampstand
on_click:
- homeassistant.action:
action: light.toggle
data:
entity_id: light.studio_bulb_1
- button:
x: 165
y: 135
width: 145
height: 75
widgets:
- label:
align: CENTER
text: All Lights Off
on_click:
- homeassistant.action:
action: light.turn_off
data:
entity_id: light.living_room_light_2
- homeassistant.action:
action: light.turn_off
data:
entity_id: light.small_living_room_lamp
- homeassistant.action:
action: light.turn_off
data:
entity_id: light.studio_bulb_1