All projects
Full Stack case study

Accellum

An IoT operations platform that turns MQTT card and gateway signals into device health, checkpoints, access history, and live dashboards.

TL;DRProject ownerJul 2025 – 2026

Turns noisy Bluetooth signals into reliable entry, exit and live occupancy.

Role
Full stack and deployment
Ownership
Project owner, end to end
Core stack
TypeScript · Nuxt.js · Vue.js · NestJS · MQTT
The problem

BLE gateways report every card they hear several times a second. Raw detections flicker, so they can't be used as attendance records directly.

Accellum original reports and statistics dashboard UI
Accellum admin running locally with demo attendance and building data.

What I built

I owned Accellum end to end, from the MQTT topic design to the Docker Compose stack.

  • Designed the MQTT topic scheme for monitor, checkpoint and device-status events, with a last-will message so offline gateways are visible
  • Turned flickering BLE detections into reliable records: a 5 s debounce per card and device before an entry or exit is committed, and a 30 s presence timeout swept every minute
  • Pushed live occupancy per building to the Nuxt admin over Socket.IO, while PostgreSQL keeps the auditable history
  • Built a gateway simulator CLI that publishes DTO-valid KBeacon payloads, so the debounce and timeout logic can be tested end to end without hardware
  • Packaged the stack as health-checked Compose services (PostgreSQL, Mosquitto, MinIO, migrations, seed, API, admin) that start in the right order with one command

How it fits together

Cards advertise over Bluetooth LE. Gateways publish what they hear to Mosquitto. A NestJS MQTT microservice validates each payload, resolves the device and card, applies the monitor or checkpoint rules, writes the record through TypeORM, and broadcasts the new count over Socket.IO.

Outcome

Admins see live room occupancy and a clean entry and exit history instead of raw MQTT messages.

Deep diveCore feature walkthroughAn interactive flow of the hardest workflow, step by step.
Core feature walkthrough

How the main product workflows operate

Core feature · Device event to attendance record

Radio observations become durable room presence and access history

Accellum separates physical detection, event transport, domain rules and operator presentation. MQTT keeps devices independent from request-response APIs, while PostgreSQL and WebSocket serve different durability and immediacy needs.

Realtime event path

BLE → gateway → MQTT → NestJS → PostgreSQL / Socket.IO

Select a node for implementation detail
Realtime does not replace history

Socket.IO improves freshness; PostgreSQL remains the auditable source for reports and investigation.

Each device has a domain role

Monitor and checkpoint devices intentionally use different session rules instead of sharing one ambiguous timeout algorithm.

Tested without hardware

A gateway simulator publishes DTO-valid KBeacon payloads every second, so the debounce and timeout rules run end to end on a laptop.

Deep diveFrom BLE card to dashboardThe physical path and the monitor / checkpoint decision logic.
Device-to-application flow

How a card detection becomes attendance data

BLE → MQTT → WebSocket

The card only broadcasts its identity. The gateway turns that radio observation into an application event; the backend then validates, interprets, stores, and publishes the result to operators.

Physical devicesEvent transportApplication logicDataUser interface
Check-in / check-out logic

Two detection modes, two session strategies

Monitor mode models presence from repeated signals and checks out on timeout. Checkpoint mode models an entry/exit session with a five-second debounce and explicit room-transfer handling.

MonitorBest for continuous room presence and occupancy counts.