// PROJECT 006

BLE Asset Tracking Platform

Industrial-grade real-time asset tracking using BLE 5.x beacons, custom gateway firmware, and AWS IoT cloud backend. Provides sub-3-metre accuracy for tools, equipment, and personnel across factory floors — with MQTT telemetry, floor-map overlays, and configurable zone alerting.

BLE 5.xnRF52840MQTT AWS IoT CoreEmbedded CPython Gateway FreeRTOSLinux Gateway
// BLE BEACONS Tag A: Tool#1 Tag B: Forklift Tag C: Worker ID Tag D: Pallet Tag E: Container ADV @ 100ms // GATEWAYS (×4 / ZONE) Raspberry Pi 4 + nRF52840 USB BLE Scanner → RSSI → Trilateration RSSI Averaging (N=5) Kalman Filter Zone Detection Geofence Alerts MQTT Publisher asset/zone/telemetry asset/alerts/zone-exit // AWS IOT CORE IoT Rules Engine DynamoDB (Positions) S3 (Telemetry Archive) SNS (Zone Alerts) TLS 1.3, QoS 1 // DASHBOARD Floor Map View Live Asset Dots Zone Heatmap Alert History Asset Search Dwell Time Report React + WebSocket AWS Amplify Grafana Fleet View
Problem
Zero Asset Visibility
Factory operations had no real-time visibility of tools, equipment, or personnel location. Manual locating wasted 45+ minutes per shift and caused costly production delays.
Solution
BLE + Gateway + Cloud
BLE 5.x beacons on each asset, fixed gateway scanners every 15m, trilateration with Kalman filtering, MQTT telemetry to AWS IoT Core with floor-map dashboard.
Result
Real-Time Tracking
Sub-3m accuracy, 2-second location refresh, automated zone-exit alerts, and a searchable asset history reducing manual search time by 90%.
<3mLocation Accuracy
2sRefresh Rate
500+Assets Tracked
2yrBeacon Battery Life

BLE Beacon Firmware (nRF52840)

Custom beacon firmware written in Embedded C using Nordic nRF5 SDK. Each beacon advertises a unique UUID payload every 100 ms in non-connectable mode to maximise battery life. Temperature and battery voltage are encoded in manufacturer-specific advertisement data bytes.

// BLE Advertisement payload structure
typedef struct {
    uint16_t company_id;      // 0x05A4 (assigned)
    uint8_t  asset_type;      // 0x01=Tool, 0x02=Vehicle, 0x03=Person
    uint16_t asset_id;        // Unique asset identifier
    int8_t   tx_power;        // Calibrated TX power at 1m (dBm)
    uint8_t  battery_pct;     // 0–100%
    int8_t   temp_degc;       // Ambient temperature
    uint8_t  motion_flag;     // 1 = moving (ADXL accelerometer)
    uint32_t seq_counter;     // Monotonic counter for dedup
} __attribute__((packed)) beacon_adv_t;

// Advertising interval: 100 ms (non-connectable, non-scannable)
// TX Power: -4 dBm (balance range vs battery)
// Expected battery life @ CR2032: ~24 months

Gateway Firmware — RSSI Processing

Each Raspberry Pi 4 gateway runs a Python scanning daemon that receives HCI events from the nRF52840 USB dongle, applies RSSI windowed averaging (N=5), and feeds measurements into a per-tag Kalman filter to reduce multipath noise before publishing to MQTT.

class AssetTracker:
    def __init__(self, asset_id):
        self.kf = KalmanFilter1D(process_noise=0.1, obs_noise=2.5)
        self.rssi_window = deque(maxlen=5)
        self.last_seen = None

    def update(self, raw_rssi, gateway_id):
        self.rssi_window.append(raw_rssi)
        avg_rssi = np.mean(self.rssi_window)
        filtered = self.kf.update(avg_rssi)
        distance_m = self._rssi_to_distance(filtered)
        self._publish_mqtt(gateway_id, distance_m)

    def _rssi_to_distance(self, rssi):
        # Log-distance path loss model: d = 10^((TxPower - RSSI) / (10 * n))
        # n=2.5 for factory floor (empirically calibrated)
        return 10 ** ((-4 - rssi) / (10 * 2.5))

MQTT Topic Schema

asset/{id}/positionx_m, y_m, floor, confidence — every 2s, QoS 1
asset/{id}/telemetrybattery_pct, temp, motion_flag — every 30s, QoS 0
asset/{id}/alertzone_exit, low_battery, tamper — retained, QoS 2
gateway/{gw_id}/statusuptime, scan_rate, connected_tags — every 60s
zone/{zone_id}/occupancyasset_count, asset_ids[] — updated on change

Technology Stack

Beacon HardwareNordic nRF52840 SoC, CR2032, ADXL345 accelerometer
Beacon FirmwareEmbedded C, nRF5 SDK 17.x, SoftDevice S140
GatewayRaspberry Pi 4, nRF52840 USB dongle, Python 3.11, BlueZ
PositioningRSSI trilateration, Kalman filter, log-distance path loss
CloudAWS IoT Core, DynamoDB, S3, SNS, Lambda
DashboardReact, AWS Amplify, WebSocket, Grafana, SVG floor maps
← All Projects