<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://developer.remotivelabs.com/blog</id>
    <title>RemotiveLabs Developer Blog</title>
    <updated>2026-09-15T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://developer.remotivelabs.com/blog"/>
    <subtitle>RemotiveDocs - Guides, code samples &amp; more Blog</subtitle>
    <icon>https://developer.remotivelabs.com/img/favicon.ico</icon>
    <entry>
        <title type="html"><![CDATA[Playing back recordings]]></title>
        <id>https://developer.remotivelabs.com/blog/2026/09/15/playing-back-recordings</id>
        <link href="https://developer.remotivelabs.com/blog/2026/09/15/playing-back-recordings"/>
        <updated>2026-09-15T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Replaying a recorded drive in RemotiveStudio and RemotiveCLI, and why that helps with debugging, development and regression tests.]]></summary>
        <content type="html"><![CDATA[<p>A good recording of a drive is often the most useful test data you will ever have. With
RemotiveTopology you can play that recording back onto virtual buses and watch it in
RemotiveStudio, with the camera videos in sync. This post covers how to set that up and
what we use it for day to day.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-play-back-a-recording">Why play back a recording<a href="https://developer.remotivelabs.com/blog/2026/09/15/playing-back-recordings#why-play-back-a-recording" class="hash-link" aria-label="Direct link to Why play back a recording" title="Direct link to Why play back a recording">​</a></h2>
<p>Playback, also called open loop simulation, sends recorded vehicle data back onto the
channels of a running topology as if the vehicle were there. Three things make that useful:</p>
<ul>
<li><strong>Debugging.</strong> When something odd happens on a test drive, you can replay those 20
seconds as often as you like, pause on the frame where it goes wrong and look at it
next to the front camera video.</li>
<li><strong>Developing against real data.</strong> A behavioral model or an app that consumes signals
gets realistic input from a laptop, without a car or a test rig. You can also mix
recorded data with a running topology (closed loop simulation), for example by feeding
recorded GPS positions to an Android Automotive instance while the climate controls still
respond.</li>
<li><strong>Regression testing.</strong> The same recording gives the same input every time, so a test case
that runs against it in CI shows you when behavior changes.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="describe-the-drive-as-a-recording-session">Describe the drive as a recording session<a href="https://developer.remotivelabs.com/blog/2026/09/15/playing-back-recordings#describe-the-drive-as-a-recording-session" class="hash-link" aria-label="Direct link to Describe the drive as a recording session" title="Direct link to Describe the drive as a recording session">​</a></h2>
<p>Everything starts with a recording session: a YAML file with the session's start and end
time, the recording files, any video files, and a mapping from the recording equipment's
device names to the platform's channels. RemotiveTopology reads CAN dumps and CSV in long
format (timestamp, signal name, signal value). This example is taken from the docs:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">schema</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> remotive</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">recording</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">session</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">0.2</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Roundabout left turn</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">start_time</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 1753865338s</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">end_time</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 1753865361s</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">files</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">location</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ./candata.log</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> recording</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">location</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> front.mp4</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> front</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> video</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">start_time</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 1753865335s</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">mapping</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">includes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> ../equipment.mapping.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Some things to watch for:</p>
<ul>
<li>The mapping is what turns <code>can0</code> on the logger into <code>DriverCan</code> in your platform. If
the device names already match the channel names, you don't need one. If you keep the
mapping in its own file, several recordings made with the same equipment can share it.</li>
<li>Videos need a <code>name</code> (<code>front</code>, <code>rear</code> and so on). Dashboards pick videos by that name, so
one dashboard works for every session from the same car. Set the video's <code>start_time</code>
too: the camera rarely starts at the same moment as the logger. Use MP4 with H.264 and
AAC, since RemotiveStudio runs in a browser.</li>
<li>You can have several sessions that point at the same recording files, for example to
cut out the interesting part of a long drive.</li>
</ul>
<p>You don't have to write the file by hand: <code>remotive topology recording-session create -f candump.log</code> generates a session from one or more recording files, and <code>recording-session recalculate</code> updates its start and end time after you change file offsets. See
<a href="https://developer.remotivelabs.com/docs/remotive-topology/usage/recordings/concepts">Recording concepts</a>
for the details.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="start-a-topology-to-play-it-on">Start a topology to play it on<a href="https://developer.remotivelabs.com/blog/2026/09/15/playing-back-recordings#start-a-topology-to-play-it-on" class="hash-link" aria-label="Direct link to Start a topology to play it on" title="Direct link to Start a topology to play it on">​</a></h2>
<p>Playback needs a running topology instance whose platform has every channel the mapping
uses. The instance can have more channels than that, so a recording of only one bus works
too. To get a simple instance with default settings and no behavioral models, generate it
from the session, then build and run it:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">remotive topology recording-session instantiate roundabout.recordingsession.yaml playback.instance.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">remotive topology generate </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> playback.instance.yaml build</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> compose </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> build/</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">instance</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain">/docker-compose.yml </span><span class="token parameter variable" style="color:#36acaa">--profile</span><span class="token plain"> ui up</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>You don't need a new instance for every recording. If you recorded several drives with the
same platform, you can use one instance to play all of them. The
<a href="https://developer.remotivelabs.com/docs/remotive-topology/usage/recordings/usage">Usage</a> page
also shows how to add your own signals that aren't on the vehicle platform, such as emulated
GPS, through a CSV file and an extra channel.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="watch-it-in-remotivestudio">Watch it in RemotiveStudio<a href="https://developer.remotivelabs.com/blog/2026/09/15/playing-back-recordings#watch-it-in-remotivestudio" class="hash-link" aria-label="Direct link to Watch it in RemotiveStudio" title="Direct link to Watch it in RemotiveStudio">​</a></h2>
<p>Start RemotiveStudio in your workspace with <code>remotive studio .</code> and open a dashboard. The
<strong>Add Panel</strong> picker has two groups. Use <strong>Open recording</strong> from the recordings group
to load the session for playback, then add a <strong>Video</strong> panel for each camera. The
video stays in sync with the signal timeline. Next to them, add the chart panels you need: a
<strong>Time series</strong> for the signals you care about, a <strong>Trace</strong> for raw frames, a <strong>Map</strong> if the
recording has latitude and longitude, or a <strong>Frame distribution</strong> to see which frames
are sent most often.</p>
<p>One tip from experience: use only one dashboard tab. RemotiveStudio warns if it sees more
than one dashboard running, and you may find that playback controls stop responding or
videos don't play. The <a href="https://developer.remotivelabs.com/docs/remotive-studio/dashboard/add-panel">Add a panel</a>
page lists every panel type.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="control-playback-from-the-command-line">Control playback from the command line<a href="https://developer.remotivelabs.com/blog/2026/09/15/playing-back-recordings#control-playback-from-the-command-line" class="hash-link" aria-label="Direct link to Control playback from the command line" title="Direct link to Control playback from the command line">​</a></h2>
<p>The same controls are in RemotiveCLI, which is handy from a script or when you only want
to jump to the interesting moment. Offsets can be given in minutes, seconds, milliseconds
or microseconds:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">REMOTIVE_RECORDING_SESSION_PATH</span><span class="token operator" style="color:#393A34">=</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">recording session</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">remotive broker playback </span><span class="token function" style="color:#d73a49">open</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$REMOTIVE_RECORDING_SESSION_PATH</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">remotive broker playback play </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$REMOTIVE_RECORDING_SESSION_PATH</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--offset</span><span class="token plain"> 10s</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">remotive broker playback pause </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$REMOTIVE_RECORDING_SESSION_PATH</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">remotive broker playback seek </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$REMOTIVE_RECORDING_SESSION_PATH</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--offset</span><span class="token plain"> 15000ms</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">remotive broker playback repeat </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$REMOTIVE_RECORDING_SESSION_PATH</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> --start-offset 10s --end-offset 20s</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">remotive broker playback status </span><span class="token parameter variable" style="color:#36acaa">--stream</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><code>repeat</code> loops a part of the recording, which is useful while you change a behavioral
model and want the same few seconds over and over. Run it with <code>--clear</code> to stop the loop.
Every command takes <code>--url</code> if your broker isn't on <code>http://localhost:50051</code>. All
options are in the
<a href="https://developer.remotivelabs.com/docs/remotive-cli/cli_man_pages">RemotiveCLI manual</a>.</p>
<p>For regression tests, playback can also be controlled from code, for example from a test
case running in its own container in the topology, and the topology can be shut down when the tests
are done (see <a href="https://developer.remotivelabs.com/docs/remotive-topology/usage/running">Running</a>).
To try all of this without a recording of your own, the
<a href="https://developer.remotivelabs.com/docs/remotive-topology/usage/recordings/examples">examples</a>
include a Tesla Model 3 drive with two CAN buses and four camera videos.</p>]]></content>
        <author>
            <name>Ola Nilsson</name>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Sniffing CAN traffic and making sense of it]]></title>
        <id>https://developer.remotivelabs.com/blog/2026/09/03/sniffing</id>
        <link href="https://developer.remotivelabs.com/blog/2026/09/03/sniffing"/>
        <updated>2026-09-03T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Capture raw CAN traffic with candump, then decode it with a DBC in RemotiveTopology and RemotiveStudio.]]></summary>
        <content type="html"><![CDATA[<p>Plug into a CAN bus and you get a wall of hex: IDs, lengths and data bytes scrolling past faster
than you can read them. This post walks through how I capture that traffic on Linux, keep it in
a file, and turn it into named signals with a DBC using RemotiveTopology and RemotiveStudio.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-sniffing-gives-you">What sniffing gives you<a href="https://developer.remotivelabs.com/blog/2026/09/03/sniffing#what-sniffing-gives-you" class="hash-link" aria-label="Direct link to What sniffing gives you" title="Direct link to What sniffing gives you">​</a></h2>
<p>Sniffing means listening to a bus without taking part in it. You see every frame that ECUs send,
with timestamps, which is exactly what you want when you're asking questions like "does the BCM
actually send the turn signal frame when I flip the stalk?" or "how often does this frame show up?"</p>
<p>What you don't get from the wire is meaning. A CAN frame is an ID and up to 8 bytes (64 for CAN
FD). Which bits are vehicle speed, and how to scale them, lives in a signal database such as a
DBC. So sniffing is really two jobs: capture the raw frames, then decode them.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="setup-get-the-bus-onto-a-socketcan-interface">Setup: get the bus onto a SocketCAN interface<a href="https://developer.remotivelabs.com/blog/2026/09/03/sniffing#setup-get-the-bus-onto-a-socketcan-interface" class="hash-link" aria-label="Direct link to Setup: get the bus onto a SocketCAN interface" title="Direct link to Setup: get the bus onto a SocketCAN interface">​</a></h2>
<p>Everything below assumes Linux, because it relies on SocketCAN. Once your CAN adapter shows up as
a network interface, standard tooling such as <code>candump</code> from can-utils works against it. The
<a href="https://developer.remotivelabs.com/docs/remotive-topology/usage/instance">RemotiveTopology docs</a>
recommend giving the interface a name that matches your architecture rather than <code>can0</code>:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">ip</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">link</span><span class="token plain"> </span><span class="token builtin class-name">set</span><span class="token plain"> can0 name drivercan0</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>That small habit pays off later, when you have three adapters plugged in and need to remember
which one is on the driver CAN.</p>
<p>If the traffic you want to look at comes from containers, for example behavioral models in a
topology, <a href="https://developer.remotivelabs.com/docs/remotive-bus/configuration">RemotiveBus</a> can expose
it on the host. A <code>vcan</code> network with a <code>host_device</code> creates a virtual CAN interface on the host,
so you can sniff simulated traffic with the same tools you use on a real vehicle:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> vcan</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">device</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> mybus</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">host_device</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> myhostbus   </span><span class="token comment" style="color:#999988;font-style:italic"># Name of the virtual CAN interface to create on the host</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>To go the other way and let containers use a physical bus, use <code>type: can</code> with <code>host_device</code>
pointing at the adapter. Note that Docker appends a <code>0</code> to the device name inside the container.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="capturing-traffic">Capturing traffic<a href="https://developer.remotivelabs.com/blog/2026/09/03/sniffing#capturing-traffic" class="hash-link" aria-label="Direct link to Capturing traffic" title="Direct link to Capturing traffic">​</a></h2>
<p>With the interface up, start with a live look:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">candump drivercan0</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Once you've confirmed frames are flowing, log them to a file instead. <code>candump -l</code> writes a
<code>candump-&lt;date&gt;.log</code> file in the current directory, in the "CAN dump" format that both
RemotiveTopology and RemotiveCloud read. Drive the scenario you care about, then stop it with
Ctrl+C.</p>
<p>Before you do anything else with the log, check it with RemotiveCLI. If a colleague needs the
capture in another format, the same tool converts between <code>.log</code>, <code>.asc</code> and <code>.blf</code>:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">remotive tools can validate candump-2026-09-03_101500.log --print-to-terminal</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">remotive tools can convert candump-2026-09-03_101500.log drive.blf</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Both commands are described in the
<a href="https://developer.remotivelabs.com/docs/remotive-cli/cli_man_pages">RemotiveCLI reference</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="making-sense-of-what-you-captured">Making sense of what you captured<a href="https://developer.remotivelabs.com/blog/2026/09/03/sniffing#making-sense-of-what-you-captured" class="hash-link" aria-label="Direct link to Making sense of what you captured" title="Direct link to Making sense of what you captured">​</a></h2>
<p>Now for the decoding. In RemotiveTopology, the signal database belongs to a channel in your
platform. A DBC doesn't say which bus it describes, so you name the channel yourself
(<a href="https://developer.remotivelabs.com/docs/remotive-topology/usage/platform">platform docs</a>):</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">schema</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> remotive</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">topology</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">platform</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">0.15</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">channels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">DriverCan</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> can</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">database</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ../databases/driver_can.dbc</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Next, wrap the log in a recording session, and add a
<a href="https://developer.remotivelabs.com/docs/remotive-topology/usage/recordings/concepts">recording mapping</a>
that connects the interface name in the log to the platform channel:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">remotive topology recording-session create </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> candump-2026-09-03_101500.log drive.recordingsession.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">schema</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> remotive</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">recording</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">mapping</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">0.1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">devices</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">drivercan0</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> DriverCan</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>If you named the interface the same as the channel, you can skip the mapping: a default mapping
from same-name devices is created automatically. Then create an instance for playback, generate
it and start it with the UI profile, as described in
<a href="https://developer.remotivelabs.com/docs/remotive-topology/usage/recordings/usage">recordings usage</a>:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">remotive topology recording-session instantiate drive.recordingsession.yaml drive.instance.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">remotive topology generate </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> drive.instance.yaml build</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> compose </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> build/</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">instance</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain">/docker-compose.yml </span><span class="token parameter variable" style="color:#36acaa">--profile</span><span class="token plain"> ui up</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>In RemotiveStudio, the
<a href="https://developer.remotivelabs.com/docs/remotive-studio/topology/signal-view">Signal view</a> lists every
frame and signal in the DBC, with unit, factor/offset and named values, which is handy for
finding the signal you're after. Then build a dashboard with a few
<a href="https://developer.remotivelabs.com/docs/remotive-studio/dashboard/add-panel">panels</a>, with an <strong>Open
recording</strong> panel to play back the log:</p>
<ul>
<li><strong>Frame distribution</strong> shows which frames are on the bus and how often. A frame that's missing,
or one far more frequent than expected, is often the first clue.</li>
<li><strong>Trace</strong> is the decoded version of <code>candump</code>: timestamp, frame ID, frame name and raw bytes,
with signal values when you expand a row.</li>
<li><strong>Time series</strong> plots the signals themselves, so you can see that brake pedal position goes up
just before vehicle speed goes down.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="other-ways-to-look-at-the-same-data">Other ways to look at the same data<a href="https://developer.remotivelabs.com/blog/2026/09/03/sniffing#other-ways-to-look-at-the-same-data" class="hash-link" aria-label="Direct link to Other ways to look at the same data" title="Direct link to Other ways to look at the same data">​</a></h2>
<p>If you'd rather not set up a platform, you can upload the log to
<a href="https://developer.remotivelabs.com/docs/cloud/Project/Recordings">RemotiveCloud</a>, either by drag and
drop or with <code>remotive cloud recordings upload</code>. It matches the recording against the signal
databases in your project and suggests the best fit. And for Ethernet traffic between containers,
including SOME/IP, <a href="https://developer.remotivelabs.com/docs/remotive-topology/tools/wireshark">Edgeshark and Wireshark</a>
let you inspect each connection in a running topology.</p>
<p>Whichever route you take, the idea is the same: capture first, keep the raw log, and let the
signal database do the decoding. The log stays useful long after the drive is over.</p>]]></content>
        <author>
            <name>Ola Nilsson</name>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Running topologies in CI]]></title>
        <id>https://developer.remotivelabs.com/blog/2026/08/20/topologies-in-ci</id>
        <link href="https://developer.remotivelabs.com/blog/2026/08/20/topologies-in-ci"/>
        <updated>2026-08-20T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Start a RemotiveTopology in a GitHub Actions job, run pytest against it, and tear it down again.]]></summary>
        <content type="html"><![CDATA[<p>A topology that only runs on your laptop is a good start, but the real payoff comes when
every pull request spins it up, runs the tests and throws it away again. This post walks
through doing that in GitHub Actions: generate the topology, start it with a test container,
let pytest talk to the RemotiveBroker, and fail the build when a test fails.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="a-tester-container-in-the-instance">A tester container in the instance<a href="https://developer.remotivelabs.com/blog/2026/08/20/topologies-in-ci#a-tester-container-in-the-instance" class="hash-link" aria-label="Direct link to A tester container in the instance" title="Direct link to A tester container in the instance">​</a></h2>
<p>RemotiveTopology lets you add your own containers to an instance, next to the ECUs. The
nice part for CI is that a test runner can be one of them: it starts inside the topology,
on the same networks as everything else, and reaches the TopologyBroker by name. Put it
behind a <a href="https://developer.remotivelabs.com/docs/remotive-topology/usage/instance">profile</a> so it
only runs when you ask for it:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">containers</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">tester</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">profiles</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">tester</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">build</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">dockerfile</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ../../../python</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">runner.dockerfile</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">volumes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> ../tests</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">/app</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">working_dir</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> /app</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">command</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"pytest --broker_url=http://topology-broker.com:50051 -s -vv"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The Dockerfile only needs Python and your test dependencies: pytest, pytest-asyncio and the
<code>remotivelabs-topology</code> package. Profiles map straight to docker compose profiles, so the
tester stays out of the way when you start the topology without <code>--profile tester</code> to poke
at it by hand.</p>
<p>One thing to check before moving to a hosted runner: CAN channels default to RemotiveBus,
which needs to be installed on the host. If you don't need SocketCAN in CI, switch the
instance to UDP emulation, which works anywhere without extra setup:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">settings</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">can</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">default_driver</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> udp</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="writing-the-tests">Writing the tests<a href="https://developer.remotivelabs.com/blog/2026/08/20/topologies-in-ci#writing-the-tests" class="hash-link" aria-label="Direct link to Writing the tests" title="Direct link to Writing the tests">​</a></h2>
<p>Tests use the <a href="https://developer.remotivelabs.com/docs/remotive-topology/usage/apis">RemotiveTopology framework</a>,
the Python library you also write behavioral models with. A small <code>conftest.py</code> turns the
<code>--broker_url</code> option from the container command into a <code>BrokerClient</code> fixture. The default
points at <code>localhost:50051</code>, which is where the broker is forwarded when you run the topology
interactively, so the same tests run from your editor too:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># tests/conftest.py</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> pytest_asyncio</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> remotivelabs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">broker </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> BrokerClient</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">pytest_addoption</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">parser</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    parser</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">addoption</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"--broker_url"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> default</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"http://localhost:50051"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token decorator annotation punctuation" style="color:#393A34">@pytest_asyncio</span><span class="token decorator annotation punctuation" style="color:#393A34">.</span><span class="token decorator annotation punctuation" style="color:#393A34">fixture</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">broker_client</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">request</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">with</span><span class="token plain"> BrokerClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">url</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">config</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">getoption</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"--broker_url"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> client</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">yield</span><span class="token plain"> client</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>A test then subscribes to frames in a namespace (named <code>&lt;ECU&gt;-&lt;Channel&gt;</code>) and waits for the
signal values it expects. This one is adapted from the
<a href="https://developer.remotivelabs.com/apis/python/remotivelabs/topology" target="_blank" rel="noopener noreferrer">testing examples in the API docs</a>:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># tests/test_hazard_lights.py</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> remotivelabs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">broker </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> BrokerClient</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> remotivelabs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">topology</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">testing</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">frames </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> capture_frames</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">test_hazard_light_sequence</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">broker_client</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> BrokerClient</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">None</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">with</span><span class="token plain"> capture_frames</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">broker_client</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"HazardLightControlUnit-DriverCan0"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        frames</span><span class="token operator" style="color:#393A34">=</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"HazardLightButton"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> cap</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> cap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">wait_for_signal_values</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token string" style="color:#e3116c">"HazardLightButton"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token string" style="color:#e3116c">"HazardLightButton.HazardLightButton"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            values</span><span class="token operator" style="color:#393A34">=</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            timeout</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">5.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The tests are async, so set <code>asyncio_mode = auto</code> in your pytest configuration (or mark
them with <code>@pytest.mark.asyncio</code>). If you're unsure which namespaces exist, start the
topology and run <code>remotive broker signals namespaces --url http://localhost:50051</code>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="credentials-for-the-runner">Credentials for the runner<a href="https://developer.remotivelabs.com/blog/2026/08/20/topologies-in-ci#credentials-for-the-runner" class="hash-link" aria-label="Direct link to Credentials for the runner" title="Direct link to Credentials for the runner">​</a></h2>
<p>Running a topology checks your organization's RemotiveTopology subscription, and a CI job
shouldn't do that with someone's personal login. Create a
<a href="https://developer.remotivelabs.com/docs/remotive-topology/ci">service account</a> with the
RemotiveTopology Executor role instead:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">remotive cloud service-accounts create ci-runner </span><span class="token parameter variable" style="color:#36acaa">--role</span><span class="token plain"> org/topologyRunner </span><span class="token parameter variable" style="color:#36acaa">--project</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">project id</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">remotive cloud service-accounts tokens create --service-account ci-runner </span><span class="token parameter variable" style="color:#36acaa">--project</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">project id</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">remotive cloud auth print-access-token </span><span class="token parameter variable" style="color:#36acaa">--account</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">email </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">service</span><span class="token plain"> account</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">remotive cloud organizations list</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Store the token as a repository secret, <code>REMOTIVE_CLOUD_AUTH_TOKEN</code>, and the organization
uid as <code>REMOTIVE_CLOUD_ORGANIZATION</code>. If you run with a RemotiveBroker license file, keep it
out of the repository: store it as a secret too and point <code>REMOTIVEBROKER_LICENSE</code> at it.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-workflow">The workflow<a href="https://developer.remotivelabs.com/blog/2026/08/20/topologies-in-ci#the-workflow" class="hash-link" aria-label="Direct link to The workflow" title="Direct link to The workflow">​</a></h2>
<p>With that in place, the job is four steps: install the
<a href="https://developer.remotivelabs.com/docs/remotive-cli/installation">RemotiveCLI</a>, generate the
topology, start it with the tester profile, and clean up.</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># .github/workflows/topology-tests.yml</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Topology tests</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">on</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">pull_request</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">jobs</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">topology-tests</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">runs-on</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ubuntu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">latest</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">env</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">REMOTIVE_CLOUD_AUTH_TOKEN</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.REMOTIVE_CLOUD_AUTH_TOKEN </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">REMOTIVE_CLOUD_ORGANIZATION</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.REMOTIVE_CLOUD_ORGANIZATION </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">steps</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">uses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> actions/checkout@v4</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Install RemotiveCLI</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> pipx install remotivelabs</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">cli</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Generate topology</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> remotive topology generate </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">n mytopology </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">f topology/mytopology.instance.yaml build</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Run tests</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">          docker compose -f build/mytopology/docker-compose.yml --profile tester</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">          up --abort-on-container-exit --exit-code-from tester</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Clean up</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">if</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> always()</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> docker compose </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">f build/mytopology/docker</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">compose.yml </span><span class="token punctuation" style="color:#393A34">-</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">profile tester down</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><code>--abort-on-container-exit</code> is what makes this work in CI: when pytest finishes, the tester
container exits and docker compose stops the rest of the topology. Adding
<code>--exit-code-from tester</code>, a plain docker compose option, makes the step's exit code pytest's,
so a failing test fails the job. The <code>down</code> step runs even after a failure, so the runner is
left clean.</p>
<p>Generate runs on every job, and that's on purpose: the generated files are completely
overwritten each time, and any change to the platform or instance files needs a new
generate anyway. Don't commit <code>build/</code>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="when-it-goes-red">When it goes red<a href="https://developer.remotivelabs.com/blog/2026/08/20/topologies-in-ci#when-it-goes-red" class="hash-link" aria-label="Direct link to When it goes red" title="Direct link to When it goes red">​</a></h2>
<p>Most failures are easier to read in the container logs than in the pytest output alone. Add
a step with <code>if: failure()</code> that runs <code>docker compose -f build/mytopology/docker-compose.yml logs</code>
before the clean-up, and you get the behavioral models' and brokers' side of the story too.
The <a href="https://developer.remotivelabs.com/docs/remotive-topology/tools/docker">Docker tips</a> page has
more commands for following logs per service.</p>
<p>To reproduce locally, run the same <code>generate</code>, then start the topology without the tester
profile, as described in
<a href="https://developer.remotivelabs.com/docs/remotive-topology/usage/running">Running a topology</a>, and
run pytest from your editor against <code>localhost:50051</code>. Same tests, same topology, just with a
debugger attached.</p>]]></content>
        <author>
            <name>Ola Nilsson</name>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[A basic restbus, watched from a dashboard]]></title>
        <id>https://developer.remotivelabs.com/blog/2026/07/29/restbus-dashboard</id>
        <link href="https://developer.remotivelabs.com/blog/2026/07/29/restbus-dashboard"/>
        <updated>2026-07-29T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Simulate the rest of the network's periodic frames with a restbus, then change signal values while it runs and watch the result in a RemotiveStudio dashboard.]]></summary>
        <content type="html"><![CDATA[<p>An ECU on its own rarely behaves the way it does in the car. It expects to hear its
neighbors: periodic frames that say the ignition is on, the speed is zero, the doors are
closed. This post sets up a basic restbus that sends those frames for you, and a
RemotiveStudio dashboard where you can see them and change values while everything runs.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-a-restbus-is-for">What a restbus is for<a href="https://developer.remotivelabs.com/blog/2026/07/29/restbus-dashboard#what-a-restbus-is-for" class="hash-link" aria-label="Direct link to What a restbus is for" title="Direct link to What a restbus is for">​</a></h2>
<p>A restbus simulates "the rest of the bus": every frame your device under test expects
from ECUs that aren't there. Most of these frames are cyclic, so the simulation has to
keep sending them at the right cycle time, or the device starts logging timeouts and
falling back to safe states.</p>
<p>In RemotiveTopology this usually starts with an
<a href="https://developer.remotivelabs.com/docs/remotive-topology/concepts">ECU mock</a>. A mock is the
simpler alternative to a behavioral model: it doesn't decide anything on its own, it
just provides a restbus that emulates the ECU, and something else (often a test case,
today it's us) decides what it sends. If the code that controls a mock gets complicated,
that's a sign it should become a behavioral model instead.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="setting-up-the-restbus">Setting up the restbus<a href="https://developer.remotivelabs.com/blog/2026/07/29/restbus-dashboard#setting-up-the-restbus" class="hash-link" aria-label="Direct link to Setting up the restbus" title="Direct link to Setting up the restbus">​</a></h2>
<p>Start from a platform with a CAN channel, and instantiate the ECU you want to stand in
for with a mock. The
<a href="https://developer.remotivelabs.com/docs/remotive-topology/usage/instance">instance docs</a> use
a body controller on two CAN buses; mocking it on just one of them looks like this:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">schema</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> remotive</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">topology</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">instance</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">0.15</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">platform</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">includes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> ./topology.platform.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">ecus</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">BCM</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">mock</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">channels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        DriverCan0</span><span class="token punctuation" style="color:#393A34">:</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Leave out <code>channels</code> (<code>mock: {}</code>) to mock the ECU on every channel it is connected to.
Then generate the topology and start it in interactive mode, so it keeps running while
you work, as described in
<a href="https://developer.remotivelabs.com/docs/remotive-topology/usage/running">Running a topology</a>:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">remotive topology generate </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> mytopology.instance.yaml build</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> compose </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> build/mytopology/docker-compose.yml up</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The broker inside the topology is forwarded to <code>http://localhost:50051</code>. Each ECU's view
of a channel is a namespace named <code>&lt;ECU&gt;-&lt;Channel&gt;</code>, so here it's <code>BCM-DriverCan0</code>. If
you're unsure, list them:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">remotive broker signals namespaces </span><span class="token parameter variable" style="color:#36acaa">--url</span><span class="token plain"> http://localhost:50051</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Now tell the broker which frames to send. The
<a href="https://developer.remotivelabs.com/docs/remotive-cli/cli_man_pages#remotive-broker-restbus"><code>remotive broker restbus</code></a>
commands follow a simple workflow: add, start, update, and stop or reset. Pick a frame
from your signal database (the
<a href="https://developer.remotivelabs.com/docs/remotive-studio/topology/signal-view">signal view</a>
in RemotiveStudio is a quick way to browse them); <code>BodyStatus</code> below is a stand-in name:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">remotive broker restbus </span><span class="token function" style="color:#d73a49">add</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--frame</span><span class="token plain"> BCM-DriverCan0:BodyStatus --cycle-time </span><span class="token number" style="color:#36acaa">100</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">remotive broker restbus start </span><span class="token parameter variable" style="color:#36acaa">--namespace</span><span class="token plain"> BCM-DriverCan0</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><code>--cycle-time</code> is in milliseconds and overrides the cycle time from the database; leave
it out to use the database value. <code>add --start</code> registers and starts in one go.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="building-the-dashboard">Building the dashboard<a href="https://developer.remotivelabs.com/blog/2026/07/29/restbus-dashboard#building-the-dashboard" class="hash-link" aria-label="Direct link to Building the dashboard" title="Direct link to Building the dashboard">​</a></h2>
<p>Start RemotiveStudio on the workspace that holds your topology files, as in
<a href="https://developer.remotivelabs.com/docs/remotive-studio/getting-started">Getting started</a>:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">remotive studio </span><span class="token builtin class-name">.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <a href="https://developer.remotivelabs.com/docs/remotive-studio/dashboard">dashboard</a> needs a
running topology to connect to; without one it shows "RemotiveTopology unavailable".
<a href="https://developer.remotivelabs.com/docs/remotive-studio/dashboard/create-dashboard">Create a dashboard</a>
from the <strong>Topology</strong> sidebar panel, then use <strong>Add Panel</strong> to
<a href="https://developer.remotivelabs.com/docs/remotive-studio/dashboard/add-panel">add panels</a>.
For a restbus, three are useful:</p>
<ul>
<li><strong>Frame distribution</strong> shows which frames arrive and how often, so you can see at a
glance that the restbus is running and at roughly the cycle time you asked for.</li>
<li><strong>Trace</strong> shows each frame as it arrives, with its raw bytes, and the signal values
when you expand a row.</li>
<li><strong>Time series</strong> plots the signals you select, which is where you'll see your changes.</li>
</ul>
<p>Use the signal selection button to pick signals for the time series panel. A new
dashboard is a draft until you click <strong>Save As</strong>; it's then stored as a
<code>.dashboard.json</code> file in your workspace, so you can commit it next to the topology and
open it again from the <strong>Files</strong> sidebar.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="changing-values-while-it-runs">Changing values while it runs<a href="https://developer.remotivelabs.com/blog/2026/07/29/restbus-dashboard#changing-values-while-it-runs" class="hash-link" aria-label="Direct link to Changing values while it runs" title="Direct link to Changing values while it runs">​</a></h2>
<p>With frames flowing, change what the restbus sends. <code>update</code> sets the values it emits
from now on; give several comma-separated values and the restbus loops over them.
For example, a door signal that reads open on every fourth value:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">remotive broker restbus update </span><span class="token parameter variable" style="color:#36acaa">--signal</span><span class="token plain"> BCM-DriverCan0:DoorOpen:0,0,0,1</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Use <code>--initial</code> for values that should be sent once before the loop starts. The time
series panel follows along as soon as the new values go out, and the trace panel shows
what changed in the raw bytes. To pause, run <code>stop</code>; the configuration stays, so <code>start</code>
picks up where you left off. <code>remove --frame</code> drops a single frame, and <code>reset</code> clears
everything for a namespace.</p>
<p>Here the dashboard is the place you watch, and the terminal next to it is where you
turn the knobs. The same restbus can be controlled from code, too: the
<a href="https://developer.remotivelabs.com/docs/remotive-topology/usage/apis">RemotiveTopology framework</a>
is a Python library for writing test cases and behavioral models against the same
namespaces, which is where to go once a sequence of <code>update</code> commands starts to feel
like a script.</p>]]></content>
        <author>
            <name>Ola Nilsson</name>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Integrating an FMU with Python]]></title>
        <id>https://developer.remotivelabs.com/blog/2026/07/08/fmu-integration-python</id>
        <link href="https://developer.remotivelabs.com/blog/2026/07/08/fmu-integration-python"/>
        <updated>2026-07-08T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Run a Functional Mock-up Unit (FMU) as a behavioral model in RemotiveTopology, with a few lines of Python that map bus signals to FMU inputs and outputs.]]></summary>
        <content type="html"><![CDATA[<p>If someone on your team already models a system in a simulation tool, you probably don't want
to rewrite that model by hand as an ECU. With the <code>fmu</code> module in the RemotiveTopology Python
framework you can load the exported FMU, connect it to the signals on your virtual buses, and
run it as a behavioral model next to everything else in the topology.</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>TODO</div><div class="admonitionContent_BuS1"><p>Also needed in the docs: once this post is written, add (or link to) a matching how-to page under docs/remotive-topology.</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-an-fmu-is-and-when-you-would-use-one">What an FMU is and when you would use one<a href="https://developer.remotivelabs.com/blog/2026/07/08/fmu-integration-python#what-an-fmu-is-and-when-you-would-use-one" class="hash-link" aria-label="Direct link to What an FMU is and when you would use one" title="Direct link to What an FMU is and when you would use one">​</a></h2>
<p>A Functional Mock-up Unit is a packaged simulation model, following the FMI standard, that
many modeling tools can export. It's a zip file with a model description (the inputs,
outputs and default experiment settings) and the compiled model.</p>
<p>In RemotiveTopology, an FMU is one of the supported kinds of
<a href="https://developer.remotivelabs.com/docs/remotive-topology/concepts">behavioral model</a>, next to
plain Python and Synopsys Silver. A behavioral model emulates the behavior of a real ECU, so
an FMU is a good fit when the behavior you need already exists as a physics or control
model: vehicle dynamics, a battery, a thermal system, or the classic bouncing ball. Instead
of hard-coding values in a mock, the model reacts to what's on the bus and produces
realistic outputs.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="prerequisites">Prerequisites<a href="https://developer.remotivelabs.com/blog/2026/07/08/fmu-integration-python#prerequisites" class="hash-link" aria-label="Direct link to Prerequisites" title="Direct link to Prerequisites">​</a></h2>
<p>You need a working RemotiveTopology setup, as described in
<a href="https://developer.remotivelabs.com/docs/remotive-topology/install">Install</a>: Docker (or Podman),
RemotiveCLI with an active subscription, and Python 3.10 or later for behavioral models.</p>
<p>The FMU support lives in the <code>remotivelabs-topology</code> package behind an extra, since it pulls
in <code>fmpy</code> and <code>numpy</code>:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">pip </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> remotivelabs-topology</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">fmu</span><span class="token punctuation" style="color:#393A34">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Then the FMU itself. The framework drives the model one step at a time, so it needs to be:</p>
<ul>
<li>an FMI 2.0 or 3.0 <strong>Co-Simulation</strong> FMU,</li>
<li>configured with a fixed step size and no internal solver,</li>
<li>carrying a <code>defaultExperiment</code> in its model description (that's where the step size is read from).</li>
</ul>
<p>If the FMU doesn't support co-simulation or lacks a default experiment, loading it fails
with an error straight away, which is a nice early warning.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="loading-the-fmu-from-python">Loading the FMU from Python<a href="https://developer.remotivelabs.com/blog/2026/07/08/fmu-integration-python#loading-the-fmu-from-python" class="hash-link" aria-label="Direct link to Loading the FMU from Python" title="Direct link to Loading the FMU from Python">​</a></h2>
<p>The entry point is <code>FMUSimulation</code>. Give it a path, and it reads the model description,
instantiates the FMU and resets it to its initial state:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> pathlib </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> Path</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> remotivelabs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">topology</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">fmu </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> FMUSimulation</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">fmu </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> FMUSimulation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"speed_model.fmu"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">fmu</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">print</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># dump model information and variables</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">print</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">fmu</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">step_size</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">print</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">fmu</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">input_var_names</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">print</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">fmu</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">output_var_names</span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><code>print()</code> is the first thing I run on any new FMU: it shows the variable names you'll need
in the next step. The step size comes from the default experiment, but you can override it
with <code>FMUSimulation(path, step_size=0.01)</code>.</p>
<p>Each call to <code>await fmu.step()</code> advances the simulation by one step, applies the current
inputs and returns the outputs. You can also set an input directly with
<code>fmu.set_input_value("name", value)</code>; it sticks for all future steps, and an unknown name
raises a <code>ValueError</code>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="mapping-fmu-inputs-and-outputs-to-signals">Mapping FMU inputs and outputs to signals<a href="https://developer.remotivelabs.com/blog/2026/07/08/fmu-integration-python#mapping-fmu-inputs-and-outputs-to-signals" class="hash-link" aria-label="Direct link to Mapping FMU inputs and outputs to signals" title="Direct link to Mapping FMU inputs and outputs to signals">​</a></h2>
<p>The <code>FMUBehavioralModel</code> class connects an <code>FMUSimulation</code> to the topology. Inputs are
described with an <code>InputMapping</code>, a nested dictionary from namespace, to frame, to signal,
to FMU input name. Namespaces are named <code>&lt;ECU&gt;-&lt;Channel&gt;</code>, as described in
<a href="https://developer.remotivelabs.com/docs/remotive-topology/usage/instance">Instantiating a topology</a>.</p>
<p>In this example (the ECU, frame and variable names are made up), the FMU gets its
<code>accelerator_pedal</code> input from a signal on <code>ChassisCan0</code>:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> remotivelabs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">topology</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">fmu </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> InputMapping</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">input_mapping</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> InputMapping </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"SpeedModel-ChassisCan0"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string" style="color:#e3116c">"PedalStatus"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token string" style="color:#e3116c">"AcceleratorPedalPosition"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"accelerator_pedal"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Whenever a matching frame arrives, the model writes the signal value to the FMU input.
Values outside the signal's min and max from the signal database are ignored, so a bad
frame doesn't push the model into nonsense.</p>
<p>Outputs go the other way. <code>FMUSimulation</code> takes an <code>on_output</code> callback that runs after
every step with a dictionary of output values. A simple way to put them on the bus is to
let a restbus send the ECU's frames and update their signals from the callback:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> remotivelabs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">topology</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">namespaces </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> filters</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> remotivelabs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">topology</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">namespaces</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">can </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> CanNamespace</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> RestbusConfig</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">chassis_can </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> CanNamespace</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"SpeedModel-ChassisCan0"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    broker_client</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    restbus_configs</span><span class="token operator" style="color:#393A34">=</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">RestbusConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">filters</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">SenderFilter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ecu_name</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"SpeedModel"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">on_output</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">outputs</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> chassis_can</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">restbus</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">update_signals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"VehicleSpeed"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> outputs</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"vehicle_speed"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="running-it-as-part-of-a-topology">Running it as part of a topology<a href="https://developer.remotivelabs.com/blog/2026/07/08/fmu-integration-python#running-it-as-part-of-a-topology" class="hash-link" aria-label="Direct link to Running it as part of a topology" title="Direct link to Running it as part of a topology">​</a></h2>
<p>Putting it together, the model script looks much like any other behavioral model.
<code>run_forever()</code> starts a ticker at the FMU's step size, steps the simulation on every tick
and handles inputs and control requests at the same time:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> asyncio</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> pathlib </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> Path</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> remotivelabs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">broker </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> BrokerClient</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> remotivelabs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">topology</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">cli</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">behavioral_model </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> BehavioralModelArgs</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> remotivelabs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">topology</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">fmu </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> FMUBehavioralModel</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> FMUSimulation</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> remotivelabs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">topology</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">namespaces </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> filters</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> remotivelabs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">topology</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">namespaces</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">can </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> CanNamespace</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> RestbusConfig</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">args</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> BehavioralModelArgs</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">with</span><span class="token plain"> BrokerClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">url</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">args</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">url</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> auth</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">args</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">auth</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> broker_client</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        chassis_can </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> CanNamespace</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token string" style="color:#e3116c">"SpeedModel-ChassisCan0"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            broker_client</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            restbus_configs</span><span class="token operator" style="color:#393A34">=</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">RestbusConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">filters</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">SenderFilter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ecu_name</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"SpeedModel"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">on_output</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">outputs</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> chassis_can</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">restbus</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">update_signals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"VehicleSpeed"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> outputs</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"vehicle_speed"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        fmu </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> FMUSimulation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"speed_model.fmu"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> on_output</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">on_output</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">with</span><span class="token plain"> FMUBehavioralModel</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token string" style="color:#e3116c">"SpeedModel"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            fmu</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">fmu</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            input_mapping</span><span class="token operator" style="color:#393A34">=</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token string" style="color:#e3116c">"SpeedModel-ChassisCan0"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token string" style="color:#e3116c">"PedalStatus"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token string" style="color:#e3116c">"AcceleratorPedalPosition"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"accelerator_pedal"</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            broker_client</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">broker_client</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            namespaces</span><span class="token operator" style="color:#393A34">=</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">chassis_can</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> bm</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> bm</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">run_forever</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> __name__ </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"__main__"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    asyncio</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">run</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">BehavioralModelArgs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">parse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>A bonus you get for free: when the model receives a reboot request, it resets the FMU to its
initial state along with the restbuses, so a test can start every case from a known state.</p>
<p>In the instance file, the model is added to its ECU like any Python behavioral model:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">ecus</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">SpeedModel</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">models</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">speed_model</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> python</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">include</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ../ecus</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">main</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> speed_model</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The container that runs Python models needs the <code>fmu</code> extra installed, so add it to the
image or Dockerfile you configure under <code>settings.docker.python</code>. Then generate and start the
topology as usual:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">remotive topology generate </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> mytopology.instance.yaml build</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> compose </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> build/mytopology/docker-compose.yml up</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>If the signals don't show up, check the namespace names first:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">remotive broker signals namespaces </span><span class="token parameter variable" style="color:#36acaa">--url</span><span class="token plain"> http://localhost:50051</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="where-to-go-next">Where to go next<a href="https://developer.remotivelabs.com/blog/2026/07/08/fmu-integration-python#where-to-go-next" class="hash-link" aria-label="Direct link to Where to go next" title="Direct link to Where to go next">​</a></h2>
<ul>
<li><a href="https://developer.remotivelabs.com/docs/remotive-topology/usage/instance">Instantiating a topology</a>: behavioral models, mocks and Docker settings.</li>
<li><a href="https://developer.remotivelabs.com/docs/remotive-topology/usage/running">Running a topology</a>: generating, interactive mode and running tests.</li>
<li><a href="https://developer.remotivelabs.com/docs/remotive-topology/usage/apis">API and client library</a>: the full Python API reference, including the <code>fmu</code> module.</li>
<li><a href="https://developer.remotivelabs.com/docs/remotive-topology/usage/examples">Examples</a>: the examples repository, a good place to start from a working setup.</li>
</ul>]]></content>
        <author>
            <name>Albin Theander</name>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Named values in RemotiveStudio and Python]]></title>
        <id>https://developer.remotivelabs.com/blog/2026/06/24/named-values-studio-python</id>
        <link href="https://developer.remotivelabs.com/blog/2026/06/24/named-values-studio-python"/>
        <updated>2026-06-24T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[What named values are, where to find them in RemotiveStudio, and how to read and write them from Python.]]></summary>
        <content type="html"><![CDATA[<p>A gear lever signal that reads <code>3</code> doesn't tell you much. Your signal database usually
knows that <code>3</code> means <code>DRIVE</code>, and RemotiveStudio and the Python libraries can use that
knowledge. This post shows where named values live and how to work with them in both.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-named-values-are">What named values are<a href="https://developer.remotivelabs.com/blog/2026/06/24/named-values-studio-python#what-named-values-are" class="hash-link" aria-label="Direct link to What named values are" title="Direct link to What named values are">​</a></h2>
<p>Many signals don't carry a measurement. They carry a state: a door is open or closed, a
gear is in park or drive, a lamp is off, on or failing. On the bus these states are plain
integers, and the signal database maps each integer to a name. In a DBC file this is the
value table for the signal; ARXML and LDF have their own ways of describing the same thing.
Think of it as an enum attached to a signal.</p>
<p>RemotiveLabs calls these mappings <strong>named values</strong>. They come straight from the signal
databases your topology references (DBC, ARXML, LDF, Fibex, see the
<a href="https://developer.remotivelabs.com/docs/remotive-studio/topology">supported file formats</a>), so
you don't define them anywhere else. If the database has them, you can use them.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="finding-named-values-in-remotivestudio">Finding named values in RemotiveStudio<a href="https://developer.remotivelabs.com/blog/2026/06/24/named-values-studio-python#finding-named-values-in-remotivestudio" class="hash-link" aria-label="Direct link to Finding named values in RemotiveStudio" title="Direct link to Finding named values in RemotiveStudio">​</a></h2>
<p>The quickest way to see what a database defines is the
<a href="https://developer.remotivelabs.com/docs/remotive-studio/topology/signal-view">Signal view</a> in
RemotiveStudio:</p>
<ol>
<li>Open the file tree with <strong>Files</strong> and click your <code>.instance.yaml</code>, <code>.platform.yaml</code>, or
a database file directly.</li>
<li>Click the bar-chart icon in the segmented control at the top of the topology viewer.</li>
<li>Find the frame you care about. The search bar filters both frames and signals.</li>
<li>Click the frame row to expand its signals. Each signal shows its unit, min/max, factor
and offset, receivers, and its named values.</li>
</ol>
<p>The first time you open the Signal view, RemotiveStudio indexes the signal databases, so
give it a moment on large ARXML files. Today the Signal view covers CAN and LIN signals.</p>
<p>This is also a good way to check a database before you write code against it. If you
expect <code>GearPosition</code> to have named values and the Signal view shows none, the database
you're using doesn't have them, and no code will fix that.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="reading-named-values-from-python">Reading named values from Python<a href="https://developer.remotivelabs.com/blog/2026/06/24/named-values-studio-python#reading-named-values-from-python" class="hash-link" aria-label="Direct link to Reading named values from Python" title="Direct link to Reading named values from Python">​</a></h2>
<p>The <a href="https://developer.remotivelabs.com/apis/python/remotivelabs/broker" target="_blank" rel="noopener noreferrer">RemotiveBroker Python API</a>
exposes the mapping on every <code>SignalInfo</code> in two directions: <code>named_values</code> maps raw
integers to names, and <code>value_names</code> maps names back to integers. Here is a small script,
adapted from the API docs, that prints both for one signal. The <code>DriverCan</code> namespace and
the <code>GearData.GearPosition</code> signal are examples; use your own.</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> asyncio</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> remotivelabs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">broker </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> BrokerClient</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">None</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">with</span><span class="token plain"> BrokerClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">url</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"http://127.0.0.1:50051"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> broker_client</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        info </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> broker_client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">get_signal_info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"GearData.GearPosition"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"DriverCan"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> info </span><span class="token keyword" style="color:#00009f">is</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">None</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">raise</span><span class="token plain"> SystemExit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Signal not found in DriverCan"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">print</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">info</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">named_values</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># raw value -&gt; name, e.g. {0: "PARK", 3: "DRIVE"}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">print</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">info</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">value_names</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic"># name -&gt; raw value, e.g. {"PARK": 0, "DRIVE": 3}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> __name__ </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"__main__"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    asyncio</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">run</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>If you're not sure which namespaces exist on a running topology, list them first:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">remotive broker signals namespaces </span><span class="token parameter variable" style="color:#36acaa">--url</span><span class="token plain"> http://localhost:50051</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>When you subscribe, you can have the client decode values for you. Pass
<code>decode_named_values=True</code> to <code>subscribe_frames</code>, and integer values that have a mapping
arrive as their names in <code>frame.signals</code>:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">stream </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> broker_client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">subscribe_frames</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"DriverCan"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"GearData"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    decode_named_values</span><span class="token operator" style="color:#393A34">=</span><span class="token boolean" style="color:#36acaa">True</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> frame </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> stream</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">print</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">frame</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">signals</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># {"GearData.GearPosition": "DRIVE", ...}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>To write a state, look up the raw value with <code>value_names</code> and publish that integer:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> remotivelabs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">broker </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> WriteSignal</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> broker_client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">publish</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"DriverCan"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">WriteSignal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">name</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"GearData.GearPosition"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> value</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">info</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">value_names</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"PARK"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The same lookup works when you set restbus signals with <code>RestbusSignalConfig.set(...)</code>.
If you write behavioral models or tests with the
<a href="https://developer.remotivelabs.com/docs/remotive-topology/usage/apis">RemotiveTopology framework</a>,
you're using the same broker client underneath, so <code>SignalInfo.named_values</code> and
<code>value_names</code> are available there too.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="common-pitfalls">Common pitfalls<a href="https://developer.remotivelabs.com/blog/2026/06/24/named-values-studio-python#common-pitfalls" class="hash-link" aria-label="Direct link to Common pitfalls" title="Direct link to Common pitfalls">​</a></h2>
<ul>
<li><strong>The value type changes.</strong> With <code>decode_named_values=True</code>, a signal that used to be an
<code>int</code> becomes a <code>str</code>. Code that compares with <code>== 3</code> or does arithmetic on the value
silently stops matching. Pick one style per script and stick to it.</li>
<li><strong>Not every value has a name.</strong> Only integers that appear in the mapping are decoded.
A value outside the table, such as a reserved or error code, still arrives as an <code>int</code>,
so handle both types, or look values up yourself with <code>info.named_values.get(value, value)</code>.</li>
<li><strong>Decoding is off by default.</strong> <code>subscribe_frames</code> doesn't decode unless you ask, and
the frame handlers in the RemotiveTopology framework take a <code>decode_named_values</code>
argument that is also off by default. If you see numbers where you expected names,
check this first.</li>
<li><strong>Names belong to a database.</strong> Two databases can map the same signal differently, for
example a channel DBC and an ECU extract. Check the Signal view for the topology you
actually run, and look names up with <code>value_names</code> instead of hard-coding the integers.</li>
<li><strong>Typos fail late.</strong> <code>info.value_names["Park"]</code> raises a <code>KeyError</code> when the database says
<code>PARK</code>. Copy names from the Signal view rather than from memory.</li>
</ul>
<p>Named values are a small feature, but they make logs, dashboards and test assertions much
easier to read. For more on the APIs, see
<a href="https://developer.remotivelabs.com/docs/remotive-broker/apis">APIs and client libraries</a>.</p>]]></content>
        <author>
            <name>Ola Nilsson</name>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Visualizing a topology, platform and instance]]></title>
        <id>https://developer.remotivelabs.com/blog/2026/06/10/topology-visualization</id>
        <link href="https://developer.remotivelabs.com/blog/2026/06/10/topology-visualization"/>
        <updated>2026-06-10T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[A worked example of looking at a RemotiveTopology platform and an instance built from it, with the CLI and in RemotiveStudio.]]></summary>
        <content type="html"><![CDATA[<p>When a topology grows past a handful of files, it gets hard to say what's actually in it.
Which ECUs does that DBC bring in? What does the instance run in the end? This post walks
through a small example and shows two ways to see the answer: <code>remotive topology show</code> in
the terminal, and the topology viewer in RemotiveStudio.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-example-topology">The example topology<a href="https://developer.remotivelabs.com/blog/2026/06/10/topology-visualization#the-example-topology" class="hash-link" aria-label="Direct link to The example topology" title="Direct link to The example topology">​</a></h2>
<p>We start with a platform that has two CAN channels, each described by a DBC file. DBC files
don't say which channel they describe, so the platform file names the channels and points
each one at its database:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># topology.platform.yaml</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">schema</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> remotive</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">topology</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">platform</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">0.15</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">channels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">DriverCan0</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> can</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">database</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ../databases/driver_can.dbc</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">BodyCan0</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> can</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">database</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ../databases/body_can.dbc</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>That's the whole file, but it describes more than it seems to. The ECUs come from the DBCs:
SCCM and BCM are on <code>DriverCan0</code>, and BCM, DIM, FLCM, RLCM and GWM are on <code>BodyCan0</code>. BCM
sits on both buses.</p>
<p>On top of that we write an instance, which says which part of the platform to run. Here we
want BCM with a Python behavioral model, and FLCM as a mock:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># main.instance.yaml</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">schema</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> remotive</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">topology</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">instance</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">0.15</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">platform</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">includes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> ./topology.platform.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">ecus</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">BCM</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">models</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">bcm</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> python</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">include</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ../ecus</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">main</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> bcm</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">FLCM</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">mock</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="looking-at-it-from-the-terminal">Looking at it from the terminal<a href="https://developer.remotivelabs.com/blog/2026/06/10/topology-visualization#looking-at-it-from-the-terminal" class="hash-link" aria-label="Direct link to Looking at it from the terminal" title="Direct link to Looking at it from the terminal">​</a></h2>
<p>Before opening any UI, I like to ask the CLI what it sees. Both files live in <code>topology/</code>,
next to <code>databases/</code> and <code>ecus/</code>. Set up a workspace at the root of the project first, so
relative includes like <code>../databases</code> resolve the same way from every subfolder:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token builtin class-name">cd</span><span class="token plain"> my_project</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">remotive topology workspace init</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Then show the platform:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">remotive topology show platform topology/topology.platform.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This prints the platform as <code>platform.yaml</code>, with everything the DBCs added filled in.
Each ECU lists the channels it's connected to, and each ECU channel gets a <code>database</code> too,
because that's the database the ECU uses to decode signals. If an ECU name isn't what you
expected, this is where you find out, before you write an instance that refers to it.</p>
<p>For the instance, use <code>show instance</code>:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">remotive topology show instance topology/main.instance.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This shows only the parts of the platform that are instantiated, plus any defaults that
were applied. In our case, SCCM, DIM, RLCM and GWM are gone. BCM keeps both channels,
because by default an ECU gets every channel it's connected to. FLCM's mock covers every
channel FLCM is on, which here is just <code>BodyCan0</code>.</p>
<p>A few options are handy here:</p>
<ul>
<li><code>--full-platform</code> shows the full platform, not just the instance-specific parts.</li>
<li><code>--check</code> checks the topology.</li>
<li><code>--json</code> switches the output from YAML to JSON, and <code>-o</code> writes it to a file, which is
useful if you want to diff the resolved instance between two branches.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="opening-it-in-remotivestudio">Opening it in RemotiveStudio<a href="https://developer.remotivelabs.com/blog/2026/06/10/topology-visualization#opening-it-in-remotivestudio" class="hash-link" aria-label="Direct link to Opening it in RemotiveStudio" title="Direct link to Opening it in RemotiveStudio">​</a></h2>
<p>YAML is precise, but a tree is quicker to read. RemotiveStudio comes with RemotiveCLI and
starts from the same workspace:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">remotive studio </span><span class="token builtin class-name">.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Open <strong>Files</strong> in the sidebar and click <code>topology.platform.yaml</code>. The topology viewer has
three modes, chosen with the segmented control at the top:</p>
<ul>
<li><strong>Tree view</strong> shows the platform as two top-level groups, <strong>Channels</strong> and <strong>ECUs</strong>.
Expand <code>BodyCan0</code> to see the five ECUs on it, or expand BCM to see that it's on both
buses. Click a node to open its details, such as channel type, database path and
connected ECUs.</li>
<li><strong>YAML view</strong> shows the resolved topology, with includes merged. It's read-only, and
roughly what <code>remotive topology show platform</code> prints.</li>
<li><strong>Signal view</strong> is a searchable table of every frame in the topology's CAN and LIN
databases. Click a frame to see its signals, with units, min and max values, receivers
and named values.</li>
</ul>
<p>Now open <code>main.instance.yaml</code>. The instance tree has the same channels and ECUs, cut down
to what the instance runs, and adds instance-level entries such as the <code>bcm</code> behavioral
model. Comparing the two trees side by side is the fastest way I know to check that an
instance contains what I meant it to.</p>
<p>Studio opens DBC, ARXML, LDF and Fibex files directly too, by converting them to
<code>.platform.yaml</code> first. Clicking an ECU extract is a quick way to see what's in it
before you include it anywhere.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="tips-for-larger-platforms">Tips for larger platforms<a href="https://developer.remotivelabs.com/blog/2026/06/10/topology-visualization#tips-for-larger-platforms" class="hash-link" aria-label="Direct link to Tips for larger platforms" title="Direct link to Tips for larger platforms">​</a></h2>
<p>Real platforms are rarely one file. They're usually a top-level <code>platform.yaml</code> that
includes subsystems:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">schema</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> remotive</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">topology</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">platform</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">0.15</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">includes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> ./lighting.platform.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> ./climate.platform.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> ./driver.platform.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Some things that help when there are many of them:</p>
<ul>
<li>Show each subsystem on its own first. If <code>lighting.platform.yaml</code> looks right by itself,
you've narrowed down where a problem in the combined platform can be.</li>
<li>Use the tree view's search bar instead of expanding everything. "Collapse all" helps
when you've lost track.</li>
<li>Studio doesn't pick up edits to topology files until you reload the browser tab. The CLI
always reads the files fresh, so it's the better choice while you're editing.</li>
<li>If a command complains about a missing ECU, run <code>show platform</code> on the file that should
define it. It's often a spelling difference between two databases.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="where-to-go-next">Where to go next<a href="https://developer.remotivelabs.com/blog/2026/06/10/topology-visualization#where-to-go-next" class="hash-link" aria-label="Direct link to Where to go next" title="Direct link to Where to go next">​</a></h2>
<ul>
<li><a href="https://developer.remotivelabs.com/docs/remotive-topology/usage/platform">Describing the platform</a>: DBC, ARXML, LDF and <code>platform.yaml</code> includes.</li>
<li><a href="https://developer.remotivelabs.com/docs/remotive-topology/usage/instance">Instantiating topology</a>: choosing ECUs and channels, models and mocks.</li>
<li><a href="https://developer.remotivelabs.com/docs/remotive-studio/topology">Topology in RemotiveStudio</a> and its <a href="https://developer.remotivelabs.com/docs/remotive-studio/topology/tree">tree view</a>.</li>
<li><a href="https://developer.remotivelabs.com/docs/remotive-topology/workspace">Workspace</a> and the <a href="https://developer.remotivelabs.com/docs/remotive-cli/cli_man_pages#remotive-topology-show"><code>remotive topology show</code> reference</a>.</li>
</ul>]]></content>
        <author>
            <name>Filip Åhfelt</name>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Welcome to the RemotiveLabs developer blog]]></title>
        <id>https://developer.remotivelabs.com/blog/2026/05/27/welcome</id>
        <link href="https://developer.remotivelabs.com/blog/2026/05/27/welcome"/>
        <updated>2026-05-27T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Short, technical articles from the people building RemotiveLabs.]]></summary>
        <content type="html"><![CDATA[<p>This is where the RemotiveLabs team writes short, technical articles: worked examples,
patterns we use ourselves, and the things that didn't fit in the
<a href="https://developer.remotivelabs.com/">documentation</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-to-expect">What to expect<a href="https://developer.remotivelabs.com/blog/2026/05/27/welcome#what-to-expect" class="hash-link" aria-label="Direct link to What to expect" title="Direct link to What to expect">​</a></h2>
<p>Posts are hands-on and to the point. Expect topics like connecting simulation models to a
topology, working with signals from Python, and building dashboards in RemotiveStudio.</p>
<p>When a post covers something you'll come back to, we link to the matching page in the
docs, which is where the reference material lives.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="code-not-slides">Code, not slides<a href="https://developer.remotivelabs.com/blog/2026/05/27/welcome#code-not-slides" class="hash-link" aria-label="Direct link to Code, not slides" title="Direct link to Code, not slides">​</a></h2>
<p>Most posts include code you can copy and run:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">remotive </span><span class="token parameter variable" style="color:#36acaa">--help</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>If you build something with RemotiveLabs and want to share it, reach out on
<a href="https://github.com/remotivelabs" target="_blank" rel="noopener noreferrer">GitHub</a>.</p>]]></content>
        <author>
            <name>Ola Nilsson</name>
        </author>
    </entry>
</feed>