[SOLVED] Post multiple values to a single variable on Ubidots with a Raspberry Pi


#1

I’ve been attempting to post multiple values to a single variable with my Raspberry Pi to no avail. I feel that I’m missing something simple here and would appreciate any help in the right direction.

import json
import requests

token = "my-token"

"""
Get values from variable 
"""
def post_values(device_label, var_label, items):

    base_url = "http://things.ubidots.com/api/v1.6/devices/" + device_label + "/" + var_label + "/values"
    try:
        r = requests.post(base_url + '?token=' + token, data=items)
        return r.json()
    except Exception as e:
        print(e)
        return {'error':'Request failed or timed out'}

"""
Main function
"""
if __name__ == '__main__':
    while True:
        device_label = "rpi-1"
        var_label = "Temperature"
        payload = (("value", 1),("value", 2),("value", 3),("value", 4),("value", 5))
        values = post_values(device_label, var_label, payload)
        print(values)

I have also tried some variations on the payload:
payload = ([{"value", 1},{"value", 2},{"value", 3},{"value", 4},{"value", 5}])
Error: {u’value’: [u’This field is required.’]}

payload = [{"value": 1},{"value": 2},{"value": 3},{"value": 4},{"value": 5}]
Error: need more than 1 value to unpack
{‘error’: ‘Request failed or timed out’}

payload = {"value": 1},{"value": 2},{"value": 3},{"value": 4},{"value": 5}
Error: need more than 1 value to unpack
{‘error’: ‘Request failed or timed out’}


#2

Having changed
r = requests.post(base_url + '?token=' + token, data=items)
to
r = requests.post(base_url + '?token=' + token, json=items)
Now returns
[{u'status_code': 201}, {u'status_code': 201}, {u'status_code': 201}, {u'status_code': 201}, {u'status_code': 201}]

However, when you look at the Ubidots charts, only the last number is printed. This is because the second value overwrites the first, the third overwrites the second and so on because they share the same time stamp. Therefore, I added:
import time
from datetime import datetime
now = datetime.now()
# Ubidots only accepts time in milliseconds.
unix_secs = long(time.mktime(now.timetuple())*1000)
payload = [{“value”: 1, “timestamp”: unix_secs},{“value”: 2, “timestamp”: unix_secs+200},{“value”: 3, “timestamp”: unix_secs+500},{“value”: 4, “timestamp”: unix_secs+600},{“value”: 6, “timestamp”: unix_secs+800}]

The effect of this is most easily seen when you export a CSV file and look at the timestamps (not the human readable datetime).

My final code:
import json
import requests
from datetime import datetime
import time

token = 'my-token'

"""
Get values from variable 
"""
def post_values(device_label, var_label, items):

    base_url = "http://things.ubidots.com/api/v1.6/devices/" + device_label + "/" + var_label + "/values"
    try:
        r = requests.post(base_url + '?token=' + token, json=items)
        return r.json()
    except Exception as e:
        print(e)
        return {'error':'Request failed or timed out'}

"""
Main function
"""
if __name__ == '__main__':
    while True:
        device_label = "rpi-1"
        var_label = "Temperature"
        now = datetime.now()
        unix_secs = long(time.mktime(now.timetuple())*1000)
        payload = [{"value": 1, "timestamp": unix_secs},{"value": 2, "timestamp": unix_secs+200},{"value": 3, "timestamp": unix_secs+500},{"value": 4, "timestamp": unix_secs+600},{"value": 6, "timestamp": unix_secs+800}]
        values = post_values(device_label, var_label, payload)
        print(values)
        time.sleep(1)

#3

Hello @jeremy,

I’m happy to read that you can solve all the inconveniences presented, and thanks for sharing it with the community!

If you have any additional question, let us know!

All the best,
Maria C.