Esp8266 web server using spiffs (spi flash file system)

Регистрация на сервере ThingSpeak

MQTT это конечно хорошо. Это просто и удобно. Но MQTT обладает одним небольшим недостатком – на MQTT брокере сообщения либо вообще не хранятся, либо хранится только последнее опубликованное сообщение (в случае, если оно retained). И если нам хочется посмотреть график изменения температуры в течение, скажем, суток, то придется все эти сутки держать запущенным клиент MQTT на смартфоне, а он любит кушать много энергии от батареи. А уж посмотреть данные за прошедшие сутки вообще нет никакой возможности. Но выход есть – можно параллельно отправлять данные на другой сервер – ThingSpeak, он будет накапливать Ваши данные и затем отображать их в виде графиков за любой период. Для работы с ThingSpeak не потребуется никаких дополнительных библиотек, он работает через REST API.

1. Переходим по адресу thingspeak.com.

2. Нажимаем кнопку “Get Started For Free”:

3. Указываем адрес электронной почты, выбираем страну:

4. Подтверждаем, что указанный адрес используется и для MatLab:

5. Дожидаемся письма на почту, подтверждаем учетную запись, нажимаем “Continue”:

6. Вводим имя профиля и придумываем пароль:

7. Регистрация завершена, можно создавать каналы. Каналов потребуется столько, сколько у нас датчиков, то есть как минимум четыре. Для создания канал нажмите “New Channel”:

8. Вводим название канала и список полей, в которые будут поступать данные. Можно использовать до 8 полей:

9. После сохранения канала попадаем в “приватный просмотр” данных канала, где и данных-то пока нет. Переходим во вкладку “API Keys”:

10. Здесь нам понадобится Write API Key – его нужно указать в скетче. Read API Key понадобится при настройке виджетов на смартфоне для отображения данных. Сохраним эти данные куда-нибудь.

Повторяем шаги 7-10 пока не будет добавлено нужное количество каналов. В бесплатном режиме ThingSpeak сейчас допускает не более 4 каналов на аккаунт, но можно создать несколько аккаунтов. Для датчиков BME280 нужно будет указать дополнительные поля для хранения данных об атмосферном давлении.

После того, как данные начнут поступать в каналы, их можно будет удобно просматривать либо на самом ThingSpeak, либо с помощью API на любом другом сайте: ravsoft2004.narod.ru

Что для этого нужно

  1. Время. При наличии под руками всех компонентов, на реализацию Вы затратите от 30 минут до 1 часа своего драгоценного времени;
  2. Arduino, я в этом примере буду использовать Uno, но подойдет и Mega и Mini (я брал здесь);
  3. ESP8266, я использовал самую дешевую версию – 01 (я брал здесь), но подойдет любая с дефолтной прошивкой (поддержка AT-команд);
  4. Датчик температуры DS18B20 (я брал здесь), а лучше пару штук;
  5. Резистор 4,7кОм – 1 шт;
  6. Резистор 1кОм;
  7. Резистор 2кОм.

(Пункты 6 и 7 для тех, кто любит что бы все было по Фен-шую, у меня работало и без них, но как мне показалось – больше греется ESP) Наличие зоны покрытия WiFi-маршрутизатора.

Если заказать детали в Китайском экспресс — это обойдется Вам порядка 500 руб., если пойти в ближайший магазин радиодеталей – то в зависимости от карманного коэффициента магазина: 800-1000 руб.

ESP8266 Webserver Init

I modified init.lua slightly to give you a function to stop the
webserver after power up (there’s a 3 second window to allow this —
and no obvious way to stop it).

Copy Sketch

—nodemcu_test_startup
— load credentials, ‘SSID’ and ‘PASSWORD’ declared and initialize in there
dofile(«credentials.lua»)dofile(«LEDBlinkn.lua»)functionstartup()iffile.open(«init.lua»)==nilthenprint(«init.lua deleted or renamed»)elseprint(«Running»)file.close(«init.lua»)LEDBlinkStop()file.close(«LEDBlinkn.lua»)— the actual application is stored in ‘application.lua’
dofile(«application.lua»)endend— Define WiFi station event callbacks
wifi_connect_event=function(T)print(«Connection to AP(«..T.SSID..») established!»)print(«Waiting for IP address…»)ifdisconnect_ct~=nilthendisconnect_ct=nilendLEDBlinkN(1,100,200)— faster blinks
endwifi_got_ip_event=function(T)— Note: Having an IP address does not mean there is internet access!
— Internet connectivity can be determined with net.dns.resolve().
print(«Wifi connection is ready! IP address is: «..T.IP)print(«Startup will resume momentarily, you have 3 seconds to abort.»)print(«Waiting…»)startUpTimer=tmr.create()— JFM mod to allow abort
startUpTimeralarm(3000,tmr.ALARM_SINGLE,startup)LEDBlinkN(3,50,550)— fast warning 3, delay
endfunctionstopWiFi()— JFM
LEDBlinkStop()startUpTimerstop()startUpTimerunregister()endwifi_disconnect_event=function(T)LEDBlinkN(2,100,700)— double flash with delay = error
ifT.reason==wifi.eventmon.reason.ASSOC_LEAVEthen—the station has disassociated from a previously connected AP
returnend— total_tries: how many times the station will attempt to connect to the AP. Should consider AP reboot duration.
localtotal_tries=75print(«\nWiFi connection to AP(«..T.SSID..») has failed!»)—There are many possible disconnect reasons, the following iterates through
—the list and returns the string corresponding to the disconnect reason.
forkey,valinpairs(wifi.eventmon.reason)doifval==T.reasonthenprint(«Disconnect reason: «..val..»(«..key..»)»)breakendendifdisconnect_ct==nilthendisconnect_ct=1elsedisconnect_ct=disconnect_ct+1endifdisconnect_ct<total_triesthenprint(«Retrying connection…(attempt «..(disconnect_ct+1)..» of «..total_tries..»)»)elsewifi.sta.disconnect()print(«Aborting connection to AP!»)disconnect_ct=nilendend— Register WiFi Station event callbacks
wifi.eventmon.register(wifi.eventmon.STA_CONNECTED,wifi_connect_event)wifi.eventmon.register(wifi.eventmon.STA_GOT_IP,wifi_got_ip_event)wifi.eventmon.register(wifi.eventmon.STA_DISCONNECTED,wifi_disconnect_event)LEDBlinkN(1,200,400)— Idle
print(«Connecting to WiFi access point…»)wifi.setmode(wifi.STATION)wifi.sta.config({ssid=SSID,pwd=PASSWORD})— wifi.sta.connect() not necessary because config() uses auto-connect=true by default

Save the above code as init.luaThe above code is a very good example of event driven programming (source here)

The LEDBlinkN() functions display WiFI connection status using the
builtin LED. In addition you can use the function stopWiFi() during the 3
second delay period to halt init.lua. You can also erase the init.lua
file from the ESP8266 to do the same (using
the ESPlorer interface) except blinking LEDs will keep blinking.

The other useful thing about the above code is that it will tell you
why a connection failed so you get a lot of information from it sent to the serial terminal.

Show Index<<< Back to Lua Examples
×
                  


Privacy Policy
| Contact
| About MeSite Map
| Terms of Use

The web server

Let’s get to the Arduino code. If you type just esp8266.local in the browser’s address bar, the initial connection attempt will be made over HTTP (port 80). This means that if you only have the HTTPS server running (port 443) you’ll get a connection refused over HTTP. Since this is not user friendly, we’ll run two servers on ESP8266, one over HTTP which will send 301 headers pointing to the HTTPS one. Redirection is instant.

The key and certificate must be pasted into the sketch:

 
 
 
 

    
    
    

 
 

      
    


       
    

In function, before configuring the servers, ESP8266 must know the current date and time from a NTP server. That’s easy since we have function which takes as first parameter the GMT offset in seconds. After getting the time, we can start the HTTP server and configure it to handle requests by responding with the redirection header. Lastly, we configure HTTPS server with key and certificate and turn it on.

  
   
  

    
    
    
  

       

   
  

     
   
  
  
  

In we make sure both servers handle requests.

HTTPS redirection routine is simple. However, no matter of you reach the server by the multicast DNS name or by its IP, this function will point to the mDNS name and that could be an issue for clients that do not support mDNS. I could have sent the local IP in the redirection header, but that would raise other certificate errors. Since ESP8266 is a client in a DHCP enabled network, it gets an IP from a router. And since I can’t know what is that IP in advance, I can’t generate a certificate with that IP in SAN field or CN attribute.

Server’s answer is managed by function. LED status is changed using HTTP GET method.

The server page viewed in Google Chrome

No errors in Chrome

There is a way to get rid of the «Not secure» error in Google Chrome. First of all you must use 1024 bits key since 512 is considered weak.

The certificate must be imported into the system’s (browser’s) trusted list. On Linux you can go straight to chrome://settings/certificates, the Authorities tab. On Windows operating systems, go to Settings — Advanced — Manage Certificates and select Trusted Root Certification Authorities tab. Click the Import button and select your generated cert.txt file (select all files type in the open dialog to see it). Import it and give it trust for site identification. On Windows, after import, find and select it in the list, then click Advanced. Check Client Authentication. Close the browser and reopen it to see the changes. In Windows, the certificate installation is system wide.

Check site security (Chrome — F12)

Create Project

Select the «Initialize new PlatformIO project» button and create a new project. This option is also available in the PlatformIO main menu.

On the popup, select the board and the directory to place your project. Since we’re using a NodeMcu dev kit, select from the dropdown. As you can see, PlatformIO supports a wide variety of boards. Once you’ve got the options selected, click «Initialize». This will take a while the first time as PlatformIO downloads and installs the correct tools for your board. Once it’s done, you’ll see some automatically generated files.

We’re now ready to write some code.

Создание Azure-функции для генерации SAS

В качестве онлайн-сервиса проще всего использовать Azure-функции. Это своеобразные сниппеты, которые можно писать сразу на портале Azure в браузере. Шутки шутками, но таким образом программировать можно даже со смартфона. Конечно, никто не запрещает создавать и отлаживать их и из Visual Studio и только потом публиковать в Azure уже в откомпилированном виде. Задача функции — выполнить какую-то, как правило, не особо сложную операцию. По микросервисной задумке, каждая функция умеет делать что-то одно, но зато очень хорошо (принцип Single responsibility).

Создать Azure Function App можно на портале, заполнив небольшую анкету.

Создание Azure-функции

Consumption Plan позволяет платить только за те вызовы функции, которые были совершены. Это самый недорогой вариант. На данный момент миллион вызовов функции дается бесплатно. Заметь, что вместе с функцией создается и вспомогательное хранилище данных (Storage).

После создания Function App можно создать и саму функцию. В данном случае нам нужна функция типа Webhook + API. Функция может быть открыта всем (анонимный доступ), а может быть доступна только обладателям особого кода. Код можно получить из окна работы с функцией, нажав на ссылку .

Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку!
Подробнее

Вариант 2. Открой один материал

Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя!
Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.

Я уже участник «Xakep.ru»

Testing the code

To test the code we just need to open our browser and make an HTTP request to the IP of the ESP8266, on a path we defined early. The format is shown bellow:

Since, as stated before, we are listening on the 80 port, the browser will assume it by default, so we don’t need to specify it:

So, we substitute the serverIP by the IP printed on the serial console, and we make a request as shown in figure 1.

Figure 1 – HTTP request via browser on the root path (Google Chrome).

In this case, only the IP is shown because the browser removed the “/” from the root path. Also, the http:// was removed by the browser. Although some browsers perform the request when we only specify the IP, others assume that we want to search something in a search engine. So, the safest way is to always specify the http:// before the IP.

The example from figure 2 shows a request on the path “/other” that we also defined.

Figure 2 – HTTP request via browser on the “/other” path (Firefox).

Finally, note that if we specify a path not defined, the ESP will return a message indicating that the resource was not found, as we can see in figure 3, where we sent an HTTP request to the path “/notdefined”.

Figure 3 – HTTP request via browser on a path not defined.

Important: The IP that will be printed by the ESP8266 will be its private IP on the network. It won’t be possible for a client outside the network to contact it on that IP (and thus, the URL will not work). In order for a client to be able to contact the ESP8266 from outside its network, it would need to use the external IP of the network and the router would need to be configured to forward the requests on its public IP for that port to the private IP of the ESP8266. Since port forwarding depends on the router used, explaining how to do it is outside of the scope of this post.

Programming Languages and Tools

There are mainly four options: Lua, MycroPython, c++ toolchain, and Arduino programming language (similar to c/c++). In this tutorial will be using Arduino programming language since it is powerful, easy to learn and all the programming and deploying tasks can be performed in the Arduino Integrated Development Environment (IDE). For Lua programming there are also some IDEs, such as ESplorer. General purpose IDEs can be used for deploying MycroPython programs to NodeMCU, such as the Pymakr Atom Package for Atom. Programming using the c++ toolchain is commonly done from the Command-Line Interface (CLI).

Регистрация на MQTT брокере

Чтобы создаваемое устройство могло отправлять данные конечным “потребителям”, ему нужен “посредник” в интернете. Можно, конечно, создать на ESP микро-web-сервер и подключаться к нему напрямую через браузер. Но какое в этом удовольствие – ведь данные можно будет увидеть только в локальной сети, а мне требовался удаленный контроль, причем “за NAT-ом и 4G-модемом”. В случае MQTT таким посредником является MQTT-брокер. MQTT-брокер “принимает” данные от устройств, которые их публикуют, и рассылает клиентам, которые на них подписались.

Предупреждение: на текущий момент на cloudmqtt.com больше нет бесплатных тарифов. С другими возможными серверами Вы можете ознакомиться в другой статье. Либо поднять свой личный MQTT сервер (на роутере Keenetic, например) и настроить мост на один из публичных.

Для себя я выбрал сервис CloudMQTT.com. Просто потому, что в сети куча примеров как это сделать. На бесплатном тарифном плане “Cute Cat” сейчас можно подключать к каждому виртуальному экземпляру брокера (instance) до 5 клиентов одновременно (раньше было 10, судя по скриншотам в интернете). Количество топиков при этом не ограничено. Пять подключений – это много или мало? Ну вот у меня например: данное устройство в гараже – это раз. Второе будет стоять в доме и контролировать доступ в сеть, при необходимости перезагружать CPE210 с роутером и выполнять авторизацию через SMS – это два. Клиент для управления на смартфоне – это три. В принципе, достаточно. Но! Зашел посмотреть данные с компьютера – сразу появилось еще подключение. А если нужно смотреть данные не с одного телефона, а с нескольких? Или выводить данные на LCD-дисплей где-то еще – то пяти подключений не хватит однозначно. Впоследствии пришлось перенастроить устройства на другой облачный брокер, который не так удобен, но зато позволяет бесплатно подключать до 100 клиентов. Но для примера нам вполне достаточно и CloudMQTT.com.

Итак, регистрируемся на сервисе CloudMQTT.com, подтверждаем учетную запись через письмо, которое придет к Вам на почту. Сразу после входа мы попадем в список “List all instances“, который сейчас пуст. Нажимаем зеленую кнопку “+ Create New Instance“, заполняем название экземпляра брокера, выбираем тарифный план и задаем метку. Метки ни на что не влияют, а служат только для группировки списка созданных экземпляров и упрощения навигации.

После этого Вам будет предложено выбрать датацентр, где будет физически расположен Ваш виртуальный сервер. Для бесплатного плана их всего два: в США и в Европе, остальные не доступны:

Подтверждаем выбор и… в общем-то все. Конфигурировать ничего не нужно – этот шаг доступен только на платных тарифных планах. Останется только подтвердить создание экземпляра. После подтверждения он появляется списке. Нажимаем на ссылку – название:

Вот здесь на нужны имя сервера и порт подключения к нему (открытый или через SSL):

Имя пользователя и пароль, которые указаны на этой странице лучше не использовать в скетче. Для “клиентов” создадим другого пользователя (а можно и не одного). Для этого нажимаем меню “USERS & ACL“, вводим желаемое имя пользователя и пароль, добавляем пользователя в список. Вот это имя и пароль мы и будем использовать в скетче в дальнейшем. А также и в мобильных клиентах на смартфоне при просмотре данных из экземпляра. Можно настроить разных пользователей для записи в топики с устройства и для чтения данных на смартфоне.

Затем внизу страницы выбираем режим “Pattern” (сразу для всех пользователей) либо “Topic” (только для выбранного пользователя), указываем шаблон имен топиков, на которые нужно задать права доступа, выбираем собственно права (только чтение, только запись, либо и чтение и запись).

Все, предварительные настройки выполнены.

Структура проекта

Проект состоит из следующих файлов:

Файл Назначение
WaterpoolManager.ino Объявление основных переменных и констант. Инициализация. Главный цикл.
HeaterMainLogic.ino Основная логика управления реле котла (по температурам) и вспомогательными реле.
Sensors.ino Считывание данных сенсоров
Settings.ino Настройки устройства, сохранение их в флеш-памяти контроллера
LCD.ino Вывод информации на LCD
ClockTimer.ino Считывание показаний часов RTC, или симуляция часов
Relays.ino Управление включением/выключением реле
ButtonLogic.ino Логика реакции на состояния аппаратных кнопок
ReadButtonStates.ino Считывание состояний аппаратных кнопок
EEPROM_Logging.ino Логгирование данных датчиков в EEPROM
WebServer.ino Встроенный веб-сервер для управления устройством и отображением состояний
WebPages В этой папке хранятся страницы веб-сервера
index.h Основная страница отображения состояния устройства. Идет считывание текущего состояния с помощью вызова ajax. Refresh каждые 5 секунд.
loggraph.h Выводит лог данных датчиков и состояний реле в виде графика. Используется библиотека jqPlot – все построение происходит на стороне клиента. Запрос к контроллеру идет лишь на бинарный файл – копии данных из EEPROM.
logtable.h тоже, но в виде таблицы
settings.h Управление настройками устройства: установка пределов по температурам, потоку воды, периодичности логгирования данных
time.h Установка текущего времени
Библиотеки
EepromLogger.cpp Библиотека записи логов во флеш
EepromLogger.h
crc8.cpp Подсчет 8-битного CRC для библиотеки
crc8.h
TimeSpan.cpp Структура для управления отрезками времени
TimeSpan.h

Managing Libraries

The Arduino IDE has many useful libraries that you can use in your sketches. Go to Tools -> Manage Libraries to search, install and update your libraries.

Arduino IDE – Library manager

If you want to use a library in your sketch, select it in Sketch -> Include Library. This action will include the library header files references in your sketch. For example, including the ESP8266WiFi library will add the following header file references. You can keep only those you need.

#include <BearSSLHelpers.h>
#include <ESP8266WiFiType.h>
#include <WiFiClientSecureAxTLS.h>
#include <WiFiUdp.h>
#include <ESP8266WiFiGeneric.h>
#include <WiFiServerSecureBearSSL.h>
#include <ESP8266WiFi.h>
#include <CertStoreBearSSL.h>
#include <WiFiClient.h>
#include <WiFiServerSecure.h>
#include <WiFiClientSecure.h>
#include <ESP8266WiFiSTA.h>
#include <WiFiServerSecureAxTLS.h>
#include <WiFiClientSecureBearSSL.h>
#include <WiFiServer.h>
#include <ESP8266WiFiScan.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266WiFiAP.h>

You can also use libraries in your sketches that are not available in the Arduino library manager. They must be in ZIP format. You can use import them in Sketch -> Include Library -> Add .ZIP Library.

ESP8266 Operating Modes

One of the greatest features ESP8266 provides is that it cannot only connect to an existing WiFi network and act as a Web Server, but it can also set up a network of its own, allowing other devices to connect directly to it and access web pages. This is possible because ESP8266 can operate in three different modes: Station mode, Soft Access Point mode, and both at the same time. This provides possibility of building mesh networks.

Station (STA) Mode

The ESP8266 that connects to an existing WiFi network (one created by your wireless router) is called Station (STA)

In STA mode ESP8266 gets IP from wireless router to which it is connected. With this IP address, it can set up a web server and deliver web pages to all connected devices under existing WiFi network.

Soft Access Point (AP) Mode

The ESP8266 that creates its own WiFi network and acts as a hub (Just like WiFi router) for one or more stations is called Access Point (AP). Unlike WiFi router, it does not have interface to a wired network. So, such mode of operation is called Soft Access Point (soft-AP). Also the maximum number of stations that can connect to it is limited to five.

In AP mode ESP8266 creates a new WiFi network and sets SSID (Name of the network) and IP address to it. With this IP address, it can deliver web pages to all connected devices under its own network.

Prerequisites

Before proceeding with this project, make sure you check all the following prerequisites.

1. Install ESP8266 Board in Arduino IDE

We’ll program the ESP8266 using Arduino IDE, so you must have the ESP8266 add-on installed. Follow the next tutorial to install it:

2. Filesystem Uploader Plugin

To upload files to the ESP8266 SPI Flash Filesystem (SPIFFS), we’ll use the Filesystem Uploader Plugin. Install the plugin in your Arduino IDE:

Installing the ESPAsyncWebServer library

This library is not available to download through the Arduino IDE libraries manager. So, you need to follow the next steps to install the library:

  1. Click here to download the ESPAsyncWebServer library. You should have a .zip folder in your Downloads folder
  2. Unzip the .zip folder and you should get ESPAsyncWebServer-master folder
  3. Rename your folder from ESPAsyncWebServer-master to ESPAsyncWebServer
  4. Move the ESPAsyncWebServer folder to your Arduino IDE installation libraries folder

Alternatively, you can go to Sketch > Include Library > .zip Library and select the previously downloaded library.

Installing the ESPAsyncTCP

The ESPAsyncWebServer library also needs the ESPAsyncTCP library to operate properly. Follow the next steps to install the ESPAsyncTCP library:

  1. Click here to download the ESPAsyncTCP library. You should have a .zip folder in your Downloads folder
  2. Unzip the .zip folder and you should get ESPAsyncTCP-master folder
  3. Rename your folder from ESPAsyncTCP-master to ESPAsyncTCP
  4. Move the ESPAsyncTCP folder to your Arduino IDE installation libraries folder
  5. Finally, re-open your Arduino IDE

Alternatively, you can go to Sketch > Include Library > .zip Library and select the previously downloaded library.

Installing BME280 libraries

In this tutorial, we’ll display readings from a BME280 sensor (Guide with ESP8266). You need to install the following libraries:

You can install these libraries through the Arduino IDE Libraries Manager. Go to Sketch > Include Libraries > Manage Libraries. Then, search for the libraries’ name to install them.

Рейтинг
( Пока оценок нет )
Editor
Editor/ автор статьи

Давно интересуюсь темой. Мне нравится писать о том, в чём разбираюсь.

Понравилась статья? Поделиться с друзьями:
Семинар по технике
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: