Tipcontrol Arduino Demo

Description

This Arduino sketch demonstrates how to use an ESP32 board to connect to WiFi, establish an MQTT connection, and send commands to a Tipcontrol device. The Tipcontrol device receives MQTT messages and executes the code contained in those messages directly on its chip.

This means you can send any code snippet (written in Tipcontrol’s scripting language) over MQTT, and the device will run it as if it were local code.

Important Note

For this example to work:

  • The Tipcontrol device must have its own WiFi connection.
  • It must be connected to the same MQTT server as the ESP32.
  • If either device is on a different network or broker, the messages will not be delivered.

Features of this example

  • Connects ESP32 to a WiFi network.
  • Configures and connects to an MQTT broker.
  • Publishes command strings to a Tipcontrol device.
  • Subscribes to a topic to receive messages back.
  • Demonstrates two examples:
    1. Cycling NeoPixel LEDs with random colors.
    2. Publishing temperature and humidity readings from an SHT40 sensor.

Configuration

Configuration

Before running, update the following variables with your own values:

std::string ssid = "your-SSID";          // WiFi SSID
std::string password = "your-PASSWORD";  // WiFi password

std::string mqtt_server = "your-MQTT-SERVER_URL"; // MQTT broker URL
std::string mqtt_user = "your-MQTT-USER";         // MQTT username
std::string mqtt_password = "your-MQTT-PASSWORD"; // MQTT password
uint16_t mqtt_port = 1883;                        // MQTT port (default 1883)

Also set the topics:

std::string subscribeTopic = "demo.demo/arduino"; 
std::string publishTopic = "demo.demo.esp32/exec"; 
  • subscribeTopic: where this ESP32 listens for incoming messages.
  • publishTopic: where this ESP32 sends commands for the Tipcontrol device to execute.

Code

#include <Arduino.h>
#include <WiFi.h>
#include "ESP32MQTTClient.h" // Custom MQTT client library for ESP32
#include "esp_idf_version.h" // Used to check ESP-IDF version

// ==========================
// User configuration
// ==========================

// WiFi credentials – replace these with your network information
std::string ssid = "your-SSID";         
std::string password = "your-PASSWORD"; 

// MQTT server information – replace with your broker info
std::string mqtt_server = "your-MQTT-SERVER_URL"; 
std::string mqtt_user = "your-MQTT-USER";     
std::string mqtt_password = "your-MQTT-PASSWORD"; 
uint16_t mqtt_port = 1883; // Default MQTT port

// ==========================
// MQTT Client instance
// ==========================
ESP32MQTTClient mqttClient;

// Function prototype for MQTT connection callback
void onMqttConnect(esp_mqtt_client_handle_t client);

// Topics for subscribing and publishing
std::string subscribeTopic = "demo.demo/arduino"; // topic this device listens to needs to start with user.project if using the tipcontrol mqtt server
std::string publishTopic = "demo.demo.esp32/exec"; // user.project.chipName of the tipcontrol device you want to send the command to 

// ==========================
// IDF version compatibility
// ==========================
// Different ESP-IDF versions require different MQTT event handler signatures
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
esp_err_t handleMQTT(esp_mqtt_event_handle_t event)
{
  mqttClient.onEventCallback(event); // Call the MQTT client event handler
  return ESP_OK;
}
#else
void handleMQTT(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
  auto *event = static_cast<esp_mqtt_event_handle_t>(event_data);
  mqttClient.onEventCallback(event); // Call the MQTT client event handler
}
#endif

// ==========================
// Arduino setup function
// ==========================
void setup()
{
  Serial.begin(115200); // Initialize serial monitor for debugging
  delay(2000);          // Short delay to stabilize

  // Connect to WiFi
  WiFi.begin(ssid->c_str(), password->c_str());
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(WiFi.status()); // Print status code while connecting
  }
  Serial.println("connected");

  // Configure MQTT client
  mqttClient.setURL(mqtt_server->c_str(), mqtt_port, mqtt_user->c_str(), mqtt_password->c_str());

  // Enable Last Will and Testament (message sent if device disconnects unexpectedly)
  mqttClient.enableLastWillMessage("lwt", "I am going offline");

  // Set MQTT keep-alive interval (seconds)
  mqttClient.setKeepAlive(30);

  // Start MQTT event loop in background
  mqttClient.loopStart();

  delay(2000); // Give time for connections to stabilize
}

void loop()
{
  // ==========================
  // Example 1: Publish a command to cycle neopixel LEDs with random colors
  // ==========================
  String msg = ":{ "                              // remember to start the code with :
               "for (i = 0, i < 25, i += 1) { "   // loop 25 times
               "red = lib.math.random(0,255); "    // generate random red value
               "green = lib.math.random(0,255); "  // generate random green value
               "blue = lib.math.random(0,255); "   // generate random blue value
               "drv.neopixel.setLeds(red, green, blue, 1, 0); " // set the neopixel LED colors
               "delay(1000);}; } "; // wait 1 second before next iteration

  // Try publishing the message until it succeeds
  while (!mqttClient.publish(publishTopic.c_str(), msg.c_str()))
  {
    Serial.println("publish failed, retrying in 5s");
    delay(5000); // retry every 5 seconds
  }

  delay(35000); // wait 35 seconds before sending next command

  // ==========================
  // Example 2: Publish temperature and humidity readings
  // ==========================
  String topic = String(subscribeTopic.c_str()); // Convert the subscribe topic to Arduino String

  // Build a command message string to send sensor readings
  msg = ":{ "
        "send = \"Temperature: \" + drv.sht40.var.temperature + \" Humidity: \" + drv.sht40.var.humidity;" 
        // 'send' is a variable that concatenates the current temperature and humidity values
        "drv.mqtt.publish(\"" + topic + "\",send,0);}" 
        // publish the 'send' message to the subscribed MQTT topic with QoS 0
        ;

  // Retry publishing until it succeeds
  while (!mqttClient.publish(publishTopic.c_str(), msg.c_str()))
  {
    Serial.println("publish failed, retrying in 5s");
    delay(5000);
  }

  delay(15000); // wait 15 seconds before next loop iteration
}


// ==========================
// MQTT connection callback
// ==========================
void onMqttConnect(esp_mqtt_client_handle_t client)
{
  Serial.println("Connected to MQTT");

  // Subscribe to a topic and print any received messages to the serial monitor
  mqttClient.subscribe(subscribeTopic, [](const std::string &payload)
                       { Serial.println(payload.c_str()); }); // Lambda function callback
}