Skip to content

Node.js MQTT Client for SiliconWit IO

In this tutorial, you will learn how to build a Node.js MQTT client that simulates an IoT device sending sensor telemetry data to the SiliconWit IO platform. The client connects to the SiliconWit IO MQTT broker over a secure TLS connection and publishes random sensor readings at regular intervals.

Node.js is well-suited for IoT applications thanks to its event-driven architecture and the mature mqtt npm package. This tutorial is useful for building device simulators, IoT gateways, or server-side MQTT integrations.

  • How to install and configure the mqtt npm package
  • How to establish a secure TLS connection to the SiliconWit IO MQTT broker
  • How to authenticate using device credentials
  • How to publish JSON telemetry data on a timed interval
  • How to handle connection events and automatic reconnection
RequirementDetails
Node.jsVersion 18 or later
npmIncluded with Node.js
SiliconWit IO AccountFree IoT platform account
A registered deviceCreated from the SiliconWit IO dashboard

Verify your Node.js installation:

Terminal window
node --version
npm --version

You will need the following credentials from your SiliconWit IO dashboard after registering a device:

CredentialExampleDescription
Device IDxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxUnique device identifier (MQTT username and client ID)
Access Tokenyour_access_token_hereMQTT password
Publish Topicd/{device_id}/tTopic for sending sensor data (d = device, t = telemetry)

Keep your access token secure. Never share it publicly or commit it to version control.

Create a new project directory and initialize it:

Terminal window
mkdir siliconwit-node-client
cd siliconwit-node-client
npm init -y

Install the mqtt package:

Terminal window
npm install mqtt

Your project structure should look like this:

siliconwit-node-client/
├── node_modules/
├── index.js
├── package.json
└── package-lock.json

Step 2: Understand the Connection Architecture

Section titled “Step 2: Understand the Connection Architecture”

The Node.js client connects directly to the SiliconWit IO MQTT broker using the mqtts:// protocol (MQTT over TLS):

┌─────────────────────────────────────────────────────────┐
│ SiliconWit IO Cloud │
│ │
│ Dashboard <--> MQTT Broker (TLS on port 8883) │
│ | │
│ Telemetry Topic │
│ d/{device_id}/t │
└────────────────────┬────────────────────────────────────┘
│ TLS 1.2 (port 8883)
┌────────────────────┴────────────────────────────────────┐
│ Node.js Client (mqtt package) │
│ │
│ - Connects with mqtts:// protocol │
│ - Authenticates with device_id + access_token │
│ - Publishes simulated sensor data every 10 seconds │
└─────────────────────────────────────────────────────────┘

The mqtt npm package supports TLS natively via the mqtts:// URL scheme. Node.js uses its built-in TLS module, which trusts the same CA certificates as your operating system.

const mqtt = require("mqtt");
const client = mqtt.connect("mqtts://mqtt.siliconwit.io:8883", {
clientId: DEVICE_ID,
username: DEVICE_ID,
password: ACCESS_TOKEN,
});

The mqtts:// prefix tells the client to use MQTT over TLS. No additional certificate configuration is needed.

The device simulator generates random sensor readings that mimic a real IoT device. Each telemetry message includes temperature, humidity, and a battery voltage level.

function generateSensorData() {
return {
temperature: parseFloat((20 + Math.random() * 15).toFixed(1)),
humidity: parseFloat((30 + Math.random() * 50).toFixed(1)),
battery_voltage: parseFloat((3.0 + Math.random() * 1.2).toFixed(2)),
};
}
FieldTypeRangeDescription
temperaturefloat20.0 - 35.0Simulated temperature in Celsius
humidityfloat30.0 - 80.0Simulated relative humidity percentage
battery_voltagefloat3.00 - 4.20Simulated battery level in volts

Use setInterval to publish telemetry data at regular intervals:

const PUBLISH_TOPIC = `d/${DEVICE_ID}/t`;
const TELEMETRY_INTERVAL = 10000; // 10 seconds in milliseconds
setInterval(() => {
if (client.connected) {
const data = generateSensorData();
const payload = JSON.stringify(data);
client.publish(PUBLISH_TOPIC, payload, { qos: 1 });
console.log(`[TELEMETRY] Sent: ${payload}`);
}
}, TELEMETRY_INTERVAL);

Create a file called index.js with the following complete code:

const mqtt = require("mqtt");
// ========== SILICONWIT IO MQTT CONFIGURATION ==========
const MQTT_BROKER = "mqtts://mqtt.siliconwit.io:8883";
const DEVICE_ID = "YOUR_DEVICE_ID";
const ACCESS_TOKEN = "YOUR_ACCESS_TOKEN";
const PUBLISH_TOPIC = `d/${DEVICE_ID}/t`;
// ========== TIMING ==========
const TELEMETRY_INTERVAL = 10000; // milliseconds
// ========== SENSOR SIMULATION ==========
function generateSensorData() {
return {
temperature: parseFloat((20 + Math.random() * 15).toFixed(1)),
humidity: parseFloat((30 + Math.random() * 50).toFixed(1)),
battery_voltage: parseFloat((3.0 + Math.random() * 1.2).toFixed(2)),
};
}
// ========== MAIN ==========
console.log("=== Node.js MQTT Device Simulator -> SiliconWit IO ===\n");
// Create MQTT client with TLS
const client = mqtt.connect(MQTT_BROKER, {
clientId: DEVICE_ID,
username: DEVICE_ID,
password: ACCESS_TOKEN,
protocol: "mqtts",
reconnectPeriod: 5000,
connectTimeout: 30000,
keepalive: 60,
});
// ========== EVENT HANDLERS ==========
client.on("connect", () => {
console.log("[MQTT] Connected to SiliconWit IO");
// Send initial telemetry immediately on connect
const data = generateSensorData();
const payload = JSON.stringify(data);
client.publish(PUBLISH_TOPIC, payload, { qos: 1 });
console.log(`[TELEMETRY] Sent: ${payload}`);
});
client.on("reconnect", () => {
console.log("[MQTT] Reconnecting...");
});
client.on("disconnect", () => {
console.log("[MQTT] Disconnected");
});
client.on("error", (err) => {
console.error(`[MQTT] Error: ${err.message}`);
});
client.on("offline", () => {
console.log("[MQTT] Client offline");
});
// ========== TELEMETRY LOOP ==========
let messageCount = 0;
const telemetryInterval = setInterval(() => {
if (client.connected) {
const data = generateSensorData();
const payload = JSON.stringify(data);
client.publish(PUBLISH_TOPIC, payload, { qos: 1 }, (err) => {
if (err) {
console.error(`[TELEMETRY] Publish error: ${err.message}`);
} else {
messageCount++;
console.log(`[TELEMETRY] #${messageCount} Sent: ${payload}`);
}
});
} else {
console.log("[MQTT] Not connected, skipping telemetry...");
}
}, TELEMETRY_INTERVAL);
// ========== GRACEFUL SHUTDOWN ==========
function shutdown() {
console.log("\n[INFO] Shutting down...");
clearInterval(telemetryInterval);
client.end(false, {}, () => {
console.log(`[INFO] Disconnected. Sent ${messageCount} messages. Goodbye.`);
process.exit(0);
});
}
process.on("SIGINT", shutdown);
process.on("SIGTERM", shutdown);

Run the simulator:

Terminal window
node index.js

Expected output:

=== Node.js MQTT Device Simulator -> SiliconWit IO ===
[MQTT] Connected to SiliconWit IO
[TELEMETRY] Sent: {"temperature":27.3,"humidity":52.1,"battery_voltage":3.85}
[TELEMETRY] #1 Sent: {"temperature":24.8,"humidity":61.4,"battery_voltage":4.02}
[TELEMETRY] #2 Sent: {"temperature":31.2,"humidity":38.7,"battery_voltage":3.54}

Press Ctrl+C to stop the simulator gracefully.

  1. Log in to your SiliconWit IO dashboard.
  2. Navigate to your registered device.
  3. You should see temperature, humidity, and battery voltage updating every 10 seconds.
  4. SiliconWit IO automatically detects and displays each data field.

Step 8: Running as a Background Process (Optional)

Section titled “Step 8: Running as a Background Process (Optional)”

For long-running simulators or production gateways, you can use a process manager like pm2:

Terminal window
npm install -g pm2
pm2 start index.js --name siliconwit-simulator
pm2 save
pm2 startup

Useful pm2 commands:

CommandDescription
pm2 logs siliconwit-simulatorView live logs
pm2 restart siliconwit-simulatorRestart the process
pm2 stop siliconwit-simulatorStop the process
pm2 statusShow all running processes
SymptomCauseSolution
ECONNREFUSEDWrong broker address or portVerify the MQTT_BROKER URL includes mqtts:// and port 8883.
UNABLE_TO_VERIFY_LEAF_SIGNATURECA certificate issueUpdate Node.js to the latest LTS version. Run npm config set strict-ssl false as a workaround.
Error: Not authorizedInvalid credentialsVerify DEVICE_ID and ACCESS_TOKEN match your SiliconWit IO dashboard.
ETIMEOUTFirewall blocking port 8883Check that outbound port 8883 is allowed on your network.
Repeated reconnect eventsNetwork instabilityCheck your internet connection. Increase reconnectPeriod.
SymptomCauseSolution
Publish callback receives errorClient not connectedThe client.connected check should prevent this. Verify connection.
Data not showing on dashboardWrong topic formatTopic must be exactly d/{device_id}/t.
Payload too largeJSON exceeds limitSiliconWit IO accepts up to 10KB. Keep payloads small.
SymptomCauseSolution
Cannot find module 'mqtt'Package not installedRun npm install mqtt in the project directory.
High memory usage over timeMemory leakEnsure you are not accumulating data in arrays or closures.
Process exits unexpectedlyUnhandled rejectionAdd process.on('unhandledRejection', console.error) for debugging.

In this tutorial, you built a Node.js device simulator that:

  • Connects securely to the SiliconWit IO MQTT broker over TLS using the mqtts:// protocol
  • Authenticates with your Device ID and Access Token
  • Publishes simulated sensor data (temperature, humidity, battery voltage) as JSON every 10 seconds
  • Handles automatic reconnection and graceful shutdown
  • Can be run as a background service using pm2

This pattern is ideal for testing your SiliconWit IO setup, simulating multiple devices, or building Node.js IoT gateways that aggregate and forward data from connected sensors.