0

Simple Python API problems
Moderators: adafruit_support_bill, adafruit

Forum rules
If you're posting code, please make sure your code does not include your Adafruit IO Active Key or WiFi network credentials.
Please be positive and constructive with your questions and comments.

Simple Python API problems

by bbulkow on Thu Jan 14, 2021 11:31 pm

Hi! I thought I would give you feedback / ask for help.

Before running this service on my actual device, I thought I'd just try the worlds simplest example, using python and my laptop. My laptop is (essentially) ubuntu 18 with python 3.9.1.

First I read your documentation, here: https://adafruit-io-python-client.readt ... en/latest/

As per instructions, I used pip3 to install the Adafruit_IO library. I don't know what version it is, right? But ubuntu 18 is very well used so I'm sure you've kept it up to date.

The first thing I did was try to figure out the difference between "creating" a datapoint and "sending" a datapoint. I also see I need a feed. I go and create the feeds I want on the website, even though it's unclear whether I want a feed-per-sample (samples have multiple values) or a feed-per-value. Heck I'm just doing the simplest thing, so I create two feeds, as my measurement has fundamentally two values per sample.

In this document, one sends a datapoint to a feed like so:

Code: Select all | TOGGLE FULL SIZE
# Import library and create instance of REST client.
from Adafruit_IO import Client
aio = Client('YOUR ADAFRUIT USER', 'YOUR ADAFRUIT IO KEY')

# Send the value 100 to a feed called 'Foo'.
aio.send('Foo', 100)

# Retrieve the most recent value from the feed 'Foo'.
# Access the value by reading the `value` property on the returned Data object.
# Note that all values retrieved from IO are strings so you might need to convert
# them to an int or numeric type if you expect a number.
data = aio.receive('Foo')
print('Received value: {0}'.format(data.value))

Using this, almost exactly, gives " Adafruit IO request failed: 404 Not Found - not found - that is an invalid URL, please check the API documentation at https://io.adafruit.com/api/docs to make sure your URL is correct "

Oh great, that's wonderful, because I NEVER CREATED A URL nor do I have any way to figure out what my url is. I carefully check my key and my username against what is on the website and they are EXACTLY THE SAME I GUARENTEE. I check this multiple times. I check the feed names I've created, I check them over and over. I read the forums on this, everyone has the names of their topics wrong. I check this too.

I look at the "data object" and "data helper object". Instead of telling me the fields in the object, I see a slightly different metaphore:

Code: Select all | TOGGLE FULL SIZE
# Import library and create instance of REST client.
from Adafruit_IO import Client
aio = Client('YOUR ADAFRUIT IO USERNAME', 'YOUR ADAFRUIT IO KEY')

# Add the value 98.6 to the feed 'Temperature'.
test = aio.feeds('test')
aio.send_data(test.key, 98.6)


That's interesting. Send to the name of the feed, and send data to the key of the feed? Great.

But getting 'feeds' gives me the same basic error:

request error: couldnt get the upload feed, aborting Adafruit IO request failed: 404 Not Found - not found - that is an invalid URL, please check the API documentation at https://io.adafruit.com/api/docs to make sure your URL is correct

Which I can't do because I have no idea what the URL is.

The examples are a little more peculiar. They generally tell you to programmatically create new feeds. This is absolutely not what anyone would do - you don't have IOT devices creating feeds willy nilly - so I don't try this.

Here are my suggestions:

  • Document your API in the same style as most of the Python documentation, where every (external) field in a class or object has a description. What are all the fields in 'feed' ? Data? The documentation is quite impoverished, with 'create_data' creating data. Does that send data? Do I create then send? What's the benefit of creating a data object, compared to sending a value?
  • It appears that I might be using the MQTT endpoint, I might be using the rest endpoint. How would I know which is which? That might help me debug this URL problem.
  • It would seem this kind of error of "invalid URL" is common. Can you discuss that in a troubleshooting section? What should I do if I get an invalid URL? Can I print the URL somehow? Is it on the "Client" object?
  • One possibility is the PIP packages might be out of date. How would I know the version, and have you tested against them? What is the current version?
  • In all the sensor systems I know of, I deal with time one of three ways. How about an example of each of the three? I can't figure out in this API how to send the time, but I think it's in the REST API.
    • The sensor knows the time. It records the time, and when it transmits the data, it transmits the time the value was taken - useful for power-constrainted devices.
    • The sensor doesn't know the time, but it has something like a reasonable network, and can send the values immediately after recording them so doesn't need the time - although a sensor with a good network does usually have the time..
    • The sensor has some kind of battery, so it can sync a value and all measurements apply as a delta from that variable. In this case, when it submits samples, it wants to submit the time, and it probably wants the receiver to not duplicate insert.
  • Please discuss feeds. Are feeds to contain a "reading" (set of values taken a single time), or for a single value from a single sensor? Can it be done both ways, and can I create dashboards in both cases, and if so how? In the case of the latter, I almost certainly want to batch my data recording, because I want the values to have the same timestamp (they are the same sample), and because I want to create as little load as possible on your servers. Are there pluses and minuses for each?

Thanks.

PS. I am using the forum instead of discord because this seems like such a simple issue that more people than myself should be running into it.

bbulkow
 
Posts: 8
Joined: Sat Oct 19, 2013 8:18 pm

Re: Simple Python API problems

by brubell on Fri Jan 15, 2021 11:14 am

Hi bbulkow,

I'll try to answer as much as I can, some of this should warrant us breaking this thread out into the API docs/Python lib repositories...

In this document, one sends a datapoint to a feed like so:

Where is this document - could you paste a URL? The example lacks the feed creation/assignment step.


But getting 'feeds' gives me the same basic error:

request error: couldnt get the upload feed, aborting Adafruit IO request failed: 404 Not Found - not found - that is an invalid URL, please check the API documentation at https://io.adafruit.com/api/docs to make sure your URL is correct

Which I can't do because I have no idea what the URL is.

Which example are you using?

The examples are a little more peculiar. They generally tell you to programmatically create new feeds. This is absolutely not what anyone would do - you don't have IOT devices creating feeds willy nilly - so I don't try this.


The examples on the repository follow the the Adafruit IO Basics Series (https://learn.adafruit.com/series/adafruit-io-basics) of guides.

---

It appears that I might be using the MQTT endpoint, I might be using the rest endpoint. How would I know which is which? That might help me debug this URL problem.

Examples which call MQTTClient use the MQTT endpoint:

Code: Select all | TOGGLE FULL SIZE
# Import Adafruit IO MQTT client.
from Adafruit_IO import MQTTClient

vs examples which use the HTTP endpoint call Client
Code: Select all | TOGGLE FULL SIZE
from Adafruit_IO import Client
aio = Client('YOUR ADAFRUIT IO USERNAME', 'YOUR ADAFRUIT IO KEY')


It would seem this kind of error of "invalid URL" is common. Can you discuss that in a troubleshooting section? What should I do if I get an invalid URL? Can I print the URL somehow? Is it on the "Client" object?

I'm not sure what you're trying to do, could you please post the full code you're using to get this error and I'll take a look at it.

One possibility is the PIP packages might be out of date. How would I know the version, and have you tested against them? What is the current version?

Call the following from your command line:
pip3 freeze | grep adafruit-io

Latest version is listed on the pip page: https://pypi.org/project/adafruit-io/ and on the github repo for adafruit io python

In all the sensor systems I know of, I deal with time one of three ways. How about an example of each of the three? I can't figure out in this API how to send the time, but I think it's in the REST API.

You can send a created_at string when you create data (https://io.adafruit.com/api/docs/#create-data). Alternatively, if one is not created, a timestamp will be assigned using the server's time.

Please discuss feeds. Are feeds to contain a "reading" (set of values taken a single time), or for a single value from a single sensor?

Feeds contain one value, https://io.adafruit.com/api/docs/#create-data

Can it be done both ways, and can I create dashboards in both cases, and if so how? In the case of the latter, I almost certainly want to batch my data recording, because I want the values to have the same timestamp (they are the same sample), and because I want to create as little load as possible on your servers.

You'll want to make a group to publish to multiple feeds at the same time.
https://io.adafruit.com/api/docs/#groups

brubell
 
Posts: 1381
Joined: Fri Jul 17, 2015 10:33 pm

Please be positive and constructive with your questions and comments.