|
AlteriomPainlessMesh v2.1.1
Easy ESP32/ESP8266 mesh networking with Alteriom IoT extensions
|
Classes | |
| class | ChunkedBodyDecoder |
| Removes HTTP/1.1 chunked transfer framing from a body read a byte at a time, and passes the content on to a ResponseExcerpt. More... | |
| class | GatewayAckPackage |
| Gateway Acknowledgment Package for delivery confirmations. More... | |
| class | GatewayDataPackage |
| Gateway Data Package for routing Internet requests through mesh. More... | |
| struct | HttpRequestOutcome |
| The outcome of a gateway HTTP request, classified for the ack. More... | |
| class | InternetHealthChecker |
| Internet Health Checker class for periodic connectivity monitoring. More... | |
| struct | InternetStatus |
| Structure to hold Internet connectivity check results. More... | |
| struct | MeshChannelCandidate |
| One occurrence of the mesh SSID seen by an all-channel scan. More... | |
| class | NegativeDnsCache |
| A few hosts that recently failed to resolve, and when. More... | |
| class | ResponseExcerpt |
| The start and the end of a response body, read a byte at a time. More... | |
| struct | SharedGatewayConfig |
| Configuration structure for Shared Gateway Mode. More... | |
| struct | ValidationResult |
| Validation result structure for SharedGatewayConfig. More... | |
Typedefs | |
| typedef std::function< void(bool available)> | InternetChangedCallback_t |
| Callback type for Internet connectivity change events. | |
Enumerations | |
| enum class | GatewayPriority : uint8_t { PRIORITY_CRITICAL = 0 , PRIORITY_HIGH = 1 , PRIORITY_NORMAL = 2 , PRIORITY_LOW = 3 } |
| Priority levels for GatewayDataPackage messages. More... | |
| enum | HttpTransportError : int { HTTP_TRANSPORT_CONNECTION_REFUSED = -1 , HTTP_TRANSPORT_SEND_HEADER_FAILED = -2 , HTTP_TRANSPORT_SEND_PAYLOAD_FAILED = -3 , HTTP_TRANSPORT_NOT_CONNECTED = -4 , HTTP_TRANSPORT_CONNECTION_LOST = -5 , HTTP_TRANSPORT_NO_STREAM = -6 , HTTP_TRANSPORT_NO_HTTP_SERVER = -7 , HTTP_TRANSPORT_TOO_LESS_RAM = -8 , HTTP_TRANSPORT_ENCODING = -9 , HTTP_TRANSPORT_STREAM_WRITE = -10 , HTTP_TRANSPORT_READ_TIMEOUT = -11 } |
| HTTPClient transport errors, by what they say about the request. More... | |
Functions | |
| constexpr bool | isValidMeshChannel (uint8_t channel) |
| constexpr bool | shouldFollowBridgeChannel (uint32_t localNodeId, uint32_t electedBridgeId, uint8_t currentChannel, uint8_t announcedChannel) |
| uint8_t | pickMeshChannel (const std::vector< MeshChannelCandidate > &candidates, uint8_t avoidChannel, uint8_t routerChannel=0) |
| Where a node that has lost the mesh should go. | |
| bool | transportErrorMayHaveReachedServer (int rawCode) |
| Can a request that failed with this transport error have reached the server? | |
| bool | responseContains (const TSTRING &haystack, const char *needle) |
| TSTRING | summarizeResponseBody (const TSTRING &body, size_t maxLen=GATEWAY_RESPONSE_REASON_MAX) |
| Reduce a response body to one line fit for a log or an error string. | |
| bool | transferEncodingIsChunked (const TSTRING &value) |
| uint32_t | parseRetryAfterMs (const TSTRING &value) |
| The delay a Retry-After header asks for, in milliseconds. | |
| TSTRING | requestIdFor (uint32_t originNode, uint32_t messageId, uint32_t requestNonce=0) |
| The identifier the gateway sends with a request, as both X-Request-Id and Idempotency-Key. | |
| uint32_t | newRequestNonce () |
| HttpRequestOutcome | classifyHttpResult (int rawCode, const TSTRING &body=TSTRING()) |
| Classify an HTTPClient result for the gateway acknowledgment. | |
| TSTRING | hostFromUrl (const TSTRING &url) |
| The host of an http(s) URL, without scheme, port, path or query. | |
| bool | looksLikeIpLiteral (const TSTRING &host) |
| constexpr unsigned long | gatewayBlockingBudgetMs () |
| Wall-clock ceiling of the gateway's blocking calls on the GATEWAY_DATA path, in milliseconds (issue #416). | |
| template<typename T > | |
| bool | reserveGatewayBlockingBudget (T &connection) |
| template<typename T > | |
| size_t | refreshPeerWatchdogs (T &mesh, unsigned long stalledMs) |
| Give every peer's running watchdog back the time a blocking call hid. | |
| typedef std::function<void(bool available)> painlessmesh::gateway::InternetChangedCallback_t |
Callback type for Internet connectivity change events.
|
strong |
Priority levels for GatewayDataPackage messages.
Defines the priority levels for message routing through the gateway. Lower values indicate higher priority.
| enum painlessmesh::gateway::HttpTransportError : int |
HTTPClient transport errors, by what they say about the request.
HTTPClient::GET()/POST() return a negative code when the request failed below HTTP. The ESP32 and ESP8266 cores number them the same way. What matters to a retry is whether the request can have reached the server: resending one that did delivers it twice, which for a request with an effect – a message, a payment, a counter – is a second effect (the rig showed a timed-out send issued four times).
Where each is raised, in both cores' HTTPClient::sendRequest() for the buffer GET()/POST() the gateway uses: -1, -2 and -3 before the request is complete; everything else from handleHeaderResponse(), which runs after the whole request was written – so -4 is a connection that closed before the reply began and -7 a reply that was not HTTP, both with the request already at the server. -6 and -8 come from stream sends and from reading a body.
|
inline |
Classify an HTTPClient result for the gateway acknowledgment.
HTTP semantics only. 200, 201, 202 and 204 are a success. Any other 2xx is an unverified failure the server answered; 1xx, 3xx, 4xx and 5xx are failures. A retry is allowed only when it cannot produce a second copy of the request: a transport error that failed before the request was complete, or 429/503, where the server says it did not take the request. The reason is a summary of whatever body was read, so the application learns why.
| rawCode | The int returned by HTTPClient::GET() or ::POST() |
| body | The start of the response body, empty if none was read |
|
constexpr |
Wall-clock ceiling of the gateway's blocking calls on the GATEWAY_DATA path, in milliseconds (issue #416).
Each HTTPClient call chain is counted at two socket waits — GET()/POST() (send + header read) and getString() (body read) — because HTTPClient::setTimeout() bounds an individual socket wait, not the whole call. The captive-portal probe and the destination request both have that shape and run back to back, and the DNS reachability probe (bounded by GATEWAY_DNS_TIMEOUT_MS on ESP8266, skipped on ESP32) runs before them whenever the GATEWAY_CONNECTIVITY_CACHE_MS window has expired.
The host of an http(s) URL, without scheme, port, path or query.
"https://api.example.com:8443/x?y" -> "api.example.com". Empty when the URL has no host.
|
constexpr |
Return whether a channel can be announced for a 2.4 GHz mesh takeover.
|
inline |
True for a dotted-decimal IPv4 literal, which needs no DNS.
|
inline |
A request nonce: random, and never the 0 that means "none".
|
inline |
The delay a Retry-After header asks for, in milliseconds.
Only the delay-seconds form is read; an HTTP-date, or anything else, is 0 – no instruction – rather than a guess. Values past GATEWAY_RETRY_AFTER_MAX_MS are returned as they are, so the caller can see the server asked for longer than it will wait.
|
inline |
Where a node that has lost the mesh should go.
Channel re-detection runs only after a node's own partition has produced nothing new for a while, so the mesh it can still see on its current channel is the partition it is stranded in. When the SSID is also visible on another channel, that is the rest of the network — a bridge that moved to its router's channel, most often — and the node should go there.
Returning the first match, as this used to, made the outcome depend on scan order: a stranded node that happened to see its own partition first concluded nothing had changed and stayed stranded.
A node that knows the router has a better signal than strength: a bridge's AP is on its router's channel, so a mesh with a bridge lives there. A failover backup that booted while the mesh was split across two channels saw one AP on each, two dB apart, and joined the one without the bridge; it had a partition of two to itself for the hundred seconds it took the re-detection rules to move it, and the election ran out of time.
| candidates | Every channel the mesh SSID was seen on, with RSSI. |
| avoidChannel | The node's current mesh channel; 0 = no preference. |
| routerChannel | The channel the router was seen on; 0 = unknown. |
| size_t painlessmesh::gateway::refreshPeerWatchdogs | ( | T & | mesh, |
| unsigned long | stalledMs | ||
| ) |
Give every peer's running watchdog back the time a blocking call hid.
Call this immediately after returning from a blocking Internet call, before the scheduler next runs, passing the measured wall-clock duration of the stall.
Nothing executes while the gateway is inside HTTPClient::GET()/POST(), but wall-clock time keeps passing. So a timeOutTask whose NODE_TIMEOUT deadline fell during the stall is already overdue when the scheduler resumes, and fires on the very next execute() – closing a peer that never actually went missing (issues #318, #332).
The compensation equals the measured stall, no more (issue #417): each enabled watchdog's existing deadline is postponed by stalledMs via Task::adjust(), which extends iDelay without touching the task's baseline. A peer's watchdog therefore measures only time the mesh was actually able to observe the peer. The earlier implementation restarted every watchdog from zero (restartDelayed()) on every exit path – which meant any live peer's gateway traffic granted a genuinely dead peer a fresh full NODE_TIMEOUT, so the dead peer was never reaped. Task::delay() would be wrong in the other direction: it resets the baseline to now, shortening the deadline of a peer that still had more than stalledMs remaining and disconnecting healthy peers early.
Paths that did not block must pass 0 and compensate nothing.
Only enabled watchdogs are touched, and this matters: timeOutTask is armed by nodeSyncTask when a sync request goes out and disabled again when the reply lands, so a disabled watchdog means the peer has nothing outstanding. Enabling it here would invent a NODE_TIMEOUT deadline for an idle-but-healthy link whose callback is Connection::close() – turning a reliability fix into a disconnect bug.
This protects the gateway's own view of its peers. The peers' view of the gateway depends on keeping the stall shorter than their watchdog, which is what gatewayBlockingBudgetMs() is meant to bound – though see the
| T | Mesh type exposing subs (see painlessmesh::layout::Layout). |
| mesh | The mesh whose direct peer connections should be refreshed. |
| stalledMs | Measured wall-clock duration of the blocking section, in milliseconds. 0 means nothing blocked and nothing is compensated. |
|
inline |
The identifier the gateway sends with a request, as both X-Request-Id and Idempotency-Key.
The same for every attempt at one sendToInternet() call, so a service that honours Idempotency-Key treats a retry as the request it already has, and anything recording requests can count the copies one call produced.
The request's nonce keeps it unique beyond its messageId, whose counter wraps after 65,535 requests in a boot. A package from a node that predates the nonce (0) keeps the two-part form it always had.
| bool painlessmesh::gateway::reserveGatewayBlockingBudget | ( | T & | connection | ) |
Reserve the blocking HTTP budget on the requester's route watchdog.
A gateway compensates its own peer watchdogs after a blocking request, but it cannot modify the requester's timer. That timer may already be partly spent, so extend its existing deadline by the bounded gateway budget before sending. Disabled watchdogs remain disabled.
|
inline |
|
constexpr |
Decide whether a peer must follow an elected bridge to another channel.
|
inline |
Reduce a response body to one line fit for a log or an error string.
Tags are dropped and whitespace collapsed, so an HTML page reads as text in a serial log. A body longer than maxLen keeps its beginning and its end, joined by " ... ": services often lead with an echo of the request and finish with the verdict, and a summary that keeps only the beginning keeps the echo and loses the verdict (issue #463).
|
inline |
Whether a Transfer-Encoding header value names chunked encoding.
|
inline |
Can a request that failed with this transport error have reached the server?
True – the safe answer – for every code that is not known to fail before the request was complete, including codes this library does not know.