substitutions: device_name: everblu-meter friendly_name: EverBlu Meter cc1101_cs: "GPIO15" # ESP8266 Huzzah: GPIO15 (safe — onboard pull-down). For ESP32 use GPIO25. cc1101_gdo0: "GPIO5" # ESP8266: GPIO5 (D1). For ESP32 use GPIO4. cc1101_gdo2: "GPIO4" # REQUIRED (v3.0.0+): free GPIO -> CC1101 GDO2 (hardware FIFO threshold) # ESP8266: GPIO4 (D2). For ESP32 use GPIO27. tz_offset_min: "0" meter_1_prefix: "Meter 1" meter_2_prefix: "Meter 2" esphome: name: ${device_name} friendly_name: ${friendly_name} # Sub-devices: each meter appears as its own device in Home Assistant. # Entities below reference these via `device_id:`. Shared-radio entities # (CC1101 state/connected, firmware, frequency calibration) are left without # a device_id so they stay on the main ${friendly_name} node. devices: - id: water_meter_device_1 name: "${meter_1_prefix}" - id: water_meter_device_2 name: "${meter_2_prefix}" # Choose your board configuration below (uncomment one): # ========== ESP8266 (Adafruit HUZZAH) ========== esp8266: board: huzzah framework: version: recommended # ========== ESP32 (uncomment to use instead of ESP8266) ========== # esp32: # board: esp32dev # framework: # type: arduino # Required since ESPHome 2026.1.0 (everblu_meter needs Arduino.h) logger: level: DEBUG logs: everblu_meter: DEBUG sensor: WARN api: encryption: key: "CHANGE_ME" ota: - platform: esphome password: "CHANGE_ME" wifi: ssid: !secret wifi_ssid password: !secret wifi_password external_components: - source: type: git url: https://github.com/genestealer/everblu-meters-esp8266-improved ref: main path: ESPHOME-release components: [everblu_meter] refresh: 1d time: - platform: homeassistant id: homeassistant_time # SPI bus shared with the CC1101 radio # Pins below are for ESP8266. For ESP32, use: clk_pin GPIO18, mosi_pin GPIO23, miso_pin GPIO19 spi: - id: main_bus clk_pin: GPIO14 mosi_pin: GPIO13 miso_pin: GPIO12 everblu_meter: - id: water_meter_1 meter_code: "20-0257750-000" # year=20, serial=257750 (dashed form, suffix 000 ignored) meter_type: water debug_cc1101: true spi_id: main_bus cs_pin: number: ${cc1101_cs} allow_other_uses: true gdo0_pin: number: ${cc1101_gdo0} allow_other_uses: true gdo2_pin: # REQUIRED (v3.0.0+): hardware FIFO threshold (TX+RX, prevents TXFIFO_UNDERFLOW) number: ${cc1101_gdo2} # free GPIO (not SPI: avoid GPIO12/MISO, GPIO13/MOSI, GPIO14/SCK) and not gdo0_pin allow_other_uses: true # Required - both meter entries share the same CC1101 # rx_attenuation: 0 # Optional: LNA gain limit (0/6/12/18 dB). Both meters share the # CC1101 hardware, so set the same value on all entries. # Only needed when *** NEAR-FIELD SATURATION DETECTED *** is logged. time_id: homeassistant_time timezone_offset: ${tz_offset_min} read_hour: 11 read_minute: 30 request_reading_button: name: "${meter_1_prefix} Read Meter Now" device_id: water_meter_device_1 # Frequency calibration is a property of the shared CC1101 radio, not the # meter. Declare these buttons/sensors on METER 1 ONLY - there is one base # frequency, one offset and one tuned frequency for the whole device. # # Every entry must use the SAME `frequency:` value (all entries here use the # default). FrequencyManager::begin() is called per entry and overwrites a # single global, so only the LAST entry's value takes effect and any others # are silently ignored. # # A scan has two properties that can disagree: # - which METER answers: the entry that triggered the scan. For this button # that is meter 1; for the automatic auto_scan_on_failure scan it is # whichever meter just exhausted its own retries. # - which FREQUENCIES are swept: always centred on the single global base # frequency, never on the triggering entry's `frequency:`. # Both are logged at scan start, e.g. # Starting frequency scan using meter 20-0257750 (water)... # Scan centred on 433.820007 MHz (this meter is configured for 433.820007 MHz) # # For genuinely independent calibration, use one CC1101 (and one ESP) per meter. deep_scan_button: name: "Radio Deep Frequency Scan" reset_frequency_button: name: "Radio Reset Frequency Offset" stop_reading_button: name: "${meter_1_prefix} Stop Reading" device_id: water_meter_device_1 volume: name: "${meter_1_prefix} Water Volume" device_id: water_meter_device_1 counter: name: "${meter_1_prefix} Read Counter" device_id: water_meter_device_1 battery: name: "${meter_1_prefix} Meter Battery" device_id: water_meter_device_1 rssi: name: "${meter_1_prefix} Meter RSSI" device_id: water_meter_device_1 rssi_percentage: name: "${meter_1_prefix} RSSI Percentage" device_id: water_meter_device_1 lqi: name: "${meter_1_prefix} LQI" device_id: water_meter_device_1 lqi_percentage: name: "${meter_1_prefix} LQI Percentage" device_id: water_meter_device_1 total_attempts: name: "${meter_1_prefix} Total Read Attempts" device_id: water_meter_device_1 successful_reads: name: "${meter_1_prefix} Successful Reads" device_id: water_meter_device_1 failed_reads: name: "${meter_1_prefix} Failed Reads" device_id: water_meter_device_1 # Global (per-radio) calibration sensors - declared on this meter only. frequency_offset: name: "Radio Frequency Offset" tuned_frequency: name: "Radio Tuned Frequency (MHz)" frequency_estimate: name: "Radio Frequency Estimate" meter_serial_sensor: name: "${meter_1_prefix} Meter Serial" device_id: water_meter_device_1 meter_year_sensor: name: "${meter_1_prefix} Meter Year" device_id: water_meter_device_1 meter_clock_sensor: name: "${meter_1_prefix} Meter Clock" device_id: water_meter_device_1 meter_model_sensor: name: "${meter_1_prefix} Meter Type" device_id: water_meter_device_1 reading_schedule_sensor: name: "${meter_1_prefix} Reading Schedule" device_id: water_meter_device_1 reading_time_utc_sensor: name: "${meter_1_prefix} Reading Time (UTC)" device_id: water_meter_device_1 time_start: name: "${meter_1_prefix} Reading Start Time" device_id: water_meter_device_1 time_end: name: "${meter_1_prefix} Reading End Time" device_id: water_meter_device_1 status: name: "${meter_1_prefix} Meter Status" device_id: water_meter_device_1 error: name: "${meter_1_prefix} Last Error" device_id: water_meter_device_1 radio_state: name: "CC1101 State" # device-level (shared radio) - stays on main node timestamp: name: "${meter_1_prefix} Last Reading Time" device_id: water_meter_device_1 history_json: name: "${meter_1_prefix} Meter History (JSON)" device_id: water_meter_device_1 firmware_version: name: "Firmware Version" # device-level (one firmware) - stays on main node active_reading: name: "${meter_1_prefix} Reading Active" device_id: water_meter_device_1 radio_connected: name: "CC1101 Connected" # device-level (shared radio) - stays on main node - id: water_meter_2 meter_code: "20-0257751-000" # year=20, serial=257751 (dashed form, suffix 000 ignored) meter_type: water debug_cc1101: true spi_id: main_bus cs_pin: number: ${cc1101_cs} allow_other_uses: true gdo0_pin: number: ${cc1101_gdo0} allow_other_uses: true gdo2_pin: # REQUIRED (v3.0.0+): hardware FIFO threshold (TX+RX, prevents TXFIFO_UNDERFLOW) number: ${cc1101_gdo2} # free GPIO (not SPI: avoid GPIO12/MISO, GPIO13/MOSI, GPIO14/SCK) and not gdo0_pin allow_other_uses: true # Required - both meter entries share the same CC1101 # rx_attenuation: 0 # Must match the value set on water_meter_1 (shared CC1101 hardware) time_id: homeassistant_time timezone_offset: ${tz_offset_min} read_hour: 11 read_minute: 40 request_reading_button: name: "${meter_2_prefix} Read Meter Now" device_id: water_meter_device_2 stop_reading_button: name: "${meter_2_prefix} Stop Reading" device_id: water_meter_device_2 # No frequency calibration entities here. deep_scan_button, # reset_frequency_button and the offset/tuned-frequency sensors are # radio-global and are declared on meter 1 only (see water_meter_1 above). # # Do NOT set `frequency:` here to a different value from water_meter_1 - # there is a single global base frequency and the last entry to initialise # silently wins. volume: name: "${meter_2_prefix} Water Volume" device_id: water_meter_device_2 counter: name: "${meter_2_prefix} Read Counter" device_id: water_meter_device_2 battery: name: "${meter_2_prefix} Meter Battery" device_id: water_meter_device_2 rssi: name: "${meter_2_prefix} Meter RSSI" device_id: water_meter_device_2 rssi_percentage: name: "${meter_2_prefix} RSSI Percentage" device_id: water_meter_device_2 lqi: name: "${meter_2_prefix} LQI" device_id: water_meter_device_2 lqi_percentage: name: "${meter_2_prefix} LQI Percentage" device_id: water_meter_device_2 total_attempts: name: "${meter_2_prefix} Total Read Attempts" device_id: water_meter_device_2 successful_reads: name: "${meter_2_prefix} Successful Reads" device_id: water_meter_device_2 failed_reads: name: "${meter_2_prefix} Failed Reads" device_id: water_meter_device_2 meter_serial_sensor: name: "${meter_2_prefix} Meter Serial" device_id: water_meter_device_2 meter_year_sensor: name: "${meter_2_prefix} Meter Year" device_id: water_meter_device_2 meter_clock_sensor: name: "${meter_2_prefix} Meter Clock" device_id: water_meter_device_2 meter_model_sensor: name: "${meter_2_prefix} Meter Type" device_id: water_meter_device_2 reading_schedule_sensor: name: "${meter_2_prefix} Reading Schedule" device_id: water_meter_device_2 reading_time_utc_sensor: name: "${meter_2_prefix} Reading Time (UTC)" device_id: water_meter_device_2 time_start: name: "${meter_2_prefix} Reading Start Time" device_id: water_meter_device_2 time_end: name: "${meter_2_prefix} Reading End Time" device_id: water_meter_device_2 status: name: "${meter_2_prefix} Meter Status" device_id: water_meter_device_2 error: name: "${meter_2_prefix} Last Error" device_id: water_meter_device_2 timestamp: name: "${meter_2_prefix} Last Reading Time" device_id: water_meter_device_2 history_json: name: "${meter_2_prefix} Meter History (JSON)" device_id: water_meter_device_2 active_reading: name: "${meter_2_prefix} Reading Active" device_id: water_meter_device_2 # CC1101 State, CC1101 Connected and Firmware Version are device-level (one # shared radio / firmware) and are declared on the first meter only above.