room-server: drive push engine on a timer + cut delivery latency

Two hardware-found fixes after on-air testing on the GAT562 kit:

- Add a 500ms push timer in main_room_server.cpp so the post-sync
  engine advances at its intended cadence. ZephCore is event-driven
  (no Arduino superloop), so without this the engine only ran on the
  5s housekeeping tick — posts dripped out every ~5s and transmits
  bunched up, causing timeouts/resends.

- Lower the post-sync hold from upstream's conservative defaults
  (POST_SYNC_DELAY 6s -> 2s, PUSH_NOTIFY 2000ms -> 1000ms). These are
  server-side timing only (no wire-format change), and take measured
  delivery from ~6-7s down to ~2s.

Verified on hardware (910.525/62.5/SF7/CR8, two clients): normal-pace
messages deliver in ~2s with clean ACKs. Rapid-fire bursts can still
drop out-of-order messages via the per-client timestamp replay check
(unchanged from upstream) — left as-is to stay upstream-compatible.
This commit is contained in:
rlwilliamson-dev
2026-06-02 14:12:08 -05:00
parent bb6d9c60e1
commit 58dbba7f3b
2 changed files with 25 additions and 5 deletions
+5 -3
View File
@@ -86,13 +86,15 @@ static void uplink_time_sync_cb(uint32_t unix_ts)
#define SERVER_RESPONSE_DELAY 300
#define TXT_ACK_DELAY 200
/* Room server: post push/sync timing (matches upstream MeshCore). */
#define PUSH_NOTIFY_DELAY_MILLIS 2000
/* Room server: post push/sync timing. Upstream defaults are conservative
* (PUSH_NOTIFY 2000, POST_SYNC 6) which adds ~6-7s of delivery lag; lowered
* here for a more responsive room without changing wire formats. */
#define PUSH_NOTIFY_DELAY_MILLIS 1000
#define SYNC_PUSH_INTERVAL 1200
#define PUSH_ACK_TIMEOUT_FLOOD 12000
#define PUSH_TIMEOUT_BASE 4000
#define PUSH_ACK_TIMEOUT_FACTOR 2000
#define POST_SYNC_DELAY_SECS 6
#define POST_SYNC_DELAY_SECS 2
/* Stats blob returned for REQ_TYPE_GET_STATUS on a room server. Mirrors the
* repeater's RepeaterStats but reports posted/pushed counts in the trailing
+20 -2
View File
@@ -77,7 +77,8 @@ static const struct gpio_dt_spec led1 = GPIO_DT_SPEC_GET(LED1_NODE, gpios);
#define MESH_EVENT_HOUSEKEEPING BIT(3) /* Periodic housekeeping (noise floor, etc.) */
#define MESH_EVENT_GPS_ACTION BIT(4) /* GPS state change (must run on main thread!) */
#define MESH_EVENT_TX_DRAIN BIT(5) /* Outbound packet delay expired, run checkSend */
#define MESH_EVENT_ALL (MESH_EVENT_LORA_RX | MESH_EVENT_LORA_TX_DONE | MESH_EVENT_CLI_RX | MESH_EVENT_HOUSEKEEPING | MESH_EVENT_GPS_ACTION | MESH_EVENT_TX_DRAIN)
#define MESH_EVENT_PUSH_TICK BIT(6) /* Room server: drive the post-sync push engine */
#define MESH_EVENT_ALL (MESH_EVENT_LORA_RX | MESH_EVENT_LORA_TX_DONE | MESH_EVENT_CLI_RX | MESH_EVENT_HOUSEKEEPING | MESH_EVENT_GPS_ACTION | MESH_EVENT_TX_DRAIN | MESH_EVENT_PUSH_TICK)
/* Housekeeping interval - infrequent to preserve power savings */
#define HOUSEKEEPING_INTERVAL_MS CONFIG_ZEPHCORE_HOUSEKEEPING_INTERVAL_MS
@@ -105,6 +106,18 @@ K_WORK_DELAYABLE_DEFINE(initial_advert_work, initial_advert_work_fn);
/* Housekeeping timer for periodic tasks (noise floor calibration, etc.) */
K_TIMER_DEFINE(housekeeping_timer, housekeeping_timer_fn, NULL);
/* Room server push timer — wakes loop() at PUSH_TICK_INTERVAL_MS so the
* post-sync push engine advances at its intended ~1.2 s cadence instead of
* the 5 s housekeeping tick. Keeps post delivery snappy and TX smooth under
* load (without running radio maintenance that often). */
#define PUSH_TICK_INTERVAL_MS 500
static void push_timer_fn(struct k_timer *timer)
{
ARG_UNUSED(timer);
k_event_post(&mesh_events, MESH_EVENT_PUSH_TICK);
}
K_TIMER_DEFINE(push_timer, push_timer_fn, NULL);
/* Forward declarations */
#ifdef ZEPHCORE_LORA
static RoomServerMesh *room_mesh_ptr;
@@ -318,6 +331,10 @@ static void room_event_loop(void)
k_timer_start(&housekeeping_timer, K_MSEC(HOUSEKEEPING_INTERVAL_MS),
K_MSEC(HOUSEKEEPING_INTERVAL_MS));
/* Start the room-server push timer (drives post sync between clients). */
k_timer_start(&push_timer, K_MSEC(PUSH_TICK_INTERVAL_MS),
K_MSEC(PUSH_TICK_INTERVAL_MS));
for (;;) {
/* Wait for any mesh event - blocks until signaled */
uint32_t events = k_event_wait(&mesh_events, MESH_EVENT_ALL, false, K_FOREVER);
@@ -333,7 +350,8 @@ static void room_event_loop(void)
/* Packet processing — only on radio/CLI/TX events */
if (room_mesh_ptr &&
(events & (MESH_EVENT_LORA_RX | MESH_EVENT_LORA_TX_DONE |
MESH_EVENT_CLI_RX | MESH_EVENT_TX_DRAIN))) {
MESH_EVENT_CLI_RX | MESH_EVENT_TX_DRAIN |
MESH_EVENT_PUSH_TICK))) {
room_mesh_ptr->loop();
}
#endif