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)