Document Core2 BLE proxy power and UI logic
This commit is contained in:
@@ -29,6 +29,9 @@ esphome:
|
||||
on_boot:
|
||||
priority: 850
|
||||
then:
|
||||
# The Core2 LCD/backlight rails are controlled by the AXP192 PMIC. ESPHome's
|
||||
# stock M5CORE2 display setup does not initialize those rails here, so the
|
||||
# custom header performs the M5Stack-specific power sequencing once I2C exists.
|
||||
- lambda: |-
|
||||
owon_b35t::core2_axp192_init(id(core2_i2c));
|
||||
project:
|
||||
@@ -77,10 +80,14 @@ wifi:
|
||||
captive_portal:
|
||||
|
||||
globals:
|
||||
# 0 = OWON meter page, 1 = Atorch DL24 page. This is intentionally volatile so
|
||||
# every boot starts with the multimeter view until one device connects.
|
||||
- id: display_page
|
||||
type: int
|
||||
initial_value: "0"
|
||||
restore_value: no
|
||||
# The Atorch external component does not expose a simple connected flag that the
|
||||
# display lambda can query, so BLE callbacks maintain this state explicitly.
|
||||
- id: atorch_connected
|
||||
type: bool
|
||||
initial_value: "false"
|
||||
@@ -100,15 +107,19 @@ script:
|
||||
- delay: 2min
|
||||
- if:
|
||||
condition:
|
||||
# Only dim when both BLE devices are disconnected; active lab instruments
|
||||
# keep the display fully lit so readings remain visible at a glance.
|
||||
lambda: |-
|
||||
return !owon_meter.connected && !id(atorch_connected);
|
||||
then:
|
||||
- light.turn_on:
|
||||
id: backlight
|
||||
brightness: 50%
|
||||
brightness: 70%
|
||||
- delay: 3min
|
||||
- if:
|
||||
condition:
|
||||
# Re-check before turning the backlight off, because a connection may
|
||||
# have been established during the preceding delay.
|
||||
lambda: |-
|
||||
return !owon_meter.connected && !id(atorch_connected);
|
||||
then:
|
||||
@@ -117,6 +128,8 @@ script:
|
||||
interval:
|
||||
- interval: 10s
|
||||
then:
|
||||
# Periodic memory telemetry is useful on the Core2 because BLE, PSRAM, the
|
||||
# MIPI framebuffer, and external components can fragment different heap pools.
|
||||
- lambda: |-
|
||||
ESP_LOGI("mem", "heap free=%u min_free=%u internal_free=%u internal_largest=%u dma_free=%u dma_largest=%u psram_free=%u psram_largest=%u",
|
||||
static_cast<unsigned>(esp_get_free_heap_size()),
|
||||
@@ -139,12 +152,16 @@ ble_client:
|
||||
on_connect:
|
||||
then:
|
||||
- script.execute: wake_backlight
|
||||
# Notify the custom parser/display object and switch to the meter page when
|
||||
# the OWON connects, so the on-device screen follows the active instrument.
|
||||
- lambda: |-
|
||||
owon_meter.on_connect();
|
||||
id(display_page) = 0;
|
||||
id(lcd).update();
|
||||
on_disconnect:
|
||||
then:
|
||||
# Keep the UI useful after a disconnect: if the Atorch is still online,
|
||||
# automatically fall back from the OWON page to the Atorch page.
|
||||
- lambda: |-
|
||||
owon_meter.on_disconnect();
|
||||
if (id(display_page) == 0 && id(atorch_connected)) {
|
||||
@@ -153,6 +170,8 @@ ble_client:
|
||||
id(lcd).update();
|
||||
- if:
|
||||
condition:
|
||||
# Start the idle timer only after both BLE clients are gone; otherwise
|
||||
# the remaining connected instrument still deserves an active display.
|
||||
lambda: |-
|
||||
return !owon_meter.connected && !id(atorch_connected);
|
||||
then:
|
||||
@@ -163,12 +182,16 @@ ble_client:
|
||||
on_connect:
|
||||
then:
|
||||
- script.execute: wake_backlight
|
||||
# The Atorch component handles measurements, while this explicit flag/page
|
||||
# switch keeps the shared display state synchronized with the BLE client.
|
||||
- lambda: |-
|
||||
id(atorch_connected) = true;
|
||||
id(display_page) = 1;
|
||||
id(lcd).update();
|
||||
on_disconnect:
|
||||
then:
|
||||
# If the load disconnects while the meter is still connected, move the
|
||||
# physical display back to the meter instead of leaving a stale load page.
|
||||
- lambda: |-
|
||||
id(atorch_connected) = false;
|
||||
if (id(display_page) == 1 && owon_meter.connected) {
|
||||
@@ -177,6 +200,8 @@ ble_client:
|
||||
id(lcd).update();
|
||||
- if:
|
||||
condition:
|
||||
# Same idle rule as OWON disconnect: only dim/off when neither BLE
|
||||
# target is connected anymore.
|
||||
lambda: |-
|
||||
return !owon_meter.connected && !id(atorch_connected);
|
||||
then:
|
||||
@@ -203,6 +228,8 @@ output:
|
||||
type: float
|
||||
id: lcd_backlight
|
||||
write_action:
|
||||
# Bridge ESPHome's generic monochromatic light level to the Core2-specific
|
||||
# AXP192 backlight voltage helper implemented in lab-ble-proxy.h.
|
||||
- lambda: |-
|
||||
owon_b35t::core2_axp192_set_backlight(state);
|
||||
|
||||
@@ -217,6 +244,8 @@ font:
|
||||
- file: "fonts/Roboto-Regular.ttf"
|
||||
id: meter_font
|
||||
size: 15
|
||||
# Glyphs are whitelisted to save flash/RAM; include symbols used by units,
|
||||
# status labels, soft-button names, and Atorch metric text.
|
||||
glyphs:
|
||||
[
|
||||
" ",
|
||||
@@ -293,6 +322,7 @@ font:
|
||||
- file: "fonts/Roboto-Medium.ttf"
|
||||
id: atorch_value_font
|
||||
size: 22
|
||||
# Larger Atorch value font only needs numeric characters and measurement units.
|
||||
glyphs:
|
||||
[
|
||||
" ",
|
||||
@@ -322,6 +352,8 @@ display:
|
||||
id: lcd
|
||||
model: M5CORE2
|
||||
update_interval: 500ms
|
||||
# Rendering is delegated to the custom C++ helper because ESPHome display YAML
|
||||
# primitives would be unwieldy for the OWON seven-segment clone and Atorch dashboard.
|
||||
lambda: |-
|
||||
owon_meter.render(
|
||||
it,
|
||||
@@ -346,6 +378,8 @@ touchscreen:
|
||||
- script.execute: wake_backlight
|
||||
- if:
|
||||
condition:
|
||||
# Touching an idle/disconnected unit wakes the display briefly, then
|
||||
# restarts the idle timer if no BLE target is available.
|
||||
lambda: |-
|
||||
return !owon_meter.connected && !id(atorch_connected);
|
||||
then:
|
||||
@@ -361,6 +395,7 @@ binary_sensor:
|
||||
y_max: 195
|
||||
on_press:
|
||||
then:
|
||||
# The large middle touch zone toggles between the two custom render pages.
|
||||
- lambda: |-
|
||||
id(display_page) = 1 - id(display_page);
|
||||
id(lcd).update();
|
||||
@@ -374,6 +409,7 @@ binary_sensor:
|
||||
internal: true
|
||||
on_press:
|
||||
then:
|
||||
# Left soft button changes which OWON remote command the center button will send.
|
||||
- lambda: |-
|
||||
owon_meter.previous_button();
|
||||
- platform: touchscreen
|
||||
@@ -396,6 +432,8 @@ binary_sensor:
|
||||
id: owon_ble_client
|
||||
service_uuid: "0000fff0-0000-1000-8000-00805f9b34fb"
|
||||
characteristic_uuid: "0000fff3-0000-1000-8000-00805f9b34fb"
|
||||
# OWON remote-control payload: first byte selects the meter button,
|
||||
# second byte selects the normal/short-press action variant.
|
||||
value: !lambda |-
|
||||
std::vector<uint8_t> data = {owon_meter.selected_button, 0x01};
|
||||
return data;
|
||||
@@ -410,6 +448,8 @@ binary_sensor:
|
||||
id: owon_ble_client
|
||||
service_uuid: "0000fff0-0000-1000-8000-00805f9b34fb"
|
||||
characteristic_uuid: "0000fff3-0000-1000-8000-00805f9b34fb"
|
||||
# Long-press encoding is not uniform: SELECT and HZ/DUTY still use
|
||||
# 0x01, while RANGE/HOLD/REL/MAX-MIN use 0x00 for their alternate action.
|
||||
value: !lambda |-
|
||||
uint8_t press_type = (owon_meter.selected_button == 1 || owon_meter.selected_button == 5) ? 0x01 : 0x00;
|
||||
std::vector<uint8_t> data = {owon_meter.selected_button, press_type};
|
||||
@@ -424,12 +464,14 @@ binary_sensor:
|
||||
internal: true
|
||||
on_press:
|
||||
then:
|
||||
# Right soft button advances to the next OWON command label.
|
||||
- lambda: |-
|
||||
owon_meter.next_button();
|
||||
|
||||
- platform: template
|
||||
name: "${friendly_name} OWON Connected"
|
||||
icon: "mdi:bluetooth-connect"
|
||||
# Template binary sensors expose state maintained by the custom OWON parser object.
|
||||
lambda: |-
|
||||
return owon_meter.connected;
|
||||
- platform: template
|
||||
@@ -450,6 +492,8 @@ binary_sensor:
|
||||
return id(atorch_connected);
|
||||
|
||||
sensor:
|
||||
# This hidden characteristic sensor is the bridge from OWON BLE notifications into
|
||||
# custom C++ parsing. The returned float becomes the source numeric meter reading.
|
||||
- platform: ble_client
|
||||
type: characteristic
|
||||
ble_client_id: owon_ble_client
|
||||
@@ -488,6 +532,8 @@ sensor:
|
||||
name: "${friendly_name} Atorch Dim Backlight"
|
||||
id: atorch_dim_backlight
|
||||
|
||||
# The DL24 component exposes power, but this config computes Wh locally so the
|
||||
# accumulated energy can be restored and reset alongside Atorch's own counters.
|
||||
- platform: integration
|
||||
name: "${friendly_name} Atorch Energy"
|
||||
id: atorch_energy_calculated
|
||||
@@ -506,18 +552,21 @@ text_sensor:
|
||||
name: "${friendly_name} OWON Reading"
|
||||
update_interval: 1s
|
||||
icon: "mdi:gauge"
|
||||
# Human-readable mirror of the meter LCD, including waiting/disconnected/OL states.
|
||||
lambda: |-
|
||||
return owon_meter.reading_text();
|
||||
- platform: template
|
||||
name: "${friendly_name} OWON Unit"
|
||||
update_interval: 1s
|
||||
icon: "mdi:ruler"
|
||||
# Combines SI prefix and unit into one HA text entity, e.g. mV, kΩ, µA, %.
|
||||
lambda: |-
|
||||
return std::string(owon_meter.scale()) + owon_meter.unit();
|
||||
- platform: template
|
||||
name: "${friendly_name} OWON Mode"
|
||||
icon: "mdi:knob"
|
||||
update_interval: 1s
|
||||
# Exposes decoded annunciators such as AC/DC, AUTO, HOLD, REL, MIN/MAX.
|
||||
lambda: |-
|
||||
return owon_meter.mode_text();
|
||||
|
||||
@@ -535,6 +584,7 @@ button:
|
||||
reset_all:
|
||||
name: "${friendly_name} Atorch Reset All"
|
||||
on_press:
|
||||
# Keep the locally integrated Wh counter in sync with the DL24 reset-all command.
|
||||
- sensor.integration.reset: atorch_energy_calculated
|
||||
usb_plus:
|
||||
name: "${friendly_name} Atorch Plus"
|
||||
@@ -544,6 +594,8 @@ button:
|
||||
name: "${friendly_name} Atorch Setup"
|
||||
enter:
|
||||
name: "${friendly_name} Atorch Enter"
|
||||
# Home Assistant button entities for direct OWON remote commands. The payloads
|
||||
# are the same two-byte command format used by the touchscreen soft buttons.
|
||||
- platform: template
|
||||
name: "OWON SELECT"
|
||||
id: owon_btn_select
|
||||
@@ -552,6 +604,7 @@ button:
|
||||
id: owon_ble_client
|
||||
service_uuid: "0000fff0-0000-1000-8000-00805f9b34fb"
|
||||
characteristic_uuid: "0000fff3-0000-1000-8000-00805f9b34fb"
|
||||
# SELECT normal press.
|
||||
value: !lambda "return std::vector<uint8_t>({1, 0x01});"
|
||||
|
||||
- platform: template
|
||||
@@ -562,6 +615,7 @@ button:
|
||||
id: owon_ble_client
|
||||
service_uuid: "0000fff0-0000-1000-8000-00805f9b34fb"
|
||||
characteristic_uuid: "0000fff3-0000-1000-8000-00805f9b34fb"
|
||||
# RANGE normal press.
|
||||
value: !lambda "return std::vector<uint8_t>({2, 0x01});"
|
||||
|
||||
- platform: template
|
||||
@@ -572,6 +626,7 @@ button:
|
||||
id: owon_ble_client
|
||||
service_uuid: "0000fff0-0000-1000-8000-00805f9b34fb"
|
||||
characteristic_uuid: "0000fff3-0000-1000-8000-00805f9b34fb"
|
||||
# HOLD is the short/normal action on the shared HLD/LIG physical key.
|
||||
value: !lambda "return std::vector<uint8_t>({3, 0x01});"
|
||||
|
||||
- platform: template
|
||||
@@ -582,6 +637,7 @@ button:
|
||||
id: owon_ble_client
|
||||
service_uuid: "0000fff0-0000-1000-8000-00805f9b34fb"
|
||||
characteristic_uuid: "0000fff3-0000-1000-8000-00805f9b34fb"
|
||||
# LIGHT is the alternate/long action on the same HLD/LIG key.
|
||||
value: !lambda "return std::vector<uint8_t>({3, 0x00});"
|
||||
|
||||
- platform: template
|
||||
@@ -592,6 +648,7 @@ button:
|
||||
id: owon_ble_client
|
||||
service_uuid: "0000fff0-0000-1000-8000-00805f9b34fb"
|
||||
characteristic_uuid: "0000fff3-0000-1000-8000-00805f9b34fb"
|
||||
# RELATIVE is the short/normal action on the shared REL/BT key.
|
||||
value: !lambda "return std::vector<uint8_t>({4, 0x01});"
|
||||
|
||||
- platform: template
|
||||
@@ -602,6 +659,7 @@ button:
|
||||
id: owon_ble_client
|
||||
service_uuid: "0000fff0-0000-1000-8000-00805f9b34fb"
|
||||
characteristic_uuid: "0000fff3-0000-1000-8000-00805f9b34fb"
|
||||
# BT is the alternate/long action on the same REL/BT key.
|
||||
value: !lambda "return std::vector<uint8_t>({4, 0x00});"
|
||||
|
||||
- platform: template
|
||||
@@ -612,6 +670,7 @@ button:
|
||||
id: owon_ble_client
|
||||
service_uuid: "0000fff0-0000-1000-8000-00805f9b34fb"
|
||||
characteristic_uuid: "0000fff3-0000-1000-8000-00805f9b34fb"
|
||||
# HZ/DUTY command uses the normal action variant.
|
||||
value: !lambda "return std::vector<uint8_t>({5, 0x01});"
|
||||
|
||||
- platform: template
|
||||
@@ -622,4 +681,5 @@ button:
|
||||
id: owon_ble_client
|
||||
service_uuid: "0000fff0-0000-1000-8000-00805f9b34fb"
|
||||
characteristic_uuid: "0000fff3-0000-1000-8000-00805f9b34fb"
|
||||
# MAX/MIN command uses the normal action variant.
|
||||
value: !lambda "return std::vector<uint8_t>({6, 0x01});"
|
||||
|
||||
Reference in New Issue
Block a user