from time import sleep
from umqtt.simple import MQTTClient
from machine import Pin
import machine
from dht import DHT22
import ujson
import utime
import ntptime
# +-------------------------------------+
# | MQTT Section |
# +-------------------------------------+
with open('client.key.der') as f: # reading client key
key_data = f.read()
with open('client.cert.der') as f: # reading client cert
cert_data = f.read()
server = 'server.ml' # MQTT Server Address
client_id = 'ESP8266_DHT22_Sensor_Polcia' # client id
topic = b'temperature_humidity'
location = 'Pokój Polci 2' # location of the sensor
counter = 1 # Control number
dsleep = 600 # number of seconds ESP is to sleep
dbr = 3 # delay between readings in getData function
nom = 5 # number of measurements before taking the median
save2db = True # Switch to save or not data to database
debug = True # if debug = True then write to debug.log
def deep_sleep(msecs): # https://randomnerdtutorials.com/micropython-esp8266-deep-sleep-wake-up-sources/
if debug: write2debug('Inside deep_sleep') # you need to connect GPIO16 (D0) to the RST pin so that the ESP8266 can wake itself up.
rtc = machine.RTC() # configure RTC.ALARM0 to be able to wake the device
rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP)
rtc.alarm(rtc.ALARM0, msecs) # set RTC.ALARM0 to fire after X milliseconds (waking the device)
# put the device to sleep
if debug: write2debug('Going to sleep...\n-------------------------------\n')
machine.deepsleep(msecs)
def median(lst): # Calculate median from given list of values
sortedLst = sorted(lst)
lstLen = len(lst)
index = (lstLen - 1) // 2
if (lstLen % 2):
return sortedLst[index]
else:
return (sortedLst[index] + sortedLst[index + 1])/2.0
def getCurrentDatetime():
ntptime.settime() # Synchronise the system time using NTP
GMT = 1 # we are at GMT+1 zone, so one hour ahead
sGMT = GMT * 3600 # hours to seconds
secs = utime.time()
cTime = utime.localtime(secs + sGMT) # calculate the current datetime considering above
month = cTime[1]
day = cTime[2]
hour = cTime[3]
minute = cTime[4]
second = cTime[5]
if int(month) < 10:
months = "0" + str(month)
else:
months = month
if int(day) < 10:
days = "0" + str(day)
else:
days = day
if int(hour) < 10: # Convert time to be 03:09:02 instead of 3:9:2
hours = "0" + str(hour)
elif int(hour) == 24: # Hour can has values from 0...23
hours = "00"
else:
hours = hour
if int(minute) < 10:
minutes = "0" + str(minute)
else:
minutes = minute
if int(second) < 10:
seconds = "0" + str(second)
else:
seconds = second
# Create current time in format: YYYY-MM-DD HH:MM:SS
currentTime = "{}-{}-{} {}:{}:{}".format(cTime[0], months, days, hours, minutes, seconds)
return currentTime
def buildjson(temp, hum, error, error_desc):
currentTime = getCurrentDatetime()
x = {
"location": location,
"temperature": temp,
"humidity": hum,
"time": currentTime,
"error": (error, error_desc),
"save2db": save2db
}
return ujson.dumps(x)
def getData(sensor):
if debug: write2debug('Inside getData')
try:
temp = []
humi = []
for x in range(nom): # Make n measurements and calculate median from them
sleep(dbr) # Give sensore some time to prepare
sensor.measure() # Poll sensor
if debug: write2debug('Sensor poll')
t = sensor.temperature()
h = sensor.humidity()
if isinstance(t, float) and isinstance(h, float): # Confirm sensor results are numeric
temp.append(t)
humi.append(h)
else:
if debug: write2debug('Invalid sensor reading. Publishing error to mosquitto.')
msg = buildjson(None, None, True, 'Invalid sensor readings.')
client.publish(topic, bytes(msg, 'utf-8')) # Publish sensor data to MQTT topic
if debug: write2debug('error published.')
temperature = median(temp)
humidity = median(humi)
msg = buildjson(temperature, humidity, False, "")
if debug: write2debug('json build. Publishing data to mosquitto.')
client.publish(topic, bytes(msg, 'utf-8')) # Publish sensor data to MQTT topic
if debug: write2debug('data published.')
except OSError:
msg = buildjson(None, None, True, 'Failed to read sensor.')
client.publish(topic, bytes(msg, 'utf-8')) # Publish sensor data to MQTT topic
if debug: write2debug('Failed to read sensor.')
def sub_cb(t, msg):
if debug: write2debug('Inside sub_cb')
if debug: write2debug('topic received=' + t.decode("utf-8") + ', topic defined=' + topic.decode("utf-8"))
if t.decode("utf-8") == topic.decode("utf-8") :
print((t, msg))
if debug: write2debug('msg received: ' + msg.decode("utf-8")) # bytes to string
client.disconnect()
deep_sleep(dsleep*1000)
def write2debug(message):
with open('debug.log', 'a') as f:
f.write(message+'\n')
client = MQTTClient(client_id, server, port=8883, user=b'username', password=b'password', ssl=True, ssl_params={'key':key_data, 'cert':cert_data})
client.set_callback(sub_cb) # wait until data is published onto broker before putting into deep sleep
client.connect() # Connect to MQTT broker
client.subscribe(topic)
if debug: write2debug('Client connected and subcribed to topic')
sensor = DHT22(Pin(5, Pin.IN, Pin.PULL_UP)) # DHT-22 on GPIO 5 (input with internal pull-up resistor)
if debug: write2debug('Sensor data read')
if debug: write2debug('Entering getData ')
getData(sensor)
if debug: write2debug('Done with getData ')
while True:
client.check_msg()
sleep(1)