from time import sleep
from umqttsimple import MQTTClient
import ubinascii
import json
import ujson
import dht
import random
from machine import Pin, unique_id, reset, deepsleep
led = Pin(21, Pin.OUT) #Led used to communicate esp32 is synced with beacon
sensor = dht.DHT22(Pin(22)) #initialized sensor connected to pin 22
led.value(False) #set led to off
mqtt_server = 'mqtt-dashboard.com'
device_id = "2" #id used in beacon to understand which device is
client_id = str(random.randint(1,1000)) #id used in the connection with the mqtt broker
topic_base = '10802244' #topic name
def sub_cb(topic, message): #function called when a message arrives from mqtt
json_msg = json.loads(message.decode('utf-8')) #convert a string in json object
if topic == b'' + topic_base: #check if it's the right topic
if 'id' in json_msg and (json_msg['id']==device_id or json_msg['id']==0): #check if it is my own message or from broker
print("My Own Message Received -- Ignored")
else:
#print("Received MQTT message: topic '{0}', value '{1}'" \
# .format(topic.decode("utf-8"), message.decode("utf-8"))) #print message arrived
if 'slotAssignments' in json_msg: #check if it has slotAssignments field, this means it is the beacon message
print("Received MQTT message: topic '{0}', value '{1}'" \
.format(topic.decode("utf-8"), message.decode("utf-8"))) #print message arrived
frame_duration = json_msg['frameDuration'] #store frame duration value
if device_id in json_msg['slotAssignments']: #check if json_msg has slot assignment for this deviceId
sleep(json_msg['cap']/frame_duration) #sleep until for cap duration
sleep(((json_msg['slotAssignments'][device_id]*frame_duration)-frame_duration)/frame_duration) #sleep until its turn
print("Measuring weather conditions... ", end="")
sensor.measure() #measure humidity
message = ujson.dumps({
"id": device_id,
"actuator": random.randint(3,4),
"humidity" : sensor.humidity(),
}) #create json object to store deviceId, actuator id (randomly chosen), himidity value
client.publish(b'' + topic_base, message) #publish message on topic
else:
led.value(True) #if no slot assignments for this deviceId then light up led to indicate if device is synced with beacon
message = ujson.dumps({
"id": device_id,
"message": "subscribe"
}) #create json object to store deviceId, message to subscribe
client.publish(b'' + topic_base,message) #publish message on topic
#should be deepsleep
sleep((json_msg['bi']-json_msg['cap']-json_msg['cfp'])/frame_duration) #sleep for the sleep beacon time
else:
print("Wrong Topic -- Ignored")
def connect_and_subscribe(): #function to connect to broker
mqtt_client = MQTTClient(client_id, mqtt_server)
mqtt_client.set_callback(sub_cb) #set function clled when messages arrive
mqtt_client.connect() #connect to broker
mqtt_client.subscribe(topic_base) #subscribe to topic
print('Connected to {0} MQTT broker'.format(mqtt_server))
return mqtt_client
def restart_and_reconnect(): #if errors occur in connection this function is called and retry connection to broker
print('Failed to connect to MQTT broker. Reconnecting...')
sleep(5)
reset()
try:
client = connect_and_subscribe() #try connection to broker
except OSError as e:
restart_and_reconnect() #OSError retry
def loop():
try:
client.check_msg() #check if message arrive
except OSError as e:
restart_and_reconnect() #OSError retry
try:
while True:
loop() #call loop
except KeyboardInterrupt:
pass