Rozdíly
Zde můžete vidět rozdíly mezi vybranou verzí a aktuální verzí dané stránky.
Obě strany předchozí revize Předchozí verze Následující verze | Předchozí verze | ||
it:iot:esp8266:vyroba-wifi-teplomeru [2023/01/04 13:37] – [Zdroje s inspirací] Petr Nosek | it:iot:esp8266:vyroba-wifi-teplomeru [2024/01/02 17:17] (aktuální) – Petr Nosek | ||
---|---|---|---|
Řádek 1: | Řádek 1: | ||
====== Výroba Wi-Fi teploměru s ESP8266 ====== | ====== Výroba Wi-Fi teploměru s ESP8266 ====== | ||
- | Wi-Fi teploměr | + | Wi-Fi teploměr |
* [[https:// | * [[https:// | ||
Řádek 7: | Řádek 7: | ||
Pro programování jsem na destičku esp8266 nahrál Micropython. Cílem je, aby se destička připojovala k Mosquitto a posílala tak zprávy skrze MQTT protokol. | Pro programování jsem na destičku esp8266 nahrál Micropython. Cílem je, aby se destička připojovala k Mosquitto a posílala tak zprávy skrze MQTT protokol. | ||
+ | |||
+ | <adm warning> | ||
+ | |||
+ | Jako výborný zdroj posloužil článek [[https:// | ||
+ | ESP32 MQTT – Publish and Subscribe with Arduino IDE senzor BME280]]. Nicméně v článku nepoužívají Python - kód jsem čerpat tedy odjinud. | ||
+ | |||
+ | Později jsem objevil tento článek [[https:// | ||
Řádek 73: | Řádek 80: | ||
Jakmile jsme se připojil k nové Wi-Fi, tak jsem kód vrátil do původního stavu. Nechtělo se mi hlouběji zkoumat, jak to vlastně funguje a hledat elegantnější řešení, protože pro můj účel mi to stačilo. | Jakmile jsme se připojil k nové Wi-Fi, tak jsem kód vrátil do původního stavu. Nechtělo se mi hlouběji zkoumat, jak to vlastně funguje a hledat elegantnější řešení, protože pro můj účel mi to stačilo. | ||
+ | |||
+ | |||
+ | ===== BME280 MicroPython knihovna ===== | ||
+ | |||
+ | Pro senzor BME280 je potřeba knihovna, která bude umět se senzorem pracovat. Knihovna musí být pro Python a našel jsem ji v tomto zdroji [[https:// | ||
+ | |||
+ | <code python> | ||
+ | from machine import I2C | ||
+ | import time | ||
+ | |||
+ | # BME280 default address. | ||
+ | BME280_I2CADDR = 0x76 | ||
+ | |||
+ | # Operating Modes | ||
+ | BME280_OSAMPLE_1 = 1 | ||
+ | BME280_OSAMPLE_2 = 2 | ||
+ | BME280_OSAMPLE_4 = 3 | ||
+ | BME280_OSAMPLE_8 = 4 | ||
+ | BME280_OSAMPLE_16 = 5 | ||
+ | |||
+ | # BME280 Registers | ||
+ | |||
+ | BME280_REGISTER_DIG_T1 = 0x88 # Trimming parameter registers | ||
+ | BME280_REGISTER_DIG_T2 = 0x8A | ||
+ | BME280_REGISTER_DIG_T3 = 0x8C | ||
+ | |||
+ | BME280_REGISTER_DIG_P1 = 0x8E | ||
+ | BME280_REGISTER_DIG_P2 = 0x90 | ||
+ | BME280_REGISTER_DIG_P3 = 0x92 | ||
+ | BME280_REGISTER_DIG_P4 = 0x94 | ||
+ | BME280_REGISTER_DIG_P5 = 0x96 | ||
+ | BME280_REGISTER_DIG_P6 = 0x98 | ||
+ | BME280_REGISTER_DIG_P7 = 0x9A | ||
+ | BME280_REGISTER_DIG_P8 = 0x9C | ||
+ | BME280_REGISTER_DIG_P9 = 0x9E | ||
+ | |||
+ | BME280_REGISTER_DIG_H1 = 0xA1 | ||
+ | BME280_REGISTER_DIG_H2 = 0xE1 | ||
+ | BME280_REGISTER_DIG_H3 = 0xE3 | ||
+ | BME280_REGISTER_DIG_H4 = 0xE4 | ||
+ | BME280_REGISTER_DIG_H5 = 0xE5 | ||
+ | BME280_REGISTER_DIG_H6 = 0xE6 | ||
+ | BME280_REGISTER_DIG_H7 = 0xE7 | ||
+ | |||
+ | BME280_REGISTER_CHIPID = 0xD0 | ||
+ | BME280_REGISTER_VERSION = 0xD1 | ||
+ | BME280_REGISTER_SOFTRESET = 0xE0 | ||
+ | |||
+ | BME280_REGISTER_CONTROL_HUM = 0xF2 | ||
+ | BME280_REGISTER_CONTROL = 0xF4 | ||
+ | BME280_REGISTER_CONFIG = 0xF5 | ||
+ | BME280_REGISTER_PRESSURE_DATA = 0xF7 | ||
+ | BME280_REGISTER_TEMP_DATA = 0xFA | ||
+ | BME280_REGISTER_HUMIDITY_DATA = 0xFD | ||
+ | |||
+ | |||
+ | class Device: | ||
+ | """ | ||
+ | |||
+ | Allows reading and writing 8-bit, 16-bit, and byte array values to | ||
+ | registers on the device.""" | ||
+ | |||
+ | def __init__(self, | ||
+ | """ | ||
+ | the specified I2C interface object.""" | ||
+ | self._address = address | ||
+ | self._i2c = i2c | ||
+ | |||
+ | def writeRaw8(self, | ||
+ | """ | ||
+ | value = value & 0xFF | ||
+ | self._i2c.writeto(self._address, | ||
+ | |||
+ | def write8(self, | ||
+ | """ | ||
+ | b=bytearray(1) | ||
+ | b[0]=value & 0xFF | ||
+ | self._i2c.writeto_mem(self._address, | ||
+ | |||
+ | def write16(self, | ||
+ | """ | ||
+ | value = value & 0xFFFF | ||
+ | b=bytearray(2) | ||
+ | b[0]= value & 0xFF | ||
+ | b[1]= (value>> | ||
+ | self.i2c.writeto_mem(self._address, | ||
+ | |||
+ | def readRaw8(self): | ||
+ | """ | ||
+ | return int.from_bytes(self._i2c.readfrom(self._address, | ||
+ | |||
+ | def readU8(self, | ||
+ | """ | ||
+ | return int.from_bytes( | ||
+ | self._i2c.readfrom_mem(self._address, | ||
+ | |||
+ | def readS8(self, | ||
+ | """ | ||
+ | result = self.readU8(register) | ||
+ | if result > 127: | ||
+ | result -= 256 | ||
+ | return result | ||
+ | |||
+ | def readU16(self, | ||
+ | """ | ||
+ | specified endianness (default little endian, or least significant byte | ||
+ | first).""" | ||
+ | result = int.from_bytes( | ||
+ | self._i2c.readfrom_mem(self._address, | ||
+ | if not little_endian: | ||
+ | result = ((result << 8) & 0xFF00) + (result >> 8) | ||
+ | return result | ||
+ | |||
+ | def readS16(self, | ||
+ | """ | ||
+ | specified endianness (default little endian, or least significant byte | ||
+ | first).""" | ||
+ | result = self.readU16(register, | ||
+ | if result > 32767: | ||
+ | result -= 65536 | ||
+ | return result | ||
+ | |||
+ | def readU16LE(self, | ||
+ | """ | ||
+ | endian byte order.""" | ||
+ | return self.readU16(register, | ||
+ | |||
+ | def readU16BE(self, | ||
+ | """ | ||
+ | endian byte order.""" | ||
+ | return self.readU16(register, | ||
+ | |||
+ | def readS16LE(self, | ||
+ | """ | ||
+ | endian byte order.""" | ||
+ | return self.readS16(register, | ||
+ | |||
+ | def readS16BE(self, | ||
+ | """ | ||
+ | endian byte order.""" | ||
+ | return self.readS16(register, | ||
+ | |||
+ | |||
+ | class BME280: | ||
+ | def __init__(self, | ||
+ | | ||
+ | # Check that mode is valid. | ||
+ | if mode not in [BME280_OSAMPLE_1, | ||
+ | BME280_OSAMPLE_8, | ||
+ | raise ValueError( | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | self._mode = mode | ||
+ | # Create I2C device. | ||
+ | if i2c is None: | ||
+ | raise ValueError(' | ||
+ | self._device = Device(address, | ||
+ | # Load calibration values. | ||
+ | self._load_calibration() | ||
+ | self._device.write8(BME280_REGISTER_CONTROL, | ||
+ | self.t_fine = 0 | ||
+ | |||
+ | def _load_calibration(self): | ||
+ | |||
+ | self.dig_T1 = self._device.readU16LE(BME280_REGISTER_DIG_T1) | ||
+ | self.dig_T2 = self._device.readS16LE(BME280_REGISTER_DIG_T2) | ||
+ | self.dig_T3 = self._device.readS16LE(BME280_REGISTER_DIG_T3) | ||
+ | |||
+ | self.dig_P1 = self._device.readU16LE(BME280_REGISTER_DIG_P1) | ||
+ | self.dig_P2 = self._device.readS16LE(BME280_REGISTER_DIG_P2) | ||
+ | self.dig_P3 = self._device.readS16LE(BME280_REGISTER_DIG_P3) | ||
+ | self.dig_P4 = self._device.readS16LE(BME280_REGISTER_DIG_P4) | ||
+ | self.dig_P5 = self._device.readS16LE(BME280_REGISTER_DIG_P5) | ||
+ | self.dig_P6 = self._device.readS16LE(BME280_REGISTER_DIG_P6) | ||
+ | self.dig_P7 = self._device.readS16LE(BME280_REGISTER_DIG_P7) | ||
+ | self.dig_P8 = self._device.readS16LE(BME280_REGISTER_DIG_P8) | ||
+ | self.dig_P9 = self._device.readS16LE(BME280_REGISTER_DIG_P9) | ||
+ | |||
+ | self.dig_H1 = self._device.readU8(BME280_REGISTER_DIG_H1) | ||
+ | self.dig_H2 = self._device.readS16LE(BME280_REGISTER_DIG_H2) | ||
+ | self.dig_H3 = self._device.readU8(BME280_REGISTER_DIG_H3) | ||
+ | self.dig_H6 = self._device.readS8(BME280_REGISTER_DIG_H7) | ||
+ | |||
+ | h4 = self._device.readS8(BME280_REGISTER_DIG_H4) | ||
+ | h4 = (h4 << 24) >> 20 | ||
+ | self.dig_H4 = h4 | (self._device.readU8(BME280_REGISTER_DIG_H5) & 0x0F) | ||
+ | |||
+ | h5 = self._device.readS8(BME280_REGISTER_DIG_H6) | ||
+ | h5 = (h5 << 24) >> 20 | ||
+ | self.dig_H5 = h5 | ( | ||
+ | self._device.readU8(BME280_REGISTER_DIG_H5) >> 4 & 0x0F) | ||
+ | |||
+ | def read_raw_temp(self): | ||
+ | """ | ||
+ | meas = self._mode | ||
+ | self._device.write8(BME280_REGISTER_CONTROL_HUM, | ||
+ | meas = self._mode << 5 | self._mode << 2 | 1 | ||
+ | self._device.write8(BME280_REGISTER_CONTROL, | ||
+ | sleep_time = 1250 + 2300 * (1 << self._mode) | ||
+ | |||
+ | sleep_time = sleep_time + 2300 * (1 << self._mode) + 575 | ||
+ | sleep_time = sleep_time + 2300 * (1 << self._mode) + 575 | ||
+ | time.sleep_us(sleep_time) | ||
+ | msb = self._device.readU8(BME280_REGISTER_TEMP_DATA) | ||
+ | lsb = self._device.readU8(BME280_REGISTER_TEMP_DATA + 1) | ||
+ | xlsb = self._device.readU8(BME280_REGISTER_TEMP_DATA + 2) | ||
+ | raw = ((msb << 16) | (lsb << 8) | xlsb) >> 4 | ||
+ | return raw | ||
+ | |||
+ | def read_raw_pressure(self): | ||
+ | """ | ||
+ | """ | ||
+ | """ | ||
+ | msb = self._device.readU8(BME280_REGISTER_PRESSURE_DATA) | ||
+ | lsb = self._device.readU8(BME280_REGISTER_PRESSURE_DATA + 1) | ||
+ | xlsb = self._device.readU8(BME280_REGISTER_PRESSURE_DATA + 2) | ||
+ | raw = ((msb << 16) | (lsb << 8) | xlsb) >> 4 | ||
+ | return raw | ||
+ | |||
+ | def read_raw_humidity(self): | ||
+ | """ | ||
+ | """ | ||
+ | msb = self._device.readU8(BME280_REGISTER_HUMIDITY_DATA) | ||
+ | lsb = self._device.readU8(BME280_REGISTER_HUMIDITY_DATA + 1) | ||
+ | raw = (msb << 8) | lsb | ||
+ | return raw | ||
+ | |||
+ | def read_temperature(self): | ||
+ | """ | ||
+ | adc = self.read_raw_temp() | ||
+ | var1 = ((adc >> 3) - (self.dig_T1 << 1)) * (self.dig_T2 >> 11) | ||
+ | var2 = (( | ||
+ | (((adc >> 4) - self.dig_T1) * ((adc >> 4) - self.dig_T1)) >> 12) * | ||
+ | self.dig_T3) >> 14 | ||
+ | self.t_fine = var1 + var2 | ||
+ | return (self.t_fine * 5 + 128) >> 8 | ||
+ | |||
+ | def read_pressure(self): | ||
+ | """ | ||
+ | adc = self.read_raw_pressure() | ||
+ | var1 = self.t_fine - 128000 | ||
+ | var2 = var1 * var1 * self.dig_P6 | ||
+ | var2 = var2 + ((var1 * self.dig_P5) << 17) | ||
+ | var2 = var2 + (self.dig_P4 << 35) | ||
+ | var1 = (((var1 * var1 * self.dig_P3) >> 8) + | ||
+ | ((var1 * self.dig_P2) >> 12)) | ||
+ | var1 = (((1 << 47) + var1) * self.dig_P1) >> 33 | ||
+ | if var1 == 0: | ||
+ | return 0 | ||
+ | p = 1048576 - adc | ||
+ | p = (((p << 31) - var2) * 3125) // var1 | ||
+ | var1 = (self.dig_P9 * (p >> 13) * (p >> 13)) >> 25 | ||
+ | var2 = (self.dig_P8 * p) >> 19 | ||
+ | return ((p + var1 + var2) >> 8) + (self.dig_P7 << 4) | ||
+ | |||
+ | def read_humidity(self): | ||
+ | adc = self.read_raw_humidity() | ||
+ | # print 'Raw humidity = {0: | ||
+ | h = self.t_fine - 76800 | ||
+ | h = (((((adc << 14) - (self.dig_H4 << 20) - (self.dig_H5 * h)) + | ||
+ | | ||
+ | self.dig_H3) >> 11) + 32768)) >> 10) + 2097152) * | ||
+ | self.dig_H2 + 8192) >> 14)) | ||
+ | h = h - (((((h >> 15) * (h >> 15)) >> 7) * self.dig_H1) >> 4) | ||
+ | h = 0 if h < 0 else h | ||
+ | h = 419430400 if h > 419430400 else h | ||
+ | return h >> 12 | ||
+ | |||
+ | @property | ||
+ | def temperature(self): | ||
+ | " | ||
+ | t = self.read_temperature() | ||
+ | ti = t // 100 | ||
+ | td = t - ti * 100 | ||
+ | return " | ||
+ | |||
+ | @property | ||
+ | def pressure(self): | ||
+ | " | ||
+ | p = self.read_pressure() // 256 | ||
+ | pi = p // 100 | ||
+ | pd = p - pi * 100 | ||
+ | return " | ||
+ | |||
+ | @property | ||
+ | def humidity(self): | ||
+ | " | ||
+ | h = self.read_humidity() | ||
+ | hi = h // 1024 | ||
+ | hd = h * 100 // 1024 - hi * 100 | ||
+ | return " | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | ===== Čtení dat ze senzoru BME280 ===== | ||
+ | |||
+ | S knihovnou je pak jednoduché vyčítat hodnoty ze senzoru: | ||
+ | |||
+ | <code python> | ||
+ | # Complete project details at https:// | ||
+ | |||
+ | from machine import Pin, I2C | ||
+ | from time import sleep | ||
+ | import BME280 | ||
+ | |||
+ | # ESP32 - Pin assignment | ||
+ | i2c = I2C(scl=Pin(22), | ||
+ | # ESP8266 - Pin assignment | ||
+ | #i2c = I2C(scl=Pin(5), | ||
+ | |||
+ | while True: | ||
+ | bme = BME280.BME280(i2c=i2c) | ||
+ | temp = bme.temperature | ||
+ | hum = bme.humidity | ||
+ | pres = bme.pressure | ||
+ | # uncomment for temperature in Fahrenheit | ||
+ | #temp = (bme.read_temperature()/ | ||
+ | #temp = str(round(temp, | ||
+ | print(' | ||
+ | print(' | ||
+ | print(' | ||
+ | |||
+ | sleep(5) | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===== Posílání dat skrze MQTT v MicroPythonu ===== | ||
+ | |||
+ | Nejprve jsem si nainstaloval MQTT server Mosquitto a napsal jednoduchý kód v MicroPythonu pro komunikaci, dle článku [[https:// | ||
+ | |||
+ | ==== Ochrana kódu proti odpojení od MQTT serveru ==== | ||
+ | |||
+ | Wi-fi a její automatické připojení je sice vyřešeno, ale jiná věc je, že může sehlat spojení s MQTT serverem. Prostě a jednoduše MQTT server třeba spadne a zařízení nemůže naslouchat nebo posílat data. | ||
+ | |||
+ | V článku [[https:// | ||
+ | |||
+ | Protože se mi to nedařilo, tak jsem se prozatím spokojil s restartem celého zařízení. Výsledný kód tak vypadá takto: | ||
+ | |||
+ | <code python> | ||
+ | from umqtt.simple import MQTTClient | ||
+ | from time import sleep | ||
+ | from machine import Pin, I2C | ||
+ | from time import sleep | ||
+ | import ubinascii | ||
+ | import BME280 | ||
+ | |||
+ | |||
+ | |||
+ | CLIENT_NAME = ubinascii.hexlify(machine.unique_id()) | ||
+ | BROKER_ADDR = ' | ||
+ | |||
+ | |||
+ | print(CLIENT_NAME) | ||
+ | |||
+ | |||
+ | # ESP8266 - Pin assignment | ||
+ | i2c = I2C(scl=Pin(5), | ||
+ | | ||
+ | |||
+ | def connect_and_subscribe(): | ||
+ | mqttc = MQTTClient(CLIENT_NAME, | ||
+ | mqttc.connect() | ||
+ | return mqttc | ||
+ | | ||
+ | def restart_and_reconnect(): | ||
+ | print(' | ||
+ | sleep(10) | ||
+ | machine.reset() | ||
+ | |||
+ | |||
+ | try: | ||
+ | mqttc = connect_and_subscribe() | ||
+ | except OSError as e: | ||
+ | restart_and_reconnect() | ||
+ | | ||
+ | | ||
+ | BTN_TOPIC = b' | ||
+ | |||
+ | |||
+ | while True: | ||
+ | bme = BME280.BME280(i2c=i2c) | ||
+ | temp = bme.temperature | ||
+ | hum = bme.humidity | ||
+ | pres = bme.pressure | ||
+ | print(' | ||
+ | | ||
+ | try: | ||
+ | mqttc.publish( BTN_TOPIC, str(' | ||
+ | except OSError as e: | ||
+ | restart_and_reconnect() | ||
+ | | ||
+ | sleep(5) | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | ==== Úprava kódu po zapnutí autentizace na MQTT ==== | ||
+ | |||
+ | Nejprve jsem musel přidat proměné s uživatelským jménem a heslem: | ||
+ | |||
+ | <code python> | ||
+ | USER = b' | ||
+ | PASSWORD = b' | ||
+ | </ | ||
+ | |||
+ | A poté upravit připojení tak, aby bralo proměnné v potaz: | ||
+ | |||
+ | <code python> | ||
+ | mqttc = MQTTClient(CLIENT_NAME, | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | ==== Problém s přerušením spojení s MQTT serverem ==== | ||
+ | |||
+ | V provozu se mi ukázalo, že když dojde k přerušení spojení s MQTT serverem, tak mi nezbyde nic jiného, než zařízení fyzicky resetovat. Což není zrovna příjemný počin - zejména, pokud budu mít více takových zařízení. Hledal jsem způsob, jak kontrolovat, | ||
+ | |||
+ | Proto jsem vytvořil funkci, která kontroluje, zda je připojení aktivní. V rámci funkce posílám testovací zprávu na mqtt servrer. Podmínkou je, že řeším Quality Of Service = 1, tedy čekám na odpověď ze serveru, zda byla zpráva opravdu doručena. Pokud nebyla, vyvolá se výjimka. | ||
+ | |||
+ | <code python> | ||
+ | def is_connected(mqttc): | ||
+ | try: | ||
+ | mqttc.publish(b" | ||
+ | return True | ||
+ | except OSError: | ||
+ | return False | ||
+ | </ | ||
+ | |||
+ | <adm warning> | ||
+ | |||
+ | Proto jsem použití MicroPython přehodnotil. Vede mě k tomu víc důvodů: | ||
+ | |||
+ | * softwarová podpora - je mnoho kódu v C pro Arduino, ale málo pro MicroPython. Pro další vzdělávání je to problém. Navíc u MicroPythonu se musí využívat knihovny, které jsou nějak minimalizované. Proto kód pro Micropython není jednoduše přenesitelný na Python a naopak, jak jsem si mylně sliboval. | ||
+ | * výkon/ | ||
+ | * bezpečnost použití - kód v C je kompilovaný. Takže když někdo přijde k zařízení s esp8266, nebude mít jednoduché vyčíst hesla k Wi-Fi, certifikát atp. Kdežto při použití Micro Pythonu to bude velmi jednoduché. Stačí zařízení na chvíli připojit k USB portu a program a certifikát v otevřené podobě. | ||
+ | * od C++ očekávám větší stabilitu - co se týče čipu esp8266 | ||
+ | |||
+ | Proto jsem myšlenku použití Micro Pythonu pro moje účely opustil a raději si napíšu program v C++. V rámci stránky připojuji i kód v C++ pro esp8266. | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==== Finální verze kódu po dalších úpravách ==== | ||
+ | |||
+ | <code bash> | ||
+ | from umqtt.simple import MQTTClient | ||
+ | from time import sleep | ||
+ | from machine import Pin, I2C | ||
+ | from time import sleep | ||
+ | import ubinascii | ||
+ | import BME280 | ||
+ | import ujson | ||
+ | |||
+ | |||
+ | CLIENT_NAME = ubinascii.hexlify(machine.unique_id()) | ||
+ | BROKER_ADDR = ' | ||
+ | USER = b' | ||
+ | PASSWORD | ||
+ | MQTT_TOPIC | ||
+ | |||
+ | |||
+ | |||
+ | with open(" | ||
+ | key = f.read() | ||
+ | | ||
+ | with open(" | ||
+ | cert = f.read() | ||
+ | |||
+ | |||
+ | ssl_params = dict() | ||
+ | ssl_params[" | ||
+ | ssl_params[" | ||
+ | |||
+ | |||
+ | print(CLIENT_NAME) | ||
+ | |||
+ | |||
+ | # ESP8266 - Pin assignment | ||
+ | i2c = I2C(scl=Pin(5), | ||
+ | |||
+ | | ||
+ | |||
+ | def connect_and_subscribe(): | ||
+ | mqttc = MQTTClient(CLIENT_NAME, | ||
+ | mqttc.connect() | ||
+ | return mqttc | ||
+ | | ||
+ | def restart_and_reconnect(): | ||
+ | print(' | ||
+ | sleep(10) | ||
+ | # Místo resetování ESP8266 zkuste znovu navázat spojení s MQTT serverem | ||
+ | try: | ||
+ | mqttc = connect_and_subscribe() | ||
+ | except OSError as e: | ||
+ | restart_and_reconnect() | ||
+ | # alternativou je reset celého zařízení | ||
+ | # | ||
+ | |||
+ | |||
+ | def is_connected(mqttc): | ||
+ | try: | ||
+ | mqttc.publish(b" | ||
+ | return True | ||
+ | except OSError: | ||
+ | return False | ||
+ | | ||
+ | |||
+ | try: | ||
+ | mqttc = connect_and_subscribe() | ||
+ | except OSError as e: | ||
+ | restart_and_reconnect() | ||
+ | | ||
+ | | ||
+ | |||
+ | while True: | ||
+ | bme = BME280.BME280(i2c=i2c) | ||
+ | | ||
+ | data = {} | ||
+ | data[' | ||
+ | data[' | ||
+ | data[' | ||
+ | | ||
+ | | ||
+ | if not is_connected(mqttc): | ||
+ | restart_and_reconnect() | ||
+ | | ||
+ | | ||
+ | print(ujson.dumps(data)) | ||
+ | | ||
+ | try: | ||
+ | mqttc.publish( MQTT_TOPIC, str(ujson.dumps(data)).encode() ) | ||
+ | except OSError as e: | ||
+ | restart_and_reconnect() | ||
+ | | ||
+ | sleep(5) | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
Řádek 78: | Řádek 626: | ||
* [[https:// | * [[https:// | ||
+ | * [[http:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | |||
+ | |||
+ | |||
+ | ===== Kód pro teploměr s ESP8266 napsaný v C++ ===== | ||
+ | |||
+ | I když jsem začal stránku s tím, že budu používat MicroPython, | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | #include " | ||
+ | #include " | ||
+ | |||
+ | |||
+ | |||
+ | const char* WiFiName = " | ||
+ | const char* WiFiPassword = " | ||
+ | |||
+ | |||
+ | // MQTT connection | ||
+ | const char* clientName = " | ||
+ | const char* mqttBroker = " | ||
+ | const int mqttPort = 8883; | ||
+ | const char* mqttUser = " | ||
+ | const char* mqttPassword = " | ||
+ | const char* mqttTopic = "/ | ||
+ | |||
+ | Adafruit_BME280 bme; | ||
+ | |||
+ | |||
+ | |||
+ | WiFiClientSecure espClient; | ||
+ | PubSubClient mqttClient(espClient); | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | void setupWiFi() { | ||
+ | | ||
+ | | ||
+ | WiFi.mode(WIFI_STA); | ||
+ | WiFi.begin(WiFiName, | ||
+ | | ||
+ | // connect to WiFi | ||
+ | Serial.print(" | ||
+ | | ||
+ | // wait for connecting to the server | ||
+ | // during this waiting it will write dot to serial link | ||
+ | while (WiFi.status() != WL_CONNECTED) { | ||
+ | delay(500); | ||
+ | Serial.print(" | ||
+ | } | ||
+ | |||
+ | // write new line, Wi-Fi network and IP address of connection | ||
+ | Serial.println("" | ||
+ | Serial.print(" | ||
+ | Serial.println(WiFiName); | ||
+ | Serial.print(" | ||
+ | Serial.println(WiFi.localIP()); | ||
+ | |||
+ | WiFi.setAutoReconnect(true); | ||
+ | WiFi.persistent(true); | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | void reconnectMQTT() { | ||
+ | |||
+ | int retryCount = 0; | ||
+ | |||
+ | while (!mqttClient.connected()) { | ||
+ | |||
+ | Serial.println(" | ||
+ | |||
+ | // SSL/TLS certificate and key settings | ||
+ | // The BearSSL:: | ||
+ | // for the duration of their usage by espClient. If these objects are defined | ||
+ | // within a separate function and used here, they will be destroyed when that | ||
+ | // function exits, leading to undefined behavior and potential device resets. | ||
+ | // A solution to this is to declare them as global variables if they need to | ||
+ | // be used across multiple functions. | ||
+ | BearSSL:: | ||
+ | BearSSL:: | ||
+ | |||
+ | |||
+ | |||
+ | espClient.setInsecure(); | ||
+ | espClient.setClientRSACert(& | ||
+ | |||
+ | mqttClient.setServer(mqttBroker, | ||
+ | |||
+ | |||
+ | if (mqttClient.connect(clientName, | ||
+ | | ||
+ | Serial.println(" | ||
+ | | ||
+ | } else { | ||
+ | Serial.print(" | ||
+ | Serial.print(mqttClient.state()); | ||
+ | Serial.println(" | ||
+ | delay(5000); | ||
+ | |||
+ | retryCount++; | ||
+ | |||
+ | if (retryCount > 5) { // Restart the ESP if it fails to connect 5 times | ||
+ | // | ||
+ | } | ||
+ | |||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | void setup() { | ||
+ | |||
+ | |||
+ | // put your setup code here, to run once: | ||
+ | |||
+ | | ||
+ | // start communication on serial line | ||
+ | Serial.begin(9600); | ||
+ | |||
+ | |||
+ | // Inicializace BME280 | ||
+ | if (!bme.begin(0x76)) { // BME280 I2C sensor address | ||
+ | Serial.println(" | ||
+ | while (1); | ||
+ | } | ||
+ | | ||
+ | setupWiFi(); | ||
+ | | ||
+ | reconnectMQTT(); | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | void loop() { | ||
+ | // put your main code here, to run repeatedly: | ||
+ | |||
+ | if (!mqttClient.connected()) { | ||
+ | reconnectMQTT(); | ||
+ | } | ||
+ | mqttClient.loop(); | ||
+ | |||
+ | |||
+ | // send message each 5 sec | ||
+ | static unsigned long lastMsg = 0; | ||
+ | unsigned long now = millis(); | ||
+ | |||
+ | if (now - lastMsg > 5000) { | ||
+ | lastMsg = now; | ||
+ | |||
+ | // read data from BME280 | ||
+ | float humidity = bme.readHumidity(); | ||
+ | float temperature = bme.readTemperature(); | ||
+ | float pressure = bme.readPressure() / 100.0F; | ||
+ | |||
+ | |||
+ | // Vytvoření JSON objektu | ||
+ | StaticJsonDocument< | ||
+ | | ||
+ | doc[" | ||
+ | doc[" | ||
+ | doc[" | ||
+ | |||
+ | // Serializace JSON objektu do řetězce | ||
+ | char jsonBuffer[200]; | ||
+ | serializeJson(doc, | ||
+ | |||
+ | // Odeslání JSON řetězce na MQTT server | ||
+ | mqttClient.publish(mqttTopic, | ||
+ | | ||
+ | } | ||
+ | |||
+ | |||
+ | } | ||
+ | </ | ||
+ | <adm warning> |