Contents

DashIO IoT Guide (ESP8266)

9 Feb 2022

So, what is DashIO? It is a quick effortless way to connect your IoT device to your phone. It allows easy setup of controls such as Dials, Text Boxes, Maps, Graphs, Notifications..., from your IoT device. You can define the look and layout of the controls on your phone from your IoT device. There are three methods to connect to your phone; Bluetooth Low Energy (BLE), TCP or MQTT. What's Dash then? Dash is a MQTT server with extra bits added in to allow you to send notifications, share your devices, and save your settings from your phone via the DashIO app.

This guide demonstractes how to make TCP and MQTT connections to an ESP8266 IoT device using the Arduino IDE.

The MQTT connection discussed in this guide is SSL/TLS enabled and we highly recommend that you only use SSL/TLS connections. The Dash MQTT server only accepts SSL connections. However, the ESP8266 does not include hardware for creating trust with certificates. Therefore, the MQTT connection is encrypted, but trust is not established.

Getting Started

For the big picture on DashIO, take a look at our website: dashio.io

For the DashIO arduino library: github.com/dashio-connect/arduino-dashio

Requirements

Grab an ESP8266 board, Arduino IDE and follow this guide. This example should work on ESP8266 development boards available for the Arduino IDE.

You will need to install the DashIO app on your pobile phone or tablet. And if you'd like to connect to one IoT device for free, setup a free DashIO account from within the DashIO app.

Install

DashIO

You will need to add the DashIO library into your project. Download the DashIO library from GitHub with the following link: https://github.com/dashio-connect/arduino-dashio

Place the DashIO library files into your project directory or add them into your library.

ESP8266 Support (WiFi, TCP and mDNS)

If you haven't yet installed the ESP8266 Arduino IDE support from espressif, please check the following link for instructions: https://github.com/esp8266/Arduino#installing-with-boards-manager

From the ESP8266 espressif library, we will use the WiFi library (ESP8266WiFi.h) and the secure WiFi client (WiFiClientSecure.h) to enable SSL connections, which are required for the Dash server.

For mDNS we are using the ESP8266mDNS.h library, which is included in the ESP8266 espressif library.

The arduino-timer library is also use for the WiFi and MQTT connection and is available in the Arduino IDE Library Manager. Search the library manager for the library titled "arduino-timer" and install.

MQTT

For MQTT we are using the arduino-mqtt library created by Joël Gähwiler. This is available in the Arduino IDE Library Manager, by searching for "mqtt" and installing the library titled "MQTT" by Joël Gähwiler. This library is also stored on GitHub where there are examples and other useful information: https://github.com/256dpi/arduino-mqtt

Guide

TCP Basics

Lets have a look at a TCP connection.

#include "DashioESP.h"

char WIFI_SSID[] = "yourWiFiSSID";
char WIFI_PASSWORD[] = "yourWiFiPassword";
#define TCP_PORT 5000

DashioDevice dashioDevice("ESP8266_Type");
DashioTCP    tcp_con(&dashioDevice, TCP_PORT, true);
DashioWiFi   wifi;

void setup() {
    Serial.begin(115200);
    delay(1000);
    
    dashioDevice.setup(wifi.macAddress(), "Jim Name"); // unique deviceID, and device name
    wifi.attachConnection(&tcp_con);
    wifi.begin(WIFI_SSID, WIFI_PASSWORD);
}

void loop() {
    wifi.run();
}

After the include we create a device and a TCP connection, with the device being an attribute to the connection. We also provide a port and the third attribute of the TCP connection enables the received and transmitted messages to be printed to the serial monitor.

In the setup function we setup the device with two parameters. These parameters describe the device to the DashIO app to allow it uniquely identify each device. The wifi object supplies the mac to the device, to be used as a unique device_ID.

We then attach the TCP connection to the wifi with wifi.attachConnection(&tcp_con);. This enables to wifi object to control the TCP connection from here on in.

We begin the wifi with the SSID and password. This starts the wifi and TCP connection and sets up the the mDNS (also called Bonjour or Zeroconf) to make the device discoverable on the DashIO app.

wifi.run(); is used to regularly check that the WiFi is connected and manage the attached connection.

This device is discoverable by the DashIO app. You can also discover your IoT device using a third party Bonjour/Zeroconf discovery tool. The mDNS service will be "_DashIO._tcp." and individual IoT devices on this service are identified by their mac address (device_ID).

In the code above, make sure you replace yourWiFiSSID with your WiFi SSID and yourWiFiPassword with your WiFI password. Setup the Arduino IDE serial monitor with 115200 baud and run the code. You will see messages on the Arduino serial monitor, and after a few attampts, your IoT device should connect to your WiFi and start the mDNS service. Then run the DashIO app on your mobile device and you will see connection "WHO" messages on the Arduino serial monitor.

Lets add dial control messages that are sent to the DashIO app every second. We use a timer and send a Dial value message from the loop every second.

#include "DashioESP.h"
#include <Arduino-timer.h>

char WIFI_SSID[] = "yourWiFiSSID";
char WIFI_PASSWORD[] = "yourWiFiPassword";
#define TCP_PORT 5000

DashioDevice dashioDevice("ESP8266_Type");
DashioTCP    tcp_con(&dashioDevice, TCP_PORT, true);
DashioWiFi   wifi;

auto timer = timer_create_default();
bool oneSecond = false; // Set by timer every second.

static bool onTimerCallback(void *argument) {
  oneSecond = true;
  return true; // to repeat the timer action - false to stop
}

void setup() {
    Serial.begin(115200);
    delay(1000);
    
    dashioDevice.setup(wifi.macAddress(), "Jim Name"); // unique deviceID, and device name
    wifi.attachConnection(&tcp_con);
    wifi.begin(WIFI_SSID, WIFI_PASSWORD);

    timer.every(1000, onTimerCallback); // 1000ms
}

void loop() {
    timer.tick();
    wifi.run();

    if (oneSecond) { // Tasks to occur every second
        oneSecond = false;
        tcp_con.sendMessage(dashioDevice.getDialMessage("D01", int(random(0, 100))));
    }
}

The code tcp_con.sendMessage(dashioDevice.getDialMessage("D01", int(random(0, 100)))); creates the message with two parameters. The first parameter is the control_ID which identifies the specific Dial control in the DashIO app and the second attribute is simply the Dial value.

Once again, run the above code and the DashIO app. This time, a new "DIAL" messages will be seen on the serial monitor every second.

The next step is to show the dial values from the messages on a control on the DashIO app.

It would be nice to have the DashIO app automagically setup a new Device View and place your control on the new Device View. To do that we need to add a few more lines of code. Most importantly, we need to respond to messages coming in from the DashIO app. To do this we add a callback into the TCP connection with the setCallback function.

#include "DashioESP.h"
#include <Arduino-timer.h>

char WIFI_SSID[] = "yourWiFiSSID";
char WIFI_PASSWORD[] = "yourWiFiPassword";
#define TCP_PORT 5000

DashioDevice dashioDevice("ESP8266_Type");
DashioTCP    tcp_con(&dashioDevice, TCP_PORT, true);
DashioWiFi   wifi;

auto timer = timer_create_default();
bool oneSecond = false; // Set by timer every second.

static bool onTimerCallback(void *argument) {
  oneSecond = true;
  return true; // to repeat the timer action - false to stop
}

void processConfig(ConnectionType connectionType) {
    String message((char *)0);
    message.reserve(2048);

    message += dashioDevice.getConfigMessage(DeviceCfg(1)); // One Device Views

    DialCfg first_dial_control("D01", "DV01", "Dial", {0.24, 0.14, 0.54, 0.26});
    message += dashioDevice.getConfigMessage(first_dial_control);

    DeviceViewCfg deviceView("DV01", "A Dial", "up", "0");
    message += dashioDevice.getConfigMessage(deviceView);

    tcp_con.sendMessage(message);
}

void processIncomingMessage(MessageData *messageData) {
    switch (messageData->control) {
    case config:
        processConfig(messageData->connectionType);
        break;
    }
}

void setup() {
    Serial.begin(115200);
    delay(1000);
    
    tcp_con.setCallback(&processIncomingMessage);
    dashioDevice.setup(wifi.macAddress(), "Jim Name"); // unique deviceID, and device name
    wifi.attachConnection(&tcp_con);
    wifi.begin(WIFI_SSID, WIFI_PASSWORD);

    timer.every(1000, onTimerCallback); // 1000ms
}

void loop() {
    timer.tick();
    wifi.run();

    if (oneSecond) { // Tasks to occur every second
        oneSecond = false;
        tcp_con.sendMessage(dashioDevice.getDialMessage("D01", int(random(0, 100))));
    }
}

The processIncomingMessage callback checks the message type and calls the appropriate function. At this stage we are only interested in CONFIG messages and the processConfig function is called appropriately. This part of the code creates quite long messages, so we allocate enough space for the message, 2048 bytes in this case. We create and send three config response messages:

  1. Device: lets the DashIO app know there is a device with one Device View.
  2. Dial: includes the control_ID of the Dial, the control_ID of the Device View it will be displayed on, the title and the position of the dial on the Device View.
  3. DeviceView: includes the control_ID, title, icon name and colour of the Device View.

Run the DashIO app once more. This time you will need to load the configuration data from your device to display the Dial Control. Tap the All Devices button, followed by the Find New Devices button. Then select the TCP Discovery option to show a list of new IoT devices that are mDNS enabled. Your device will be shown (named "Jim Name"). Select your IoT device and follow the instructions to load the Device View with a Dial Control.

The next piece of the puzzle to consider is how we receive data from the DashIO app. Lets add a Knob and connect it to the Dial. We do this by adding the Knob to the processIncomingMessage function and send the Knob value to the Dial in the processConfig function. And remember to remove the timer and the Dial ble_con.sendMessage from the loop:

void processConfig(ConnectionType connectionType) {
    String message((char *)0);
    message.reserve(2048);

    message += dashioDevice.getConfigMessage(DeviceCfg(1)); // One Device Views

    DialCfg first_dial_control("D01", "DV01", "Dial", {0.24, 0.14, 0.54, 0.26});
    message += dashioDevice.getConfigMessage(first_dial_control);

    KnobCfg aKnob("KB01", "DV01", "Knob", {0.24, 0.42, 0.54, 0.26});
    message += dashioDevice.getConfigMessage(aKnob);

    DeviceViewCfg deviceView("DV01", "Dial & Knob", "up", "black");
    message += dashioDevice.getConfigMessage(deviceView);
    
    tcp_con.sendMessage(message);
}

void processIncomingMessage(MessageData *messageData) {
    switch (messageData->control) {
    case config:
        processConfig(messageData->connectionType);
        break;
    case knob:
        if (messageData->idStr == "KB01") {
            String message = dashioDevice.getDialMessage("D01", (int)messageData->payloadStr.toFloat());
            tcp_con.sendMessage(message);
        }
        break;
    }
}

Run the DashIO app and then you will need to reload the configuration from your IoT device; Tap the All Devices button and select your device, then tap the Get Layout button. Follow the instructions to update the Device View to contain both a Dial and Knob Control. When you adjust the Knob on the DashIO app, a message with the knob value is sent your IoT device, which returns the knob value into the dial control, which you will see on the DashIO app.

Finally, we should respond to the STATUS message from the DashIO app. STATUS messages allows the IoT device to send initial conditions for each control to the DashIO app as soon as a connection becomes active. Once again, we do this from the processIncomingMessage function and our complete code looks like this:

#include "DashioESP.h"

char WIFI_SSID[] = "yourWiFiSSID";
char WIFI_PASSWORD[] = "yourWiFiPassword";
#define TCP_PORT 5000

DashioDevice dashioDevice("ESP8266_Type");
DashioTCP    tcp_con(&dashioDevice, TCP_PORT, true);
DashioWiFi   wifi;

int dialValue = 0;

void processConfig(ConnectionType connectionType) {
    String message((char *)0);
    message.reserve(2048);

    message += dashioDevice.getConfigMessage(DeviceCfg(1)); // One Device Views

    DialCfg first_dial_control("D01", "DV01", "Dial", {0.24, 0.14, 0.54, 0.26});
    message += dashioDevice.getConfigMessage(first_dial_control);

    KnobCfg aKnob("KB01", "DV01", "Knob", {0.24, 0.42, 0.54, 0.26});
    message += dashioDevice.getConfigMessage(aKnob);

    DeviceViewCfg deviceView("DV01", "Dial & Knob", "up", "black");
    message += dashioDevice.getConfigMessage(deviceView);
    
    tcp_con.sendMessage(message);
}

void processStatus(ConnectionType connectionType) {
    String message((char *)0);
    message.reserve(1024);

    message = dashioDevice.getKnobMessage("KB01", dialValue);
    message += dashioDevice.getDialMessage("D01", dialValue);

    tcp_con.sendMessage(message);
}

void processIncomingMessage(MessageData *messageData) {
    switch (messageData->control) {
    case status:
        processStatus(messageData->connectionType);
        break;
    case config:
        processConfig(messageData->connectionType);
        break;
    case knob:
        if (messageData->idStr == "KB01") {
            dialValue = messageData->payloadStr.toFloat();
            String message = dashioDevice.getDialMessage("D01", dialValue);
            tcp_con.sendMessage(message);
        }
        break;
    }
}

void setup() {
    Serial.begin(115200);
    delay(1000);
    
    tcp_con.setCallback(&processIncomingMessage);
    dashioDevice.setup(wifi.macAddress(), "Jim Name"); // unique deviceID, and device name
    wifi.attachConnection(&tcp_con);
    wifi.begin(WIFI_SSID, WIFI_PASSWORD);
}

void loop() {
    wifi.run();
}

MQTT Basics

Now lets look at a MQTT connection. We also need the WiFi for MQTT.

#include "DashioESP.h"

// WiFi
char WIFI_SSID[] = "yourWiFiSSID";
char WIFI_PASSWORD[] = "yourWiFiPassword";

// MQTT
char MQTT_USER[] = "yourMQTTuserName";
char MQTT_PASSWORD[] = "yourMQTTpassword";

DashioDevice dashioDevice("DashIO_Nano_Type");
DashioMQTT mqtt_con(&dashioDevice, 2048, true, true);
DashioWiFi wifi;

void setup() {
    Serial.begin(115200);

    dashioDevice.setup(wifi.macAddress(), "Bob Name"); // unique deviceID, and device name
    mqtt_con.setup(MQTT_USER, MQTT_PASSWORD);
    wifi.attachConnection(&mqtt_con);
    wifi.begin(WIFI_SSID, WIFI_PASSWORD);
}

void loop() {
    wifi.run();
}

Again we create a device and this time a MQTT connection, with the device being an attribute to the connection. We also provide a buffer size (2048) and the third attribute of the MQTT connection enables a push notification to be sent to your mobile phone when the IoT device reboots (Dash MQTT only). The final attribute enables the received and transmitted messages to be printed to the serial monitor.

In the setup function we setup the device with two parameters. These parameters describe the device to the DashIO app to allow it uniquely identify each device. The wifi object supplies the mac address to the device, to be used as a unique device_ID.

For MQTT connections, the device must be setup before we begin the wifi.

The MQTT connection setup requires the MQTT broker username and password, supplied in the mqtt_con.setup(MQTT_USER, MQTT_PASSWORD); method.

We then attach the MQTT connection to the wifi with wifi.attachConnection(&mqtt_con);. This enables to wifi object to control the MQTT connection from here on in.

Finally, we begin the wifi with the SSID and password.

wifi.run(); is used to regularly check that the WiFi is connected and to manage the attached connection.

This device is discoverable by the DashIO app.

In the code above, make sure you replace yourWiFiSSID with your WiFi SSID, yourWiFiPassword with your WiFI password, yourMQTTuserName with you dash account username and yourMQTTpassword with your dash account password. Setup the Arduino IDE serial monitor with 115200 baud and run the code. You will see messages on the Arduino serial monitor, and after a few attampts, your IoT device should connect to your WiFi and then connect to the dash MQTT server.

Message processing for a MQTT connection is done exactly the samy way as for the TCP connection, by adding the processIncomingMessage callback into the MQTT connection during setup function. Our finished code, with Dial and Knob added is:

#include "DashioESP.h"

// WiFi
char WIFI_SSID[] = "yourWiFiSSID";
char WIFI_PASSWORD[] = "yourWiFiPassword";

// MQTT
char MQTT_USER[] = "yourMQTTuserName";
char MQTT_PASSWORD[] = "yourMQTTpassword";

DashioDevice dashioDevice("DashIO_Nano_Type");
DashioMQTT   mqtt_con(&dashioDevice, 2048, true, true);
DashioWiFi   wifi;

int dialValue = 0;

void processConfig(ConnectionType connectionType) {
    String message((char *)0);
    message.reserve(2048);

    message += dashioDevice.getConfigMessage(DeviceCfg(1)); // One Device Views

    DialCfg first_dial_control("D01", "DV01", "Dial", {0.24, 0.14, 0.54, 0.26});
    message += dashioDevice.getConfigMessage(first_dial_control);

    KnobCfg aKnob("KB01", "DV01", "Knob", {0.24, 0.42, 0.54, 0.26});
    message += dashioDevice.getConfigMessage(aKnob);

    DeviceViewCfg deviceView("DV01", "Dial & Knob", "up", "black");
    message += dashioDevice.getConfigMessage(deviceView);
    
    mqtt_con.sendMessage(message);
}

void processStatus(ConnectionType connectionType) {
    String message((char *)0);
    message.reserve(1024);

    message = dashioDevice.getKnobMessage("KB01", dialValue);
    message += dashioDevice.getDialMessage("D01", dialValue);

    mqtt_con.sendMessage(message);
}

void processIncomingMessage(MessageData *messageData) {
    switch (messageData->control) {
    case status:
        processStatus(messageData->connectionType);
        break;
    case config:
        processConfig(messageData->connectionType);
        break;
    case knob:
        if (messageData->idStr == "KB01") {
            dialValue = messageData->payloadStr.toFloat();
            String message = dashioDevice.getDialMessage("D01", dialValue);
            mqtt_con.sendMessage(message);
        }
        break;
    }
}

void setup() {
    Serial.begin(115200);

    dashioDevice.setup(wifi.macAddress(), "Bob Name"); // unique deviceID, and device name
    mqtt_con.setup(MQTT_USER, MQTT_PASSWORD);
    mqtt_con.setCallback(&processIncomingMessage);
    wifi.attachConnection(&mqtt_con);
    wifi.begin(WIFI_SSID, WIFI_PASSWORD);
}

void loop() {
    wifi.run();
}

Run the DashIO app once more. This time you will need to load the configuration data from your device to display the Dial and Knob Controls. Tap the All Devices button, followed by the Find New Devices button. Then select the My Devices On DashIO option to show a list of new IoT devices that have announced themselves to the dash server. Your device will be shown (named "Bob Name"). Select your IoT device and follow the instructions to load the Device View.

When you adjust the Knob on the DashIO app, a message with the knob value is sent your IoT device, which returns the knob value into the dial control, which you will see on the DashIO app.

For MQTT connections operating through the DashIO MQTT broker, a service is available for sending Alarms (push notifications) to your mobile device. These are handy for sending messages or alarms to the user when they are not currently using the DashIO app. To send an alarm, simply call the MQTT connection's sendMessage method with two attrbutes; the first being any message String and the second having alarm_topic specified.

mqtt_con.sendMessage("message", alarm_topic);

Combining TCP and MQTT

The ESP8266 is capable of operating with both TCP and MQTT connections. It's relativelty easy to combine to code for both connections in one ESP8266 IoT device where each connection calls a common processIncomingMessage callback.

This is just the beginning and there is a lot more we can do. Take a look at the examples in the library to see more details.

Provisioning

Provisioning is the method by which the DashIO app can send user credentials and other setup information to the IoT device and the IoT device will store this data to non-volatile memory.

A provisioning library is available within the DashIO library for the ESP38266 (DashioProvisionESP.h and DashioProvisionESP.cpp) which stores the following provisioning data to EEPROM:

  • Device Name
  • WiFi SSID
  • WiFI Password
  • Dash MQTT broker User Name
  • Dash MQTT broker Password

The library exposes the following structure to manade the provisioning data:

struct DeviceData {
    char deviceName[32];
    char wifiSSID[32];
    char wifiPassword[63];
    char dashUserName[32];
    char dashPassword[32];
    char saved;
};

Use the provisioning library as follows:

Include the library

#include "DashioProvisionESP.h"

Create a provisioning object

DashioProvision dashioProvision(&dashioDevice);

Setup provisioning in the setup method. Here we update the provisioning object with the default provisioning data (using the DeviceData structure), then load the provisioning data. If the provisioning data has never been saved, then the the default provisionig data will be used. We also include a provision callback (discussed later).

We then use the provisioning data in the WiFi and MQTT setup.

// setup
DeviceData defaultDeviceData = {DEVICE_NAME, WIFI_SSID, WIFI_PASSWORD, MQTT_USER, MQTT_PASSWORD};
dashioProvision.load(&defaultDeviceData, &onProvisionCallback);

dashioDevice.setup(wifi.macAddress());
    
mqtt_con.setup(dashioProvision.dashUserName, dashioProvision.dashPassword);
mqtt_con.setCallback(&processIncomingMessage);
    
wifi.attachConnection(&mqtt_con);
wifi.begin(dashioProvision.wifiSSID, dashioProvision.wifiPassword);

Add provisioning process message in the processIncomingMessage callback from the example above becomes:

void processIncomingMessage(MessageData *messageData) {
    switch (messageData->control) {
    case status:
        processStatus(messageData->connectionType);
        break;
    case config:
        processConfig(messageData->connectionType);
        break;
    case knob:
        if (messageData->idStr == "KB01") {
            dialValue = messageData->payloadStr.toFloat();
            String message = dashioDevice.getDialMessage("D01", dialValue);
            ble_con.sendMessage(message);
        }
        break;
    default:
        dashioProvision.processMessage(messageData);
        break;
    }
}

Make sure your IoT device lets the DashIO app know what provisioning services are available. This is done in the device configuration message:

message += dashioDevice.getConfigMessage(DeviceCfg(1), "name, wifi, dashio"); // One Device Views

The second attribute of the device configuration message contains a comma separated string where each field defines a provisioning service that is available in the IoT device. The possible options are:

  • "name" (set the device name)
  • "wifi" (set the WiFI SSID and password)
  • "dashio" (set the dashio username and password)

And finally, here is the onProvisionCallback:

void onProvisionCallback(ConnectionType connectionType, const String& message, bool commsChanged) {
    tcp_con.sendMessage(connectionType, message);

    if (commsChanged) {
        mqtt_con.setup(dashioProvision.dashUserName, dashioProvision.dashPassword);
        wifi.begin(dashioProvision.wifiSSID, dashioProvision.wifiPassword);
    }
}

The callback has two purposes. Firstly we send a message back to the DashIO app to let it know the provisioning is complete. And secondly, if the WiFi or MQTT connection credentials have changed, we need to restart the WiFi or MQTT connection. In the above example we call begin on the WiFI and MQTT. Alternatively, you could reboot the processor for a fresh start.

To provision your device, run the DashIO app and tap the All Devices button and select your device. Tap the Provisioning button and follow the instructions.

SoftAP Provisioning

SoftAP enables the ESP8266 to be made into a wireless access point. This is particularly useful for provisioning WiFi, TCP and MQTT services because the ESP8266 does not contain BLE functionality (BLE is very useful for provisioning).

The SoftAP functionality is included in the DashioESP library and can be implemented follows:

#include <DashioESP.h>

char DEVICE_TYPE[] = "ESP8266_DashIO";
char DEVICE_NAME[] = "DashIO8266";

#define TCP_PORT 5650
#define SOFT_AP_PWD    "" // Can be empty i.e. "" or must be a VALID password

DashioDevice    dashioDevice(DEVICE_TYPE);
DashioSoftAP    soft_AP;
DashioTCP       tcp_con(&dashioDevice, TCP_PORT, true);

void setup() {
    Serial.begin(115200);
    delay(1000);

    dashioDevice.setup(WiFi.macAddress(), DEVICE_NAME); // Get unique deviceID
    Serial.print(F("Device ID: "));
    Serial.println(dashioDevice.deviceID);

    soft_AP.attachConnection(&tcp_con);

    if (!soft_AP.begin(SOFT_AP_PWD)) {
        Serial.println(F("Failed to start soft AP"));
    }
}

void loop() {
    soft_AP.run();
}

The DashioSoftAP class behaves in a similar manner to the DashioWiFi class. You simply attach a TCP connection to it and it will manage the connection to allow the DashIO app to connect to it.

This device is discoverable by the DashIO app. However, you will need to connect you phone or tablet WiFi to the SoftAP WiFi SSID which is called "DashIO_Provision". You will then be able to discover your IoT device with the normal TCP discovery functionality within the DashIO app (Devices/Find New Devices/TCP Discovery). After you have provisioned your device, connect your phone or tablet back to you normal WiFi.

For referency only, the SoftAP IP address is: 192.168.68.100 and uses port 55892 for discovery only on the DashIO app. This address and port is independent of the address and port for the TCP connection attached to the SoftAP.

Take a look in the examples for DashIO_ESP8266_softAP, which incorporates full provisioning of WiFi, TCP and MQTT connections. A push button is used to switch to the SoftAP to enable provisioning. After the phone or tablet disconnects from the SoftAP, the IoT device switches back to the WiFi that you have provisioned.

Jump In and Build Your Own IoT Device

When you are ready to create your own IoT device, the following links will provide you with more details about what you need to know.

Devices & Connections

https://dashio.io/dashio-arduino-devices/

Messaging for All Controls

https://dashio.io/dashio-arduino-messaging/

Configuration for All Controls

https://dashio.io/dashio-arduino-config/