Gisteresis termostat

This commit is contained in:
Dmitry Borisenko
2020-12-09 04:08:36 +03:00
parent 6e44f76385
commit 6205f6959c
31 changed files with 257 additions and 741 deletions

View File

@@ -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
View 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
View 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

View File

@@ -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
View File

@@ -0,0 +1,4 @@
{
"widget": "chart",
"dateFormat": "HH:mm"
}

View File

@@ -0,0 +1,6 @@
{
"widget" : "input",
"color" : "green",
"type" : "number",
"icon": "thermometer"
}

View File

@@ -0,0 +1,6 @@
{
"widget" : "input",
"color" : "orange",
"type" : "time",
"icon": "alarm-outline"
}

566
doc/1.txt
View File

@@ -1,566 +0,0 @@
***
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/1.png?raw=true)
## Возможности
- Объединение различных по типу и назначению устройств: управление, получение данных, и настройка параметров - всё в одном приложении
- Взаимодействие с устройствами осуществляется через "облачный" сервис с использованием протокола mqtt, позволит контролировать их из любой точки Мира (при наличии доступа в Интернет)
- Поддержка нескольких профилей и их переключение "на лету", дает возможность объединить устройства в группы
Настройка (после "прошивки") производится через веб-интерфейс, чтобы получить к нему доступ необходимо соединиться с WiFi AP устройства и набрать в адресной строке браузера http://192.168.4.1.
Далее выбрать типовой шаблон автоматизации, произвести настройку под свои требования и задачи.
Основные разделы интерфейса: конфигурация и сценарии.
В окне конфигурации задаются "объекты", "элементы управления" устройства (dashboard) - им устройство будет представлено в приложении компаньоне проекта. В окне сценариев задаются реакции на события и изменения в параметрах работы системы.
***
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/1.png?raw=true)
## Команды, назначение и применение
Команды служат для настройки и управления устройством и его взаимодействия
**`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**
***
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/1.png?raw=true)
## 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`
***
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/1.png?raw=true)
## 2.1 Объект "физическая кнопка"
`switch 1 0 10`
**switch** это объект создающий физическую кнопку
**1** номер кнопки
**0** пин кнопки (при подключении необходим подтягивающий резистор)
**10** задержка для избавления от дребезга с мили секундах
## 2.2 Вызов событий объектом "физическая кнопка"
`switch1` может быть равна нулю или единицы, ноль - событие отбрасывания кнопки, единица - событие нажатия
`switch1 = 1`
`buttonChange 1`
`end`
***
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/1.png?raw=true)
## 3.1 Объект "широтноимпульсная модуляция"
`pwm 1 12 яркость освещение 1023 1`
**"pwm"** это объект создающий управление шим в приложении в виде ползунка
**"1"** это номер этого объекта
**"12"** это номер пина на котором будет генерироваться шим заданной в приложении величены
**"Яркость"** это название кнопки в приложении
**"Оповещение"** это название вкладки в приложении на которой появится данная кнопка
**"1023"** это начальное значение шим сигнала и ползунка (изменяется от 0 до 1023)
**"1"** это уникальный номер и номер сортировки данной кнопки. Этот номер должен быть уникален для каждого объекта
## 3.2 Команда управления объектом "широтноимпульсная модуляция"
`pwmSet 1 500`
**"pwmSet"** команда управления объектом
**"1"** номер объекта, которым будем управлять
**"500"** значение которое установится после выполнения команды (от 0 до 1023)
***
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/1.png?raw=true)
## 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`
***
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/1.png?raw=true)
## 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`
***
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/1.png?raw=true)
## 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`
***
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/1.png?raw=true)
## 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`
***
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/1.png?raw=true)
## 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`
***
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/1.png?raw=true)
## 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`
***
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/1.png?raw=true)
## 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`
***
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/1.png?raw=true)
## 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`
Вот что может произойти на разных устройствах по одному событию повышения температуры...
***
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/1.png?raw=true)
## 12 Журнал (лог) данных
`logging analog 1 100 slow Аналоговый#вход Датчики 7`
**logging** объект для логирования
**analog** или **dhtT** или **dhtH** какой сенсор будем логировать, можно указать любой
**1** период между точками в минутах
**100** количество точек (старые точки будут удаляться по мере добавления новых)
**slow** или **fast** метод выгрузки графика в приложение, slow - выгружает график по одной точке (меньше расходуется оперативка, лучше использовать для esp8266), fast - выгрузка графика сразу (больше расход оперативки, подходит для esp32)
**Аналоговый#вход** название графика в приложении
**Датчики** название вкладки в приложении
**7** это уникальный номер и номер сортировки. Этот номер должен быть уникален для каждого объекта
***
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/1.png?raw=true)
## 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

View File

@@ -1,85 +0,0 @@
# В этой инструкции будет описано как с esp отправлять email и push
# Часть 1. Привязать email и pushbullet к сайту pushingbox
### 1. Необходимо перейти на сайт: [pushingbox](https://www.pushingbox.com/)
### 2. Войти с помощью google
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_1.png)
### 3. Перейти в мои сервисы и добавить новый сервис
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_2.png)
### 4. Нас интересуют два сервиса email и pushbullet
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_4%2B.png)
### 5. Выбираем сначало сервис для отправки email. В окно `Name of your email configuration` - вводим слово "email". В окно `Email address` - вводим ваш email адрес. жмем submit
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_5.png)
manager_modules_firmware/blob/master/push_instruction/Screenshot_6.png)
### 6.1 Привязываем pushbullet. Переходим на сайт [pushbullet.com](https://www.pushbullet.com/)
### 6.2 Входим с гуглом или фейсбуком
### 6.3 Идем в настройки
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_7.png)
### 6.4 Создаем токен
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_8.png)
### 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".
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_6.png)
### 7. Теперь наш email и pushbullet привязаны к pushingbox. Далее можно скачать приложение pushbullet на телефон и войти с гуглом или фейсбуком сответственно с пунктом 6.3 этой инструкции
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_9.png)
# Часть 2. Создание сценариев отправки email
### 8.1. Сценарий для отправки email. Заходим в My Scenarios:
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_10.png)
### 8.2 Пишем слово email (это имя сценария отправки email) жмем add:
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_12.png)
### 8.3 Нажимаем add an action
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_14.png)
### 8.4 Выбираем наш email который мы зарегестрировали ранее и нажимаем Add an action with this service
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_11.png)
### 8.5 Делаем все как на скриншоте и жмем submit
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_15.png)
### 8.6 Возвращаемся на мои сценарии
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_17.png)
### 8.7 Вставляем токен в веб интерфейс esp
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_18.png)
# Часть 3. Создание сценариев отправки push
### 9.1. Сценарий для отправки push. Заходим в My Scenarios:
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_10.png)
### 9.2 Пишем слово push (это имя сценария отправки email) жмем add:
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_19.png)
### 9.3 Нажимаем add an action
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_20.png)
### 9.4 Выбираем наш pushbullet который мы зарегестрировали ранее и нажимаем Add an action with this service
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_11.png)
### 9.5 Делаем все как на скриншоте и жмем submit
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_15.png)
### 9.6 Возвращаемся на мои сценарии
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_21.png)
### 9.7 Вставляем токен в веб интерфейс esp
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_18.png)
# Часть 4. Итог
При создании такой конфигурации как на картинке:
`button 1 na Отправить#push Push 0 1`
`button1 = 1`
`push внимание кнопка#нажата`
`end`
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_22.png)
Если мы введем токен для email то будут приходить email
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_17.png)
Если для push то будут приходить push в pushbullet
![](https://github.com/IoTManagerProject/Wiki/tree/master/pictures/push_instruction/Screenshot_21.png)
Способ описанный в данной инструкции более сложный в настройке но зато очень надежный.

View File

@@ -1,32 +0,0 @@
***
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/1.png?raw=true)
### 1. Скачать архив из [релизов](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/releases) или из закрепленного сообщения группы телеграм с последней версией прошивки
***
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/1.png?raw=true)
### 2. Для ESP8266 c 4 и больше мб памяти (все сделать как на скриншотах)
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/esp8266_1.png)
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/esp8266_2.png)
***
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/1.png?raw=true)
### 2. Для ESP8266 c 1 мб памяти (все сделать как на скриншотах)
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/esp8266_1mb_1.png)
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/esp8266_1mb_2.png)
***
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/1.png?raw=true)
### 2. Для ESP32 (все сделать как на скриншотах)
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/esp32_1.png)
![](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/blob/master/pictures/esp32_2.png)

24
doc/eagle.txt Normal file
View 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,

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;

View File

@@ -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();

View File

@@ -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}

View File

@@ -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;

View File

@@ -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();

View File

@@ -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;

View File

@@ -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;
} }

View File

@@ -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");
} }

View File

@@ -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) {

View File

@@ -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);