# =====================================================================
#  示例 2：多页面 UI（KEY 按键翻页）
#  页面：环境 / 电池 / 系统，三页循环切换，底部小圆点指示当前页
#  硬件依赖：显示屏、SHTC3、电池 ADC、BOOT 与 KEY 两枚按键
# =====================================================================

esphome:
  name: esp32-s3-rlcd-42
  friendly_name: ESP32-S3-RLCD-4.2

esp32:
  board: esp32-s3-devkitc-1
  framework:
    type: esp-idf

psram:
  mode: octal
  speed: 80MHz

external_components:
  - source: github://kylehase/ESPHome-ST7305-RLCD
    components: [st7305_rlcd]

logger:

api:
  encryption:
    key: "7J7XVVoREEncoG39FrOxlb/ZVMRS/u7RmTc4WK2Ej7w="

ota:
  - platform: esphome
    password: "d9a7ee09077e2b8c27f2563e475e66ea"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:
    ssid: "Esp32-S3-Rlcd-42"
    password: "Wa3PMQZVj5kn"

captive_portal:

# ---------- 总线 ----------
i2c:
  - id: bus_a
    sda: GPIO13
    scl: GPIO14
    scan: true

spi:
  - id: spi_lcd
    clk_pin: GPIO11
    mosi_pin: GPIO12

# ---------- 时间（SNTP + 国内时区）----------
time:
  - platform: sntp
    id: ha_time
    timezone: Asia/Shanghai
    servers:
      - ntp.aliyun.com
      - ntp1.aliyun.com
      - pool.ntp.org

# ---------- 传感器 ----------
sensor:
  - platform: shtcx
    id: shtc3
    address: 0x70
    i2c_id: bus_a
    update_interval: 30s
    temperature:
      name: "Temperature"
      id: temp_sensor
    humidity:
      name: "Humidity"
      id: hum_sensor

  - platform: adc
    id: bat_voltage
    name: "Battery Voltage"
    pin: GPIO4
    attenuation: 12db
    update_interval: 30s
    filters:
      - multiply: 3.0

  - platform: copy
    source_id: bat_voltage
    id: bat_level
    name: "Battery Level"
    unit_of_measurement: "%"
    filters:
      - calibrate_linear:
          - 2.5 -> 0.0
          - 4.2 -> 100.0
      - clamp:
          min_value: 0
          max_value: 100

  - platform: wifi_signal
    id: wifi_rssi
    name: "WiFi Signal"
    update_interval: 30s

  - platform: uptime
    id: uptime_s
    name: "Uptime"

# 系统页用到的 IP 文本
text_sensor:
  - platform: wifi_info
    ip_address:
      id: wifi_ip
      name: "WiFi IP"

# ---------- 字体 ----------
font:
  - file: "gfonts://Roboto"
    id: font_xs
    size: 14
    glyphs: &glyphs "!\"#%()+,-_.:°0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/ "
  - file: "gfonts://Roboto"
    id: font_sm
    size: 18
    glyphs: *glyphs
  - file: "gfonts://Roboto"
    id: font_md
    size: 28
    glyphs: *glyphs
  - file: "gfonts://Roboto@700"
    id: font_lg
    size: 56
    glyphs: *glyphs

# ---------- 全局状态：当前页、反色开关 ----------
globals:
  - id: page_index
    type: int
    restore_value: false
    initial_value: "0"
  - id: inverted
    type: bool
    restore_value: true
    initial_value: "false"

# ---------- 按键 ----------
binary_sensor:
  - platform: gpio
    name: "Boot Button"
    pin:
      number: GPIO0
      inverted: true
      mode: INPUT
    on_press:
      - lambda: 'id(inverted) = !id(inverted);'
      - component.update: my_display

  - platform: gpio
    name: "Key Button"
    pin:
      number: GPIO18
      inverted: true
      mode: INPUT
    on_press:
      - lambda: 'id(page_index) = (id(page_index) + 1) % 3;'
      # 翻页时立即重读所有传感器，让屏上数据是最新的
      - component.update: shtc3
      - component.update: bat_voltage
      - component.update: wifi_rssi
      - component.update: uptime_s
      - component.update: my_display

# ---------- 显示屏 ----------
display:
  - platform: st7305_rlcd
    id: my_display
    model: WAVESHARE_400X300
    width: 400
    height: 300
    cs_pin: GPIO40
    dc_pin: GPIO5
    reset_pin: GPIO41
    data_rate: 1MHz
    update_interval: 60s
    lambda: |-
      // 根据反色开关决定前景色 / 背景填充
      auto fg = id(inverted) ? COLOR_OFF : COLOR_ON;
      if (id(inverted)) it.fill(COLOR_ON);

      // 顶栏
      it.strftime(10, 6, id(font_xs), fg, "%Y-%m-%d %H:%M", id(ha_time).now());
      it.printf(390, 6, id(font_xs), fg, TextAlign::TOP_RIGHT,
                "RSSI %.0f dBm", id(wifi_rssi).state);
      it.line(0, 28, 400, 28, fg);

      switch (id(page_index)) {
        case 0: {  // 环境
          it.print(15, 40, id(font_sm), fg, "Environment");
          it.print(15, 90, id(font_md), fg, "Temperature");
          it.printf(390, 90, id(font_lg), fg, TextAlign::TOP_RIGHT,
                    "%.1f °C", id(temp_sensor).state);
          it.print(15, 175, id(font_md), fg, "Humidity");
          it.printf(390, 175, id(font_lg), fg, TextAlign::TOP_RIGHT,
                    "%.0f %%", id(hum_sensor).state);
          break;
        }
        case 1: {  // 电池
          it.print(15, 40, id(font_sm), fg, "Battery");
          it.print(15, 90, id(font_md), fg, "Voltage");
          it.printf(390, 90, id(font_lg), fg, TextAlign::TOP_RIGHT,
                    "%.2f V", id(bat_voltage).state);
          it.print(15, 175, id(font_md), fg, "Level");
          it.printf(390, 175, id(font_lg), fg, TextAlign::TOP_RIGHT,
                    "%.0f %%", id(bat_level).state);
          break;
        }
        case 2: {  // 系统
          it.print(15, 40, id(font_sm), fg, "System");
          it.printf(15, 80,  id(font_sm), fg, "Device : esp32-s3-rlcd-42");
          it.printf(15, 105, id(font_sm), fg, "IP     : %s",
                    id(wifi_ip).state.c_str());
          it.printf(15, 130, id(font_sm), fg, "RSSI   : %.0f dBm", id(wifi_rssi).state);
          uint32_t up = millis() / 1000;
          it.printf(15, 155, id(font_sm), fg, "Uptime : %02d:%02d:%02d",
                    up / 3600, (up % 3600) / 60, up % 60);
          it.strftime(15, 180, id(font_sm), fg, "Time   : %H:%M:%S", id(ha_time).now());
          break;
        }
      }

      // 页码指示
      it.line(0, 270, 400, 270, fg);
      for (int i = 0; i < 3; i++) {
        int cx = 180 + i * 20;
        if (i == id(page_index)) it.filled_circle(cx, 287, 5, fg);
        else                     it.circle(cx, 287, 5, fg);
      }
