Update 2026-07-10 11:59:35

This commit is contained in:
kassam 2026-07-10 11:59:37 +04:00
parent 6a91ca7c45
commit 6c864d91ae
3 changed files with 118 additions and 0 deletions

View File

@ -8,6 +8,8 @@ handled**. For install/ops, see [README.md](README.md).
## 1. Big picture
![Sanad Fleet — architecture and data pipeline](diagram.svg)
```
ROBOT (edge) │ YS LOOTAH (cloud)

View File

@ -5,6 +5,8 @@ Every robot type ships as its own self-contained **Docker** image with a
user-level **systemd auto-start service**, deployed, managed, and removed over
SSH by a single script. No `docker-compose` on the robot, **no `sudo`** required.
![Sanad Fleet — architecture and data pipeline](diagram.svg)
> For the end-to-end data flow (topics → agent → HTTP → server), see
> [PIPELINE.md](PIPELINE.md).

114
diagram.svg Normal file
View File

@ -0,0 +1,114 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 600" font-family="system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif">
<defs>
<marker id="arw" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto">
<path d="M0,0 L8,3 L0,6 Z" fill="#475569"/>
</marker>
<marker id="arwL" markerWidth="12" markerHeight="12" refX="9" refY="4" orient="auto">
<path d="M0,0 L10,4 L0,8 Z" fill="#0e7490"/>
</marker>
</defs>
<!-- card -->
<rect x="8" y="8" width="984" height="584" rx="16" fill="#f8fafc" stroke="#e2e8f0"/>
<!-- header -->
<text x="32" y="46" font-size="22" font-weight="700" fill="#0f172a">Sanad Fleet — Architecture &amp; Data Pipeline</text>
<text x="33" y="70" font-size="13" fill="#64748b">Robot state -&gt; containerized agent -&gt; fleet server · outbound HTTPS only</text>
<!-- zone labels -->
<text x="44" y="106" font-size="11" font-weight="700" letter-spacing="1.5" fill="#94a3b8">ON THE ROBOT (edge)</text>
<text x="452" y="106" font-size="11" font-weight="700" letter-spacing="1.5" fill="#94a3b8">AGENT</text>
<text x="704" y="106" font-size="11" font-weight="700" letter-spacing="1.5" fill="#94a3b8">YS LOOTAH FLEET</text>
<!-- ============ robot source cards ============ -->
<!-- G1 -->
<g>
<rect x="40" y="130" width="280" height="112" rx="10" fill="#ffffff" stroke="#cbd5e1"/>
<rect x="40" y="130" width="6" height="112" rx="3" fill="#b45309"/>
<text x="62" y="160" font-size="15" font-weight="700" fill="#0f172a">G1 — map uploader</text>
<text x="62" y="184" font-size="11.5" fill="#475569">source: navigation map files</text>
<text x="62" y="205" font-size="11" fill="#64748b" font-family="ui-monospace,Menlo,Consolas,monospace">web_nav3 maps/*.db + places</text>
<text x="62" y="224" font-size="11" fill="#64748b" font-family="ui-monospace,Menlo,Consolas,monospace">maps_meta.json</text>
</g>
<!-- R1 -->
<g>
<rect x="40" y="258" width="280" height="112" rx="10" fill="#ffffff" stroke="#cbd5e1"/>
<rect x="40" y="258" width="6" height="112" rx="3" fill="#0e7c86"/>
<text x="62" y="288" font-size="15" font-weight="700" fill="#0f172a">R1 — telemetry</text>
<text x="62" y="312" font-size="11.5" fill="#475569">source: DDS (unitree_hg)</text>
<text x="62" y="333" font-size="11" fill="#64748b" font-family="ui-monospace,Menlo,Consolas,monospace">rt/lf/bmsstate · rt/lowstate</text>
<text x="62" y="352" font-size="11" fill="#64748b" font-family="ui-monospace,Menlo,Consolas,monospace">iface eth10</text>
</g>
<!-- Go2 -->
<g>
<rect x="40" y="386" width="280" height="112" rx="10" fill="#ffffff" stroke="#cbd5e1"/>
<rect x="40" y="386" width="6" height="112" rx="3" fill="#4f46e5"/>
<text x="62" y="416" font-size="15" font-weight="700" fill="#0f172a">Go2 — telemetry</text>
<text x="62" y="440" font-size="11.5" fill="#475569">source: DDS (unitree_go)</text>
<text x="62" y="461" font-size="11" fill="#64748b" font-family="ui-monospace,Menlo,Consolas,monospace">rt/lowstate.bms_state</text>
<text x="62" y="480" font-size="11" fill="#94a3b8">unverified on hardware</text>
</g>
<!-- source -> agent arrows -->
<line x1="322" y1="186" x2="366" y2="230" stroke="#475569" stroke-width="2" marker-end="url(#arw)"/>
<line x1="322" y1="314" x2="366" y2="314" stroke="#475569" stroke-width="2" marker-end="url(#arw)"/>
<line x1="322" y1="442" x2="366" y2="398" stroke="#475569" stroke-width="2" marker-end="url(#arw)"/>
<!-- ============ agent ============ -->
<g>
<rect x="370" y="130" width="250" height="368" rx="12" fill="#ecfeff" stroke="#06b6d4"/>
<text x="495" y="164" text-anchor="middle" font-size="16" font-weight="700" fill="#0e7490">sanad_api_&lt;type&gt;</text>
<text x="495" y="187" text-anchor="middle" font-size="11.5" fill="#0f766e">Docker · --network host</text>
<text x="495" y="205" text-anchor="middle" font-size="11.5" fill="#0f766e">read-only · never moves</text>
<!-- read/build -->
<text x="495" y="238" text-anchor="middle" font-size="11.5" font-weight="600" fill="#334155">read -&gt; build payload -&gt; POST</text>
<!-- systemd box -->
<rect x="392" y="256" width="206" height="66" rx="8" fill="#ffffff" stroke="#94a3b8"/>
<text x="495" y="282" text-anchor="middle" font-size="12.5" font-weight="700" fill="#0f172a">systemd --user service</text>
<text x="495" y="303" text-anchor="middle" font-size="11" fill="#475569">auto-start on boot · no sudo</text>
<!-- heartbeat box -->
<rect x="392" y="336" width="206" height="62" rx="8" fill="#fff7ed" stroke="#fdba74"/>
<text x="495" y="360" text-anchor="middle" font-size="12" font-weight="600" fill="#9a3412">heartbeat if source silent</text>
<text x="495" y="380" text-anchor="middle" font-size="11" fill="#b45309">-&gt; robot stays "online"</text>
<text x="495" y="428" text-anchor="middle" font-size="11" fill="#0f766e">loop: 2 s telemetry · 30 s map (on change)</text>
<text x="495" y="452" text-anchor="middle" font-size="10.5" fill="#64748b">deployed via fleet_install.sh</text>
<text x="495" y="470" text-anchor="middle" font-size="10.5" fill="#64748b">(rsync + docker build on robot)</text>
</g>
<!-- agent -> server -->
<line x1="620" y1="235" x2="700" y2="200" stroke="#0e7490" stroke-width="2.5" marker-end="url(#arwL)"/>
<text x="660" y="180" text-anchor="middle" font-size="11" font-weight="700" fill="#0e7490">HTTPS POST</text>
<text x="660" y="222" text-anchor="middle" font-size="10" fill="#0e7490">Bearer token</text>
<!-- ============ fleet server ============ -->
<g>
<rect x="700" y="130" width="260" height="168" rx="12" fill="#0f172a"/>
<text x="718" y="160" font-size="15" font-weight="700" fill="#e2e8f0">Fleet Server — ingest API</text>
<text x="718" y="190" font-size="11" fill="#7dd3fc" font-family="ui-monospace,Menlo,Consolas,monospace">POST …/ingest/telemetry</text>
<text x="928" y="190" text-anchor="end" font-size="10" fill="#94a3b8">~2 s</text>
<text x="718" y="214" font-size="11" fill="#fcd34d" font-family="ui-monospace,Menlo,Consolas,monospace">POST …/ingest/{sn}/map</text>
<text x="928" y="214" text-anchor="end" font-size="10" fill="#94a3b8">on change</text>
<line x1="718" y1="234" x2="942" y2="234" stroke="#334155"/>
<text x="718" y="258" font-size="10.5" fill="#94a3b8" font-family="ui-monospace,Menlo,Consolas,monospace">Authorization: Bearer &lt;token&gt;</text>
<text x="718" y="280" font-size="10.5" fill="#64748b">keyed by sn · mac in telemetry</text>
</g>
<!-- server -> dashboard -->
<line x1="830" y1="298" x2="830" y2="332" stroke="#475569" stroke-width="2" marker-end="url(#arw)"/>
<g>
<rect x="700" y="334" width="260" height="96" rx="12" fill="#ffffff" stroke="#cbd5e1"/>
<text x="830" y="368" text-anchor="middle" font-size="14" font-weight="700" fill="#0f172a">Dashboard · Storage · Alerts</text>
<text x="830" y="392" text-anchor="middle" font-size="11" fill="#64748b">live status · map view · fault alerts</text>
<text x="830" y="411" text-anchor="middle" font-size="10.5" fill="#94a3b8">(YS Lootah side — already built)</text>
</g>
<!-- footer -->
<line x1="32" y1="524" x2="968" y2="524" stroke="#e2e8f0"/>
<text x="32" y="548" font-size="11.5" fill="#64748b">Outbound HTTPS only — no inbound port on the robot. Each robot type = its own Docker image, installed &amp; managed over SSH by</text>
<text x="32" y="566" font-size="11.5" font-weight="600" fill="#475569" font-family="ui-monospace,Menlo,Consolas,monospace">fleet_install.sh<tspan font-family="system-ui" font-weight="400" fill="#64748b"> · user-level systemd auto-start, no sudo.</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 7.6 KiB