Adafruit Industries, Essential service and business: NYC – Executive Order 202.6 - Read more.
0

Adafruit IO & MQTT & Pyportal
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.

Adafruit IO & MQTT & Pyportal

by oakpress01 on Tue Mar 03, 2020 9:41 am

I've subscribed to a feed by topic and user and now I'd like to print the value of that feed and display it on the pyportal. I can't get the value to print .... I only get (New Message on topic Name/of/topic: <function message at 0x2000ca30>)...please help

oakpress01
 
Posts: 5
Joined: Mon Dec 02, 2019 1:43 pm

Re: Adafruit IO & MQTT & Pyportal

by dastels on Tue Mar 03, 2020 9:52 am

Can you post your code, please? Use code tags around it (in the formatting bar above).

Dave

dastels
 
Posts: 1906
Joined: Tue Oct 20, 2015 3:22 pm

Re: Adafruit IO & MQTT & Pyportal

by oakpress01 on Tue Mar 03, 2020 2:24 pm

The pertinent part of the code is:

[code]
#MQTT TOPIC SETUP#
[mqtt_temperature = ‘user/temperature’

# Define callback methods which are called when events occur
# pylint: disable=unused-argument, redefined-outer-name
def connect(client, userdata, flags, rc):
# This function will be called when the client is connected
# successfully to the broker.
print('Connected to MQTT Broker!')
print('Flags: {0}\n RC: {1}'.format(flags, rc))

def disconnected(client, userdata, rc):
# This method is called when the client is disconnected
print('Disconnected from MQTT Broker!')

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 publish(client, userdata, topic, pid):
# This method is called when the client publishes data to a feed.
print('Published to {0} with PID {1}'.format(topic, pid))

def message(client, topic, message):
"""Method callled when a client's subscribed feed has a new
value.
:param str topic: The topic of the feed with a new value.
:param str message: The new value
"""
print('New message on topic {0}: {1}'.format(topic, message))


# Connect to WiFi
wifi.connect()


# Set up a MiniMQTT Client
client = MQTT(socket,
broker = secrets['broker'],
port = 8883,
username = secrets['user'],
password = secrets['pass'],
network_manager = wifi)


# Connect callback handlers to client
client.on_connect = connect
client.on_disconnect = disconnected
client.on_subscribe = subscribe
client.on_publish = publish
client.on_message = message

client.connect()

print('Subscribing to %s' % (mqtt_temperature))
client.subscribe(mqtt_temperature)


# ------------- Code Loop ------------- #

while True:
touch = ts.touch_point
light = light_sensor.value
light_value = lux = light_sensor.value
light_label.text = 'Light Sensor Value: {}'.format(lux)
print('New message on topic {0}: {1}'.format(mqtt_humidity, message))
code]

oakpress01
 
Posts: 5
Joined: Mon Dec 02, 2019 1:43 pm

Re: Adafruit IO & MQTT & Pyportal

by dastels on Tue Mar 03, 2020 3:41 pm

Try renaming the message parameter to the message function. It looks like the function is taking precedence for some reason.

Dave

dastels
 
Posts: 1906
Joined: Tue Oct 20, 2015 3:22 pm

Re: Adafruit IO & MQTT & Pyportal

by oakpress01 on Tue Mar 03, 2020 7:01 pm

How would I rename the message parameter to the message function? I'm very new at this and been trying to work through this "error" for weeks... The data I'm trying to get onto the pyportal is from a AM2302 sensor that is connected to a raspberry pi 4 and being sent to Adafruit IO via python3. I've read everything I can find online (including things that aren't by Adafruit).... I really don't know where to go from here ...

oakpress01
 
Posts: 5
Joined: Mon Dec 02, 2019 1:43 pm

Re: Adafruit IO & MQTT & Pyportal

by dastels on Tue Mar 03, 2020 9:54 pm

Open the file in an editor and change the parameter and where it's used, it should then look like:

Code: Select all | TOGGLE FULL SIZE
def message(client, topic, msg):
    """Method callled when a client's subscribed feed has a new value.
    :param str topic: The topic of the feed with a new value.
    :param str msg: The new value
    """
    print('New message on topic {0}: {1}'.format(topic, msg))

dastels
 
Posts: 1906
Joined: Tue Oct 20, 2015 3:22 pm

Re: Adafruit IO & MQTT & Pyportal

by brubell on Wed Mar 04, 2020 12:32 pm

Hi oakpress1,

This line attaches the on_message method callback to the message() method in your code:
client.on_message = message


You are not subscribed to the mqtt_humidity feed in your code, so the message() callback method will never trigger as intended.

Add the following line underneath your call to client.subscribe()
Code: Select all | TOGGLE FULL SIZE
mqtt_humidity = ‘user/humidity’
client.subscribe(mqtt_humidity)


Also - Your loop doesn't seem to publish data (light_value or touch) to Adafruit IO. I don't know if this is intentional or not, did you post your full code?

I'll like to suggest the following modification to the loop, adding io.loop() will periodically ping the adafruit io mqtt server and keep your pyportal's connection allive.
Code: Select all | TOGGLE FULL SIZE
while True:
    # Explicitly pump the message loop.
    io.loop()
   touch = ts.touch_point
   light = light_sensor.value
   light_value = lux = light_sensor.value

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

Re: Adafruit IO & MQTT & Pyportal

by oakpress01 on Thu Mar 05, 2020 7:57 am

Thank you both for your responses. Brubell, you're right ....i didn't post all of my code. I've continued to make edits, but I'm still getting function messages instead of values .... below is all of my code....

[code]
import time
import board
import displayio
import busio
from digitalio import DigitalInOut
from analogio import AnalogIn
import neopixel
from adafruit_bitmap_font import bitmap_font
from adafruit_display_text.label import Label
from adafruit_button import Button
import adafruit_touchscreen
from adafruit_pyportal import PyPortal
from adafruit_esp32spi import adafruit_esp32spi
from adafruit_esp32spi import adafruit_esp32spi_wifimanager
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
#from Adafruit_IO import Client
#from Adafruit_IO import Client, RequestError, Feed
from adafruit_minimqtt import MQTT
from adafruit_io.adafruit_io import IO_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


# ------------- Inputs and Outputs Setup ------------- #

i2c_bus = busio.I2C(board.SCL, board.SDA)
# PyPortal ESP32 AirLift Pins
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)

spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
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)


# init. the light sensor
light_sensor = AnalogIn(board.LIGHT)


WHITE = 0xffffff
RED = 0xff0000
YELLOW = 0xffff00
GREEN = 0x00ff00
BLUE = 0x0000ff
PURPLE = 0xff00ff
BLACK = 0x000000

pyportal = PyPortal(esp=esp,external_spi=spi)
display = board.DISPLAY
display.rotation = 0

# Backlight function
# Value between 0 and 1 where 0 is OFF, 0.5 is 50% and 1 is 100% brightness.
def set_backlight(val):
val = max(0, min(1.0, val))
board.DISPLAY.auto_brightness = False
board.DISPLAY.brightness = val

# Set the Backlight
set_backlight(1.0)

# Touchscreen setup
# ------Rotate 0:
screen_width = 480
screen_height = 320
# -------Rotate 0:
ts = adafruit_touchscreen.Touchscreen(board.TOUCH_XL, board.TOUCH_XR,
board.TOUCH_YD, board.TOUCH_YU,
calibration=((5200, 59000), (5800, 57000)),
size=(480, 320))

# ------------- Display Groups ------------- #
splash = displayio.Group(max_size=10)
view1 = displayio.Group(max_size=15)
view2 = displayio.Group(max_size=15, x=0, y=40)


# ------------- Setup for Images ------------- #
"""Set the image file for a given goup for display.
This is most useful for Icons or image slideshows.
:param group: The chosen group
:param filename: The filename of the chosen image
"""
print("Set image to ", filename)
if group:
group.pop()

# Display an image until the loop starts
pyportal.set_background('/images/loading.bmp')

#CREATE MAIN GROUP
main_group = displayio.Group(max_size=1)
splash.append(main_group)
set_image(main_group,"/images/nep.bmp")

# Create a new DisplayIO group
splash = displayio.Group(max_size=8)

# show splash group
display.show(splash)

#splash.append(background)


# Set the font and preload letters
font = bitmap_font.load_font("/fonts/Helvetica-Bold-16.bdf")
font.load_glyphs(b'abcdefghjiklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890- ()')

# Default Label styling:
TABS_X = 5
TABS_Y = 50

#TEXT LABEL OBJECTS
light_label = Label(font, text="Light Sensor", color=0xFFFFFF, max_glyphs=200)
light_label.x = TABS_X
light_label.y = TABS_Y
splash.append(light_label)

temperature_label = Label(font, text="Temperature", color=0xFFFFFF, max_glyphs=200)
temperature_label.x = TABS_X
temperature_label.y = TABS_Y+25
splash.append(temperature_label)

humidity_label = Label(font, text="Humidity", color=0xFFFFFF, max_glyphs=200)
humidity_label.x = TABS_X
humidity_label.y = TABS_Y+60
splash.append(humidity_label)

# Used to calculate vertical text height for Top Alignment
text_hight = Label(font, text="M", color=0x03AD31, max_glyphs=10)

# return a string with word wrapping using PyPortal.wrap_nicely
def text_box(target, top, max_chars, string):
text = pyportal.wrap_nicely(string, max_chars)
new_text = ""
test = ""
for w in text:
new_text += '\n'+w
test += 'M\n'
text_hight.text = test
glyph_box = text_hight.bounding_box
print(glyph_box[3])
target.text = "" # Odd things happen without this
target.y = round(glyph_box[3]/2)+top
target.text = new_text
# ------------- MQTT Topic Setup ------------- #

# Adafruit IO-style Topic
# Use this topic if you'd like to connect to io.adafruit.com
mqtt_temperature = 'aio_user/feeds/temperature'
mqtt_humidity = 'aio_user/feeds/humidity'
mqtt_light = 'aio_user/feeds/light'

# Define callback methods which are called when events occur
# pylint: disable=unused-argument, redefined-outer-name
def connect(client, userdata, flags, rc):
# This function will be called when the client is connected
# successfully to the broker.
print('Connected to MQTT Broker!')
print('Flags: {0}\n RC: {1}'.format(flags, rc))

def disconnected(client, userdata, rc):
# This method is called when the client is disconnected
print('Disconnected from MQTT Broker!')

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 publish(client, userdata, topic, pid):
# This method is called when the client publishes data to a feed.
print('Published to {0} with PID {1}'.format(topic, pid))

def message(client, topic, message):
"""Method callled when a client's subscribed feed has a new value.
:param str topic: The topic of the feed with a new value.
:param str msg: The new value
"""
print('New message on topic {0}: {1}'.format(topic, message))


# Connect to WiFi
wifi.connect()


# Set up a MiniMQTT Client
client = MQTT(socket,
broker = secrets['broker'],
port = 1883,
username = secrets['user'],
password = secrets['pass'],
network_manager = wifi)

# Connect callback handlers to client
client.on_connect = connect
client.on_disconnect = disconnected
client.on_subscribe = subscribe
client.on_publish = publish
client.on_message = message

client.connect()

print('Subscribing to %s %s and %s' % (mqtt_temperature, mqtt_humidity, mqtt_light))
client.subscribe(mqtt_temperature)
client.subscribe(mqtt_humidity)
client.subscribe(mqtt_light)

# ------------- Code Loop ------------- #
while True:
# RETRIEVE MESSAGES.
client.loop()
touch = ts.touch_point
light = light_sensor.value
light_value = lux = light_sensor.value
light_label.text = 'Light Sensor Value: {}'.format(lux)
temperature_label.text = 'Temperature: {}'.format(message)
humidity_label.text = 'Humidity: \n {}'.format(message)
print ('New message on topic {0}: {1}'.format(mqtt_humidity, message))
print ('New message on topic {0}: {1}'.format(mqtt_temperature, message))/code]

I'll appreciate any suggestions or input ...

oakpress01
 
Posts: 5
Joined: Mon Dec 02, 2019 1:43 pm

Re: Adafruit IO & MQTT & Pyportal

by brubell on Thu Mar 05, 2020 7:02 pm

but I'm still getting function messages instead of values

That's because you are calling these methods:
Code: Select all | TOGGLE FULL SIZE
print ('New message on topic {0}: {1}'.format(mqtt_humidity, message))
print ('New message on topic {0}: {1}'.format(mqtt_temperature, message))/code]



Remove them. The message method will execute automatically when there is a new message on the mqtt_temperature or mqtt_humidity feeds. Start your code. Then, try manually adding data to the feed from the Adafruit IO Website..

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

Re: Adafruit IO & MQTT & Pyportal

by oakpress01 on Fri Mar 06, 2020 9:40 am

Makes perfect sense .... thank you Brubell - it works perfectly!

oakpress01
 
Posts: 5
Joined: Mon Dec 02, 2019 1:43 pm

Re: Adafruit IO & MQTT & Pyportal

by brubell on Fri Mar 06, 2020 10:13 am

oakpress01 wrote:Makes perfect sense .... thank you Brubell - it works perfectly!

Congrats!

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

Please be positive and constructive with your questions and comments.