
Research
/Security News
Miasma Mini Shai-Hulud Hits ImmobiliareLabs npm Packages
Miasma Mini Shai-Hulud hits @immobiliarelabs Backstage plugins, targeting GitLab and LDAP auth packages on npm.
await-mqtt
Advanced tools
🔄 Elegant Promise-based async/await wrapper for MQTT.js with TypeScript support and React hooks
# Using npm
npm install await-mqtt mqtt
# Using yarn
yarn add await-mqtt mqtt
# Using bun
bun add await-mqtt mqtt
# If using with React
npm install await-mqtt mqtt react
import { Mqtt } from 'await-mqtt';
async function main() {
// Create a client and connect in one step
const mqtt = await Mqtt({
url: 'mqtt://broker.example.com',
clientId: 'my-client',
});
try {
console.log('Connected successfully!');
// Subscribe to topics
await mqtt.subscribe('sensors/#');
// Register message handler with async support
mqtt.onMessage('sensors/temperature', async (topic, message) => {
const temperature = parseFloat(message.toString());
console.log(`Temperature: ${temperature}°C`);
// Perform async operations inside handlers
await processTemperature(temperature);
});
// Publish string message
await mqtt.publish('sensors/command', 'READ');
// Publish JSON object (automatically serialized)
await mqtt.publish('sensors/config', {
interval: 5000,
precision: 2,
enabled: true
});
// Clean disconnect when done
await mqtt.end();
} catch (err) {
console.error('MQTT Error:', err);
}
}
main();
import React, { useState } from 'react';
import { MqttProvider, useMqtt, usePublish, useMessages } from 'await-mqtt/react';
// Main component with MQTT provider
function App() {
return (
<MqttProvider options={{ clientId: 'react-client' }}>
<div className="app">
<h1>MQTT React Demo</h1>
<ConnectionControl />
<MessagePublisher />
<MessageSubscriber />
</div>
</MqttProvider>
);
}
// Connection control component
function ConnectionControl() {
const { connect, disconnect, isConnected, isConnecting, error } = useMqtt();
const [brokerUrl, setBrokerUrl] = useState('ws://broker.example.com:8883');
return (
<div>
<h2>Connection Status: {isConnected ? 'Connected' : (isConnecting ? 'Connecting...' : 'Disconnected')}</h2>
{error && <p className="error">Error: {error.message}</p>}
<input
type="text"
value={brokerUrl}
onChange={(e) => setBrokerUrl(e.target.value)}
placeholder="Broker URL"
/>
<button onClick={() => isConnected ? disconnect() : connect(brokerUrl)}>
{isConnected ? 'Disconnect' : 'Connect'}
</button>
</div>
);
}
// Message publisher component
function MessagePublisher() {
const { sendMessage, isPublishing } = usePublish();
const [topic, setTopic] = useState('test/topic');
const [message, setMessage] = useState('Hello MQTT');
const handlePublish = async () => {
const result = await sendMessage(topic, message);
if (result.success) {
console.log('Message published successfully');
}
};
return (
<div>
<h2>Publish Message</h2>
<input
type="text"
value={topic}
onChange={(e) => setTopic(e.target.value)}
placeholder="Topic"
/>
<input
type="text"
value={message}
onChange={(e) => setMessage(e.target.value)}
placeholder="Message"
/>
<button onClick={handlePublish} disabled={isPublishing}>
{isPublishing ? 'Publishing...' : 'Publish'}
</button>
</div>
);
}
// Message subscriber component
function MessageSubscriber() {
const [topic, setTopic] = useState('test/topic');
const { messages, isSubscribed } = useMessages(topic, 10);
return (
<div>
<h2>Subscribe to Messages</h2>
<input
type="text"
value={topic}
onChange={(e) => setTopic(e.target.value)}
placeholder="Topic"
/>
<p>Status: {isSubscribed ? 'Subscribed' : 'Not subscribed'}</p>
<div className="messages">
<h3>Received Messages</h3>
{messages.length === 0 ? (
<p>No messages received</p>
) : (
<ul>
{messages.map((msg, idx) => (
<li key={idx}>
<div>{msg.topic} - {new Date(msg.timestamp).toLocaleTimeString()}</div>
<div>{typeof msg.payload === 'object' ? JSON.stringify(msg.payload) : String(msg.payload)}</div>
</li>
))}
</ul>
)}
</div>
</div>
);
}
export default App;
import { Mqtt } from 'await-mqtt';
// Create and connect with default options
const mqtt = await Mqtt({
url: 'mqtt://broker.example.com'
});
// Create and connect with custom options
const mqtt = await Mqtt({
url: 'mqtt://broker.example.com',
clientId: 'my-client',
clean: true,
keepalive: 30,
// Additional await-mqtt options
autoReconnect: true,
reconnectInterval: 1000,
maxReconnectAttempts: 10
});
Since the Mqtt function connects automatically, you typically don't need to call connect separately. However, if you need to reconnect:
Reconnect to the broker if disconnected.
// Reconnect to the broker
await mqtt.reconnect();
Disconnect from the broker.
// Graceful disconnect (default)
await mqtt.end();
// Force disconnect immediately
await mqtt.end(true);
Manually trigger a reconnection.
await mqtt.reconnect();
// Reconnect with clean session
await mqtt.reconnect(true);
Publish a message to a topic with Promise support.
// String payload
await mqtt.publish('home/lights/living-room', 'ON');
// Buffer payload
await mqtt.publish('home/sensor/data', Buffer.from([0x01, 0x02, 0x03]));
// Object payload (automatically JSON serialized)
await mqtt.publish('home/settings', {
brightness: 80,
color: '#FFFFFF',
mode: 'auto'
});
// With QoS and other options
await mqtt.publish('home/alerts', 'MOTION_DETECTED', {
qos: 2,
retain: true,
timeout: 5000 // ms, await-mqtt specific
});
Subscribe to topics with flexible formats.
// Single topic
await mqtt.subscribe('home/temperature');
// Multiple topics as array
await mqtt.subscribe(['home/temperature', 'home/humidity']);
// With QoS
await mqtt.subscribe('home/temperature', { qos: 1 });
// Multiple topics with different QoS levels
await mqtt.subscribe({
'home/temperature': { qos: 0 },
'home/humidity': { qos: 1 },
'home/pressure': { qos: 2 }
});
// With timeout
await mqtt.subscribe('home/#', {
qos: 1,
timeout: 5000 // ms, await-mqtt specific
});
Unsubscribe from topics.
// Single topic
await mqtt.unsubscribe('home/temperature');
// Multiple topics
await mqtt.unsubscribe(['home/temperature', 'home/humidity']);
// With timeout
await mqtt.unsubscribe('home/#', {
timeout: 5000 // ms, await-mqtt specific
});
Register message handlers with wildcard support.
// Basic handler
mqtt.onMessage('home/temperature', (topic, message) => {
console.log(`Temperature: ${message}`);
});
// Async handler
mqtt.onMessage('home/commands', async (topic, message) => {
const command = message.toString();
await executeCommand(command);
await mqtt.publish('home/commands/response', 'SUCCESS');
});
// Wildcard handler
mqtt.onMessage('home/+/temperature', (topic, message) => {
const room = topic.split('/')[1];
console.log(`${room} temperature: ${message}°C`);
});
// Global message handler
mqtt.onMessage('#', (topic, message) => {
console.log(`[${topic}] ${message}`);
});
Provides MQTT context to all child components.
import { MqttProvider } from 'await-mqtt/react';
function App() {
return (
<MqttProvider
options={{
clientId: 'react-app',
url: 'ws://broker.example.com:8883'
}}
autoConnect={true}
>
{/* Your app components */}
</MqttProvider>
);
}
Primary hook for accessing the MQTT client and connection state.
import { useMqtt } from 'await-mqtt/react';
function ConnectionStatus() {
const {
client, // The MqttManager instance
isConnected, // Boolean indicating connection status
isConnecting, // Boolean indicating if connection is in progress
error, // Error object if connection failed
connect, // Function to connect to a broker
disconnect, // Function to disconnect from the broker
publish, // Function to publish a message
subscribe, // Function to subscribe to a topic
unsubscribe, // Function to unsubscribe from a topic
onMessage, // Function to register a message handler
getSubscriptions // Function to get active subscriptions
} = useMqtt();
return (
<div>
<div>Status: {isConnected ? 'Connected' : (isConnecting ? 'Connecting...' : 'Disconnected')}</div>
{error && <div>Error: {error.message}</div>}
<button onClick={() => connect('ws://broker.example.com:8883')}>Connect</button>
<button onClick={disconnect}>Disconnect</button>
</div>
);
}
Hook for subscribing to a specific topic.
import { useSubscription } from 'await-mqtt/react';
function TopicSubscriber({ topic }) {
const { isSubscribed, error } = useSubscription(topic, { qos: 1 });
return (
<div>
<div>Topic: {topic}</div>
<div>Status: {isSubscribed ? 'Subscribed' : 'Not subscribed'}</div>
{error && <div>Error: {error.message}</div>}
</div>
);
}
Hook for collecting messages from a specific topic.
import { useMessages } from 'await-mqtt/react';
function MessageList({ topic }) {
const { messages, clearMessages, isSubscribed, subscriptionError } = useMessages(topic, 10);
return (
<div>
<div>Topic: {topic}</div>
<div>Status: {isSubscribed ? 'Subscribed' : 'Not subscribed'}</div>
<button onClick={clearMessages}>Clear Messages</button>
<ul>
{messages.map((msg, idx) => (
<li key={idx}>
<div>{new Date(msg.timestamp).toLocaleTimeString()}</div>
<div>{typeof msg.payload === 'object'
? JSON.stringify(msg.payload)
: String(msg.payload)}
</div>
</li>
))}
</ul>
</div>
);
}
Hook for tracking the latest message from a specific topic.
import { useMessage } from 'await-mqtt/react';
function LatestMessage({ topic }) {
const { message, clearMessage, isSubscribed, subscriptionError } = useMessage(topic);
return (
<div>
<div>Topic: {topic}</div>
<div>Status: {isSubscribed ? 'Subscribed' : 'Not subscribed'}</div>
<button onClick={clearMessage}>Clear Message</button>
<div>
{message === null ? (
<p>No message received</p>
) : (
<div>
{typeof message === 'object'
? JSON.stringify(message, null, 2)
: String(message)}
</div>
)}
</div>
</div>
);
}
Hook for publishing messages with state tracking.
import { usePublish } from 'await-mqtt/react';
function MessagePublisher() {
const { sendMessage, isPublishing, lastError } = usePublish();
const [topic, setTopic] = useState('test/topic');
const [message, setMessage] = useState('Hello MQTT');
const handlePublish = async () => {
const result = await sendMessage(topic, message, { qos: 1 });
if (result.success) {
console.log('Message published successfully');
}
};
return (
<div>
<input
type="text"
value={topic}
onChange={(e) => setTopic(e.target.value)}
placeholder="Topic"
/>
<input
type="text"
value={message}
onChange={(e) => setMessage(e.target.value)}
placeholder="Message"
/>
<button onClick={handlePublish} disabled={isPublishing}>
{isPublishing ? 'Publishing...' : 'Publish'}
</button>
{lastError && <div>Error: {lastError.message}</div>}
</div>
);
}
import { Mqtt } from 'await-mqtt';
async function setupHomeAutomation() {
try {
// Create and connect client
const mqtt = await Mqtt({
url: 'mqtt://home-broker.local',
clientId: 'home-controller'
});
// Subscribe to all device commands
await mqtt.subscribe('home/+/command');
// Handle lights
mqtt.onMessage('home/lights/+/command', async (topic, message) => {
const room = topic.split('/')[2];
const command = message.toString();
console.log(`Setting ${room} lights to ${command}`);
await controlLight(room, command);
// Confirm the action
await mqtt.publish(`home/lights/${room}/status`, command);
});
// Handle temperature sensors
mqtt.onMessage('home/sensors/+/temperature', (topic, message) => {
const room = topic.split('/')[2];
const temperature = parseFloat(message.toString());
console.log(`${room} temperature: ${temperature}°C`);
// Trigger climate control if needed
if (temperature > 25) {
mqtt.publish(`home/climate/${room}/command`, 'COOL');
} else if (temperature < 18) {
mqtt.publish(`home/climate/${room}/command`, 'HEAT');
}
});
} catch (error) {
console.error('Failed to setup home automation:', error);
}
}
import React, { useState } from 'react';
import { MqttProvider, useMqtt, useMessage, usePublish } from 'await-mqtt/react';
function SmartHomeApp() {
return (
<MqttProvider
options={{
url: 'ws://home-broker.local:8883',
clientId: 'home-dashboard'
}}
autoConnect={true}
>
<div className="smart-home-dashboard">
<h1>Smart Home Dashboard</h1>
<ConnectionStatus />
<div className="rooms-grid">
<RoomPanel room="living-room" />
<RoomPanel room="kitchen" />
<RoomPanel room="bedroom" />
<RoomPanel room="bathroom" />
</div>
</div>
</MqttProvider>
);
}
function ConnectionStatus() {
const { isConnected, isConnecting, error, connect, disconnect } = useMqtt();
return (
<div className="connection-status">
<div className={`status-indicator ${isConnected ? 'connected' : 'disconnected'}`}>
{isConnected ? 'Connected' : (isConnecting ? 'Connecting...' : 'Disconnected')}
</div>
{error && <div className="error-message">Error: {error.message}</div>}
<button onClick={() => isConnected ? disconnect() : connect('ws://home-broker.local:8883')}>
{isConnected ? 'Disconnect' : 'Connect'}
</button>
</div>
);
}
function RoomPanel({ room }) {
return (
<div className="room-panel">
<h2>{room.replace('-', ' ')}</h2>
<div className="sensors">
<TemperatureSensor room={room} />
<HumiditySensor room={room} />
</div>
<div className="controls">
<LightControl room={room} />
<ClimateControl room={room} />
</div>
</div>
);
}
function TemperatureSensor({ room }) {
const { message } = useMessage(`home/sensors/${room}/temperature`);
return (
<div className="sensor temperature-sensor">
<h3>Temperature</h3>
<div className="sensor-value">
{message !== null ? `${message}°C` : '--'}
</div>
</div>
);
}
function HumiditySensor({ room }) {
const { message } = useMessage(`home/sensors/${room}/humidity`);
return (
<div className="sensor humidity-sensor">
<h3>Humidity</h3>
<div className="sensor-value">
{message !== null ? `${message}%` : '--'}
</div>
</div>
);
}
function LightControl({ room }) {
const { message: status } = useMessage(`home/lights/${room}/status`);
const { sendMessage } = usePublish();
const isOn = status === 'ON';
const toggleLight = async () => {
const newStatus = isOn ? 'OFF' : 'ON';
await sendMessage(`home/lights/${room}/command`, newStatus);
};
return (
<div className="control light-control">
<h3>Lights</h3>
<button
className={`toggle-button ${isOn ? 'on' : 'off'}`}
onClick={toggleLight}
>
{isOn ? 'ON' : 'OFF'}
</button>
</div>
);
}
function ClimateControl({ room }) {
const { message: currentMode } = useMessage(`home/climate/${room}/status`);
const { sendMessage } = usePublish();
const setMode = async (mode) => {
await sendMessage(`home/climate/${room}/command`, mode);
};
return (
<div className="control climate-control">
<h3>Climate</h3>
<div className="mode-buttons">
<button
className={`mode-button ${currentMode === 'OFF' ? 'active' : ''}`}
onClick={() => setMode('OFF')}
>
Off
</button>
<button
className={`mode-button ${currentMode === 'HEAT' ? 'active' : ''}`}
onClick={() => setMode('HEAT')}
>
Heat
</button>
<button
className={`mode-button ${currentMode === 'COOL' ? 'active' : ''}`}
onClick={() => setMode('COOL')}
>
Cool
</button>
<button
className={`mode-button ${currentMode === 'AUTO' ? 'active' : ''}`}
onClick={() => setMode('AUTO')}
>
Auto
</button>
</div>
</div>
);
}
export default SmartHomeApp;
MIT
FAQs
🔄 Promise-based async/await wrapper for MQTT.js with React hooks
We found that await-mqtt demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
Miasma Mini Shai-Hulud hits @immobiliarelabs Backstage plugins, targeting GitLab and LDAP auth packages on npm.

Security News
Rolldown paused Rust React Compiler integration after a 5MB binary size increase raised concerns about shipping React-specific code to all Vite users.

Security News
/Research
Mini Shai-Hulud expands into the Go ecosystem after hitting LeoPlatform npm packages and targeting GitHub Actions workflows.