# Datacake - WiFi, using MQTT ###### tags: `TA Stuff ESP32` `PyCom` `Heltec` `ESP32` In this tutorial, we will take a look at how to connect our devices to WiFi and display our sensor data on Datacake. The tutorial is divided in to two sections. The first section shows how you can connect to WiFi using a `heltec`, `Fipy` or a generic `ESP32` to WiFi. The second part shows how to create a device on Datacake, how to create fields, and where to find the MQTT `topic` and account `Token`. ## WiFi part The WiFi implementation in micropython may differ depending on what micropython firmware you have. In this course, we are using three different micropython firmwares: One for Heltec and Pycom devices, one for generic ESP32 devices and one for Arduino RP2040 devices. We assume that you have flashed your device with micropython at this point. If not, then please reiterate to Part 1 in the [Roadmap](https://discord.com/channels/720703210884563065/854718999296081981/989217904614584430) and firmware update your device. ### Heltec and Pycom devices The objective is to connect to WiFi and send sensor data using MQTT. This is how we do that on Heltec and Pycom devices. We recommend you to start a `new project` and add only three files in it, `config.py`, `boot.py` and `main.py`. In the example below, the project structure looks like the following: ![](https://i.imgur.com/qt6CgTz.png) In `boot.py`, we set up the WiFi connection. This is how it can be done: ```python= import network import time import config # setup as a station wlan = network.WLAN(mode=network.WLAN.STA) wlan.connect(config.WIFI_SSID, auth=(network.WLAN.WPA2, config.WIFI_PASS)) while not wlan.isconnected(): time.sleep_ms(50) print(wlan.ifconfig()) ``` Now, we need to edit `config.py`, since our `boot.py` is expecting `config.py` to have the `WIFI_SSID` and `WIFI_PASS`. This is how `config.py` should look like: ```python= # WiFi credentials WIFI_SSID = 'WIFI_SSID' WIFI_PASS = 'WIFI_PASS' # Datacake credentials SERIAL_NUMBER = 'DEVICE_SERIAL_NUMBER' MQTT_BROKER = 'mqtt.datacake.co' TOKEN = 'ACCOUNT_TOKEN' PORT = 1883 TOPIC = 'TOPIC_TO_PUBLISH_TO' ``` Make sure that the `WIFI_SSID` is a `2.4GHz` network, otherwise our device won't be able to connect. Given that `main.py` is empty, e.g. no code inside it, we should see an output similar to the following: ![](https://i.imgur.com/sIGlsk0.png) We know if the connection was sucessful by looking at the IP-address tuple (`('192.168.43.32', '255.255.255.0', '192.168.43.1', '192.168.43.1')`) Now that we have our WiFi-connection sorted out, we need to import an `MQTT library` and use it to publish sensor data to `Datacake`. Create a file inside your project and call it `mqtt.py` and copy the code from [pycom github repository](https://raw.githubusercontent.com/pycom/pycom-libraries/master/lib/mqtt/mqtt.py) and paste it inside `mqtt.py`. The next step is to use the library and actually send sensor data. Copy the following code snippet and add it in `main.py`: ```python= from mqtt import MQTTClient import time import ujson import machine import config def sub_cb(topic, msg): print(msg) # MQTT Setup client = MQTTClient(config.SERIAL_NUMBER, config.MQTT_BROKER, user=config.TOKEN, password=config.TOKEN, port=config.PORT) client.set_callback(sub_cb) client.connect() print('connected to MQTT broker') # The MQTT topic that we publish data to my_topic = config.TOPIC # Dummy data temperature = 23 while True: # Here, we publish the dummy data to the broker, under topic client.publish(topic=my_topic, msg=str(temperature)) client.check_msg() print("Send data to MQTT broker, sleeping for 2 minutes...") time.sleep(120) # Wait 2 minutes (120 seconds) ``` Now that we have set up our `config.py`, `boot.py` and `main.py`, we can run the code and expect the following output: ![](https://i.imgur.com/y2uzNpX.png) The error originates from the `connect` function in `mqtt.py`, and it makes sense. We didn't fill in the Datacake credentials yet. More on that under [Datacake part](#Datacake-part) ### Generic ESP32 The objective is to connect to WiFi and send sensor data using MQTT. This is how we do that on Heltec and Pycom devices. We recommend you to start a `new project` and add only three files in it, `config.py`, `boot.py` and `main.py`. In the example below, the project structure looks like the following: ![](https://i.imgur.com/qt6CgTz.png) In `boot.py`, we set up the WiFi connection. This is how it can be done: ```python= import network import config sta_if = network.WLAN(network.STA_IF) if not sta_if.isconnected(): print('connecting to network...') sta_if.active(True) sta_if.connect(config.WIFI_SSID, config.WIFI_PASS) while not sta_if.isconnected(): pass print('network config:', sta_if.ifconfig()) ``` Now, we need to edit `config.py`, since our `boot.py` is expecting `config.py` to have the `WIFI_SSID` and `WIFI_PASS`. This is how `config.py` should look like: ```python= # WiFi credentials WIFI_SSID = 'WIFI_SSID' WIFI_PASS = 'WIFI_PASS' # Datacake credentials SERIAL_NUMBER = 'DEVICE_SERIAL_NUMBER' MQTT_BROKER = 'mqtt.datacake.co' TOKEN = 'ACCOUNT_TOKEN' PORT = 1883 TOPIC = 'TOPIC_TO_PUBLISH_TO' ``` Make sure that the `WIFI_SSID` is a `2.4GHz` network, otherwise our device won't be able to connect. Given that `main.py` is empty, e.g. no code inside it, we should see an output similar to the following: ![](https://i.imgur.com/6f27VbP.png) We know if the connection was sucessful by looking at the IP-address tuple,`('192.168.43.174', '255.255.255.0', '192.168.43.1', '192.168.43.1')`. Now that we have our WiFi-connection sorted out, we need to import an `MQTT library` and use it to publish sensor data to `Datacake`. Create a file inside your project and call it `mqtt.py` and copy the code from [ESP-MicroPython](https://raw.githubusercontent.com/RuiSantosdotme/ESP-MicroPython/master/code/MQTT/umqttsimple.py) and paste it inside `mqtt.py`. The next step is to use the library and actually send sensor data. Copy the following code snippet and add it in `main.py`: ```python= from mqtt import MQTTClient import time import ujson import machine import config def sub_cb(topic, msg): print(msg) # MQTT Setup client = MQTTClient(config.SERIAL_NUMBER, config.MQTT_BROKER, user=config.TOKEN, password=config.TOKEN, port=config.PORT) client.set_callback(sub_cb) client.connect() print('connected to MQTT broker') # The MQTT topic that we publish data to my_topic = config.TOPIC # Dummy data temperature = 23 while True: # Here, we publish the dummy data to the broker, under topic client.publish(topic=my_topic, msg=str(temperature)) client.check_msg() print("Send data to MQTT broker, sleeping for 2 minutes...") time.sleep(120) # Wait 2 minutes (120 seconds) ``` Now that we have set up our `config.py`, `boot.py` and `main.py`, we can run the code and expect the following output: ![](https://i.imgur.com/J2Oh154.png) The error originates from the `connect` function in `mqtt.py`, and it makes sense. We didn't fill in the Datacake credentials yet. More on that in the following section. ## Datacake part At this point, we have gotten our devices to connect to WiFi and we have also implemented a code that utilizes MQTT to send data. Datacake will be the end-point and we need to start by creating an account on [Datacake](https://app.datacake.de/login). ### Create a device Once you have created an account, navigate to `devices` and add a new device. ![](https://i.imgur.com/lvEvNip.png) A modal will pop up, we select `API` hit `Next`. ![image alt](https://i.imgur.com/fUhBiYL.png) Then, we select `New product`, give our device a and hit `Next`. ![image alt](https://i.imgur.com/sSMrxj7.png) Then, we fill in our custom `Serial Number`, and give our device a `Name`, and hit `Next`. :::warning It is important that you fill in your own `Serial Number`. It can be anything, just make sure to not leave it empty, else it will cause connection problems later on. ::: ![](https://i.imgur.com/JfAyPDd.png) Finally, select a plan (The Free plan) and hit `Add 1 device`. Now, you should be redirected to the page of the device you just created. ![](https://i.imgur.com/bPGXCIv.png) ### Configure the device The device we just created is a representation of our physical device (Heltec board, Fipy or the Generic esp32). Since our physical devices will send sensor data, we need to define a set of fields accordingly. For example, our code in `main.py` sends dummy temperature data, so that means that our device on Datacake should have a temperature field. This is how it is done. Navigate to your device and select `Configuration`. Scroll then down until you see `Fields`. ![](https://i.imgur.com/hqmRkzK.png) Define the `Type` of field, give it a `Name`, a `Unit`, and hit `Add Field`. :::info Note that the name is also the identifier of that field, but in capital case. ::: ![](https://i.imgur.com/TfPd5OJ.png) Once the field is added, it should be listed under `Fields`. ![](https://i.imgur.com/xU7jv0j.png) Now, to update that field, we need to know that what `Topic` to publish to. We find that information under `Integrations` -> `MQTT` -> `Configure`. A modal will pop up with information about the `Topic`. ![](https://i.imgur.com/9MiwaR3.png) The selected string is the `Topic` that we can publish to. Notice the `[FIELD_NAME]` at the end of the string. In our case, the `[FIELD_NAME]` is `TEMPERATURE`. Let's copy that string and paste it in `config.py`. This is how `config.py` should look like now (we changed line 10): ```python= # WiFi credentials WIFI_SSID = 'WIFI_SSID' WIFI_PASS = 'WIFI_PASS' # Datacake credentials SERIAL_NUMBER = 'DEVICE_SERIAL_NUMBER' MQTT_BROKER = 'mqtt.datacake.co' TOKEN = 'ACCOUNT_TOKEN' PORT = 1883 TOPIC = 'dtck-pub/samplename/5ef47349-2606-47a1-9719-26edfa729cf7/TEMPERATURE' ``` Now, we need to fill in `SERIAL_NUMBER` and `TOKEN`. We can get the `SERIAL_NUMBER` from the device-page. ![](https://i.imgur.com/2kXoe1m.png) and the `TOKEN` from our profile -> `Edit Profile` -> `API` -> `Show`. Copy the `API Token` and paste it in `config.py`. ![](https://i.imgur.com/tpLIaao.png) ![](https://i.imgur.com/6fZhR7A.png) ```python= # WiFi credentials WIFI_SSID = 'orion' WIFI_PASS = '12345678' # Datacake credentials SERIAL_NUMBER = '1234david1234' MQTT_BROKER = 'mqtt.datacake.co' TOKEN = '08179e9ec7822251434a834ff3ce8c50216a3e01' PORT = 1883 TOPIC = 'dtck-pub/samplename/5ef47349-2606-47a1-9719-26edfa729cf7/TEMPERATURE' ``` Once you've edited `config.py`, save all files in Atom and upload the code. When the device boots, it will connect to WiFi, then to the MQTT broker and send the temperature value. Notice how the temperature field in datacake updates. ![](https://i.imgur.com/7WqwtY1.png) And in the terminal in Atom, we can see that the device connects to WiFi, connects to the MQTT broker, sends data and goes for sleep for 2 minutes. ![](https://i.imgur.com/KuRPCnj.png) ### Create a simple dashboard Now that we can send data to Datacake, let's build a simple dashboard. To do that, navigate to your device and select `Dashboard`. ![](https://i.imgur.com/3fYm57C.png) Click on the toggle button to the far right and you will see some additional options. ![](https://i.imgur.com/DrmVRfS.png) Click on `Add Widget` and select `Value`. ![](https://i.imgur.com/LRnWUQo.png) Give it a name and select `Data` in the middle menu. Select the `Field` from which you want your Widget to fetch data from, in our case it is the Temperature field. ![](https://i.imgur.com/KIDdBj9.png) Finally, Click on `Save` and make sure to click on the toggle button to the far right again to save your dashboard. ![](https://i.imgur.com/R3uiN1x.png) You can do a lot of things on Datacake. You can customize your widgets, set up rules to notify you when certain sensors exceeds given threshold etc.. Feel free to explore the platform. Good luck! :blush: