Традиционным “Hello World!” в мире микроконтроллеров можно по праву назвать мигание светодиодом. Это и было сделано после установки MicroPython на ESP8266. Но время идти двигаться дальше и реализовать второй традиционный проект для микроконтроллера - измерение температуры и влажности со всеми любимым датчиком DHT22. Но мы не ограничимся тихими измерениями, а вместе с этим будем отсылать эти важные данные в интернеты. Для этого у нас есть, например, прекрасный сервис ThingSpeak. Пополним армию Internet of Shit!

English version - MicroPython on ESP8266: sending data to ThingSpeak

Железо и схема: ESP8266 (ESP-07) и DHT22

За основу возьмем предыдущий пост - как запустить MicroPython на ESP8266. Все описанное в том посте вполне применимо и к этому.

Так же отметим, что лучше использовать ESP8266, у которых объем памяти превышает 512K, потому что можно использовать полные версии MicroPython. Похоже, что урезанные версии MicroPython могут не всегда хорошо работать на ESP8266.

Будем опять использовать ESP-07, хотя можно использовать и ESP-12 без внесения изменений в схему ниже. С другими версиями ESP8266 возможно придется что-то поменять.

Схема включения ESP8266 ESP-07 и DHT22

Схема похожа на ту, что была в предыдущем посте. Вот, что было добавлено

  • Датчик DHT22 и сопротивление R6.
  • Переключатель на GPIO5, который используется для перевода устройства в конфигурационный режим, о котором ниже.
  • Переключатель на GPIO4, который в результате не использовался. Он был добавлен просто на всякий случай, потому что у меня были лишь сдвоенные переключатели.

Как уже говорилось ранее, для измерения температуры и влажности будем использовать датчик DHT22. Можно также использовать DHT11. Это довольно популярные датчики, и MicroPython любезно умеет работать с ними. Вот так выглядит DHT22, если кто-то еще не видел:

DHT22 датчик

Так все выглядело в результате:

ESP8266 м датчик DHT22

Запуск Wi-Fi точки доступа на ESP8266

С железной частью мы разобрались, перейдем к программной. Весь код лежит на GitHub:

https://github.com/artem-smotrakov/yellow-duck

git clone https://github.com/artem-smotrakov/yellow-duck

Так как мы собираемся отсылать температуру и влажность на ThingSpeak, нам надо подключить нашу ESP8266 к существующей (скажем, домашней) Wi-Fi сети для доступа в интернеты. Для этого нашей ESP8266 надо знать SSID и пароль к Wi-Fi сети. Вот так можно подключиться к Wi-Fi сети с помощью MicroPython:

import network
nic = network.WLAN(network.STA_IF)
nic.active(True)
nic.connect(ssid, password)

Но это не совсем хорошо и удобно, когда мы прописали пароли-явки прямо в код. Если SSID и пароль изменятся, то надо надо будет поправить исходники, а потом залить их опять на устройство. Вместо прописывания паролей и явок прямо в коде мы может сделать следующее:

  • Добавить на пин GPIO5 переключатель в конфигурационный режим.
  • При старте устройство проверяет, находится ли оно в конфигурационном режиме (функция is_config_mode).
  • Если включен конфигурационный режим, то устройство поднимает Wi-Fi точку доступа и стартует локальный web-сервер (функции start_access_point и start_local_server).
  • Когда пользователь подключается к этой точке доступа, web-сервер предлагает ему ввести SSID и пароль от Wi-Fi сети, которая должна использоваться в обычном режиме.
  • После того, как пользователь введет SSID и пароль, web-сервер сохраняет их в конфигурационном файле и перезагружает устройство (функции write_wifi_config и reboot).
  • До перезагрузки, пользователь должен переключить устройство из конфигурационного режима в обычный.
  • После перезагрузки устройство подключается к Wi-Fi сети, SSID и пароль которой был указан (функция connect_to_wifi).
  • В случае успешного подключения зажигается светодиод LD1 (функция turn_on_wifi_led).

Таким образом, если мы захотим использовать устройство с другими Wi-Fi сетями, или просто поменялся пароль, нам не надо будет заливать поправленные исходники.

После успешного подключения к Wi-Fi устройство начинает героически измерять температуру и влажность с определенным интервалом:

while True:
    current_time = time.time()
    if current_time - last_mesurement_time > MESUREMENT_INTERVAL:
        mesure_temperature_and_humidity()
        last_mesurement_time = current_time
    time.sleep(DELAY)

Как уже упоминалось ранее, MicroPython поддерживает как DHT22, так и DHT11. Вот как мы используем функцию dht.DHT22 для измерения нужных нам характеристик агрессивной окружающей среды:

def mesure_temperature_and_humidity():
    import dht
    import machine
    d = dht.DHT22(machine.Pin(DHT22_PIN))
    d.measure()
    t = d.temperature()
    h = d.humidity()
    print('temperature = %.2f' % t)
    print('humidity = %.2f' % h)

Пока вроде бы довольно просто. Дальше нам надо отправить ценные данные в интернеты. Данные эти будем отправлять на ThingSpeak, который любезно и безвозмездно предлагает зарегистрироваться, чтобы потом можно было туда отсылать всякие важные данные вроде температуры и влажности воздуха, и более того, анализировать эти самые данные и даже рисовать по ним картинки. ThingSpeak для этих целей предоставляет RestFUL API для IoT устройств. Сначала регистрируемся. Дальше надо создать канал. Потом для этого канала получаем API-ключ, который будет использоваться устройством для отправки данных в этот канал. Не забываем включить два поля в нашем канале: одно для температуры, другое для влажности.

Настройки канала в ThingSpeak

Вот так мы отправляем данные в ThingSpeak:

global THINGSPEAK_WRITE_KEY
    if not THINGSPEAK_WRITE_KEY:
        print('not ThingSpeak key specified, skip sending data')
        return

    print('send data to ThingSpeak')
    s = socket.socket()
    ai = socket.getaddrinfo(API_THINGSPEAK_HOST, API_THINGSPEAK_PORT)
    addr = ai[0][-1]
    s.connect(addr)
    s = ssl.wrap_socket(s)
    data = 'field1=%.2f&field2=%.2f' % (t, h)
    http_data = THINGSPEAK_POST_TEMPLATE % (THINGSPEAK_WRITE_KEY, len(data), data)
    s.write(http_data.encode())
    s.close()

Здесь у нас возникает та же самая проблема, что и с SSID и паролем от Wi-Fi. Нам надо как-то рассказать устройству о API ключе, который оно должно использовать. Решение точно такое же: устройство предлагает указать API-ключ в конфигурационном режиме.

Как можно заметить, мы используем TLS, о чем говорит вызов функции ssl.wrap_socket, который заворачивает обычный socket в TLS socket. Признаться, я был немножко, но приятно удивлен, когда обнаружил, что MicroPython для ESP8266 умеет работать с TLS. Но есть один нюанс. Даже если TLS и используется, MicroPython на ESP8266 не поддерживает проверку серверного сертификата. (во всяком случае, версия 1.8.7 это не поддерживает). Это означает, что мы в относительной безопасности, пока злобные злоумышленники могут просто читать наши зашифрованные сообщения в рамках TLS-соединения. Расшифровать эти сообщения будет немного проблематично (но если во благо времени, то в общем случае это все равно возможно). Но вот если хитрые злоумышленники могут модифицировать передаваемые данные, то это уже беда, потому что они могут запросто подменить сертификат сервера с заранее известными ключами, и в результате они смогут спокойно расшифровать все наши сообщения.

Внимательный читатель кода мог заметить разные вызовы функции print. Это просто отладочная информация. Можно подсоединиться к ESP8266 через USB-Serial адаптер и увидеть эти самые отладочные сообщения.

Визуализация данных на ThingSpeak

Если все прошло гладко, то устройство начнет отсылать данные на ThingSpeak. Дальше ThingSpeak великодушно предоставляет нам разные способы визуализации наших важных данных. И даже более того, ThingSpeak щедро позволяет нам анализировать эти данные с помощью MatLab. Самое простое, что приходит в голову, это нарисовать график:

Эти графики показывают температуру и влажность в моей комнате. Вот и канал на ThingSpeak, который целиком и полностью посвящен этим важным показателям:

https://thingspeak.com/channels/230189

Ссылки