Support reference FSE23204 / #16460. These tools were built to diagnose a
QuickServer that enters an ERROR state within seconds of an OPW SiteSentinel Nano console being
connected. Everything below is in service of finding out what that console sends that the driver
does not expect.
3.4.0 2026-09-11current
Changed — wiring guidance now covers four console families
- Wiring and console setup is now tabbed by console type.
OPW SiteSentinel Nano opens by default, followed by Veeder-Root TLS-350,
Veeder-Root TLS-450 and Other console. The serial protocol is common to all of
them; the connector, the settings screen and the indicators are not, and presenting one
console’s wiring as though it were universal was misleading.
- Veeder-Root TLS-300, TLS-350 and TLS-350R. The port is a 25-pin D-connector on
the bottom left, panel-mount female, wired as DTE. Since a USB adapter is also DTE, a null modem
cable is required and a straight-through cable produces silence. Diagram, pinout for data and
ground, the front panel character format options, and the DIP switch on the CPU board whose
second position enables the RS-232 security code. Sourced from Veeder-Root part 576013-635.
- Veeder-Root TLS-450 and TLS-450PLUS. A 9-pin D-connector, also DTE, also
needing a null modem cable. Full connector pinout, the wider baud range, and a warning that this
console is commonly set to 7 data bits with odd parity rather than the TLS-350’s 8 and none.
Also notes that not every slot and port can be an RS-232 serial port. Sourced from Veeder-Root
part 577013-950.
- Other console. A generic route for any panel speaking this protocol: finding
the port, working out whether a null modem cable is needed, connecting the signal ground, and
three quick checks that narrow a fault down without a capture.
- Both Veeder-Root tabs record that these consoles do not echo received characters, so a reply
that is a copy of the request cannot have come from the console.
- The tab strip is a proper tablist. Arrow keys, Home and End move between tabs, and it wraps to
multiple rows on a phone without the page scrolling sideways.
3.3.0 2026-09-11
Added — wiring and console setup, on the page itself
- New section: Wiring and console setup. Three collapsible references, placed
before step 1 so they are available before anything is connected. Written for the OPW SiteSentinel
Nano and boards that share its layout.
- Wiring the RS-232 connection. A diagram of the console’s RJ45 socket wired
to a DB9 adapter, the pinout, the Cat5 colour mapping for T568B, and a table matching each symptom
this tool reports to its usual cause in the wiring. The RS-232 port is an RJ45 socket on this
console, which surprises people who go looking for a D-sub.
- The ground fault is called out specifically. White / orange is RJ45 pin 1, which
the console uses for RTS. Landing it on the adapter’s ground pin ties the ground reference to
a signal output and produces a link that works, then does not. The ground is white / green on pin 3.
A two-wire link with no ground at all is also covered, since it is a common cause of a connection
that runs for years and then turns intermittent.
- Selecting RS-232 in the console software. The Preferences and Port Settings
sequence for mapping a service to the RS232 port, because correct wiring is not enough on its own
and RS-232 and RS-485 appear as two separate devices.
- Reading the board LEDs. The console has separate transmit and receive lights for
RS-232 and for RS-485. A table reads each combination: whether the console is hearing the request,
hearing it and refusing to answer, or not hearing it at all. This settles in seconds what a capture
takes an afternoon to establish, and it is the only check that can prove replies are not coming
from the console.
- Jumper P4 is documented alongside the LEDs. It switches RS-485 local echo, and with it on every
message comes back as a copy of itself, which this tool reports as a loopback.
- The two relevant troubleshooting entries now point at the new section.
3.2.1 2026-09-01
Added — a looped-back cable is now named as such
- Reflected replies are detected. A reply that is byte-for-byte the request the
tool just sent did not come from a console; it is the adapter’s transmit line fed straight
back into receive — a loopback plug, a cable with TX and RX bridged, or an adapter in echo
mode. Each such reply now raises
REFLECTED_COMMAND (critical) instead of the
misleading pair NO_ETX + MISSING_CHECKSUM_TAG, which pointed at the
console when the fault was in the cable.
- When every reply is a reflection, the tool says the line is looped back in
plain language: in the result of Read everything, in live monitoring, in the settings
search, in the on-screen report, in the downloaded text report, and in the log. The report
summary gains a Reflected replies row and a
LOOPBACK line.
- The settings search scores an echoed request as tier 1 rather than tier 3, so a looped-back
line is no longer reported as “close, the speed is probably right”.
- RS-485 echo is handled. A half-duplex RS-485 adapter passes its own
transmission up as received data, so every reply begins with a copy of the request and the
console’s answer follows. This is noted as
ECHOED_COMMAND (medium), the echo is
removed, and the answer is analysed — and scored in the settings search — as if the
echo had not been there. Previously this tripped a checksum failure on every reply.
- New troubleshooting entry: Every reply is a copy of the request.
- Five new conformance checks cover the reflection and echo detectors.
- Conformance suite: every simulator fault through the analyser. When served over
http, the suite loads the simulator in a hidden frame and pushes each of its nineteen
fault modes, against every command it knows, through the client’s own analyser. Each must
raise the anomaly its help text promises; conformant frames must raise none; and coverage is
checked both ways so a fault added to one side without the other is a failure. From a saved
offline copy the group is reported as skipped, never as passed. The first run of this group caught
a bug in the new echo detector before release: a genuine reply begins with the same bytes as the
request, so a prefix match alone flagged every good reply. An echo is now recognised only when the
console’s own SOH follows the echoed request.
- Simulator: two new fault modes.
loopback sends the request straight
back and nothing else, as a shorted cable would; echo sends the request back and then
the correct reply, as a half-duplex RS-485 adapter does. Both are included in the auto-cycle.
3.2.0 2026-07-30
Five independent reviews before release — customer experience, diagnostic fitness,
regression hunt, safety and deployment, and the usefulness of the output. The most important
change is new: the tool can now reproduce what the gateway actually does, rather than reading the
console once.
Added — the reason for this release
- Reproduce the gateway (step 5). The gateway does not read the console once. Its
deployed configuration polls System Status at address 01 every second and In-Tank Inventory at
addresses 01/02/03 every seven seconds, continuously — and it fails about seventeen seconds
in. Reading each report once, which is all the tool previously did, could easily never provoke
that. This mode issues the same requests, to the same devices, at the same rates, interleaved,
for as long as you let it, and reports when the first problem appeared.
- The report now names the first serious problem of the session, computed before
any truncation. It is the one line most likely to matter.
Fixed — the report could mislead
- "The console reports all functions normal" was shown even when no alarm data had been
received at all. Those are completely different things, and the green reassuring version
was being shown for both.
- Long sessions discarded the beginning, which is the part worth having. The
anomaly, request and trace lists kept only the most recent entries, so the onset of an
intermittent fault — normally the diagnostic moment — was the first thing dropped.
All three now keep both ends and say what was omitted from the middle.
- The report claimed per-byte arrival times were preserved in the capture file. They
never were — the capture timestamps each message, not each byte. Corrected, and
the trace now states plainly that its byte-spacing figures are the only per-byte timing that
exists.
- "Finished" was shown in green even when nothing at all had answered.
- A settings search stopped early reported "no reply on any combination" without mentioning that
most combinations had never been tried.
- Time the tab spent in the background is now measured and reported, because browser throttling
stretches every timing taken during it.
Fixed — read-only hardening
- The allowlist check now also sits in the function that actually writes to the port, not only in
the layer above it. A guard one level up is a guard that can be stepped around.
- The command table and the device limits are frozen, so neither can be extended at runtime.
- The security code is validated before it reaches the wire. It is concatenated
into the request, so a value containing control characters could have injected framing into the
middle of our own command — and a console that resynchronises on an embedded start marker,
behaviour this tool detects in replies, might then have read the remainder as a different
command. Printable characters only, correct length enforced.
- Verified by test: five separate bypass attempts, including calling the internal send function
directly, all blocked with zero bytes transmitted.
Fixed — concurrency
- All four ways of reading the console — read everything, live monitoring, settings search,
and gateway reproduction — now exclude one another. Two running at once would have quietly
destroyed the timing fidelity the reproduction mode exists to provide.
- The settings search now holds the connection controls while it runs; connecting manually
part-way through raced it for the same port.
- Double-clicking Connect could start two overlapping opens, after which the recorded connection
settings might not describe the one the report was taken over.
- Alarm reports now check device numbers like every other decoder does.
Fixed — the conformance tests could not run from disk
- The test page loaded the explorer in a hidden frame and drove it from outside. That works over
http but not from file://, where the browser gives every document its
own unique origin — and the attempt throws rather than returning nothing, so it presented
as a broken tool rather than an unsupported one. The suite now runs inside the explorer itself,
reachable at index.html?selftest, and works from a hosted copy and a saved offline
copy alike. It also now verifies the code in that very file, so a customer's own copy can be
checked by adding ?selftest to whatever they ran.
Added — safety net
- Closing the tab with an un-downloaded session now warns first. Losing it means repeating the
whole on-site procedure.
- A message when the page is blocked from running by a script policy, instead of a blank page
that does nothing.
- The security code appears in both files sent to Chipkin; the page now says so.
3.1.0 2026-07-30
A full pre-release code review and a command-by-command audit against the RS-232 manual. This
release is almost entirely corrections, several of which would have produced confidently wrong
readings rather than visible errors. A new
protocol conformance suite now checks every command on demand.
Fixed — decoding was wrong
- Active and cleared alarm reports (i113, i114) were parsed with the wrong layout
entirely. Both begin with four 20-character station-header strings and use wider records
than the system status report — 18 characters for i113 and 20 for i114, including a sensor
category and a timestamp. They were being read as the 6-character records of i101, which meant
80 characters of site name were parsed as alarm codes and every real record after them was
misaligned. Both now have their own parser.
- System alarm names (category 01) were wrong throughout. The table bore almost
no relation to the published one — type 05 is "Too many tanks", not "Printer out of paper".
Replaced with the manual's table in full.
- Liquid sensor alarm names (category 03) were shifted by two. The i101 alarm
table starts at 02 and is numbered differently from the i301 sensor status values; the two had
been conflated, so every liquid sensor alarm was reported under the wrong name.
- Input alarm names (category 05) were incomplete — "Generator off",
"Generator on" and "Input out alarm" were missing and would have been reported as unknown.
- Input status names (i401) were guesses and all four were wrong. The documented
values are setup data warning, normal, alarm and out alarm.
- Relay status names (i406) were inverted. The manual defines 0001 as Relay
Active and 0002 as Relay Inactive.
- The About Screen report (i907) is a length-prefixed structure, not prose. It
was being run through the version-string parser, which presented raw length bytes as if they
were text. It is now captured verbatim and left for a human to read.
- Tank numbers above 16 were accepted. A TLS-350 has at most 16 tanks, so a
misaligned reply claiming "tank 40" is impossible and should be caught — which is the
entire point of that guard. Sensors, inputs and relays remain bounded at 64.
- Delivery reports (i202) did not check tank numbers at all, unlike inventory and sensor
reports.
Fixed — could produce a wrong report
- Two requests could be in flight at once. Starting live monitoring or a
settings search while "Read everything" was running began a second command stream, and the
protocol allows only one command at a time. The controls now exclude each other, and the request
layer refuses an overlapping send outright rather than relying on every button being disabled
correctly in every error path.
- Reconnecting mid-run is now blocked. It could tear down the port an in-flight
request was using and finish the run on different settings than it started with, producing one
report that silently described two different connections.
- A dropped cable was never noticed. When the serial stream died the tool
stopped reading but still believed it was connected, so a live session would spin indefinitely
inventing timeouts. It now reports the disconnection and offers to reconnect.
- An unparseable clock reply (i501) was echoed into the report as though it were a timestamp,
unfiltered. It is now flagged as malformed and not displayed as a time.
Fixed — capture file
- Messages larger than about 65500 bytes produced a malformed capture. The
length fields in the readable format are 16-bit and silently wrapped, so Wireshark rejected the
packet — losing the evidence in precisely the runaway-console case worth capturing.
Oversized messages are now split across consecutive packets.
Added
- A protocol conformance suite that drives the shipping decoder
with responses built from the manual's documented layout for all fifteen commands, and asserts
every field decodes to the value that was encoded. It is deliberately checked against
deliberately-broken builds to confirm it detects regressions rather than passing vacuously.
- The tool's own self-check result now appears in the environment check, so a build with broken
protocol arithmetic is visible to whoever is standing at the console instead of only in a
downloaded file.
- A warning when the security code is not exactly six characters. A wrong-length code produces a
command the console silently ignores — indistinguishable from a dead cable, and exactly
the sort of thing that sends someone hunting a wiring fault that does not exist.
- The simulator now sends real data for active and cleared alarms, inputs, relays, tank and
sensor configuration, port settings, and a full delivery record. Previously these returned only a
bare timestamp, so the decoders for them were never exercised by testing.
Fixed — simulator
- Stopping the simulator left the fault auto-cycle timer running.
- Neither history was capped, despite the auto-cycle being built for multi-hour runs.
- The read loop lacked the event-loop guard the explorer was given in 2.3.0.
- The count-field faults could silently do nothing while still being reported as applied, which
would make a correctly-behaving explorer look as though it had missed a fault.
3.0.0 2026-07-30
Renamed
- The client is now TLS-350 Explorer. It speaks the Veeder-Root TLS-350 serial
protocol, which is what the OPW SiteSentinel Nano and a range of other consoles implement, so the
name describes what it talks to rather than one vendor's badge.
- The explorer and the simulator now share a single version number and this single change log.
Previously they were versioned separately, which made it impossible to tell from two log files
whether they came from a matching pair.
Fixed
- The port stayed open after an automatic settings search. Pressing
Use these settings and then Connect failed with
InvalidStateError: The port is already open. The search borrows the port for every
combination it tries and did not always hand it back — our own bookkeeping could believe the port
was closed while the browser still held it open. Every connection attempt now closes first,
and the search explicitly releases the port when it finishes.
- Use these settings now connects directly instead of only filling in the boxes and
leaving you to press Connect.
Added
- Save for offline use. A button in the last step downloads this tool as a
single file you can keep on a laptop and open later with no internet connection at all. Useful
for sites where the machine that reaches the console cannot reach the web.
- Links in the header of every page to move between the explorer, the simulator and this change
log.
- A footer on every page showing the version and linking to chipkin.com and this change log.
- Much fuller on-page instructions, including a troubleshooting section covering
the problems customers actually hit: an empty port list, a port that will not open, no reply from
the console, replies that arrive garbled, and downloads being blocked.
2.3.0 2026-07-30
Fixed
- The automatic settings search froze after its first attempt and the Stop
button did nothing.
port.open() can sit unresolved forever when the driver has not
finished releasing the handle from the previous close, and an await that never
settles is a loop that never checks its abort flag. Every serial operation is now time-bounded —
open 5 s, request 6 s, close 5 s — with a settle delay between attempts and each phase logged by
name, so a stall says where it happened instead of the page simply stopping.
- A fast console's reply could be missed. The receiver was installed after the
write completed, so a console answering inside that gap had its reply counted as unsolicited and
the request timed out anyway. The receiver is now in place before anything is sent.
- The page could lock up completely. If the input stream was already closed,
reads returned instantly and the read loop spun on microtasks alone, starving rendering and
input. It now detects that and stops, and yields to the browser on every pass regardless.
Added
- A running status line during the settings search naming the combination being tried, so a slow
attempt is visibly slow rather than looking like a hang.
2.2.0 2026-07-30
Fixed
- Corrupted replies invented tanks and sensors that do not exist. A reply with a
second start marker embedded in it decodes into a mixture of real devices and fragments of the
reply header. Because the site picture merged results by device number, one such reply
permanently added a phantom device that no later good reply could remove — a fault-injection run
produced a "tank 0" whose height was really tank 2's volume, and sensors "0" and "30" conjured
out of a date stamp. The tank, sensor and alarm figures are now built only from replies that
arrived intact. Excluded replies keep their full detail lower down and are counted in the
summary.
- Replies claiming a device numbered outside 1–64 now raise
INVALID_DEVICE_NUMBER.
The protocol reserves 00 for "all devices" in a request; no reply should ever use it.
Changed
- Protocol anomalies and Requests are scrollable with the newest at the top, and anomalies are
grouped by type with counts before the detail.
- The text report is bounded — 200 anomalies, 200 requests, 800 trace messages, newest first —
with true counts always stated. The capture file remains complete and is never truncated.
2.1.0 2026-07-30
Added
- Live monitoring. Polls the console every 1–30 seconds and refreshes the whole
report each cycle, flagging how many problems are new, so changes at the site show up as they
happen.
- Simulator: an auto-cycle that steps through every fault on a timer with clean intervals between
them, which is what an intermittent problem actually looks like.
- Simulator: every tank and sensor starts with different values, and two alarms are active by
default, so it is obvious at a glance whether the explorer mapped each device correctly.
Fixed
- The capture file recorded one packet per byte. At 9600 baud the browser
delivers a byte at a time, so a six-command session became 141 unreadable rows. Bytes are now
grouped into whole messages.
- A deadlock between closing the port and the read loop acquiring its next reader.
Changed
- The capture file offers two formats. The default wraps each message in Ethernet/IP/UDP with
invented addresses so Wireshark's Source and Destination columns name the two ends and Follow
Stream reconstructs the conversation as text; the alternative uses the true RS-232 link type,
where those columns are necessarily blank.
2.0.0 2026-07-30
Added
- Full read-only interrogation across fifteen reports, then each tank and sensor individually.
- A console report covering tanks, deliveries, liquid sensors, alarms, inputs and relays.
- Three depths of automatic settings search: 19, 54 or all 108 combinations.
- Delivery records decode properly instead of being dumped raw.
Changed
- Dropped the JSON download; the text report now carries everything.
1.0.0 2026-07-30
- First release. Built to answer one question before committing to a build approach: will a
browser talk to the console on the site laptop at all? It does — including, unexpectedly, from a
local file with no web server.
- Environment check, port selection, read-only command set, anomaly detection, Wireshark capture,
and a console simulator with sixteen deliberate fault modes.