diff --git a/Cameras/jordyn-a1-camera.yaml b/Cameras/jordyn-a1-camera.yaml new file mode 100644 index 0000000..721b2d3 --- /dev/null +++ b/Cameras/jordyn-a1-camera.yaml @@ -0,0 +1,83 @@ +substitutions: + device_name: ljordyn-a1-camera + friendly_name: "Jordyn's A1 Camera" + +esphome: + name: ${device_name} + friendly_name: ${friendly_name} + +esp32: + board: esp32dev + framework: + type: esp-idf + #cpu_frequency: 240MHZ + +# Enable logging +logger: + level: INFO + +# Enable Home Assistant API +api: + encryption: + key: "PDB5LTKAcNWMC+MeE03/SKpqX42pcnITzmfwu761LjI=" + +ota: + - platform: esphome + password: "d207583702e4b979e28a43f6f52d19ae" + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password + + # Enable fallback hotspot (captive portal) in case wifi connection fails + ap: + ssid: "Jordyn-A1-Camera" + password: "jN4rzGokp5mt" + +captive_portal: + +i2c: + - id: camera_i2c + sda: GPIO26 + scl: GPIO27 + +psram: + mode: quad + speed: 80MHz + +esp32_camera: + external_clock: + pin: GPIO0 + frequency: 20MHz + i2c_id: camera_i2c + data_pins: [GPIO5, GPIO18, GPIO19, GPIO21, GPIO36, GPIO39, GPIO34, GPIO35] + vsync_pin: GPIO25 + href_pin: GPIO23 + pixel_clock_pin: GPIO22 + power_down_pin: GPIO32 + resolution: 800x600 + jpeg_quality: 15 + vertical_flip: False + horizontal_mirror: False + max_framerate: 20 fps + idle_framerate: 0.05 fps + + # Image settings + name: esp32-jordyn-a1-cam + brightness: 1 + #contrast: 0 + agc_gain_ceiling: 2X + agc_mode: MANUAL + agc_value: 5 + # ... + +esp32_camera_web_server: + - port: 80 + mode: STREAM + - port: 8080 + mode: SNAPSHOT + +switch: + - platform: gpio + name: "${device_name}-flash" + pin: 4 \ No newline at end of file diff --git a/Home-Assistant-Remotes/ha-remote-1.yml b/Home-Assistant-Remotes/ha-remote-1.yml index 4203836..f3ec731 100644 --- a/Home-Assistant-Remotes/ha-remote-1.yml +++ b/Home-Assistant-Remotes/ha-remote-1.yml @@ -1,11 +1,16 @@ +substitutions: + device_name: ha-family-room-remote + friendly_name: "Family Room HA Remote" + esphome: - name: ha-remote-1 - friendly_name: ha-remote-1 + name: ${device_name} + friendly_name: ${friendly_name} on_boot: priority: -10 then: - light.turn_on: ha_remote_backlight - lvgl.page.show: home + - component.update: battery_voltage - lambda: |- id(last_activity_ms) = millis(); @@ -19,21 +24,27 @@ logger: api: encryption: - key: "mn3Lv3ud5jCSOqH/QKcspUu7ShdZ0OGotm0G01p9r94=" + key: !secret api_encryption_key +# Enable over-the-air updates ota: - platform: esphome - password: "680170fb1d63d3490b2fc710fe064749" + password: !secret ota_password wifi: - ssid: !secret wifi_ssid + ssid: !secret wifi_iot_ssid password: !secret wifi_password power_save_mode: LIGHT fast_connect: true + # Enable fallback hotspot (captive portal) in case wifi connection fails + ap: + ssid: "${friendly_name} Fallback" + password: !secret fallback_password + + psram: mode: octal - speed: 80MHz i2c: sda: 8 @@ -142,6 +153,48 @@ touchscreen: - light.turn_on: ha_remote_backlight # --- LVGL UI --- +sensor: + # Waveshare routes battery sensing to EXIO_ADC (GPIO14) through a resistor divider. + # Divider on schematic is 470k/100k, so scale ADC by (470+100)/100 = 5.7. + - platform: adc + id: battery_voltage + name: "HA Remote Battery Voltage" + pin: GPIO14 + attenuation: auto + update_interval: 30s + device_class: voltage + state_class: measurement + unit_of_measurement: V + accuracy_decimals: 2 + filters: + - multiply: 5.7 + - median: + window_size: 7 + send_every: 3 + send_first_at: 1 + + - platform: copy + source_id: battery_voltage + name: "HA Remote Battery Level" + id: battery_level + device_class: battery + state_class: measurement + unit_of_measurement: "%" + accuracy_decimals: 0 + filters: + - lambda: |- + float pct = (x - 3.20f) * 100.0f / (4.20f - 3.20f); + if (pct < 0.0f) return 0.0f; + if (pct > 100.0f) return 100.0f; + return pct; + on_value: + then: + - lambda: |- + if (id(battery_label) == nullptr) return; + char txt[24]; + snprintf(txt, sizeof(txt), "Battery: %.0f%%", x); + lv_label_set_text(id(battery_label), txt); + text_sensor: - platform: wifi_info ip_address: @@ -153,25 +206,172 @@ lvgl: - main_display touchscreens: - touch_panel + disp_bg_color: 0x0A1020 + style_definitions: + - id: glass_header + bg_color: 0x1A2740 + bg_opa: 70% + border_color: 0xA7C8FF + border_width: 1 + border_opa: 35% + radius: 22 + pad_all: 0 + shadow_color: 0x061022 + shadow_width: 22 + shadow_opa: 40% + shadow_ofs_x: 0 + shadow_ofs_y: 8 + - id: glass_chip + bg_color: 0xCFE1FF + bg_opa: 28% + border_color: 0xFFFFFF + border_width: 1 + border_opa: 45% + radius: 18 + pad_all: 0 + - id: glass_tile_blue + bg_color: 0x7BB8FF + bg_opa: 30% + border_color: 0xE6F1FF + border_width: 1 + border_opa: 35% + radius: 24 + shadow_color: 0x091529 + shadow_width: 24 + shadow_opa: 35% + shadow_ofs_x: 0 + shadow_ofs_y: 8 + text_color: 0xF4F8FF + pressed: + bg_opa: 46% + border_opa: 65% + - id: glass_tile_pink + bg_color: 0xD99CFF + bg_opa: 30% + border_color: 0xF7E7FF + border_width: 1 + border_opa: 35% + radius: 24 + shadow_color: 0x1A0E2B + shadow_width: 24 + shadow_opa: 35% + shadow_ofs_x: 0 + shadow_ofs_y: 8 + text_color: 0xFFF8FF + pressed: + bg_opa: 46% + border_opa: 65% + - id: glass_tile_amber + bg_color: 0xFFD29A + bg_opa: 30% + border_color: 0xFFF0D9 + border_width: 1 + border_opa: 35% + radius: 24 + shadow_color: 0x2A1A08 + shadow_width: 24 + shadow_opa: 35% + shadow_ofs_x: 0 + shadow_ofs_y: 8 + text_color: 0xFFF9EE + pressed: + bg_opa: 46% + border_opa: 65% + - id: glass_tile_green + bg_color: 0x9BE2C6 + bg_opa: 30% + border_color: 0xE4FFF3 + border_width: 1 + border_opa: 35% + radius: 24 + shadow_color: 0x0B2018 + shadow_width: 24 + shadow_opa: 35% + shadow_ofs_x: 0 + shadow_ofs_y: 8 + text_color: 0xF3FFF9 + pressed: + bg_opa: 46% + border_opa: 65% + - id: glass_tile_red + bg_color: 0xFF9FAF + bg_opa: 34% + border_color: 0xFFE8EC + border_width: 1 + border_opa: 38% + radius: 24 + shadow_color: 0x2A0A12 + shadow_width: 24 + shadow_opa: 36% + shadow_ofs_x: 0 + shadow_ofs_y: 8 + text_color: 0xFFF5F7 + pressed: + bg_opa: 50% + border_opa: 70% + - id: glass_tile_violet + bg_color: 0xB8A8FF + bg_opa: 30% + border_color: 0xF0EAFF + border_width: 1 + border_opa: 35% + radius: 24 + shadow_color: 0x1A1230 + shadow_width: 24 + shadow_opa: 35% + shadow_ofs_x: 0 + shadow_ofs_y: 8 + text_color: 0xF7F3FF + pressed: + bg_opa: 46% + border_opa: 65% + theme: + label: + text_color: 0xEAF2FF + button: + text_color: 0xF6FAFF pages: - id: home widgets: + - obj: + x: 14 + y: 14 + width: 772 + height: 84 + styles: glass_header + widgets: + - label: + id: status_label + x: 22 + y: 14 + text: "Family Room" + - label: + x: 22 + y: 46 + text: "Quick scenes and lighting controls" + - obj: + x: 594 + y: 16 + width: 160 + height: 52 + styles: glass_chip + widgets: + - label: + id: battery_label + align: center + text: "Battery: --%" - label: - id: status_label - x: 20 - y: 10 - text: "HA Remote" - - label: - x: 20 - y: 40 - text: "Tap to wake • Idle 60s to sleep" + x: 22 + y: 108 + text: "Tap any card. Screen sleeps after 60s idle." - button: - x: 40 - y: 100 - width: 220 - height: 100 + x: 24 + y: 138 + width: 244 + height: 136 + styles: glass_tile_blue on_click: - homeassistant.service: service: light.toggle @@ -183,10 +383,11 @@ lvgl: text: "Living Room\nLights" - button: - x: 290 - y: 100 - width: 220 - height: 100 + x: 278 + y: 138 + width: 244 + height: 136 + styles: glass_tile_pink on_click: - homeassistant.service: service: light.toggle @@ -198,10 +399,11 @@ lvgl: text: "Kitchen\nLights" - button: - x: 540 - y: 100 - width: 220 - height: 100 + x: 532 + y: 138 + width: 244 + height: 136 + styles: glass_tile_red on_click: - homeassistant.service: service: script.turn_off_everything @@ -211,10 +413,11 @@ lvgl: text: "All Off" - button: - x: 40 - y: 230 - width: 220 - height: 100 + x: 24 + y: 286 + width: 244 + height: 136 + styles: glass_tile_amber on_click: - homeassistant.service: service: scene.turn_on @@ -226,10 +429,11 @@ lvgl: text: "Movie Time" - button: - x: 290 - y: 230 - width: 220 - height: 100 + x: 278 + y: 286 + width: 244 + height: 136 + styles: glass_tile_green on_click: - homeassistant.service: service: scene.turn_on @@ -241,13 +445,14 @@ lvgl: text: "Good Night" - button: - x: 540 - y: 230 - width: 220 - height: 100 + x: 532 + y: 286 + width: 244 + height: 136 + styles: glass_tile_violet on_click: - light.toggle: ha_remote_backlight widgets: - label: align: center - text: "Backlight\nToggle" \ No newline at end of file + text: "Backlight\nToggle"