mirror of
https://github.com/IoTManagerProject/IoTManager.git
synced 2026-03-26 22:22:16 +03:00
Gisteresis termostat
This commit is contained in:
@@ -3,8 +3,8 @@
|
|||||||
"chipID": "",
|
"chipID": "",
|
||||||
"apssid": "IoTmanager",
|
"apssid": "IoTmanager",
|
||||||
"appass": "",
|
"appass": "",
|
||||||
"routerssid": "VOLODYA",
|
"routerssid": "rise",
|
||||||
"routerpass": "BELCHENKO",
|
"routerpass": "hostel3333",
|
||||||
"timezone": 1,
|
"timezone": 1,
|
||||||
"ntp": "pool.ntp.org",
|
"ntp": "pool.ntp.org",
|
||||||
"mqttServer": "wqtt.ru",
|
"mqttServer": "wqtt.ru",
|
||||||
|
|||||||
12
data/presets/2.c.txt
Normal file
12
data/presets/2.c.txt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
0;dallas-temp;temp;anydataTemp;Термостат;Температура;1;pin[2];index[0];int[10]
|
||||||
|
0;logging;log;chart;Термостат;История;2;val[temp];int[10];cnt[100]
|
||||||
|
0;inoutput;threshold;inputDigitTemp;Термостат;Заданная#температура;3
|
||||||
|
0;button-out;heater;toggle;Термостат;Нагреватель;7;pin[12]
|
||||||
|
0;inoutput;time1;inputTimeClock;Расписание;Утренний#период;8
|
||||||
|
0;inoutput;threshold1;inputDigitTemp;Расписание;Температура;9
|
||||||
|
0;inoutput;time2;inputTimeClock;Расписание;Дневной#период;10
|
||||||
|
0;inoutput;threshold2;inputDigitTemp;Расписание;Температура;11
|
||||||
|
0;inoutput;time3;inputTimeClock;Расписание;Вечерний#период;12
|
||||||
|
0;inoutput;threshold3;inputDigitTemp;Расписание;Температура;13
|
||||||
|
0;inoutput;time4;inputTimeClock;Расписание;Ночной#период;14
|
||||||
|
0;inoutput;threshold4;inputDigitTemp;Расписание;Температура;15
|
||||||
18
data/presets/2.s.txt
Normal file
18
data/presets/2.s.txt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
temp > threshold+-2
|
||||||
|
heater 0
|
||||||
|
end
|
||||||
|
temp < threshold+-2
|
||||||
|
heater 1
|
||||||
|
end
|
||||||
|
timenow = time1
|
||||||
|
threshold threshold1
|
||||||
|
end
|
||||||
|
timenow = time2
|
||||||
|
threshold threshold2
|
||||||
|
end
|
||||||
|
timenow = time3
|
||||||
|
threshold threshold3
|
||||||
|
end
|
||||||
|
timenow = time4
|
||||||
|
threshold threshold4
|
||||||
|
end
|
||||||
@@ -72,8 +72,8 @@
|
|||||||
"#": "Выберите элемент из списка<span class=\"caret\"></span>",
|
"#": "Выберите элемент из списка<span class=\"caret\"></span>",
|
||||||
"/set?addItem=button-out.pin": "1.Кнопка управляющая пином",
|
"/set?addItem=button-out.pin": "1.Кнопка управляющая пином",
|
||||||
"/set?addItem=button-out.inv": "2.Кнопка управляющая пином (с инверсией)",
|
"/set?addItem=button-out.inv": "2.Кнопка управляющая пином (с инверсией)",
|
||||||
"/set?addItem=button-out.npin": "3.Кнопка виртуальная",
|
"/set?addItem=button-out.npin": "3.Кнопка виртуальная (не привязанная к пину)",
|
||||||
"/set?addItem=button-in": "4.Кнопка физическая",
|
"/set?addItem=button-in": "4.Кнопка физическая, чтение состояния пина (подключается провдами к устройству)",
|
||||||
"/set?addItem=pwm-out": "3.Широтно импульсная модуляция pwm",
|
"/set?addItem=pwm-out": "3.Широтно импульсная модуляция pwm",
|
||||||
"/set?addItem=input-digit": "5.Окно ввода цифровых значений",
|
"/set?addItem=input-digit": "5.Окно ввода цифровых значений",
|
||||||
"/set?addItem=input-time": "6.Окно ввода времени",
|
"/set?addItem=input-time": "6.Окно ввода времени",
|
||||||
@@ -104,10 +104,11 @@
|
|||||||
"style": "display:inline",
|
"style": "display:inline",
|
||||||
"title": {
|
"title": {
|
||||||
"#": "Выберите пресет из списка<span class=\"caret\"></span>",
|
"#": "Выберите пресет из списка<span class=\"caret\"></span>",
|
||||||
"/set?addPreset=dal.c": "1.Термостат на основе ds18b20 с оповещением в телеграм",
|
"/set?addPreset=1.c": "1.Термостат на основе ds18b20 с оповещением в телеграм",
|
||||||
"/set?addPreset=dht.c": "2.Контроль влажности на основе DHT с оповещением в телеграм",
|
"/set?addPreset=2.c": "2.Гистерезис термостат на основе ds18b20 с суточным расписанием",
|
||||||
"/set?addPreset=rel.c": "3.Включение выключение реле в заданное время",
|
"/set?addPreset=3.c": "3.Контроль влажности на основе DHT с оповещением в телеграм",
|
||||||
"/set?addPreset=alloff.c": "4.Выключить все (пример работы сценариев)"
|
"/set?addPreset=4.c": "4.Включение выключение реле в заданное время",
|
||||||
|
"/set?addPreset=5.c": "5.Выключить все (пример работы сценариев)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
4
data/widgets/chart2.json
Normal file
4
data/widgets/chart2.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"widget": "chart",
|
||||||
|
"dateFormat": "HH:mm"
|
||||||
|
}
|
||||||
6
data/widgets/inputDigitTemp.json
Normal file
6
data/widgets/inputDigitTemp.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"widget" : "input",
|
||||||
|
"color" : "green",
|
||||||
|
"type" : "number",
|
||||||
|
"icon": "thermometer"
|
||||||
|
}
|
||||||
6
data/widgets/inputTimeClock.json
Normal file
6
data/widgets/inputTimeClock.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"widget" : "input",
|
||||||
|
"color" : "orange",
|
||||||
|
"type" : "time",
|
||||||
|
"icon": "alarm-outline"
|
||||||
|
}
|
||||||
566
doc/1.txt
566
doc/1.txt
@@ -1,566 +0,0 @@
|
|||||||
***
|
|
||||||

|
|
||||||
|
|
||||||
## Возможности
|
|
||||||
|
|
||||||
- Объединение различных по типу и назначению устройств: управление, получение данных, и настройка параметров - всё в одном приложении
|
|
||||||
|
|
||||||
- Взаимодействие с устройствами осуществляется через "облачный" сервис с использованием протокола mqtt, позволит контролировать их из любой точки Мира (при наличии доступа в Интернет)
|
|
||||||
|
|
||||||
- Поддержка нескольких профилей и их переключение "на лету", дает возможность объединить устройства в группы
|
|
||||||
|
|
||||||
|
|
||||||
Настройка (после "прошивки") производится через веб-интерфейс, чтобы получить к нему доступ необходимо соединиться с WiFi AP устройства и набрать в адресной строке браузера http://192.168.4.1.
|
|
||||||
Далее выбрать типовой шаблон автоматизации, произвести настройку под свои требования и задачи.
|
|
||||||
Основные разделы интерфейса: конфигурация и сценарии.
|
|
||||||
В окне конфигурации задаются "объекты", "элементы управления" устройства (dashboard) - им устройство будет представлено в приложении компаньоне проекта. В окне сценариев задаются реакции на события и изменения в параметрах работы системы.
|
|
||||||
|
|
||||||
***
|
|
||||||

|
|
||||||
|
|
||||||
## Команды, назначение и применение
|
|
||||||
|
|
||||||
Команды служат для настройки и управления устройством и его взаимодействия
|
|
||||||
|
|
||||||
**`buttonSet 1 1`** Изменит состояние "кнопки" №1, установит его в значение 1
|
|
||||||
|
|
||||||
**`pinSet 13 0`** Установит GPIO 13 состояние 0
|
|
||||||
|
|
||||||
**`pinChange 13`** Состояние GPIO 13 будет изменено на противоположное
|
|
||||||
|
|
||||||
**`pwmSet 1 500`** Настройка pwm №1 будет использовано значение 500
|
|
||||||
|
|
||||||
**`timeSet 1 08-00-00`** Установит для элемента ввода времени - inputTime значение 08:00:00
|
|
||||||
|
|
||||||
**`digitSet 1 56`** Элемент №1 (для цифровых параметров) отобразит число 56
|
|
||||||
|
|
||||||
**`stepperSet 1 100 1`** Шаговый двигатель №1 - вращение 100 "шагов" по часовой стрелке (для движения в обратную сторону используются отрицательные значения параметра)
|
|
||||||
|
|
||||||
**`servoSet 1 180`** Сервопривод №1 принять положение 180°
|
|
||||||
|
|
||||||
**`timerStart 1 60 sec`** Установить для таймера №1 обратный отсчёт в 60 секунд
|
|
||||||
|
|
||||||
**`timerStop 1`** Остановить таймер №1
|
|
||||||
|
|
||||||
**`textSet 1 Привет`** Установить для элемента текстовое поле №1 - "привет"
|
|
||||||
|
|
||||||
**`push Внимание Протечка`** Отправить push-уведомление с темой "внимание" и содержанием "протечка"
|
|
||||||
|
|
||||||
**`firmwareUpdate`** Обновить прошивку устройства "по воздуху"
|
|
||||||
|
|
||||||
**`firmwareVersion Версия прошивки Системные 1`** Узнать версию прошивки устройстве
|
|
||||||
|
|
||||||
## Сценарии
|
|
||||||
|
|
||||||
Элементарный блок в сценарии состоит из набора команд и триггера - условия для их выполнения
|
|
||||||
|
|
||||||
**temp > 60**
|
|
||||||
digitSet 1 60
|
|
||||||
stepperSet 1 100 1
|
|
||||||
textSet 1 Перегрев
|
|
||||||
**end**
|
|
||||||
|
|
||||||
Условие: когда температура превысит 60°
|
|
||||||
Запустит: команда шаговому двигателю, в приложение отправить сообщение и цифровое значение температуры.
|
|
||||||
|
|
||||||
В сценарии может быть несколько блоков, при необходимости из приложения есть возможность "выключать" часть из них.
|
|
||||||
Неактивные блоки сценария будут проигнорированы.
|
|
||||||
|
|
||||||
Для взаимодействия устройств между собой предусмотрены команды mqtt и http
|
|
||||||
|
|
||||||
**temp > 60**
|
|
||||||
mqtt 154348-134 digitSet_1_56
|
|
||||||
mqtt 154348-136 stepperSet _1_100_1
|
|
||||||
http 192.168.1.10 textSet_1_Перегрев
|
|
||||||
**end**
|
|
||||||
|
|
||||||
***
|
|
||||||

|
|
||||||
## 1.1 Объект "кнопка"
|
|
||||||
|
|
||||||
(эти строки мы пишем в "конфигурации устройства")
|
|
||||||
|
|
||||||
### a) кнопка управляющая выходом (пином). Пины нумеруются по системе нумирации gpio для esp контроллеров.
|
|
||||||
|
|
||||||
`button 1 13 кухня освещение 0 1`
|
|
||||||
|
|
||||||
**"button"** это объект создающий кнопку в приложении
|
|
||||||
**"1"** это номер этой кнопки (необходимый для ее аутентификации)
|
|
||||||
**"13"** это номер пина которым будет управлять данная кнопка
|
|
||||||
**"кухня"** это название кнопки в приложении
|
|
||||||
**"освещение"** это название вкладки в приложении на которой появится данная кнопка
|
|
||||||
**"0"** это начальное состояние кнопки при старте модуля (выкд 0, вкл 1)
|
|
||||||
**"1"** это уникальный номер и номер сортировки данной кнопки. Этот номер должен быть уникален для каждого объекта
|
|
||||||
|
|
||||||
|
|
||||||
### б) виртуальная кнопка - кнопка реакцию на которую можно задать в сценариях:
|
|
||||||
|
|
||||||
`button 1 na запустить таймеры 0 1`
|
|
||||||
|
|
||||||
**"button"** это объект создающий кнопку в приложении
|
|
||||||
**"1"** это номер этой кнопки (необходимый для ее аутентификации)
|
|
||||||
**"na"** абривиатура not available означающая что эта кнопка виртуальная и что пин не установлен
|
|
||||||
**"запустить"** это название кнопки в приложении
|
|
||||||
**"таймеры"** это название вкладки в приложении на которой появится данная кнопка
|
|
||||||
**"0"** это начальное состояние кнопки при старте модуля (выкд 0, вкл 1)
|
|
||||||
**"1"** это уникальный номер и номер сортировки данной кнопки. Этот номер должен быть уникален для каждого объекта
|
|
||||||
|
|
||||||
### в) кнопка включающая и выключающая все сценарии:
|
|
||||||
|
|
||||||
`button 1 scenario запустить таймеры 0 1`
|
|
||||||
|
|
||||||
**"button"** это объект создающий кнопку в приложении
|
|
||||||
**"1"** это номер этой кнопки (необходимый для ее аутентификации)
|
|
||||||
**"scenario"** слово означающее что эта кнопка для управления сценариями
|
|
||||||
**"запустить"** это название кнопки в приложении
|
|
||||||
**"таймеры"** это название вкладки в приложении на которой появится данная кнопка
|
|
||||||
**"0"** это начальное состояние кнопки при старте модуля (выкд 0, вкл 1)
|
|
||||||
**"1"** это уникальный номер и номер сортировки данной кнопки. Этот номер должен быть уникален для каждого объекта
|
|
||||||
|
|
||||||
|
|
||||||
### г) кнопка включающая выключающая определенные блоки сценариев:
|
|
||||||
|
|
||||||
`button 1 line1,line3, Включить#отправку#push Оповещение 0 1`
|
|
||||||
|
|
||||||
**"button"** это объект создающий кнопку в приложении
|
|
||||||
**"1"** это номер этой кнопки (необходимый для ее аутентификации)
|
|
||||||
**"line1,line3,"** это блоки сценариев нумирация сверху вниз. Блоком считается выражение от начала до слова end
|
|
||||||
**"Включить#отправку#push"** это название кнопки в приложении
|
|
||||||
**"Оповещение"** это название вкладки в приложении на которой появится данная кнопка
|
|
||||||
**"0"** это начальное состояние кнопки при старте модуля (выкд 0, вкл 1)
|
|
||||||
**"1"** это уникальный номер и номер сортировки данной кнопки. Этот номер должен быть уникален для каждого объекта
|
|
||||||
|
|
||||||
## 1.2 Команды управления объектом "кнопка"
|
|
||||||
|
|
||||||
(эти строки мы пишем в "сценариях")
|
|
||||||
|
|
||||||
### а) Команда включения выключения кнопки по ее номеру
|
|
||||||
|
|
||||||
`buttonSet 1 1`
|
|
||||||
|
|
||||||
**"buttonSet"** команда управления объектом button
|
|
||||||
**"1"** номер кнопки которой будем управлять
|
|
||||||
**"1"** состояние включено, 0 - выключено
|
|
||||||
|
|
||||||
### б) Команда изменения состояния кнопки на противоположное
|
|
||||||
|
|
||||||
`buttonChange 1`
|
|
||||||
|
|
||||||
**"buttonChange"** команда управления объектом button
|
|
||||||
**"1"** номер кнопки которой будем управлять
|
|
||||||
|
|
||||||
## 1.3 Вызов событий объектом "кнопока"
|
|
||||||
|
|
||||||
(эти строки мы пишем в "сценариях")
|
|
||||||
|
|
||||||
объект button может быть равен либо 0 либо 1
|
|
||||||
|
|
||||||
`button1 = 1`
|
|
||||||
`button2 = 0`
|
|
||||||
|
|
||||||
Пример использования:
|
|
||||||
|
|
||||||
`button1 = 1`
|
|
||||||
`buttonSet 2 1`
|
|
||||||
`buttonSet 3 0`
|
|
||||||
`end`
|
|
||||||
|
|
||||||
|
|
||||||
***
|
|
||||||

|
|
||||||
## 2.1 Объект "физическая кнопка"
|
|
||||||
|
|
||||||
`switch 1 0 10`
|
|
||||||
|
|
||||||
**switch** это объект создающий физическую кнопку
|
|
||||||
**1** номер кнопки
|
|
||||||
**0** пин кнопки (при подключении необходим подтягивающий резистор)
|
|
||||||
**10** задержка для избавления от дребезга с мили секундах
|
|
||||||
|
|
||||||
## 2.2 Вызов событий объектом "физическая кнопка"
|
|
||||||
|
|
||||||
`switch1` может быть равна нулю или единицы, ноль - событие отбрасывания кнопки, единица - событие нажатия
|
|
||||||
|
|
||||||
`switch1 = 1`
|
|
||||||
`buttonChange 1`
|
|
||||||
`end`
|
|
||||||
|
|
||||||
|
|
||||||
***
|
|
||||||

|
|
||||||
## 3.1 Объект "широтноимпульсная модуляция"
|
|
||||||
|
|
||||||
`pwm 1 12 яркость освещение 1023 1`
|
|
||||||
|
|
||||||
**"pwm"** это объект создающий управление шим в приложении в виде ползунка
|
|
||||||
**"1"** это номер этого объекта
|
|
||||||
**"12"** это номер пина на котором будет генерироваться шим заданной в приложении величены
|
|
||||||
**"Яркость"** это название кнопки в приложении
|
|
||||||
**"Оповещение"** это название вкладки в приложении на которой появится данная кнопка
|
|
||||||
**"1023"** это начальное значение шим сигнала и ползунка (изменяется от 0 до 1023)
|
|
||||||
**"1"** это уникальный номер и номер сортировки данной кнопки. Этот номер должен быть уникален для каждого объекта
|
|
||||||
|
|
||||||
## 3.2 Команда управления объектом "широтноимпульсная модуляция"
|
|
||||||
|
|
||||||
`pwmSet 1 500`
|
|
||||||
|
|
||||||
**"pwmSet"** команда управления объектом
|
|
||||||
**"1"** номер объекта, которым будем управлять
|
|
||||||
**"500"** значение которое установится после выполнения команды (от 0 до 1023)
|
|
||||||
|
|
||||||
***
|
|
||||||

|
|
||||||
## 4.1 Объект "окно ввода времени"
|
|
||||||
|
|
||||||
`inputTime time1 Во#сколько#включить? Таймеры 20-30-00 1`
|
|
||||||
|
|
||||||
**inputTime** это объект создающий окно ввода в приложении
|
|
||||||
**time1** переменная в которую будет записано время введенное в окно
|
|
||||||
**Во#сколько#включить?** это название окна в приложении
|
|
||||||
**Таймеры** это название вкладки в приложении
|
|
||||||
**20-30-00** начальное значение времени после загрузки устройства
|
|
||||||
**1** это уникальный номер и номер сортировки. Этот номер должен быть уникален для каждого объекта
|
|
||||||
|
|
||||||
## 4.2 Управление объектом "окно ввода времени"
|
|
||||||
|
|
||||||
`timeSet 1 08-00-00`
|
|
||||||
|
|
||||||
**"timeSet"** команда управления объектом
|
|
||||||
**"1"** номер объекта, которым будем управлять в данном случае окном ввода с `time1`
|
|
||||||
**"08-00-00"** время которое хотим установить
|
|
||||||
|
|
||||||
В окно ввода можно вводить время в приложении но если необходимо изменить время автоматически
|
|
||||||
по какому нибудь событию то можно использовать команду выше - **timeSet**.
|
|
||||||
|
|
||||||
## 4.3 Вызов событий объектом "окно ввода времени"
|
|
||||||
|
|
||||||
`timenow = time1`
|
|
||||||
`buttonSet 1 1`
|
|
||||||
`end`
|
|
||||||
|
|
||||||
`timenow` всегда хранит в себе текущее время, и поэтому исходя из данного сценария кнопка номер 1 включится в то время которое будет введено в окно ввода `time1`
|
|
||||||
|
|
||||||
***
|
|
||||||

|
|
||||||
## 5.1 Объект "окно ввода цифры"
|
|
||||||
|
|
||||||
`inputDigit digit1 Через#сколько#секунд#выключить? Таймеры 5 2`
|
|
||||||
|
|
||||||
**inputDigit** это объект создающий окно ввода в приложении
|
|
||||||
**digit1** переменная в которую будет записана цифра, введенная в окно
|
|
||||||
**Через#сколько#секунд#выключить?** это название окна в приложении
|
|
||||||
**Таймеры** это название вкладки в приложении
|
|
||||||
**5** цифра по умолчанию, после загрузки модуля
|
|
||||||
**2** это уникальный номер и номер сортировки. Этот номер должен быть уникален для каждого объекта
|
|
||||||
|
|
||||||
## 5.2 Управление объектом "окно ввода цифры":
|
|
||||||
|
|
||||||
`digitSet 1 56`
|
|
||||||
|
|
||||||
**"digitSet"** команда управления объектом
|
|
||||||
**"1"** номер объекта, которым будем управлять в данном случае окном ввода с `digit1`
|
|
||||||
**"56"** цифра которую хотим установить
|
|
||||||
|
|
||||||
В окно ввода можно вводить цифры в приложении, но если необходимо изменить цифру автоматически
|
|
||||||
по какому нибудь событию, то можно использовать команду выше - **digitSet**.
|
|
||||||
|
|
||||||
## 5.3 Вызов событий объектом "окно ввода цифры"
|
|
||||||
|
|
||||||
`dallas > digit1`
|
|
||||||
`buttonSet 1 0`
|
|
||||||
`end`
|
|
||||||
|
|
||||||
`button1 = 1`
|
|
||||||
`timerStart 1 digit1 sec`
|
|
||||||
`end`
|
|
||||||
|
|
||||||
***
|
|
||||||

|
|
||||||
## 6.1 Объект "dallas" (сенсор температуры ds18b20)
|
|
||||||
|
|
||||||
`dallas temp1 2 123456 Водонагреватель,#t°C Термостат any-data 1`
|
|
||||||
|
|
||||||
**dallas** это объект чтения датчика температуры
|
|
||||||
**2** пин датчика температуры
|
|
||||||
**Водонагреватель,#t°C** это название виджета в приложении
|
|
||||||
**Датчики** название вкладки в приложении
|
|
||||||
**any-data** или **progress-round** или **progress-line** три разных варианта виджета отображения
|
|
||||||
**1** это уникальный номер и номер сортировки. Этот номер должен быть уникален для каждого объекта
|
|
||||||
|
|
||||||
## 6.2 Вызов событий объектом "dallas"
|
|
||||||
|
|
||||||
В сценариях dallas можно сравнивать с переменной окна ввода `digit1` (>,<,>=,<=,=):
|
|
||||||
|
|
||||||
`dallas > digit1`
|
|
||||||
`buttonSet 1 0`
|
|
||||||
`end`
|
|
||||||
|
|
||||||
Или можно сравнивать с постоянной цифрой (>,<,>=,<=,=):
|
|
||||||
|
|
||||||
`dallas > 60`
|
|
||||||
`buttonSet 1 0`
|
|
||||||
`end`
|
|
||||||
|
|
||||||
|
|
||||||
***
|
|
||||||

|
|
||||||
## 7.1 Объект "analog" (аналоговый вход контроллера)
|
|
||||||
|
|
||||||
`analog adc 0 Аналоговый#вход,#% Датчики progress-round 310 620 1 100 1`
|
|
||||||
|
|
||||||
**analog** это объект чтения аналогового входа
|
|
||||||
**adc** это переменная
|
|
||||||
**0** пин аналогового входа (для esp8266 всегда 0, для esp32 пока что не доделал читаться будет всегда пин 34)
|
|
||||||
**Аналоговый#вход,#%** это название виджета в приложении
|
|
||||||
**Датчики** название вкладки в приложении
|
|
||||||
**any-data** или **progress-round** или **progress-line** три разных варианта виджета отображения
|
|
||||||
**310** начальная величина читаемого диапазона
|
|
||||||
**620** конечная величина читаемого диапазона
|
|
||||||
**1** начальная величина выводимого диапазона
|
|
||||||
**100** конечная величина выводимого диапазона
|
|
||||||
**1** это уникальный номер и номер сортировки. Этот номер должен быть уникален для каждого объекта
|
|
||||||
|
|
||||||
## 7.2 Вызов событий объектом "analog"
|
|
||||||
|
|
||||||
В сценариях analog можно сравнивать с переменной окна ввода `digit1` (>,<,>=,<=,=):
|
|
||||||
|
|
||||||
`analog > digit1`
|
|
||||||
`buttonSet 1 0`
|
|
||||||
`end`
|
|
||||||
|
|
||||||
Или можно сравнивать с постоянной цифрой (>,<,>=,<=,=):
|
|
||||||
|
|
||||||
`analog > 50`
|
|
||||||
`buttonSet 1 0`
|
|
||||||
`end`
|
|
||||||
|
|
||||||
|
|
||||||
***
|
|
||||||

|
|
||||||
## 8.1 Объект "level" (ультразвуковой дальномер JSN-SR04T, HC-SR04, HY-SRF05)
|
|
||||||
|
|
||||||
`level Вода#в#баке,#% Датчики any-data 125 20 1`
|
|
||||||
|
|
||||||
**level** это объект чтения датчика расстояния
|
|
||||||
**Вода#в#баке** это название виджета в приложении
|
|
||||||
**Датчики** название вкладки в приложении
|
|
||||||
**any-data** или **progress-round** или **progress-line** три разных варианта отображения виджета
|
|
||||||
**125** расстояние от датчика до дна бака в сантиметрах
|
|
||||||
**20** расстояние от датчика до поверхности воды, когда бак полный, в сантиметрах
|
|
||||||
**1** это уникальный номер и номер сортировки. Этот номер должен быть уникален для каждого объекта
|
|
||||||
|
|
||||||
Подключать дальномер нужно:
|
|
||||||
|
|
||||||
| | trig | echo |
|
|
||||||
| :-: | :-: | :-: |
|
|
||||||
| wemos | D5 | D6 |
|
|
||||||
| esp | 14 | 12 |
|
|
||||||
|
|
||||||
## 8.2 Вызов событий объектом "level"
|
|
||||||
|
|
||||||
В сценариях level можно сравнивать с переменной окна ввода `digit1` (>,<,>=,<=,=):
|
|
||||||
|
|
||||||
`level > digit1`
|
|
||||||
`buttonSet 1 0`
|
|
||||||
`end`
|
|
||||||
|
|
||||||
Или можно сравнивать с постоянной цифрой (>,<,>=,<=,=):
|
|
||||||
|
|
||||||
`level > 95`
|
|
||||||
`buttonSet 1 0`
|
|
||||||
`end`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
***
|
|
||||||

|
|
||||||
## 9.1 Объект "dht" (Сенсоры DHT11, DHT22, DHT33, DHT44, AM2302, RHT03)
|
|
||||||
|
|
||||||
dhtT DHT11 2 Температура#DHT,#t°C Датчики any-data 1
|
|
||||||
dhtH DHT11 2 Влажность#DHT,#% Датчики any-data 2
|
|
||||||
dhtComfort Степень#комфорта: Датчики 3
|
|
||||||
dhtPerception Восприятие: Датчики 4
|
|
||||||
dhtDewpoint Точка#росы: Датчики 5
|
|
||||||
|
|
||||||
**dhtT** или **dhtH** температура или влажность
|
|
||||||
**DHT11** или **DHT22** чтение DHT11 или DHT22, DHT33, DHT44, AM2302, RHT03 соответственно
|
|
||||||
**2** пин датчика
|
|
||||||
**Температура#DHT,#t°C** это название виджета в приложении
|
|
||||||
**Датчики** название вкладки в приложении
|
|
||||||
**any-data** или **progress-round** или **progress-line** три разных варианта отображения виджета
|
|
||||||
**1** это уникальный номер и номер сортировки. Этот номер должен быть уникален для каждого объекта
|
|
||||||
|
|
||||||
## 9.2 Вызов событий объектом "dhtT" или "dhtH"
|
|
||||||
|
|
||||||
В сценариях "dhtT" или "dhtH" можно сравнивать с переменной окна ввода `digit1` (>,<,>=,<=,=):
|
|
||||||
|
|
||||||
`dhtT > digit1`
|
|
||||||
`buttonSet 1 0`
|
|
||||||
`end`
|
|
||||||
|
|
||||||
`dhtH > digit1`
|
|
||||||
`buttonSet 1 0`
|
|
||||||
`end`
|
|
||||||
|
|
||||||
Или можно сравнивать с постоянной цифрой (>,<,>=,<=,=):
|
|
||||||
|
|
||||||
`dhtT > 50`
|
|
||||||
`buttonSet 1 0`
|
|
||||||
`end`
|
|
||||||
|
|
||||||
`dhtH < 40`
|
|
||||||
`buttonSet 1 0`
|
|
||||||
`end`
|
|
||||||
|
|
||||||
|
|
||||||
***
|
|
||||||

|
|
||||||
## 10.1 Объект "stepper" (Драйвер шагового двигателя A4988)
|
|
||||||
|
|
||||||
stepper 1 12 4
|
|
||||||
stepper 2 13 5
|
|
||||||
|
|
||||||
**stepper** объект создающий шаговый двигатель
|
|
||||||
**1** номер шаговика
|
|
||||||
**12** номер пина количества шагов
|
|
||||||
**4** номер пина направления
|
|
||||||
|
|
||||||
## 10.2 управление объектом "stepper"
|
|
||||||
|
|
||||||
`stepperSet 1 200 1`
|
|
||||||
|
|
||||||
**stepperSet** команда управления шаговым двигателем
|
|
||||||
**1** номер шагового двигателя (их может быть не более двух)
|
|
||||||
**200** количество шагов (обратное направление отрицательное значение параметра)
|
|
||||||
**1** интервал между шагами (мс)
|
|
||||||
|
|
||||||
`button1 = 1`
|
|
||||||
`stepperSet 1 200 1`
|
|
||||||
`end`
|
|
||||||
`button1 = 0`
|
|
||||||
`stepperSet 1 -200 1`
|
|
||||||
`end`
|
|
||||||
|
|
||||||
***
|
|
||||||

|
|
||||||
## 11.1 Объект "обратный таймер"
|
|
||||||
|
|
||||||
Прежде чем читать этот раздел запустите пресет №3 на устройстве.
|
|
||||||
Нажав на кнопку "Выберите во что вы хотите превратить esp"
|
|
||||||
|
|
||||||
Можно использовать цифры из окон ввода:
|
|
||||||
|
|
||||||
`timerStart 1 digit1 sec`
|
|
||||||
|
|
||||||
Можно писать цифры прям в объект:
|
|
||||||
|
|
||||||
`timerStart 1 10 sec`
|
|
||||||
|
|
||||||
Можно установить часы минуты или секунды:
|
|
||||||
|
|
||||||
`timerStart 1 10 sec`
|
|
||||||
`timerStart 1 10 min`
|
|
||||||
`timerStart 1 10 hours`
|
|
||||||
|
|
||||||
Используем это объект в сценариях вот так:
|
|
||||||
|
|
||||||
`button1 = 1`
|
|
||||||
`timerStart 1 digit1 sec`
|
|
||||||
`end`
|
|
||||||
|
|
||||||
Смысл в том что при нажатии на кнопку один запуститься обратный отчет, на величину digit1 секунд. Если напишем например:
|
|
||||||
|
|
||||||
`dallas < 60`
|
|
||||||
`timerStart 1 digit1 sec`
|
|
||||||
`end`
|
|
||||||
|
|
||||||
то такой же отчет запустится когда значение температуры вырастит больше 60 градусов. Таким образом обратный отчет можно запустить реакцией на любое событие. Итак теперь обратный отчет запущен, обратный таймер уменьшается, и нам надо назначить действие на тот момент когда он обнулится. Для этого я придумал выражение: `timer1 = 0`
|
|
||||||
|
|
||||||
Используем его и в общем получаем вот такой сценарий:
|
|
||||||
|
|
||||||
`button1 = 1`
|
|
||||||
`timerStart 1 digit1 sec`
|
|
||||||
`end`
|
|
||||||
`timer1 = 0`
|
|
||||||
`buttonSet 1 0`
|
|
||||||
`end`
|
|
||||||
|
|
||||||
Когда таймер закончит отсчёт, кнопка станет "неактивной". Используйте преет №3, как пример подобного сценария
|
|
||||||
Например:
|
|
||||||
|
|
||||||
`dallas < 60`
|
|
||||||
`buttonSet 1 0`
|
|
||||||
`buttonSet 2 0`
|
|
||||||
`pwmSet 1 1023`
|
|
||||||
`mqtt 2653450020 buttonChange_1`
|
|
||||||
`mqtt 2653450020 pinSet_13_1`
|
|
||||||
`http 192.168.1.32 pinSet_14_1`
|
|
||||||
`end`
|
|
||||||
|
|
||||||
Вот что может произойти на разных устройствах по одному событию повышения температуры...
|
|
||||||
|
|
||||||
|
|
||||||
***
|
|
||||||

|
|
||||||
## 12 Журнал (лог) данных
|
|
||||||
|
|
||||||
|
|
||||||
`logging analog 1 100 slow Аналоговый#вход Датчики 7`
|
|
||||||
|
|
||||||
**logging** объект для логирования
|
|
||||||
**analog** или **dhtT** или **dhtH** какой сенсор будем логировать, можно указать любой
|
|
||||||
**1** период между точками в минутах
|
|
||||||
**100** количество точек (старые точки будут удаляться по мере добавления новых)
|
|
||||||
**slow** или **fast** метод выгрузки графика в приложение, slow - выгружает график по одной точке (меньше расходуется оперативка, лучше использовать для esp8266), fast - выгрузка графика сразу (больше расход оперативки, подходит для esp32)
|
|
||||||
**Аналоговый#вход** название графика в приложении
|
|
||||||
**Датчики** название вкладки в приложении
|
|
||||||
**7** это уникальный номер и номер сортировки. Этот номер должен быть уникален для каждого объекта
|
|
||||||
|
|
||||||
***
|
|
||||||

|
|
||||||
## 13 Взаимодействие устройств между собой
|
|
||||||
|
|
||||||
Устройства могут между собой обмениваться командами. Команды можно отправлять по http или по mqtt.
|
|
||||||
По событию на одном устройстве можно вызвать действие на другом. Например на esp01 стоит датчик температуры, реле стоит на esp02.
|
|
||||||
|
|
||||||
Настройки esp01:
|
|
||||||
|
|
||||||
`dhtT temp 2 dht11 Температура#DHT,#t°C Датчики any-data 1`
|
|
||||||
|
|
||||||
`temp < 40`
|
|
||||||
`http 192.168.10.25 buttonSet_1_1`
|
|
||||||
`end`
|
|
||||||
|
|
||||||
Настройки esp02:
|
|
||||||
|
|
||||||
`button 1 13 Включить#реле Реле 0 1`
|
|
||||||
|
|
||||||
И теперь когда температура датчика на esp01 станет меньше 40 градусов то на esp02 будет отправлена команда на включение кнопки: buttonSet_1_1
|
|
||||||
|
|
||||||
Если вы хотите отправить команду через mqtt то сценарий будет выглядеть следующим образом:
|
|
||||||
|
|
||||||
`temp < 40`
|
|
||||||
`mqtt 12343442-12413131 buttonSet_1_1`
|
|
||||||
`end`
|
|
||||||
|
|
||||||
где `12343442-12413131` id esp02 той на которую отправляем команду. Id можно взять в веб интерфейсе на странице конфигурация устройства. Или в списке устройств в сети.
|
|
||||||
|
|
||||||
Теперь рассмотрим вариант внешнего управления esp с помощью get запросов.
|
|
||||||
|
|
||||||
`http://192.168.88.239/cmd?command=buttonSet%201%201`
|
|
||||||
|
|
||||||
Разберем эту строку. Сама команда в ней выглядит вот так: buttonSet%201%201. `%20` заменяют пробел.
|
|
||||||
|
|
||||||
То есть что бы составить get запрос на изменение например pwm нужно:
|
|
||||||
|
|
||||||
Взять команду `pwmSet 1 500`
|
|
||||||
Заменить в ней пробелы на `%20` получится так: `pwmSet%201%20500`
|
|
||||||
И добавить ее в конец строки `http://192.168.88.239/cmd?command=` где указывается ip адрес устройства
|
|
||||||
|
|
||||||
В итоге получится http://192.168.88.239/cmd?command=pwmSet%201%20500
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
85
doc/2.txt
85
doc/2.txt
@@ -1,85 +0,0 @@
|
|||||||
# В этой инструкции будет описано как с esp отправлять email и push
|
|
||||||
|
|
||||||
# Часть 1. Привязать email и pushbullet к сайту pushingbox
|
|
||||||
|
|
||||||
### 1. Необходимо перейти на сайт: [pushingbox](https://www.pushingbox.com/)
|
|
||||||
### 2. Войти с помощью google
|
|
||||||

|
|
||||||
### 3. Перейти в мои сервисы и добавить новый сервис
|
|
||||||

|
|
||||||
### 4. Нас интересуют два сервиса email и pushbullet
|
|
||||||

|
|
||||||
### 5. Выбираем сначало сервис для отправки email. В окно `Name of your email configuration` - вводим слово "email". В окно `Email address` - вводим ваш email адрес. жмем submit
|
|
||||||

|
|
||||||
manager_modules_firmware/blob/master/push_instruction/Screenshot_6.png)
|
|
||||||
### 6.1 Привязываем pushbullet. Переходим на сайт [pushbullet.com](https://www.pushbullet.com/)
|
|
||||||
### 6.2 Входим с гуглом или фейсбуком
|
|
||||||
### 6.3 Идем в настройки
|
|
||||||

|
|
||||||
### 6.4 Создаем токен
|
|
||||||

|
|
||||||
### 6.5 Идем опять в сервисы и теперь выбираем сервис pushbullet [pushingbox.com/services](https://www.pushingbox.com/services.php) нажимаем add service
|
|
||||||
### Берем токен, и вставляем его в окно Access token.
|
|
||||||
### Окно Device token (optional) оставляем пустым.
|
|
||||||
### В окно Name of your Pushbullet configuration пишем слово "push".
|
|
||||||

|
|
||||||
|
|
||||||
### 7. Теперь наш email и pushbullet привязаны к pushingbox. Далее можно скачать приложение pushbullet на телефон и войти с гуглом или фейсбуком сответственно с пунктом 6.3 этой инструкции
|
|
||||||

|
|
||||||
|
|
||||||
# Часть 2. Создание сценариев отправки email
|
|
||||||
|
|
||||||
### 8.1. Сценарий для отправки email. Заходим в My Scenarios:
|
|
||||||

|
|
||||||
|
|
||||||
### 8.2 Пишем слово email (это имя сценария отправки email) жмем add:
|
|
||||||

|
|
||||||
### 8.3 Нажимаем add an action
|
|
||||||

|
|
||||||
### 8.4 Выбираем наш email который мы зарегестрировали ранее и нажимаем Add an action with this service
|
|
||||||

|
|
||||||
### 8.5 Делаем все как на скриншоте и жмем submit
|
|
||||||

|
|
||||||
### 8.6 Возвращаемся на мои сценарии
|
|
||||||

|
|
||||||
### 8.7 Вставляем токен в веб интерфейс esp
|
|
||||||

|
|
||||||
|
|
||||||
# Часть 3. Создание сценариев отправки push
|
|
||||||
|
|
||||||
### 9.1. Сценарий для отправки push. Заходим в My Scenarios:
|
|
||||||

|
|
||||||
|
|
||||||
### 9.2 Пишем слово push (это имя сценария отправки email) жмем add:
|
|
||||||

|
|
||||||
### 9.3 Нажимаем add an action
|
|
||||||

|
|
||||||
### 9.4 Выбираем наш pushbullet который мы зарегестрировали ранее и нажимаем Add an action with this service
|
|
||||||

|
|
||||||
### 9.5 Делаем все как на скриншоте и жмем submit
|
|
||||||

|
|
||||||
### 9.6 Возвращаемся на мои сценарии
|
|
||||||

|
|
||||||
### 9.7 Вставляем токен в веб интерфейс esp
|
|
||||||

|
|
||||||
|
|
||||||
# Часть 4. Итог
|
|
||||||
|
|
||||||
При создании такой конфигурации как на картинке:
|
|
||||||
|
|
||||||
`button 1 na Отправить#push Push 0 1`
|
|
||||||
|
|
||||||
|
|
||||||
`button1 = 1`
|
|
||||||
`push внимание кнопка#нажата`
|
|
||||||
`end`
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Если мы введем токен для email то будут приходить email
|
|
||||||

|
|
||||||
|
|
||||||
Если для push то будут приходить push в pushbullet
|
|
||||||

|
|
||||||
|
|
||||||
Способ описанный в данной инструкции более сложный в настройке но зато очень надежный.
|
|
||||||
32
doc/3.txt
32
doc/3.txt
@@ -1,32 +0,0 @@
|
|||||||
***
|
|
||||||

|
|
||||||
|
|
||||||
### 1. Скачать архив из [релизов](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/releases) или из закрепленного сообщения группы телеграм с последней версией прошивки
|
|
||||||
|
|
||||||
***
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
### 2. Для ESP8266 c 4 и больше мб памяти (все сделать как на скриншотах)
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
***
|
|
||||||

|
|
||||||
|
|
||||||
### 2. Для ESP8266 c 1 мб памяти (все сделать как на скриншотах)
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
***
|
|
||||||

|
|
||||||
|
|
||||||
### 2. Для ESP32 (все сделать как на скриншотах)
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
24
doc/eagle.txt
Normal file
24
doc/eagle.txt
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
eagle.flash.512k0.ld 512K (no SPIFFS)
|
||||||
|
eagle.flash.512k64.ld 512K (64K SPIFFS)
|
||||||
|
eagle.flash.512k128.ld 512K (128K SPIFFS)
|
||||||
|
eagle.flash.1m0.ld 1M (no SPIFFS)
|
||||||
|
eagle.flash.1m64.ld 1M (64K SPIFFS)
|
||||||
|
eagle.flash.1m128.ld 1M (128K SPIFFS)
|
||||||
|
eagle.flash.1m144.ld 1M (144K SPIFFS)
|
||||||
|
eagle.flash.1m160.ld 1M (160K SPIFFS)
|
||||||
|
eagle.flash.1m192.ld 1M (192K SPIFFS)
|
||||||
|
eagle.flash.1m256.ld 1M (256K SPIFFS)
|
||||||
|
eagle.flash.1m512.ld 1M (512K SPIFFS)
|
||||||
|
eagle.flash.2m.ld 2M (1M SPIFFS)
|
||||||
|
eagle.flash.4m1m.ld 4M (1M SPIFFS)
|
||||||
|
eagle.flash.4m2m.ld 4M (2M SPIFFS)
|
||||||
|
eagle.flash.4m.ld 4M (3M SPIFFS)
|
||||||
|
eagle.flash.8m.ld 8M (7M SPIFFS)
|
||||||
|
eagle.flash.16m.ld 16M (15M SPIFFS)
|
||||||
|
|
||||||
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
|
nvs, data, nvs, 0x9000, 0x5000,
|
||||||
|
otadata, data, ota, 0xe000, 0x2000,
|
||||||
|
app0, app, ota_0, 0x10000, 0x1F0000,
|
||||||
|
app1, app, ota_1, 0x200000, 0x1F0000,
|
||||||
|
spiffs, data, spiffs, 0x3F0000,0x10000,
|
||||||
@@ -30,7 +30,28 @@ public:
|
|||||||
|
|
||||||
String setEventSign = selectFromMarkerToMarker(condition, " ", 1);
|
String setEventSign = selectFromMarkerToMarker(condition, " ", 1);
|
||||||
String setEventValue = selectFromMarkerToMarker(condition, " ", 2);
|
String setEventValue = selectFromMarkerToMarker(condition, " ", 2);
|
||||||
if (!isDigitStr(setEventValue)) setEventValue = getValue(setEventValue); //jsonReadStr(configLiveJson , setEventValue);
|
|
||||||
|
if (!isDigitStr(setEventValue)) {
|
||||||
|
if (setEventValue.indexOf("+-") != -1) {
|
||||||
|
String setEventValueName = selectToMarker(setEventValue, "+-");
|
||||||
|
String gisteresisValue = selectToMarkerLast(setEventValue, "+-");
|
||||||
|
gisteresisValue.replace("+-", "");
|
||||||
|
String value = getValue(setEventValueName);
|
||||||
|
String upValue = String(value.toFloat() + gisteresisValue.toFloat());
|
||||||
|
String lowValue = String(value.toFloat() - gisteresisValue.toFloat());
|
||||||
|
|
||||||
|
if (setEventSign == ">") {
|
||||||
|
setEventValue = upValue;
|
||||||
|
}
|
||||||
|
else if (setEventSign == "<") {
|
||||||
|
setEventValue = lowValue;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setEventValue = getValue(setEventValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
boolean flag = false;
|
boolean flag = false;
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
//===========Firmware=============================================================================================================================================
|
//===========Firmware=============================================================================================================================================
|
||||||
|
#define FIRMWARE_VERSION 268
|
||||||
|
//#define FLASH_SIZE_1MB
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
#define FIRMWARE_NAME "esp8266-iotm"
|
#define FIRMWARE_NAME "esp8266-iotm"
|
||||||
#define FIRMWARE_VERSION 268
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
#define FIRMWARE_NAME "esp32-iotm"
|
#define FIRMWARE_NAME "esp32-iotm"
|
||||||
#define FIRMWARE_VERSION 268
|
|
||||||
#endif
|
#endif
|
||||||
#define FLASH_4MB true
|
|
||||||
|
|
||||||
//===========FSystem==============================================================================================================================================
|
//===========FSystem==============================================================================================================================================
|
||||||
#define NUM_BUTTONS 6
|
#define NUM_BUTTONS 6
|
||||||
@@ -86,6 +85,8 @@ enum NotAsyncActions {
|
|||||||
do_MQTTPARAMSCHANGED,
|
do_MQTTPARAMSCHANGED,
|
||||||
do_deviceInit,
|
do_deviceInit,
|
||||||
do_delChoosingItems,
|
do_delChoosingItems,
|
||||||
|
do_addItem,
|
||||||
|
do_addPreset,
|
||||||
do_sendScenUDP,
|
do_sendScenUDP,
|
||||||
do_sendScenMQTT,
|
do_sendScenMQTT,
|
||||||
do_LAST,
|
do_LAST,
|
||||||
@@ -117,4 +118,7 @@ enum ConfigType_t {
|
|||||||
|
|
||||||
//17.11.2020 (SSDP OFF, UDP OFF)
|
//17.11.2020 (SSDP OFF, UDP OFF)
|
||||||
//RAM: [===== ] 45.7% (used 37476 bytes from 81920 bytes)
|
//RAM: [===== ] 45.7% (used 37476 bytes from 81920 bytes)
|
||||||
//Flash: [===== ] 54.5% (used 569296 bytes from 1044464 bytes)
|
//Flash: [===== ] 54.5% (used 569296 bytes from 1044464 bytes)
|
||||||
|
|
||||||
|
//RAM: [===== ] 45.6% (used 37336 bytes from 81920 bytes)
|
||||||
|
//Flash: [====== ] 55.3% (used 577396 bytes from 1044464 bytes)
|
||||||
@@ -85,14 +85,18 @@ extern int pwmOut_EnterCounter;
|
|||||||
extern String countDown_KeyList;
|
extern String countDown_KeyList;
|
||||||
extern int countDown_EnterCounter;
|
extern int countDown_EnterCounter;
|
||||||
//=========================================
|
//=========================================
|
||||||
|
extern String logging_KeyList;
|
||||||
|
extern int logging_EnterCounter;
|
||||||
|
//=========================================
|
||||||
|
|
||||||
// Sensors
|
// Sensors
|
||||||
extern String sensorReadingMap10sec;
|
extern String sensorReadingMap10sec;
|
||||||
extern String sensorReadingMap30sec;
|
extern String sensorReadingMap30sec;
|
||||||
|
|
||||||
|
extern String itemName;
|
||||||
|
extern String presetName;
|
||||||
|
|
||||||
|
|
||||||
extern String loggingKeyList;
|
|
||||||
extern int enter_to_logging_counter;
|
|
||||||
extern int scenario_line_status[40];
|
extern int scenario_line_status[40];
|
||||||
extern int lastVersion;
|
extern int lastVersion;
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ class LoggingClass {
|
|||||||
~LoggingClass();
|
~LoggingClass();
|
||||||
|
|
||||||
void loop();
|
void loop();
|
||||||
|
void execute(String payload);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -25,12 +26,13 @@ class LoggingClass {
|
|||||||
String _loggingValueKey;
|
String _loggingValueKey;
|
||||||
String _key;
|
String _key;
|
||||||
|
|
||||||
void addNewDelOldData(const String filename, size_t maxPoints, String payload);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern MyLoggingVector* myLogging;
|
extern MyLoggingVector* myLogging;
|
||||||
|
|
||||||
extern void logging();
|
extern void logging();
|
||||||
|
extern void loggingExecute();
|
||||||
extern void choose_log_date_and_send();
|
extern void choose_log_date_and_send();
|
||||||
extern void sendLogData(String file, String topic);
|
extern void sendLogData(String file, String topic);
|
||||||
extern void cleanLogAndData();
|
extern void cleanLogAndData();
|
||||||
|
|||||||
@@ -35,8 +35,10 @@ extra_scripts = ./tools/littlefsbuilder.py
|
|||||||
;=============================================================================================================================================
|
;=============================================================================================================================================
|
||||||
[env:esp8266_01_1m]
|
[env:esp8266_01_1m]
|
||||||
framework = arduino
|
framework = arduino
|
||||||
board = esp01_1m
|
;board = esp01_1m
|
||||||
board_build.ldscript = eagle.flash.1m512.ld
|
board = nodemcuv2
|
||||||
|
;board_build.ldscript = eagle.flash.1m512.ld
|
||||||
|
board_build.ldscript = eagle.flash.1m256.ld
|
||||||
platform = https://github.com/platformio/platform-espressif8266.git
|
platform = https://github.com/platformio/platform-espressif8266.git
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${common_env_data.lib_deps_external}
|
${common_env_data.lib_deps_external}
|
||||||
|
|||||||
@@ -55,14 +55,16 @@ int pwmOut_EnterCounter = -1;
|
|||||||
String countDown_KeyList = "";
|
String countDown_KeyList = "";
|
||||||
int countDown_EnterCounter = -1;
|
int countDown_EnterCounter = -1;
|
||||||
//=========================================
|
//=========================================
|
||||||
|
String logging_KeyList = "";
|
||||||
|
int logging_EnterCounter = -1;
|
||||||
|
//=========================================
|
||||||
|
|
||||||
// Sensors
|
// Sensors
|
||||||
String sensorReadingMap10sec;
|
String sensorReadingMap10sec;
|
||||||
String sensorReadingMap30sec;
|
String sensorReadingMap30sec;
|
||||||
|
|
||||||
// Logging
|
String itemName;
|
||||||
String loggingKeyList;
|
String presetName;
|
||||||
int enter_to_logging_counter;
|
|
||||||
|
|
||||||
// Upgrade
|
// Upgrade
|
||||||
String serverIP;
|
String serverIP;
|
||||||
|
|||||||
@@ -52,7 +52,8 @@ void Device_init() {
|
|||||||
if (myLogging != nullptr) {
|
if (myLogging != nullptr) {
|
||||||
myLogging->clear();
|
myLogging->clear();
|
||||||
}
|
}
|
||||||
loggingKeyList = "";
|
logging_KeyList = "";
|
||||||
|
logging_EnterCounter = -1;
|
||||||
//======clear impuls params=======
|
//======clear impuls params=======
|
||||||
if (myImpulsOut != nullptr) {
|
if (myImpulsOut != nullptr) {
|
||||||
myImpulsOut->clear();
|
myImpulsOut->clear();
|
||||||
|
|||||||
@@ -18,36 +18,56 @@ void itemsListInit() {
|
|||||||
delChoosingItems();
|
delChoosingItems();
|
||||||
},
|
},
|
||||||
nullptr);
|
nullptr);
|
||||||
|
#ifdef FLASH_SIZE_1MB
|
||||||
|
myNotAsyncActions->add(
|
||||||
|
do_addItem, [&](void*) {
|
||||||
|
addItem(itemName);
|
||||||
|
itemName = "";
|
||||||
|
},
|
||||||
|
nullptr);
|
||||||
|
|
||||||
|
myNotAsyncActions->add(
|
||||||
|
do_addPreset, [&](void*) {
|
||||||
|
addPreset(presetName);
|
||||||
|
presetName = "";
|
||||||
|
},
|
||||||
|
nullptr);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void addItem(String name) {
|
void addItem(String name) {
|
||||||
|
#ifdef FLASH_SIZE_1MB
|
||||||
|
String url = serverIP + F("/projects/iotmanager/config/items/") + name + ".txt";
|
||||||
|
String item = getURL(url);
|
||||||
|
Serial.println(url);
|
||||||
|
Serial.println(item);
|
||||||
|
if (item == "error") return;
|
||||||
|
#endif
|
||||||
|
#ifndef FLASH_SIZE_1MB
|
||||||
String item = readFile("items/" + name + ".txt", 1024);
|
String item = readFile("items/" + name + ".txt", 1024);
|
||||||
|
#endif
|
||||||
|
|
||||||
name = selectToMarker(name, "-");
|
name = selectToMarker(name, "-");
|
||||||
|
|
||||||
randomSeed(micros());
|
randomSeed(micros());
|
||||||
unsigned int num = random(0, 1000);
|
unsigned int num = random(0, 1000);
|
||||||
|
|
||||||
item.replace("id", name + String(num)); // "-" + String(getNewElementNumber("id.txt")));
|
item.replace("id", name + String(num));
|
||||||
item.replace("order", String(getNewElementNumber("order.txt")));
|
item.replace("order", String(getNewElementNumber("order.txt")));
|
||||||
|
|
||||||
if (item.indexOf("pin") != -1) { //all cases (random pins from available)
|
if (item.indexOf("pin") != -1) { //all cases (random pins from available)
|
||||||
item.replace("pin", "pin[" + String(getFreePinAll()) + "]");
|
item.replace("pin", "pin[" + String(getFreePinAll()) + "]");
|
||||||
} else
|
}
|
||||||
|
else if (item.indexOf("gol") != -1) { //analog
|
||||||
if (item.indexOf("gol") != -1) { //analog
|
|
||||||
item.replace("gol", "pin[" + String(getFreePinAnalog()) + "]");
|
item.replace("gol", "pin[" + String(getFreePinAnalog()) + "]");
|
||||||
} else
|
}
|
||||||
|
else if (item.indexOf("cin") != -1) { //ultrasonic
|
||||||
if (item.indexOf("cin") != -1) { //ultrasonic
|
|
||||||
item.replace("cin", "pin[" + String(getFreePinAll()) + "," + String(getFreePinAll()) + "]");
|
item.replace("cin", "pin[" + String(getFreePinAll()) + "," + String(getFreePinAll()) + "]");
|
||||||
} else
|
}
|
||||||
|
else if (item.indexOf("sal") != -1) { //dallas
|
||||||
if (item.indexOf("sal") != -1) { //dallas
|
|
||||||
item.replace("sal", "pin[2]");
|
item.replace("sal", "pin[2]");
|
||||||
} else
|
}
|
||||||
|
else if (item.indexOf("thd") != -1) { //dht11/22
|
||||||
if (item.indexOf("thd") != -1) { //dht11/22
|
|
||||||
item.replace("thd", "pin[2]");
|
item.replace("thd", "pin[2]");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,12 +78,32 @@ void addItem(String name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void addPreset(String name) {
|
void addPreset(String name) {
|
||||||
|
#ifdef FLASH_SIZE_1MB
|
||||||
|
String url2 = serverIP + F("/projects/iotmanager/config/presets/") + name + ".txt";
|
||||||
|
String preset = getURL(url2);
|
||||||
|
Serial.println(url2);
|
||||||
|
Serial.println(preset);
|
||||||
|
if (preset == "error") return;
|
||||||
|
#endif
|
||||||
|
#ifndef FLASH_SIZE_1MB
|
||||||
String preset = readFile("presets/" + name + ".txt", 4048);
|
String preset = readFile("presets/" + name + ".txt", 4048);
|
||||||
|
#endif
|
||||||
|
|
||||||
addFile(DEVICE_CONFIG_FILE, "\n" + preset);
|
addFile(DEVICE_CONFIG_FILE, "\n" + preset);
|
||||||
|
|
||||||
name.replace(".c",".s");
|
name.replace(".c", ".s");
|
||||||
|
|
||||||
|
#ifdef FLASH_SIZE_1MB
|
||||||
|
String url = serverIP + F("/projects/iotmanager/config/presets/") + name + ".txt";
|
||||||
|
String scenario = getURL(url);
|
||||||
|
Serial.println(url);
|
||||||
|
Serial.println(scenario);
|
||||||
|
if (scenario == "error") return;
|
||||||
|
#endif
|
||||||
|
#ifndef FLASH_SIZE_1MB
|
||||||
String scenario = readFile("presets/" + name + ".txt", 4048);
|
String scenario = readFile("presets/" + name + ".txt", 4048);
|
||||||
|
#endif
|
||||||
|
|
||||||
removeFile(DEVICE_SCENARIO_FILE);
|
removeFile(DEVICE_SCENARIO_FILE);
|
||||||
addFile(DEVICE_SCENARIO_FILE, scenario);
|
addFile(DEVICE_SCENARIO_FILE, scenario);
|
||||||
loadScenario();
|
loadScenario();
|
||||||
@@ -89,16 +129,17 @@ uint8_t getNewElementNumber(String file) {
|
|||||||
|
|
||||||
uint8_t getFreePinAll() {
|
uint8_t getFreePinAll() {
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
uint8_t pins[] = {0, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5};
|
uint8_t pins[] = { 0, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5 };
|
||||||
#endif
|
#endif
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
uint8_t pins[] = {0, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5};
|
uint8_t pins[] = { 0, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5 };
|
||||||
#endif
|
#endif
|
||||||
uint8_t array_sz = sizeof(pins) / sizeof(pins[0]);
|
uint8_t array_sz = sizeof(pins) / sizeof(pins[0]);
|
||||||
uint8_t i = getNewElementNumber("pins.txt");
|
uint8_t i = getNewElementNumber("pins.txt");
|
||||||
if (i < array_sz) {
|
if (i < array_sz) {
|
||||||
return pins[i];
|
return pins[i];
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -121,7 +162,8 @@ void delChoosingItems() {
|
|||||||
String item = configFile.readStringUntil('\n');
|
String item = configFile.readStringUntil('\n');
|
||||||
if (firstLine) {
|
if (firstLine) {
|
||||||
finalConf += item;
|
finalConf += item;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
int checkbox = selectToMarker(item, ";").toInt();
|
int checkbox = selectToMarker(item, ";").toInt();
|
||||||
if (checkbox == 0) {
|
if (checkbox == 0) {
|
||||||
finalConf += "\n" + item;
|
finalConf += "\n" + item;
|
||||||
|
|||||||
@@ -42,11 +42,11 @@ void getLastVersion() {
|
|||||||
#endif
|
#endif
|
||||||
if (tmp == "error") {
|
if (tmp == "error") {
|
||||||
lastVersion = -1;
|
lastVersion = -1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lastVersion = tmp.toInt();
|
lastVersion = tmp.toInt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lastVersion = -2;
|
lastVersion = -2;
|
||||||
}
|
}
|
||||||
@@ -102,7 +102,7 @@ bool upgradeFS() {
|
|||||||
if (retFS == HTTP_UPDATE_OK) { //если FS обновилась успешно
|
if (retFS == HTTP_UPDATE_OK) { //если FS обновилась успешно
|
||||||
SerialPrint("I", "Update", "LittleFS upgrade done!");
|
SerialPrint("I", "Update", "LittleFS upgrade done!");
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ bool upgradeBuild() {
|
|||||||
if (retBuild == HTTP_UPDATE_OK) { //если BUILD обновился успешно
|
if (retBuild == HTTP_UPDATE_OK) { //если BUILD обновился успешно
|
||||||
SerialPrint("I", "Update", "BUILD upgrade done!");
|
SerialPrint("I", "Update", "BUILD upgrade done!");
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
18
src/Web.cpp
18
src/Web.cpp
@@ -20,14 +20,24 @@ void web_init() {
|
|||||||
server.on("/set", HTTP_GET, [](AsyncWebServerRequest* request) {
|
server.on("/set", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
//==============================set.device.json====================================================================================================
|
//==============================set.device.json====================================================================================================
|
||||||
if (request->hasArg("addItem")) {
|
if (request->hasArg("addItem")) {
|
||||||
String name = request->getParam("addItem")->value();
|
#ifdef FLASH_SIZE_1MB
|
||||||
addItem(name);
|
itemName = request->getParam("addItem")->value();
|
||||||
|
myNotAsyncActions->make(do_addItem);
|
||||||
|
#endif
|
||||||
|
#ifndef FLASH_SIZE_1MB
|
||||||
|
addItem(request->getParam("addItem")->value());
|
||||||
|
#endif
|
||||||
request->redirect("/?set.device");
|
request->redirect("/?set.device");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->hasArg("addPreset")) {
|
if (request->hasArg("addPreset")) {
|
||||||
String name = request->getParam("addPreset")->value();
|
#ifdef FLASH_SIZE_1MB
|
||||||
addPreset(name);
|
presetName = request->getParam("addPreset")->value();
|
||||||
|
myNotAsyncActions->make(do_addPreset);
|
||||||
|
#endif
|
||||||
|
#ifndef FLASH_SIZE_1MB
|
||||||
|
addPreset(request->getParam("addPreset")->value());
|
||||||
|
#endif
|
||||||
request->redirect("/?set.device");
|
request->redirect("/?set.device");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,13 @@ void inOutputExecute() {
|
|||||||
String key = sCmd.order();
|
String key = sCmd.order();
|
||||||
String value = sCmd.next();
|
String value = sCmd.next();
|
||||||
|
|
||||||
|
|
||||||
|
if (!isDigitStr(value)) { //если значение - текст
|
||||||
|
if (value.indexOf(":") == -1) { //если этот текст не время
|
||||||
|
value = getValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int number = getKeyNum(key, inOutput_KeyList);
|
int number = getKeyNum(key, inOutput_KeyList);
|
||||||
|
|
||||||
if (myInOutput != nullptr) {
|
if (myInOutput != nullptr) {
|
||||||
|
|||||||
@@ -16,27 +16,36 @@ LoggingClass::LoggingClass(unsigned long period, unsigned int maxPoints, String
|
|||||||
LoggingClass::~LoggingClass() {}
|
LoggingClass::~LoggingClass() {}
|
||||||
|
|
||||||
void LoggingClass::loop() {
|
void LoggingClass::loop() {
|
||||||
currentMillis = millis();
|
if (_period > 0) {
|
||||||
difference = currentMillis - prevMillis;
|
currentMillis = millis();
|
||||||
if (difference >= _period) {
|
difference = currentMillis - prevMillis;
|
||||||
prevMillis = millis();
|
if (difference >= _period) {
|
||||||
addNewDelOldData("logs/" + _key + ".txt", _maxPoints, getValue(_loggingValueKey)); //jsonReadStr(configLiveJson , _loggingValueKey));
|
prevMillis = millis();
|
||||||
|
execute("");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoggingClass::addNewDelOldData(const String filename, size_t maxPoints, String payload) {
|
void LoggingClass::execute(String payload) {
|
||||||
|
|
||||||
|
if (_period > 0) {
|
||||||
|
payload = getValue(_loggingValueKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
String filename = "logs/" + _key + ".txt";
|
||||||
String logData = readFile(filename, 5120);
|
String logData = readFile(filename, 5120);
|
||||||
|
|
||||||
size_t lines_cnt = itemsCount(logData, "\r\n");
|
size_t lines_cnt = itemsCount(logData, "\r\n");
|
||||||
|
|
||||||
SerialPrint("I", "Logging", "http://" + WiFi.localIP().toString() + "/" + filename + " (" + String(lines_cnt, DEC) + ")");
|
SerialPrint("I", "Logging", "http://" + WiFi.localIP().toString() + "/" + filename + " (" + String(lines_cnt, DEC) + ")");
|
||||||
|
|
||||||
if ((lines_cnt > maxPoints + 1) || !lines_cnt) {
|
if ((lines_cnt > _maxPoints + 1) || !lines_cnt) {
|
||||||
removeFile(filename);
|
removeFile(filename);
|
||||||
lines_cnt = 0;
|
lines_cnt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (payload != "") {
|
if (payload != "") {
|
||||||
if (lines_cnt > maxPoints) {
|
if (lines_cnt > _maxPoints) {
|
||||||
logData = deleteBeforeDelimiter(logData, "\r\n");
|
logData = deleteBeforeDelimiter(logData, "\r\n");
|
||||||
if (timeNow->hasTimeSynced()) {
|
if (timeNow->hasTimeSynced()) {
|
||||||
logData += timeNow->getTimeUnix() + " " + payload + "\r\n";
|
logData += timeNow->getTimeUnix() + " " + payload + "\r\n";
|
||||||
@@ -61,16 +70,40 @@ void logging() {
|
|||||||
String maxcnt = myLineParsing.gcnt();
|
String maxcnt = myLineParsing.gcnt();
|
||||||
myLineParsing.clear();
|
myLineParsing.clear();
|
||||||
|
|
||||||
loggingKeyList += key + ",";
|
logging_KeyList += key + ",";
|
||||||
|
|
||||||
|
logging_EnterCounter++;
|
||||||
|
addKey(key, logging_KeyList, logging_EnterCounter);
|
||||||
|
|
||||||
static bool firstTime = true;
|
static bool firstTime = true;
|
||||||
if (firstTime) myLogging = new MyLoggingVector();
|
if (firstTime) myLogging = new MyLoggingVector();
|
||||||
firstTime = false;
|
firstTime = false;
|
||||||
myLogging->push_back(LoggingClass(interv.toInt(), maxcnt.toInt(), loggingValueKey, key));
|
myLogging->push_back(LoggingClass(interv.toInt(), maxcnt.toInt(), loggingValueKey, key));
|
||||||
|
|
||||||
|
sCmd.addCommand(key.c_str(), loggingExecute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void loggingExecute() {
|
||||||
|
String key = sCmd.order();
|
||||||
|
String value = sCmd.next();
|
||||||
|
|
||||||
|
if (!isDigitStr(value)) { //если значение - текст
|
||||||
|
value = getValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int number = getKeyNum(key, logging_KeyList);
|
||||||
|
|
||||||
|
if (myLogging != nullptr) {
|
||||||
|
if (number != -1) {
|
||||||
|
myLogging->at(number).execute(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void choose_log_date_and_send() {
|
void choose_log_date_and_send() {
|
||||||
String all_line = loggingKeyList;
|
String all_line = logging_KeyList;
|
||||||
while (all_line.length() != 0) {
|
while (all_line.length() != 0) {
|
||||||
String tmp = selectToMarker(all_line, ",");
|
String tmp = selectToMarker(all_line, ",");
|
||||||
sendLogData("logs/" + tmp + ".txt", tmp);
|
sendLogData("logs/" + tmp + ".txt", tmp);
|
||||||
|
|||||||
Reference in New Issue
Block a user