---
# System prepended metadata

title: TTS-Ubidots
tags: [Pycom, ESP32, TA Stuff 2021]

---

###### tags: `TA Stuff 2021` `Pycom` `ESP32`

# TTS-Ubidots
In the previous [TTS tutorial](https://hackmd.io/@lnu-iot/rkWOVue6_), we left things off at sending payload/data. In this tutorial, you will learn how to visualize the data you send to TTS. 

### Table of Contents
[TOC]

## Create a Ubidots STEM Account

First, you need to create your Ubidots stem account [here](https://ubidots.com/stem/). Once you're registered, you will be redirected to the following page:

![](https://i.imgur.com/gxc46Zz.png)

## Create a Ubidots Data Plugin
Navigate to `Devices` and select `plugins`. 

:::warning
Ubidots STEM accounts can only have one data plugin, so if you already have one configured for e.g. Helium, then remove it and create a new one.
:::

To create a new Data Plugin, select the `Create Data Plugin` button and choose `The Things Stack`. 

![](https://i.imgur.com/FBrOUlY.png)

:::info
There are two plugins available for TTS. The one we use in this tutorial is the one for receiving and decoding data from LoRaWAN devices. 
:::

Confirm your choice by pressing the turquoise right-arrow and select the `Default token` as your `Ubidots Token` from the drop-down menu. 

![](https://i.imgur.com/UUmDmIQ.png)

Now, finish the configuration by giving your plugin a name and description (in the next step). This is what you should see. 

![](https://i.imgur.com/O7WqE7r.png)

Give your plugin a few seconds to fire up and refresh the page. Now, you should see the pluging running. 



## Create a TTS webhook

Now that you have created a Ubidots Data Plugin, revisit your TTS application and navigate to `Integrations/Webhooks`. Select the `Add webhook` button located in the top-right corner and choose `Ubidots`. 

Give your webhook an appropriate name (can be anything). 

Then, navigate to `Devices->Plugins` in Ubidots and select your TTS plugin. Once there, you can find your `Plugin ID` in the page URL. 

![](https://i.imgur.com/UJcAkCx.png)

The `Plugin ID` in the example image above is `60ef11c04763e72fe7e16090`. Add this as `Plugin ID` in TTS.


Finally, enter your `Ubidots token` in TTS, which can be found in `My Profile->API Credentials` or [here](https://stem.ubidots.com/accounts/me/apiCredentials).

![](https://i.imgur.com/fQ0rd08.png)

Now, create the webhook. It should now be listed under `Integrations->Webhooks` in your TTS console. Select it, and scroll down to `Enabled messages`.

![](https://i.imgur.com/hc8AjIc.png)

Replace the default `Uplink message` url with the one provided for you in the Ubidots Data Plugin you created earlier. You can find it by nagivating to `Devices->Plugins->YourPlugin->Decoder` and copying `HTTPs Endpoint URL` of the plugin. You dont need the whole URL, only the part from `/api`, so your `Uplink message` url should look something like:  

`/api/web-hook/kxSCgvP93BUJXL25gUQCErvvJrA=`


![](https://i.imgur.com/yz37uWh.png)

In the image above, you can see our API-url in place. When you're done, press `Save changes`. 


## Simulate Uplinks

Now, it is time to see how uplink messages to TTS (from your device) are forwarded to Ubidots. In your TTS-console, navigate to `Applications->End devices->your device -> Messaging`. 


![](https://i.imgur.com/iRBWIyO.png)

Enter `02 03` in the `Payload` field and press `Simulate uplink`. You should see a success-message indicating a successful simulation. Now, go to your Ubidots account and navigate to `Devices`. Woop woop, a new device!

![](https://i.imgur.com/oPSt6jp.png)

And if you select it, you should see something like this: 

![](https://i.imgur.com/mNUmPN4.png)

This simply means that your Ubidots integration in TTS works! However, you probably have more interesting variables to visualize than `F Port`, `Frame Counter`, etc.. You will learn how to decode your payload in the next section. 

## Ubidots decoder

In the [TTS](https://hackmd.io/5RbTAtCxTPu-hRi3k4p3dQ) tutorial, we left things off at transmitting data to TTS. Consider the code snippet below:

```python=
while True:
    temperature = -23.3    # Your sensor value
    humidity = 40          # Your sensor value

    # > = big-endian
    # h = Temperature (2 bytes, 16 bits, signed) Range: −32,768 to 32,767
    # B = Humidity (1 byte, 8 bits, unsigned) Range: 0 to 255
    payload = struct.pack('>hB', int(temperature * 100), int(humidity))
    s.send(payload)

    print('sent temperature:', temperature)
    print('sent humidity:', humidity)

    time.sleep(900)     # wait 900 seconds (15 minutes) before sending again
```

When these two values are sent to TTS, the `MAC payload` looks like this:


![](https://i.imgur.com/CziaVAQ.png)

The first two bytes (`F6 E6`) are the temperature bytes and the third byte (`28`) is the humidity byte. Here is why we chose one byte for humidity and two bytes for temperature:


The humidity value can span between 0 and 100 % and an appropriate datatype to use here is an `unsigned byte` (0-127). 

As for the temperature, it can span (depending on the type of your sensor) from -60°C to 80°C. So we need a signed type. A signed type means that its values can be both positive and negative. We could use a `signed byte`, and that would probably suffice, but then we would only get the temperature as integer values, and not as floats. 23.3°C looks nicer than 23°C. So we use two bytes for temperature. Now, we can multiply our temperature by 100 before packing & sending it and divide it by 100 when unpacking/decoding our payload. 

:::info
Notice that we're already multiplying our temperature by 100 during the packing in row 8 in the code-snippet above.
:::

So here is how you decode your payload:

In ubidots, navigate to `Devices->Plugins->Your plugin->Decoder` and replace the default `Decoding Function` with the following code-snippet and press `SAVE & MAKE LIVE`:

```javascript=
function format_payload(args){
  var ubidots_payload = {};
  // Log received data for debugging purposes:
  // console.log(JSON.stringify(args));
  // Get RSSI and SNR variables using gateways data:
  var gateways = args['uplink_message']['rx_metadata'];
  for (const i in gateways) {
    // Get gateway EUI and name
    var gw = gateways[i];
    var gw_eui = gw['gateway_ids']['eui'];
    var gw_id = gw['gateway_ids']['gateway_id'];
    // Build RSSI and SNR variables
    ubidots_payload['rssi-' + gw_id] = {
      "value": gw['rssi'],
      "context": {
        "channel_index": gw['channel_index'],
        "channel_rssi": gw['channel_rssi'],
        "gw_eui": gw_eui,
        "gw_id": gw_id,
        "uplink_token": gw['uplink_token']
      }
    }
    ubidots_payload['snr-' + gw_id] = gw['snr'];

  }

  // Get Fcnt and Port variables:
  ubidots_payload['f_cnt'] = args['uplink_message']['f_cnt'];
  ubidots_payload['f_port'] = args['uplink_message']['f_port'];

  // Get uplink's timestamp
  ubidots_payload['timestamp'] = new Date(args['uplink_message']['received_at']).getTime();

  // If you're already decoding in TTS using payload formatters,
  // then uncomment the following line to use "uplink_message.decoded_payload".
  // PROTIP: Make sure the incoming decoded payload is an Ubidots-compatible JSON (See https://ubidots.com/docs/hw/#sending-data)
  // var decoded_payload = args['uplink_message']['decoded_payload'];

  // By default, this plugin uses "uplink_message.frm_payload" and sends it to the decoding function "decodeUplink".
  // For more vendor-specific decoders, check out https://github.com/TheThingsNetwork/lorawan-devices/tree/master/vendor
  let bytes =  Buffer.from(args['uplink_message']['frm_payload'], 'base64');
  var decoded_payload = decodeUplink(bytes)['data'];
  // Merge decoded payload into Ubidots payload
  Object.assign(ubidots_payload, decoded_payload);
  return ubidots_payload
}

function decodeUplink(bytes) {
  var decoded = {};
  decoded.temperature = (bytes[0] << 24 >> 16 | bytes[1]) / 100;
  decoded.humidity = bytes[2];

  return {"data": decoded};
}

module.exports = { format_payload };
```

:::info
Notice the division by 100 in row 50 in the code-snippet above.
:::

To test your new decoder, navigate to `Applications->End devices->Your device->Messaging` and insert `FF E9 28` as your payload and press `Simulate uplink`. Now, if you go back to your device in Ubidots, you should see your temperature & humidity values. Just now, we simulated the uplink but the same would happen if you ran `main.py`. 

![](https://i.imgur.com/2vNBJ58.png)

Now that you have your sensor data available on Ubidots, let's create a dashboard! :D


## Create a Ubidots Dashboard

In Ubidots, navigate to `Data->Dashboards` and press `Add new Dashboard`. Now, it is your task to experiment with the settings to create a dashboard that best fits your needs. 

![](https://i.imgur.com/rlh6ibo.png)

Then, go ahead and click on `Add new Widget` and select the `Thermometer` widget. 

![](https://i.imgur.com/q5iakRS.png)

Now, click on `Add variables` in the `Data` section in your thermometer and set the label to `temperature`. This connects the widget with your `temperature` variable in your Ubidots device. Do the same for your humidity value. Perhaps, use the gauge widget for humidity. Here are the results: 

![](https://i.imgur.com/s4piX8B.png)

<br/>

:::info
**Credit**
Written by David Mozart
:::