🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

arduino-mqtt

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

arduino-mqtt

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.

latest
npmnpm
Version
0.0.7
Version published
Maintainers
1
Created
Source

🔌 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

ParameterDescriptionDefault Value
portSerial port connected to ArduinoCOM7
baudBaud rate for serial communication9600
ipMQTT broker addressmqtt://localhost:1883
commandsTopicTopic to receive commands for Arduinoarduino/commands
sensorsTopicTopic to publish Arduino sensor dataarduino/sensors
usernameMQTT broker username (if required)
passwordMQTT broker password (if required)

📝 Command Reference

CommandDescription
arduino-mqtt configInteractive configuration wizard
arduino-mqtt runStart the bridge
arduino-mqtt stopStop 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

  • Download and install PuTTY
  • 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:

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

Sending Commands to Arduino:

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

Using for Serial Bridge Testing:

  • Install a COM port emulator like com0com
  • Create a virtual port pair (COM7-COM8)
  • Configure arduino-mqtt bridge to use COM7
  • Connect PuTTY to COM8
  • Start the bridge with arduino-mqtt run
  • Type sample JSON data into PuTTY:
    {"temperature":23.5,"humidity":55,"light":890}
    
  • 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

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

Testing Examples

Monitoring Arduino Output:

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

Sending Commands:

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

Testing While Bridge is Running:

  • Upload your sketch to Arduino
  • Start the bridge in a terminal: arduino-mqtt run
  • Open Arduino IDE Serial Monitor
  • You'll see a warning about port being in use - this is expected
  • 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

  • Download MQTTX for your platform
  • Install and open the application
  • Click "+" to add a new connection
  • 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:

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

Sending Commands to Arduino:

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

Testing Complex Scenarios:

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

🔄 Combined Testing Workflow

For a complete test setup, try this workflow:

  • 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
  • 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
  • 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
  • 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

FAQs

Package last updated on 26 May 2025

Did you know?

Socket

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.

Install

Related posts