Fluxo de dados¶
Descrição de como os dados se movem dentro de um dispositivo em execução. O objetivo é mostrar que idryer-core não usa um barramento de eventos nem um localizador de serviço: os participantes são conectados por ponteiros explícitos na raiz de composição, e cada direção de dados é um caminho separado e legível.
Padrões detalhados para "como rotear dados entre minhas partes" estão em 04-patterns/99-data-flow.md.
Direções principais¶
Backend / app
│
│ MQTT commands/*
▼
┌──────────────────────────────┐
│ MqttClient │
│ analisa topic + payload │
└──────────────┬───────────────┘
│
│ CommandCallback
▼
┌──────────────────────────────┐
│ IdryerRuntime │
│ ping → settimeofday + info │
│ outros → CommandHandler │
└──────────────┬───────────────┘
│
│ commandHandler_(cmd, data)
▼
┌──────────────────────────────┐
│ Produto handleCommand() │
│ invoke / set / get_config / │
│ comandos específicos produto│
└──────┬───────────────┬───────┘
│ │
▼ ▼
ActionDispatcher IProfile
handleInvoke / Set getConfig
applyConfig
buildInfoJson
Sensor (produto) Perfil / executor
│ │
│ tick() / leia │ atualiza estado
▼ ▼
┌───────────────────────────────────────┐
│ Editor de produto │
│ (StorageTelemetryPublisher, …) │
│ constrói JsonDocument │
└────────────────┬──────────────────────┘
│
│ pub.publishX(doc)
▼
┌───────────────────────────────────────┐
│ DevicePublisher (opcional) │
│ ajudante duplo publicar: MQTT + WS │
└─────────┬─────────────────────┬───────┘
│ │
▼ ▼
MqttClient LocalAccess (WS)
broker cliente LAN
Comandos recebidos¶
- MQTT entrega uma mensagem no tópico
idryer/{serial}/commands/{cmd}. MqttClient::handleMessageanalisa a carga como JSON e chamaCommandCallback.CommandCallbacké registrado porIdryerRuntimeembegin()— aceita(command, data), ondecommandé o sufixo apóscommands/.IdryerRuntime::onMqttCommand:- Se
command == "ping"— sincroniza tempo e publica informações. Não passado adiante. - Se um
commandHandler_é registrado — passa tudo o mais para o produto. -
Caso contrário — caminho integrado de fallback:
invoke→ActionDispatcher,set→ActionDispatcher,device.getConfig→IProfile::getConfig. -
WS local (se usado) aceita
{"type":"command","command":"...","data":{...}}, desembrulha o envelope e chama o mesmoCommandSinkregistrado para o caminho MQTT. Um manipulador — dois transportes.
Dados de saída¶
A biblioteca não publica nada a menos que seja solicitada. Todas as mensagens de saída são iniciadas pelo produto:
| O quê | Iniciado por | Via qual API |
|---|---|---|
info |
IdryerRuntime (uma vez quando Online e no ping) |
MqttClient::publishInfoJson |
telemetry |
editor do produto | MqttClient::publishTelemetry ou DevicePublisher::publishTelemetry |
status |
código do produto na mudança de estado | MqttClient::publishStatus ou DevicePublisher::publishStatus |
config |
handleCommand em device.getConfig ou get_config |
MqttClient::publishConfig |
events |
código do produto em um evento | MqttClient::publishEvent |
integrations/status |
LinkIntegrationsManager |
MqttClient::publishIntegrationsStatus |
offline |
broker automaticamente (LWT) | dispositivo nunca publica isto |
Conexões de objetos na raiz de composição¶
Referências entre participantes são passadas explicitamente através de construtores e setters. Sem registros globais.
ArduinoWifiManager ─┐
ArduinoCredentialStore ─┤
HttpApi (← Http) ─┼──→ CloudStateMachine ──→ IdryerRuntime ──→ MqttClient
MqttClient ─┘ ▲
│
ActionDispatcher ──────┤
IProfile ──────┘
LocalAccess ──── (setCommandSink) ────→ mesmo handleCommand
DevicePublisher (&MqttClient, &LocalAccess)
Sensor ──→ Editor ──→ DevicePublisher ──→ MqttClient + LocalAccess
Executor ←── ActionDispatcher (invoke) ←── handleCommand
Cada conexão é uma linha em main.cpp. Esta é a "raiz de composição explícita".
Por quê este design¶
- Sem magia: para entender como os dados viajam de um sensor para a nuvem, o leitor vê a cadeia de ponteiros em
main.cpp. Nenhum fluxo de dados fica escondido atrás de uma fachada. - Flexibilidade: o produto escolhe se usar
DevicePublisher(MQTT + WS), publicar apenas para MQTT ou usar seu próprio editor com lógica adicional. - Testabilidade: cada nó é uma classe separada com dependências explícitas. Os nós podem ser substituídos por mocks sem alterar o resto da pilha.
O que está intencionalmente ausente¶
- Nenhum barramento de eventos global ou intermediário de mensagens dentro do dispositivo.
- Nenhuma detecção automática de "tenho um sensor, publicarei seus dados por conta própria".
- Nenhum registro de tipo de "dispositivo conhece todos os seus provedores de telemetria".
Se o produto precisa de tais conexões — o produto as adiciona em seu próprio código. A biblioteca não as impõe.