Skip to content

STM32: possible problem with strings and adafruit_minimqtt library (AdafruitIO) #2433

@hukuzatuna

Description

@hukuzatuna

I have the Feather STM32F405 Express board. I built firmware for it on Christmas. I have an LPS3x bord connected via QT. If I just print data, everything is fine. If I try to push the data to AdafruitIO, though, I get an error "AttributeError: 'str' object has no attribute 'encode'. When I run
adafruit/Adafruit_CircuitPython_AdafruitIO/examples/mqtt/adafruit_io_simpletest.py it throws the same error and backtrace. Here's the backtrace, code to follow down below.

Press any key to enter the REPL. Use CTRL-D to reload.soft reboot

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.
code.py output:
Traceback (most recent call last):
  File "code.py", line 93, in <module>
  File "adafruit_minimqtt.py", line 121, in __init__
AttributeError: 'str' object has no attribute 'encode'

Then I thought maybe something had changed, so I went back to the Adafruit IO guides and could not find resolution.

Then I went to the library bundle 5.x source as of 20191223 and looked at line 121 in adafruit_minimqtt.py. (If you need me to include a snippet here, I will.) There didn't seem t be anything unusual, but I did see the .encode() method that was causing the problem.

Then I just connected to the REPL, created a string and called the same encode method:

Adafruit CircuitPython 5.0.0-beta.2-13-g7387f6092 on 2019-12-27; Feather STM32F405 Express with STM32F405RG
>>> foo = "heresastringtotestwith"
>>> foo.encode('utf-u')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'encode'
>>> 

The last couple of issues I raised LadyAda had to exercise extreme patience with my bumbling, so I hope this is more cohesive and helpful. I still assume I'm just doing something stupid, but people on Discord don't seem to think so.

Here is the code that generated the original backtrace:

# Example of using the Adafruit IO CircuitPython MQTT client
# to subscribe to an Adafruit IO feed and publish random data
# to be received by the feed.
#
# Example by Tony DiCola for Adafruit Industries
# Modified by Brent Rubell for Adafruit Industries, 2019
import time
from random import randint


import board
import busio
from adafruit_esp32spi import adafruit_esp32spi
from adafruit_esp32spi import adafruit_esp32spi_wifimanager
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
from digitalio import DigitalInOut
import neopixel
from adafruit_io.adafruit_io import IO_MQTT
from adafruit_minimqtt import MQTT

### WiFi ###

# Get wifi details and more from a secrets.py file
try:
    from secrets import secrets
except ImportError:
    print("WiFi secrets are kept in secrets.py, please add them there!")
    raise

# If you have an externally connected ESP32:
esp32_cs = DigitalInOut(board.D13)
esp32_ready = DigitalInOut(board.D11)
esp32_reset = DigitalInOut(board.D12)


spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
"""Use below for Most Boards"""
status_light = neopixel.NeoPixel(
    board.NEOPIXEL, 1, brightness=0.2
)  # Uncomment for Most Boards
"""Uncomment below for ItsyBitsy M4"""
# status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2)
# Uncomment below for an externally defined RGB LED
# import adafruit_rgbled
# from adafruit_esp32spi import PWMOut
# RED_LED = PWMOut.PWMOut(esp, 26)
# GREEN_LED = PWMOut.PWMOut(esp, 27)
# BLUE_LED = PWMOut.PWMOut(esp, 25)
# status_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED)
wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light)

# Define callback functions which will be called when certain events happen.
# pylint: disable=unused-argument
def connected(client):
    # Connected function will be called when the client is connected to Adafruit IO.
    # This is a good place to subscribe to feed changes.  The client parameter
    # passed to this function is the Adafruit IO MQTT client so you can make
    # calls against it easily.
    print("Connected to Adafruit IO!  Listening for DemoFeed changes...")
    # Subscribe to changes on a feed named DemoFeed.
    client.subscribe("DemoFeed")

def subscribe(client, userdata, topic, granted_qos):
    # This method is called when the client subscribes to a new feed.
    print('Subscribed to {0} with QOS level {1}'.format(topic, granted_qos))

def unsubscribe(client, userdata, topic, pid):
    # This method is called when the client unsubscribes from a feed.
    print('Unsubscribed from {0} with PID {1}'.format(topic, pid))

# pylint: disable=unused-argument
def disconnected(client):
    # Disconnected function will be called when the client disconnects.
    print("Disconnected from Adafruit IO!")

# pylint: disable=unused-argument
def message(client, feed_id, payload):
    # Message function will be called when a subscribed feed has a new value.
    # The feed_id parameter identifies the feed, and the payload parameter has
    # the new value.
    print("Feed {0} received new value: {1}".format(feed_id, payload))


# Connect to WiFi
wifi.connect()

# Initialize a new MQTT Client object
mqtt_client = MQTT(
    socket=socket,
    broker="io.adafruit.com",
    username=secrets["aio_username"],
    password=secrets["aio_key"],
    network_manager=wifi
)

# Initialize an Adafruit IO MQTT Client
io = IO_MQTT(mqtt_client)

# Connect the callback methods defined above to Adafruit IO
io.on_connect = connected
io.on_disconnect = disconnected
io.on_subscribe = subscribe
io.on_unsubscribe = unsubscribe
io.on_message = message

# Connect to Adafruit IO
io.connect()

# Below is an example of manually publishing a new  value to Adafruit IO.
last = 0
print("Publishing a new message every 10 seconds...")
while True:
    # Explicitly pump the message loop.
    io.loop()
    # Send a new message every 10 seconds.
    if (time.monotonic() - last) >= 5:
        value = randint(0, 100)
        print("Publishing {0} to DemoFeed.".format(value))
        io.publish("DemoFeed", value)
        last = time.monotonic()


# You can also call loop_blocking if you only want to receive values.
# NOTE: If uncommented, no code below this line will run.
# io.loop_blocking()

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions