It can be tempting to brush off digital twins as just another trendy term, but once you really understand their purpose and application, you'll recognize that any comprehensive asset tracking system will eventually need one. Read about the definition of digital twins, architecture behind creating one and sample code to get started.
Definition of a digital twin
A digital twin is a live, up-to-date reflection of the actual object, which includes all of its current properties and status, including location, state and conditions of operation. The digital twin is not an archival copy stored in some data warehouse – it is an actively updated and synchronized representation of the actual physical object, including all changes made to it.
The synchronization of the two copies is crucial here; the changes happening in the object should immediately reflect in its digital copy, making it fully up-to-date with its status in the physical world.
Layers of a Digital Twin
Layer 1
Physical Asset — the physical object, equipped with IoT sensors, GPS tags, and actuators
Layer 2
Data Ingestion Layer — MQTT and HTTP streams delivering sensor readings to your back-end systems in real-time
Layer 3
Twin Model Layer — the in-memory or persisted object modeling the reality of the asset
Layer 4
Services Layer — services such as analytics, alerts, simulation, and API services consuming the state of the twin
The Twin Model — in code
The core concept behind a twin of any asset is an object storing its state and getting updated as sensor data comes in. Let's define a simple twin class in TypeScript for our tracked vehicle example:
// Digital twin model for a tracked asset
interface AssetState {
assetId: string
location: { lat: number; lng: number }
speed: number
tempC: number
batteryPct: number
status: 'active' | 'idle' | 'offline'
lastSeen: Date
alerts: string[]
}
class AssetTwin {
private state: AssetState
constructor(assetId: string) {
this.state = {
assetId,
location: { lat: 0, lng: 0 },
speed: 0, tempC: 0, batteryPct: 100,
status: 'offline',
lastSeen: new Date(),
alerts: []
}
}
update(payload: Partial<AssetState>) {
this.state = {
...this.state,
...payload,
lastSeen: new Date()
}
this.evaluate()
}
private evaluate() {
this.state.alerts = []
if (this.state.tempC > 8) this.state.alerts.push('TEMP_BREACH')
if (this.state.batteryPct < 15) this.state.alerts.push('LOW_BATTERY')
if (this.state.speed > 120) this.state.alerts.push('SPEED_BREACH')
}
getState(): AssetState { return { ...this.state } }
}
*Step 2 * — Twin Registry
— managing hundreds or thousands of twins
In practice, you'd be dealing with hundreds or thousands of assets — each requiring a separate twin instance. The Registry pattern can be used to store, manage, and create instances of twins on-demand:
class TwinRegistry {
private twins = new Map<string, AssetTwin>()
getOrCreate(assetId: string): AssetTwin {
if (!this.twins.has(assetId)) {
this.twins.set(assetId, new AssetTwin(assetId))
}
return this.twins.get(assetId)!
}
handleIncoming(msg: { assetId: string; [key: string]: any }) {
const twin = this.getOrCreate(msg.assetId)
twin.update(msg)
// Fire alerts if any triggered
const { alerts } = twin.getState()
if (alerts.length) broadcastAlerts(msg.assetId, alerts)
}
getAllStates() {
return [...this.twins.values()].map(t => t.getState())
}
}
Step 3 — Hook up MQTT messages to the registry
Connect your registry with your MQTT consumer so that every message received will update the corresponding twin automatically:
const registry = new TwinRegistry()
const client = mqtt.connect('mqtts://broker.yourdomain.com')
client.on('connect', () => {
client.subscribe('assets/+/telemetry')
})
client.on('message', (topic, payload) => {
const assetId = topic.split('/')[1]
const data = JSON.parse(payload.toString())
registry.handleIncoming({ assetId, ...data })
})
// Expose all twin states via REST
app.get('/twins', (req, res) => {
res.json(registry.getAllStates())
})
What you can do with a twin
Live dashboards
Push twin status to React through WebSockets; all assets update in real-time without any polling
Simulation
Simulate scenarios against the twin without having to touch any actual assets
Predictive maintenance
Feed twin history into your ML algorithms — the twin gives you nice structured data about each asset
Automated actions
Automate workflows based on twin status changes; send out alerts, update ERPs, or reassign tasks automatically
Tip: While in-memory twins are super-fast, they disappear once the application restarts. Save your twins' states in Redis for lightning-fast access and take snapshots every N seconds into PostgreSQL or TimescaleDB. At startup, restore your registry to its last known state; this will allow you to have live twins immediately without waiting for actual devices to reconnect.
Recommended stack
- TypeScript / Node.js
- MQTT (Mosquitto)
- Redis (state cache)
- TimescaleDB
- WebSockets
- React + Leaflet
This scales cleanly — Redis processes thousands of twin reads concurrently with sub-millisecond latencies, TimescaleDB retains the entire history of the sensors' data for analytics and machine learning purposes, and WebSockets transmit state changes to the dashboard instantly. Twin becomes the source of all truth about the object after that — monitoring, analytics, integration, and user interface.
The platform of AssetTrackPro is based on a digital twin approach — every tracked asset is represented by a digital model, which provides real-time dashboards, predictive notifications, and compliance reporting capabilities. Get to know more about it →
Don't want to design infrastructure from the ground up? IoT platform of AssetTrackPro allows implementing tracking services based on the digital twin approach without any backend design at all.
Explore AssetTrackPro ↗
Top comments (0)