mirror of
https://github.com/IoTManagerProject/IoTManager.git
synced 2026-03-30 11:59:12 +03:00
Merge branch 'ver4dev' of https://github.com/biveraxe/IoTManager into ver4dev
This commit is contained in:
Binary file not shown.
@@ -382,7 +382,23 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"global": 0,
|
"global": 0,
|
||||||
"name": "26. PZEM 004t Напряжение",
|
"name": "26. Аналоговый счетчик импульсов",
|
||||||
|
"type": "Writing",
|
||||||
|
"subtype": "Impulse",
|
||||||
|
"id": "impulse",
|
||||||
|
"widget": "anydataDef",
|
||||||
|
"page": "Счетчики",
|
||||||
|
"descr": "Импульсов",
|
||||||
|
"needSave": 0,
|
||||||
|
"int": 1,
|
||||||
|
"pin": 16,
|
||||||
|
"pinMode": "INPUT",
|
||||||
|
"debounceDelay": 3,
|
||||||
|
"num": 26
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"global": 0,
|
||||||
|
"name": "27. PZEM 004t Напряжение",
|
||||||
"type": "Reading",
|
"type": "Reading",
|
||||||
"subtype": "Pzem004v",
|
"subtype": "Pzem004v",
|
||||||
"id": "v",
|
"id": "v",
|
||||||
@@ -392,11 +408,11 @@
|
|||||||
"int": 15,
|
"int": 15,
|
||||||
"addr": "0xF8",
|
"addr": "0xF8",
|
||||||
"round": 1,
|
"round": 1,
|
||||||
"num": 26
|
"num": 27
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"global": 0,
|
"global": 0,
|
||||||
"name": "27. PZEM 004t Сила тока",
|
"name": "28. PZEM 004t Сила тока",
|
||||||
"type": "Reading",
|
"type": "Reading",
|
||||||
"subtype": "Pzem004a",
|
"subtype": "Pzem004a",
|
||||||
"id": "a",
|
"id": "a",
|
||||||
@@ -406,11 +422,11 @@
|
|||||||
"int": 15,
|
"int": 15,
|
||||||
"addr": "0xF8",
|
"addr": "0xF8",
|
||||||
"round": 1,
|
"round": 1,
|
||||||
"num": 27
|
"num": 28
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"global": 0,
|
"global": 0,
|
||||||
"name": "28. PZEM 004t Мощность",
|
"name": "29. PZEM 004t Мощность",
|
||||||
"type": "Reading",
|
"type": "Reading",
|
||||||
"subtype": "Pzem004w",
|
"subtype": "Pzem004w",
|
||||||
"id": "w",
|
"id": "w",
|
||||||
@@ -420,11 +436,11 @@
|
|||||||
"int": 15,
|
"int": 15,
|
||||||
"addr": "0xF8",
|
"addr": "0xF8",
|
||||||
"round": 1,
|
"round": 1,
|
||||||
"num": 28
|
"num": 29
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"global": 0,
|
"global": 0,
|
||||||
"name": "29. PZEM 004t Энергия",
|
"name": "30. PZEM 004t Энергия",
|
||||||
"type": "Reading",
|
"type": "Reading",
|
||||||
"subtype": "Pzem004wh",
|
"subtype": "Pzem004wh",
|
||||||
"id": "wh",
|
"id": "wh",
|
||||||
@@ -434,11 +450,11 @@
|
|||||||
"int": 15,
|
"int": 15,
|
||||||
"addr": "0xF8",
|
"addr": "0xF8",
|
||||||
"round": 1,
|
"round": 1,
|
||||||
"num": 29
|
"num": 30
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"global": 0,
|
"global": 0,
|
||||||
"name": "30. PZEM 004t Частота",
|
"name": "31. PZEM 004t Частота",
|
||||||
"type": "Reading",
|
"type": "Reading",
|
||||||
"subtype": "Pzem004hz",
|
"subtype": "Pzem004hz",
|
||||||
"id": "hz",
|
"id": "hz",
|
||||||
@@ -448,11 +464,11 @@
|
|||||||
"int": 15,
|
"int": 15,
|
||||||
"addr": "0xF8",
|
"addr": "0xF8",
|
||||||
"round": 1,
|
"round": 1,
|
||||||
"num": 30
|
"num": 31
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"global": 0,
|
"global": 0,
|
||||||
"name": "31. PZEM 004t Косинус",
|
"name": "32. PZEM 004t Косинус",
|
||||||
"type": "Reading",
|
"type": "Reading",
|
||||||
"subtype": "Pzem004pf",
|
"subtype": "Pzem004pf",
|
||||||
"id": "pf",
|
"id": "pf",
|
||||||
@@ -462,11 +478,11 @@
|
|||||||
"int": 15,
|
"int": 15,
|
||||||
"addr": "0xF8",
|
"addr": "0xF8",
|
||||||
"round": 1,
|
"round": 1,
|
||||||
"num": 31
|
"num": 32
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"global": 0,
|
"global": 0,
|
||||||
"name": "32. PZEM настройка",
|
"name": "33. PZEM настройка",
|
||||||
"type": "Reading",
|
"type": "Reading",
|
||||||
"subtype": "Pzem004cmd",
|
"subtype": "Pzem004cmd",
|
||||||
"id": "set",
|
"id": "set",
|
||||||
@@ -478,11 +494,11 @@
|
|||||||
"changeaddr": 0,
|
"changeaddr": 0,
|
||||||
"setaddr": "0x01",
|
"setaddr": "0x01",
|
||||||
"reset": 0,
|
"reset": 0,
|
||||||
"num": 32
|
"num": 33
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"global": 0,
|
"global": 0,
|
||||||
"name": "33. Часы реального времени",
|
"name": "34. Часы реального времени",
|
||||||
"type": "Reading",
|
"type": "Reading",
|
||||||
"subtype": "RTC",
|
"subtype": "RTC",
|
||||||
"id": "rtc",
|
"id": "rtc",
|
||||||
@@ -498,11 +514,11 @@
|
|||||||
"int": 5,
|
"int": 5,
|
||||||
"btn-setUTime": "0",
|
"btn-setUTime": "0",
|
||||||
"btn-setSysTime": "nil",
|
"btn-setSysTime": "nil",
|
||||||
"num": 33
|
"num": 34
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"global": 0,
|
"global": 0,
|
||||||
"name": "34. Sht20 Температура",
|
"name": "35. Sht20 Температура",
|
||||||
"type": "Reading",
|
"type": "Reading",
|
||||||
"subtype": "Sht20t",
|
"subtype": "Sht20t",
|
||||||
"id": "tmp2",
|
"id": "tmp2",
|
||||||
@@ -511,11 +527,11 @@
|
|||||||
"descr": "Температура",
|
"descr": "Температура",
|
||||||
"int": 15,
|
"int": 15,
|
||||||
"round": 1,
|
"round": 1,
|
||||||
"num": 34
|
"num": 35
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"global": 0,
|
"global": 0,
|
||||||
"name": "35. Sht20 Влажность",
|
"name": "36. Sht20 Влажность",
|
||||||
"type": "Reading",
|
"type": "Reading",
|
||||||
"subtype": "Sht20h",
|
"subtype": "Sht20h",
|
||||||
"id": "Hum2",
|
"id": "Hum2",
|
||||||
@@ -524,11 +540,11 @@
|
|||||||
"descr": "Влажность",
|
"descr": "Влажность",
|
||||||
"int": 15,
|
"int": 15,
|
||||||
"round": 1,
|
"round": 1,
|
||||||
"num": 35
|
"num": 36
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"global": 0,
|
"global": 0,
|
||||||
"name": "36. Sht30 Температура",
|
"name": "37. Sht30 Температура",
|
||||||
"type": "Reading",
|
"type": "Reading",
|
||||||
"subtype": "Sht30t",
|
"subtype": "Sht30t",
|
||||||
"id": "tmp30",
|
"id": "tmp30",
|
||||||
@@ -537,11 +553,11 @@
|
|||||||
"descr": "SHT30 Температура",
|
"descr": "SHT30 Температура",
|
||||||
"int": 15,
|
"int": 15,
|
||||||
"round": 1,
|
"round": 1,
|
||||||
"num": 36
|
"num": 37
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"global": 0,
|
"global": 0,
|
||||||
"name": "37. Sht30 Влажность",
|
"name": "38. Sht30 Влажность",
|
||||||
"type": "Reading",
|
"type": "Reading",
|
||||||
"subtype": "Sht30h",
|
"subtype": "Sht30h",
|
||||||
"id": "Hum30",
|
"id": "Hum30",
|
||||||
@@ -550,12 +566,12 @@
|
|||||||
"descr": "SHT30 Влажность",
|
"descr": "SHT30 Влажность",
|
||||||
"int": 15,
|
"int": 15,
|
||||||
"round": 1,
|
"round": 1,
|
||||||
"num": 37
|
"num": 38
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"global": 0,
|
"global": 0,
|
||||||
"name": "38. HC-SR04 Ультразвуковой дальномер",
|
"name": "39. HC-SR04 Ультразвуковой дальномер",
|
||||||
"num": 38,
|
"num": 39,
|
||||||
"type": "Reading",
|
"type": "Reading",
|
||||||
"subtype": "Sonar",
|
"subtype": "Sonar",
|
||||||
"id": "sonar",
|
"id": "sonar",
|
||||||
@@ -567,7 +583,7 @@
|
|||||||
"int": 5
|
"int": 5
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "39. UART",
|
"name": "40. UART",
|
||||||
"type": "Reading",
|
"type": "Reading",
|
||||||
"subtype": "UART",
|
"subtype": "UART",
|
||||||
"page": "",
|
"page": "",
|
||||||
@@ -579,14 +595,14 @@
|
|||||||
"line": 2,
|
"line": 2,
|
||||||
"speed": 9600,
|
"speed": 9600,
|
||||||
"eventFormat": 0,
|
"eventFormat": 0,
|
||||||
"num": 39
|
"num": 40
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"header": "Исполнительные устройства"
|
"header": "Исполнительные устройства"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"global": 0,
|
"global": 0,
|
||||||
"name": "40. Кнопка подключенная к пину",
|
"name": "41. Кнопка подключенная к пину",
|
||||||
"type": "Writing",
|
"type": "Writing",
|
||||||
"subtype": "ButtonIn",
|
"subtype": "ButtonIn",
|
||||||
"id": "btn",
|
"id": "btn",
|
||||||
@@ -601,11 +617,11 @@
|
|||||||
"debounceDelay": 50,
|
"debounceDelay": 50,
|
||||||
"fixState": 0,
|
"fixState": 0,
|
||||||
"inv": 0,
|
"inv": 0,
|
||||||
"num": 40
|
"num": 41
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"global": 0,
|
"global": 0,
|
||||||
"name": "41. Управление пином",
|
"name": "42. Управление пином",
|
||||||
"type": "Writing",
|
"type": "Writing",
|
||||||
"subtype": "ButtonOut",
|
"subtype": "ButtonOut",
|
||||||
"needSave": 0,
|
"needSave": 0,
|
||||||
@@ -616,11 +632,11 @@
|
|||||||
"int": 0,
|
"int": 0,
|
||||||
"inv": 0,
|
"inv": 0,
|
||||||
"pin": 2,
|
"pin": 2,
|
||||||
"num": 41
|
"num": 42
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"global": 0,
|
"global": 0,
|
||||||
"name": "42. Сервопривод",
|
"name": "43. Сервопривод",
|
||||||
"type": "Writing",
|
"type": "Writing",
|
||||||
"subtype": "IoTServo",
|
"subtype": "IoTServo",
|
||||||
"id": "servo",
|
"id": "servo",
|
||||||
@@ -631,11 +647,11 @@
|
|||||||
"pin": 12,
|
"pin": 12,
|
||||||
"apin": -1,
|
"apin": -1,
|
||||||
"amap": "0, 4096, 0, 180",
|
"amap": "0, 4096, 0, 180",
|
||||||
"num": 42
|
"num": 43
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"global": 0,
|
"global": 0,
|
||||||
"name": "43. Расширитель портов Mcp23017",
|
"name": "44. Расширитель портов Mcp23017",
|
||||||
"type": "Reading",
|
"type": "Reading",
|
||||||
"subtype": "Mcp23017",
|
"subtype": "Mcp23017",
|
||||||
"id": "Mcp",
|
"id": "Mcp",
|
||||||
@@ -645,11 +661,11 @@
|
|||||||
"int": "0",
|
"int": "0",
|
||||||
"addr": "0x20",
|
"addr": "0x20",
|
||||||
"index": 1,
|
"index": 1,
|
||||||
"num": 43
|
"num": 44
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"global": 0,
|
"global": 0,
|
||||||
"name": "44. MP3 плеер",
|
"name": "45. MP3 плеер",
|
||||||
"type": "Reading",
|
"type": "Reading",
|
||||||
"subtype": "Mp3",
|
"subtype": "Mp3",
|
||||||
"id": "mp3",
|
"id": "mp3",
|
||||||
@@ -659,11 +675,11 @@
|
|||||||
"int": 1,
|
"int": 1,
|
||||||
"pins": "14,12",
|
"pins": "14,12",
|
||||||
"volume": 20,
|
"volume": 20,
|
||||||
"num": 44
|
"num": 45
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"global": 0,
|
"global": 0,
|
||||||
"name": "45. Сенсорная кнопка",
|
"name": "46. Сенсорная кнопка",
|
||||||
"type": "Writing",
|
"type": "Writing",
|
||||||
"subtype": "Multitouch",
|
"subtype": "Multitouch",
|
||||||
"id": "impulse",
|
"id": "impulse",
|
||||||
@@ -677,11 +693,11 @@
|
|||||||
"pinMode": "INPUT",
|
"pinMode": "INPUT",
|
||||||
"debounceDelay": 50,
|
"debounceDelay": 50,
|
||||||
"PWMDelay": 500,
|
"PWMDelay": 500,
|
||||||
"num": 45
|
"num": 46
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"global": 0,
|
"global": 0,
|
||||||
"name": "46. Расширитель портов Pcf8574",
|
"name": "47. Расширитель портов Pcf8574",
|
||||||
"type": "Reading",
|
"type": "Reading",
|
||||||
"subtype": "Pcf8574",
|
"subtype": "Pcf8574",
|
||||||
"id": "Pcf",
|
"id": "Pcf",
|
||||||
@@ -691,11 +707,11 @@
|
|||||||
"int": "0",
|
"int": "0",
|
||||||
"addr": "0x20",
|
"addr": "0x20",
|
||||||
"index": 1,
|
"index": 1,
|
||||||
"num": 46
|
"num": 47
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"global": 0,
|
"global": 0,
|
||||||
"name": "47. PWM ESP8266",
|
"name": "48. PWM ESP8266",
|
||||||
"type": "Writing",
|
"type": "Writing",
|
||||||
"subtype": "Pwm8266",
|
"subtype": "Pwm8266",
|
||||||
"id": "pwm",
|
"id": "pwm",
|
||||||
@@ -707,11 +723,11 @@
|
|||||||
"freq": 5000,
|
"freq": 5000,
|
||||||
"val": 0,
|
"val": 0,
|
||||||
"apin": -1,
|
"apin": -1,
|
||||||
"num": 47
|
"num": 48
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"global": 0,
|
"global": 0,
|
||||||
"name": "48. Телеграм-Лайт",
|
"name": "49. Телеграм-Лайт",
|
||||||
"type": "Writing",
|
"type": "Writing",
|
||||||
"subtype": "TelegramLT",
|
"subtype": "TelegramLT",
|
||||||
"id": "tg",
|
"id": "tg",
|
||||||
@@ -720,14 +736,14 @@
|
|||||||
"descr": "",
|
"descr": "",
|
||||||
"token": "",
|
"token": "",
|
||||||
"chatID": "",
|
"chatID": "",
|
||||||
"num": 48
|
"num": 49
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"header": "Экраны"
|
"header": "Экраны"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"global": 0,
|
"global": 0,
|
||||||
"name": "49. LCD экран 2004",
|
"name": "50. LCD экран 2004",
|
||||||
"type": "Reading",
|
"type": "Reading",
|
||||||
"subtype": "Lcd2004",
|
"subtype": "Lcd2004",
|
||||||
"id": "Lcd",
|
"id": "Lcd",
|
||||||
@@ -739,10 +755,10 @@
|
|||||||
"size": "20,4",
|
"size": "20,4",
|
||||||
"coord": "0,0",
|
"coord": "0,0",
|
||||||
"id2show": "id датчика",
|
"id2show": "id датчика",
|
||||||
"num": 49
|
"num": 50
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "50. LCD экран 1602",
|
"name": "51. LCD экран 1602",
|
||||||
"type": "Reading",
|
"type": "Reading",
|
||||||
"subtype": "Lcd2004",
|
"subtype": "Lcd2004",
|
||||||
"id": "Lcd",
|
"id": "Lcd",
|
||||||
@@ -754,6 +770,6 @@
|
|||||||
"size": "16,2",
|
"size": "16,2",
|
||||||
"coord": "0,0",
|
"coord": "0,0",
|
||||||
"id2show": "id датчика",
|
"id2show": "id датчика",
|
||||||
"num": 50
|
"num": 51
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -41,7 +41,25 @@
|
|||||||
"label": "Ватты",
|
"label": "Ватты",
|
||||||
"widget": "anydata",
|
"widget": "anydata",
|
||||||
"after": "Wt",
|
"after": "Wt",
|
||||||
"icon": "speedometer"
|
"icon": "speedometer",
|
||||||
|
"color": [
|
||||||
|
{
|
||||||
|
"level": 0,
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 200,
|
||||||
|
"value": "#009933"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 2000,
|
||||||
|
"value": "#FF9900"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 4000,
|
||||||
|
"value": "red"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "anydataWth",
|
"name": "anydataWth",
|
||||||
@@ -62,7 +80,42 @@
|
|||||||
"label": "Температура",
|
"label": "Температура",
|
||||||
"widget": "anydata",
|
"widget": "anydata",
|
||||||
"after": "°С",
|
"after": "°С",
|
||||||
"icon": "thermometer"
|
"icon": "thermometer",
|
||||||
|
"font": "OCR A Std",
|
||||||
|
"color": [
|
||||||
|
{
|
||||||
|
"level": -20,
|
||||||
|
"value": "#0000CC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": -10,
|
||||||
|
"value": "#0000CC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 0,
|
||||||
|
"value": "#0000CC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 12,
|
||||||
|
"value": "#3366FF"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 16,
|
||||||
|
"value": "#33CCFF"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 18,
|
||||||
|
"value": "#009933"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 30,
|
||||||
|
"value": "#FF9900"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 40,
|
||||||
|
"value": "red"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "anydataMm",
|
"name": "anydataMm",
|
||||||
@@ -225,11 +278,18 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "anydatamWt",
|
"name": "anydatamWt",
|
||||||
"label": "миллиВатты",
|
"label": "миллиВатты",
|
||||||
"widget": "anydata",
|
"widget": "anydata",
|
||||||
"after": "mWt",
|
"after": "mWt",
|
||||||
"icon": "speedometer"
|
"icon": "speedometer"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "anydataCm",
|
||||||
|
"label": "Сантиметры",
|
||||||
|
"widget": "anydata",
|
||||||
|
"after": "cm",
|
||||||
|
"icon": "speedometer"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "nil",
|
"name": "nil",
|
||||||
"label": "Без виджета"
|
"label": "Без виджета"
|
||||||
|
|||||||
Binary file not shown.
@@ -4,12 +4,17 @@
|
|||||||
#ifdef STANDARD_WEB_SERVER
|
#ifdef STANDARD_WEB_SERVER
|
||||||
extern void standWebServerInit();
|
extern void standWebServerInit();
|
||||||
extern bool handleFileRead(String path);
|
extern bool handleFileRead(String path);
|
||||||
extern String getContentType(String filename);
|
//extern String getContentType(String filename);
|
||||||
//#ifdef REST_FILE_OPERATIONS
|
//#ifdef REST_FILE_OPERATIONS
|
||||||
extern void handleFileUpload();
|
extern void handleFileUpload();
|
||||||
extern void handleFileDelete();
|
extern void handleFileDelete();
|
||||||
extern void handleFileCreate();
|
extern void handleFileCreate();
|
||||||
extern void handleFileList();
|
extern void handleFileList();
|
||||||
void printDirectory(File dir, String& out);
|
//void printDirectory(File dir, String& out);
|
||||||
|
extern void handleStatus();
|
||||||
|
extern void handleGetEdit();
|
||||||
|
extern void replyOK ();
|
||||||
|
extern void handleNotFound ();
|
||||||
|
|
||||||
//#endif
|
//#endif
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -136,6 +136,10 @@
|
|||||||
"path": "src/modules/sensors/Hx711",
|
"path": "src/modules/sensors/Hx711",
|
||||||
"active": false
|
"active": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "src/modules/sensors/Impulse",
|
||||||
|
"active": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "src/modules/sensors/Ina219",
|
"path": "src/modules/sensors/Ina219",
|
||||||
"active": false
|
"active": false
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ build_src_filter =
|
|||||||
[env:esp8266_2mb_ota]
|
[env:esp8266_2mb_ota]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${common_env_data.lib_deps_external}
|
${common_env_data.lib_deps_external}
|
||||||
${env:esp8266_2mb_fromitems.lib_deps}
|
${env:esp8266_2mb_ota_fromitems.lib_deps}
|
||||||
ESPAsyncUDP
|
ESPAsyncUDP
|
||||||
build_flags = -Desp8266_2mb_ota="esp8266_2mb_ota"
|
build_flags = -Desp8266_2mb_ota="esp8266_2mb_ota"
|
||||||
framework = arduino
|
framework = arduino
|
||||||
@@ -110,7 +110,7 @@ build_src_filter =
|
|||||||
+<classes/*.cpp>
|
+<classes/*.cpp>
|
||||||
+<utils/*.cpp>
|
+<utils/*.cpp>
|
||||||
+<modules/*.cpp>
|
+<modules/*.cpp>
|
||||||
${env:esp8266_2mb_fromitems.build_src_filter}
|
${env:esp8266_2mb_ota_fromitems.build_src_filter}
|
||||||
|
|
||||||
[env:esp8285_1mb]
|
[env:esp8285_1mb]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
@@ -232,6 +232,7 @@ build_src_filter =
|
|||||||
|
|
||||||
[env:esp8266_2mb_ota_fromitems]
|
[env:esp8266_2mb_ota_fromitems]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
|
adafruit/Adafruit BME280 Library
|
||||||
plerup/EspSoftwareSerial
|
plerup/EspSoftwareSerial
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
+<modules/virtual/Cron>
|
+<modules/virtual/Cron>
|
||||||
@@ -241,6 +242,7 @@ build_src_filter =
|
|||||||
+<modules/virtual/Variable>
|
+<modules/virtual/Variable>
|
||||||
+<modules/virtual/VariableColor>
|
+<modules/virtual/VariableColor>
|
||||||
+<modules/virtual/VButton>
|
+<modules/virtual/VButton>
|
||||||
|
+<modules/sensors/Bme280>
|
||||||
+<modules/sensors/Pzem004t>
|
+<modules/sensors/Pzem004t>
|
||||||
+<modules/sensors/UART>
|
+<modules/sensors/UART>
|
||||||
+<modules/exec/TelegramLT>
|
+<modules/exec/TelegramLT>
|
||||||
@@ -332,6 +334,7 @@ build_src_filter =
|
|||||||
+<modules/sensors/Bmp280>
|
+<modules/sensors/Bmp280>
|
||||||
+<modules/sensors/Dht1122>
|
+<modules/sensors/Dht1122>
|
||||||
+<modules/sensors/Ds18b20>
|
+<modules/sensors/Ds18b20>
|
||||||
|
+<modules/sensors/Impulse>
|
||||||
+<modules/sensors/Pzem004t>
|
+<modules/sensors/Pzem004t>
|
||||||
+<modules/sensors/RTC>
|
+<modules/sensors/RTC>
|
||||||
+<modules/sensors/Sht20>
|
+<modules/sensors/Sht20>
|
||||||
|
|||||||
@@ -1,9 +1,17 @@
|
|||||||
#include "StandWebServer.h"
|
#include "StandWebServer.h"
|
||||||
#ifdef STANDARD_WEB_SERVER
|
#ifdef STANDARD_WEB_SERVER
|
||||||
|
|
||||||
File fsUploadFile;
|
File uploadFile;
|
||||||
|
String unsupportedFiles = String();
|
||||||
|
|
||||||
void standWebServerInit() {
|
static const char TEXT_PLAIN[] PROGMEM = "text/plain";
|
||||||
|
static const char FS_INIT_ERROR[] PROGMEM = "FS INIT ERROR";
|
||||||
|
static const char FILE_NOT_FOUND[] PROGMEM = "FileNotFound";
|
||||||
|
//static bool fsOK;
|
||||||
|
//const char* fsName = "LittleFS";
|
||||||
|
|
||||||
|
void standWebServerInit()
|
||||||
|
{
|
||||||
// Кэшировать файлы для быстрой работы
|
// Кэшировать файлы для быстрой работы
|
||||||
HTTP.serveStatic("/bundle.js", FileFS, "/", "max-age=31536000"); // кеширование на 1 год
|
HTTP.serveStatic("/bundle.js", FileFS, "/", "max-age=31536000"); // кеширование на 1 год
|
||||||
HTTP.serveStatic("/bundle.css", FileFS, "/", "max-age=31536000"); // кеширование на 1 год
|
HTTP.serveStatic("/bundle.css", FileFS, "/", "max-age=31536000"); // кеширование на 1 год
|
||||||
@@ -41,18 +49,18 @@ void standWebServerInit() {
|
|||||||
|
|
||||||
HTTP.on("/set", HTTP_GET, []() {
|
HTTP.on("/set", HTTP_GET, []() {
|
||||||
if (HTTP.hasArg(F("routerssid")) && WiFi.getMode() == WIFI_AP) {
|
if (HTTP.hasArg(F("routerssid")) && WiFi.getMode() == WIFI_AP) {
|
||||||
jsonWriteStr(settingsFlashJson, F("routerssid"), HTTP.arg(F("routerssid")));
|
jsonWriteStr(settingsFlashJson, F("routerssid"), HTTP.arg(F("routerssid")));
|
||||||
syncSettingsFlashJson();
|
syncSettingsFlashJson();
|
||||||
HTTP.send(200, "text/plain", "ok");
|
HTTP.send(200, "text/plain", "ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HTTP.hasArg(F("routerpass")) && WiFi.getMode() == WIFI_AP) {
|
if (HTTP.hasArg(F("routerpass")) && WiFi.getMode() == WIFI_AP) {
|
||||||
jsonWriteStr(settingsFlashJson, F("routerpass"), HTTP.arg(F("routerpass")));
|
jsonWriteStr(settingsFlashJson, F("routerpass"), HTTP.arg(F("routerpass")));
|
||||||
syncSettingsFlashJson();
|
syncSettingsFlashJson();
|
||||||
HTTP.send(200, "text/plain", "ok");
|
HTTP.send(200, "text/plain", "ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Добавляем функцию Update для перезаписи прошивки по WiFi при 1М(256K FileFS) и выше
|
// Добавляем функцию Update для перезаписи прошивки по WiFi при 1М(256K FileFS) и выше
|
||||||
// httpUpdater.setup(&HTTP);
|
// httpUpdater.setup(&HTTP);
|
||||||
@@ -60,193 +68,640 @@ void standWebServerInit() {
|
|||||||
// Запускаем HTTP сервер
|
// Запускаем HTTP сервер
|
||||||
HTTP.begin();
|
HTTP.begin();
|
||||||
|
|
||||||
//#ifdef REST_FILE_OPERATIONS
|
|
||||||
// SPIFFS.begin();
|
|
||||||
// {
|
|
||||||
// Dir dir = SPIFFS.openDir("/");
|
|
||||||
// while (dir.next()) {
|
|
||||||
// String fileName = dir.fileName();
|
|
||||||
// size_t fileSize = dir.fileSize();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// HTTP страницы для работы с FFS
|
// HTTP страницы для работы с FFS
|
||||||
|
|
||||||
// list directory
|
////////////////////////////////
|
||||||
|
// WEB SERVER INIT
|
||||||
|
|
||||||
|
// Filesystem status
|
||||||
|
HTTP.on("/status", HTTP_GET, handleStatus);
|
||||||
|
|
||||||
|
// List directory
|
||||||
HTTP.on("/list", HTTP_GET, handleFileList);
|
HTTP.on("/list", HTTP_GET, handleFileList);
|
||||||
|
|
||||||
//загрузка редактора editor
|
// Load editor
|
||||||
HTTP.on("/edit", HTTP_GET, []() {
|
HTTP.on("/edit", HTTP_GET, handleGetEdit);
|
||||||
if (!HTTP.args()) {
|
|
||||||
if (!handleFileRead("/edit.htm")) HTTP.send(404, "text/plain", "FileNotFound");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HTTP.hasArg("list")) {
|
// Create file
|
||||||
handleFileList();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HTTP.hasArg("edit")) {
|
|
||||||
if (!handleFileRead(HTTP.arg("edit"))) HTTP.send(404, "text/plain", "FileNotFound");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HTTP.hasArg("download")) {
|
|
||||||
if (!handleFileRead(HTTP.arg("download"))) HTTP.send(404, "text/plain", "FileNotFound");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//Создание файла
|
|
||||||
HTTP.on("/edit", HTTP_PUT, handleFileCreate);
|
HTTP.on("/edit", HTTP_PUT, handleFileCreate);
|
||||||
|
|
||||||
//Удаление файла
|
// Delete file
|
||||||
HTTP.on("/edit", HTTP_DELETE, handleFileDelete);
|
HTTP.on("/edit", HTTP_DELETE, handleFileDelete);
|
||||||
|
|
||||||
//Изменение файла
|
// Upload file
|
||||||
HTTP.on(
|
// - first callback is called after the request has ended with all parsed arguments
|
||||||
"/edit", HTTP_POST, []() {
|
// - second callback handles file upload at that location
|
||||||
HTTP.send(200, "text/plain", "");
|
HTTP.on("/edit", HTTP_POST, replyOK, handleFileUpload);
|
||||||
},
|
|
||||||
handleFileUpload);
|
|
||||||
|
|
||||||
// called when the url is not defined here
|
// Default handler for all URIs not defined above
|
||||||
HTTP.onNotFound([]() {
|
// Use it to read files from filesystem
|
||||||
if (!handleFileRead(HTTP.uri()))
|
HTTP.onNotFound(handleNotFound);
|
||||||
HTTP.send(404, "text/plain", "FileNotFound");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool handleFileRead(String path) {
|
////////////////////////////////
|
||||||
path = "/" + path;
|
// Utils to return HTTP codes, and determine content-type
|
||||||
if (path.endsWith("/")) path += "index.html";
|
|
||||||
String contentType = getContentType(path);
|
void replyOK()
|
||||||
String pathWithGz = path + ".gz";
|
{
|
||||||
if (FileFS.exists(pathWithGz) || FileFS.exists(path)) {
|
HTTP.send(200, FPSTR(TEXT_PLAIN), "");
|
||||||
if (FileFS.exists(pathWithGz))
|
}
|
||||||
path += ".gz";
|
|
||||||
|
void replyOKWithMsg(String msg)
|
||||||
|
{
|
||||||
|
HTTP.send(200, FPSTR(TEXT_PLAIN), msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void replyNotFound(String msg)
|
||||||
|
{
|
||||||
|
HTTP.send(404, FPSTR(TEXT_PLAIN), msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void replyBadRequest(String msg)
|
||||||
|
{
|
||||||
|
// DBG_OUTPUT_PORT.println(msg);
|
||||||
|
HTTP.send(400, FPSTR(TEXT_PLAIN), msg + "\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void replyServerError(String msg)
|
||||||
|
{
|
||||||
|
// DBG_OUTPUT_PORT.println(msg);
|
||||||
|
HTTP.send(500, FPSTR(TEXT_PLAIN), msg + "\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Return the FS type, status and size info
|
||||||
|
*/
|
||||||
|
void handleStatus()
|
||||||
|
{
|
||||||
|
// DBG_OUTPUT_PORT.println("handleStatus");
|
||||||
|
String json;
|
||||||
|
json.reserve(128);
|
||||||
|
|
||||||
|
json = "{\"type\":\"";
|
||||||
|
json += FS_NAME;
|
||||||
|
json += "\", \"isOk\":";
|
||||||
|
|
||||||
|
#ifdef ESP8266
|
||||||
|
FSInfo fs_info;
|
||||||
|
|
||||||
|
FileFS.info(fs_info);
|
||||||
|
json += F("\"true\", \"totalBytes\":\"");
|
||||||
|
json += fs_info.totalBytes;
|
||||||
|
json += F("\", \"usedBytes\":\"");
|
||||||
|
json += fs_info.usedBytes;
|
||||||
|
json += "\"";
|
||||||
|
#endif
|
||||||
|
#ifdef ESP32
|
||||||
|
json += F("\"true\", \"totalBytes\":\"");
|
||||||
|
json += String(FileFS.totalBytes());
|
||||||
|
json += F("\", \"usedBytes\":\"");
|
||||||
|
json += String(FileFS.usedBytes());
|
||||||
|
json += "\"";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
json += F(",\"unsupportedFiles\":\"");
|
||||||
|
json += unsupportedFiles;
|
||||||
|
json += "\"}";
|
||||||
|
|
||||||
|
HTTP.send(200, "application/json", json);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
String getContentType(String filename) {
|
||||||
|
if (HTTP.hasArg("download")) {
|
||||||
|
return "application/octet-stream";
|
||||||
|
} else if (filename.endsWith(".htm")) {
|
||||||
|
return "text/html";
|
||||||
|
} else if (filename.endsWith(".html")) {
|
||||||
|
return "text/html";
|
||||||
|
} else if (filename.endsWith(".css")) {
|
||||||
|
return "text/css";
|
||||||
|
} else if (filename.endsWith(".js")) {
|
||||||
|
return "application/javascript";
|
||||||
|
} else if (filename.endsWith(".png")) {
|
||||||
|
return "image/png";
|
||||||
|
} else if (filename.endsWith(".gif")) {
|
||||||
|
return "image/gif";
|
||||||
|
} else if (filename.endsWith(".jpg")) {
|
||||||
|
return "image/jpeg";
|
||||||
|
} else if (filename.endsWith(".ico")) {
|
||||||
|
return "image/x-icon";
|
||||||
|
} else if (filename.endsWith(".xml")) {
|
||||||
|
return "text/xml";
|
||||||
|
} else if (filename.endsWith(".pdf")) {
|
||||||
|
return "application/x-pdf";
|
||||||
|
} else if (filename.endsWith(".zip")) {
|
||||||
|
return "application/x-zip";
|
||||||
|
} else if (filename.endsWith(".gz")) {
|
||||||
|
return "application/x-gzip";
|
||||||
|
}
|
||||||
|
return "text/plain";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
Read the given file from the filesystem and stream it back to the client
|
||||||
|
*/
|
||||||
|
bool handleFileRead(String path)
|
||||||
|
{
|
||||||
|
// DBG_OUTPUT_PORT.println(String("handleFileRead: ") + path);
|
||||||
|
if (path.endsWith("/"))
|
||||||
|
{
|
||||||
|
path += "index.html";
|
||||||
|
}
|
||||||
|
|
||||||
|
String contentType;
|
||||||
|
if (HTTP.hasArg("download"))
|
||||||
|
{
|
||||||
|
contentType = F("application/octet-stream");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef ESP32
|
||||||
|
contentType = getContentType(path);
|
||||||
|
#endif
|
||||||
|
#ifdef ESP8266
|
||||||
|
contentType = mime::getContentType(path);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FileFS.exists(path))
|
||||||
|
{
|
||||||
|
// File not found, try gzip version
|
||||||
|
path = path + ".gz";
|
||||||
|
}
|
||||||
|
if (FileFS.exists(path))
|
||||||
|
{
|
||||||
File file = FileFS.open(path, "r");
|
File file = FileFS.open(path, "r");
|
||||||
if (contentType == "application/octet-stream")
|
if (HTTP.streamFile(file, contentType) != file.size())
|
||||||
HTTP.sendHeader("Content-Disposition", "attachment;filename=" + (String)file.name());
|
{
|
||||||
HTTP.streamFile(file, contentType);
|
// DBG_OUTPUT_PORT.println("Sent less data than expected!");
|
||||||
|
}
|
||||||
file.close();
|
file.close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getContentType(String filename) {
|
/*
|
||||||
if (HTTP.hasArg("download"))
|
As some FS (e.g. LittleFS) delete the parent folder when the last child has been removed,
|
||||||
return "application/octet-stream";
|
return the path of the closest parent still existing
|
||||||
else if (filename.endsWith(".htm"))
|
*/
|
||||||
return "text/html";
|
String lastExistingParent(String path)
|
||||||
else if (filename.endsWith(".html"))
|
{
|
||||||
return "text/html";
|
while (!path.isEmpty() && !FileFS.exists(path))
|
||||||
else if (filename.endsWith(".txt"))
|
{
|
||||||
return "text/plain";
|
if (path.lastIndexOf('/') > 0)
|
||||||
else if (filename.endsWith(".json"))
|
{
|
||||||
return "application/json";
|
path = path.substring(0, path.lastIndexOf('/'));
|
||||||
else if (filename.endsWith(".css"))
|
}
|
||||||
return "text/css";
|
else
|
||||||
else if (filename.endsWith(".js"))
|
{
|
||||||
return "application/javascript";
|
path = String(); // No slash => the top folder does not exist
|
||||||
else if (filename.endsWith(".png"))
|
}
|
||||||
return "image/png";
|
}
|
||||||
else if (filename.endsWith(".gif"))
|
// DBG_OUTPUT_PORT.println(String("Last existing parent: ") + path);
|
||||||
return "image/gif";
|
return path;
|
||||||
else if (filename.endsWith(".jpg"))
|
|
||||||
return "image/jpeg";
|
|
||||||
else if (filename.endsWith(".ico"))
|
|
||||||
return "image/x-icon";
|
|
||||||
else if (filename.endsWith(".xml"))
|
|
||||||
return "text/xml";
|
|
||||||
else if (filename.endsWith(".pdf"))
|
|
||||||
return "application/x-pdf";
|
|
||||||
else if (filename.endsWith(".zip"))
|
|
||||||
return "application/x-zip";
|
|
||||||
else if (filename.endsWith(".gz"))
|
|
||||||
return "application/x-gzip";
|
|
||||||
return "text/plain";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Здесь функции для работы с файловой системой
|
/*
|
||||||
void handleFileUpload() {
|
Handle a file upload request
|
||||||
if (HTTP.uri() != "/edit") return;
|
*/
|
||||||
HTTPUpload& upload = HTTP.upload();
|
void handleFileUpload()
|
||||||
if (upload.status == UPLOAD_FILE_START) {
|
{
|
||||||
|
if (HTTP.uri() != "/edit")
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
HTTPUpload &upload = HTTP.upload();
|
||||||
|
if (upload.status == UPLOAD_FILE_START)
|
||||||
|
{
|
||||||
String filename = upload.filename;
|
String filename = upload.filename;
|
||||||
if (!filename.startsWith("/")) filename = "/" + filename;
|
// Make sure paths always start with "/"
|
||||||
fsUploadFile = FileFS.open(filename, "w");
|
if (!filename.startsWith("/"))
|
||||||
filename = String();
|
{
|
||||||
} else if (upload.status == UPLOAD_FILE_WRITE) {
|
filename = "/" + filename;
|
||||||
// Serial.print("handleFileUpload Data: "); Serial.println(upload.currentSize);
|
}
|
||||||
if (fsUploadFile)
|
// DBG_OUTPUT_PORT.println(String("handleFileUpload Name: ") + filename);
|
||||||
fsUploadFile.write(upload.buf, upload.currentSize);
|
uploadFile = FileFS.open(filename, "w");
|
||||||
} else if (upload.status == UPLOAD_FILE_END) {
|
if (!uploadFile)
|
||||||
if (fsUploadFile)
|
{
|
||||||
fsUploadFile.close();
|
return replyServerError(F("CREATE FAILED"));
|
||||||
|
}
|
||||||
|
// DBG_OUTPUT_PORT.println(String("Upload: START, filename: ") + filename);
|
||||||
|
}
|
||||||
|
else if (upload.status == UPLOAD_FILE_WRITE)
|
||||||
|
{
|
||||||
|
if (uploadFile)
|
||||||
|
{
|
||||||
|
size_t bytesWritten = uploadFile.write(upload.buf, upload.currentSize);
|
||||||
|
if (bytesWritten != upload.currentSize)
|
||||||
|
{
|
||||||
|
return replyServerError(F("WRITE FAILED"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// DBG_OUTPUT_PORT.println(String("Upload: WRITE, Bytes: ") + upload.currentSize);
|
||||||
|
}
|
||||||
|
else if (upload.status == UPLOAD_FILE_END)
|
||||||
|
{
|
||||||
|
if (uploadFile)
|
||||||
|
{
|
||||||
|
uploadFile.close();
|
||||||
|
}
|
||||||
|
// DBG_OUTPUT_PORT.println(String("Upload: END, Size: ") + upload.totalSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleFileDelete() {
|
|
||||||
if (HTTP.args() == 0) return HTTP.send(500, "text/plain", "BAD ARGS");
|
#ifdef ESP8266
|
||||||
|
void deleteRecursive(String path)
|
||||||
|
{
|
||||||
|
File file = FileFS.open(path, "r");
|
||||||
|
bool isDir = file.isDirectory();
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
// If it's a plain file, delete it
|
||||||
|
if (!isDir)
|
||||||
|
{
|
||||||
|
FileFS.remove(path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Dir dir = FileFS.openDir(path);
|
||||||
|
while (dir.next())
|
||||||
|
{
|
||||||
|
deleteRecursive(path + '/' + dir.fileName());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then delete the folder itself
|
||||||
|
FileFS.rmdir(path);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
struct treename{
|
||||||
|
uint8_t type;
|
||||||
|
char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void deleteRecursive( String path ){
|
||||||
|
fs::File dir = FileFS.open( path );
|
||||||
|
|
||||||
|
if(!dir.isDirectory()){
|
||||||
|
Serial.printf("%s is a file\n", path);
|
||||||
|
dir.close();
|
||||||
|
Serial.printf( "result of removing file %s: %d\n", path, FileFS.remove( path ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.printf("%s is a directory\n", path);
|
||||||
|
|
||||||
|
fs::File entry, nextentry;
|
||||||
|
|
||||||
|
while ( entry = dir.openNextFile() ){
|
||||||
|
|
||||||
|
if ( entry.isDirectory() ){
|
||||||
|
deleteRecursive( entry.path() );
|
||||||
|
} else{
|
||||||
|
String tmpname = path+"/"+strdup( entry.name() ); // buffer file name
|
||||||
|
entry.close();
|
||||||
|
Serial.printf( "result of removing file %s: %d\n", tmpname, FileFS.remove( tmpname ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
dir.close();
|
||||||
|
Serial.printf( "result of removing directory %s: %d\n", path, FileFS.rmdir( path ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
Handle a file deletion request
|
||||||
|
Operation | req.responseText
|
||||||
|
---------------+--------------------------------------------------------------
|
||||||
|
Delete file | parent of deleted file, or remaining ancestor
|
||||||
|
Delete folder | parent of deleted folder, or remaining ancestor
|
||||||
|
*/
|
||||||
|
void handleFileDelete()
|
||||||
|
{
|
||||||
String path = HTTP.arg(0);
|
String path = HTTP.arg(0);
|
||||||
if (path == "/")
|
if (path.isEmpty() || path == "/")
|
||||||
return HTTP.send(500, "text/plain", "BAD PATH");
|
{
|
||||||
|
return replyBadRequest("BAD PATH");
|
||||||
|
}
|
||||||
|
|
||||||
|
// DBG_OUTPUT_PORT.println(String("handleFileDelete: ") + path);
|
||||||
if (!FileFS.exists(path))
|
if (!FileFS.exists(path))
|
||||||
return HTTP.send(404, "text/plain", "FileNotFound");
|
{
|
||||||
FileFS.remove(path);
|
return replyNotFound(FPSTR(FILE_NOT_FOUND));
|
||||||
HTTP.send(200, "text/plain", "");
|
}
|
||||||
path = String();
|
deleteRecursive(path);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
replyOKWithMsg(lastExistingParent(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleFileCreate() {
|
/*
|
||||||
if (HTTP.args() == 0)
|
Handle the creation/rename of a new file
|
||||||
return HTTP.send(500, "text/plain", "BAD ARGS");
|
Operation | req.responseText
|
||||||
String path = HTTP.arg(0);
|
---------------+--------------------------------------------------------------
|
||||||
|
Create file | parent of created file
|
||||||
|
Create folder | parent of created folder
|
||||||
|
Rename file | parent of source file
|
||||||
|
Move file | parent of source file, or remaining ancestor
|
||||||
|
Rename folder | parent of source folder
|
||||||
|
Move folder | parent of source folder, or remaining ancestor
|
||||||
|
*/
|
||||||
|
void handleFileCreate()
|
||||||
|
{
|
||||||
|
String path = HTTP.arg("path");
|
||||||
|
if (path.isEmpty())
|
||||||
|
{
|
||||||
|
return replyBadRequest(F("PATH ARG MISSING"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_SPIFFS
|
||||||
|
if (checkForUnsupportedPath(path).length() > 0)
|
||||||
|
{
|
||||||
|
return replyServerError(F("INVALID FILENAME"));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (path == "/")
|
if (path == "/")
|
||||||
return HTTP.send(500, "text/plain", "BAD PATH");
|
{
|
||||||
|
return replyBadRequest("BAD PATH");
|
||||||
|
}
|
||||||
if (FileFS.exists(path))
|
if (FileFS.exists(path))
|
||||||
return HTTP.send(500, "text/plain", "FILE EXISTS");
|
{
|
||||||
File file = FileFS.open(path, "w");
|
return replyBadRequest(F("PATH FILE EXISTS"));
|
||||||
if (file)
|
}
|
||||||
file.close();
|
|
||||||
|
String src = HTTP.arg("src");
|
||||||
|
if (src.isEmpty())
|
||||||
|
{
|
||||||
|
// No source specified: creation
|
||||||
|
// DBG_OUTPUT_PORT.println(String("handleFileCreate: ") + path);
|
||||||
|
if (path.endsWith("/"))
|
||||||
|
{
|
||||||
|
// Create a folder
|
||||||
|
path.remove(path.length() - 1);
|
||||||
|
if (!FileFS.mkdir(path))
|
||||||
|
{
|
||||||
|
return replyServerError(F("MKDIR FAILED"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Create a file
|
||||||
|
File file = FileFS.open(path, "w");
|
||||||
|
if (file)
|
||||||
|
{
|
||||||
|
#ifdef ESP8266
|
||||||
|
file.write((const char *)0);
|
||||||
|
#endif
|
||||||
|
#ifdef ESP32
|
||||||
|
file.write(0);
|
||||||
|
#endif
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return replyServerError(F("CREATE FAILED"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (path.lastIndexOf('/') > -1)
|
||||||
|
{
|
||||||
|
path = path.substring(0, path.lastIndexOf('/'));
|
||||||
|
}
|
||||||
|
replyOKWithMsg(path);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return HTTP.send(500, "text/plain", "CREATE FAILED");
|
{
|
||||||
HTTP.send(200, "text/plain", "");
|
// Source specified: rename
|
||||||
path = String();
|
if (src == "/")
|
||||||
|
{
|
||||||
|
return replyBadRequest("BAD SRC");
|
||||||
|
}
|
||||||
|
if (!FileFS.exists(src))
|
||||||
|
{
|
||||||
|
return replyBadRequest(F("SRC FILE NOT FOUND"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// DBG_OUTPUT_PORT.println(String("handleFileCreate: ") + path + " from " + src);
|
||||||
|
|
||||||
|
if (path.endsWith("/"))
|
||||||
|
{
|
||||||
|
path.remove(path.length() - 1);
|
||||||
|
}
|
||||||
|
if (src.endsWith("/"))
|
||||||
|
{
|
||||||
|
src.remove(src.length() - 1);
|
||||||
|
}
|
||||||
|
if (!FileFS.rename(src, path))
|
||||||
|
{
|
||||||
|
return replyServerError(F("RENAME FAILED"));
|
||||||
|
}
|
||||||
|
replyOKWithMsg(lastExistingParent(src));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleFileList() {
|
/*
|
||||||
File dir = FileFS.open("/", "r");
|
Return the list of files in the directory specified by the "dir" query string parameter.
|
||||||
String output = "[";
|
Also demonstrates the use of chunked responses.
|
||||||
File entry;
|
*/
|
||||||
while (entry = dir.openNextFile()) {
|
#ifdef ESP8266
|
||||||
if (output != "[") output += ',';
|
void handleFileList()
|
||||||
bool isDir = entry.isDirectory();
|
{
|
||||||
|
if (!HTTP.hasArg("dir"))
|
||||||
|
{
|
||||||
|
return replyBadRequest(F("DIR ARG MISSING"));
|
||||||
|
}
|
||||||
|
|
||||||
|
String path = HTTP.arg("dir");
|
||||||
|
if (path != "/" && !FileFS.exists(path))
|
||||||
|
{
|
||||||
|
return replyBadRequest("BAD PATH");
|
||||||
|
}
|
||||||
|
|
||||||
|
// DBG_OUTPUT_PORT.println(String("handleFileList: ") + path);
|
||||||
|
Dir dir = FileFS.openDir(path);
|
||||||
|
path.clear();
|
||||||
|
|
||||||
|
// use HTTP/1.1 Chunked response to avoid building a huge temporary string
|
||||||
|
if (!HTTP.chunkedResponseModeStart(200, "text/json"))
|
||||||
|
{
|
||||||
|
HTTP.send(505, F("text/html"), F("HTTP1.1 required"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use the same string for every line
|
||||||
|
String output;
|
||||||
|
output.reserve(64);
|
||||||
|
while (dir.next())
|
||||||
|
{
|
||||||
|
#ifdef USE_SPIFFS
|
||||||
|
String error = checkForUnsupportedPath(dir.fileName());
|
||||||
|
if (error.length() > 0)
|
||||||
|
{
|
||||||
|
// DBG_OUTPUT_PORT.println(String("Ignoring ") + error + dir.fileName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (output.length())
|
||||||
|
{
|
||||||
|
// send string from previous iteration
|
||||||
|
// as an HTTP chunk
|
||||||
|
HTTP.sendContent(output);
|
||||||
|
output = ',';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
output = '[';
|
||||||
|
}
|
||||||
|
|
||||||
output += "{\"type\":\"";
|
output += "{\"type\":\"";
|
||||||
output += (isDir) ? "dir" : "file";
|
if (dir.isDirectory())
|
||||||
output += "\",\"name\":\"";
|
{
|
||||||
output += String(entry.name());
|
output += "dir";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
output += F("file\",\"size\":\"");
|
||||||
|
output += dir.fileSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
output += F("\",\"name\":\"");
|
||||||
|
// Always return names without leading "/"
|
||||||
|
if (dir.fileName()[0] == '/')
|
||||||
|
{
|
||||||
|
output += &(dir.fileName()[1]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
output += dir.fileName();
|
||||||
|
}
|
||||||
|
|
||||||
output += "\"}";
|
output += "\"}";
|
||||||
entry.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// send last string
|
||||||
output += "]";
|
output += "]";
|
||||||
//Serial.println(output);
|
HTTP.sendContent(output);
|
||||||
HTTP.send(200, "text/json", output);
|
HTTP.chunkedResponseFinalize();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
void handleFileList() {
|
||||||
|
if (!HTTP.hasArg("dir")) {
|
||||||
|
HTTP.send(500, "text/plain", "BAD ARGS");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String path = HTTP.arg("dir");
|
||||||
|
// DBG_OUTPUT_PORT.println("handleFileList: " + path);
|
||||||
|
|
||||||
|
|
||||||
|
File root = FileFS.open(path);
|
||||||
|
path = String();
|
||||||
|
|
||||||
|
String output = "[";
|
||||||
|
if(root.isDirectory()){
|
||||||
|
File file = root.openNextFile();
|
||||||
|
while(file){
|
||||||
|
if (output != "[") {
|
||||||
|
output += ',';
|
||||||
|
}
|
||||||
|
output += "{\"type\":\"";
|
||||||
|
// output += (file.isDirectory()) ? "dir" : "file";
|
||||||
|
if (file.isDirectory())
|
||||||
|
{
|
||||||
|
output += "dir";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
output += F("file\",\"size\":\"");
|
||||||
|
output += file.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
output += "\",\"name\":\"";
|
||||||
|
output += String(file.name());
|
||||||
|
output += "\"}";
|
||||||
|
file = root.openNextFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output += "]";
|
||||||
|
HTTP.send(200, "text/json", output);
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
The "Not Found" handler catches all URI not explicitly declared in code
|
||||||
|
First try to find and return the requested file from the filesystem,
|
||||||
|
and if it fails, return a 404 page with debug information
|
||||||
|
*/
|
||||||
|
void handleNotFound()
|
||||||
|
{
|
||||||
|
#ifdef ESP8266
|
||||||
|
String uri = ESP8266WebServer::urlDecode(HTTP.uri()); // required to read paths with blanks
|
||||||
|
#endif
|
||||||
|
#ifdef ESP32
|
||||||
|
String uri = WebServer::urlDecode(HTTP.uri()); // required to read paths with blanks
|
||||||
|
#endif
|
||||||
|
if (handleFileRead(uri))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dump debug data
|
||||||
|
String message;
|
||||||
|
message.reserve(100);
|
||||||
|
message = F("Error: File not found\n\nURI: ");
|
||||||
|
message += uri;
|
||||||
|
message += F("\nMethod: ");
|
||||||
|
message += (HTTP.method() == HTTP_GET) ? "GET" : "POST";
|
||||||
|
message += F("\nArguments: ");
|
||||||
|
message += HTTP.args();
|
||||||
|
message += '\n';
|
||||||
|
for (uint8_t i = 0; i < HTTP.args(); i++)
|
||||||
|
{
|
||||||
|
message += F(" NAME:");
|
||||||
|
message += HTTP.argName(i);
|
||||||
|
message += F("\n VALUE:");
|
||||||
|
message += HTTP.arg(i);
|
||||||
|
message += '\n';
|
||||||
|
}
|
||||||
|
message += "path=";
|
||||||
|
message += HTTP.arg("path");
|
||||||
|
message += '\n';
|
||||||
|
// DBG_OUTPUT_PORT.print(message);
|
||||||
|
|
||||||
|
return replyNotFound(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void printDirectory(File dir, String& out) {
|
/*
|
||||||
while (true) {
|
This specific handler returns the index.htm (or a gzipped version) from the /edit folder.
|
||||||
File entry = dir.openNextFile();
|
If the file is not present but the flag INCLUDE_FALLBACK_INDEX_HTM has been set, falls back to the version
|
||||||
if (!entry) {
|
embedded in the program code.
|
||||||
break;
|
Otherwise, fails with a 404 page with debug information
|
||||||
}
|
*/
|
||||||
if (entry.isDirectory()) {
|
void handleGetEdit()
|
||||||
out += entry.name();
|
{
|
||||||
out += "/";
|
if (handleFileRead(F("/edit.htm")))
|
||||||
printDirectory(entry, out);
|
{
|
||||||
} else {
|
return;
|
||||||
out += entry.name();
|
|
||||||
out += "\r\n";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef INCLUDE_FALLBACK_INDEX_HTM
|
||||||
|
server.sendHeader(F("Content-Encoding"), "gzip");
|
||||||
|
server.send(200, "text/html", index_htm_gz, index_htm_gz_len);
|
||||||
|
#else
|
||||||
|
replyNotFound(FPSTR(FILE_NOT_FOUND));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ void* getAPI_Bme280(String subtype, String params);
|
|||||||
void* getAPI_Bmp280(String subtype, String params);
|
void* getAPI_Bmp280(String subtype, String params);
|
||||||
void* getAPI_Dht1122(String subtype, String params);
|
void* getAPI_Dht1122(String subtype, String params);
|
||||||
void* getAPI_Ds18b20(String subtype, String params);
|
void* getAPI_Ds18b20(String subtype, String params);
|
||||||
|
void* getAPI_Impulse(String subtype, String params);
|
||||||
void* getAPI_Pzem004(String subtype, String params);
|
void* getAPI_Pzem004(String subtype, String params);
|
||||||
void* getAPI_RTC(String subtype, String params);
|
void* getAPI_RTC(String subtype, String params);
|
||||||
void* getAPI_Sht20(String subtype, String params);
|
void* getAPI_Sht20(String subtype, String params);
|
||||||
@@ -47,6 +48,7 @@ if ((tmpAPI = getAPI_Bme280(subtype, params)) != nullptr) return tmpAPI;
|
|||||||
if ((tmpAPI = getAPI_Bmp280(subtype, params)) != nullptr) return tmpAPI;
|
if ((tmpAPI = getAPI_Bmp280(subtype, params)) != nullptr) return tmpAPI;
|
||||||
if ((tmpAPI = getAPI_Dht1122(subtype, params)) != nullptr) return tmpAPI;
|
if ((tmpAPI = getAPI_Dht1122(subtype, params)) != nullptr) return tmpAPI;
|
||||||
if ((tmpAPI = getAPI_Ds18b20(subtype, params)) != nullptr) return tmpAPI;
|
if ((tmpAPI = getAPI_Ds18b20(subtype, params)) != nullptr) return tmpAPI;
|
||||||
|
if ((tmpAPI = getAPI_Impulse(subtype, params)) != nullptr) return tmpAPI;
|
||||||
if ((tmpAPI = getAPI_Pzem004(subtype, params)) != nullptr) return tmpAPI;
|
if ((tmpAPI = getAPI_Pzem004(subtype, params)) != nullptr) return tmpAPI;
|
||||||
if ((tmpAPI = getAPI_RTC(subtype, params)) != nullptr) return tmpAPI;
|
if ((tmpAPI = getAPI_RTC(subtype, params)) != nullptr) return tmpAPI;
|
||||||
if ((tmpAPI = getAPI_Sht20(subtype, params)) != nullptr) return tmpAPI;
|
if ((tmpAPI = getAPI_Sht20(subtype, params)) != nullptr) return tmpAPI;
|
||||||
|
|||||||
@@ -6,23 +6,22 @@ extern IoTGpio IoTgpio;
|
|||||||
class Multitouch : public IoTItem
|
class Multitouch : public IoTItem
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
int _pin;
|
|
||||||
int _int;
|
int _int;
|
||||||
int _inv;
|
|
||||||
String _pinMode;
|
|
||||||
int _lastButtonState = LOW;
|
|
||||||
unsigned long _lastDebounceTime = 0;
|
|
||||||
unsigned long timing;
|
unsigned long timing;
|
||||||
long _debounceDelay = 50;
|
|
||||||
long _PWMDelay = 500;
|
long _PWMDelay = 500;
|
||||||
int _buttonState;
|
|
||||||
int _reading;
|
|
||||||
int _count = 0;
|
int _count = 0;
|
||||||
int duration = 0;
|
int duration = 0;
|
||||||
|
|
||||||
|
int _pin;
|
||||||
|
bool _execLevel, _fixState, _inv, _buttonState, _reading;
|
||||||
|
bool _lastButtonState = LOW;
|
||||||
|
unsigned long _lastDebounceTime = 0;
|
||||||
|
int _debounceDelay = 50;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Multitouch(String parameters) : IoTItem(parameters)
|
Multitouch(String parameters) : IoTItem(parameters)
|
||||||
{
|
{
|
||||||
|
String _pinMode;
|
||||||
jsonRead(parameters, "pin", _pin);
|
jsonRead(parameters, "pin", _pin);
|
||||||
jsonRead(parameters, "pinMode", _pinMode);
|
jsonRead(parameters, "pinMode", _pinMode);
|
||||||
jsonRead(parameters, "debounceDelay", _debounceDelay);
|
jsonRead(parameters, "debounceDelay", _debounceDelay);
|
||||||
@@ -31,15 +30,20 @@ public:
|
|||||||
jsonRead(parameters, "inv", _inv);
|
jsonRead(parameters, "inv", _inv);
|
||||||
_round = 0;
|
_round = 0;
|
||||||
|
|
||||||
IoTgpio.pinMode(_pin, INPUT);
|
if (_pinMode == F("INPUT"))
|
||||||
if (_pinMode == "INPUT_PULLUP")
|
IoTgpio.pinMode(_pin, INPUT);
|
||||||
IoTgpio.digitalWrite(_pin, HIGH);
|
else if (_pinMode == F("INPUT_PULLUP"))
|
||||||
else if (_pinMode == "INPUT_PULLDOWN")
|
IoTgpio.pinMode(_pin, INPUT_PULLUP);
|
||||||
|
else if (_pinMode == F("INPUT_PULLDOWN"))
|
||||||
|
{
|
||||||
|
IoTgpio.pinMode(_pin, INPUT);
|
||||||
IoTgpio.digitalWrite(_pin, LOW);
|
IoTgpio.digitalWrite(_pin, LOW);
|
||||||
|
}
|
||||||
|
|
||||||
value.valD = _buttonState = IoTgpio.digitalRead(_pin);
|
value.valD = _buttonState = IoTgpio.digitalRead(_pin);
|
||||||
// сообщаем всем о стартовом статусе без генерации события
|
// сообщаем всем о стартовом статусе без генерации события
|
||||||
regEvent(_buttonState, "", false, false);
|
regEvent(_buttonState, "", false, false);
|
||||||
|
SerialPrint("I", F("Multitouch"), "_buttonState " + String(_buttonState));
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
@@ -49,35 +53,34 @@ public:
|
|||||||
{
|
{
|
||||||
_lastDebounceTime = millis();
|
_lastDebounceTime = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((millis() - _lastDebounceTime) > _debounceDelay)
|
if ((millis() - _lastDebounceTime) > _debounceDelay)
|
||||||
{
|
{
|
||||||
if (millis() - timing > _int && _reading == _inv && millis() - _lastDebounceTime > _PWMDelay)
|
|
||||||
{
|
|
||||||
timing = millis();
|
|
||||||
duration = millis() - _lastDebounceTime - _PWMDelay;
|
|
||||||
value.valD = duration / 50;
|
|
||||||
regEvent(value.valD, "Multitouch");
|
|
||||||
_count = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_reading != _buttonState)
|
if (_reading != _buttonState)
|
||||||
{
|
{
|
||||||
_buttonState = _reading;
|
|
||||||
_count++;
|
_count++;
|
||||||
duration = 0;
|
duration = 0;
|
||||||
|
_buttonState = _reading;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (1 < _count && millis() > _lastDebounceTime + _PWMDelay)
|
if (1 < _count && millis() > _lastDebounceTime + _PWMDelay)
|
||||||
{
|
{
|
||||||
value.valD = _count / 2;
|
value.valD = _count / 2;
|
||||||
regEvent(value.valD, "Multitouch");
|
regEvent(value.valD, F("Multitouch"));
|
||||||
_count = 0;
|
_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (millis() - timing > _int && _reading == _inv && millis() - _lastDebounceTime > _PWMDelay)
|
||||||
|
{
|
||||||
|
SerialPrint("I", F("Multitouch"), "Считаем задержку");
|
||||||
|
timing = millis();
|
||||||
|
duration = millis() - _lastDebounceTime - _PWMDelay;
|
||||||
|
value.valD = duration / _int + 1;
|
||||||
|
regEvent(value.valD, F("Multitouch"));
|
||||||
|
_count = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_lastButtonState = _reading;
|
_lastButtonState = _reading;
|
||||||
}
|
}
|
||||||
|
|
||||||
~Multitouch(){};
|
~Multitouch(){};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
"authorGit": "https://github.com/avaksru",
|
"authorGit": "https://github.com/avaksru",
|
||||||
"specialThanks": "",
|
"specialThanks": "",
|
||||||
"moduleName": "Multitouch",
|
"moduleName": "Multitouch",
|
||||||
"moduleVersion": "1.0",
|
"moduleVersion": "2.0",
|
||||||
"usedRam": {
|
"usedRam": {
|
||||||
"esp32_4mb": 15,
|
"esp32_4mb": 15,
|
||||||
"esp8266_4mb": 15
|
"esp8266_4mb": 15
|
||||||
@@ -48,8 +48,6 @@
|
|||||||
"esp8266_1mb": [],
|
"esp8266_1mb": [],
|
||||||
"esp8266_1mb_ota": [],
|
"esp8266_1mb_ota": [],
|
||||||
"esp8285_1mb": [],
|
"esp8285_1mb": [],
|
||||||
"esp8285_1mb_ota": [],
|
"esp8285_1mb_ota": []
|
||||||
"esp8266_2mb": [],
|
|
||||||
"esp8266_2mb_ota": []
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
99
src/modules/sensors/A02Distance/A02Distance.cpp
Normal file
99
src/modules/sensors/A02Distance/A02Distance.cpp
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
|
||||||
|
#include "Global.h"
|
||||||
|
#include "classes/IoTItem.h"
|
||||||
|
|
||||||
|
#include "modules/sensors/UART/Uart.h"
|
||||||
|
|
||||||
|
#define READ_TIMEOUT 100
|
||||||
|
|
||||||
|
class A02Distance : public IoTItem
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
public:
|
||||||
|
A02Distance(String parameters) : IoTItem(parameters)
|
||||||
|
{
|
||||||
|
if (myUART)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Периодическое выполнение программы, в int секунд, которые зададим в конфигурации
|
||||||
|
void doByInterval()
|
||||||
|
{
|
||||||
|
if (myUART)
|
||||||
|
{
|
||||||
|
static uint8_t data[4];
|
||||||
|
|
||||||
|
if (recieve(data, 4) == 4)
|
||||||
|
{
|
||||||
|
if (data[0] == 0xff)
|
||||||
|
{
|
||||||
|
int sum;
|
||||||
|
sum = (data[0] + data[1] + data[2]) & 0x00FF;
|
||||||
|
if (sum == data[3])
|
||||||
|
{
|
||||||
|
float distance = (data[1] << 8) + data[2];
|
||||||
|
if (distance > 30)
|
||||||
|
{
|
||||||
|
value.valD = distance / 10;
|
||||||
|
//SerialPrint("i", F("A02Distance"), "distance = " + String(value.valD) + "cm");
|
||||||
|
regEvent(value.valD, "A02Distance");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SerialPrint("E", "A02Distance", "Below the lower limit");
|
||||||
|
regEvent(NAN, "A02Distance");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
regEvent(NAN, "A02Distance");
|
||||||
|
SerialPrint("E", "A02Distance", "Distance data error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
regEvent(NAN, "A02Distance");
|
||||||
|
SerialPrint("E", "A02Distance", "Recieve data error");
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
regEvent(NAN, "A02Distance");
|
||||||
|
SerialPrint("E", "A02Distance", "Not find UART");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Приём данных из COM порта
|
||||||
|
uint16_t recieve(uint8_t *resp, uint16_t len)
|
||||||
|
{
|
||||||
|
((SoftwareSerial *)myUART)->listen(); // Start software serial listen
|
||||||
|
unsigned long startTime = millis(); // Start time for Timeout
|
||||||
|
uint8_t index = 0; // Bytes we have read
|
||||||
|
while ((index < len) && (millis() - startTime < READ_TIMEOUT))
|
||||||
|
{
|
||||||
|
if (myUART->available() > 0)
|
||||||
|
{
|
||||||
|
uint8_t c = (uint8_t)myUART->read();
|
||||||
|
resp[index++] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
~A02Distance(){};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//Функиця ядра, чтобы нашел наш модуль
|
||||||
|
void *getAPI_A02Distance(String subtype, String param)
|
||||||
|
{
|
||||||
|
if (subtype == F("A02Distance"))
|
||||||
|
{
|
||||||
|
return new A02Distance(param);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
40
src/modules/sensors/A02Distance/modinfo.json
Normal file
40
src/modules/sensors/A02Distance/modinfo.json
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"menuSection": "Сенсоры",
|
||||||
|
"configItem": [
|
||||||
|
{
|
||||||
|
"name": "A02 Дальность",
|
||||||
|
"type": "Reading",
|
||||||
|
"subtype": "A02Distance",
|
||||||
|
"id": "dist",
|
||||||
|
"widget": "anydataCm",
|
||||||
|
"page": "Сенсоры",
|
||||||
|
"descr": "Дальность",
|
||||||
|
"int": 5,
|
||||||
|
"round": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"about": {
|
||||||
|
"authorName": "Bubnov Mikhail",
|
||||||
|
"authorContact": "https://t.me/Mitchel",
|
||||||
|
"authorGit": "https://github.com/Mit4el",
|
||||||
|
"exampleURL": "https://iotmanager.org/wiki",
|
||||||
|
"specialThanks": "",
|
||||||
|
"moduleName": "A02Distance",
|
||||||
|
"moduleVersion": "0.1",
|
||||||
|
"moduleDesc": "A0221AU, A02YYUW Ультразвуковой датчик. Позволяет получить дальность с ультрозвуковых датчиков A0221AU, A02YYUW",
|
||||||
|
"propInfo": {
|
||||||
|
"int": "Количество секунд между опросами датчика."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defActive": true,
|
||||||
|
"usedLibs": {
|
||||||
|
"esp32_4mb": [],
|
||||||
|
"esp8266_4mb": [],
|
||||||
|
"esp8266_1mb": [],
|
||||||
|
"esp8266_1mb_ota": [],
|
||||||
|
"esp8285_1mb": [],
|
||||||
|
"esp8285_1mb_ota": [],
|
||||||
|
"esp8266_2mb": [],
|
||||||
|
"esp8266_2mb_ota": []
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,14 @@
|
|||||||
|
|
||||||
extern IoTGpio IoTgpio;
|
extern IoTGpio IoTgpio;
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
#define SC_ADC 4095. //Scale ADC
|
||||||
|
#else
|
||||||
|
#define SC_ADC 1023. //Scale ADC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DEF_NAN 50 //количество отсчетов АПЦ которые мы принимаем за отсутствие датчика (в идеале 0, но все равно Acs712 выдает минимум 0,5В)
|
||||||
|
|
||||||
class Acs712 : public IoTItem
|
class Acs712 : public IoTItem
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@@ -10,56 +18,97 @@ private:
|
|||||||
const unsigned long _sampleTime = 100000UL; // sample over 100ms, it is an exact number of cycles for both 50Hz and 60Hz mains
|
const unsigned long _sampleTime = 100000UL; // sample over 100ms, it is an exact number of cycles for both 50Hz and 60Hz mains
|
||||||
const unsigned long _numSamples = 250UL; // choose the number of samples to divide sampleTime exactly, but low enough for the ADC to keep up
|
const unsigned long _numSamples = 250UL; // choose the number of samples to divide sampleTime exactly, but low enough for the ADC to keep up
|
||||||
const unsigned long _sampleInterval = _sampleTime / _numSamples; // the sampling interval, must be longer than then ADC conversion time
|
const unsigned long _sampleInterval = _sampleTime / _numSamples; // the sampling interval, must be longer than then ADC conversion time
|
||||||
int _adc_zero1; //Переменная автоматической калибровки
|
int _adc_zero1; // Переменная автоматической калибровки
|
||||||
|
int _fl_rms; // 1 - подсчет средне-квадратического тока (переменный), 0 - подсчет средне-арифмитического тока (постоянный)
|
||||||
|
int _sens = 100; //Чувствительность датчика тока: 5A = 185mВ/A, 20A = 100mВ/A, 30A = 66mВ/A
|
||||||
|
int _vref; //"Vref (мВ) - Опороное наряжение питания Acs712, по умолчанию = 5000мВ",
|
||||||
|
float k ; //Чувствительность(разрешение) Acs712 по току, сколько тока в одном отсчете АЦП, k=VACP/sens (30А->74mА, 20A->49mA, 5A->26mA для esp8266)
|
||||||
|
bool f_nan = false; //Флаг отсутствия входа на АЦП
|
||||||
|
float vacp; //Напряжение в мВ для смещения одного разряда АЦП esp8266 = 4.887, esp32 = 1.221; vacp = vcc*1000/1023
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Acs712(String parameters) : IoTItem(parameters)
|
Acs712(String parameters) : IoTItem(parameters)
|
||||||
{
|
{
|
||||||
String tmp;
|
String tmp;
|
||||||
jsonRead(parameters, "pin", tmp);
|
jsonRead(parameters, "pin", tmp);
|
||||||
_pin = tmp.toInt();
|
_pin = tmp.toInt();
|
||||||
_adc_zero1 = determineVQ(_pin);
|
jsonRead(parameters, "adczero", tmp);
|
||||||
|
_adc_zero1 = tmp.toInt(); // determineVQ(_pin);
|
||||||
|
jsonRead(parameters, "rms", tmp);
|
||||||
|
_fl_rms = tmp.toInt();
|
||||||
|
jsonRead(parameters, "sens", tmp);
|
||||||
|
_sens = tmp.toInt();
|
||||||
|
jsonRead(parameters, "vref", tmp);
|
||||||
|
_vref = tmp.toInt();
|
||||||
|
vacp = _vref/SC_ADC;
|
||||||
|
k = vacp / (float)_sens; //коэффециент для домножения измерений АЦП
|
||||||
}
|
}
|
||||||
|
|
||||||
void doByInterval()
|
void doByInterval()
|
||||||
{
|
{
|
||||||
|
f_nan = false;
|
||||||
unsigned long currentAcc = 0;
|
unsigned long currentAcc = 0;
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
unsigned long prevMicros = micros() - _sampleInterval;
|
unsigned long prevMicros = micros() - _sampleInterval;
|
||||||
while (count < _numSamples)
|
while (count < _numSamples)
|
||||||
|
{
|
||||||
|
if (micros() - prevMicros >= _sampleInterval)
|
||||||
{
|
{
|
||||||
if (micros() - prevMicros >= _sampleInterval)
|
int adc_raw = IoTgpio.analogRead(_pin);
|
||||||
{
|
if (adc_raw > DEF_NAN) f_nan = true; //Если за цикл измерений не было АЦП больше 50, то считаем что нет датчика
|
||||||
int adc_raw = IoTgpio.analogRead(_pin) - _adc_zero1;
|
adc_raw -= _adc_zero1;
|
||||||
|
if (_fl_rms == 0)
|
||||||
|
currentAcc += (unsigned long)abs(adc_raw);
|
||||||
|
else
|
||||||
currentAcc += (unsigned long)(adc_raw * adc_raw);
|
currentAcc += (unsigned long)(adc_raw * adc_raw);
|
||||||
++count;
|
++count;
|
||||||
prevMicros += _sampleInterval;
|
prevMicros += _sampleInterval;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#ifdef ESP32
|
}
|
||||||
value.valD = int(sqrt((float)currentAcc / (float)_numSamples) * (75.7576 / 4095.0));
|
|
||||||
#else
|
if (_fl_rms == 0)
|
||||||
value.valD = int(sqrt((float)currentAcc / (float)_numSamples) * (75.7576 / 1023.0));
|
{
|
||||||
#endif
|
#ifdef ESP32
|
||||||
|
value.valD = ((float)currentAcc / (float)_numSamples) * k;
|
||||||
|
#else
|
||||||
|
value.valD = ((float)currentAcc / (float)_numSamples) * k;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef ESP32
|
||||||
|
value.valD = (sqrt((float)currentAcc / (float)_numSamples) * k);
|
||||||
|
#else
|
||||||
|
value.valD = (sqrt((float)currentAcc / (float)_numSamples) * k);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (f_nan)
|
||||||
regEvent(value.valD, "Acs712");
|
regEvent(value.valD, "Acs712");
|
||||||
|
else
|
||||||
|
regEvent(NAN, "Acs712");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onModuleOrder(String &key, String &value)
|
||||||
|
{
|
||||||
|
if (key == "setZero")
|
||||||
|
{
|
||||||
|
_adc_zero1 = determineVQ(_pin);
|
||||||
|
SerialPrint("i", F("Acs712"), "User run calibration ADC zero: " + String(_adc_zero1));
|
||||||
|
// TODO wtitejson to config.json?????
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int determineVQ(int PIN)
|
int determineVQ(int PIN)
|
||||||
{
|
{
|
||||||
long VQ = 0;
|
long VQ = 0;
|
||||||
// read 5000 samples to stabilise value
|
for (int i = 0; i < 100; i++)
|
||||||
for (int i = 0; i < 5000; i++)
|
|
||||||
{
|
{
|
||||||
VQ += IoTgpio.analogRead(PIN);
|
VQ += IoTgpio.analogRead(PIN);
|
||||||
//delay(1); // depends on sampling (on filter capacitor), can be 1/80000 (80kHz) max.
|
|
||||||
}
|
}
|
||||||
VQ /= 5000;
|
VQ /= 100;
|
||||||
return int(VQ);
|
return int(VQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
~Acs712(){};
|
~Acs712(){};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"configItem": [
|
"configItem": [
|
||||||
{
|
{
|
||||||
"name": "Acs712 Ток",
|
"name": "Acs712 Ток",
|
||||||
"type": "Reading",
|
"type": "Reading",
|
||||||
"subtype": "Acs712",
|
"subtype": "Acs712",
|
||||||
"id": "amp",
|
"id": "amp",
|
||||||
"widget": "anydataAmp",
|
"widget": "anydataAmp",
|
||||||
@@ -11,26 +11,42 @@
|
|||||||
"descr": "Ток",
|
"descr": "Ток",
|
||||||
"round": 3,
|
"round": 3,
|
||||||
"pin": 39,
|
"pin": 39,
|
||||||
"int": 5
|
"int": 5,
|
||||||
|
"rms": 1,
|
||||||
|
"vref": 5000,
|
||||||
|
"sens": 100,
|
||||||
|
"adczero" : 512,
|
||||||
|
"btn-setZero": "nil"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"about": {
|
"about": {
|
||||||
"authorName": "Yuriy Kuneev",
|
"authorName": "Bubnov Mikhail",
|
||||||
"authorContact": "https://t.me/Kuneev07",
|
"authorContact": "https://t.me/Mitchel",
|
||||||
"authorGit": "",
|
"authorGit": "https://github.com/Mit4el",
|
||||||
"exampleURL": "https://iotmanager.org/wiki",
|
"exampleURL": "https://iotmanager.org/wiki",
|
||||||
"specialThanks": "",
|
"specialThanks": "",
|
||||||
"moduleName": "Acs712",
|
"moduleName": "Acs712",
|
||||||
"moduleVersion": "1.0",
|
"moduleVersion": "2.0",
|
||||||
"moduleDesc": "Позволяет получить текущее значение тока на аналоговом пине с помощью модуля Acs712.",
|
"moduleDesc": "Позволяет получить текущее значение тока на аналоговом пине с помощью модуля Acs712. Не забываем про делитель для входа на АЦП/",
|
||||||
"propInfo": {
|
"propInfo": {
|
||||||
"pin": "Аналоговый GPIO номер, к которому подключен датчик.",
|
"pin": "Аналоговый GPIO номер, к которому подключен датчик. Для esp8266 0",
|
||||||
"int": "Количество секунд между опросами датчика."
|
"int": "Количество секунд между опросами датчика.",
|
||||||
|
"rms": "1 - подсчет средне-квадратического тока (переменный), 0 - подсчет средне-арифмитического тока (постоянный)",
|
||||||
|
"vref": "Vref (мВ) - Опороное наряжение питания Acs712, по умолчанию = 5000мВ",
|
||||||
|
"sens": "Чувствительность датчика тока: 5A = 185mВ/A , 20A = 100mВ/A , 30A = 66mВ/A ",
|
||||||
|
"adczero" : "Переменная калибровки нулевого значения отсчетов АЦП при нулевой нагрузке. Для ESP8266 - 512, Для ESP32 -2048, это 2.5В = 0А (1,65 с делителем) для Acs712 20A и 30A при стабильном токе 5В",
|
||||||
|
"btn-setZero": "Кнопка калибровки нулевого значения отсчетов АЦП при нулевой нагрузке. Нагрузка в момент калибровки должна быть отключена! После перезагрузки будет установлено в значение по умолчанию adczero. Для сохранение смотрим лог, и изменияем adczero"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"defActive": true,
|
"defActive": true,
|
||||||
"usedLibs": {
|
"usedLibs": {
|
||||||
"esp32_4mb": [],
|
"esp32_4mb": [],
|
||||||
"esp8266_4mb": []
|
"esp8266_4mb": [],
|
||||||
|
"esp8266_1mb": [],
|
||||||
|
"esp8266_1mb_ota": [],
|
||||||
|
"esp8285_1mb": [],
|
||||||
|
"esp8285_1mb_ota": [],
|
||||||
|
"esp8266_2mb": [],
|
||||||
|
"esp8266_2mb_ota": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
87
src/modules/sensors/Impulse/Impulse.cpp
Normal file
87
src/modules/sensors/Impulse/Impulse.cpp
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
#include "Global.h"
|
||||||
|
#include "classes/IoTItem.h"
|
||||||
|
|
||||||
|
extern IoTGpio IoTgpio;
|
||||||
|
|
||||||
|
class Impulse : public IoTItem
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int _int;
|
||||||
|
int _pin;
|
||||||
|
bool _buttonState, _reading;
|
||||||
|
bool _lastButtonState = LOW;
|
||||||
|
unsigned long _lastDebounceTime = 0;
|
||||||
|
int _debounceDelay = 50;
|
||||||
|
int _count = 0;
|
||||||
|
unsigned long timing;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Impulse(String parameters) : IoTItem(parameters)
|
||||||
|
{
|
||||||
|
String _pinMode;
|
||||||
|
jsonRead(parameters, F("pin"), _pin);
|
||||||
|
jsonRead(parameters, F("pinMode"), _pinMode);
|
||||||
|
jsonRead(parameters, F("debounceDelay"), _debounceDelay);
|
||||||
|
jsonRead(parameters, "int", _int);
|
||||||
|
_round = 0;
|
||||||
|
|
||||||
|
if (_pinMode == F("INPUT"))
|
||||||
|
IoTgpio.pinMode(_pin, INPUT);
|
||||||
|
else if (_pinMode == F("INPUT_PULLUP"))
|
||||||
|
IoTgpio.pinMode(_pin, INPUT_PULLUP);
|
||||||
|
else if (_pinMode == F("INPUT_PULLDOWN"))
|
||||||
|
{
|
||||||
|
IoTgpio.pinMode(_pin, INPUT);
|
||||||
|
IoTgpio.digitalWrite(_pin, LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
value.valD = _buttonState = IoTgpio.digitalRead(_pin);
|
||||||
|
regEvent(_buttonState, "", false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
_reading = IoTgpio.digitalRead(_pin);
|
||||||
|
if (_reading != _lastButtonState)
|
||||||
|
{
|
||||||
|
|
||||||
|
_lastDebounceTime = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((millis() - _lastDebounceTime) > _debounceDelay)
|
||||||
|
{
|
||||||
|
if (_reading != _buttonState)
|
||||||
|
{
|
||||||
|
_buttonState = _reading;
|
||||||
|
_count++;
|
||||||
|
}
|
||||||
|
if (_count == 1)
|
||||||
|
{
|
||||||
|
timing = millis();
|
||||||
|
}
|
||||||
|
if (millis() - timing > _int * 1000 && _count > 1)
|
||||||
|
{
|
||||||
|
timing = millis();
|
||||||
|
value.valD = _count;
|
||||||
|
regEvent(value.valD, F("Impulse"));
|
||||||
|
_count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_lastButtonState = _reading;
|
||||||
|
}
|
||||||
|
|
||||||
|
~Impulse(){};
|
||||||
|
};
|
||||||
|
|
||||||
|
void *getAPI_Impulse(String subtype, String param)
|
||||||
|
{
|
||||||
|
if (subtype == F("Impulse"))
|
||||||
|
{
|
||||||
|
return new Impulse(param);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
50
src/modules/sensors/Impulse/modinfo.json
Normal file
50
src/modules/sensors/Impulse/modinfo.json
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"menuSection": "Сенсоры",
|
||||||
|
"configItem": [
|
||||||
|
{
|
||||||
|
"global": 0,
|
||||||
|
"name": "Аналоговый счетчик импульсов",
|
||||||
|
"type": "Writing",
|
||||||
|
"subtype": "Impulse",
|
||||||
|
"id": "impulse",
|
||||||
|
"widget": "anydataDef",
|
||||||
|
"page": "Счетчики",
|
||||||
|
"descr": "Импульсов",
|
||||||
|
"needSave": 0,
|
||||||
|
"int": 1,
|
||||||
|
"pin": 16,
|
||||||
|
"pinMode": "INPUT",
|
||||||
|
"debounceDelay": 3,
|
||||||
|
"multiply": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"about": {
|
||||||
|
"authorName": "AVAKS",
|
||||||
|
"authorContact": "https://t.me/@avaks_dev",
|
||||||
|
"authorGit": "https://github.com/avaksru",
|
||||||
|
"specialThanks": "",
|
||||||
|
"moduleName": "Impulse",
|
||||||
|
"moduleVersion": "2.0",
|
||||||
|
"usedRam": {
|
||||||
|
"esp32_4mb": 15,
|
||||||
|
"esp8266_4mb": 15
|
||||||
|
},
|
||||||
|
"title": "Аналоговый счетчик импульсов. Датчик Холла ",
|
||||||
|
"moduleDesc": "Считает количество импульсов за период времени",
|
||||||
|
"propInfo": {
|
||||||
|
"int": "Период сбора импульсов в секундах",
|
||||||
|
"pin": "Укажите GPIO номер пина для чтения импульсов",
|
||||||
|
"pinMode": "Может быть INPUT_PULLUP INPUT_PULLDOWN INPUT",
|
||||||
|
"debounceDelay": "Время обработки дребезга (миллисекунд)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defActive": true,
|
||||||
|
"usedLibs": {
|
||||||
|
"esp32_4mb": [],
|
||||||
|
"esp8266_4mb": [],
|
||||||
|
"esp8266_1mb": [],
|
||||||
|
"esp8266_1mb_ota": [],
|
||||||
|
"esp8285_1mb": [],
|
||||||
|
"esp8285_1mb_ota": []
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -119,7 +119,7 @@
|
|||||||
"moduleDesc": "Считает потраченную электроэнергию, измеряет напряжение, частоту, силу тока и прочие параметры",
|
"moduleDesc": "Считает потраченную электроэнергию, измеряет напряжение, частоту, силу тока и прочие параметры",
|
||||||
"propInfo": {
|
"propInfo": {
|
||||||
"addr": "Адрес modbus",
|
"addr": "Адрес modbus",
|
||||||
"int": "Количество секунд между опросами датчика. Желателно устанавливать разные интервалы для параметров что бы опросы происходили в разное время.",
|
"int": "Количество секунд между опросами датчика. Желателно устанавливать одинаковые интервалы для параметров (для одного адреса Pzem) что опрос происходил один раз, остальные из 500мс буфера.",
|
||||||
"changeaddr": "Поставьте этот параметр равным 1 и перезагрузите esp - будет установлен адрес указанный в setaddr. Смотрите в логе результат: [i] Pzem address set: 0x01",
|
"changeaddr": "Поставьте этот параметр равным 1 и перезагрузите esp - будет установлен адрес указанный в setaddr. Смотрите в логе результат: [i] Pzem address set: 0x01",
|
||||||
"setaddr": "Новый адрес который нужно назначить",
|
"setaddr": "Новый адрес который нужно назначить",
|
||||||
"reset": "Поставьте этот параметр равным 1 и pzem будет сброшен к нулю. Смотрите в логе результат: [i] Pzem reset done"
|
"reset": "Поставьте этот параметр равным 1 и pzem будет сброшен к нулю. Смотрите в логе результат: [i] Pzem reset done"
|
||||||
|
|||||||
@@ -124,6 +124,8 @@ const String readFile(const String& filename, size_t max_size) {
|
|||||||
size_t size = file.size();
|
size_t size = file.size();
|
||||||
if (size > max_size) {
|
if (size > max_size) {
|
||||||
file.close();
|
file.close();
|
||||||
|
if (path == "/config.json")
|
||||||
|
return "[]";
|
||||||
return "large";
|
return "large";
|
||||||
}
|
}
|
||||||
String temp = file.readString();
|
String temp = file.readString();
|
||||||
|
|||||||
Reference in New Issue
Block a user