Vrstva UART¶
Modul UART implementuje binární rámcový protokol pro obousměrnou komunikaci mezi ESP32 (Link) a RP2040 (Controller). Používá se v zařízeních se dvěma MCU: iDryer LINK, iHeater LINK.
Storage Link nepoužívá modul UART — jedná se o samostatné zařízení ESP32-C3 bez druhého MCU.
Zahrňte samostatně:
Fyzická vrstva¶
- UART 8N1, 115200 baudů (výchozí), bez hardwarového řízení toku.
- Maximální datová část rámce: 200 bajtů.
- CRC-16/CCITT (poly 0x1021, init 0xFFFF) na rámec.
Struktura rámce¶
bajt 0 : SOF = 0xAA
bajt 1 : verze = 1
bajt 2 : příznaky (je vyžadován ACK | je ACK | chyba | fragment | poslední fragment)
bajt 3 : typ zprávy (UartMsgKind)
bajt 4 : číslo sekvence (0..255, wrap)
bajt 5 : délka datové části
datová část : data (0..200 bajtů)
crc16 : CRC, nízký bajt + vysoký bajt
Třídy¶
UartBridge¶
Hlavní třída modulu. Zpracovává příchozí tok bajt po bajtu, vytváří rámce, ověřuje CRC, spravuje ACK/retry a odesílá rámce do registrovaných zpětných volání.
UartBridge bridge;
bridge.begin(&Serial1, 115200);
// Zaregistrujte obslužné programy před begin()
bridge.setHelloHandler([&](const UartHelloPayload& p, const UartFrameHeader&) {
cloud.setMcuSerial(p.mcuSerial);
UartHelloAckPayload ack{};
bridge.sendHelloAck(ack);
});
// v loop():
bridge.loop();
Metody odesílání jsou rozděleny do dvou skupin:
- ESP32 → RP2040:
sendHelloAck,sendCommand,sendProfileCommand,sendConfigPush,sendHeartbeat,sendClaimStatus,sendClaimComplete,sendWsStatus,sendTelemetryAck,sendCommandAck,sendConfigAck. - RP2040 → ESP32 (nebo pro testy):
sendHello,sendTelemetry,sendStatus,sendWeights,sendRfid.
ACK/retry: rámce s příznakem UART_FLAG_ACK_REQ se opakují až 3krát s vypršením časového limitu 700 ms. Pokud je přijat ACK — send* vrátí false.
Typy zpráv¶
| Typ | Kód | Směr | Účel |
|---|---|---|---|
Hello |
0x01 | RP2040 → ESP32 | Oznámení při spuštění; obsahuje sériové číslo MCU, typ zařízení, schopnosti |
HelloAck |
0x02 | ESP32 → RP2040 | Odpověď s IP adresou a SSID |
Telemetry |
0x10 | RP2040 → ESP32 | Teplota, vlhkost, výkon topidla |
Weights |
0x12 | RP2040 → ESP32 | Čtení váhy |
Status |
0x13 | RP2040 → ESP32 | Aktuální režim sušení, průběh relace |
Rfid |
0x14 | RP2040 → ESP32 | Událost RFID (tag detekován/odebrán) |
Command |
0x20 | ESP32 → RP2040 | Příkaz z backendu (start, stop, find...) |
ConfigPush |
0x30 | ESP32 → RP2040 | Konfigurace (jednoduchá nebo dělená) |
Heartbeat |
0x40 | ESP32 → RP2040 | Provozní doba, RSSI, stav cloudu |
Error |
0x50 | oba | Chyba protokolu |
ClaimStart..Complete |
0x70–0x72 | oba | Životní cyklus žádosti |
WsEnable..StatusRequest |
0x73–0x76 | oba | Řízení WebSocket serveru na RP2040 |
ConfigReceiver / ConfigSender¶
Pomocné třídy pro přenos velkých konfigurací JSON přes UART v fragmentech (každý fragment ≤ 194 bajtů dat).
// Přijmout (ESP32 ← RP2040)
ConfigReceiver rx;
bridge.setConfigChunkHandler([&rx, &mqtt](const UartConfigChunkPayload& p, uint8_t len, const UartFrameHeader& hdr) {
if (rx.processFragment(p, len, hdr.flags) == ConfigFragResult::Complete) {
mqtt.publishConfigRaw(rx.getJson(), rx.getLength());
rx.reset();
}
});
// Poslat (ESP32 → RP2040)
ConfigSender tx;
uint16_t tid = ConfigSender::generateTransferId();
tx.send(json, length, tid, [&](const UartConfigChunkPayload& p, uint8_t payloadLen, uint8_t flags) {
return bridge.sendConfigPushChunk(p, payloadLen, flags);
});
Integrace s CloudStateMachine¶
Zařízení se dvěma MCU vyžadují sériové číslo z RP2040 před zřizováním:
idryer::cloud::CloudConfig cfg;
cfg.waitForMcuSerial = true;
idryer::cloud::CloudStateMachine cloud(..., cfg);
bridge.setHelloHandler([&](const UartHelloPayload& p, const UartFrameHeader&) {
cloud.setMcuSerial(p.mcuSerial);
// ...
});
Stavový stroj zůstane v WaitingForMcuSerial až do zavolání setMcuSerial().