# Plate reader (ALPR)

The ALPR reads the plates of cars around you and runs them automatically, without a manual plate lock. **Only flagged vehicles raise an alert**; clean plates stay silent.

Each hit gives two notifications (plate, vehicle and direction, then owner, statuses and flags) and an audio cue. ALPR only runs while the plate reader is showing (`/togglepr`).

> [!NOTE]
> ALPR runs plates through c3r's own records by default (`provider = 'c3r'`), so no CAD is needed. It can use CDE CAD or ImperialCAD instead. With `provider = 'none'`, plates are still read and shown, just never run.

## Alerts

| Flag | Means |
|---|---|
| **Stolen Vehicle** | Marked stolen in the CAD |
| **Impounded Vehicle** | Marked impounded in the CAD |
| **Expired Registration** | Registration not valid or active |
| **No Insurance** | Insurance missing or invalid |
| *CAD flags* | Anything else your CAD returns: warrants, BOLOs, dangerous or missing person, your own custom flags (CDE CAD only) |

Custom flags come through as they are, so a flag you add in the CAD shows up in game without touching the radar.

A flagged car also flashes on the map for `blipSeconds` (10 by default): red for stolen cars and BOLOs, yellow for bad papers. `0` turns it off.

## With CODE3RESPONSE

- It reads c3r's own records and flags stolen cars, BOLOs, expired registration and no insurance.
- As you drive, it also turns up the odd stolen or expired car in traffic (`Config.AlprChance`, about 1 car in 150), and pulling it over finds that same car. Only moving cars with an NPC at the wheel: never parked cars, units, emergency vehicles, or players' or scripts' cars.
- Results aren't cached with this provider, and a new BOLO skips the rescan wait, on every unit.
- Without c3r running, it prints one warning in the console and does nothing. Set `provider` to something else.

## Setup: CDE CAD

Your credentials go in `server.cfg`, not in the config. Most communities already have these set from CDE's own resource.

1. Generate a FiveM API key in your CDE CAD **Admin Panel → FiveM Settings**.
2. Add to `server.cfg`:
   ```cfg
   set CDE_CAD_API_URL      "https://your-cdecad-instance.com/api"
   set CDE_CAD_API_KEY      "fvm_your_api_key"
   set CDE_CAD_COMMUNITY_ID "your-discord-guild-id"
   ```
3. Set `Config.alpr.provider = 'cde'` in `shared/config.lua`.

## Setup: ImperialCAD

Runs through the ImperialCAD resource, so the radar never handles your API key.

1. Install and start [ImperialCAD](https://docs.imperialcad.app).
2. Put your credentials (**Admin Panel → Settings → API**) at the top of `server.cfg`, above `ensure ImperialCAD`:
   ```cfg
   setr imperial_community_id "yourCommunityId"
   set imperialAPI "yourApiKey"
   ```
3. Set `Config.alpr.provider = 'imperial'`.

ImperialCAD doesn't return a vehicle's make, model or colour, so those alerts show the plate and flags only. It has no impound field either: a registration status containing "impound" raises the impound flag. Business-owned plates are marked `(Business)`.

## Scan settings

```lua
Config.alpr = {
    provider = 'c3r',          -- 'none' | 'c3r' | 'cde' | 'imperial'
    radius       = 25.0,       -- metres around you that plates are read
    rescanDelay  = 300,        -- seconds before the same plate is read again
    scanInterval = 200,        -- ms between scans
    blipSeconds  = 10,         -- how long a flagged car flashes on the map; 0 for no blip
    cacheMinutes = 60,         -- how long a result is reused; 0 looks up every sighting
    lockCooldown = 120,        -- seconds before re-locking the same plate asks the CAD fresh again
    maxQueriesPerMinute = 60,  -- per player; 0 for no limit
    discordWebhook     = '',   -- posts flagged hits to Discord
    discordWebhookName = 'ALPR System',
}
```

With a CAD, results are cached so a unit sat in traffic doesn't hammer it, and the cache survives a restart. The catch is staleness: a car reported stolen five minutes ago reads clean until its entry expires. **Locking a plate skips the cache** and asks the CAD there and then, at most once every `lockCooldown` seconds per plate. Lower `cacheMinutes` if your CAD data changes fast, or clear it with `exports.seeker_dual:ClearAlprCache()`. `/alprcache` in the server console shows what's cached.

Lookups over the per-minute limit aren't lost: they're retried on a later pass.

## Discord

Set `discordWebhook` and every flagged hit posts an embed with the plate, direction, vehicle, owner and flags: red for stolen or impounded, yellow for registration and insurance. Clean plates never post.
