Skip to content

Data and Business Logic

Data model themes

The migration history shows the system has grown from core places/devices into a broader safety and operations platform.

Core entities

  • buildings, floors, zones
  • receivers/gateways
  • transmitters/beacons/assets/personnel-linked devices
  • current positions and historical raddec/ambient events

Operational domains added over time

  • emergency events, contacts, escalation, notification requests, rules
  • RBAC roles and permissions
  • audit logging and retention
  • analytics dashboards
  • weather schema
  • phone-as-beacon and phone enrollment tables
  • desktop gateway runtime metadata
  • BLE runtime tuning and positioning settings

Positioning pipeline

mermaid
flowchart LR
  A[Beacon observations] --> B[iotHub.js / ingest routes]
  B --> C[RSSI filtering]
  C --> D[Receiver selection + thresholds]
  D --> E[Trilateration or centroid]
  E --> F[Boundary / zone attribution]
  F --> G[Position smoothing]
  G --> H[current_positions + history]
  H --> I[Centrifugo + Nuxt floorplan]

What the code currently does

  • filters RSSI with Kalman logic
  • limits weak/noisy observations with configurable thresholds
  • supports trilateration, weighted centroid, and dominant/nearest receiver decisions
  • reconciles floor dimensions and percent-based map coordinates
  • smooths positions before writing/displaying them
  • attributes building/floor/zone after position resolution

Emergency workflow

mermaid
sequenceDiagram
  participant User as Operator
  participant UI as Nuxt emergency UI
  participant API as emergency.js
  participant DB as PostgreSQL
  participant Orch as notificationOrchestrator
  participant RT as Centrifugo

  User->>UI: Trigger event
  UI->>API: POST /emergency/trigger
  API->>DB: Create event + query people/contacts
  API->>Orch: Start scenario notifications
  Orch->>DB: Queue/send/escalate
  Orch->>RT: Broadcast updates
  RT-->>UI: Live emergency updates
  UI->>API: Refresh muster / confirmations / status

Current emergency business rules visible in code

  • scenarios such as manual, power outage, fire, medical, weather, shelter-in-place, drill
  • per-scenario channel choices and escalation timing
  • employee notification and escalation tracking
  • CSV export and history views
  • service-status visibility for SMS/email/voice providers

Additional ingestion paths

MikroTik KNOT ingestion (knotIngest.js)

MikroTik KNOT routers can POST BLE observations in their native JSON format directly to /api/knot/ingest. The route authenticates via X-Api-Key header (KNOTs cannot handle Bearer JWTs). The payload includes:

  • uid — gateway MAC address (becomes gatewayId)
  • timestamp — KNOT-format timestamp string (parsed via timestamps.js)
  • beacons[] — array of observed BLE devices with RSSI, raw ad packets, optional battery/temperature

After normalization, observations feed into the same positioning pipeline as Aruba Event Hub and Desktop Gateway input.

To configure on a KNOT device:

/iot/knot/set url=http://<api-host>:7071/api/knot/ingest
/iot/knot/set http-method=post
/iot/knot/set header="X-Api-Key: <KNOT_API_KEY value>"

Aruba ingestion (arubaIngest.js)

Accepts WiFi-derived location data from Aruba infrastructure in Aruba's native format. Normalizes and routes observations into the shared positioning pipeline.

RPA resolution (rpaResolver.js)

Phones with Bluetooth enabled rotate their MAC addresses using Resolvable Private Addresses (RPAs) to preserve user privacy. The backend resolves RPAs against stored Identity Resolving Keys (IRKs) using the Bluetooth Core Spec ah() function (AES-128-ECB). This links rotating phone addresses back to a registered phone beacon identity, so position tracking continues even when the MAC changes.

Outage detection

outageDetectionService.js monitors gateway heartbeat timestamps on a 30-second interval and classifies failures:

PatternThresholdClassification
One gateway offline, rest of building onlineSingle gateway failure
25–75% of building gateways offline simultaneouslyBUILDING_PARTIAL = 0.25Building partial outage
≥75% of building gateways offline simultaneouslyBUILDING_FULL = 0.75Building full outage (likely power)
Multiple buildings with full outagesCampus-level outage

A minimum of 2 gateways per building is required before outage patterns are classified. Gateway offline threshold is 90 seconds since last heartbeat.

Emergency IVR voice flow

ivrStateMachineService.js manages multi-level interactive voice response for emergency escalation calls:

  • main_menu — initial menu with options: confirm safe, request assistance, or transfer to safety officer
  • assistance_floor — captures floor number when assistance is requested
  • transfer — routes call to safety officer line
  • confirmed — records safety confirmation
  • assistance_requested — records assistance request and logs in emergency event

The IVR integrates with employeeEscalationService.js to update escalation records based on keypad responses.

Desktop gateway business flow

mermaid
flowchart LR
  A[Windows machine] --> B[Capture SSID/BSSID/DNS/subnet]
  B --> C[SiteDetectionEngine]
  C -->|ON_SITE| D[BLE scan + advertise]
  D --> E[Batch observations]
  E --> F[POST /desktop-gateway/heartbeat]
  E --> G[POST raddec observations]
  F --> H[gateway_health + receivers]
  G --> I[standard positioning pipeline]

Mobile and phone-beacon logic

  • Capacitor wraps the same Nuxt application instead of maintaining a second mobile codebase.
  • Phone badge onboarding and station flows live in the web app.
  • Phone beacon enrollment is public-token driven and uses native Bluetooth pairing.
  • The current UI explicitly shows native app requirement messaging and disabled store buttons when opened in a browser.

Data stewardship notes

  • Schema changes are additive and heavily migration-driven; do not edit production assumptions directly in old SQL files.
  • Receiver and transmitter identifiers appear in multiple ingestion paths, so normalization rules matter.
  • Many business flows depend on settings tables and runtime-config rows, not hard-coded constants alone.

NISC Muster Tracking Documentation