Skip to content

[lightning-ln882h] Add static IP support#375

Open
Bl00d-B0b wants to merge 1 commit into
libretiny-eu:masterfrom
Bl00d-B0b:ln882h-static-ip-fix
Open

[lightning-ln882h] Add static IP support#375
Bl00d-B0b wants to merge 1 commit into
libretiny-eu:masterfrom
Bl00d-B0b:ln882h-static-ip-fix

Conversation

@Bl00d-B0b

@Bl00d-B0b Bl00d-B0b commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

Adds static IP support for LN882H. The LN882H SDK always starts DHCP internally in \wifi_sta_connect()\ with no option to disable it, so static IP is not supported at the SDK level. This PR implements static IP by stopping DHCP and applying the configured address after each connect, reconnect and roam event.

Changes

  1. Apply static IP after connect — stop DHCP and apply static IP in \wifiEventStaConnected()\ before the SDK hands over to the application. \wifi_sta_connect()\ always starts DHCP internally with no way to disable it.

  2. *Fix forward declaration of \wifiEventIpReceived* — required for the above.

  3. Ensure static IP survives reconnect and roam — two additional cases:

    • Wrong order:
      etif_set_addr()\ was called before
      etifapi_dhcp_release_and_stop(). When DHCP is already BOUND, this triggers the netif status callback with \dhcp_supplied_address==true\ before DHCP is stopped. Fixed: stop DHCP first.
    • Missing fallback: \wifiEventIpReceived()\ is called from inside \dhcp_recv()\ in the LwIP tcpip_thread. If DHCP completes despite the early stop (roaming, SDK-internal reconnect), the lease stays active. Cannot call
      etifapi_dhcp_release_and_stop()\ (deadlock) or \dhcp_release_and_stop()\ directly (use-after-free). Fixed: schedule \wifiApplyStaticIpCallback\ via \ cpip_callback()\ to run after \dhcp_recv()\ returns.

Tested on

LN882H-based 2-gang light switch (DS-101JL) running ESPHome — static IP stable across power cycles, reconnects and roaming for several months.

Bl00d-B0b added a commit to Bl00d-B0b/libretiny that referenced this pull request Apr 2, 2026
…y-eu#375)

wifi_sta_connect() always starts DHCP internally; there is no way to
pass a dhcp_mode parameter to it like BK72XX's bk_wlan_start_sta_adv_fix.

Apply static IP and stop DHCP in wifiEventStaConnected(), immediately
after the L2 association event fires, before the SDK-initiated DHCP
exchange completes. Emit GOT_IP manually since the netdev callback
won't fire when DHCP is stopped.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Bl00d-B0b Bl00d-B0b force-pushed the ln882h-static-ip-fix branch from 648ae3b to ea5142d Compare April 2, 2026 19:15
Bl00d-B0b added a commit to Bl00d-B0b/libretiny that referenced this pull request Apr 2, 2026
Bl00d-B0b added a commit to Bl00d-B0b/libretiny that referenced this pull request Apr 2, 2026
…am (libretiny-eu#375)

Two bugs in the previous static-IP fix (e2d501b + f49e18f):

1. Wrong order in wifiEventStaConnected(): netif_set_addr() was called
   before netifapi_dhcp_release_and_stop(). When DHCP is already BOUND
   at the time the connected event fires, netif_set_addr() triggers the
   LwIP netif status callback with dhcp_supplied_address==true, emitting
   a spurious GOT_IP before DHCP was stopped.
   Fix: stop DHCP first, then set the address.

2. Missing fallback in wifiEventIpReceived(): this callback is invoked by
   the SDK's sta_netif_status_changed_cb() from inside dhcp_recv() in the
   LwIP tcpip_thread. If DHCP completes before or after the connected
   event (e.g. roaming, SDK-internal reconnect), the DHCP lease stays
   active and the client sends periodic renewal requests.
   Cannot call netifapi_dhcp_release_and_stop() here (deadlock: we ARE
   the tcpip_thread waiting on itself) and cannot call dhcp_release_and_stop()
   directly (use-after-free: dhcp_recv() hasn't returned yet).
   Fix: schedule wifiApplyStaticIpCallback via tcpip_callback(). It runs
   after dhcp_recv() unwinds, where it is safe to stop DHCP, apply the
   static address, and emit GOT_IP.
@Bl00d-B0b Bl00d-B0b force-pushed the ln882h-static-ip-fix branch 2 times, most recently from 5760e15 to 6686568 Compare April 2, 2026 19:54
Bl00d-B0b pushed a commit to Bl00d-B0b/libretiny that referenced this pull request Apr 5, 2026
…ct (libretiny-eu#375)

When the reconnect/roam fallback path fires (wifiApplyStaticIpCallback),
LwIP's dhcp_recv() has already updated the DNS table via DHCP option 6
before we could stop DHCP. Restore info.dns1/dns2 after netif_set_addr()
to ensure the user-configured DNS servers survive reconnects.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Bl00d-B0b

Bl00d-B0b commented Apr 5, 2026

Copy link
Copy Markdown
Contributor Author

Added one more fix: on the reconnect/roam fallback path (wifiApplyStaticIpCallback), LwIP's dhcp_recv() processes DHCP option 6 and overwrites the DNS table before we get to stop DHCP. The static IP and gateway were already being restored, but DNS was not. Added DNS restoration (dns_setserver) after netif_set_addr() using the stored info.dns1/info.dns2 values.

Currently testing on a DS-101JL / BSEED WiFi Touch Light Switch 2 Gang with an LN-CB3S V1.0 module (WL2H-U-2 / LN882H).

Bl00d-B0b pushed a commit to Bl00d-B0b/libretiny that referenced this pull request Apr 7, 2026
…ct (libretiny-eu#375)

When the reconnect/roam fallback path fires (wifiApplyStaticIpCallback),
LwIP's dhcp_recv() has already updated the DNS table via DHCP option 6
before we could stop DHCP. Restore info.dns1/dns2 after netif_set_addr()
to ensure the user-configured DNS servers survive reconnects.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Bl00d-B0b Bl00d-B0b force-pushed the ln882h-static-ip-fix branch from 3e876e5 to fc8c881 Compare April 7, 2026 05:34
Bl00d-B0b added a commit to Bl00d-B0b/libretiny that referenced this pull request May 21, 2026
…y-eu#375)

wifi_sta_connect() always starts DHCP internally; there is no way to
pass a dhcp_mode parameter to it like BK72XX's bk_wlan_start_sta_adv_fix.

Apply static IP and stop DHCP in wifiEventStaConnected(), immediately
after the L2 association event fires, before the SDK-initiated DHCP
exchange completes. Emit GOT_IP manually since the netdev callback
won't fire when DHCP is stopped.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bl00d-B0b added a commit to Bl00d-B0b/libretiny that referenced this pull request May 21, 2026
@Bl00d-B0b Bl00d-B0b force-pushed the ln882h-static-ip-fix branch from fc8c881 to 6bf1b38 Compare May 21, 2026 03:46
Bl00d-B0b added a commit to Bl00d-B0b/libretiny that referenced this pull request May 21, 2026
…am (libretiny-eu#375)

Two bugs in the previous static-IP fix (e2d501b + f49e18f):

1. Wrong order in wifiEventStaConnected(): netif_set_addr() was called
   before netifapi_dhcp_release_and_stop(). When DHCP is already BOUND
   at the time the connected event fires, netif_set_addr() triggers the
   LwIP netif status callback with dhcp_supplied_address==true, emitting
   a spurious GOT_IP before DHCP was stopped.
   Fix: stop DHCP first, then set the address.

2. Missing fallback in wifiEventIpReceived(): this callback is invoked by
   the SDK's sta_netif_status_changed_cb() from inside dhcp_recv() in the
   LwIP tcpip_thread. If DHCP completes before or after the connected
   event (e.g. roaming, SDK-internal reconnect), the DHCP lease stays
   active and the client sends periodic renewal requests.
   Cannot call netifapi_dhcp_release_and_stop() here (deadlock: we ARE
   the tcpip_thread waiting on itself) and cannot call dhcp_release_and_stop()
   directly (use-after-free: dhcp_recv() hasn't returned yet).
   Fix: schedule wifiApplyStaticIpCallback via tcpip_callback(). It runs
   after dhcp_recv() unwinds, where it is safe to stop DHCP, apply the
   static address, and emit GOT_IP.
Bl00d-B0b pushed a commit to Bl00d-B0b/libretiny that referenced this pull request May 21, 2026
…ct (libretiny-eu#375)

When the reconnect/roam fallback path fires (wifiApplyStaticIpCallback),
LwIP's dhcp_recv() has already updated the DNS table via DHCP option 6
before we could stop DHCP. Restore info.dns1/dns2 after netif_set_addr()
to ensure the user-configured DNS servers survive reconnects.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bl00d-B0b added a commit to Bl00d-B0b/libretiny that referenced this pull request May 21, 2026
…retiny-eu#375)

- Replace double-space with tab before trailing comment on lwip/dhcp.h include
  (AlignTrailingComments + UseTab:Always requires tab alignment to col 24)
- Replace double-space with tab+space in ipaddr.addr assignment
  (AlignConsecutiveAssignments + UseTab:Always requires tab padding)
@Bl00d-B0b Bl00d-B0b force-pushed the ln882h-static-ip-fix branch from 00524d8 to 07fac3b Compare May 21, 2026 11:01
Bl00d-B0b added a commit to Bl00d-B0b/libretiny that referenced this pull request May 21, 2026
…y-eu#375)


wifi_sta_connect() always starts DHCP internally; there is no way to
pass a dhcp_mode parameter to it like BK72XX's bk_wlan_start_sta_adv_fix.

Apply static IP and stop DHCP in wifiEventStaConnected(), immediately
after the L2 association event fires, before the SDK-initiated DHCP
exchange completes. Emit GOT_IP manually since the netdev callback
won't fire when DHCP is stopped.
Bl00d-B0b added a commit to Bl00d-B0b/libretiny that referenced this pull request May 21, 2026
Bl00d-B0b added a commit to Bl00d-B0b/libretiny that referenced this pull request May 21, 2026
…am (libretiny-eu#375)


Two bugs in the previous static-IP fix (e2d501b + f49e18f):

1. Wrong order in wifiEventStaConnected(): netif_set_addr() was called
   before netifapi_dhcp_release_and_stop(). When DHCP is already BOUND
   at the time the connected event fires, netif_set_addr() triggers the
   LwIP netif status callback with dhcp_supplied_address==true, emitting
   a spurious GOT_IP before DHCP was stopped.
   Fix: stop DHCP first, then set the address.

2. Missing fallback in wifiEventIpReceived(): this callback is invoked by
   the SDK's sta_netif_status_changed_cb() from inside dhcp_recv() in the
   LwIP tcpip_thread. If DHCP completes before or after the connected
   event (e.g. roaming, SDK-internal reconnect), the DHCP lease stays
   active and the client sends periodic renewal requests.
   Cannot call netifapi_dhcp_release_and_stop() here (deadlock: we ARE
   the tcpip_thread waiting on itself) and cannot call dhcp_release_and_stop()
   directly (use-after-free: dhcp_recv() hasn't returned yet).
   Fix: schedule wifiApplyStaticIpCallback via tcpip_callback(). It runs
   after dhcp_recv() unwinds, where it is safe to stop DHCP, apply the
   static address, and emit GOT_IP.
Bl00d-B0b pushed a commit to Bl00d-B0b/libretiny that referenced this pull request May 21, 2026
…ct (libretiny-eu#375)


When the reconnect/roam fallback path fires (wifiApplyStaticIpCallback),
LwIP's dhcp_recv() has already updated the DNS table via DHCP option 6
before we could stop DHCP. Restore info.dns1/dns2 after netif_set_addr()
to ensure the user-configured DNS servers survive reconnects.
Bl00d-B0b added a commit to Bl00d-B0b/libretiny that referenced this pull request May 21, 2026
…retiny-eu#375)


- Replace double-space with tab before trailing comment on lwip/dhcp.h include
  (AlignTrailingComments + UseTab:Always requires tab alignment to col 24)
- Replace double-space with tab+space in ipaddr.addr assignment
  (AlignConsecutiveAssignments + UseTab:Always requires tab padding)
@Bl00d-B0b Bl00d-B0b force-pushed the ln882h-static-ip-fix branch 4 times, most recently from 2b6828b to cdf3b81 Compare May 24, 2026 07:40
@Bl00d-B0b Bl00d-B0b changed the title [lightning-ln882h] Fix static IP ignored after WiFi connect [lightning-ln882h] Add static IP support May 25, 2026
@Bl00d-B0b Bl00d-B0b force-pushed the ln882h-static-ip-fix branch from cdf3b81 to d5f9469 Compare June 2, 2026 14:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant