📡 RDS AI Decoder – Documentation v2.7
📡

RDS AI Decoder

Plugin Documentation
Server Plugin: rds-ai-decoder_server.js
Client Plugin: rds-ai-decoder.js
Version: 2.7
Author: Highpoint
Date: 2026
v2.7

Table of Contents

1What is RDS?
2Why an AI Plugin?
3What's New in Version 2.7 (and prior)
4Architecture – The Two Plugin Components
5Simple Explanation – How the Plugin Works
5.1Learning by Voting
5.2fmdx.org Reference Database
5.3PS Lock Engine and Hybrid Case
5.4Provisional → Locked Status Display
5.5Frequency Change and Pre-Cache
5.6Dynamic vs. Static Stations & Timeout
5.7Alternate Frequency (AF) Decoding
5.8RDS Follow Mode & Admin Padlock v2.6
5.9Special / Wildcard PI Codes
5.10Regional PI Codes (PIreg)
5.11The Panel – Display Elements
5.12Extended FMDX Station Data
5.13Local Database Management
6Technical Deep Dive
6.1RDS Group Structure and Error Correction
6.2Smart Propagation Score & Spatial Awareness v2.6
6.3PS Lock Engine – Priority Ladder
6.4Provisional → Locked Status Engine
6.5Voting Engine – Compact Aggregation Format
6.6Confidence Calculation
6.7PI Verification Pipeline & Hysteresis Limits
6.8Database Format, Auto-Wipe & 5-Min SpE Cache v2.6
6.9WebSocket Protocol and Delete Logic
6.10dataHandler Patch – Property Locking
6.11FMDX.ORG Panel – Frequency Chips and AF Coverage
6.12GPS WebSocket Listener
6.13Panel State Persistence
7REST API Reference
8Configuration Parameters
9Troubleshooting & FAQ

1 · What is RDS?

RDS (Radio Data System) is a digital communication standard that transmits data as an inaudible signal modulated onto FM broadcasts (87.5–108 MHz). It was standardised under ETSI EN 50067 and has been in use across Europe since the 1980s. In North America, a nearly identical standard exists called RBDS.

RDS carries a variety of continuous digital metadata alongside the analog audio signal. The most commonly used data fields are:

Code Name Meaning Size
PI Programme Identification Unique 16-bit station identifier (hex, e.g. D3C3). Essential for auto-tuning. 16 bit
PS Programme Service Name Station name, max. 8 characters (e.g. "NRJ ") 8 × 8 bit
RT RadioText Scrolling text, max. 64 characters (title, artist, show name) 64 × 8 bit
PTY Programme Type Programme category (0–31, e.g. 10 = Pop Music) 5 bit
TP Traffic Programme Flag indicating if the station broadcasts traffic announcements 1 bit
TA Traffic Announcement Flag indicating if a traffic announcement is currently active 1 bit
AF Alternate Frequencies List of alternative frequencies carrying the same programme 8 bit each
ECC Extended Country Code Extended country identifier (combined with PI nibble to determine country) 8 bit

RDS transmits at 1,187.5 bit/s as a BPSK signal on a 57 kHz subcarrier. A complete basic data block containing PI, PTY, TP, and two characters of the PS name requires 104 bits (26 bits per block × 4 blocks). A complete 8-character PS transmission takes approximately 0.35 seconds under perfect, error-free conditions.

2 · Why an AI Plugin?

Under local reception conditions with a strong antenna, RDS decoding is instantaneous and error-free. However, during long-distance FM reception (DX) – especially via tropospheric ducting, meteor scatter, or Sporadic-E propagation – signals are often extremely weak, rapidly fading, and severely affected by multipath interference or co-channel interference.

When the signal-to-noise ratio drops, the native RDS decoder built into the receiver chips (like TEF6686 / NXP) struggles:

Plugin Goal: Rather than relying on the receiver's real-time, volatile interpretation of the data, the AI Decoder intercepts the raw bitstream before it reaches the UI. By collecting and statistically evaluating thousands of received packets – including those flagged with minor errors – a highly reliable probability model of the station is constructed.

Known stations are recognized instantly from the FMDX.ORG database. Corrupted characters are filtered out mathematically, and the web interface is fed a stable, perfectly locked station name, completely eliminating UI flicker.

3 · What's New in Version 2.7 (and prior)

Version 2.7 introduces powerful raw data recording and enhanced visual identification, building upon the spatial awareness and UI features of the 2.6 series.

1. Server-Side Raw RDS Recording & CSV Export v2.7

A new Record button (⏺) has been added to the panel header. To ensure stability and zero memory leaks during long recording sessions, recording is now handled entirely on the server side. Only logged-in Administrators can start or stop the recording. When activated, the server streams all incoming raw RDS groups, block hex codes, error levels, and the AI's real-time prediction data directly into a CSV file in the ../../web/logs directory. Stopping the recording automatically provides a download link to the RDS_RAW_YYYYMMDD_HHMM.csv file, perfectly formatted for later analysis in the standalone RDS RAW Decoder web tool.

2. ITU Country Code Integration & Flag Display v2.7

The server plugin now extracts the precise ITU (International Telecommunication Union) country code from the FMDX reference database and transmits it over the WebSocket. The client UI uses this ITU code to seamlessly display the corresponding national flag next to the predicted station name, using a robust external countryList and a fallback flag server with a 404-loop prevention mechanism.

3. Spatial Awareness (SpE Cloud Tracking) v2.6

The AI now calculates the geometric center of the currently active Sporadic-E cloud. It tracks countries (ITU) and azimuth angles of all DX stations received in the last 5 minutes. During PI collisions, candidates aligning with the active cloud receive massive bonus points, effectively eliminating false logs from other directions.

4. 5-Minute SpE Cache & Dummy-PI Blocker v2.6

Stations received via Sporadic-E (>800km) are now aggressively purged from the local memory exactly 5 minutes after signal loss, preventing long-term PI blocking. Furthermore, "Dummy PIs" (like 1060 in Spain/Italy) are strictly validated: single candidates are now rejected if live PS characters conflict with the FMDX database.

5. Long-Press Navigation & Public Padlock v2.6

The RDS Follow toggle has been moved from the AI panel to the main Webserver navigation bar via a Long-Press action (600ms). Additionally, a new Padlock (🔒/🔓) allows Admins to unlock the RDS Follow feature, granting public guest users the ability to toggle the AI decoder.

6. Database One-Time Wipe Mechanism v2.6

To safely handle database schema updates without user intervention, a seamless One-Time-Wipe routine triggers on `DB_VERSION` bumps. It automatically resets cached memory while perfectly preserving your administrative lock and follow settings.


7. Dynamic PS Timeout & Strict Live Detection v2.5a

Dynamic mode is now 100% driven by live signal analysis. If scrolling text stops and reverts to a static station name for 50 consecutive RDS frames (~20–30 seconds), the plugin will automatically drop out of dynamic mode and lock onto the static name.

8. Distance-Based Confirmation Thresholds v2.5a

To further suppress "Ghost PIs", v2.5a introduced a dynamic Distance-Based scale: <300km requires 2 hits, 300-800km requires 4 hits, and >800km requires 6 hits for PI confirmation.

9. Meteor Scatter & Ghost PI Suppression v2.4g

Anti-Hallucination (Scatter Mode): If a PI code is received via a brief scatter ping, but zero PS characters are decoded, the AI will not hallucinate the station name from the FMDX database. The PS field remains accurately blank.

10. Local Truth Override (FMDX Bypass) v2.4g

If the receiver decodes an 8-character PS string with 100% mathematical perfection, the AI trusts the live signal over the global database to support local test transmitters and rebrands.

11. Dynamic Tie-Breaker & Sporadic-E Protection v2.4f

When two stations share the exact same PI code on the same frequency, the AI requires hard physical evidence to break the tie: either matching Alternate Frequencies (AF) or a strict 100% match of at least 3 cleanly received PS characters.

12. Smart Propagation Scoring v2.4

The calculatePropagationScore() algorithm uses real-world RF propagation physics to pick the most logical transmitter, evaluating ERP, Site Verification (AF network), and historical records.

4 · Architecture – The Two Plugin Components

┌──────────────────────────────────────────────────────────────────────┐ │ WEB SERVER (Node.js) │ │ │ │ ┌────────────┐ RDS data stream ┌──────────────────────────────┐ │ │ │ Receiver │ ─────────────────▶ │ datahandler.js │ │ │ │ Hardware │ │ (native decoder) │ │ │ │ TEF6686 / │ └──────────────┬───────────────┘ │ │ │ TEF6687 │ │ Patch-Hook │ │ └────────────┘ ┌────────────────────────▼──────────────┐ │ │ │ rds-ai-decoder_server.js v2.7 │ │ │ │ │ │ │ │ • fmdx.org Bulk Index (3000 km) │ │ │ │ • Spatial Awareness (v2.6) │ │ │ │ • 5-Min SpE Cache Wipe (v2.6) │ │ │ │ • ITU Code Transmission (v2.7) │ │ │ │ • Server-Side CSV Recording (v2.7) │ │ │ │ • Distance-Based Thresholds │ │ │ │ • Voting Engine + PS Lock │ │ │ │ • Provisional→Locked state engine │ │ │ │ • AF / ECC / Country Decode │ │ │ │ • AI Prediction Builder │ │ │ │ • dataHandler property locking │ │ │ └──────────────┬────────────────────────┘ │ │ │ │ │ maps.fmdx.org ◀───── HTTP fetch ──────┤ │ │ config.json ◀──── lat/lon / port ─────┤ │ │ rdsm_memory.json ◀───── persist ──────┤ │ │ rdsm_fmdx_cache.json ◀── bulk cache ──┘ │ └──────────────────────────────────────────────────────┬───────────────┘ │ WebSocket /data_plugins│ ┌──────────▼────────────┐ │ User's Browser │ │ │ │ rds-ai-decoder.js │ │ v2.7 │ │ • Recording UI & Admin Control (v2.7)│ │ • Flag Rendering Engine (v2.7) │ │ • Main Nav Long-Press│ │ • Admin Padlock UI │ │ • FMDX.ORG Panel │ │ • LOCAL DB + Delete │ └───────────────────────┘

The plugin is strictly split into two layers:

  1. The Server Layer (Node.js): This intercepts the low-level hex data arriving from the TEF chip over the serial connection. It performs all the heavy lifting: downloading the 30MB FMDX index, calculating SpE cloud direction, managing the persistent local JSON database, running the statistical weighting engine, recording the raw CSV file on disk, and eventually forcibly overwriting the output of the native datahandler.js when RDS Follow Mode is enabled.
  2. The Client Layer (Browser): A pure frontend UI written in vanilla JavaScript. It connects directly to the server plugin via a dedicated WebSocket channel. It performs no decoding logic of its own; it exists solely to draw the beautiful debugging panels, handle the Long-Press navigation integration, render the active flag via the ITU code, trigger server-side CSV recording (Admins only), and capture Admin commands like database deletions and Padlock toggles.

5 · Simple Explanation – How the Plugin Works

5.1 · Learning by Voting

The station name (PS) consists of 8 character positions. Each position is voted on separately. The receiver hardware flags every 16-bit block with an "Error Level" from 0 (perfect) to 3 (unrecoverable).

When the AI Decoder receives a raw PS character (e.g. at position 0), it looks at the hardware error level:

Received packets for position 0: Packet 1: 'N' (error=0, weight=10) ──┐ Packet 2: 'N' (error=0, weight=10) │ Voting Packet 3: 'M' (error=1, weight= 5) │ for position 0 Packet 4: 'N' (error=0, weight=10) │ Packet 5: '?' (error=2, weight= 0) ──┘ (discarded) Result: 'N' = 30 points ← Winner 'M' = 5 points

These points are accumulated in the server's memory. As time passes, the points decay (using a 7-day half-life formula). This allows the plugin to "forget" old corrupted data while strongly favoring a consistent signal. After enough votes, a reliable station name emerges.

5.2 · fmdx.org Reference Database

On startup (and automatically every 6 hours) the plugin downloads the full FM transmitter database from maps.fmdx.org/api/?qth={lat},{lon} centred on the receiver's own location. All transmitters within a radius of 3000 km are indexed into two lightning-fast in-memory lookup tables.

Each fmdx.org entry provides:

Strict PI gate: The plugin only displays an fmdx.org reference entry when the received PI code (or its PIreg equivalent) is explicitly listed for the exact currently tuned frequency. A PI that appears on a different frequency in the database does not count as a match and is silently skipped.

5.3 · PS Lock Engine and Hybrid Case

Once a PS name has been determined with high confidence, it is locked – the displayed name stops changing until the frequency or PI code changes. This totally eliminates UI flickering.

The lock is achieved through three priority levels:

Priority A – DB verified string: Previously stored psVerifiedRaw ─────▶ LOCK immediately (entire PS received error-free in one round, stored in DB) Priority B – fmdx.org match ≥ 75%: Live buffer matches a known PS variant ─▶ LOCK with hybrid PS (raw RDS case preserved where characters agree with reference) Priority C – Full raw verification: All 8 positions received with errLevel ≤ 1, all characters non-space, one complete round ─▶ LOCK + store

The Hybrid Case System: Many stations transmit their PS names in ALL CAPS (e.g. ANTENNE ) but they look terrible in the UI. FMDX.org contains beautifully formatted mixed-case variants (e.g. Antenne ). The plugin uses a Hybrid Constructor: if the live received uppercase letter mathematically matches the reference mixed-case letter at the exact same position, the plugin swaps in the beautiful mixed-case letter before sending it to the web server.

Local Truth Override: If all 8 positions are received with error level 0 or 1, the AI trusts the live signal over the global database, overriding the strict FMDX sanity filter.

5.4 · Provisional → Locked Status Display

Before a PS name is fully locked, the decoder goes through an intermediate provisional stage. This state is communicated to the user via the STATUS row in the panel.

StateBadge colourConditionAdditional info shown
WAIT Dark grey (neutral) Default on start / after frequency change. Not enough data yet. "collecting…"
PROVISIONAL Amber (#c8a020) A candidate PS exists with confidence ≥ 55% but is not yet locked. Confidence % · stable time in seconds (e.g. "72% · stable 1.5s")
LOCKED Green (#44ff88) Confidence ≥ 90% and stable, OR strong fmdx.org match, OR raw-verified. Reason for lock (e.g. "FMDX match 100%" or "DB verified string")

5.5 · Frequency Change and Pre-Cache

When you change frequencies, the native decoder usually blanks out completely. The AI plugin behaves differently. Because it stores historical data in rdsm_memory.json, the moment you tune to a new frequency, it looks up known transmitters for that frequency.

If it finds a station in its memory that matches the frequency, it instantly prepares the "Predicted PS" and displays it in the statistics panel, even before a single RDS packet has been received from the antenna. If RDS Follow Mode is enabled, this cached prediction is immediately pushed to the web UI.

5.6 · Dynamic vs. Static Stations & Timeout

Some stations unfortunately use their PS field to transmit scrolling text (song titles, phone numbers). The AI decoder features a Dynamic Jump Engine to detect this.

When a station is flagged as dynamic (⚡), the statistical voting engine is bypassed, because voting on scrolling text produces absolute garbage. Instead, the plugin switches to a raw pass-through mode.

The 50-Frame Timeout: If the text stops scrolling and reverts to a static station name for 50 consecutive RDS frames (~20–30 seconds), the plugin automatically drops out of dynamic mode and firmly locks onto the static name.

5.7 · Alternate Frequency (AF) Decoding

The Alternate Frequency list is transmitted as a highly compressed set of 8-bit codes. The plugin decodes these codes according to the standard ETSI table (Method A).

The decoded frequencies are maintained in a Set to guarantee uniqueness. In the UI, the AF badge illuminates and displays the total count. Hovering over the badge reveals the exact list of frequencies.

5.8 · RDS Follow Mode & Admin Padlock v2.6

By default, the AI Decoder operates purely as an invisible observer. It draws its own floating statistics panel but does not alter the main web interface (the large blue PS blocks and RadioText banner at the top of the FM-DX-Webserver page).

Activating RDS Follow Mode forces the AI to intercept the data pipeline and inject its mathematically stabilized, FMDX-verified PS strings and RadioText directly into the main web server UI.

UI Interaction:

5.9 · Special / Wildcard PI Codes

Certain PI codes are considered invalid or uninformative by the standard, particularly 0000 and FFFF. Cheap transmitters or pirate stations often use these.

If the plugin detects 0000 or FFFF, it skips database lookup, FMDX verification, and statistical voting. It acts purely as a raw pass-through.

5.10 · Regional PI Codes (PIreg)

In many countries, national networks broadcast identical programming on dozens of transmitters, but insert local news for 5 minutes an hour, temporarily switching their PI code to a "Regional" PI code.

The FMDX database download brings both the Primary PI and the Regional PI. If the plugin detects the Regional PI, it mathematically treats it exactly the same as the Primary PI, locking instantly without rebuilding its statistical profile.

5.11 · The Panel – Display Elements

The floating AI panel is divided into sections:

5.12 · Extended FMDX Station Data

When the statistics panel is expanded, a golden highlighted section appears displaying:

5.13 · Local Database Management

The LOCAL DB section queries the server's rdsm_memory.json and extracts all stations seen on the currently tuned frequency. It shows the PI code, the locked PS string, dynamic status (⚡), and seen count.

Deletion: Logged-in Administrators will see a red next to every entry. Clicking this deletes a "Ghost PI" from the server's permanent memory immediately.

6 · Technical Deep Dive

6.1 · RDS Group Structure and Error Correction

An RDS data stream consists of consecutive "Groups", each 104 bits long, split into 4 Blocks (A, B, C, D). Each block contains 16 bits of payload and 10 bits of Checkword.

The native receiver chip assigns an error level from 0 to 3:

The AI decoder strictly ignores any payload data from a block that has an error level of 2 or 3. Only levels 0 and 1 are permitted into the voting algorithms.

6.2 · Smart Propagation Score & Spatial Awareness v2.6

Selecting the correct transmitter when multiple sites share a PI code relies on the calculatePropagationScore() algorithm combined with a new Spatial Awareness Engine.

Base Scoring factors:

Spatial Awareness (SpE Cloud Tracking) v2.6:
When a PI collision occurs for candidates >800km, the AI scans all active DX stations logged in the last 5 minutes. It extracts their ITU country codes and Azimuths.

This completely overrides the base score, ensuring that a Spanish station with PI 1060 wins when the band is open to Spain, rather than a Greek station with PI 1060 that happens to be mathematically closer.

6.3 · PS Lock Engine – Priority Ladder

The checkAndLockPS(pi) function runs every time a new RDS packet arrives. Priority ladder:

  1. If a fully verified string already exists in the local database (entry.psVerifiedRaw), use it.
  2. If the live buffer characters match an FMDX.org reference string at >75%, construct a hybrid string and lock it.
  3. If 8/8 characters are received error-free directly from the airwaves, lock and store as psVerifiedRaw.

Single-Candidate Strict Validation (Dummy-PI Blocker) v2.6:
Previously, if the database only returned one candidate for a PI/Frequency combo, it was trusted blindly. Now, if the live received characters heavily conflict with that single candidate's FMDX name, the candidate is rejected entirely. This blocks uncoordinated "Dummy PIs" (like 1060 in Spain) from incorrectly logging the only official 1060 station (in Greece).

6.4 · Provisional → Locked Status Engine

The client UI calculates the STATUS string based on boolean flags and confidences sent by the server:

6.5 · Voting Engine – Compact Aggregation Format

Votes are stored in rdsm_memory.json in a compact format:

"ps": {
  "0": {
    "N": {
      "w": 45.2,
      "count": 120,
      "firstSeen": 1712849200,
      "lastSeen": 1712850000
    }
  }
}

The weight (w) decays mathematically based on the time elapsed since lastSeen, using the VOTE_HALFLIFE_DAYS constant (7 days).

6.6 · Confidence Calculation

Confidence is a floating point number between 0.0 and 1.0. It is calculated by blending:

6.7 · PI Verification Pipeline & Hysteresis Limits

The threshold for verification is dynamic based on calculated FMDX distance:

Hysteresis Bonus Limit v2.6:
Previously, the memory system granted a 2000-point "superglue" bonus to a station if it was successfully locked, preventing jumps during fading. In v2.6, this bonus is strictly disabled for distances >800km because SpE clouds are too volatile and a 2000-point bonus would suppress genuine, fast-changing PI collisions.

6.8 · Database Format, Auto-Wipe & 5-Min SpE Cache v2.6

The local database rdsm_memory.json is saved automatically every 60 seconds. Memory is capped at MAX_STATIONS = 2000.

5-Minute Aggressive SpE Purge v2.6:
Any station logged with a calculated distance ≥800km is now assigned an aggressive SPE_EXPIRE_MINUTES timer (default 5 minutes). Exactly 5 minutes after the signal fades, the station is completely wiped from memory. This ensures that a SpE spaniel doesn't permanently block a local station that shares the same PI code later in the day.

One-Time Auto-Wipe Mechanism v2.6:
When the server boots, loadDB() checks the `DB_VERSION` variable. If it detects a mismatch (schema update), it safely extracts the Admin's `rdsFollowMode` and `rdsFollowLocked` preferences, dumps all memory caches to prevent corruption, and saves a fresh versioned database instantly.

6.9 · WebSocket Protocol and Delete Logic

The client and server communicate via a standard JSON WebSocket protocol. The server broadcasts payloads of type: 'rdsm_ai' continuously.

Client commands:

{
  "type": "rdsm_delete_pi",
  "pi": "D3C3"
}

And the new lock command v2.6:

{
  "type": "rdsm_set_rds_lock",
  "locked": false
}

6.10 · dataHandler Patch – Property Locking

To override the native datahandler.js, the server plugin intercepts the variables via Object.defineProperty getters/setters before they are dispatched via the main Webserver WebSockets. It overwrites dataHandler.dataToSend.ps and dataHandler.dataToSend.pi with the mathematically verified AI strings.

6.11 · FMDX.ORG Panel – Frequency Chips and AF Coverage

The client UI calculates the "AF Coverage %" by extracting the Alternate Frequencies from the active FMDX.org JSON reference block and comparing it against the live currentState.afSet. It generates a horizontally scrolling UI of Frequency Chips that highlight blue when a match occurs.

6.12 · GPS WebSocket Listener

The server plugin connects to `ws://127.0.0.1:8080/data_plugins` to listen for GPS payloads. Coordinates are rounded to ~1km (`roundGps`), and a 30MB FMDX index rebuild is only triggered if the distance moved exceeds FMDX_REINDEX_MIN_DIST_KM (100km).

6.13 · Panel State Persistence

The frontend hooks into the `mouseup` event of the drag handler. It reads `el.style.left` and `el.style.top` and dumps a JSON object into `window.localStorage.setItem('rdsm_panel_pos')`. On page load, this is parsed and injected directly into the DOM CSS properties.

7 · REST API Reference

While the AI Decoder communicates primarily over WebSockets for live data, it exposes a silent footprint on the main HTTP API of the FM-DX Webserver.

When polling the /api endpoint of the server, standard RDS fields are replaced by the AI if Follow Mode is active:

{
  "freq": "104.600",
  "pi": "D3B8",
  "ps": "RTL     ",
  "pty": 10,
  "rds": true,
  "ta": 0,
  "tp": 1,
  "ms": 1,
  "af": [89000, 104600],
  "rt0": "RTL - BERLINS HITRADIO",
  "country_name": "Germany",
  "country_iso": "DE"
}

If Follow mode is disabled, the /api returns the native hardware decoding results, which may contain spaces or errors like "R L ".

8 · Configuration Parameters

Advanced users can tweak the constants at the top of rds-ai-decoder_server.js to tune the AI behavior.

Parameter Default Description
VOTE_HALFLIFE_DAYS 7 Days before a vote loses 50% of its weight.
VOTE_EXPIRE_DAYS 30 Days before an old vote is completely purged from memory.
STATION_EXPIRE_DAYS 90 Days before an inactive local/tropo station is deleted from memory.
SPE_EXPIRE_MINUTES 5 Minutes before an inactive SpE station (>800km) is purged to prevent PI collisions. v2.6
FMDX_RADIUS_KM 3000 Radius in km for downloading transmitters from maps.fmdx.org.
PROVISIONAL_MIN_CONF 0.55 Confidence threshold (0.0 to 1.0) to enter the Amber PROVISIONAL state.
LOCK_MIN_CONF 0.90 Confidence threshold to turn Green and LOCK the PS name permanently.

9 · Troubleshooting & FAQ

The FMDX match says 0% even though the station is correct.

This happens when the FMDX database variant uses special characters, differing casing, or abbreviations that mathematically clash with the raw data. The AI will eventually lock onto the Raw RDS string instead of the FMDX variant.

The panel is stuck on "WAIT collecting..." forever.

The signal is too weak, or the TEF chip is dropping every packet with Error Level 2 or 3. If the hardware cannot deliver a single Level 1 packet, the AI has nothing to vote on.

I clicked the red ✕ to delete a PI, but it came back instantly!

If you are still tuned to the frequency and the hardware is still decoding that exact PI code from the noise floor, the plugin will instantly recreate the memory entry. Tune away to a blank frequency before purging ghost PI codes.

Why does the "RDS Follow" toggle text light up red?

By default, the AI Decoder operates in a secure Admin-Only mode. The red text and padlock (🔒) indicate that only logged-in Administrators can turn RDS Follow on or off (via Long-Pressing the main navigation button). Click the padlock to unlock it (🔓) and allow public users to toggle the AI, which turns the text green.

Why does the Record button (⏺) show a warning?

Raw RDS recording is processed on the server and saved directly to the webserver's logs folder. To prevent abuse and storage issues, only logged-in Administrators can start or stop recordings.

My GPS coordinates drifted and caused a massive lag spike.

Ensure your GPS hardware has a solid lock. The plugin mitigates GPS jitter by rounding to ~1km and requiring a 100km total movement before triggering the 30MB FMDX index rebuild. If you see constant console logs about "fmdx.org index built", your coordinates in `config.json` might be oscillating wildly due to a bad script pushing fake GPS data to the websocket.