GET & parse returned value from feed?

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.
Locked
User avatar
DJDevon3
 
Posts: 210
Joined: Wed Mar 06, 2019 11:02 am

GET & parse returned value from feed?

Post by DJDevon3 »

I'm unsure how to unparse the response from adafruitio to pull out a value. I'm using a triple stack NRF52840 + 3.5" TFT featherwing + airlift featherwing. The adafruit_esp32spi helper library is specifically for the airlift featherwing (and a few other things) so that's why the format is a little different. I tried using mqtt but couldn't get it to work right. This works 100%.

Code: Select all

import time
import board
import busio
import displayio
from digitalio import DigitalInOut
import adafruit_bmp280
import adafruit_sht31d
import neopixel
from adafruit_esp32spi import adafruit_esp32spi
from adafruit_esp32spi import adafruit_esp32spi_wifimanager
from adafruit_hx8357 import HX8357
displayio.release_displays()

# This sketch should also work for the 2.5" TFT, just change the size.
DISPLAY_WIDTH = 480
DISPLAY_HEIGHT = 320

i2c = board.I2C()
bmp280 = adafruit_bmp280.Adafruit_BMP280_I2C(i2c)
sht31d = adafruit_sht31d.SHT31D(i2c)
bmp280.sea_level_pressure = bmp280.pressure

# Get wifi details and more from a secrets.py file
try:
    from secrets import secrets
except ImportError:
    print("Secrets File Import Error")
    raise

# Initialize SPI bus
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)

# Initilize ESP32 Airlift on SPI bus
esp32_cs = DigitalInOut(board.D13)
esp32_ready = DigitalInOut(board.D11)
esp32_reset = DigitalInOut(board.D12)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2)
wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light)

# Initialize TFT Display on SPI bus
tft_cs = board.D9
tft_dc = board.D10
display_bus = displayio.FourWire(spi, command=tft_dc, chip_select=tft_cs)
display = HX8357(display_bus, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT)

# Connect to WiFi
print("\n===============================")
print("Connecting to WiFi...")
wifi.connect()
print("Connected!\n")

# Your feed key might be different from the feed name (no underscore allowed).
# It's not your IO account key or feed name. It's the individual key for each feed.
# For example, create a feed "temp_test" at AdafruitIO it sets the key "temp-test".
feed_key = "sense-temp"

print("Connecting to AdafruitIO...")
while True:
    try:
        print("Connected!")
        print("===============================\n")
        print("Posting Value...")
        publish = {"value": "{:.1f}".format(bmp280.temperature*1.8+32)}
        post = wifi.post(
            "https://io.adafruit.com/api/v2/"
            + secrets["aio_username"]
            + "/feeds/"
            + feed_key
            + "/data",
            json=publish,
            headers={"X-AIO-KEY": secrets["aio_key"]},
        )
        print(post.json())
        post.close()

        print("\nConfirmation Response...")
        time.sleep(10)
        get = wifi.get(
            "https://io.adafruit.com/api/v2/"
            + secrets["aio_username"]
            + "/feeds/"
            + feed_key
            + "/data?limit=1",
            json=None,
            headers={"X-AIO-KEY": secrets["aio_key"]},
        )
        print(get.json())
        get.close()
        print("\n===============================")
    except (ValueError, RuntimeError) as e:
        print("Failed to get data, retrying\n", e)
        wifi.reset()
        time.sleep(60)
        continue
    response = None
    time.sleep(600)
which returns the following in serial. I have no idea how to pull the value out of the get.json response though. Like how you do parse returned data so you can use it to do other things with? The part of the value I want is coming from the call to print(get.json()) which shows up in serial under Confirmation Response.

Code: Select all

===============================
Connecting to WiFi...
Connected!

Connecting to AdafruitIO...
Connected!
===============================

Value: 89.0
Posting Value...
{'created_at': '2022-06-22T08:01:37Z', 'id': 'obfuscated', 'expiration': '2022-07-22T08:01:37Z', 'created_epoch': 1655884897, 'feed_id': obfuscated, 'value': '89.0', 'feed_key': 'sense-temp'}

Confirmation Response...
[{'created_at': '2022-06-22T08:01:37Z', 'id': 'obfuscated', 'expiration': '2022-07-22T08:01:37Z', 'created_epoch': 1655884897, 'feed_id': obfuscated, 'value': '89.0', 'feed_key': 'sense-temp'}]

===============================

User avatar
eherrada
 
Posts: 161
Joined: Thu Jan 04, 2018 4:59 pm

Re: GET & parse returned value from feed?

Post by eherrada »

Does it not work to do

Code: Select all

var = get.json()

User avatar
DJDevon3
 
Posts: 210
Joined: Wed Mar 06, 2019 11:02 am

Re: GET & parse returned value from feed?

Post by DJDevon3 »

Ah it's not returning an array, it's returning a string. It's just one big string. Might be able to pull the value out with regular expressions but I was hoping for something a bit easier with some kind of json parser. I have no idea how to use json with circuit python.

User avatar
DJDevon3
 
Posts: 210
Joined: Wed Mar 06, 2019 11:02 am

Re: GET & parse returned value from feed?

Post by DJDevon3 »

SWEET! The airlift featherwing learn guide was updated with a ton of much needed examples yesterday. Thank you Brubell!
https://learn.adafruit.com/adafruit-air ... et-connect

User avatar
DJDevon3
 
Posts: 210
Joined: Wed Mar 06, 2019 11:02 am

Re: GET & parse returned value from feed?

Post by DJDevon3 »

OK for all you airlift featherwing owners here's the code that works for posting & returning a single value from your AdafruitIO feed. :) This demo would be greatly appreciated if it was added to the airlift featherwing learn guide. Could have saved me an entire day of trying to get it working.

Airlift Featherwing AdafruitIO POST & GET
First make sure you "import json" at the top of your code.py. The main return string is a json list type. Using json.dumps converts it into 1 long string as resp[0] if you were to print resp[0] you'd see it's a list type. Inside the list is the dictionary but you first must parse out the list with json.dumps to get inside to the dictionary.

Then you must parse it a 2nd time using json.loads which changes it into a dictionary type. Once it's a dictionary type you can easily pull a single value from it. I left the len in there so you can see there are 7 pair items in a feed list by default, separated by semi-colon. Once you have a grasp on how many items there are you can iterate through them in a loop (for long dictionaries) or pull out a single value. Json lists and dictionaries look like arrays but you cannot iterate through them like a traditional array. You must use Circuit Python's json functions.

Finally dictionary['value'} will pull the item named "value" from the dictionary and display its value. For me I'm using temperature values to 1 decimal. Here's the final serial output of the demo:

Code: Select all

===============================
Connecting to WiFi...
Connected!

Connecting to AdafruitIO...
Connected!
===============================

POST Value...
{'created_at': '2022-06-25T10:32:54Z', 'id': '0F2043EX7Q2T0CVHAXBV5TWQJE', 'expiration': '2022-07-25T10:32:54Z', 'created_epoch': 1656153174, 'feed_id': 2267676, 'value': '87.0', 'feed_key': 'sense-temp'}

GET Response...
Number of Items in Dictionary:  7
{'expiration': '2022-07-25T10:32:54Z', 'id': '0F2043EX7Q2T0CVHAXBV5TWQJE', 'feed_key': 'sense-temp', 'created_epoch': 1656153174, 'feed_id': 2267676, 'value': '87.0', 'created_at': '2022-06-25T10:32:54Z'}
Circuit Python Object Type : <class 'dict'>
Return Single Value! : 87.0

Next Update in 1 minutes

===============================
and here's the full code I'm using. It works as of today perfectly fine. :) Keep in mind I'm using it with a bluefruit sense, TFT featherwing, and airlift featherwing.

Code: Select all

import time
import board
import busio
import displayio
from digitalio import DigitalInOut
import adafruit_bmp280
import adafruit_sht31d
import neopixel
import json
from adafruit_esp32spi import adafruit_esp32spi
from adafruit_esp32spi import adafruit_esp32spi_wifimanager
from adafruit_hx8357 import HX8357
displayio.release_displays()

# Should also work for the 2.5" TFT Featherwing, just change the size.
DISPLAY_WIDTH = 480
DISPLAY_HEIGHT = 320

i2c = board.I2C()
bmp280 = adafruit_bmp280.Adafruit_BMP280_I2C(i2c)
sht31d = adafruit_sht31d.SHT31D(i2c)
bmp280.sea_level_pressure = bmp280.pressure

# Get wifi details and more from a secrets.py file
try:
    from secrets import secrets
except ImportError:
    print("Secrets File Import Error")
    raise

# Initialize SPI bus
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)

# Initilize ESP32 Airlift on SPI bus
esp32_cs = DigitalInOut(board.D13)
esp32_ready = DigitalInOut(board.D11)
esp32_reset = DigitalInOut(board.D12)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2)
wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light)

# Initialize TFT Display on SPI bus
tft_cs = board.D9
tft_dc = board.D10
display_bus = displayio.FourWire(spi, command=tft_dc, chip_select=tft_cs)
display = HX8357(display_bus, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT)

# Connect to WiFi
print("\n===============================")
print("Connecting to WiFi...")
wifi.connect()
print("Connected!\n")

# Each of your feeds will have an individual feed key
feed_key = "sense-temp"
sleep_time = 60  # Timeout between Get/Post updates

if (sleep_time) < 60:
    sleep_time_conversion = "seconds"
elif (sleep_time) >= 60 and (sleep_time) < 3600:
    sleep_int = sleep_time / 60
    sleep_time_conversion = "minutes"
elif (sleep_time) >= 3600:
    sleep_int = sleep_time / 60 / 60
    sleep_time_conversion = "hours"
    
print("Connecting to AdafruitIO...")
while True:
    try:
        print("Connected!")
        print("===============================\n")
        print("POST Value...")
        publish = {"value": "{:.1f}".format(bmp280.temperature*1.8+32)}
        post = wifi.post(
            "https://io.adafruit.com/api/v2/"
            + secrets["aio_username"]
            + "/feeds/"
            + feed_key
            + "/data",
            json=publish,
            headers={"X-AIO-KEY": secrets["aio_key"]},
        )
        print(post.json())
        post.close()

        print("\nGET Response...")
        # time.sleep(10)
        get = wifi.get(
            "https://io.adafruit.com/api/v2/"
            + secrets["aio_username"]
            + "/feeds/"
            + feed_key
            + "/data?limit=1",
            json=None,
            headers={"X-AIO-KEY": secrets["aio_key"]},
        )
        array_val = get.json()
        json_str = json.dumps(array_val)
        resp = json.loads(json_str)
        dictionary = resp[0]
        print("Number of Items in Dictionary: ", len(dictionary))
        print(dictionary)
        print("Circuit Python Object Type :", type(dictionary))
        print("Return Single Value! :", dictionary['value'])  # Single Value Return Yay!
        get.close()
        print("\nNext Update in %s %s" % (int(sleep_int), sleep_time_conversion))
        print("\n===============================")
    except (ValueError, RuntimeError) as e:
        print("Failed to get data, retrying\n", e)
        wifi.reset()
        time.sleep(60)
        continue
    response = None
    time.sleep(sleep_time)
Updated example on my github

Locked
Forum rules
If you're posting code, please make sure your code does not include your Adafruit IO Active Key or WiFi network credentials.

Return to “Internet of Things: Adafruit IO and Wippersnapper”