Фреймворк LCE на чипе ESP8266
2
Как настроить устройство?
Если у вас есть устройство этой системы, необходимо сделать следующее:
1. Включить девайс и услышать звуковые сигналы.
2. Найти WiFi сетку вида ESP-cf8e5e, которую устройство создает само от безысходности и отсутствия доступа к интернету.
3. Необходимо залогиниться в эту сеть и открыть любой сайт не https, а лучше не париться (не на всей мобильниках почему-то работает dns), а сразу открывать титул чипа по адресу http://192.168.4.1
4. Чтобы стать админом, надо увидеть в верхнем правом углу экрана желтый кружок, ткнуть туда и набрать пароль. Если вы не меняли пароль (в config.txt), то по умолчанию он «gluki»
5. Далее следует кнопкой WiFIscan найти нужную сеть и залогиниться в нее. Связь при этом пропадет, но чип перезагрузится и войдет в сеть, о чем сообщит, высвистывая последние цифры IP. Если по какой-то причине (бывает из-за устаревшей версии) не получается это сделать кнопкой, откройте файл-менеджер чипа Files и там впишите логин и на следующей строчке пароль в файл /wifi_last.txt (втрой перенос строки не делайте).
6. После входа в сеть чип пойдет обновлять файлы и прошивку. Это займет какое-то время, может минут 5, не выключайте устройство! Выключение во время обновления прошивки может его убить и спасет только программатор.
7. Далее вы можете работать с устройством.
ЖЕЛЕЗО ESP8266
Если у вас нет устройства? Вы можете его легко сделать. Нужен чип ESP8266 на плате с USB-слотом, например NodeMCU или D1 mini (фото ниже). Я использую программатор, потом из него чипы вынимаются и сразу паяются куда надо. Так или иначе, чтобы не морочиться с программными системами, можно просто соединить чип кабелем OTG со смартфоном, установить туда приложение ESP8266 Loader и залить готовый бинарник. Относительно последняя версия бинарника лежит здесь: http://lleo.me/ESP8266/firmware/firmware.bin Если вам интересны исходники, то относительно свежие здесь: http://lleo.me/ESP8266/CFAQ.zip
Чип имеет 15 полноценных GPIO выходов, но 6 из них (нижние) заняты микросхемой flash памяти и никоим образом их использовать нельзя. Для использования рекомендуются: 4, 5, 12, 13, 14, имеют ограничения: 0,1,2,3,15.
GPIO 0 — FLASH, не должен быть подтянут к минусу при старте, иначе модуль перейдет в режим программирования до следующего включения
GPIO 1 — TXD
GPIO 2 — blink.pin — LED, лампочка, если нужны дополнительные светодиоды, рекомендую их вешать сюда
GPIO 3 — RXD, sound.pin — рекомендую вешать сюда пьезодинамик
GPIO 4 — poliv.pin — включение мотора полива или реле в моей системе (SDA-SS для NFC)
GPIO 5 — act.pin — включение всего остального, например дополнительного реле в моей системе (RST для NFC)
GPIO 12 — не задействован, также SPI:MISO.
GPIO 13 — не задействован, также RXD2 или SPI:MOSI.
GPIO 14 — не задействован, также SPI:SCK.
GPIO 15 — в момент старта должен подтянут к минусу через резистор 10к или напрямую, как у меня. Также это TXD2, если переключить. Или SPI:CS.
GPIO 16 — только на OUTPUT (или для пробуждения, если подключить к RESET)
Вариант готовой платы D1-mini
Вариант готовой платы Node-MCU
Если у вас вопросы по делу, пишите мне, с удовольствием отвечу.
Если вопросы не по делу, если вы попали сюда случайно и у вас острое недоумение, что это, и зачем вам нужно, то вам это точно не нужно. Это не публичный проект, он сделан для решения своих задач, а также по рабочим надобностям и по ТЗ, которое формулировали явно не вы и не для своей сферы применения. Вы можете использовать эту систему для личных нужд, но вас точно никто не уговаривал это делать.
Ниже подробное описание системы.
Задачи, решаемые при помощи чипа ESP628, имеют свои особенности. Чаще всего здесь не требуется мощное программирование, а нужно лишь отвечать на сигналы и производить несложные действия с довольно узким кругом оборудования, но по достаточно сложным сценариям, требующим многочисленных ветвлений, условий, циклов и четкого планирования событий по времени.
Концепция данной системы состоит в том, чтобы максимально облегчить работу с чипом, исключив программирование бинарника вообще. Бинарник может со временем усовершенствоваться и автоматически обновляться (эти инструменты, разумеется, есть в системе), но он всегда один для всех задач. Сами же задачи выполняются при помощи неограниченного количества текстовых файлов-скриптов, которые хранятся во флеш-памяти чипа, относительно безграничной для таких скриптов.
Также система включает в себя элементы админки: программировать чип, меняя скрипты, можно прямо в браузере на страницах, которые предоставляет сам чип, являющийся веб-сайтом.
Язык скриптов, которого потребовала эта задача, максимально прост и достаточно примитивен. На сегодняшний день, помимо обращений к внутреннему и внешнему оборудованию и различным сервисным протоколам (GET, MQTT, MODBUS/TCP), он позволяет делать разнообразные ветвления, осуществлять совсем простые математические вычисления, активно обрабатывать файлы внутренней флешки и управлять многочисленными таймерами. Он чем-то похож на C, но главная его задача — ставить системе задачи и получать ответы, поэтому я называю этот язык CFAQ.
ОСНОВЫ ЯЗЫКА СИФАК
Основой языка является строка, где через ОДИН ПРОБЕЛ (это важно) перечислены команды и операторы. Повторю: язык очень чувствителен к пробелам. В начале строки может стоять сколько угодно пробелов и табуляций. Все, что идет после знака #, считается комментарием и отбрасывается.
Исполняемые скрипты могут приходить несколькими разными путями:
1. В строке GET-запроса: http://192.168.4.1/MOTO?pinmode%204%20OUTPUT|echo%20{gpioA0}
2. В POST-запросе AJAX на http://192.168.4.1/ Например, так работает окно консоли на титульной странице админки.
3. В тексте, переданном внешним сайтом в ответ на запроса к нему командой ping
Разумеется, запросы GET и POST сработают только при наличии авторизации в куках. Пароль устанавливается в config.txt, по умолчанию пароль «gluki»
Если строка скрипта не распознана, она считается именем файла скрипта, и этот файл вызывается на исполнение. Если и файл такой не найден, система пропускает эту строку. Ошибки при этом подавляются (почему так — отдельная долгая дискуссия, но пока нужно было именно так). Любое имя файла является скриптом, файл открывается и запускается на исполнение. В начале имени файла может для понятности стоять /, а может и нет. Например, /SCRIPT.TXT и MOTOR-START — это всё имена скриптов, лишь бы файл с таким именем был среди файлов во флеш-памяти.
Команды условных ветвлений if и else используют либо строку, либо область действия, которая заключается в фигурных скобки.
Основным скриптом, исполняемым однократно при старте, является /config.txt в нем прописываются нужные настройки, задаются циклы и отложенные задачи, необходимые на первое время. Здесь особенное значение представляет команда loopfile — она позволяет задать скрипт, который будет, в отличие от таймеров, исполняться постоянно с наивысшей скоростью и приоритетом. Хороший пример такого скрипта — «плавное дыхание» светодиода если есть интернет, или мигание, когда интернета нет.
Теперь, когда мы уже немного понимаем, как работает язык, приступим к подробному описанию всех его команд. Начнем с самого простого:
РАБОТА С GPIO
Логи в консоли
ESP выводит информацию в uart. Как минимум, при старте — это свойство чипа, с котоым ничего поделать нельзя. Если нужно, чтобы в uart никогда ничего не летело, имеет смысл использовать альтернативные пины uart (TX=15,RX=13 вместо 1 и 3), переключив на них вывод командой «SERIAL.swap 1» Так можно избежать в консоли мусора при старте, но в новую консоль все равно будет сыпаться информация во время работы чипа и процедур фреймворка. И вот её можно регулировать все сразу (ALL) или по группам. Группы логов:
ALL — вообще все логи сразу |
АРИФМЕТИКА И ОПЕРАТОРЫ ПРИСВАИВАНИЯ
Арифметика в нашем языке находится в зачаточном состоянии. Но её, тем не менее, вполне достаточно, чтобы выполнять несложные арифметические вычисления. Наши правила:
— Имена переменных могут быть латинскими, русскими, заглавными, строчными и неограниченной длины, и только пробел они содержать не могут.
— Вычисления можно производить только в операторе присваивания типа X = {Y} / 3 На лету арифметика не работает, нельзя написать «echo {Y} / 3»
— В строке мы перечисляем числа, имена переменных (в фигурных скобках), знаки математических операций, и всё это разделяем одним пробелом.
— В операторе присваивания = можно делать сразу несколько вычислений: X = {Y} / 3 + 1 * {K}, при этом порядок выполнения будет последовательным, без приоритета операций. Чисто физически наш интерпретатор имеет аккумулятор, значение которого в конце присвоит переменной, и двигается вперед по строке, производя с аккумулятором всё новые действия.
— У нас нет скобок. Извините за временные неудобства.
— Все незаданные пока переменные считаются пустыми строками, поэтому если их использует арифметика, то это будет 0.
— Все вычисления в ESP производятся с типом double (4 байта, фиксированная точка — 2 знака после запятой). Я точно не помню параметры, но можно оперировать достаточно громадными числами, не боясь вылезти за рамки. Плавающей точки нет — точка фиксированная: ровно два знака после запятой. «X = 3.1415925 ; echo {X}» даст 3.14 В принципе, этой точности нам должно хватать.
ОПЕРАТОРЫ ПРИСВАИВАНИЯ
# примеры простых и сложных присваиваний
G = 9.8
Radius = 10
Тракторов-или-велосипедов = 3
X = 2 * 3.14 * {Radius} / {G}
echo результат: {X} для {Тракторов-или-велосипедов} единиц транспорта
# результат: 6.41 для 3 единиц транспорта
<?php
set Y = 10 + {LIMIT} + {X} * 10
echo результат: {Y}
# результат: 10 + {LIMIT} + {X} * 10
<?php
X ~ 2
Y ~ {X}
echo X={X} Y={Y}
# X=65533 Y=2
<?php
X unsigned -1.11111
Y unsigned 3.1415
echo X={X} Y={Y}
# X=65535 Y=3
ОПЕРАТОРЫ МАТЕМАТИКИ
ПЛАНИРОВАНИЕ ВРЕМЕНИ, ЦИКЛЫ, ЗАПУСК ЗАДАЧ
В системе можно устанавливать циклы, которые будут выполнять определенные действия через определенное количество секунд — регулярно, однократно или некоторое заданное число раз. В качестве действий указывается СТРОКА — это может быть имя файла (тогда будет исполняться он) или одна команда, или последовательность команд, разделенных ; (для команд, исполняемых по сети в GET-запросе можно также использовать разделитель |) Однако можно указать небольшой скрипт в несколько строк, разместив его в фигурных скобках, соблюдая пробелы — примерно как мы видели в примере выше с командой mainloop { ... }
loopfile { if {gpio4} == 1 blink 3 }
РАБОТА С ПЕРЕМЕННЫМИ
В нашем языке короткая конструкция в фигурных скобках без пробелов — это всегда кандидат на подстановку значения. Имя переменной должно состоять из латинских букв не менее 8 символов, обязательно содержать заглавные и строчные, цифру и хотя бы один специальный символ... Да шучу, шучу! Имя может быть любым, даже кириллицей, лишь бы не было пробелов. Но учтите, что память у чипа куцая, и чем короче имя, тем ему легче.
УСЛОВИЯ
if {gpioA0} >= 300 {
echo Ток превышен, насос перегружен!
if {gpioA0} > 800 echo Возможно, он заржавел и его вообще заело?
} else {
if {gpioA0} < 100 echo Слабая нагрузка, возможно, в колодце кончилась вода?
else echo Насос работает в штатном режиме...
}
РАБОТА С ФАЙЛОВОЙ СИСТЕМОЙ
Здесь почти все самые необходимые команды для работы не только с файлами, а также с файлами-списками и файлами-данными. В качестве данных удобно использовать формат файла, где каждая строка записана через пробел как «КЛЮЧ ЗНАЧЕНИЕ». Так можно делать небольшие ьбазы данных, например, список бесконтактных карт с именами владельцев.
<?php
FILE.save 1.txt {
0001 товары и услуги
0002 объекты и кредиты
}
РАБОТА С ПРЕРЫВАНИЯМИ ОТ GPIO
<?php
INTERRUPT.add 12 CHANGE blink {sound.pin}
РАБОТА С ВНУТЕННИМИ ФУНКЦИЯМИ ESP
РАБОТА С WIFI
— style='color:WiFi.scanDelete — Очистить результат последнего сканирования (не надо, это автоматически происходит)echo {WIFI.scan} — Вернуть список сетей одной командой (с ожиданием, устаревший способ)РАБОТА С UDP и NTP (синхронизация часов)
NTP.update (url) — Синхронизировать время по WiFi или LAN, url можно указать (по умолчанию time.nist.gov), порт всегда 123, пример:
<?php
NTP.update mysite.com
NTP.update 192.168.100.200
loop 600 NTP.updateUDP.send [url:port] [Data] — отправить пакет Data по UDP на url:port, ответ не принимать, пример:UDP.send 10.8.0.72:8313 The Text Of Packet for SendingUDP.ping [url:port] [Data] — отправить пакет Data по UDP на url:port, в ответ принять консольные команды и выполнить их процедурой MOTO(), пример:UDP.send 10.8.0.72:8313 AskUDP.get [url:port] [Data] — отправить пакет Data по UDP на url:port, в ответ принять некие данные и сохранить их в переменной UDP_result, при получении выполнить процедуру UDP_func, пример:
<?php
set UDP_result =
set UDP_func = {
if {UDP_result} = OK play D.R.M
else play mmm
}
UDP.get mysite.com:8813 Erase_allРАБОТА С MDNS
MDNS.begin [name] — Запустить сервис https://[name].local или остановить если указано пустое имя. Скажем прямо — бессмысленная вещь в реальной жизни.РАБОТА СО ЗВУКОМ
play (pin) [music] — сыграть ноты music на пине pin (если не указан, берется по умолчанию soundpin), музыка кодируется в формате гаммы: DRMFSLCdrmfslc Точка и запятая обозначают паузы длинную и короткую. Если pin не указан (в нормально написанных скриптах его не надо указывать), то используется ранее установленная переменная {sound.pin}. Важно заметить, что переменная {sound.pin.0} указывает, в какое состояние вернуть pin по окончании звучания — по умолчанию это 0, но для устройств, которые используют, например, инвертер для звука, это важно., пример:play 4 M,d,d,d,d,dd.C,C,r,r,d,C,CC.L,L,L,LS,F,MM.d,dCCC.drddd...M,d,d,d,d,dd.C,C,r,r,d,C,CC.L,L,L,LS,F,MM.d,M,M,L,CCCCCplayip (пин) — высвистеть последние три цифры полученного IP в местной сети в пине (если не указан, то soundpin)"), например для 10.9.0.203 это эквивалентно цепочке команд: repeat 2 play 4 M, ; play 4 .. ; repeat 0 play 4 L, ; play 4 .. ; repeat 3 play 4 d,, пример:{2}mp3 [файл.mp3] — Воспроизвести в эмулированном пине RX файл mp3. Увы, только очень короткие файлы можно, иначе катастрофически не хватает памяти., пример:mp3 /pes.mp3mp3stop — Остановить воспроизведение mp3, пример:mp3stopmp3web [урл]— Отключено, потому что чип, скомпилированный в Ардуине, да еще со всем остальным фреймфорком, висящим в памяти, банально не тянет., пример:mp3web http://radio.4duk.ru/4duk128.mp3РАБОТА С SERIAL
SERIAL.begin (speed) — инициализировать Serial с нужной скоростью, если не указана, то 115200 по умолчанию, пример:SERIAL.begin 9600SERIAL.end — остановить Serial, пример:SERIAL.endSERIAL.flush — очистить буффер, пример:SERIAL.flushSERIAL.swap (конфигурация) — только дял ESP8266: переключить GPIO Serial с RX=3,TX=1 (конфигурация 0) на RX=13,TX=15 (конфигурация 1) и обратно, но также можно строго указать номер конфигурации, пример:SERIAL.swap 1 # RX=13,TX=15
SERIAL.swap 0 # RX=3,TX=1
echo {SERIALSWAP} # прочитать, какой именно канал сейчас включенecho [string] — напечатать строку, пример:echo Только что пришла по Serial строка: {SERIAL}SERIAL1.begin (скорость) — Serial1.begin(115200); В отличие от Serial, в ESP12 есть Serial1, который работает только на передачу (TX) и только через GPIO2, с ним тоже реализованы команды, пример:{2}SERIAL1.flush — Serial1.flush();, пример:{2}SERIAL1.end — Serial1.end();, пример:{2}SERIAL1.setTimeout (время) — Serial1.setTimeout(t);, пример:{2}UART.init (пин RX) (пин TX) (baud) — сделать один Soft-Serial через SerialX (на ESP12 скорость до 9600), но почти на любом пине, если номер -1, то TX или соответственно RX не делать, пример:UART.init 16 17 115200 # ESP32
UART.init 4 5 9600
UART.init 14 -1 9600
echo {UART} # прочесть, что пришло, либо пустую строкуРАБОТА С СЕРВО
Старый формат:
attach [номер серво] [пин] — подключить сервопривод к gpio [пин], пример:attach 1 5detach [номер серво] — отключить сервопривод к gpio [пин], пример:detach 1go [номер серво] [градус] — повернуть сервопривод в нужное положение, пример:go 1 180Что-то я задолбался таскать с собой чужую громоздкую библиотеку, когда там всего 5 строчек кода. Вот одной командой (не забудьте выставить пину выход: pin 5 OUTPUT):
servo [пин] [градус] — повернуть сервопривод в нужное положение от 0 до 180, пример:servo 5 180Считыватель бесконтактных карт WIEGAND
WIEGAND.start [pin0] [pin1] [mode] — Активировать считыватель Wiegand. pin0 — gpio для получения 0, pin1 — gpio для получения 1, mode — битность 26 или 34, пример:WIEGAND.start 2 3 34WIEGAND.end — Отключить считыватель WIEGAND, пример:WIEGAND.end{WIEGAND} — Переменная, из которой считывается полученный код, если есть, пример:
<?php
set CARD = {WIEGAND}
if.!empty {CARD} echo Введена карта, ее номер: "{CARD}"!РАБОТА С NFC-СКАНЕРОМ БЕСКОНТАКТНЫХ КАРТ RFID-RC522
RC522.init — Активировать сканер карт RC522, подключенный как RST=GPIO5, SDA(SS)=GPIO4, MOSI=GPIO13, MISO=GPIO12, SCK=GPIO14, GND=GND, 3.3V=3.3V, пример:RC522.init{RC522.ver} — чтение байта версии в 16-ричном коде (обычно 91 или 92), пример:if {RC522.ver} != 91 {
echo Кажется, наш сканер подвис, тихонько перезапустим его
RC522.init
}{RC522.card} — чтение карты: возвращает пустое знаечние, если карта еще не была поднесена, или ее номер, если недавно была поднесена, пример:
<?php
set CARD = {RC522.card}
if.!empty {CARD} echo Введена карта, ее номер: "{CARD}"!{KEY:[filename] [key]} — Простой способ организовать элементарные базы данных (и не только для NFC-сканнера). Если в файле filename найдется строка, первое слово которой — ключ key, то вернуть значение (остальную часть строки), иначе вернуть пустое значение. ВАЖНО: при извлечении даже цифровых переменных всегда используйте оператор set. set X = {KEY:...}, а не просто X = {KEY:...}, пример:
<?php
set CARD = {RC522.card}
if.!empty {CARD} {
echo Поднесли карту номер: "{CARD}"
set NAME = {KEY:/keybasa.txt {CARD}}
if.empty {NAME} echo Ключа нет в списке доступа!
else {
echo Добро пожаловать, уважаемый {NAME}!
/DOOR_OPEN_ENGINE
}
}РАБОТА MQTT
MQTT.connect [url:port] [login] [password] — соединиться с сервером MQTT, если порт не указан, то 1883. Параметры при вызове этой процедуры также запоминаются в системных переменныхMQTT_server, — MQTT_port,MQTT.reconnect — выполнить пересоединение с MQTTMQTT.publish [topic] [string] — Публикация в топикеMQTT.subscribe [topic] — подписка на топикMQTT.unsubscribe [topic] — отписка от топикаРАБОТА MODBUS/TCP SLAVE
MODBUS.begin — запустить иницилизациюMODBUS.add [reg] (value) — создать регистр (номер от 1 до 9999), можно указать ему сразу значение для инициализацииMODBUS.save [reg] (value) — записано новое значение в созданный ранее регистр
РАБОТА C ДАТЧИКАМИ
DS18B20.begin — запустить инициализацию датчика температуры DS18B20, датчик поключают по onewire к GPIO4, и только к нему, уж извините. Схема подключения:, пример: — style='color:, пример:#0000BB'><?phpРАБОТА C АНАЛОГОВЫМ ВХОДОМ A0
calibrate [пин] [N] [имя] — Провести калибровку: рассчитать среднее арифметическое от N измерений пина (конечно он всегда A0) каждые 10 мс и сохроанить в переменную с указанным именем, пример:calibrate A0 20 SREDNEE
echo Сейчас среднее значение измерений = {SREDNEE}MOTORSTOP [N] — Установить значение внутренней переменной для срабатывания для системы контроля мгновенной остановки мотора, пример:{2}TIMER.start (ms) — Запустить таймер кольцевой записи параметров всех пинов. Это сложная процедура, которая проводит очень частые (можно указать время в ms, по умолчанию 50) проверки состояния пинов. При этом проводится вычисление Z-фильтра на появление пиков, а также обработка некоторых случаев с вызовом соответствующих процедур., пример:TIMER.start 50TIMER.stop — Остановить кольцевую запись пинов, пример:TIMER.stopset.FLT [lag] [TOL] [THRESHOLD] [INFLUENCE] — Установить параметры сглаживающего фильтра измерений, пример:set.FLT 15 64 6 1.5echobuf [N] — Выдать содержимое кольцевого буфера измерений, начиная с N, пример:echobuf 0Операции текстовых строк
{GET:[url]} — загрузить страницу из сети (очень короткую! памяти не хватит!) по адресу url, также можно первым аргументом перед url через пробел указать таймаут в мс: {GET: 500 http://lenta.ru/robots.txt}, если не указан, то по умолчанию 5000мс., пример:set unixtime = {GET: 2000 http://lleo.me/ESP8266/index.php?unixtime=1}{FILE:[файл]} — Загрузить (с внутренней флешки) содержимое файла с именем «файл», пример:set num = {FILE:/numer.txt}{FILEMD5:[файл]} — подсчитать хэш MD5 файла с именем «файл», пример:set md5string = {FILEMD5:/ESP.jpg}{PARSE:[переменная] [шаблон]} — ищет в строковой переменой данные по шаблону, где нужный кусок обозначен * Также понимает обозначения: \n \r, пример:set time = 06:40
set h = {PARSE:time *:}
set m = {PARSE:time :*}
echo m={m} h={h}{TAKE:[name] [num] [sep]} — Разобрать текстовую переменную с именем [name] на аргументы по сепаратору [sep] (если не указан, то разделить по пробелам) и взять аргумент номер [num], пример:{2}{SET} — вывести дамп всех переменных в формате «имя = [значение]\n», пример:{2}{INFO} — вывести полное инфо, как /info, пример:{2}{dir} — дать список всех файлов на внутренней флешке в формате «[имя] [размер]\n», пример:{2}{WIFI.scan} — дать список WiFi-сетей вокруг в формате «[доступ] [имя сети]\n», где доступ «free» для открытых и «pass» для закрытых, пример:{2}Служебные переменные
Команда формата {имя} покажет значение пользолвательской переменной.
Но в системе есть различные предопределенные переменные, динамические значения, результаты сложных взаимодействий с внешними устройстами и так далее. У них есть свои имена, вот они:GPIO
{gpio[N]} — прочесть значение gpio 1,2,3,4,5,12,13,14,15,16 и A0Сеть
{ip} — полученные IP WiFi.localIP().toString(){ip_mask} — WiFi.subnetMask(){ip_gateway} — WiFi.gatewayIP(){macAddress} — WiFi.macAddress(){ip_connected} — 1 или 0 WiFi.isConnected() ? 1 : 0{ip_autoconnect} — 1 или 0 WiFi.getAutoConnect() ? 1 : 0{ip_dns} — WiFi.dnsIP(0) + WiFi.dnsIP(1){ip_hostname} — WiFi.hostname(){ip_status} — WiFi.status(){ip_ssid} — WiFi.SSID(){ip_psk} — WiFi.psk(){ip_bssid} — WiFi.BSSIDstr(){ip_rssi} — WiFi.RSSI(){softAPIP} — WiFi.softAPIP(){softAPmacAddress} — WiFi.softAPmacAddress(){softAPgetStationNum} — WiFi.softAPgetStationNum(){mdns} — return String(mdns);{LAN.started} — Есть ли внешний Ethernet через подключенное устройствоВнутренние параметры чипа ESP
{ESP_TYPE} — тип ESP, например: ESP-12, ESP-32, ESP32S2, ESP32S3, ESP32C3{FreeHeap} — ESP.getFreeHeap(){FreeSketchSpace} — ESP.getFreeSketchSpace(){SketchSize} — ESP.getSketchSize(){chip} — ESP.getChipId() HEX{FlashChipId} — ESP.getFlashChipId(){FlashChipSize} — ESP.getFlashChipSize(){FlashChipRealSize} — ESP.getFlashChipRealSize(){FlashChipSpeed} — ESP.getFlashChipSpeed(){cycles} — ESP.getCycleCount(){CoreVersion} — ESP.getCoreVersion(){FullVersion} — ESP.getFullVersion(){BootVersion} — ESP.getBootMode(){BootMode} — ESP.getCycleCount(){CpuFreq} — ESP.getCpuFreqMHz(){FlashChipSizeByChipId} — ESP.getFlashChipSizeByChipId(){getSketchMD5} — ESP.getSketchMD5(){ResetReason} — ESP.getResetReason(){ResetInfo} — ESP.getResetInfo(){flashmode} — ESP.getFlashChipMode() — возвращает QIO, QOUT, DIO, DOUT, UNKNOWN{vcc} — ESP.getVcc()Файловая система
{Files} — Список всех файлов внутренней флешки в формате " [имя]"{Files_count} — число файлов внутренней флешки{SPIFFStotal} — общее количество байт в файловой системе{SPIFFSused} — количество занятых байт в файловой системе{SPIFFSfree} — количество свободных байт в файловой системеПрошивка и ее опции
{VER} — номер версии прошивки (число){VERNAME} — имя версии прошивки{MOTORSTOP} — флаг остановки мотора{NBUF} — константа — размер буфера{NLOOP} — константа — максимальное количество циклов{NSET} — константа — максимальное количество переменных{NSERV} — константа — максимальное количество серв{EchoMOTO} — return EchoMOTO;Обработка данные аналогового входа A0
{MaxA0} — Значение максимума для срабатывания прерывания по максимуму{MinA0} — Значение минимума для срабатывания прерывания по минимуму{FltA0} — Значение фильтраВремя
{UnixTime} — текущее время UnixTime (начинает тикать с 0 в момент старта, нопозже можно записать настоящее время){hh} — текущие часы{mm} — текущие минуты{ss} — текущие секунды{dn} — день недели, номер 0-6{ddn} — день недели su mo tu we th fr sa{Time} или {hhmmss} — время в формате hhmmss{millis} — число миллисекунд millis();Внешние устройства
{MQTT} — если сервис MQTT поднят, то 1, иначе 0{DS18B20} — считать показания температурного датчика Dallas{WIEGAND} — код последней введенной беспроводной карты{RC522.ver} — версия прошивки считывателя rc522 ( 0x91 или 0x92 ){RC522.card} — код последней прочитанной беспроводной карты со считывателя rc522{SERIAL} — прочесть строку из внутреннего Serial, если былаMODBUS
{MODBUS.started} — если сервис ModBus уже был инициализирован, то 1, иначе 0{MODBUS.last} — показать дамп последнего запроса{MODBUS:[reg]} — значение регистра regПРИМЕРЫ
{LOOP:[N]} — Число оставшихся секунд до срабатывания цикла по его номеру, пример:echo До обновления сфота осталось {LOOP:1} секунд{LOOP:[действия]} — Возвращает число оставшихся секунд до срабатывания цикла по его исполняемой команде (если ее помним или это было имя файла, неудобная команда), пример:echo {LOOP:/MOTOR_STOP.txt}{LOOP} — вывести дамп всех циклов в формате «Loop #[N] [count] of [value] [тело] ONE\n» ONE добавляется — если цикл однократный, пример:{LOOP}Системная часть — edge
Также есть системная веб-часть по обращению к веб-сайту чипа, например http://192.168.4.1/info
GET /FM?a=login&password=MYPASSWORD — логиниться админом, получить в ответ hash пароля — доступно всем, не только админуGET /FM?a=loop&n=3 — показать сколько осталось секунд до выполнения цикла номер (например 1) — доступно всем, не только админуGET /FM?a=WIFIconn1 — переконнектиться по WiFI если сеть была «ESP-HELP», передает «net»+«pass», записывает их в «wifi_last.txt» — доступно всем, не только админуGET /info — страница полной информации о чипе и системеGET /dir — список файлов на флешкеPOST /upload — загрузка файлов на флешку методом POSTPOST / — выполнить скрипт, которые передается методом POSTGET /MOTO?script — выполнить скрипт, в котором разделители строк заменены на знак «GET /MOTO?hash=5fd310ef5fd7e6ab523&script — то же, но выполнить скрипт от незалогиненного пользователя, указав правильный парольный hashАвторизация
Система позволяет выполнить произвольный скрипт на устройстве, но для этого надо знать пароль, установленный в config.txt («set password = ...»). Сам пароль используется только во время логина, при этом чип возвращает 32-символьный hash MD5, который зависит не только от пароля, но и от уникального серийного номера каждого чипа (для ESP12 это серийный номер чипа и памяти, для ESP32 — МАК-сдрес). В дальнейшем система считает запрос от админа, если правильный хэш передан в куках «ESP=...», либо указан в строке параметров «hash=...»
Вот один из способов управлять устройством с компьютера, зная лишь IP и пароль админа. Сперва надо получить хэш, затем исполнять скрипты — их можно передавать методом POST на эндпоинт «/», либо в строке запроса на эндпоинт «/MOTO», заменяя переводы строк на знак «|».
#!/bin/sh# change password
hash=`wget -q -O - "http://10.9.0.133/FM?a=login&password=Zyablik123"`
wget -q -O - "http://10.9.0.133/MOTO?hash=${hash}&echo Old Password:{FILE:wifi_last.txt}|
FILE.save.text wifi_last.txt kv121\\nPassword12345|echo New Password{FILE:wifi_last.txt}|pinmode 4 OUTPUT|play 4 DRM"
посещений 759