Contents

Dash Python Guide

25 May 2023

This guide demonstrates how to make BLE, TCP and MQTT connections to an IoT device, using Python and the DashIO Python library. It also shows how to load user controls (widgets) into your mobile device to monitor and control an IoT device.

Getting Started

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

For the DashIO Python library: https://github.com/dashio-connect/python-dashio

The python library contains a simple example to create a graph of network traffic with a connection_id that is your hostname.

cd Examples
python3 iot_monitor.py -s dash.dashio.io -p 8883 -u user -w password -c`hostname`

The MQTT control and data topics are hostname_data and hostname_control.

Requirements

  • python3.6 and above
  • paho-mqtt
  • pyzmq
  • python-dateutil
  • zeroconf
  • shortuuid

You will need to install the Dash app on your mobile phone or tablet.

If you'd like to connect to your IoT devices through the Dash MQTT broker, setup an account on the dashio.io website.

Install

pip3 install dashio

Or

git clone git@github.com/dashio-connect/python-dashio
cd python-dashio
pip3 install .

Guide

TCP Basics

Lets start with a simple TCP connection.

import dashio

device = dashio.Device("aDeviceType", "aDeviceID", "aDeviceName")
tcp_con = dashio.TCPConnection()
tcp_con.add_device(device)

while True:
    pass

This is about the fewest number of lines of code necessary to get talking to the Dash app. There is a lot happening under the hood to make this work. After the import dashio we create a device with three user devined attributes:

  • "aDeviceType": a common name device_type for all IoT devices using this code which is used for device discovery
  • "aDeviceID": a device_ID to uniquely identify this device, preferably a UUID.
  • "aDeviceName": The name of this device, which can be changed at any time.

We also create a TCP connection and add the newly created device to the connection.

This device is discoverable by the Dash app. You can also discover your IoT device using a third party Bonjour/Zeroconf discovery tool. The mDNS service will be "DashIO.tcp."

Make sure your IoT device is connected to the same TCP network as your mobile device running the Dash app. Now run the Dash app on your mobile device.

In the Dash app, tap the All Devices button, followed by the Find New Device button. Then select the TCP Discovery option to show a list of new IoT devices that are TCP mDNS enabled. Your IoT device should be shown in the list. Select your device and from the next menu select Create Device View. This will create an empty Device View for your new IoT deivce. You can now add controls to the Device View:

Layout Configuration - Creating Controls On The Dash App

Controls and their layout on the Dash app can be easily created on the Dash app. You can then export the controls layout configuration to your IoT device so that any Dash app that subsequently connects to your IoT device can retrieve the layout configuration to show the layout on the Dash app. This allows you to distribute or share your IoT devices to anyone with the Dash app.

Once you have discovered your IoT device in the Dash app and have a Device View available for editing, you can add controls to the Device View:

  • Start Editing: Tap the Edit button (it not already in editing mode).
  • Add Dial Control: Tap the Add Control button and select the Dial control from the list.
  • Edit Controls: Tap the Dial control to select it. The Control Settings Menu button will appear in the middle of the Control. The Control can then be dragged and resized (pinch). Tapping the button allows you to edit the Control settings where you can setup the style, colors and other characteristics of your Control. Make sure the Control_ID is set to the same value that is used in the Dial messages (in this case it should be set to "D01").
  • Quit editing: Tap the Edit button again.

The Dial on the Dash app will now show the random Dial values as they arrive.

The next piece of the puzzle to consider is how your IoT device can receive data from the Dash app. Lets add a Knob and connect it to the Dial.

In the Dash app you will need to add a Knob control onto your Device View, next to your Dial control. Edit the Knob to make sure the Control ID of the Knob matches what you have used in your Knob messages (in this case it should be "KB01"), then quit edit mode.

Continuing with the TCP example, in the Python code we need create the Knob and Dial controls and respond to messages coming in from a Knob control that we just added to the Dash app.

To include the Layout Configuration in your IoT device, simply follow these steps:

  • Design your layout in the Dash app and include all controls and connections that you need in your layout. We have already completed this step for our example by adding the Knob and Dial controls as above.
  • Export the layout: Tap on the Device button, then tap the Export Layout button.
  • Select the provisioning setup that you want (see below for provisioning details) and tap the Export button. The Layout Configuration will be emailed to you.
  • Copy and paste the C64 configuration text from the email into your Python code. Your C64 configuration text may be different to that shown below.
  • Decode the C64 and add the decoded C64 as an attribute to the Device.
# Examples/ex04.py
import dashio
import time

cfg64 = "pVNdr5pAEP0rN/tMjHCrbXnjQ60RxQD1Nmn6wIVVN8IuXZar1vjfOwuLeNWmTfo2OztzZnLmnBPybA+Z339oaLbwbYhOqBTHDCMT"\
"LfxgbnlIQwmjgrNs6kIyni1sSJWYpj7Njj4NcIbjEuoFr7CG8viATL3f11ARc0xF0+TiN5LgFcF7eGuI43QVZxU0fRxoSBBRz7Oe"\
"ZpS9wvcWk81WBLEgDJn9njFUNUtWEshRqLX9KPLncpEt288Jncux6zgrYYVjW3dB0D9oaAfYDssYh+4Ap9Cakjgbsyxj+7Ie3PbL"\
"fFtpyy01tCep2F7gBgB3uBtiQDYnsFz/DGyGnhs0vEajb5GKnCUyT6hgXCBzMBwASaSw0pTjsoRZ+mejpw8/9fSebvTRWUPuVEHM"\
"rWUTeP5EZUaLr000CZZfmshauU0Qek6kOh1PBe5q9fLuurYVTh15XMEzYG8MNw7JL/gxYK0NJylQUOUUFjMMSTNcs8m0l6ZVfinR"\
"b0Ryc285w2Y8xbzl9WVLBH4Kc7bD7f9uQ9OO9jjZqY+/tEQ8pmWtteQI3MtF3mN08nLhsKo1kkmbHR4NbP/ukCUrAagFmc/GVWlH"\
"nQ5KJUDEIs7lxPBnBd1IysGdWl5Nf8FxQspaxIDYHmM5Hd34bEx4KdTC/+UphfHAU7X+SXYhuHHFH512b6tnACkYoaK7q/ILaOMV"\
"8ysUbzSOHrv1X61VUSKkS9C1y6JO/XYULdpoouzijCfScGnNVIhFVQAAheNoe7ImmkiKZteOSqXl9SbAbxCez78B"

config_dict = dashio.decode_cfg64(cfg64)
device = dashio.Device("aDeviceType", "aDeviceID", "aDeviceName", cfg_dict=config_dict)
tcp_con = dashio.TCPConnection()
tcp_con.add_device(device)

aknob: dashio.Knob = device.get_control(dashio.ControlName.KNOB, "aKNB")
first_dial_control: dashio.Dial = device.get_control(dashio.ControlName.DIAL, "FirstDial")

def knob_event_handler(msg):
    aknob.knob_dial_value = float(msg[3])
    first_dial_control.dial_value = float(msg[3])

aknob.add_receive_message_callback(knob_event_handler)

while True:
    time.sleep(1)

We've added the C64 string to cfg64, then decoded it with dashio.decode_cfg64(cfg64). This function returns a dictionary that we can pass into Device so that it can instantiate and add the controls. See the Helper Functions in the Dash Python Library for tools to use the C64 generated by exporting a layout from the Dash app.

Run the Dash app and delete the the device "aDeviceName" that you created in the previous example. Now, when you run the Python code for this example on your IoT device, you will be able use TCP Discovery to find and select your IoT device. This time, once connection is complete, tap the DownLoad Layout button to load the layout design from your IoT device.

When you adjust the Knob on the Dash 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 Dash app.

Layout Configuration - Creating Controls Without Using The Dash App

It is possible to create all controls and their layout from within your IoT device without requiring you to export the C64 configuration text from the Dash app. This is an optional way of creating controls, so feel free to skip this section if you are not interested.

The following example creates a Knob and Dial control:

# Examples/ex01.py
import dashio
import random
import time

device = dashio.Device("aDeviceType", "aDeviceID", "aDeviceName")
tcp_con = dashio.TCPConnection()
tcp_con.add_device(device)
first_dial_control = dashio.Dial("FirstDial")
device.add_control(first_dial_control)

while True:
    first_dial_control.dial_value = random.random() * 100
    time.sleep(5)

After the import we create a device with three attributes. These attributes describe the device to the app and allow you to distinguish one of your devices from another. The next two lines create a TCP connection and then add the device to the connection. The connection will be created with the default setting of port 5000 and will also advertise the service using zeroconf, also known as bonjour. This allows the Dash app to find your device. After that we create a dial add it to the device and then every five seconds send a randomly generated dial value to the Dash app.

Though this device is discoverable by the app it would be nice to have the Dash app automatically setup a new DeviceView and place your control on the new DeviceView. To do that we need to add a few more lines of code:

# Examples/ex02.py
import dashio
import random
import time

device = dashio.Device("aDeviceType", "aDeviceID", "aDeviceName")
tcp_con = dashio.TCPConnection()
tcp_con.add_device(device)
first_dial_control = dashio.Dial("FirstDial", control_position=dashio.ControlPosition(0.24, 0.36, 0.54, 0.26))
device.add_control(first_dial_control)

dv_dial = dashio.DeviceView("aDeviceViewID", "A Dial")
dv_dial.add_control(first_dial_control)
device.add_control(dv_dial)

while True:
    first_dial_control.dial_value = random.random() * 100
    time.sleep(5)

First we altered the instantiation of a Dial by including a control_position. This allows us to place the control at a set location. The added lines instantiated a DeviceView control, which we than added the dial control. Finally we added the DeviceView to the device.

The next piece of the puzzle to consider is how do we get data from the Dash app? Lets add a Knob and connect it to the Dial:

# Examples/ex03.py
import dashio
import time

device = dashio.Device("aDeviceType", "aDeviceID", "aDeviceName")
tcp_con = dashio.TCPConnection()
tcp_con.add_device(device)
first_dial_control = dashio.Dial("FirstDial", control_position=dashio.ControlPosition(0.24, 0.36, 0.54, 0.26))
device.add_control(first_dial_control)

dv = dashio.DeviceView("aDeviceViewID", "A Dial")
dv.add_control(first_dial_control)
device.add_control(dv)

def knob_event_handler(msg):
    first_dial_control.dial_value = float(msg[3])

aknob = dashio.Knob("aKNB", control_position=dashio.ControlPosition(0.24, 0.14, 0.54, 0.26))
aknob.add_receive_message_callback += knob_event_handler
dv.add_control(aknob)
device.add_control(aknob)

while True:
    time.sleep(1)

First we added a function that sets the dial value. Next we added a Knob control and added our new function to be called when it receives data from the Dash app. We also add it to the DeviceView and to the device. Now when the knob in the Dash app is moved the dial is set to the same value.

MQTT Dash Basics

The MQTT connection discussed in this guide is SSL/TLS enabled as the Dash MQTT server only accepts SSL connections.

Add a MQTT Dash connection as follows:

import dashio

device = dashio.Device("aDeviceType", "aDeviceID", "aDeviceName")
dash_con = dashio.DashConnection("yourDashUsername", "yourDashPassword")
dash_con.add_device(device)

while True:
    pass

In the Dash app, 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 dashserver. Your IoT device should be shown in the list for you to select.

Troubleshooting: If you are running the Dash Python library on MacOS, make sure the appropriate certificates are installed or a certificate failure error will occur. To install the certificates, use Finder navigate to your Python directory (e.g. /Applications/Python 3.11) and double click to run "Install Certificates.Command".

BLE Basics

The BLEConnection is only supported on Linux systems and requires bluez and dbus to be installed. It has been developed with the RaspberryPi in mind.

Add a BLE connection as follows:

import dashio
from dashio import bleconnection

device = dashio.Device("aDeviceType", "aDeviceID", "aDeviceName")
ble_con = dashio.BLEConnection()
ble_con.add_device(device)

while True:
    pass

In the Dash app, tap the All Devices button, followed by the Find New Device button. Then select the BLE Scan option to show a list of new IoT devices that are BLE enabled. Your IoT device should be shown in the list for you to select.

Jump In and Build Your Own IoT Device

When you are ready to create your own IoT device, the Dash Python Library will provide you with more details about what you need to know:

https://dashio.io/python-library/