Build P&IDs into your HMI with VS Code: the Nautilus mimic editor

P&ID Mimic Diagrams in VS Code

Companion post for the week-6 video. The tour covers the same ground on screen, including the whole build at 4× speed: watch it here.

This week we demonstrated drawing the heated surge tank from the earlier videos as a P&ID in VS Code, with live values from the running controller, and then putting the same file on a SvelteKit page as the HMI.

A diagram is a file in the project

The mimic editor is a VS Code webview. The diagram it edits is heated-tank.mimic.json, and it sits in the project beside nautilus.yaml and the PLC programs, so it's versioned in git with them.

The editor draws the diagram with the same Svelte components the HMI uses at runtime. What you see while you draw is what the operator will see.

The whole diagram from a blank canvas

The video builds the complete P&ID in one take, from a blank canvas. It's about five and a half minutes of real work, shown at four times speed:

  • Drop the equipment from the library and name it: pump P-101, tank T-101, valve DV-101.
  • Draw the four pipes by clicking from one port to another: the city water supply into the pump, the fill line to the tank, the draw off the tank, and the line out to process.
  • Bind each piece to a tag. P-101's running state is PumpRun, and T-101 shows LevelPct, TempC and Heater. Each piece is live as soon as it's bound.
  • Add three gauges (level, temperature with its setpoint, and heater output) and the two off-page labels.

Halfway through the build: equipment placed, pipes drawn port to port

The finished tank, live

With the controller running, the values move through the whole diagram. The tank drains to process, the pump seals in at 40 % level and fills it, and the pump drops out again at 75 %. The level and temperature gauges move with it.

Named ports

Every piece of equipment in the library has named ports. The pump has an inlet and an outlet, and the tank has four nozzles. Open a piece of equipment's ports and they're listed by name, each with the direction a pipe leaves it, so a pipe attaches to a specific point on the equipment instead of somewhere near it.

The pump's ports, in and out, listed by name beside the drawing

Move the equipment, keep the pipes

Those attachments are anchors. In the video I drag the pump to a new spot while the process runs. Its supply and fill pipes are still on its ports afterwards, the runs are still square, and the values keep moving the whole time.

The fill line keeps the bends it was drawn with, so the move leaves it with an extra jog. One click on Re-route gives you a fresh path between the same two ports.

The pump moved while it runs, its pipes still on its ports

The HMI is a SvelteKit app

The same project has an hmi/ folder with a SvelteKit app in it, and the controller serves the built app (server: hmi: ./hmi/build in nautilus.yaml). The page imports the diagram file and renders it with one component:

<script lang="ts">
	import {
		Mimic,
		createRealtimeClient,
		type MimicDoc
	} from '@joyautomation/nautilus-hmi';
	import '@joyautomation/nautilus-hmi/theme.css';
	import { onMount } from 'svelte';
	import tank from '../../../heated-tank.mimic.json';
	import Pump from '$lib/Pump.svelte';

	const rt = createRealtimeClient({
		url: '/api/stream'
	});
	onMount(() => (rt.start(), () => rt.stop()));
	const doc = tank as MimicDoc;
	const registry = { Pump };
	const tags = $derived(rt.frame?.tags ?? {});
</script>

<main>
	<h1>Heated surge tank</h1>
	<Mimic {doc} {tags} {registry} />
</main>

The diagram in the browser is the one drawn in the editor, with the same live values.

The tank, the pump and the valve are each a component, and a component is a file. This app carries its own src/lib/Pump.svelte and hands it to <Mimic>, so the pump on that page is drawn by a file in the app: JavaScript for what it does, HTML for what's drawn, and CSS for how it looks. It's similar to a template in Ignition or another SCADA package, except it's a file in your project that you can read, change, or replace with your own.

Because the HMI is a web app, it also gets the tools web teams use every day: version control, unit and end-to-end tests, and CI/CD.

+page.svelte beside the running SvelteKit app, the same tank live

What's next

That's the approach: the HMI is a SvelteKit app you own, and to make it quicker to build, we're adding editors to VS Code for authoring its components, like this one for P&IDs. I'd like to do the same for conveyors, networks and electrical one-lines.

How do you feel about building your HMI with a web framework, and what components would you want to see?

Next week is a detour into Rockwell, with sixty Logix projects converted to text.

Nautilus is open source, Apache-2.0. If you'd like help with your own plant, start with a Control System Assessment: a fixed-price review that ends in a written report you keep either way.

HMI docs: nautilus.joyautomation.com/reference/hmi · Repo: github.com/joyautomation/nautilus

Subscribe to the weekly newsletter to keep up to date: joyautomation.com/newsletter