1. Arquitetura
Orquestra comandos e telemetria
Tempo real de baixo consumo
Lê/escreve CAN Bus da máquina
Testa sem hardware físico
Controla tudo pelo browser
Trator / plantadeira / drone
2. Docker Compose
version: "3.9"
services:
api:
build: ./api
ports:
- "8000:8000"
depends_on:
- mqtt
environment:
- MQTT_HOST=mqtt
mqtt:
image: eclipse-mosquitto
ports:
- "1883:1883"
gateway:
build: ./gateway
network_mode: host
privileged: true
depends_on:
- mqtt
environment:
- MQTT_HOST=localhost
simulator:
build: ./simulator
depends_on:
- mqtt
environment:
- MQTT_HOST=mqtt
web:
build: ./web
ports:
- "3000:3000"
depends_on:
- apidocker-compose up --build3. API (FastAPI + MQTT)
# api/main.py
from fastapi import FastAPI
import paho.mqtt.publish as publish
import os
app = FastAPI()
MQTT_HOST = os.getenv("MQTT_HOST", "localhost")
@app.post("/plant")
def plant(machine_id: str, depth: int, spacing: float):
payload = {
"machine_id": machine_id,
"cmd": "PLANT",
"depth": depth,
"spacing": spacing
}
publish.single("zony/commands", str(payload), hostname=MQTT_HOST)
return {"status": "sent"}
@app.post("/stop")
def stop(machine_id: str):
publish.single("zony/commands", f"{machine_id}:STOP", hostname=MQTT_HOST)
return {"status": "stopped"}# api/Dockerfile FROM python:3.11 WORKDIR /app COPY . . RUN pip install fastapi uvicorn paho-mqtt CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
4. Gateway CAN (Real)
# gateway/gateway.py
import can
import paho.mqtt.client as mqtt
import os
MQTT_HOST = os.getenv("MQTT_HOST", "localhost")
bus = can.interface.Bus(channel='can0', bustype='socketcan')
def on_message(client, userdata, msg):
data = eval(msg.payload.decode())
if data["cmd"] == "PLANT":
send_can(0x100, [1, data["depth"], int(data["spacing"]*100)])
if data["cmd"] == "STOP":
send_can(0x101, [0])
def send_can(arbid, data):
message = can.Message(arbitration_id=arbid, data=data, is_extended_id=False)
bus.send(message)
client = mqtt.Client()
client.connect(MQTT_HOST, 1883)
client.subscribe("zony/commands")
client.on_message = on_message
print("Gateway ativo...")
client.loop_forever()# gateway/Dockerfile FROM python:3.11 WORKDIR /app COPY . . RUN pip install python-can paho-mqtt CMD ["python", "gateway.py"]
⚙️ Fluxo do Gateway
5. Simulador (Sem Hardware)
Testa todo o stack sem precisar de máquina física. Recebe os comandos MQTT e imprime no terminal.
# simulator/sim.py
import paho.mqtt.client as mqtt
def on_message(client, userdata, msg):
print("SIMULADOR RECEBEU:", msg.payload.decode())
client = mqtt.Client()
client.connect("mqtt", 1883)
client.subscribe("zony/commands")
client.on_message = on_message
print("Simulador ativo...")
client.loop_forever()<!-- web/index.html -->
<!DOCTYPE html>
<html>
<body>
<h2>ZONY Control</h2>
<button onclick="plant()">Iniciar Plantio</button>
<button onclick="stop()">Parar</button>
<script>
function plant() {
fetch("http://localhost:8000/plant?machine_id=tractor_01&depth=5&spacing=0.5",
{ method: "POST" });
}
function stop() {
fetch("http://localhost:8000/stop?machine_id=tractor_01",
{ method: "POST" });
}
</script>
</body>
</html># web/Dockerfile FROM nginx:alpine COPY . /usr/share/nginx/html
6. Protocolo CAN ZONY v1
| ID CAN | Função | Byte 0 | Byte 1 | Byte 2 |
|---|---|---|---|---|
| 0x100 | Iniciar plantio | Cmd (0x01) | Profundidade cm | Espaçamento cm |
| 0x101 | Parar tudo | Cmd (0x00) | — | — |
| 0x102 | Ajustar prof. | Cmd (0x02) | Nova depth cm | — |
| 0x103 | Ajustar espaç. | Cmd (0x03) | — | Novo spacing cm |
Exemplo real — plantio
[0x01, 0x05, 0x32]0x01 → plantar
0x05 → 5 cm de profundidade
0x32 → 50 cm de espaçamento
7. Campo Real — Checklist
Validar protocolo CAN da máquina
Cada fabricante pode ter IDs e bauds diferentes.
Usar isolador CAN
Protege o Raspberry Pi de surtos elétricos.
Testar em modo seguro
Desconectar implemento físico nos primeiros testes.
Implementar STOP físico
Botão de emergência independente do software.
🔥 Resultado Final
"Do clique na tela ao movimento da máquina — em tempo real."
— ZONY Field Stack™