PortDock

PortDock Simulator Guide

Rule-based fake device over serial, TCP and UDP

About this program

PortDock Simulator turns the PC into a «fake device» so you can test host software (masters, HMIs, test programs) without the real hardware.

When received data matches a rule it sends the configured reply, and it can also send status reports or heartbeats on its own, like a device.

It works over Serial (COM), TCP server, TCP client and UDP.

Getting started

  • 1. Choose a «Transport» on the left and enter the port or address.
  • 2. Add rules with «+ Add rule»: a «When» pattern, a «Reply», and optionally checksum, line ending and delay. With no rules yet, the [Modbus RTU 03 reply] [SCPI *IDN? reply] [Echo] example buttons give you a start.
  • 3. Press «Start». When the host sends a request the matching rule replies, and both show in «Traffic».
  • 4. Check how often each rule replied in «Times replied».

Layout

  • Left: «Transport», port/address, «Framing», «Start»/«Stop», status, «Log to file».
  • Top: «Reply rules» cards, «Ignore line ending when matching» / «Log unmatched requests (NO MATCH)», «Reset counts», «Save rule set» / «Load rule set».
  • Below: the «Device-initiated message» section (collapsed; opens when repeat is on).
  • Bottom: «Traffic» (time, RX ◀ / TX ▶ / EV, peer address, data), HEX/ASCII toggle, «Clear».
  • 📌 in the header: always on top — keeps this window above others (same as «Always on top» in Settings).
  • The window title shows the current state (e.g. «COM3 115200 8N1 · Connected ● REC — PortDock Serial»), so you can tell windows apart on the taskbar.
  • At 900 px wide or less (e.g. half-screen snap) the left connection panel folds away and a summary line with «⚙ Connection» and the connect button appears. «⚙ Connection» opens the panel; ✕ or clicking outside closes it.

Transport

  • «Serial (COM)»: choose «Port», «Baud rate» and «Parity». Opened as 8 data bits, 1 stop bit, no flow control. Unplugging and replugging USB reopens it automatically.
  • «TCP server (peer connects)»: listens on «Host» (usually 0.0.0.0) and «Port» for the host software to connect. Each connection gets its own replies.
  • «TCP client (connect to peer)»: connects to the «Connect to» host and port when the host software is the server. It reconnects when disconnected.
  • «UDP»: receives on «Listen port» and replies to the sender. «Send to» is used for device-initiated messages before anything has been received. To send to a broadcast address (255.255.255.255, x.x.x.255), check «Allow broadcast» before starting.
  • Transport, port, addresses and baud are locked (🔒) while running; stop to change them. Framing, reply rules and match options apply immediately.
  • When waiting to reconnect or stopped, the status line also shows the last failure reason.
  • With Serial and no port, «Start» is disabled.

Framing

Rules are compared against whole frames, so you choose where incoming bytes are split (UDP needs none: one datagram is one frame).

  • «Idle gap»: split when nothing arrives for «Idle gap (ms)». Suits binary protocols such as Modbus RTU.
  • «Terminator»: split when «Terminator (HEX)» (e.g. 0A, 0D 0A) arrives; pending bytes are also flushed after the idle gap. Suits ASCII commands. When first chosen it starts with terminator 0A (LF) and a 50 ms idle gap.
  • «Terminator (HEX)» also accepts «0D0A» or names like «CR LF» / «CRLF». Below the field it shows how it was read, e.g. «Read as: 0D 0A (2 bytes)», or the reason in red. When empty, it warns that only the idle gap splits frames.
  • Changes apply immediately while running.

Reply rules

Each card is a rule. Rules are checked top-down and only the first match replies. If none matches, nothing is sent.

  • Checkbox: enable or disable the rule. Disabled rules are skipped.
  • Name: logged as «AUTO name», and reply counts are kept by name. Duplicate names show a warning.
  • «When»: pattern mode (HEX/ASCII), «exact» (whole frame must match) or «contains» (anywhere in the frame), and the pattern. ASCII rules get a «Wildcards» checkbox (see «Wildcards»).
  • A new rule («+ Add rule») takes the format of the rule above it — match HEX/ASCII and exact/contains, reply HEX/ASCII, checksum and line ending. Wildcards always start off.
  • Right-click an RX line (or a «NO MATCH» line) in Traffic and choose «Make a rule from this request» to create a rule from those bytes and jump to its reply. Text becomes an ASCII literal pattern (trailing CR/LF moves to the reply line ending); Modbus RTU gets «**» for the CRC and a CRC16 Modbus reply checksum; Modbus TCP gets «?? ??» for the transaction ID. If a catch-all rule such as «**» exists, the new rule goes above it.
  • «Ignore line ending when matching» (on by default): the terminator and trailing CR/LF are removed from the received frame before comparing, so «exact» patterns need no line ending. When off, the raw bytes are compared.
  • «Log unmatched requests (NO MATCH)» (on by default): a request no rule matched is logged as a «NO MATCH» event (EV).
  • «Reply»: reply mode (HEX/ASCII), content, «Checksum», «Line ending», «Delay» (ms, 0–600000).
  • A reply is built as «content + checksum + line ending»; the checksum covers the whole content. Fields such as {req 0..1}, {counter}, {rand 0..9}, {time}, {crc …} in the content are filled for every request (see «Reply templates»).
  • «▸ More»: delay range (jitter), drop every Nth / by chance, rotating replies, and a reply preview from a sample request (see «Fault injection and rotating replies»).
  • ↑ «Move up (checked first)», ↓ «Move down», ✕ «Delete» (no dialog — «Undo» in the notice restores it in place for 5 seconds). Switching a reply between HEX and ASCII converts it to the same bytes.
  • Edits apply immediately, even while running. A rule with an invalid pattern or reply turns red with the reason below it; only that rule is skipped and the others stay active («N invalid rule(s) skipped»).
  • Rules are kept after restarting.

Wildcards

  • HEX: «??» = any one byte, «**» = zero or more bytes.
  • ASCII: set per rule with the «Wildcards» checkbox. Off (the default for new rules) compares ? and * literally — SCPI «*IDN?» matches only «*IDN?», not «XIDN!».
  • On: «?» = any one character, «*» = zero or more. To match a literal ? or * while on, write «\x3F» (?) or «\x2A» (*). A rule with wildcards on and ? or * in its pattern shows a yellow notice with [Turn wildcards off].
  • Rules saved before this checkbox existed (before 10/18) load with wildcards on, so they behave as before. «\r», «\n» and «\xNN» escapes work either way.
  • Example: «01 03 ?? ?? 00 01 **» = Slave ID 1, function 03, any start address, count 1, any CRC.
  • Example: ASCII «contains» + «STATUS?» — with wildcards off it needs the text «STATUS?»; with them on, «STATUS» followed by any one character (not necessarily a question mark).
  • A rule of just «**» matches everything. At the bottom it becomes the default reply (e.g. NAK) for everything else.

Reply templates ({…} fields)

A reply may contain {…} fields that are filled for every request. They work in HEX and ASCII, and «Insert field» next to the reply puts one at the cursor.

  • {req} whole request · {req 0..1} request bytes 0–1 (inclusive) · {req 6} one byte · {req 2..} byte 2 to the end · {req -2..-1} the last 2 bytes (negative counts from the end, -1 = last).
  • {counter} how many times this rule has replied (from 0), 1 byte · {counter 2} / {counter 4} size in bytes · add le for little-endian (default big-endian) · {counter dec} decimal text. «Reset counts» starts over at 0.
  • {rand 0..100} random value in the range (inclusive; size 1/2/4 bytes to fit the max) · {rand 0..1000 2 le} explicit size and order · {rand 10..99 dec} decimal text.
  • {time} current time «HH:MM:SS» as text · {time %Y-%m-%d %H:%M:%S} custom format · {unix} Unix seconds · {unix ms} milliseconds.
  • {crc kind} checksum of all bytes before this field, placed here · {crc bcc 1..-1} explicit range (counted over the reply without checksum fields) · add swap to reverse the byte order. Kinds: crc16-modbus, crc16-ccitt, crc16-xmodem, crc8, lrc, bcc, sum8, sum16, crc32.
  • Order: fill fields → {crc} fields → the rule's «Checksum» (over everything) → «Line ending». So «01 03 02 {req 4..5}» with checksum CRC16 Modbus equals «01 03 02 {req 4..5} {crc crc16-modbus}».
  • Example — Modbus TCP read of 2 holding registers: when «?? ?? 00 00 00 06 ?? 03 **», reply «{req 0..1} 00 00 00 07 {req 6} 03 04 00 64 00 C8». The transaction ID (bytes 0–1) and MBAP Unit ID (byte 6, the Slave ID) are echoed so the master can pair them. MBAP has no CRC, so set checksum to «None».
  • Example — a device with sequence numbers: «ACK {counter dec}\r\n» (ASCII). Example — BCC after STX…ETX: «02 {req 1..-2} 03 {crc bcc 1..-1}».
  • If a request is too short for a field such as {req 9}, nothing is sent and the log shows «AUTO name — request range …». A { that does not start a known name (req, counter, rand, time, unix, crc) is sent as is (e.g. {"ok":1}). To send text like «{req» literally, write \x7B in ASCII.
  • Type a request into «Sample request» under «More» (same HEX/ASCII as the pattern) to see whether it matches and the exact reply bytes. It is filled with count 0 and sample random values, so real values differ.

Fault injection and rotating replies

Expand «▸ More» on a rule card to test the host's timeout, retry and state handling. Active options are always shown as small tags under the card («delay 10–50 ms», «drop 1 in 3», …).

  • «Delay range»: replies after a random delay between the start and end (ms) every time (jitter). If the end is not above the start, the start is a fixed delay. The log shows the real delay, e.g. «AUTO name +37ms».
  • «drop every Nth request»: the Nth, 2Nth … requests matching this rule get no answer (0 = off). «% = drop by chance» drops with that probability. Dropped requests are logged as «DROP name — …» and do not count as replies.
  • «Rotate replies»: with several replies («+ Add reply»), each match sends the next one «in sequence» (1 → 2 → … → 1) or a «random» one — to mimic a device whose state changes (idle → running → done). The log shows which, e.g. «AUTO name [2/3]».
  • «In sequence» and {counter} use the rule's reply count — «Reset counts» starts over. Editing a rule (same name) keeps counting.

Rule warnings

  • «matches everything, so the rules below it never reply»: a rule like «**» sits above others. Move it to the bottom with ↓.
  • «Same pattern as a rule above»: the lower rule can never be used.
  • «Rules share a name»: their reply counts are merged. Rename one.

Counts and rule sets

  • Each card shows «Times replied». «Reset counts» sets them to 0.
  • «Save rule set»: saves all rules plus transport, ports, addresses (incl. broadcast), framing, match options, the device-initiated message and its repeat interval as one JSON file (a profile). Keep one per device or test.
  • «Load rule set»: asks first, then replaces the rules and settings with the file. While running, connection settings are not loaded. Older files (rules and framing only) still load; settings missing from the file are left as they are. An invalid file shows «Invalid rule set file.» and nothing changes.

Device-initiated message

Imitates status reports, heartbeats or alarms that a device sends without a request. It is separate from the reply rules and stays collapsed so it is not mistaken for one (the collapsed title shows the content, or «sending every 1000 ms» while repeating). Turning on repeat opens it; its open state is remembered.

  • Choose HEX/ASCII, content, «Checksum» and «Line ending», then press «Send». The exact bytes are shown below.
  • The content may use reply templates (10/19): {counter dec} is the send count (from 0 at each start), {rand 0..100 dec} a random value, {time} / {unix ms} the time, {crc …} a checksum — filled anew on every send (see «Reply templates»; {req} is unavailable as there is no request). «Will send» below shows sample values. Example: «{rand 20..25 dec}.{rand 0..9 dec},{counter dec}» + line ending CR LF + repeat 100 ms → graph it in PortDock Plot.
  • Check «Repeat (ms)» to send every interval (10 ms or more). While no peer is connected, turns are skipped with «Waiting for a peer» and sending resumes when one connects. Only unchecking it or «Stop» turns it off.
  • Destination: the serial port; all connected peers (TCP server); the server (TCP client); the last sender, or «Send to» if none (UDP).
  • «Send» and «Repeat» are disabled until you start.
  • Switching HEX↔ASCII converts the input to the same bytes in the new notation (e.g. «41 54 0D 0A» ↔ «AT» plus CR LF escapes). If the input cannot be read, the text is kept and a notice explains why.
  • If a checksum is on when you switch, a notice (instead of a dialog) says so and offers «Turn checksum off».

Traffic

  • RX ◀ received, TX ▶ sent (rule replies and device-initiated messages), EV events (start, connect, disconnect, «AUTO rule name», …).
  • «Make a rule from this request» in the right-click menu of an RX or «NO MATCH» line creates a rule without retyping the request (see «Reply rules»).
  • Toggle HEX/ASCII view. At the bottom the view follows new lines; scroll up to pause it.
  • «Log to file»: after starting, pick a file to write every line from then on. «Stop logging» ends it.
  • Follow: new lines are followed only while you are at the bottom. Scroll up to pause (the view stays put) — «↓ Jump to latest (n new)» appears at the bottom right. Click it, press End or scroll to the bottom to follow again.
  • Selecting: click a line, Shift+click for a range, Ctrl+click to add or remove one. Clicking does not stop following.
  • Right-click menu: Copy lines · Copy HEX · Copy ASCII · Copy HEX + ASCII · Copy as C array ({0x01, 0x03}) · Send again (TX lines — exactly those bytes). Data copies (HEX, ASCII, C array) skip event lines (EV), one frame per line.

Settings (⚙)

  • Language, theme, font size, timestamp format, line limit.
  • «Start file log automatically»: with an auto-log folder, each start writes a log automatically.
  • «Ask before closing while connected or logging».
  • «Export settings» / «Import settings» move display settings as JSON. Move rules with «Save rule set».
  • «Always on top»: keeps this window above other windows (same as 📌 in the header).
  • «Expand all (expert view)»: shows the groups that are normally collapsed (advanced connection, receive settings, fault injection, statistics, scan options, triggers, auto-reply …) open. Folding one while it is on lasts only for this run. Turning it off returns each group to its remembered state.

Shortcuts and tips

  • F4: start / stop (same as the button on the left).
  • Ctrl+L: clear the on-screen log (file logs are kept).
  • Ctrl+Shift+L: start / stop logging to file.
  • Esc: stop repeat sending (outside text boxes — inside a box Esc keeps its own meaning).
  • End: jump to the latest log line and follow again.
  • Ctrl+C: copy the selected log lines as «time direction data» (in the current view). Inside a text box it copies normally.
  • F1 or the ? button: this help. Close it with Esc.
  • Number boxes: ↑/↓ by 1, Shift+↑/↓ by 10, PageUp/PageDown by 100, or the mouse wheel once the box is focused. The baud box steps through the listed rates.
  • Shortcuts are ignored while a dialog or the right-click menu is open, or while composing Korean text.
  • Hover over a field to see a tooltip.
  • Testing on one PC: use a TCP server on 127.0.0.1, or a virtual COM pair (e.g. com0com) for serial.
  • Use reply delays to test the host's timeouts, and deliberately wrong replies to test its error handling.

Troubleshooting

  • No reply: check the rule is enabled, the pattern mode (HEX/ASCII) and exact/contains, and that no «**» rule sits above it. Compare the RX line with the pattern. With «Log unmatched requests» on, each unmatched request leaves a «NO MATCH» line, and right-clicking it makes a rule. If a rule answers the wrong requests, check whether «Wildcards» is on for an ASCII rule.
  • Requests split or merged: adjust «Framing» and «Idle gap (ms)».
  • Serial port does not open: check whether another program is using it.
  • Cannot connect to the TCP server: check the Windows Firewall prompt, the port, and the IP the host connects to.
  • The program does not open: Microsoft Edge WebView2 is required (included in Windows 11).