Full Backend for Your IoT Platform (Node.js + MQTT + PostgreSQL + Timescale)

🚀 NOW WE ENTER PHASE 5


🎯 WHAT YOU WILL GET AFTER PHASE 5

✔️ A backend server running on Node.js

✔️ An MQTT ingestion service that listens for device messages

✔️ Inserts telemetry into TimescaleDB

✔️ A REST API that your frontend dashboard will use

✔️ Device registration + device keys

✔️ Secure token-based authentication

✔️ All running as systemd services (like real production systems)

No Docker needed.
Straight Linux + Node.js.


🧱 PHASE 5 — Step-by-Step

We will do this in proper order:


🔹 STEP 1 — Install Node.js LTS on Ubuntu (the correct method)

We will install Node.js 20 LTS (stable for production).

Run:

sudo apt update
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs

Then verify:

node -v
npm -v

Successful output looks like:

v20.x.x
10.x.x

🔹 STEP 2 — Create Directory for Your IoT Server

We will place it in:

/home/user/iot-server

Run:

mkdir ~/iot-server
cd ~/iot-server

in the command mkdir ~/iot-server, there is no space between the tilde (~) and the /iot-server part of the path.

  • mkdir: This is the “make directory” command, used to create new directories.
  • ~: The tilde symbol is a special character that represents the current user’s home directory (e.g., /home/username/ on Linux).
  • iot-server: This is the name of the new directory that will be created. 

After running this command, you will have a new, empty directory ready for use at the path ~/iot-server (e.g., /home/username/iot-server). 


🔹 STEP 3 — Initialize the Project

Run:

npm init -y

This creates package.json.


🔹 STEP 4 — Install Required Libraries

Run:

npm install mqtt pg express cors dotenv

These libraries will be used for:

LibraryPurpose
mqttConnect to the local Mosquitto broker
pgPostgreSQL + TimescaleDB client
expressREST API server
corsAllow browser dashboard to access the API
dotenvLoad passwords safely

🔹 STEP 5 — Create Basic Backend Files

We will create:

1. .env → store DB and MQTT credentials

2. server.js → REST API

3. mqttWorker.js → MQTT ingestion worker

4. db.js → PG connection pool

I will generate full code for all files once you confirm Step 1 is complete.


🧪 Your Turn

Please run:

node -v
npm -v

And paste the output here.

Once Node.js is installed successfully, I will generate the full backend structure and code for you.


💬 Reply with the Node.js + npm versions, and we proceed to full backend creation.

O/P

1.) ~/iot-server$ node -v npm -v v20.19.5 10.8.2, 
2.) ~/iot-server$ npm install mqtt pg express cors dotenv added 126 packages, and audited 127 packages in 11s 22 packages are looking for funding run npm fund for details found 0 vulnerabilities

🔥 Perfect! Perfect! Perfect!
Your Node.js environment is ready for a real production IoT backend.

You now have:

  • Node.js v20 LTS
  • npm v10
  • All required libraries installed
    • mqtt
    • pg
    • express
    • cors
    • dotenv

Now we can build the backend + MQTT ingestion engine that connects Mosquitto → Node.js → TimescaleDB.

This is the core of your IoT platform.

We will proceed cleanly, with full explanation of what each line does.


🚀 PHASE 5 — Create Your IoT Backend Structure

Inside:

~/iot-server

We will create 3 main files:

1️⃣ db.js

Connection to PostgreSQL (TimescaleDB)

2️⃣ mqttWorker.js

Listens to MQTT messages (from Mosquitto)
Parses them
Stores into TimescaleDB

3️⃣ server.js

REST API server (Express)
For device management, dashboard API, etc.

4️⃣ .env

Secure credentials (never hard-code passwords)


🔹 STEP 1 — Create the .env file

Run:

nano .env

Put this inside (replace passwords accordingly):

# PostgreSQL
PG_HOST=127.0.0.1
PG_PORT=5432
PG_USER=iotadmin
PG_PASSWORD=your_pg_password
PG_DATABASE=iotdb

# MQTT
MQTT_HOST=mqtt://127.0.0.1
MQTT_USERNAME=iotdevice
MQTT_PASSWORD=your_iotdevice_password
MQTT_TOPIC=devices/+/data

Explanation:

  • devices/+/data means:
    • Any device ID
    • Topic format like: devices/device123/data
  • This is good for scalable device structures.

Save:
CTRL + O → Enter
CTRL + X


🔹 STEP 2 — Create db.js (PostgreSQL connection)

Run:

nano db.js

Paste:

const { Pool } = require('pg');
require('dotenv').config();

const pool = new Pool({
  host: process.env.PG_HOST,
  port: process.env.PG_PORT,
  user: process.env.PG_USER,
  password: process.env.PG_PASSWORD,
  database: process.env.PG_DATABASE,
});

module.exports = pool;

Explanation:

  • Uses connection pool (recommended)
  • Automatically loads credentials from .env
  • We export pool to use everywhere

Save and exit.


🔹 STEP 3 — Create mqttWorker.js (MQTT ingestion service)

Run:

nano mqttWorker.js

Paste:

const mqtt = require('mqtt');
const pool = require('./db');
require('dotenv').config();

const client = mqtt.connect(process.env.MQTT_HOST, {
  username: process.env.MQTT_USERNAME,
  password: process.env.MQTT_PASSWORD,
});

client.on('connect', () => {
  console.log('MQTT connected');
  client.subscribe(process.env.MQTT_TOPIC, (err) => {
    if (err) console.error('Subscription error:', err);
    else console.log(`Subscribed to ${process.env.MQTT_TOPIC}`);
  });
});

client.on('message', async (topic, message) => {
  try {
    const payload = message.toString();
    const parts = topic.split('/'); // devices/deviceId/data
    const deviceId = parts[1];    

    console.log(`Message from ${deviceId}:`, payload);

    await pool.query(
      `INSERT INTO telemetry (time, device_id, payload)
       VALUES (NOW(), $1, $2::jsonb)`,
      [deviceId, payload]
    );

    console.log('Data inserted into TimescaleDB');
  } catch (err) {
    console.error('Insert error:', err);
  }
});

What this does:

  • Connects to MQTT broker
  • Subscribes to all device data topics
  • Every message is:
    • Time-stamped
    • Device ID extracted from topic
    • Stored into TimescaleDB telemetry hypertable

This is a TRUE IoT backend ingestion engine.

Save and exit.


🔹 STEP 4 — Create server.js (REST API)

Run:

nano server.js

Paste:

const express = require('express');
const cors = require('cors');
const pool = require('./db');
require('dotenv').config();

const app = express();
app.use(cors());
app.use(express.json());

// Simple test route
app.get('/', (req, res) => {
  res.send('IoT Backend API running');
});

// Get latest telemetry for a device
app.get('/api/device/:id/latest', async (req, res) => {
  try {
    const result = await pool.query(
      `SELECT * FROM telemetry 
       WHERE device_id = $1
       ORDER BY time DESC
       LIMIT 1`,
      [req.params.id]
    );
    res.json(result.rows[0] || {});
  } catch (err) {
    console.error(err);
    res.status(500).send('Database error');
  }
});

const PORT = 3000;
app.listen(PORT, () => console.log(`API running on port ${PORT}`));

[req.params.id]

); res.json(result.rows[0] || {}); } catch (err) { console.error(err); res.status(500).send(‘Database error’); } }); const PORT = 3000; app.listen(PORT, () => console.log(`API running on port ${PORT}`));

This:

  • Creates API
  • Adds endpoint:
    /api/device/<id>/latest
  • Fetches latest message from TimescaleDB
  • Prepares foundation for dashboard

Save and exit.


🔹 STEP 5 — Run MQTT Worker + API

Open two terminal tabs.

Tab 1 — Start MQTT Worker

node mqttWorker.js

Should show:

MQTT connected
Subscribed to devices/+/data

Tab 2 — Start API

node server.js

Should show:

API running on port 3000

🧪 Send Test MQTT Message (simulate a device)

From any terminal:

mosquitto_pub \
  -h 127.0.0.1 \
  -u iotdevice \
  -P 'yourpassword' \
  -t devices/deviceA/data \
  -m '{"temp": 25.5, "hum": 60}'

MQTT worker should log:

Message from deviceA: {"temp": 25.5, "hum": 60}
Data inserted into TimescaleDB

📩 Your Turn — Reply with:

1. Output of "node mqttWorker.js" after starting
2. Output of "node server.js"
3. Run the mosquitto_pub test message and paste MQTT worker output

Once all this works, we move to:

🚀 PHASE 6 — Turning MQTT Worker + API into Background Services (systemd)

This will make your backend run 24/7, automatically on reboot.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *