Skip to main content

Scan Events Guide

Scan events are the core processing unit in Tagnet. When RFID readers detect tags, the raw reads are ingested, grouped into meaningful scan events, and optionally trigger automated workflows. This guide explains the full lifecycle: from tag read ingestion through processing, windowing, cooldowns, and workflow execution.

Overview​

flowchart LR
A[RFID Reader] -->|Tag Reads| B[Ingest API]
B --> C[Scan Event Router]
C --> D[Processing Mode]
D --> E[Scan Event]
E --> F[Workflow Engine]

style A fill:#f0f0f0,stroke:#333
style E fill:#e8f4e8,stroke:#2d7d2d

The scan event pipeline has five stages:

StageWhat Happens
IngestionRaw tag reads arrive via API and are stored
RoutingReads are filtered by cooldown and routed based on processing mode
WindowingReads are accumulated into scan events based on timing rules
PersistenceCompleted scan events are saved with aggregated metrics
WorkflowMatching workflows are evaluated and executed

Viewing Scan Events​

The Scan Events List​

The Scan Events page (/scan-events) is a server-paged, searchable list. Search matches by device name or tag EPC. Filters narrow by Device, Device Group, Processing Mode, and Signature match. Every column can be shown or hidden from the column chooser on the grid header, and your choices are remembered between sessions.

The Source column shows what collected the event. For a single reader, it shows the device name. For a device group collecting across multiple readers (MultiTagPassage or shared windows), it shows the device group's name with a caption noting it was a group capture, since a multi-reader portal reads as one grouped event rather than being attributed to whichever reader happened to report first.

Two related views sit alongside the list:

  • Active Events (the /scan-events/active tab): a live view of in-flight scan windows still accumulating reads, refreshing every 2 seconds while the page is open. It lists each open window's device or group, tag count so far, and how long it has been open. This polling only runs while you have the page open, so the main Scan Events list itself has no refresh tick or layout shift.
  • Analytics (the /scan-events/analytics tab): fleet-wide event volume, tag activity, and outcome trends. Choose a time range (1h / 6h / 24h / 7d) and one or more device groups, and review summary tiles (total events, total tags, average duration, tags that did not match) alongside time-series charts. Data is aggregated into 15-minute buckets, so the most recent bucket can trail live activity by up to 15 minutes; a "Data through" caption shows how fresh the charts are.

Scan Event Details​

Click any row (or choose Details from the row actions menu) to open the event's own page at a stable, shareable URL (/scan-events/{id}), with four tabs:

Overview​

  • Overview: event id, device, device group (if applicable), processing mode, and status. Status says whether the event's workflows have run (see Scan Event Status); hover the chip for a one-line explanation.

  • Timing: First read and Last read mark the span of actual tag activity; Read activity is the duration between them. These are deliberately distinct from Closed at, since a window can stay open after its last read until a close timer fires. Closed by shows which timer fired:

    ReasonMeaning
    Quiet PeriodReads stayed silent for the full quiet period after the last read.
    Max DurationThe window reached its maximum duration before the quiet period elapsed.
    Service StopThe service stopped while the window was open, so it was closed early with the reads seen so far (see When the Service Stops).

    When shown, Quiet period and Max duration report the window settings in effect for this event (see Window Configuration).

  • Statistics: unique tags, mapped tags, total reads, and raw read count. Total reads is how many times the reader read the tags; raw read count is how many read records the reader sent. They match when the reader reports every read. Under a summary report filter each record stands for several reads, so total reads is the larger number (see Per-Tag Metrics).

  • Signature match: shown only for events compared with a read signature in use at the event's read point (its device group, or the reader itself when it is not in a group). Compared with names the signature, and Result gives the outcome (Matches / Partial match / No match / No tags) with counts of tags that match, do not match, or had too few reads to check. A tag with too few reads is not checked and does not count against the event, so an event whose checked tags all match is a full match even when some tags had too few reads. The list shows the same result in its Signature match column; an event that was not compared shows a dash, or a Settings changed chip when a reader's settings changed since the signature was captured (Not compared in the filter).

Tags​

A grid of every tag in the event: tag ID, mapped inventory item (or "Unmapped"), motion indicator, read count, dwell time, and peak RSSI. When the event was collected by a device group, an additional Reader column shows which reader in the group had the most reads for that specific tag, since different tags in a shared window can be picked up strongest by different antennas or readers. When the event was compared with a read signature, a Signature match column shows each tag's result. When the event came from a Zebra ATR7000, Zone, State and Direction columns show each tag's latest directionality event.

Raw Reads​

The individual tag reads that were aggregated into this event, lazy-loaded the first time you open the tab: timestamp, tag ID, mapped item, antenna, and RSSI for each read.

Analytics​

Time-series charts built from this event's own raw reads (for example, RSSI over time per tag), useful for understanding exactly what a reader saw during one specific event. This is distinct from the fleet-wide Analytics page described above.

Ingestion​

Tag reads are sent to Tagnet via the ingest API endpoint. Reads can be sent individually or in batches.

sequenceDiagram
participant Reader as RFID Reader
participant API as Ingest API
participant DB as Database
participant Router as Scan Event Router
participant RT as Real-Time Updates

Reader->>API: POST /api/v1/ingest/tag-reads
API->>DB: Store raw TagReadEvents
API->>DB: Update device LastSeen
API-->>Router: Route to scan event processing
API-->>RT: Broadcast via SignalR
API->>Reader: IngestResponse

Each tag read includes:

  • EPC: The unique identifier encoded on the RFID tag
  • RSSI: Signal strength (used for motion and proximity analysis)
  • Antenna: Which antenna port detected the tag
  • Time: When the read occurred
  • Phase / Channel: RF characteristics (used for motion detection)
  • Zone: Optional zone identification from the reader

Who can send reads​

Posting to the typed ingest endpoints (/api/v1/ingest/tag-reads and /api/v1/ingest/telemetry) needs the Ingest Reads permission and write access to the reader's access scope. The Admin and Contributor roles and the ApiInventory and ApiIntegration API key roles have the permission; ReadOnly, Operator, and ApiClient do not. A caller without the permission gets 403 Forbidden. A reader in a scope the caller cannot see answers 404 Not Found, exactly like an identifier that does not exist, so a key locked to one site cannot discover another site's readers. A reader the caller can see but not write to (a reader in the shared scope, for a user not explicitly assigned to it) answers 403 Forbidden. Administrators can send reads for any reader.

Zebra and Impinj readers that post directly to Tagnet are not affected: they sign in as the device itself, with the device credentials Tagnet created for them.

Reads are stored as raw TagReadEvent records for independent retention, then forwarded to the scan event router for processing. Ingestion is designed to never fail due to downstream processing issues. Routing errors are logged but do not reject the ingest request.

Processing Modes​

The processing mode determines how raw tag reads are grouped into scan events. Each device resolves its processing mode in this order:

  1. Device-level override (ProcessingModeOverride on the device): highest priority
  2. Device group default (ProcessingMode on the device group)
  3. System default: MultiTagPassage, with a 5 second quiet period and a 15 second max duration, if neither is configured

Readers that had no group and no settings of their own before Multi Tag Passage became the system default kept their old behavior on upgrade: Tagnet saved Single Tag Passage, a 2 second quiet period and a 30 second max duration as the reader's own settings, so its scan events did not change. You can see and change them on the reader's page.

flowchart TD
A[Tag Reads Arrive] --> B{Device has mode override?}
B -->|Yes| C[Use device override]
B -->|No| D{Device group configured?}
D -->|Yes| E[Use group mode]
D -->|No| F[MultiTagPassage default]

C --> G{Processing Mode}
E --> G
F --> G

G -->|Immediate| H[Create ScanEvent immediately]
G -->|SingleTagPassage| I[Per-tag windows]
G -->|MultiTagPassage| J[Shared device window]

Immediate Mode​

Each batch of tag reads creates a scan event right away with no windowing or accumulation. The event is closed immediately with reason Immediate.

Best for: Workstations, handhelds, and scenarios where each scan action is intentional and isolated.

SingleTagPassage Mode​

Each unique tag gets its own independent time window per device. A window opens when a tag is first seen and closes when that specific tag's quiet period elapses, regardless of activity from other tags.

This prevents a static tag (e.g., one mounted near the reader) from keeping a window open and blocking detection of transient tags passing through.

Best for: Portals and doorways where static and transient tags coexist.

MultiTagPassage Mode​

All tags read within a time window are combined into a single scan event per device (or device group). One shared window accumulates all tag reads together.

Best for: Loading docks, order fulfillment, and batch operations where multiple tags move together.

This is the system default: a pallet of 40 tags through a portal is one scan event and one run of each matching workflow, not 40. Two trade-offs come with it:

  • Static tags keep the window open. The window stays open while any tag keeps reading, so a reader that also sees tags that do not move (stock parked beside the portal, tags on the fixture) produces back-to-back events, each closed by the max duration, that all contain the static tags. Use Single Tag Passage at such a reader, or a read signature to filter the strays.
  • Workflows run after the quiet period. A window closes once no tag has been read for the quiet period, so workflows run at least 5 seconds after the last read of a pass by default.

Scan Event Windows​

For SingleTagPassage and MultiTagPassage modes, scan events are built using time-based windows. Windows accumulate tag reads in memory until closing conditions are met.

stateDiagram-v2
[*] --> Open: First tag read arrives
Open --> Open: More reads arrive (LastActivity updated)
Open --> Closed: Quiet period expires OR max duration reached OR service stops
Closed --> Processed: Persisted, then workflows run
Processed --> [*]

Window Lifecycle​

  1. Open: A window is created on the first tag read for a given device/group/EPC combination (depending on mode). The start time is recorded and last activity is tracked.
  2. Accumulating: As more reads arrive, they are added to the window. Tag-level metrics (RSSI, phase, antenna data) are aggregated in real time.
  3. Closed: The window closes when either condition is met:
    • Quiet period expired: No new reads for the configured quiet period duration
    • Max duration reached: The window has been open for the maximum allowed duration (hard ceiling, takes precedence)
    • Service stop: The Tagnet service is stopping while the window is still open (see When the Service Stops)
  4. Processed: The closed window is persisted as a ScanEvent with all aggregated tag data and metrics, and its workflows then run.

A background processor checks for closed windows every 500 milliseconds.

Window Configuration​

Windows are configured at the device group level:

SettingDescriptionDefault
Quiet PeriodHow long to wait with no new reads before closing5 seconds
Max Event DurationHard maximum for how long a window can stay open15 seconds

The quiet period acts as a "silence detector": once the reader stops seeing tags, the window closes after this delay. The max duration is a safety net that prevents windows from staying open indefinitely during continuous reads.

When the Service Stops​

A window lives in memory, so it would be lost if the service stopped while it was open. This happens on every upgrade, restart, Admin Console Restart, and automatic recovery restart. Instead of dropping the window, Tagnet saves every open SingleTagPassage and MultiTagPassage window as a scan event as the service stops, with the closed reason Service Stop. The event holds the reads seen up to that moment, and its detail page shows a note saying so.

Reads that arrive after the restart start a new window. For a pass that was cut off, this means two consecutive scan events from the same reader: one before the restart and one after.

  • Per-tag actions end up the same. Actions such as Move Inventory and Update Custom Fields act on each tag's current state, so every tag ends up where it should whichever event it landed in. A tag read on both sides of the restart appears in both events unless a cooldown filters it.
  • Whole-event logic sees two partial batches. A workflow that treats the scan event as one unit, such as a count check against an expected quantity or a single outbound message listing the whole batch, runs once for each half. If that matters at a dock door or portal, avoid planned restarts while a load is passing.
  • Windows that had already closed keep their normal reason. A window that had met its quiet period or maximum duration before the stop is saved as Quiet Period or Max Duration.
  • The stop has a time limit. If the service's shutdown timeout runs out first, the windows not yet saved are lost and the loss is written to the log. Raw reads are stored as they arrive, so they remain in the tag read history (when raw capture is on).

How Windows Differ by Mode​

flowchart TB
subgraph SingleTagPassage["SingleTagPassage Mode"]
direction TB
S1[Tag A reads] --> SW1[Window for Tag A]
S2[Tag B reads] --> SW2[Window for Tag B]
S3[Tag C reads] --> SW3[Window for Tag C]
SW1 --> SE1[ScanEvent 1]
SW2 --> SE2[ScanEvent 2]
SW3 --> SE3[ScanEvent 3]
end

subgraph MultiTagPassage["MultiTagPassage Mode"]
direction TB
M1[Tag A reads] --> MW1[Shared Window]
M2[Tag B reads] --> MW1
M3[Tag C reads] --> MW1
MW1 --> ME1[ScanEvent 1 - 3 tags]
end
  • SingleTagPassage: Tag A's window closes independently from Tag B's. If Tag A passes through a portal at 10:00 and Tag B at 10:05, they each get their own scan event.
  • MultiTagPassage: All tags feed into one shared window. If tags A, B, and C are read within the same time window, they produce a single scan event containing all three.

Cooldowns​

Cooldowns prevent the same tag from generating duplicate scan events in rapid succession. After a tag is included in a completed scan event, it enters a cooldown period during which subsequent reads of that tag are filtered out before scan event processing.

sequenceDiagram
participant Reader as RFID Reader
participant Router as Scan Event Router
participant Cooldown as Cooldown Service
participant Window as Scan Window

Reader->>Router: Tag reads (EPC: A, B, C)
Router->>Cooldown: Filter against active cooldowns
Note over Cooldown: EPC B is in cooldown
Cooldown->>Router: Filtered reads (EPC: A, C)
Router->>Window: Route filtered reads

Note over Window: Window closes, ScanEvent created
Window->>Cooldown: Record cooldowns for A, C
Note over Cooldown: A and C now in cooldown

Cooldown Scope​

The scope determines where the cooldown is enforced:

ScopeBehaviorExample Use Case
DeviceTag is only blocked on the device that created the scan eventA tag passing through Portal A can still be detected at Portal B
GroupTag is blocked on all devices within the same device groupPrevent duplicate events across multiple readers at the same loading dock
GlobalTag is blocked across the entire systemEnsure a tag is only processed once regardless of which reader sees it

Cooldown Configuration​

Cooldowns are configured at the device group level with optional device-level overrides:

  • Tag Cooldown (duration): How long a tag remains in cooldown after being processed. Set to null or leave unconfigured to disable cooldowns.
  • Tag Cooldown Scope: Device, Group, or Global

A Zebra ATR7000 is the exception: it never applies a cooldown, so each tag's Timed out event reaches workflows. See Zebra ATR7000 Directionality.

How Cooldowns Work Internally​

Cooldowns use a hybrid storage model for performance and reliability:

  • In-memory cache: Fast lookups during real-time filtering using a thread-safe dictionary
  • Database backup: Periodic sync (every 5 minutes) ensures cooldowns survive application restarts
  • Automatic cleanup: Expired cooldowns are removed by a background service

Scan Event Data​

When a scan event is persisted, Tagnet calculates and stores detailed metrics for analysis and workflow evaluation.

Per-Tag Metrics​

Each tag within a scan event includes:

  • Read count and dwell time: How many times and how long the tag was observed. A reader with a summary report filter (a Zebra FX reader with a non-zero report filter, or in Inventory mode) sends one record per tag per interval and says how many reads it covers; the read count adds those up, so it reflects what the radio did whatever the report filter. The read rate is the read count divided by the dwell time. A tag seen in only one report has no dwell, so its read rate is 0 and it is left out of read signature read-rate statistics.
  • Peak RSSI: Strongest signal strength observed
  • Primary antenna and device: Which antenna saw the tag most
  • RSSI statistics per antenna: Min, max, mean, and standard deviation
  • Phase statistics per antenna/channel: For motion analysis
  • Motion indicator: Whether the tag appears stationary, in slight movement, or in motion
  • Inventory item link: If the EPC is mapped to an inventory item, the association is recorded

Motion Detection​

Tagnet analyzes RF characteristics to determine whether a tag is moving or stationary, with no additional hardware or training required. The analysis uses:

  • Phase stationarity: How stable the phase angle readings are over time
  • RSSI variability: Standard deviation of signal strength across reads
  • Motion sensitivity: A configurable threshold (1–5) set at the device group level
IndicatorMeaning
StationaryTag is not moving (high phase stability, low RSSI variance)
SlightMovementTag may be shifting slightly
InMotionTag is clearly moving through the read zone
UnknownInsufficient data for a reliable determination

Phase stationarity requires the reader to report each individual tag read; a reader configured to report periodic summaries instead (a Zebra FX reader with a non-zero report filter, or in Inventory mode) has no phase data to analyze and every tag resolves to Unknown.

Workflow Execution​

After a scan event is persisted, it is placed onto an internal workflow queue for evaluation against configured workflows.

flowchart LR
A[ScanEvent Persisted] --> B[Workflow Queue]
B --> C[Workflow Engine]
C --> D{Evaluate Workflows}
D -->|Conditions Met| E[Execute Actions]
D -->|Conditions Not Met| F[Skip]
D -->|No Matching Tags| G[Skip]
E --> H[WorkflowExecution Record Created]

Event Conditions​

Each workflow's FROM clause decides which scan events it runs for (see FROM: which devices in the Workflows guide):

ChoiceBehavior
Any deviceEvery scan event the workflow's scope admits: the fleet for a shared workflow, the site for a site workflow
Matching conditionsOnly scan events whose device matches every condition row: by device, device group, device type, or device scope

Scan Event Status​

A scan event's Status tells you whether its workflows ran. It appears as a chip on the Scan Events list and the event's detail page.

StatusMeaning
OpenThe window is still collecting reads (shown on the Active Events tab).
WaitingThe event is saved and its workflows have not finished yet. It is queued or running.
ProcessedThe event's workflows ran. This does not mean any workflow matched; see Execution Statuses.
SkippedThe workflows did not run. The service restarted before they ran, and the Workflows / CatchUp policy was off or the event was older than its maximum age.
DroppedThe workflows did not run because the read point's workflow lane, or the whole workflow queue, was full (see Execution Flow).

The detail page shows a warning on a Skipped or Dropped event explaining why, so an event with no workflow runs is not mistaken for a configuration problem. The event itself, its tags, and its reads are saved either way. Events saved before this status existed all show Processed.

After a Restart​

The workflow queue is held in memory, so events still waiting (or cut off part-way through their workflows) when the service stops would otherwise never run. At startup, before Tagnet accepts new reads, the Workflows / CatchUp policy decides what happens to them: events no older than its maximum age (15 minutes by default) are run, oldest first; older events, or all of them when the policy is off, are marked Skipped. Events that do not fit in the workflow queue are marked Dropped. The Workflows Diagnostics tab reports what the last startup did.

Workflows that already finished for an event are not run again. A workflow that was cut off part-way has no run record and starts again from the beginning, so an action that ran before the cut, such as an HTTP call, can repeat.

Execution Flow​

  1. A completed scan event is placed on the workflow queue, in the lane for its read point (200 waiting events per lane, 1,000 overall)
  2. A background service consumes each lane in order; different readers' lanes run in parallel
  3. The workflow engine evaluates each applicable workflow, one at a time in run order, so each one sees what the workflows above it did:
    • Checks the workflow's event conditions (any device, or rows on device, group, type and scope); a miss records nothing
    • Applies the workflow's tag conditions to select the tags
  4. If the event conditions are met and matching tags exist, the workflow actions are executed
  5. A WorkflowExecution record is created tracking the result

Execution Statuses​

StatusMeaning
ConditionsMetEvent and tag conditions were met and actions were executed
ConditionsNotMetReserved; an event condition that is not met records nothing
NoMatchingTagsEvent conditions were met, but no tags matched the workflow's tag conditions

End-to-End Flow​

Putting it all together, here is the complete lifecycle of tag reads becoming actionable events:

flowchart TD
A[RFID Reader detects tags] --> B[POST to Ingest API]
B --> C[Store raw TagReadEvents]
B --> D[Update device LastSeen]
B --> E[Broadcast via SignalR]
B --> F[Route to Scan Event Router]

F --> G{Filter against cooldowns}
G -->|Tag in cooldown| H[Tag filtered out]
G -->|Tag not in cooldown| I{Resolve processing mode}

I -->|Immediate| J[Create ScanEvent immediately]
I -->|SingleTagPassage| K[Add to per-tag window]
I -->|MultiTagPassage| L[Add to shared device window]

K --> M{Window close condition met?}
L --> M
M -->|Quiet period expired| N[Close window]
M -->|Max duration reached| N
M -->|No| O[Continue accumulating]

J --> P[Persist ScanEvent with metrics]
N --> P

P --> Q[Record cooldowns for processed tags]
P --> R[Enqueue for workflow processing]
R --> S[Evaluate matching workflows]
S --> T[Execute workflow actions]

Configuration Summary​

SettingLevelDescription
Processing ModeDevice GroupImmediate, SingleTagPassage, or MultiTagPassage (default: MultiTagPassage)
Processing Mode OverrideDeviceOverride the group's processing mode for this device
Quiet PeriodDevice GroupInactivity timeout before closing a window (default: 5s)
Quiet Period OverrideDeviceOverride the group's quiet period for this device
Max Event DurationDevice GroupHard maximum window duration (default: 15s)
Max Event Duration OverrideDeviceOverride the group's max event duration for this device
Tag CooldownDevice GroupDuration a tag is suppressed after processing
Tag Cooldown OverrideDeviceOverride the group's cooldown for this device
Tag Cooldown ScopeDevice GroupDevice, Group, or Global
Motion SensitivityDevice GroupMotion detection threshold (1–5, default: 3)
Workflow event conditionsWorkflowAny device, or rows on device, group, type and scope