npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

arduino-mqtt

v0.0.7

Published

A powerful tool for connecting your Arduino devices to MQTT brokers. This bridge enables bidirectional communication between Arduino serial interfaces and MQTT protocols, perfect for IoT applications.

Readme

🔌 Arduino MQTT Bridge

A powerful tool for connecting your Arduino devices to MQTT brokers. This bridge enables bidirectional communication between Arduino serial interfaces and MQTT protocols, perfect for IoT applications.

✨ Features

  • 🔄 Bidirectional communication between Arduino and MQTT
  • ⚙️ Simple configuration through CLI
  • 🔒 Support for MQTT authentication
  • 📊 Automatic JSON parsing for sensor data
  • 🧩 Customizable MQTT topics
  • 🔧 Easy serial port configuration

📦 Installation

# Install globally
npm install -g arduino-mqtt

# Or use directly with npx
npx arduino-mqtt config

🚀 Quick Start

1. Configure the bridge

# Interactive setup
arduino-mqtt config

# Or set individual values
arduino-mqtt set port COM7
arduino-mqtt set baud 9600
arduino-mqtt set ip mqtt://localhost:1883

2. Start the bridge

# Start the MQTT-Arduino bridge
arduino-mqtt run

3. Stop the bridge

# Press Ctrl+C or run
arduino-mqtt stop

🔧 Configuration Options

| Parameter | Description | Default Value | |-----------|-------------|---------------| | port | Serial port connected to Arduino | COM7 | | baud | Baud rate for serial communication | 9600 | | ip | MQTT broker address | mqtt://localhost:1883 | | commandsTopic | Topic to receive commands for Arduino | arduino/commands | | sensorsTopic | Topic to publish Arduino sensor data | arduino/sensors | | username | MQTT broker username (if required) | | | password | MQTT broker password (if required) | |

📝 Command Reference

| Command | Description | |---------|-------------| | arduino-mqtt config | Interactive configuration wizard | | arduino-mqtt run | Start the bridge | | arduino-mqtt stop | Stop the bridge | | arduino-mqtt set <key> <value> | Update specific configuration | | arduino-mqtt get [key] | View configuration (all or specific key) |

📊 Data Flow

Arduino → MQTT

  • Serial data from Arduino is read line by line
  • JSON data is automatically parsed and published to the sensorsTopic
  • Non-JSON data is published to sensorsTopic/raw

MQTT → Arduino

  • Messages received on commandsTopic are sent directly to Arduino
  • Each command is terminated with a newline character

🔌 Arduino Code Examples

Basic LED Control Example

#include <ArduinoJson.h>  // Include ArduinoJson library (install from Library Manager)

// Define pins
#define LED1_PIN 13  // Built-in LED
#define LED2_PIN 12
#define LED3_PIN 11
#define LED4_PIN 10

// Define JSON document size based on your needs
#define JSON_DOC_SIZE 256

void setup() {
  Serial.begin(9600);
  
  // Initialize LED pins
  pinMode(LED1_PIN, OUTPUT);
  pinMode(LED2_PIN, OUTPUT);
  pinMode(LED3_PIN, OUTPUT);
  pinMode(LED4_PIN, OUTPUT);
  
  delay(1000);  // Give serial connection time to stabilize
}

void loop() {
  // Read and process commands from MQTT
  if (Serial.available() > 0) {
    String command = Serial.readStringUntil('\n');
    processCommand(command);
  }
  
  // Send sensor data to MQTT
  sendSensorData();
  
  delay(5000);  // Send every 5 seconds
}

// Process incoming commands, including simple key-value pairs
void processCommand(String command) {
  // Check if command has a key-value format (key=value)
  int separatorPos = command.indexOf('=');
  
  if (separatorPos > 0) {
    // Extract key and value
    String key = command.substring(0, separatorPos);
    String value = command.substring(separatorPos + 1);
    
    // Trim whitespace
    key.trim();
    value.trim();
    
    // Convert key to lowercase for case-insensitive comparison
    key.toLowerCase();
    
    // Check for LED commands (l1, l2, l3, l4)
    if (key == "l1" || key == "led1") {
      setLedState(LED1_PIN, value);
    } 
    else if (key == "l2" || key == "led2") {
      setLedState(LED2_PIN, value);
    }
    else if (key == "l3" || key == "led3") {
      setLedState(LED3_PIN, value);
    }
    else if (key == "l4" || key == "led4") {
      setLedState(LED4_PIN, value);
    }
    else if (key == "all") {
      // Set all LEDs to the same state
      setLedState(LED1_PIN, value);
      setLedState(LED2_PIN, value);
      setLedState(LED3_PIN, value);
      setLedState(LED4_PIN, value);
    }
  }
  else {
    // Handle legacy commands like "LED_ON" or "LED_OFF"
    if (command == "LED_ON") {
      digitalWrite(LED1_PIN, HIGH);
    } 
    else if (command == "LED_OFF") {
      digitalWrite(LED1_PIN, LOW);
    }
  }
}

// Set LED state based on various input formats
void setLedState(int pin, String state) {
  // Convert to lowercase for case-insensitive comparison
  state.toLowerCase();
  
  // Check for various ON representations
  if (state == "on" || state == "true" || state == "1" || state == "high") {
    digitalWrite(pin, HIGH);
  }
  // Check for various OFF representations
  else if (state == "off" || state == "false" || state == "0" || state == "low") {
    digitalWrite(pin, LOW);
  }
  // Handle numeric brightness for PWM pins
  else {
    // Try to parse as integer for PWM value
    int brightness = state.toInt();
    if (brightness > 0 || state == "0") {
      // Constrain value to valid PWM range
      brightness = constrain(brightness, 0, 255);
      analogWrite(pin, brightness);
    }
  }
}

// Send sensor data as JSON to MQTT
void sendSensorData() {
  StaticJsonDocument<JSON_DOC_SIZE> doc;
  
  // Add sensor readings
  doc["temperature"] = readTemperature();
  doc["humidity"] = readHumidity();
  doc["light"] = analogRead(A2);
  doc["uptime"] = millis() / 1000;
  
  // Add LED states
  doc["led1"] = digitalRead(LED1_PIN);
  doc["led2"] = digitalRead(LED2_PIN);
  doc["led3"] = digitalRead(LED3_PIN);
  doc["led4"] = digitalRead(LED4_PIN);
  
  // Serialize and send JSON
  serializeJson(doc, Serial);
  Serial.println();  // Add newline to complete the message
}

// Example sensor reading functions
float readTemperature() {
  return analogRead(A0) * 0.48;  // Example conversion - replace with actual sensor code
}

float readHumidity() {
  return analogRead(A1) * 0.1;  // Example conversion - replace with actual sensor code
}

Advanced DHT Sensor Example

#include <ArduinoJson.h>
#include <DHT.h>

#define DHTPIN 2          // Digital pin connected to the DHT sensor
#define DHTTYPE DHT22     // DHT 22 (AM2302)
#define RELAY_PIN 4       // Digital pin connected to relay
#define JSON_DOC_SIZE 384 // Larger for more complex JSON

DHT dht(DHTPIN, DHTTYPE);
bool autoMode = true;
float tempThreshold = 25.0; // Temperature threshold in °C

void setup() {
  Serial.begin(9600);
  pinMode(RELAY_PIN, OUTPUT);
  dht.begin();
  delay(2000); // DHT sensor stabilization
  
  // Initial status report
  sendStatusReport();
}

void loop() {
  // Handle incoming commands
  if (Serial.available() > 0) {
    String command = Serial.readStringUntil('\n');
    processCommand(command);
  }
  
  // Auto mode logic
  if (autoMode) {
    float temperature = dht.readTemperature();
    if (!isnan(temperature)) {
      if (temperature > tempThreshold) {
        digitalWrite(RELAY_PIN, HIGH); // Turn on cooling
      } else {
        digitalWrite(RELAY_PIN, LOW);  // Turn off cooling
      }
    }
  }
  
  // Send regular sensor updates
  static unsigned long lastSendTime = 0;
  if (millis() - lastSendTime > 10000) { // Every 10 seconds
    sendStatusReport();
    lastSendTime = millis();
  }
}

void processCommand(String command) {
  // Try to parse as JSON first
  StaticJsonDocument<JSON_DOC_SIZE> doc;
  DeserializationError error = deserializeJson(doc, command);
  
  if (!error) {
    // JSON command handling
    if (doc.containsKey("relay")) {
      digitalWrite(RELAY_PIN, doc["relay"] ? HIGH : LOW);
      autoMode = false; // Disable auto mode when manually controlled
    }
    
    if (doc.containsKey("auto")) {
      autoMode = doc["auto"];
    }
    
    if (doc.containsKey("threshold")) {
      tempThreshold = doc["threshold"];
    }
    
    // Send confirmation
    sendStatusReport();
  }
  else {
    // Key-value command handling
    int separatorPos = command.indexOf('=');
    if (separatorPos > 0) {
      String key = command.substring(0, separatorPos);
      String value = command.substring(separatorPos + 1);
      key.trim();
      value.trim();
      key.toLowerCase();
      
      if (key == "relay") {
        value.toLowerCase();
        bool state = (value == "on" || value == "true" || value == "1" || value == "high");
        digitalWrite(RELAY_PIN, state ? HIGH : LOW);
        autoMode = false;
      }
      else if (key == "auto") {
        value.toLowerCase();
        autoMode = (value == "on" || value == "true" || value == "1");
      }
      else if (key == "threshold") {
        tempThreshold = value.toFloat();
      }
      
      // Send confirmation
      sendStatusReport();
    }
  }
}

void sendStatusReport() {
  StaticJsonDocument<JSON_DOC_SIZE> doc;
  
  // Read sensor data
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  
  // Add sensor readings
  doc["humidity"] = isnan(h) ? "error" : h;
  doc["temperature"] = isnan(t) ? "error" : t;
  
  // Add system state
  doc["relay"] = digitalRead(RELAY_PIN);
  doc["auto_mode"] = autoMode;
  doc["threshold"] = tempThreshold;
  doc["uptime"] = millis() / 1000;
  
  // Serialize and send
  serializeJson(doc, Serial);
  Serial.println();
}

Battery Powered Sensor Node Example

#include <ArduinoJson.h>
#include <LowPower.h>

#define BATTERY_PIN A0
#define SOIL_MOISTURE_PIN A1
#define LIGHT_SENSOR_PIN A2
#define JSON_DOC_SIZE 256

// Configuration with defaults
int sleepCycles = 75;      // 75 cycles × 8s = 10 minutes
bool ledEnabled = false;   // LED indicators (disable to save power)
int sensorThreshold = 30;  // Soil moisture threshold percent

void setup() {
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW); // Ensure LED is off
  
  delay(1000); // Allow serial to initialize
  sendSensorData(); // Initial reading
}

void loop() {
  // Check for config commands
  if (Serial.available() > 0) {
    String command = Serial.readStringUntil('\n');
    processCommand(command);
  }
  
  // Flash LED indicator if enabled
  if (ledEnabled) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(50);
    digitalWrite(LED_BUILTIN, LOW);
  }
  
  // Send data before sleeping
  sendSensorData();
  
  // Enter power-down mode for 8s × sleepCycles
  Serial.flush(); // Make sure all serial data is sent
  for (int i = 0; i < sleepCycles; i++) {
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
  }
}

void processCommand(String command) {
  // Find key=value separator
  int separatorPos = command.indexOf('=');
  
  if (separatorPos > 0) {
    String key = command.substring(0, separatorPos);
    String value = command.substring(separatorPos + 1);
    
    key.trim();
    value.trim();
    key.toLowerCase();
    
    if (key == "sleep") {
      int cycles = value.toInt();
      if (cycles > 0) {
        sleepCycles = cycles;
      }
    }
    else if (key == "led") {
      value.toLowerCase();
      ledEnabled = (value == "on" || value == "true" || value == "1");
    }
    else if (key == "threshold") {
      int threshold = value.toInt();
      if (threshold >= 0 && threshold <= 100) {
        sensorThreshold = threshold;
      }
    }
    
    // Send updated configuration
    StaticJsonDocument<JSON_DOC_SIZE> doc;
    doc["config_sleep"] = sleepCycles;
    doc["config_led"] = ledEnabled;
    doc["config_threshold"] = sensorThreshold;
    serializeJson(doc, Serial);
    Serial.println();
  }
}

void sendSensorData() {
  StaticJsonDocument<JSON_DOC_SIZE> doc;
  
  // Read battery voltage (example calculation for 3.7V LiPo through voltage divider)
  int batteryRaw = analogRead(BATTERY_PIN);
  float batteryVoltage = batteryRaw * (5.0 / 1023.0) * 2.0; // Example voltage divider calculation
  int batteryPercent = map(batteryRaw, 614, 820, 0, 100);   // Map raw values to percentage (calibrate these values)
  batteryPercent = constrain(batteryPercent, 0, 100);
  
  // Read soil moisture (example)
  int soilRaw = analogRead(SOIL_MOISTURE_PIN);
  int soilPercent = map(soilRaw, 0, 1023, 100, 0);  // Inverted - higher resistance = drier soil
  
  // Read light level (example)
  int lightRaw = analogRead(LIGHT_SENSOR_PIN);
  int lightPercent = map(lightRaw, 0, 1023, 0, 100);
  
  // Populate JSON
  doc["device_id"] = "soil_sensor_1";
  doc["battery_v"] = batteryVoltage;
  doc["battery_pct"] = batteryPercent;
  doc["moisture"] = soilPercent;
  doc["light"] = lightPercent;
  doc["needs_water"] = soilPercent < sensorThreshold;
  
  // Serialize and send
  serializeJson(doc, Serial);
  Serial.println();
}

🖥️ Testing & Development Tools

🔌 PuTTY Serial Testing

PuTTY is a versatile tool for testing serial communication with your Arduino:

Basic PuTTY Setup

  1. Download and install PuTTY
  2. Configure PuTTY for serial connection:
    • Connection type: Serial
    • Serial line: COM8 (or your Arduino port)
    • Speed: 9600 (match Arduino baud rate)
    • Under Terminal → Local echo: Force on
    • Under Terminal → Local line editing: Force on

PuTTY Testing Examples

Testing Arduino Output:

  1. Open PuTTY with the above configuration
  2. Messages from the Arduino will appear in the terminal
  3. You should see JSON data like:
    {"temperature":23.5,"humidity":48,"light":512}

Sending Commands to Arduino:

  1. Type a command in PuTTY window and press Enter
  2. Example commands:
    LED_ON
    l1=on
    l2=off
    l3=128
    {"led1":true,"led2":false}

Using for Serial Bridge Testing:

  1. Install a COM port emulator like com0com
  2. Create a virtual port pair (COM7-COM8)
  3. Configure arduino-mqtt bridge to use COM7
  4. Connect PuTTY to COM8
  5. Start the bridge with arduino-mqtt run
  6. Type sample JSON data into PuTTY:
    {"temperature":23.5,"humidity":55,"light":890}
  7. This data will be forwarded to your MQTT broker

🔧 Arduino IDE Serial Monitor

The Arduino IDE's built-in Serial Monitor is perfect for quick testing:

Basic Setup

  1. Connect your Arduino to your computer
  2. Open Arduino IDE
  3. Select the correct board and port
  4. Open Serial Monitor (Tools → Serial Monitor or Ctrl+Shift+M)
  5. Set baud rate to match your Arduino (e.g., 9600)
  6. Set line ending to "Newline"

Testing Examples

Monitoring Arduino Output:

  1. Upload a sketch that sends JSON data (like examples above)
  2. Open Serial Monitor
  3. You'll see the JSON output:
    {"temperature":22.8,"humidity":45,"led1":1,"led2":0}

Sending Commands:

  1. Type commands in the input field at the top of Serial Monitor
  2. Press "Send" or Enter
  3. Example commands:
    l1=on
    l1=off
    l2=128
  4. Verify the Arduino responds correctly (LEDs change, status updates)

Testing While Bridge is Running:

  1. Upload your sketch to Arduino
  2. Start the bridge in a terminal: arduino-mqtt run
  3. Open Arduino IDE Serial Monitor
  4. You'll see a warning about port being in use - this is expected
  5. Close Serial Monitor and interact with Arduino via MQTT clients

📊 MQTTX Client

MQTTX is a free, cross-platform MQTT client with a user-friendly interface:

Setting up MQTTX

  1. Download MQTTX for your platform
  2. Install and open the application
  3. Click "+" to add a new connection
  4. Configure connection:
    • Name: Arduino Bridge
    • Host: localhost (or your MQTT broker address)
    • Port: 1883 (default MQTT port)
    • Add client ID, username, and password if required

MQTTX Testing Examples

Subscribing to Arduino Data:

  1. After connecting, click "New Subscription"
  2. Topic: arduino/sensors (or your configured sensorsTopic)
  3. QoS: 0
  4. Click "Confirm"
  5. You should see incoming data from your Arduino as JSON messages

Sending Commands to Arduino:

  1. In "Publish" section:
    • Topic: arduino/commands (or your configured commandsTopic)
    • QoS: 0
    • Retain: false (usually)
  2. Type a command in the payload field:
    l1=on
  3. Click "Send"
  4. Arduino should respond by turning on the LED
  5. Try other commands:
    l1=off
    led2=128
    all=high
  6. For JSON commands, select "JSON" format in MQTTX and enter:
    {
      "led1": true,
      "led2": false,
      "threshold": 25
    }

Testing Complex Scenarios:

  1. Subscribe to multiple topics:
    • arduino/sensors (for main data)
    • arduino/sensors/raw (for non-JSON data)
    • arduino/status (if your sketch publishes status)
  2. Use the MQTTX history feature to save frequently used commands
  3. Create a workspace with frequently used topics
  4. Test message retention by enabling "Retain" for configuration commands

🔄 Combined Testing Workflow

For a complete test setup, try this workflow:

  1. Setup:

    • Connect Arduino or set up COM port emulator
    • Configure arduino-mqtt with arduino-mqtt config
    • Start the bridge with arduino-mqtt run
    • Open MQTTX and connect to your broker
    • Subscribe to arduino/sensors topic
  2. Testing Arduino → MQTT Flow:

    • Open Arduino IDE Serial Monitor (or PuTTY) to view/send serial data
    • Send data via Serial Monitor or have your Arduino sketch send data
    • Verify the data appears in MQTTX
  3. Testing MQTT → Arduino Flow:

    • In MQTTX, publish a command to arduino/commands
    • Verify the Arduino responds correctly (LEDs change state)
    • Check the Arduino's JSON response to confirm changes
  4. Troubleshooting with Serial Monitor:

    • Stop the bridge
    • Open Arduino IDE Serial Monitor
    • Test commands directly to isolate issues
    • Close Serial Monitor and restart the bridge

🧰 Troubleshooting

Common Issues:

  • Serial port not found: Ensure your Arduino is connected and the port is correct
  • MQTT connection failed: Verify broker address and credentials
  • No data from Arduino: Check baud rate matches your Arduino sketch
  • Garbled data: Ensure line endings are consistent (use \n or \r\n)
  • JSON parsing errors: Verify your Arduino is sending valid JSON data
  • Commands not working: Make sure newline characters are being sent after commands
  • Bridge starts but no data flows: Confirm topics match between bridge and MQTT client

Advanced Troubleshooting:

  • Use the bridge's raw topic (sensorsTopic/raw) to see unparsed data
  • Enable verbose logging in your MQTT broker (if available)
  • Test with simple text commands before trying JSON commands
  • Use arduino-mqtt get to verify your configuration settings
  • Check Arduino serial buffer size if sending large JSON payloads

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🤝 Contributing

Contributions are welcome! Feel free to open issues or submit pull requests.

🙏 Acknowledgements

  • SerialPort for the robust serial communication
  • await-mqtt for the Promise-based async/await MQTT client implementation
  • MQTT.js for the MQTT client implementation
  • ArduinoJson for efficient JSON parsing on Arduino
  • Clack for the beautiful CLI interface