Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion firmware/esp32-matter/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# . ~/esp/esp-idf-v5.5.4/export.sh && . $ESP_MATTER_PATH/export.sh
# idf.py set-target esp32 && idf.py build flash monitor
cmake_minimum_required(VERSION 3.16)
set(PROJECT_VER "1.1.7")
set(PROJECT_VER "1.1.8")

# Unified versioning (issue #77): the Matter softwareVersion INT is DERIVED from PROJECT_VER --
# MAJOR*10000+MINOR*100+PATCH -> a readable, strictly-monotonic uint32. This keeps the human
Expand Down
33 changes: 33 additions & 0 deletions firmware/esp32-matter/main/app_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -971,6 +971,32 @@ class HisenseOTARequestorDriver : public chip::DeviceLayer::ExtendedOTARequestor
};
static HisenseOTARequestorDriver s_hisense_ota_driver;

/* #83 defense-in-depth: Wi-Fi connectivity-transition diagnostics. CHIP's ESP32 ConnectivityManager
* already owns Wi-Fi reconnect and auto-re-arms on a FIXED CHIP_DEVICE_CONFIG_WIFI_STATION_RECONNECT_
* INTERVAL (5 s) timer (DriveStationState), so the "re-arm after a genuine association loss" half of
* #83 is already covered. A runtime exponential backoff would be nicer, but esp-matter's ESP32
* platform DECLARES ConnectivityManagerImpl::_SetWiFiStationReconnectInterval WITHOUT defining it
* (only _Get links; the member is set once at init), so ConnectivityMgr().SetWiFiStationReconnect-
* Interval() does not link on this platform -- and patching the SDK for a marginal win is not worth
* it. Note too: the field "never reconnects until power-cycle" symptom is the brownout REBOOT loop
* (the device resets at phy_init before CHIP even runs), which no reconnect logic can fix -- only the
* bulk cap / custom PCB (#11) does. So this handler stays purely OBSERVATIONAL: it timestamps
* Lost/Established transitions on the hisense_ac log so a real Wi-Fi drop can be told apart from a
* brownout reboot when triaging a field node. Runs on the CHIP event loop (PostEventOrDie ->
* DispatchEvent) with the stack lock already held; reads the event only, touches no CHIP state. */
static void wifi_connectivity_log_handler(const chip::DeviceLayer::ChipDeviceEvent *event, intptr_t)
{
if (event->Type != chip::DeviceLayer::DeviceEventType::kWiFiConnectivityChange) return;

const auto result = event->WiFiConnectivityChange.Result;
const unsigned up_s = (unsigned) (esp_timer_get_time() / 1000000);
if (result == chip::DeviceLayer::kConnectivity_Established) {
ESP_LOGW(TAG, "Wi-Fi connectivity: ESTABLISHED (uptime %us)", up_s);
} else if (result == chip::DeviceLayer::kConnectivity_Lost) {
ESP_LOGW(TAG, "Wi-Fi connectivity: LOST (uptime %us) -- CHIP auto-reconnects on its ~5s timer", up_s);
}
}

static void https_ota_task(void *arg)
{
ESP_LOGW(TAG, "HTTPS-OTA: fetching %s", HISENSE_OTA_URL);
Expand Down Expand Up @@ -1520,6 +1546,13 @@ extern "C" void app_main()
esp_matter_ota_requestor_set_config(ota_cfg);
}

// #83 defense-in-depth: log Wi-Fi connectivity transitions. Registers an observer for CHIP's
// own connectivity-change event so a field node's Lost/Established transitions are timestamped
// (tells a real Wi-Fi drop apart from a brownout reboot). Observer only -- CHIP's DriveStation-
// State owns the actual 5s auto-reconnect (its interval setter is unimplemented on esp-matter
// ESP32, so no runtime backoff). Safe to register any time after esp_matter::start().
chip::DeviceLayer::PlatformMgr().AddEventHandler(wifi_connectivity_log_handler, 0);

// HA entity labels (UserLabel key "ha_entitylabel") -> distinguishable same-type entities.
// start() has returned (Server::Init done, endpoints exist); take the stack lock since we
// run on a different task than the Matter event loop. Read live by the UserLabel cluster.
Expand Down
12 changes: 10 additions & 2 deletions firmware/esp32-matter/sdkconfig.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ CONFIG_CUSTOM_DEVICE_INFO_PROVIDER=y
# so it (and the fallback NUMBER) MUST stay equal to PROJECT_VER or the device reports a stale
# softwareVersionString. Edit PROJECT_VER in CMakeLists.txt, then update both lines below.
# esp32-lint.sh enforces this equality (fails the commit/CI if they drift).
CONFIG_DEVICE_SOFTWARE_VERSION_NUMBER=10107
CONFIG_DEVICE_SOFTWARE_VERSION_STRING="1.1.7"
CONFIG_DEVICE_SOFTWARE_VERSION_NUMBER=10108
CONFIG_DEVICE_SOFTWARE_VERSION_STRING="1.1.8"
# --- OTA hardening (faster + reliable on marginal Wi-Fi) ---
# Delta OTA: ship a diff (tens of KB) instead of the full ~1.5MB image over BDX.
CONFIG_ENABLE_DELTA_OTA=y
Expand Down Expand Up @@ -75,6 +75,14 @@ CONFIG_ESP_BROWNOUT_DET=y
CONFIG_ESP_BROWNOUT_DET_LVL_SEL_0=y
CONFIG_ESP_BROWNOUT_DET_LVL=0

# Reduce Wi-Fi TX power on the boot that FOLLOWS a brownout reset (#83). IDF-native, no code:
# esp_phy_reduce_tx_power() forces the lowest PHY TX power before register_chipv7_phy on the boot
# immediately after esp_reset_reason()==ESP_RST_BROWNOUT, trimming a little current on the retry
# boot so a marginal rail is likelier to clear re-association. HONEST SCOPE: this is a POST-brownout
# backoff, NOT a cut to the initial phy_init calibration PEAK that trips the reset (esp-idf#1308) --
# only the bulk cap / custom PCB (#11) fixes the peak. Belt-and-suspenders, not a hardware substitute.
CONFIG_ESP_PHY_REDUCE_TX_POWER=y

# Task watchdog PANIC (#12): turn a hung task into a reboot (which re-runs the Wi-Fi/Matter/RS-485
# bring-up) instead of a warning + a wedged node (Matter + A/C both dark) until a power cycle --
# exactly the "recover without a reflash" case #12 is about. The RS-485 bus task explicitly
Expand Down