Skip to content

Commit f0a83d1

Browse files
committed
add esp8266 net preset
1 parent 2ddb275 commit f0a83d1

7 files changed

Lines changed: 119 additions & 10 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
## Unreleased
1010

11+
- Added `ZeroNetProfileEsp8266`, a constrained MQTT-first preset for Wemos / ESP8266.
12+
- Added optional offline queue gating in `ZeroHttpPump` and `ZeroMqttPump` so constrained boards can refuse backlog when link or transport is down.
1113
- Added generic compare workloads for `EnvMonitor`, `TelemetryGateway`, and `IndustrialLoop`.
1214
- Added repeatable ESP32 compare runners plus a cross-target workload compile matrix.
1315
- Improved telemetry gateway tuning so module throughput rises without queue buildup.

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ The optional network helpers are currently marked **BETA**:
104104
- `ZeroHttpPump`
105105
- `ZeroMqttPump`
106106
- `ZeroWiFiMaintainer`
107+
- `ZeroNetProfileEsp8266` (recommended constrained starting point for Wemos / ESP8266)
107108

108109
They are already useful and validated on desktop plus ESP32 hardware, but they are still under active tuning for footprint, retry behavior, and cross-board transport quirks. The core runtime is the stable layer; the network helpers should be treated as add-on modules that are ready for evaluation and controlled deployments.
109110

@@ -113,6 +114,11 @@ Current target maturity:
113114
- **ESP8266 / Wemos:** still BETA. Live delivery is real, but timing cost is still under active hardening.
114115
- **Other supported families:** compile-validated, but network helper maturity should still be treated as evaluation-grade until they receive the same live validation depth.
115116

117+
Recommended board-specific path:
118+
119+
- **ESP32:** use the default network module configs first, then validate against your real endpoint.
120+
- **ESP8266 / Wemos:** start with `ZeroNetProfileEsp8266`. It is a BETA, MQTT-first constrained preset that disables periodic HTTP dispatch by default and prevents offline queue buildup so constrained boards do not need heavy manual tuning just to stay responsive.
121+
116122
Current best module tradeoff reference (ESP32, `LEAN_NET`, manual pattern vs module pattern):
117123

118124
- RAM overhead: `+408 bytes`

docs/wiki/Beta-Modules.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ The following optional modules are currently marked **BETA**:
66
- `ZeroHttpPump`
77
- `ZeroMqttPump`
88
- `ZeroTransportMetrics`
9+
- `ZeroNetProfileEsp8266`
910

1011
They are already useful and validated on desktop plus ESP32 smoke tests, but they are not yet considered fully field-proven across all transport stacks and all board families.
1112

@@ -15,6 +16,10 @@ They are already useful and validated on desktop plus ESP32 smoke tests, but the
1516
- **ESP8266 / Wemos:** still BETA. Live transport works, but timing cost is still under active hardening.
1617
- **Other targets:** compile-supported, but network helpers should still be treated as validation targets until they see the same live-network coverage.
1718

19+
Recommended default:
20+
21+
- For constrained ESP8266 boards, start with `ZeroNetProfileEsp8266`. It is a BETA, MQTT-first constrained preset that keeps HTTP degraded by default and rejects offline queueing so the board stays more predictable without hand-tuning every interval.
22+
1823
## What BETA Means Here
1924

2025
- API shape is usable, but may still tighten as real-world patterns accumulate.

examples/LiveNetworkNode/LiveNetworkNode.ino

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <adapters/PowerSaveLoopAdapter.h>
33
#include <modules/net/ZeroHttpPump.h>
44
#include <modules/net/ZeroMqttPump.h>
5+
#include <modules/net/ZeroNetProfileEsp8266.h>
56
#include <modules/net/ZeroWiFiMaintainer.h>
67

78
#if defined(ARDUINO_ARCH_ESP8266)
@@ -18,17 +19,18 @@
1819
using zerokernel::Kernel;
1920
using zerokernel::modules::net::ZeroHttpPump;
2021
using zerokernel::modules::net::ZeroMqttPump;
22+
using zerokernel::modules::net::ZeroNetProfileEsp8266;
2123
using zerokernel::modules::net::ZeroTransportMetrics;
2224
using zerokernel::modules::net::ZeroWiFiMaintainer;
2325

2426
namespace {
2527

2628
const unsigned long kSamplePeriodUs = 100000UL;
2729
#if defined(ARDUINO_ARCH_ESP8266)
28-
const unsigned long kSampleTaskIntervalMs = 100UL;
29-
const unsigned long kHttpDispatchPeriodMs = 1500UL;
30-
const unsigned long kMqttDispatchPeriodMs = 1000UL;
31-
const unsigned long kHttpIoTimeoutMs = 200UL;
30+
const unsigned long kSampleTaskIntervalMs = ZeroNetProfileEsp8266::kSampleTaskIntervalMs;
31+
const unsigned long kHttpDispatchPeriodMs = ZeroNetProfileEsp8266::kHttpDispatchPeriodMs;
32+
const unsigned long kMqttDispatchPeriodMs = ZeroNetProfileEsp8266::kMqttDispatchPeriodMs;
33+
const unsigned long kHttpIoTimeoutMs = ZeroNetProfileEsp8266::kHttpIoTimeoutMs;
3234
#else
3335
const unsigned long kSampleTaskIntervalMs = 1UL;
3436
const unsigned long kHttpDispatchPeriodMs = 500UL;
@@ -282,7 +284,8 @@ void sampleTask() {
282284
void dispatchTask() {
283285
const unsigned long nowMs = millis();
284286

285-
const bool httpDue = (nowMs - g_lastHttpDispatchAtMs) >= kHttpDispatchPeriodMs;
287+
const bool httpDue = kHttpDispatchPeriodMs > 0 &&
288+
(nowMs - g_lastHttpDispatchAtMs) >= kHttpDispatchPeriodMs;
286289
const bool mqttDue = (nowMs - g_lastMqttDispatchAtMs) >= kMqttDispatchPeriodMs;
287290

288291
if (httpDue && g_httpPump.queuedCount() == 0 && !g_httpPump.isBusy()) {
@@ -403,12 +406,18 @@ void setup() {
403406
ZeroKernel.subscribeTypedFast(kMqttStateTopic, onTypedState);
404407

405408
ZeroWiFiMaintainer::Config wifiConfig;
409+
#if defined(ARDUINO_ARCH_ESP8266)
410+
wifiConfig = ZeroNetProfileEsp8266::wifiConfig();
411+
#endif
406412
wifiConfig.manageCapabilities = true;
407413
wifiConfig.capabilityMask = Kernel::kCapNetwork;
408414
wifiConfig.stateTopicKey = kWiFiStateTopic;
409415
g_wifiMaintainer.begin(ZeroKernel, isWiFiConnected, connectWiFi, disconnectWiFi, wifiConfig);
410416

411417
ZeroHttpPump::Config httpConfig;
418+
#if defined(ARDUINO_ARCH_ESP8266)
419+
httpConfig = ZeroNetProfileEsp8266::httpConfig();
420+
#endif
412421
g_httpPump.begin(ZeroKernel,
413422
httpConnectStep,
414423
httpWriteStep,
@@ -418,6 +427,9 @@ void setup() {
418427
g_httpPump.setLinkProbe(isWiFiConnected);
419428

420429
ZeroMqttPump::Config mqttConfig;
430+
#if defined(ARDUINO_ARCH_ESP8266)
431+
mqttConfig = ZeroNetProfileEsp8266::mqttConfig();
432+
#endif
421433
mqttConfig.stateTopicKey = kMqttStateTopic;
422434
g_mqttPump.begin(ZeroKernel,
423435
mqttLinkProbe,
@@ -428,11 +440,11 @@ void setup() {
428440
g_mqttPump.setTransportProbe(isWiFiConnected);
429441

430442
#if defined(ARDUINO_ARCH_ESP8266)
431-
ZeroKernel.addTask("Sample", sampleTask, 100, 0);
432-
ZeroKernel.addTask("WiFiMaint", wifiMaintainerTask, 100, 0);
433-
ZeroKernel.addTask("HttpPump", httpPumpTask, 100, 0);
434-
ZeroKernel.addTask("MqttPump", mqttPumpTask, 100, 0);
435-
ZeroKernel.addTask("Dispatch", dispatchTask, 100, 0);
443+
ZeroKernel.addTask("Sample", sampleTask, ZeroNetProfileEsp8266::kSampleTaskIntervalMs, 0);
444+
ZeroKernel.addTask("WiFiMaint", wifiMaintainerTask, ZeroNetProfileEsp8266::kWiFiTaskIntervalMs, 0);
445+
ZeroKernel.addTask("HttpPump", httpPumpTask, ZeroNetProfileEsp8266::kHttpTaskIntervalMs, 0);
446+
ZeroKernel.addTask("MqttPump", mqttPumpTask, ZeroNetProfileEsp8266::kMqttTaskIntervalMs, 0);
447+
ZeroKernel.addTask("Dispatch", dispatchTask, ZeroNetProfileEsp8266::kDispatchTaskIntervalMs, 0);
436448
#else
437449
ZeroKernel.addTask("Sample", sampleTask, kSampleTaskIntervalMs, 0);
438450
ZeroKernel.addTask("WiFiMaint", wifiMaintainerTask, 100, kWiFiMaintStartDelayMs);

src/modules/net/ZeroHttpPump.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class ZeroHttpPump {
5757
unsigned long phaseTimeoutMs;
5858
uint8_t maxRetries;
5959
bool dropOldestOnFull;
60+
bool queueWhenLinkDown;
6061
bool emitCompletionEvents;
6162

6263
Config()
@@ -79,6 +80,7 @@ class ZeroHttpPump {
7980
#endif
8081
maxRetries(2),
8182
dropOldestOnFull(true),
83+
queueWhenLinkDown(true),
8284
emitCompletionEvents(true) {}
8385
};
8486

@@ -151,6 +153,11 @@ class ZeroHttpPump {
151153
return false;
152154
}
153155

156+
if (!config_.queueWhenLinkDown && linkProbe_ != NULL && !linkProbe_()) {
157+
metrics_.recordQueueDrop();
158+
return false;
159+
}
160+
154161
Request queued = request;
155162
if (queued.retriesRemaining == 0) {
156163
queued.retriesRemaining = config_.maxRetries;

src/modules/net/ZeroMqttPump.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class ZeroMqttPump {
4141
unsigned long idleLoopIntervalMs;
4242
uint8_t maxRetries;
4343
bool dropOldestOnFull;
44+
bool queueWhenTransportDown;
4445
Kernel::TopicKey stateTopicKey;
4546

4647
Config()
@@ -51,6 +52,7 @@ class ZeroMqttPump {
5152
idleLoopIntervalMs(250),
5253
maxRetries(2),
5354
dropOldestOnFull(true),
55+
queueWhenTransportDown(true),
5456
stateTopicKey(0) {}
5557
};
5658

@@ -121,6 +123,15 @@ class ZeroMqttPump {
121123
return false;
122124
}
123125

126+
if (!config_.queueWhenTransportDown) {
127+
const bool transportReady = transportProbe_ != NULL ? transportProbe_()
128+
: (connected_ || (linkProbe_ != NULL && linkProbe_()));
129+
if (!transportReady) {
130+
metrics_.recordQueueDrop();
131+
return false;
132+
}
133+
}
134+
124135
Message message;
125136
message.topicKey = topicKey;
126137
message.value = value;
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#ifndef ZEROKERNEL_MODULES_NET_ZERONETPROFILEESP8266_H
2+
#define ZEROKERNEL_MODULES_NET_ZERONETPROFILEESP8266_H
3+
4+
#include "ZeroHttpPump.h"
5+
#include "ZeroMqttPump.h"
6+
#include "ZeroWiFiMaintainer.h"
7+
8+
namespace zerokernel {
9+
namespace modules {
10+
namespace net {
11+
12+
// Recommended constrained-network preset for ESP8266-class boards.
13+
// This profile intentionally prefers MQTT cadence over aggressive HTTP churn.
14+
struct ZeroNetProfileEsp8266 {
15+
static const unsigned long kSampleTaskIntervalMs = 100UL;
16+
static const unsigned long kWiFiTaskIntervalMs = 100UL;
17+
static const unsigned long kHttpTaskIntervalMs = 100UL;
18+
static const unsigned long kMqttTaskIntervalMs = 100UL;
19+
static const unsigned long kDispatchTaskIntervalMs = 100UL;
20+
static const unsigned long kReportTaskIntervalMs = 250UL;
21+
22+
static const unsigned long kHttpDispatchPeriodMs = 0UL;
23+
static const unsigned long kMqttDispatchPeriodMs = 1000UL;
24+
static const unsigned long kHttpIoTimeoutMs = 200UL;
25+
26+
static ZeroWiFiMaintainer::Config wifiConfig() {
27+
ZeroWiFiMaintainer::Config config;
28+
config.pollIntervalMs = 1000UL;
29+
config.retryBaseMs = 10000UL;
30+
config.retryMaxMs = 30000UL;
31+
config.retryJitterMs = 500UL;
32+
config.stablePollMultiplier = 4;
33+
config.stableThreshold = 6;
34+
return config;
35+
}
36+
37+
static ZeroHttpPump::Config httpConfig() {
38+
ZeroHttpPump::Config config;
39+
config.pollIntervalMs = 100UL;
40+
config.retryBaseMs = 700UL;
41+
config.retryMaxMs = 3200UL;
42+
config.retryJitterMs = 180UL;
43+
config.phaseTimeoutMs = 300UL;
44+
config.maxRetries = 2;
45+
config.queueWhenLinkDown = false;
46+
return config;
47+
}
48+
49+
static ZeroMqttPump::Config mqttConfig() {
50+
ZeroMqttPump::Config config;
51+
config.pollIntervalMs = 150UL;
52+
config.retryBaseMs = 600UL;
53+
config.retryMaxMs = 3000UL;
54+
config.retryJitterMs = 180UL;
55+
config.idleLoopIntervalMs = 300UL;
56+
config.maxRetries = 2;
57+
config.queueWhenTransportDown = false;
58+
return config;
59+
}
60+
};
61+
62+
} // namespace net
63+
} // namespace modules
64+
} // namespace zerokernel
65+
66+
#endif

0 commit comments

Comments
 (0)