Arduino Iot Cloud API testing

Hi Im currently using portenta H7 and have a few devices connected with Things. I want to use the API to have an interface of my own, building an analytics dashboard. Im using Insomnia to GET and POST curl requests.
using this for the POST, I get the access token.

curl --request POST \
  --url 'https://api2.arduino.cc/iot/v1/clients/token' \
  --header 'content-type: application/x-www-form-urlencoded' \
  --header 'X-Organization: org_id' \
  --data 'grant_type=client_credentials' \
  --data 'client_id=YOUR_CLIENT_ID' \
  --data 'client_secret=YOUR_SECRET_ID' \
  --data 'audience=https://api2.arduino.cc/iot'

but when I try to GET the things using this

curl --request GET \
  --url https://api2.arduino.cc/iot/v2/things/{YOUR_THING_ID}/properties \
  --header 'Authorization: Bearer YOUR_TOKEN'

it gives me this error:

Can someone please help, what could be the issue? I know it will be a minor one, but cannot figure out after spending so many hours, trying it in Python too.

Hello @fzehra1,

Did you get the token correctly?

If yes, could you please give me your Arduino account username that you are using?

Thanks.

Hi @s-torneo i think so, yes.

my arduino account user is fzehra1@ualberta.ca

I see that the thing 6e171f42-ed71-44a8-8425-0bff2724855d belongs to the account user fzehra1@ualberta.ca, so probably the problem is the token that you generated or how you use it in the API that gets the thing's properties.

When you try to get the thing's properties by using this API curl --request GET \ --url https://api2.arduino.cc/iot/v2/things/{YOUR_THING_ID}/properties \ --header 'Authorization: Bearer YOUR_TOKEN', did you let the word Bearer and replace only YOUR_TOKEN?

Yes. here is the code:

curl --request GET \
  --url https://api2.arduino.cc/iot/v2/things/6e171f42-ed71-44a8-8425-0bff2724855d/properties \
  --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJodHRwczovL2FwaTIuYXJkdWluby5jYy9pb3QiLCJhenAiOiI2TjBoeUZoRnRESTBONlI1Z0JOYUdXZkNocm83N1ZmNSIsImV4cCI6MTcyMDEzODU1NywiZ3R5IjoiY2xpZW50LWNyZWRlbnRpYWxzIiwiaHR0cDovL2FyZHVpbm8uY2MvY2xpZW50X2lkIjoiRm9yX1B5dGhvbiIsImh0dHA6Ly9hcmR1aW5vLmNjL2lkIjoiNjUzNzcxZDctZDNhMS00M2E1LWJhNDEtMjc3YmMwZTBhZWQ0IiwiaHR0cDovL2FyZHVpbm8uY2MvcmF0ZWxpbWl0IjoxMCwiaHR0cDovL2FyZHVpbm8uY2MvdXNlcm5hbWUiOiJmemVocmExIiwiaWF0IjoxNzIwMTM4MjU3LCJzdWIiOiI2TjBoeUZoRnRESTBONlI1Z0JOYUdXZkNocm83N1ZmNUBjbGllbnRzIn0.yNnzO4oISQhIJ7GXTFWu64OZ5z8MAGT50rmvHkRmcIg'

I still get errors.

I tried it in Python though, and when i get token and list things of the specific space, it gives me the results:

import iot_api_client as iot
from iot_api_client.rest import ApiException
from iot_api_client.configuration import Configuration

# Configure the API client
client_config = Configuration(host="https://api2.arduino.cc/iot")
client_config.access_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJodHRwczovL2FwaTIuYXJkdWluby5jYy9pb3QiLCJhenAiOiI2TjBoeUZoRnRESTBONlI1Z0JOYUdXZkNocm83N1ZmNSIsImV4cCI6MTcyMDEzNzUwOCwiZ3R5IjoiY2xpZW50LWNyZWRlbnRpYWxzIiwiaHR0cDovL2FyZHVpbm8uY2MvY2xpZW50X2lkIjoiRm9yX1B5dGhvbiIsImh0dHA6Ly9hcmR1aW5vLmNjL2lkIjoiNjUzNzcxZDctZDNhMS00M2E1LWJhNDEtMjc3YmMwZTBhZWQ0IiwiaHR0cDovL2FyZHVpbm8uY2MvcmF0ZWxpbWl0IjoxMCwiaHR0cDovL2FyZHVpbm8uY2MvdXNlcm5hbWUiOiJmemVocmExIiwiaWF0IjoxNzIwMTM3MjA4LCJzdWIiOiI2TjBoeUZoRnRESTBONlI1Z0JOYUdXZkNocm83N1ZmNUBjbGllbnRzIn0.Xr_-VfAULkU1YwZ9JWj5h7Avp4n7ynzTTCkQMGy0aKA'
# Create an instance of the API client
client = iot.ApiClient(client_config)

# Set the organization ID as a header
org_id = "orgID"
client.set_default_header("X-Organization", org_id)

# As an example, interact with the devices API
devices_api = iot.DevicesV2Api(client)

try:
    devices_list = devices_api.devices_v2_list()

    # Assuming devices_list is a list of devices
    for device in devices_list:
        print(f"Device ({device.id}): {device.name}")  # Adjust property names accordingly

except ApiException as e:
    print(f"Exception when calling DevicesV2Api: {e}")

but when i try to get properties of things with the code in python below, it gives me errors.

from oauthlib.oauth2 import BackendApplicationClient
from requests_oauthlib import OAuth2Session

import iot_api_client as iot
from iot_api_client.rest import ApiException
from iot_api_client.configuration import Configuration
import iot_api_client.apis.tags.things_v2_api as thingApi
import iot_api_client.apis.tags.properties_v2_api as propertiesApi
import iot_api_client.apis.tags.series_v2_api as seriesApi

import csv
from time import sleep

HOST = "https://api2.arduino.cc/iot"
TOKEN_URL = "https://api2.arduino.cc/iot/v1/clients/token"

client_id="ID" # get a valid one from your Arduino account
client_secret="secret" # get a valid one from your Arduino account
org_id="orgID"
extract_from="2024-06-03T00:00:00Z"
extract_to="2024-06-06T00:00:00Z"
filename="dump.csv"

def get_token():
    oauth_client = BackendApplicationClient(client_id=client_id)
    oauth = OAuth2Session(client=oauth_client)
    token = oauth.fetch_token(
        token_url=TOKEN_URL,
        client_id=client_id,
        client_secret=client_secret,
        include_client_id=True,
        audience=HOST,
        headers={"X-Organization":org_id}
    )
    return token


def init_client(token):
    client_config = Configuration(HOST)
    client_config.access_token = token.get("access_token")
    if org_id!="":
        client = iot.ApiClient(client_config,header_name="X-Organization",header_value=org_id)
    else :
        client = iot.ApiClient(client_config)
    return client



def dump_property_data(series_api,thing_name,prop_name,thing_id,prop_id):
    sleep(1)
    print(f"Extracting property {thing_name}.{prop_name}")
    body={
        'resp_version':1,
        'requests': [ {'q': "property."+prop_id,'from':extract_from,'to':extract_to} ]
    }
    timeseries=series_api.series_v2_batch_query_raw(body)  
    
    if timeseries.response.status==200:
        data = timeseries.body['responses']
        for s in data:
            times = s['times']
            values = s['values']
            i=0
            while i<len(times):
                writer.writerow([thing_name,prop_name,times[i],values[i]])
                i=i+1
    else:print(f"Unable to extract data for property {prop_id}")
    

def get_things_and_props():
    token = get_token()
    client = init_client(token)
    things_api = thingApi.ThingsV2Api(client)
    properties_api = propertiesApi.PropertiesV2Api(client)
    series_api = seriesApi.SeriesV2Api(client)
    todolist=[]  #use this to track extractions to do    
    try:
        things = things_api.things_v2_list()
        
        if things.response.status==200:
            for thing in things.body: 
                sleep(5)
                tname=thing["name"]
                print(f"Found thing: {tname}")
                todo={}
                todo["thing_id"]=thing["id"]
                todo["thing_name"]=tname
                properties=properties_api.properties_v2_list(path_params={'id': thing["id"]})  
                for property in properties.body:
                    id = property["id"]
                    name = property["name"]
                    ptype = property["type"]
                    value = property["last_value"]
                    print(f"Property: {name}::{ptype}={value}")
                    if ptype=="FLOAT" or ptype=="INT":
                        todo["prop_id"]=id
                        todo["prop_name"]=name
                        todolist.append(todo.copy())
        else:
            print("IoT API returned status "+things.response.status)
    except ApiException as e:
        print("Exception: {}".format(e))

    while len(todolist)!=0:
        todo = todolist.pop()
        try:
            dump_property_data(series_api,todo["thing_name"],todo["prop_name"],todo["thing_id"],todo["prop_id"])
        except ApiException as e:
            print("Exception: {}".format(e))

#################

with open(filename, 'w', newline='') as outfile:
    writer = csv.writer(outfile)
    writer.writerow(["thing_name","variable","timestamp","value"])
    get_things_and_props()

errors:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[6], line 7
      5 from iot_api_client.rest import ApiException
      6 from iot_api_client.configuration import Configuration
----> 7 import iot_api_client.apis.tags.things_v2_api as thingApi
      8 import iot_api_client.apis.tags.properties_v2_api as propertiesApi
      9 import iot_api_client.apis.tags.series_v2_api as seriesApi

File c:\Users\fzehra1\AppData\Local\anaconda3\Lib\site-packages\iot_api_client\apis\tags\things_v2_api.py:12
      1 # coding: utf-8
      3 """
      4     Arduino IoT Cloud API
      5 
   (...)
      9     Generated by: https://openapi-generator.tech
     10 """
---> 12 from iot_api_client.paths.v2_things_id_clone.put import ThingsV2Clone
     13 from iot_api_client.paths.v2_things.put import ThingsV2Create
     14 from iot_api_client.paths.v2_things_id_sketch.put import ThingsV2CreateSketch

File c:\Users\fzehra1\AppData\Local\anaconda3\Lib\site-packages\iot_api_client\paths\v2_things_id_clone\put.py:54
     50 class RequestHeaderParams(RequestRequiredHeaderParams, RequestOptionalHeaderParams):
     51     pass
---> 54 request_header_x_organization = api_client.HeaderParameter(
...
     58 )
     59 # Path params
     60 IdSchema = schemas.StrSchema

AttributeError: module 'iot_api_client.api_client' has no attribute 'HeaderParameter'
Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...

Im using arduino-iot-client version 1.4.4 for displaying list of things, but its not working to display properties. I tried with latest version as well 2.0.1. but it doesn't work

I feel like, its a library version issue. unfortunately the documentation doesnt help that much, and i try to look for answers in the forum. Is there any documentation for step by step process and requirements with compatible libraries and Python versions?

Also the cURL commands too. Please any help would be appreciated. I am under a deadline for my research project.

Hello @fzehra1,

For references and examples, you can see the Github repo: GitHub - arduino/iot-client-py: Python client for Arduino IoT API.

I started from the example in the readme and then added some calls to get things and properties using the package arduino-iot-client (version 2.0.1) and it works.

Here the code:

from oauthlib.oauth2 import BackendApplicationClient
from requests_oauthlib import OAuth2Session

oauth_client = BackendApplicationClient(client_id=YOUR_CLIENT_ID)
token_url = "https://api2.arduino.cc/iot/v1/clients/token"

oauth = OAuth2Session(client=oauth_client)
token = oauth.fetch_token(
    token_url=token_url,
    client_id=YOUR_CLIENT_ID,
    client_secret=YOUR_CLIENT_SECRET,
    include_client_id=True,
    audience="https://api2.arduino.cc/iot"
)

access_token = token.get("access_token")

import iot_api_client as iot
from iot_api_client.rest import ApiException
from iot_api_client.configuration import Configuration
import iot_api_client.apis.tags.things_v2_api as thingApi
import iot_api_client.apis.tags.properties_v2_api as propertyApi

# configure and instance the API client
client_config = Configuration(host="https://api2.arduino.cc/iot")
client_config.access_token = access_token
client = iot.ApiClient(client_config)

things_api = thingApi.ThingsV2Api(client)
properties_api = propertyApi.PropertiesV2Api(client)

try:
    things = things_api.things_v2_list()
    if things.response.status==200:
        for thing in things.body: 
            print("Thing ("+thing["id"]+"): "+thing["name"])
            try:
                properties = properties_api.properties_v2_list(path_params={'id': thing["id"]})
                if properties.response.status==200:
                    for property in properties.body: 
                        print("Property ("+property["id"]+"): "+property["name"])
            except ApiException as e:
                print("Got an exception: {}".format(e))
except ApiException as e:
    print("Got an exception: {}".format(e))

Let me know if it works also for you, thanks.

Hi s-torneo.

Thank you for your response.

I tried the code. it just prints the access token, doesn't list things or properties:

Hello @fzehra1,

Did you add a print for the access token? Because there is no print for that in my code.

If the code doesn't list anything for things and properties, maybe there is no things for that client. It's very strange, I don't think it is an API problem.

hi,

thank you for your response.
Yes, I added print to make sure it was getting the access token. I passed the organization ID in this line and it gave me the list of things and their properties

client = iot.ApiClient(client_config,header_name="X-Organization", header_value=org_id)

Thank you for your help.

As I am new to Arduino IoT and APIs, I was wondering if you have some resources on how I can get these things data into some Python web frameworks.

The goal of my project is to create an analytics dashboard for the operational efficiency of machines. I am looking into Python for these as it is the language I'm getting more familiar with.

Therefore, I was looking to customize this IoT data in Python and get it displayed on an analytics dashboard.

Where should I look first? I came across Streamlit and Dash by Plotly. Would you recommend these? Or any other sources, please?

Hello @fzehra1,

I am happy that you resolved your problem.

I didn't know the softwares that you mentioned.

Why don't you use the Arduino Dashboards?

Hi @s-torneo
I am using the dashboard currently. however I wanna do some analytics study and get data from API to another platform to use python fo processing data and storage and get the historical analytics or statistics.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.