ESP32 MQTT: publish and subscribe in same script
Posted: Sun Feb 25, 2018 9:43 pm
Hi,
I am working on project where I can leave ESP32 in greenhouse to monitor sensors (temperature, soil moisture, etc), report (publish) to MQTT broker and also listen (subscribe) to commands (start valve to water plants, etc). It should publish data periodically (based on my defined schedule) or if some criteria is met (like window is closed, water valve is turned off). It should also continuesly listen to mqtt messages.
Currently I am on breadboard stage and testing various sensors, running small micropython scripts, trying to learn and understand. My set up is:
Respberry Pi 3 running Raspbian. I have Mosquitto server on it that acts as MQTT broker. Also have Node-Red that helps to visually see incomming mqtt messages and also create messages that are picked up by mqtt clients. Then I have ESP32 with micropython dowloaded from this website (umqtt.simple) and sensors that are connected to it via breadboard. I have been able to write (mostly copy/paste from web with some adjustments to fit local environment) scripts to read DHT22 sensor values (temp, humidity) and send it over to mqtt broker. This task runs in the loop until I interrupt. I have another script that subsribes to message and based on message it either turns on or off led light (imagine that is my water valve later on).
My attempt is to write one micropython code (or combine my existingworking codes into one) to do following tasks:
1. Read sensor data and publish msg1 (message1) to mqtt broker at certain interval;
2. Subscribe to msg2
3. If message says ON, turn led On.
I then plan to use Node-Red to listne to msg1 (contains temp and humidity) and if value exceeds certain number, then turn on led. Then I should be able to have led OFF under normal conditions, but if I blow to sensor, then led turns ON (as temp and humidity increases). If I manage that , then I should be able to run various scenarios in greenhouse (open watervalve for certain time if soil is dry, open windown if temp above x, close if below Y, etc).
So I managed to do publishing and subsribing separately, but not in one code, suspect something is wrong with my loop. Do you see what I am doing wrong? what should I change? Code below waits for message from broker after connecting to wifi, once received it executes code (turns led on or off) and publishes sensor values once, then I get error message pointing to line " client.wait_msg()"
I am working on project where I can leave ESP32 in greenhouse to monitor sensors (temperature, soil moisture, etc), report (publish) to MQTT broker and also listen (subscribe) to commands (start valve to water plants, etc). It should publish data periodically (based on my defined schedule) or if some criteria is met (like window is closed, water valve is turned off). It should also continuesly listen to mqtt messages.
Currently I am on breadboard stage and testing various sensors, running small micropython scripts, trying to learn and understand. My set up is:
Respberry Pi 3 running Raspbian. I have Mosquitto server on it that acts as MQTT broker. Also have Node-Red that helps to visually see incomming mqtt messages and also create messages that are picked up by mqtt clients. Then I have ESP32 with micropython dowloaded from this website (umqtt.simple) and sensors that are connected to it via breadboard. I have been able to write (mostly copy/paste from web with some adjustments to fit local environment) scripts to read DHT22 sensor values (temp, humidity) and send it over to mqtt broker. This task runs in the loop until I interrupt. I have another script that subsribes to message and based on message it either turns on or off led light (imagine that is my water valve later on).
My attempt is to write one micropython code (or combine my existingworking codes into one) to do following tasks:
1. Read sensor data and publish msg1 (message1) to mqtt broker at certain interval;
2. Subscribe to msg2
3. If message says ON, turn led On.
I then plan to use Node-Red to listne to msg1 (contains temp and humidity) and if value exceeds certain number, then turn on led. Then I should be able to have led OFF under normal conditions, but if I blow to sensor, then led turns ON (as temp and humidity increases). If I manage that , then I should be able to run various scenarios in greenhouse (open watervalve for certain time if soil is dry, open windown if temp above x, close if below Y, etc).
So I managed to do publishing and subsribing separately, but not in one code, suspect something is wrong with my loop. Do you see what I am doing wrong? what should I change? Code below waits for message from broker after connecting to wifi, once received it executes code (turns led on or off) and publishes sensor values once, then I get error message pointing to line " client.wait_msg()"
Code: Select all
from time import sleep
from umqtt.simple import MQTTClient
from machine import Pin
from dht import DHT22
import ubinascii
import machine
import micropython
import network, utime
#-----------Connect to WiFi
station = network.WLAN(network.STA_IF)
station.active(True)
station.connect("******", "******")
tmo = 50
while not station.isconnected():
utime.sleep_ms(100)
tmo -= 1
if tmo == 0:
break
if tmo > 0:
ifcfg = station.ifconfig()
print("WiFi started, IP:", ifcfg[0])
utime.sleep_ms(500)
#-----------------
led = Pin(13, Pin.OUT, value=1) # led on GPIO 13
sensor = DHT22(Pin(15, Pin.IN, Pin.PULL_UP)) # DHT-22 on GPIO 15 (input with internal pull-up resistor)
def callback(topic, msg):
global state
print((topic, msg))
if msg == b"on":
led.value(1)
state = 0
elif msg == b"off":
led.value(0)
state = 1
elif msg == b"toggle":
# LED is inversed, so setting it to current state
# value will make it toggle
led.value(state)
state = 1 - state
broker_address = '*******'
client_id ='test1'
topic=b'led'
TOPIC2 = b'temp_humidity'
state=0
client = MQTTClient(client_id, broker_address, port=1883, user=b"*****", password=b"******")
client.set_callback(callback)
client.connect()
client.subscribe(b"led")
while True:
if True:
# Blocking wait for message
client.wait_msg()
else:
# Non-blocking wait for message
client.check_msg()
# Then need to sleep to avoid 100% CPU usage (in a real
# app other useful actions would be performed instead)
time.sleep(1)
try:
sensor.measure() # Poll sensor
t = sensor.temperature()
h = sensor.humidity()
if isinstance(t, float) and isinstance(h, float): # Confirm sensor results are numeric
msg = (b'{0:3.1f},{1:3.1f}'.format(t, h))
client.publish(TOPIC2, msg) # Publish sensor data to MQTT topic
print("Published", msg)
else:
print('Invalid sensor readings.')
except OSError:
print('Failed to read sensor.')
sleep(4)
client.disconnect()