What this tool does
The Live Data Plotter listens to an MQTT topic over a WebSocket and draws numbers from each message onto a live time-series chart. It does not know anything about your payload format — you tell it how to pull the numbers out, using one regular expression and one short line of JavaScript per line on the chart.
Before you start
http://, never https://.
The broker on port 3000 has no TLS, so a secure page will silently
block the ws:// connection and nothing will ever arrive.
The plotter shows a yellow warning bar if you get this wrong.
- Use a current Chrome, Edge or Firefox.
- Your device must already be publishing to the broker. The plotter only reads — it never sends data to your device.
- Know your topic and roughly what your payload looks like. If you do not, connect first and read one off the console (step 2 below).
Quick start
-
Connect. Leave WebSocket URL as
ws://iperfect.net:3000, type your topic into Subscribe Topic, and press Connect & Subscribe. The pill top-right turns green and reads Connected. -
Look at one real message. The black console fills with
timestamped payloads. If it stays empty, your topic is wrong —
try a wildcard such as
Zone/#to see what is being published. Copy one payload; you need it for step 4. -
Name your chart lines. In Axis Configuration set
X-Axis data types to plot to how many lines you want and press
Apply. Give each one a name. Note the grey
highcharts.series[0]tag beside each — that is how you refer to it. -
Count your fields. Split the payload you copied on every comma
and pipe, then count from zero. That position is the number you
put in
regEx[…]. See How parsing works. - Set the expression count. In RegEx Configuration set Expressions to plot to 1 + one per line (three lines means four) and press Apply.
-
Row 1 splits the payload. Enter
/([^|,]+)/gand tick Is RegEx. -
The remaining rows plot. Leave Is RegEx unticked and enter
one line each, pointing at the field you counted in step 4:
highcharts.series[0].addPoint([dt,(regEx[4])*1],false) - Press Save Configuration. The page reloads with your settings in the address bar. Press Connect & Subscribe again and the chart starts drawing.
How parsing works
Every row in RegEx Configuration runs once per message, top to bottom. The Is RegEx tick is what decides how it runs:
| Is RegEx | What the row does |
|---|---|
| Ticked | The text is treated as a regular expression. The plotter
matches it against the payload and stores every match in the
regEx array. It draws nothing by itself. |
| Unticked | The text is treated as a line of JavaScript and executed
as written. This is where you call addPoint(). |
What you can use inside a row
| Name | Meaning |
|---|---|
data |
The payload of the message that just arrived. |
regEx |
The array produced by your Is RegEx row. Counts from zero. |
dt |
The time the message arrived, in milliseconds. Use it as the x-value of every point. |
highcharts |
The chart. highcharts.series[0] is your first named
line, [1] the second, and so on. |
Counting the index
/([^|,]+)/g means “every run of characters that is not a
comma or a pipe” — in other words, every field. Suppose a message
reads:
Zone,2340,e1:0b:6f:40:82:fb,17,1.42,-0.87,9.61|ok
Splitting it gives these positions:
So the three numbers you want are regEx[4],
regEx[5] and regEx[6]. Do this with a payload
copied from your own console — the layout above is only an
illustration of the counting.
Four rules worth remembering
- Put the Is RegEx row first. Rows run in order, so the array has to be filled before anything reads from it.
- Use only one Is RegEx row on this page. A second one replaces the first one's result. (The dev page lifts this limit.)
- End each addPoint with
,false. That skips a redraw per point; the chart redraws once after all rows have run, which keeps it smooth at high message rates. - Multiply by
1. Matches come out as text.(regEx[4])*1turns"1.42"into the number1.42. Without it the point plots as zero or not at all.
Worked example — three accelerometer axes
This is a complete, working configuration that plots AccelX, AccelY and AccelZ from a BLE zone sensor. Copy it field for field.
| Field | Value |
|---|---|
| WebSocket URL | ws://iperfect.net:3000 |
| Username / Password | left empty |
| Subscribe Topic | Zone/2340_e1:0b:6f:40:82:fb |
| X-Axis data types | 3 → named AccelX,
AccelY, AccelZ |
| Expressions to plot | 4 — one to split, three to plot |
| Expression 1 Is RegEx ticked | /([^|,]+)/g |
| Expression 2 | highcharts.series[0].addPoint([dt,(regEx[4])*1],false) |
| Expression 3 | highcharts.series[1].addPoint([dt,(regEx[5])*1],false) |
| Expression 4 | highcharts.series[2].addPoint([dt,(regEx[6])*1],false) |
Read it as: row 1 chops the message into fields; rows 2–4 take fields 5, 6 and 7 and push them onto the first, second and third line of the chart, stamped with the arrival time.
Field reference
Top bar
| Control | What it does |
|---|---|
| Status pill | Not Connected · Connecting · Connected · Error. The dot pulses while a connection is live. |
| Connect & Subscribe | Opens the WebSocket and subscribes to your topic. |
| Disconnect | Closes the connection. The chart keeps whatever it has drawn. |
| Help | Opens this guide. |
Connection strip
| Field | What it does |
|---|---|
| WebSocket URL | The broker. ws://iperfect.net:3000 unless you are
told otherwise. |
| Username / Password | Only if your broker demands them. Usually blank. |
| Subscribe Topic | The topic to listen on. + matches one level,
# matches the rest — Zone/# is a
good way to discover what is publishing. |
Chart and console
| Control | What it does |
|---|---|
| 1M / 5M / All | Show the last minute, last five minutes, or everything. |
| Legend | Click a name to hide or show that line. |
| Export menu (☰) | Save as PNG, JPEG, PDF or SVG, download CSV or XLS, or choose View data table to read the exact numbers. |
| Console | The last 500 payloads with arrival times. Green lines are status messages, red are errors. |
| Autoscroll / Clear | Untick autoscroll to hold position while reading; Clear empties the console and resets the counter. |
| Visible Series | Coloured chips, one per line. Click to hide or show it. |
Configuration
| Field | What it does |
|---|---|
| X-Axis data types | How many lines the chart has. Press Apply to get that many name boxes. |
| Expressions to plot | How many expression rows. Press Apply to get that many. |
| Is RegEx | Ticked = split the payload. Unticked = run as JavaScript. |
| Save Configuration | Applies everything and puts it in the URL. Edits do nothing until you press this. |
| Dump Parsed Data to Console | Prints the current regEx array to the browser
console (F12) so you can check your indices. |
Expression cookbook
Splitting rows — tick Is RegEx
| Payload looks like | Use |
|---|---|
12.5,13.1,9.8 |
/([^,]+)/g |
a,b,c|1.4,-0.8,9.6 |
/([^|,]+)/g |
X=1.4 Y=-0.8 Z=9.6 |
/=([-0-9.]+)/g |
| Any text, numbers only | /[-+]?[0-9]*\.?[0-9]+/g |
| Fields separated by spaces | /(\S+)/g |
Plotting rows — leave Is RegEx unticked
| Goal | Write |
|---|---|
| Plot field 5 on line 1 | highcharts.series[0].addPoint([dt,(regEx[4])*1],false) |
| Plot the last field | highcharts.series[0].addPoint([dt,(regEx[regEx.length-1])*1],false)
|
| Scale a value (mg → g) | highcharts.series[0].addPoint([dt,(regEx[4])/1000],false) |
| Plot a difference | highcharts.series[0].addPoint([dt,(regEx[4]*1)-(regEx[5]*1)],false)
|
| Payload is JSON | highcharts.series[0].addPoint([dt,JSON.parse(data.toString()).temp],false)
— no Is RegEx row needed at all |
Troubleshooting
| What you see | Why | Fix |
|---|---|---|
| Yellow bar about HTTPS, nothing connects | The page is on https://, which blocks
ws:// |
Reopen the same address with http:// |
| Status goes to Library Missing | The MQTT client script did not load | Check that iperfect.net:3000 is up; reload |
| Status sticks on Connecting | Broker unreachable, or the URL is wrong | Confirm the URL and that port 3000 is open from your network |
| Connected but the console stays empty | Nothing is published on that topic | Subscribe to Zone/# to see what exists, then narrow it |
| Console fills but the chart stays flat | Your regEx[…] indices point at the wrong
fields |
Recount from a real payload; use Dump Parsed Data to Console |
| Lines plot as 0 | The field is text, not a number | Add *1, and check you are not pointing at a label |
| Chart shows one point at 05:30 | The placeholder point every new line starts with | Normal. It disappears from view once real data arrives; use 1M or 5M |
| Edits appear to do nothing | Save Configuration was not pressed | Press it — the page reloads with the new settings |
| Chart area shows a red “library unavailable” box | Highcharts could not be downloaded | Check internet access to
code.highcharts.com or
cdn.jsdelivr.net |
| It slows down after a long run | Every point is kept in memory | Reload the page to start a fresh capture |
The dev page
basic_line_dev.php is the same tool with three extras. Use it
when the main page is not enough.
- External MQTT Host. Fill it in and the broker will bridge another broker's traffic onto your topic, so you can plot data from a machine the browser cannot reach directly.
- More than one Is RegEx row. Rows are written as
source>pattern, for exampledata>/([^|,]+)/g. Each ticked row gets its own slot: the first fillsregEx[0][…], the secondregEx[1][…]. Note the extra index compared with this page. - Errors are swallowed. A row that fails is skipped instead of stopping the rest, which is more forgiving while you experiment.
regEx[4] where the dev page uses
regEx[0][4].