fleet/diagram.svg

110 lines
9.2 KiB
XML

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1060 500" font-family="'Segoe UI',Roboto,Helvetica,Arial,'DejaVu Sans',sans-serif">
<defs>
<marker id="arw" markerWidth="9" markerHeight="9" refX="7" refY="3" orient="auto">
<path d="M0,0 L7,3 L0,6 Z" fill="#5f6368"/>
</marker>
</defs>
<rect width="1060" height="500" fill="#f6f8fa"/>
<!-- title -->
<text x="30" y="34" font-size="22" font-weight="700" fill="#202124">Sanad Fleet — one agent, five endpoints</text>
<text x="30" y="57" font-size="13.5" fill="#5f6368">Robot state -&gt; containerized agent -&gt; YS Lootah fleet server &#183; outbound HTTPS only, read-only toward the robot</text>
<!-- =============== ROBOT =============== -->
<rect x="24" y="84" width="300" height="372" rx="12" fill="#ffffff" stroke="#4285f4" stroke-width="1.5"/>
<text x="40" y="110" font-size="15" font-weight="700" fill="#1a73e8">ROBOT &#183; G1 &#183; R1 &#183; Go2</text>
<text x="40" y="128" font-size="11.5" fill="#5f6368">unitree_hg (G1/R1) &#183; unitree_go (Go2)</text>
<rect x="40" y="144" width="268" height="150" rx="8" fill="#f1f6ff" stroke="#c6dafc"/>
<text x="54" y="166" font-size="12.5" font-weight="700" fill="#202124">DDS topics</text>
<text x="54" y="190" font-size="11" fill="#3c4043" font-family="'Roboto Mono',Menlo,Consolas,monospace">rt/lf/bmsstate</text><text x="182" y="190" font-size="11" fill="#5f6368">-&gt; battery, SoH</text>
<text x="54" y="212" font-size="11" fill="#3c4043" font-family="'Roboto Mono',Menlo,Consolas,monospace">rt/lowstate</text><text x="182" y="212" font-size="11" fill="#5f6368">-&gt; temps, faults</text>
<text x="54" y="234" font-size="11" fill="#3c4043" font-family="'Roboto Mono',Menlo,Consolas,monospace">rt/lf/odommodestate</text>
<text x="54" y="250" font-size="11" fill="#5f6368">-&gt; position</text>
<text x="54" y="274" font-size="11" fill="#3c4043" font-family="'Roboto Mono',Menlo,Consolas,monospace">sport RPC 7001</text><text x="182" y="274" font-size="11" fill="#5f6368">-&gt; loco mode (ro)</text>
<rect x="40" y="304" width="268" height="66" rx="8" fill="#f1f6ff" stroke="#c6dafc"/>
<text x="54" y="326" font-size="12.5" font-weight="700" fill="#202124">Files &#183; via /host:ro mount</text>
<text x="54" y="348" font-size="11" fill="#5f6368">SLAM <tspan font-family="'Roboto Mono',Menlo,Consolas,monospace" fill="#3c4043">.db</tspan> &#183; Nav2/Pudu <tspan font-family="'Roboto Mono',Menlo,Consolas,monospace" fill="#3c4043">map.pgm+yaml</tspan></text>
<text x="54" y="363" font-size="10.5" fill="#80868b">rendered to PNG for upload</text>
<rect x="40" y="380" width="268" height="64" rx="8" fill="#f1f6ff" stroke="#c6dafc"/>
<text x="54" y="402" font-size="12.5" font-weight="700" fill="#202124">Sanad app</text>
<text x="54" y="422" font-size="11" fill="#5f6368">docker json-log -&gt; project logs</text>
<text x="54" y="438" font-size="11" fill="#5f6368">dashboard :8001 -&gt; remote URL</text>
<!-- robot -> agent -->
<line x1="324" y1="250" x2="380" y2="250" stroke="#5f6368" stroke-width="2" marker-end="url(#arw)"/>
<text x="352" y="242" text-anchor="middle" font-size="10.5" fill="#5f6368">reads</text>
<!-- =============== AGENT =============== -->
<rect x="380" y="84" width="300" height="372" rx="12" fill="#ffffff" stroke="#34a853" stroke-width="2"/>
<text x="530" y="110" text-anchor="middle" font-size="16" font-weight="700" fill="#188038">sanad_api_&lt;type&gt;</text>
<text x="530" y="130" text-anchor="middle" font-size="11.5" fill="#5f6368">Docker &#183; --network host &#183; user systemd &#183; no sudo</text>
<text x="530" y="148" text-anchor="middle" font-size="11.5" fill="#5f6368">read-only &#183; never commands motion</text>
<!-- loop rows -->
<g font-family="'Segoe UI',Roboto,Helvetica,Arial,'DejaVu Sans',sans-serif">
<!-- telemetry -->
<rect x="398" y="167" width="264" height="42" rx="7" fill="#f1f6ff" stroke="#c6dafc"/><rect x="398" y="167" width="5" height="42" rx="2.5" fill="#1a73e8"/>
<text x="414" y="185" font-size="12.5" font-weight="700" fill="#202124">Telemetry &#183; 2s</text>
<text x="414" y="201" font-size="10.5" fill="#5f6368">battery &#183; status &#183; position &#183; faults &#183; control mode</text>
<!-- map -->
<rect x="398" y="219" width="264" height="42" rx="7" fill="#f0faf3" stroke="#b7e1c4"/><rect x="398" y="219" width="5" height="42" rx="2.5" fill="#34a853"/>
<text x="414" y="237" font-size="12.5" font-weight="700" fill="#202124">Map sync &#183; 30s</text>
<text x="414" y="253" font-size="10.5" fill="#5f6368">discover pgm+yaml / .db &#183; upload once per change</text>
<!-- alert -->
<rect x="398" y="271" width="264" height="42" rx="7" fill="#fdecea" stroke="#f5c0ba"/><rect x="398" y="271" width="5" height="42" rx="2.5" fill="#ea4335"/>
<text x="414" y="289" font-size="12.5" font-weight="700" fill="#202124">Alert scan &#183; 10s</text>
<text x="414" y="305" font-size="10.5" fill="#5f6368">battery&lt;=50 &#183; Gemini billing &#183; any error</text>
<!-- logs -->
<rect x="398" y="323" width="264" height="42" rx="7" fill="#f7f0fe" stroke="#d9c2f5"/><rect x="398" y="323" width="5" height="42" rx="2.5" fill="#a142f4"/>
<text x="414" y="341" font-size="12.5" font-weight="700" fill="#202124">Log ship &#183; 60s</text>
<text x="414" y="357" font-size="10.5" fill="#5f6368">agent lines + <tspan font-family="'Roboto Mono',Menlo,Consolas,monospace">[sanadr1-logs]</tspan></text>
<!-- remote -->
<rect x="398" y="375" width="264" height="42" rx="7" fill="#fef4e5" stroke="#fadfa8"/><rect x="398" y="375" width="5" height="42" rx="2.5" fill="#f29900"/>
<text x="414" y="393" font-size="12.5" font-weight="700" fill="#202124">Remote register &#183; 60s</text>
<text x="414" y="409" font-size="10.5" fill="#5f6368">dashboard URL + <tspan font-family="'Roboto Mono',Menlo,Consolas,monospace">ssh unitree@ip</tspan></text>
</g>
<text x="530" y="437" text-anchor="middle" font-size="10.5" fill="#80868b">all three generated from agents/g1 &#183; gen_agents.py</text>
<!-- agent -> server arrows -->
<g stroke-width="2" marker-end="url(#arw)">
<line x1="680" y1="188" x2="736" y2="188" stroke="#1a73e8"/>
<line x1="680" y1="240" x2="736" y2="240" stroke="#34a853"/>
<line x1="680" y1="292" x2="736" y2="292" stroke="#ea4335"/>
<line x1="680" y1="344" x2="736" y2="344" stroke="#a142f4"/>
<line x1="680" y1="396" x2="736" y2="396" stroke="#f29900"/>
</g>
<!-- =============== SERVER =============== -->
<rect x="736" y="84" width="300" height="372" rx="12" fill="#ffffff" stroke="#5f6368" stroke-width="1.5"/>
<text x="886" y="110" text-anchor="middle" font-size="15" font-weight="700" fill="#202124">Fleet server</text>
<text x="886" y="129" text-anchor="middle" font-size="11.5" fill="#5f6368" font-family="'Roboto Mono',Menlo,Consolas,monospace">eco.yslootahrobotics.com</text>
<text x="886" y="148" text-anchor="middle" font-size="10.5" fill="#80868b">Authorization: Bearer &lt;token&gt; &#183; keyed by sn</text>
<g>
<rect x="754" y="167" width="264" height="42" rx="7" fill="#f1f6ff" stroke="#c6dafc"/>
<text x="768" y="185" font-size="11.5" font-weight="700" fill="#1a73e8" font-family="'Roboto Mono',Menlo,Consolas,monospace">POST /ingest/telemetry</text>
<text x="768" y="201" font-size="10.5" fill="#5f6368">every ~2s &#183; 27 fields</text>
<rect x="754" y="219" width="264" height="42" rx="7" fill="#f0faf3" stroke="#b7e1c4"/>
<text x="768" y="237" font-size="11.5" font-weight="700" fill="#188038" font-family="'Roboto Mono',Menlo,Consolas,monospace">POST /ingest/{sn}/map</text>
<text x="768" y="253" font-size="10.5" fill="#5f6368">on change &#183; PNG + resolution + origin</text>
<rect x="754" y="271" width="264" height="42" rx="7" fill="#fdecea" stroke="#f5c0ba"/>
<text x="768" y="289" font-size="11.5" font-weight="700" fill="#c5221f" font-family="'Roboto Mono',Menlo,Consolas,monospace">POST /ingest/{sn}/alert</text>
<text x="768" y="305" font-size="10.5" fill="#5f6368">on new fault (strings)</text>
<rect x="754" y="323" width="264" height="42" rx="7" fill="#f7f0fe" stroke="#d9c2f5"/>
<text x="768" y="341" font-size="11.5" font-weight="700" fill="#8430ce" font-family="'Roboto Mono',Menlo,Consolas,monospace">POST /ingest/{sn}/logs</text>
<text x="768" y="357" font-size="10.5" fill="#5f6368">every 60s &#183; ring-buffered lines</text>
<rect x="754" y="375" width="264" height="42" rx="7" fill="#fef4e5" stroke="#fadfa8"/>
<text x="768" y="393" font-size="11.5" font-weight="700" fill="#b06000" font-family="'Roboto Mono',Menlo,Consolas,monospace">POST /ingest/{sn}/remote</text>
<text x="768" y="409" font-size="10.5" fill="#5f6368">kind: web + ssh</text>
</g>
<text x="886" y="437" text-anchor="middle" font-size="10.5" fill="#80868b">also GET /ingest/{sn}/commands (+ ack)</text>
<!-- footer -->
<line x1="30" y1="474" x2="1030" y2="474" stroke="#e0e0e0"/>
<text x="30" y="492" font-size="11" fill="#80868b">No inbound port on the robot &#183; each robot type is its own Docker image &#183; installed &amp; managed over SSH by <tspan font-family="'Roboto Mono',Menlo,Consolas,monospace" fill="#5f6368">fleet_install.sh</tspan> &#183; user-level systemd auto-start, no sudo.</text>
</svg>