Whisker IDE Changelog
=====================

1.3.1 - 2026-10-04
------------------

Bug fixes

  - The installed IDE could not run its certificate tool. The
    Security dialog's Site section reported "whisker_cert.py not
    found", and Import site identity, issuing identities and
    signing a deploy to a managed controller all failed on any PC
    without a Python development setup. The tool now ships with
    the IDE as tools\whisker-cert\whisker_cert.exe and needs no
    Python. Connecting to a managed controller was not affected.

1.3.0 - 2026-10-04
------------------

Four months of work since 1.2.2. The headline items are the ladder
instruction set (three tiers of IEC 61131-3 blocks plus device
blocks), emulation on the PC, the on-controller historian, managed
security with either a cloud account or your own site certificate
authority, reading Allen-Bradley PLCs by tag name, and serving the
controller's own tags by name to Aveva, FactoryTalk or Ignition
over EtherNet/IP.

Note: items marked (controller) need the runtime on the controller
updated as well as the IDE. Build & Download does not replace the
runtime; see the setup guide.


Ladder instruction set (controller)

  - Tier 0/1 IEC 61131-3 blocks: rising and falling edge contacts,
    TP pulse timer, TONR retentive timer, CTD and CTUD counters,
    R_TRIG and F_TRIG, SR and RS latches, MATH, LIMIT, SEL, MUX,
    PACK and UNPACK, MEQ masked equal, and inline EQ/NE/GT/GE/LT/LE
    comparisons that pass rung power when true.

  - Tier 2 process blocks: HYST deadband comparator, TOTAL
    totalizer, FILTER first-order lag, ROC rate of change, PID
    closed-loop controller, and ALT lead/lag pump alternator.

  - Tier 2B industrial blocks: MOTOR and VALVE device blocks that
    carry the whole start, stop, mode, feedback and fault handling
    for a piece of equipment, plus FIRSTOUT first-out interlock
    annunciator and DEBOUNCE input filter. MOTOR and VALVE report
    why they faulted, and RUN is deliberately not cleared by a
    fault - the overload contact breaks the starter, not the logic.

  - DRUM step sequencer, RTC wall clock and SCHED time-of-day
    window, for sequencing and time-based control without writing
    a state machine in rungs.

  - PYFB - call a Python function from a ladder rung and use its
    answer in the same scan. For the things ladder is poor at:
    string handling, protocol glue, arithmetic-heavy calculations.

  - User functions with CALL and RET. Define a function once, call
    it from any task; RET returns early from a function or a task.

  - Event tasks now run. A task can be released by a bit going
    true, on the rising edge, with a debounce. Bit areas only - an
    analog threshold is a comparison in a cyclic task that sets a
    bit the event task watches.

Ladder editor

  - Undo and redo, and cut / copy / paste, per instruction and per
    network. The clipboard carries one element, the terminal or a
    whole network as marked JSON on the Windows clipboard, so it
    works between projects and between IDE windows. Paste rules:
    an element goes into the highlighted empty cell, else the next
    empty cell to its right; a terminal goes into the network's
    terminal slot and asks before replacing one that is already
    there; a network pastes below the selection. Pasted blocks get
    unique instance names, and branch wiring never travels.
    Ctrl-C / X / V on the canvas, and a right-click menu on the
    rung number.

  - Network comments are visible and editable. A non-empty comment
    draws as an italic line above its rung; the Properties panel
    for a selected network has the edit box, now four lines tall
    with a permanent scrollbar when the text runs past the bottom.

  - Clicking a network's rung number selects the whole network on
    its own, which is what Copy, Cut and Delete Network act on.

  - Online write and force from the Properties panel while
    monitoring: a switch for BOOL, plus and minus for INT, a text
    box for REAL, with forced tags marked and held every scan.

Tags

  - 16-bit INT and 32-bit DINT are now separate types in separate
    memory areas (%MW and %MD). Projects from earlier versions
    migrate on load.

  - System tags are created with the object they describe instead
    of appearing at Build: add a device and its Comm OK, Comm Age
    and Error Type tags exist at once. Also the cellular and cloud
    tags, and a per-process-variable Age tag.

  - Import Tags and Export Tags on the Tag Database toolbar, as
    CSV. Thirteen columns, headers matched by name in any order,
    unknown columns ignored, blank addresses allocated as Add Tag
    would. Refusals are reported per row with line numbers, and
    existing names can be skipped or updated in one choice.

  - One tag-name rule everywhere. Empty, malformed, duplicate,
    duplicate differing only in case (the compiler treats those as
    one tag) and system-tag names are refused with the reason, in
    Add Tag, in the Properties panel's New Tag dialog and rename,
    in the undefined-tag sweep and in CSV import.

  - Retained values survive a program update. The controller
    migrates them by name, so a setpoint an operator entered at
    the panel is still there after a download. Renaming a retained
    variable makes it a new one.

  - Data Type is editable for a controller memory tag: the tag
    moves to a new slot in the matching area and its initial value
    resets.

  - History switch and deadband per tag, for the historian.

  - The tag editor no longer allocates an address that is already
    taken, and the compiler refuses to build two tags on one
    memory location instead of silently merging them.

I/O and devices

  - EtherNet/IP: read and write named tags in Allen-Bradley PLCs
    (controller). ControlLogix, CompactLogix, Micro800, MicroLogix,
    SLC500 and PLC5 by CIP explicit messaging. Add the PLC as a
    device, add its tags by name in the PLC Tags dialog, and they
    behave like any other I/O - polled into the tag database, with
    local changes written back. One connection per PLC on its own
    thread, so a slow or dead PLC never stalls anything else. The
    device's IP, port, PLC type, CIP path and timeout are editable
    in the Properties panel after it exists.

  - ArenaTCP: one controller reads and writes another controller's
    tags (controller), optionally over NexusSec mutual TLS. Import
    the tags you want from the source project. This is also how a
    WhiskerHMI PC application gets its data.

  - The two RS-485 ports are mapped correctly (controller): RS485A
    is /dev/ttyS7 and RS485B /dev/ttyS5. Note that the A and B
    labels on the terminal block are swapped relative to the
    ports; the manual's wiring section shows which is which.

  - Selectable analog ranges on I/O points, spanning the
    over-range, with per-module count scales; the range selector
    is in the points table and the emulator's stimulus slider is
    labelled in engineering units.

CIP tag server (controller)

  - SCADA reads and writes the controller's tags by name over
    EtherNet/IP, the way it reads a CompactLogix: Aveva's ABCIP
    driver, FactoryTalk, Ignition or any client that browses a
    Logix controller. No name-to-register aliasing as with Modbus.

  - Off unless the project turns it on (Project Properties). Each
    tag is published or not, and read-only or writeable, from the
    Tag Database's CIP column or the tag's Properties; physical
    I/O can never be written over CIP. A CIP Name lets a tag be
    published under the name the SCADA already uses, including
    dotted names such as CSLS19PMP00108.oRun, which the server
    presents as structures so ABCIP accepts them.

  - A deploy needs nothing on the SCADA side: the client re-reads
    the tag list on its own within seconds. For Aveva ABCIP set
    the device's Optimization Mode to No optimization.

  - Listens on TCP 44818; the controller firewall accepts it on
    Ethernet.

Emulation

  - Build & Emulate runs the project on your PC with no controller
    and no account. It compiles exactly as Build does, starts the
    emulator on that build, and connects to it; the toolbar turns
    amber for as long as it runs. The connect-time reconcile and
    the monitoring gate are satisfied automatically.

  - IO Stimulus tab for driving the program by hand: digital
    inputs as switches, analog inputs as a number box or a slider
    in engineering units, with outputs shown read-only. A value
    you set is held every scan so the program cannot overwrite it.

  - HMI Preview tab renders the project's panel screens with live
    values and accepts touch while monitoring is on, so buttons,
    selector switches and numeric inputs on the preview write into
    the emulated program exactly as the panel would.

  - The project's Python application runs under emulation too. The
    controller's own Python runtime starts beside the emulator and
    runs app.py unmodified, with alerts evaluated and PYFB blocks
    answered from your @pyfb functions. The Python Log panel
    connects to it exactly as it does to a controller.

Historian and trends

  - On-controller historian (controller). Tags with History
    checked, plus any tag on a Trend Chart, are recorded on the
    unit for 60 days by default, with the raw samples kept for
    seven days. Retention is set in Project Properties.

  - Trend Chart widget for panel screens and the PC application,
    with a legend of current values and time-range chips.

HMI

  - Create HMI Faceplate on a MOTOR or VALVE block builds a
    complete faceplate on an HMI screen in one click, with the
    mode, feedback and fault handling already bound.

  - Operator PIN login at the panel, with a user picker, per-user
    roles and per-user lockout. Users and roles come from your
    Whisker.io account.

  - Standard device-state colours throughout: open green, closed
    grey, mid-travel amber, fault red.

  - Panel status bar shows the cellular signal: bars, dBm and a
    quality word, or No cell on a unit without a modem.

  - Panel keypads use large square keys, and screens hidden under
    the PIN pad are no longer drawn, which made the panel feel
    sluggish.

  - Alert Table: the State column no longer wraps FIRED and
    CLEARED onto two lines. Trend Chart: the legend no longer
    overlaps the chart title or the range chips.

Security, provisioning and enrolment

  - A controller now has three postures. Standalone is the factory
    default and accepts plain connections and unsigned programs.
    Awaiting enrolment is provisioned but has no identity yet and
    its data port is closed. Managed requires mutual TLS and
    refuses any program not signed by a certificate its authority
    issued.

  - Cloud provisioning and enrolment. Provision New Device in the
    Cloud Explorer, the unit enrols against your account's
    certificate authority and comes up managed. Rotate Device
    Cert, Decommission Device and Approve Re-Enrollment for a unit
    changing hands or suspected compromised.

  - Site certificate authority, for plants with several engineers
    and no cloud account. One authority per site, held by the
    customer on an administrator PC and protected by a passphrase
    the IDE never stores. Engineers hold identities it issued,
    never the authority's keys, so a download is attributable to a
    named person and a departed engineer is revoked fleet-wide.
    The Security dialog has Make this keystore a site, Issue
    engineer identity, Export site trust package, Provision unit
    and Push CRL to unit.

  - Signed deploy. Build compiles and downloads in one step as a
    signed bundle, and a managed controller verifies the signature
    and the revocation list before it activates the program.

  - Panel identities for WhiskerHMI PCs. A build for a managed
    project stages only the authority's chain and a marker file,
    never a certificate; the engineer issues one identity package
    per panel PC from the Security dialog and the operator imports
    it on that PC. Revoking one puts it on the authority's
    revocation list.

  - Unified audit trail across the cloud, the PC application and
    the panel: a hash-chained local log with an uploader, and an
    Audit Log view with filters and CSV export.

  - The Security dialog is now present in both editions. The
    Offline edition shows the site authority and the local
    keystore, which is what a plant without a cloud account needs;
    only the Account section is Cloud-edition only. This replaces
    the note under 1.2.0 below, which said the Standalone edition
    had no security features.

  - Device certificates moved from Ed25519 to ECDSA P-256.

Cloud

  - Per-device broker credentials over TLS, set on the unit by
    factory provisioning rather than carried in the project. The
    project's Cloud section no longer holds broker credentials or
    a Secure switch that did not control security.

  - Process variables, report-on-change, remote writes and remote
    system commands, with 64 process-variable slots per unit.

  - A Nexus.io process variable can be shown in the cloud as
    Multiselect, a label per value (OFF / HAND / AUTO), set with
    Display As in the tag's cloud settings.

  - Cloud Writeable switch per process variable, off by default:
    only the tags you choose can be written from the cloud.

  - Save Tag Configuration says when it worked and refreshes the
    device, and shows the server's reason when it is refused.

WhiskerHMI PC application

  - Multi-window layouts with role assignments per window.

  - User login with roles, and the audit log described above.

  - Historical trends with CSV export.

  - Per-device Comm OK, Comm Age and Error Type tags, written by
    the PC's own I/O scanner, and reconnection after a controller
    outage.

  - An EtherNet/IP driver, so the PC application can read
    Allen-Bradley PLCs directly as well as through a controller.

  - The I/O scanner matches each controller reply to its request
    and reconnects after a timeout, so a slow or stalled
    controller can no longer leave it showing another tag's
    values.

  - The generated installer no longer registers Windows services.
    The application starts and stops its own scanner and database,
    which is what it was already doing; the service registration
    was broken and never started anything.

SmartController (Classic)

  - Classic projects inside an Application show the File System
    tree (Local and Target) and Sync; they previously showed the
    Nexus.io tree.

  - Sync installs the way the factory load tool does: files to the
    root of the controller, a legacy /app folder removed (it hid
    the installed program), saved values cleared when config.json
    changes, every upload verified on the controller, and the
    controller's manifest given an app package and a config
    package named and versioned from appName and appVersion in
    app.py. Firmware files are never touched.

  - config.json is generated from the project before every Sync
    and Build and includes the Modbus stop bits and parity the
    runtime requires. A project without a process variable is
    refused, because the controller restarts every 30 seconds
    without one.

  - Build writes the app and config packages (dist_app and
    dist_config, each with its manifest) to a folder for the
    factory load tool, instead of running the ladder compiler.

  - The console stays usable: the IDE keeps the controller's
    watchdog fed while it holds the controller at the prompt, a
    Restart controller button replaces Soft Reset and follows the
    controller through its restart so its start-up log and program
    output appear, and Disconnect restarts the program. A
    controller that resets or is unplugged is reported as a lost
    connection instead of showing Connected with nothing behind it.

  - Serial transfers are reliable: back-to-back writes were being
    dropped by the serial library, and long replies lost
    characters; every write now completes or fails, and file reads
    are verified piece by piece. Each port is listed once in the
    Connect dialog.

Monitoring and debugging

  - Monitoring stays off until the open project has been built and
    downloaded in this session. Before that the values on screen
    would belong to a different program under this project's tag
    names, so it fails closed and says why.

  - Connect-time reconcile. When the controller holds a different
    project the IDE offers to download it from the target rather
    than silently overwriting either side.

  - F7, Shift-F7 and F9 now actually run, stop and switch to debug
    mode; the tooltips have named those keys for some time.

Documentation

  - The user manual has been rewritten for the current product,
    with screenshots throughout, including new chapters for cloud
    provisioning and enrolment, the site certificate authority,
    the instruction reference, retained values, the historian and
    trends, Python on the controller, Project Properties, the
    WhiskerHMI PC application and the CIP tag server. One manual
    covers both editions, and each chapter says where a feature
    needs an account. The full manual and the Quick Start are
    published separately on the website.

  - The Quick Start covers both commissioning paths, cloud and
    standalone.

IDE

  - Close Application on the toolbar closes the open application
    (asking to save first) without opening another.

  - The Statistics tab is a dashboard: controller and mode, a scan
    time gauge and trend, per-program tiles and a project summary.

  - The AI Designer is not part of this release; it will return in
    a future one.

Bug fixes

  - Programs in a multi-program project could jump into another
    program's code: jump labels were not unique across programs
    (controller-visible). Rebuild and download every multi-program
    project with this version.

  - A network peer that opened the controller's data port and
    never finished the TLS handshake froze the controller's data
    service, and the programs reading through it could then
    receive another request's values (controller). Fixed on both
    sides; update the controller runtime.

  - The cloud service wrote its three DINT health tags into the
    INT area, corrupting %MW4 to %MW7 (controller).

  - Add Tag's button stayed disabled when the name was typed last.

  - Compiler not found now names the file it looked for and says
    the compiler ships in the IDE's tools folder, instead of a raw
    process_win.cc ENOENT. The guard short-circuited for every
    Windows path.

  - The emulator reported its run state in the wrong numbering, so
    the Statistics panel read STOPPED while the ladder was plainly
    scanning and the Run and Stop buttons appeared to do nothing.

  - Function block pins were silently emptied when a project was
    loaded from disk.

  - The IODF cache was emptied by every project edit.

  - Monitoring rounded every REAL to one decimal and reported a
    different number than the controller held.

  - The force panel presented its entry box as though it were the
    tag's live value.

  - Applying initial values for plain VAR no longer erases the
    retained-value file.

  - Opening an application now tears down any running emulation
    session instead of leaving it connected.

  - The project tree selects a row without collapsing it; the
    triangle toggles expansion.

  - Undeclared variables are a hard compiler error rather than a
    warning you could build through.

Known issue

  - If the controller runtime faults, it stops scanning and the
    outputs hold their last commanded values rather than falling
    to a safe state, and nothing raises an alarm. Recovery needs
    an engineer with the IDE. A fix is designed and scheduled;
    until then, treat a controller that has stopped updating as
    needing a site visit.


1.2.2 - 2026-05-21
------------------

Bug fixes

  - Installer now bundles WhiskerPlc.exe under <install>\tools\. The
    1.2.1 installer shipped without the PLC compiler binary, so any
    project Build failed with a raw "process_win.cc:577" ENOENT (Dart's
    "cannot spawn process" error) instead of either compiling or even
    a readable error message. The IDE also now looks for the compiler
    next to itself at install time.


1.2.1 - 2026-05-20
------------------

New features

  - Tag Monitor — new bottom-panel tab that lists every addressed
    symbol with its live arena value, refreshed every poll cycle.
    Filter by name / address / description; toggle system-generated
    tags in or out of view; copy the visible table to clipboard as
    TSV. Replaces the "open the journal and watch print() output"
    workflow that walkthrough chapters previously suggested.

  - Per-IO-point enable/disable. Each row in the IO Configuration
    point tables has a checkbox at its leading edge; unchecked
    points keep their symbol in the tag database but the compiler
    skips emitting a Modbus mapping for them. Cuts wire traffic on
    multi-channel modules where only a few channels are wired
    (e.g. 3 of 6 DIs in use, no pulse counters, no AI filter
    windows). Disabled rows dim out and stay in the project.

Python editor

  - Tab / Shift-Tab now block-indent / block-outdent a multi-line
    selection (every selected line gets 4 spaces added or stripped).
    Single-line Tab still inserts 4 spaces; single-line Shift-Tab
    outdents the current line.

  - Ctrl-V normalizes tab characters to 4 spaces on paste, so
    snippets copied from chat, web docs, or other editors land with
    consistent space indentation that Python accepts. No more
    "reformat in VS Code first."

Python Log

  - Log entries are now selectable text — drag-select any
    timestamp, level, or message line and Ctrl-C to clipboard.

  - New Copy All toolbar button serializes the entire log to the
    clipboard as plain text ("HH:MM:SS  LEVEL    message" per
    line). Useful for pasting log slices into chat or bug reports.

WhiskerHMI

  - Alarm panel reliability. Fixed a TCP socket race in the IO
    Scanner service that caused alert-history queries from the
    Flutter HMI runtime to silently drop their responses (the
    poll thread and the alert-history request thread shared one
    NetworkStream with no mutex). Adds diagnostic logging to
    surface future relay issues.

  - Alerts without an explicit output_tag now compile cleanly.
    The compiler auto-binds them to bit slots within a synthetic
    __alerts_state register, so the on-PLC alert tracker can watch
    transitions. Previously these alerts silently produced no
    history entries.

PLC compiler

  - Digital inputs/outputs now always emit as BIT type regardless
    of the IODF's source-register width. IODFs commonly declare
    each DI as a "uint16" holding register whose value is 0 or 1;
    the compiler now correctly treats the value as a boolean
    instead of silently dropping the read.

  - BitOffset default for DI/DQ is now 0 (was the arena-position
    modulo 8 — a leftover that broke whole-register-boolean
    modules). Bit-packed modules still work via the IODF's
    explicit `bit: N` field.

  - Consecutive same-(device, table, datatype) input reads are now
    coalesced into single multi-register Modbus transactions. Cuts
    wire traffic ~5-6x for typical modules (e.g. six DIs at
    consecutive addresses become one read of six registers).

  - RTU device validation no longer fails with "RTU device requires
    uart setting" — the IDE now carries the UART index from the
    hardware definition into saved ModbusPort entries, and
    auto-heals legacy projects on load.

  - The IO Scanner service binary tries /dev/ttyAMA{N} first, then
    falls back to /dev/ttyS{N}, so a single io_scanner build runs
    on both CM5 (BCM2712, ttyAMA naming) and RK3568 (ttyS naming)
    targets. Same uart_index semantics on both platforms.

IODF library

  - mSmart-Universal-IO: removed the Baud Rate, Slave ID, and
    Sample Rate config registers — they're configuration-only,
    not runtime values, and polling them wasted bus cycles.
    Fixed the Solar Voltage register address (1224 -> 1225).

Documentation

  - User manual (PDF and HTML) renders with a branded layout:
    D6 Labs logo top-left header, copyright bottom-left footer,
    Acrobat-sidebar PDF bookmarks generated from the heading
    hierarchy, and a fixed split-pane TOC on the left in the HTML
    output. Custom Pandoc HTML5 template drops Pandoc's default
    reset stylesheet so the sidebar layout isn't fighting a
    max-width: 36em constraint.

  - Walkthrough chapters updated to introduce the Tag Monitor in
    the overview, instruct readers to disable unused IO points in
    Step 2 of W1 and W2, and use the Tag Monitor as the primary
    verification surface in each Step 9.

Internal

  - WhiskerHMI runtime alert_history_service now exposes an
    optional onLog callback that surfaces first-tick byte counts,
    per-tick record counts, and any malformed-line decode errors.
    Stops silent parse failures from producing a blank table.


1.2.0 - 2026-05-17
------------------

Initial public release of the Whisker IDE Standalone edition.

Includes:

  - Application + Project workspace with dockable panels
  - Tag Database (BOOL, INT, DINT, REAL types with INT/DINT split)
  - Ladder Logic editor (Nexus.io AC target)
  - Function Blocks and Tasks
  - HMI Designer (Nexus.io AC and WhiskerHMI targets) with full
    widget palette (gauges, pumps, valves, tanks, trends, alerts)
  - I/O Configuration (built-in I/O plus Modbus TCP/RTU expansion)
  - Alerts editor with HMI runtime overlay and alert history
  - Modbus Server (TCP slave) with Map Viewer and CSV export
  - Python editor with REPL and live print() log
    (SmartControllerClassic targets)
  - Device discovery via mDNS
  - Build, Upload, Download, Run/Stop/Debug Mode controls
  - WhiskerHMI "Generate Installer" packaging
  - Inno Setup-based Windows installer
  - User manual covering all features (PDF + HTML)

Standalone edition does not include cloud features. For cloud-based
fleet management, role-based access control, and signed deployments,
see the Whisker IDE Cloud edition.
