Merge branch 'IoTManagerProject:ver4dev' into ver4dev

This commit is contained in:
2023-10-03 21:31:03 +03:00
committed by GitHub
113 changed files with 5792 additions and 2293 deletions

View File

@@ -207,7 +207,7 @@ with open("platformio.ini", 'w') as configFile:
config.write(configFile) config.write(configFile)
# сохраняем применяемый профиль в папку data_svelte для загрузки на контроллер и дальнейшего переиспользования # сохраняем применяемый профиль в папку data_svelte для загрузки на контроллер и дальнейшего переиспользования
print(f"Сохраняем профиль {profile} в {dataDir}") print(f"Saving profile {profile} in {dataDir}")
shutil.copy(profile, dataDir + "/" + profile) shutil.copy(profile, dataDir + "/" + profile)
@@ -218,10 +218,10 @@ shutil.copy(profile, dataDir + "/" + profile)
# ctypes.windll.user32.MessageBoxW(0, "Профиль " + profile + " применен, можно запускать компиляцию и прошивку.", "Операция завершена.", 0) # ctypes.windll.user32.MessageBoxW(0, "Профиль " + profile + " применен, можно запускать компиляцию и прошивку.", "Операция завершена.", 0)
if update: if update:
print(f"\x1b[1;31;42m Модули профиля " + profile + " обновлены, а сам профиль применен, можно запускать компиляцию и прошивку.\x1b[0m") print(f"\x1b[1;31;42m Profile modules " + profile + " updated, profile applied, you can run compilation and firmware.\x1b[0m")
else: else:
print(f"\x1b[1;31;42m Профиль ", profile, " применен, можно запускать компиляцию и прошивку.\x1b[0m") print(f"\x1b[1;31;42m Profile ", profile, " applied, you can run compilation and firmware.\x1b[0m")
# print(f"\x1b[1;32;41m Операция завершена. \x1b[0m") # print(f"\x1b[1;32;41m Операция завершена. \x1b[0m")

Binary file not shown.

Binary file not shown.

View File

@@ -712,7 +712,7 @@
"type": "Writing", "type": "Writing",
"subtype": "IoTServo", "subtype": "IoTServo",
"id": "servo", "id": "servo",
"widget": "range", "widget": "rangeServo",
"page": "servo", "page": "servo",
"descr": "угол", "descr": "угол",
"int": 1, "int": 1,
@@ -757,7 +757,7 @@
"id": "impulse", "id": "impulse",
"widget": "anydataDef", "widget": "anydataDef",
"page": "Кнопки", "page": "Кнопки",
"descr": "Количество нажаний", "descr": "Количество нажатий",
"needSave": 0, "needSave": 0,
"int": 300, "int": 300,
"inv": 1, "inv": 1,
@@ -820,7 +820,7 @@
"subtype": "Lcd2004", "subtype": "Lcd2004",
"id": "Lcd", "id": "Lcd",
"widget": "inputTxt", "widget": "inputTxt",
"page": "Экраны", "page": "screens",
"descr": "LCD Экран", "descr": "LCD Экран",
"addr": "0x27", "addr": "0x27",
"size": "20,4", "size": "20,4",
@@ -836,7 +836,7 @@
"subtype": "Lcd2004", "subtype": "Lcd2004",
"id": "Lcd", "id": "Lcd",
"widget": "inputTxt", "widget": "inputTxt",
"page": "Экраны", "page": "screens",
"descr": "LCD Экран", "descr": "LCD Экран",
"addr": "0x27", "addr": "0x27",
"size": "16,2", "size": "16,2",
@@ -845,5 +845,25 @@
"prefix": "", "prefix": "",
"postfix": "", "postfix": "",
"num": 55 "num": 55
},
{
"global": 0,
"name": "56. 7 сегментный дисплей TM16XX",
"type": "Writing",
"subtype": "TM16XX",
"id": "tm",
"widget": "inputTxt",
"page": "screens",
"descr": "Экран",
"round": 0,
"chip": 1637,
"numDigits": 4,
"DIO": "13",
"CLK": "14",
"STB": "12",
"intensity": "5",
"on": "1",
"id2show": "",
"num": 56
} }
] ]

View File

@@ -3,8 +3,14 @@
"name": "IoTmanagerVer4", "name": "IoTmanagerVer4",
"apssid": "IoTmanager", "apssid": "IoTmanager",
"appass": "", "appass": "",
"routerssid": "iot", "routerssid": [
"routerpass": "hostel3333", "iot",
"wifi"
],
"routerpass": [
"hostel3333",
"pswd"
],
"timezone": 2, "timezone": 2,
"ntp": "pool.ntp.org", "ntp": "pool.ntp.org",
"weblogin": "admin", "weblogin": "admin",
@@ -27,13 +33,70 @@
"default_envs": "esp8266_4mb", "default_envs": "esp8266_4mb",
"comments_default_envs": "choose from: esp8266_4mb or esp32_4mb or esp32s2_4mb or esp8266_1mb or esp8266_1mb_ota or esp8285_1mb or esp8285_1mb_ota", "comments_default_envs": "choose from: esp8266_4mb or esp32_4mb or esp32s2_4mb or esp8266_1mb or esp8266_1mb_ota or esp8285_1mb or esp8285_1mb_ota",
"envs": [ "envs": [
"esp8266_4mb", {
"esp32_4mb", "name": "esp8266_4mb",
"esp8266_1mb", "firmware": "0x00000",
"esp8266_1mb_ota", "littlefs": "0x300000"
"esp8285_1mb", },
"esp8285_1mb_ota", {
"esp32s2_4mb" "name": "esp8266_16mb",
"firmware": "0x00000",
"littlefs": "0x200000"
},
{
"name": "esp32_4mb",
"boot_app0": "0xe000",
"bootloader_qio_80m": "0x1000",
"firmware": "0x10000",
"partitions": "0x8000",
"littlefs": "0x290000"
},
{
"name": "esp32_16mb",
"boot_app0": "0xe000",
"bootloader_qio_80m": "0x1000",
"firmware": "0x10000",
"partitions": "0x8000",
"littlefs": "0x910000"
},
{
"name": "esp8266_1mb",
"firmware": "0x00000000",
"littlefs": "0x000bb000"
},
{
"name": "esp8266_1mb_ota",
"firmware": "0x00000000",
"littlefs": "0x000eb000"
},
{
"name": "esp8266_2mb",
"firmware": "0x00000000",
"littlefs": "0x00100000"
},
{
"name": "esp8266_2mb_ota",
"firmware": "0x00000000",
"littlefs": "0x001c0000"
},
{
"name": "esp8285_1mb",
"firmware": "0x00000000",
"littlefs": "0x000bb000"
},
{
"name": "esp8285_1mb_ota",
"firmware": "0x00000000",
"littlefs": "0x000eb000"
},
{
"name": "esp32s2_4mb",
"boot_app0": "0xe000",
"bootloader_qio_80m": "0x1000",
"firmware": "0x10000",
"partitions": "0x8000",
"littlefs": "0x290000"
}
] ]
} }
}, },
@@ -126,11 +189,11 @@
"active": false "active": false
}, },
{ {
"path": "src/modules/sensors/Ds2423", "path": "src/modules/sensors/Emon",
"active": false "active": false
}, },
{ {
"path": "src/modules/sensors/Emon", "path": "src/modules/sensors/ExampleModule",
"active": false "active": false
}, },
{ {
@@ -165,6 +228,10 @@
"path": "src/modules/sensors/Ina219", "path": "src/modules/sensors/Ina219",
"active": false "active": false
}, },
{
"path": "src/modules/sensors/Ina226",
"active": false
},
{ {
"path": "src/modules/sensors/IoTWiegand", "path": "src/modules/sensors/IoTWiegand",
"active": false "active": false
@@ -314,6 +381,10 @@
{ {
"path": "src/modules/exec/Thermostat", "path": "src/modules/exec/Thermostat",
"active": false "active": false
},
{
"path": "src/modules/sensors/Ds2423",
"active": false
} }
], ],
"screens": [ "screens": [
@@ -329,10 +400,18 @@
"path": "src/modules/display/NextionUpload", "path": "src/modules/display/NextionUpload",
"active": false "active": false
}, },
{
"path": "src/modules/display/Oled128",
"active": false
},
{ {
"path": "src/modules/display/Smi2_m", "path": "src/modules/display/Smi2_m",
"active": true "active": true
}, },
{
"path": "src/modules/display/TM16XX",
"active": true
},
{ {
"path": "src/modules/display/Ws2812b", "path": "src/modules/display/Ws2812b",
"active": false "active": false

View File

@@ -2,8 +2,14 @@
"name": "IoTmanagerVer4", "name": "IoTmanagerVer4",
"apssid": "IoTmanager", "apssid": "IoTmanager",
"appass": "", "appass": "",
"routerssid": "iot", "routerssid": [
"routerpass": "hostel3333", "iot",
"wifi"
],
"routerpass": [
"hostel3333",
"pswd"
],
"timezone": 2, "timezone": 2,
"ntp": "pool.ntp.org", "ntp": "pool.ntp.org",
"weblogin": "admin", "weblogin": "admin",

View File

@@ -246,11 +246,11 @@
"debounce": 500 "debounce": 500
}, },
{ {
"name": "range", "name": "rangeServo",
"label": "Ползунок (Servo)", "label": "Ползунок (Servo)",
"widget": "range", "widget": "range",
"descrColor": "red", "descrColor": "red",
"after": "%", "after": "°",
"k": 1, "k": 1,
"min": 0, "min": 0,
"max": 180, "max": 180,

View File

@@ -4,7 +4,7 @@
"num": 0 "num": 0
}, },
{ {
"header": "Виртуальные элементы" "header": "virtual_elments"
}, },
{ {
"global": 0, "global": 0,
@@ -189,7 +189,7 @@
"num": 12 "num": 12
}, },
{ {
"header": "Сенсоры" "header": "sensors"
}, },
{ {
"name": "13. Acs712 Ток", "name": "13. Acs712 Ток",
@@ -197,7 +197,7 @@
"subtype": "Acs712", "subtype": "Acs712",
"id": "amp", "id": "amp",
"widget": "anydataAmp", "widget": "anydataAmp",
"page": "Сенсоры", "page": "sensors",
"descr": "Ток", "descr": "Ток",
"round": 3, "round": 3,
"pin": 39, "pin": 39,
@@ -216,7 +216,7 @@
"subtype": "AnalogAdc", "subtype": "AnalogAdc",
"id": "t", "id": "t",
"widget": "anydataTmp", "widget": "anydataTmp",
"page": "Сенсоры", "page": "sensors",
"descr": "Температура", "descr": "Температура",
"map": "1,1024,1,100", "map": "1,1024,1,100",
"plus": 0, "plus": 0,
@@ -234,7 +234,7 @@
"subtype": "Bme280t", "subtype": "Bme280t",
"id": "Tmp3", "id": "Tmp3",
"widget": "anydataTmp", "widget": "anydataTmp",
"page": "Сенсоры", "page": "sensors",
"descr": "Температура", "descr": "Температура",
"int": 15, "int": 15,
"addr": "0x77", "addr": "0x77",
@@ -248,7 +248,7 @@
"subtype": "Bme280p", "subtype": "Bme280p",
"id": "Press3", "id": "Press3",
"widget": "anydataMm", "widget": "anydataMm",
"page": "Сенсоры", "page": "sensors",
"descr": "Давление", "descr": "Давление",
"int": 15, "int": 15,
"addr": "0x77", "addr": "0x77",
@@ -262,7 +262,7 @@
"subtype": "Bme280h", "subtype": "Bme280h",
"id": "Hum3", "id": "Hum3",
"widget": "anydataHum", "widget": "anydataHum",
"page": "Сенсоры", "page": "sensors",
"descr": "Влажность", "descr": "Влажность",
"int": 15, "int": 15,
"addr": "0x77", "addr": "0x77",
@@ -276,7 +276,7 @@
"subtype": "Bme280dp", "subtype": "Bme280dp",
"id": "Dew3", "id": "Dew3",
"widget": "anydataTmp", "widget": "anydataTmp",
"page": "Сенсоры", "page": "sensors",
"descr": "Точка росы", "descr": "Точка росы",
"int": 15, "int": 15,
"addr": "0x77", "addr": "0x77",
@@ -290,7 +290,7 @@
"subtype": "Bmp280t", "subtype": "Bmp280t",
"id": "tmp3", "id": "tmp3",
"widget": "anydataTmp", "widget": "anydataTmp",
"page": "Сенсоры", "page": "sensors",
"descr": "280 Температура", "descr": "280 Температура",
"int": 15, "int": 15,
"addr": "0x77", "addr": "0x77",
@@ -304,7 +304,7 @@
"subtype": "Bmp280p", "subtype": "Bmp280p",
"id": "Press3", "id": "Press3",
"widget": "anydataMm", "widget": "anydataMm",
"page": "Сенсоры", "page": "sensors",
"descr": "280 Давление", "descr": "280 Давление",
"int": 15, "int": 15,
"addr": "0x77", "addr": "0x77",
@@ -318,7 +318,7 @@
"subtype": "Ds18b20", "subtype": "Ds18b20",
"id": "dstmp", "id": "dstmp",
"widget": "anydataTmp", "widget": "anydataTmp",
"page": "Сенсоры", "page": "sensors",
"descr": "DS Температура", "descr": "DS Температура",
"int": 15, "int": 15,
"pin": 2, "pin": 2,
@@ -471,7 +471,7 @@
"subtype": "Sht20t", "subtype": "Sht20t",
"id": "tmp2", "id": "tmp2",
"widget": "anydataTmp", "widget": "anydataTmp",
"page": "Сенсоры", "page": "sensors",
"descr": "Температура", "descr": "Температура",
"int": 15, "int": 15,
"round": 1, "round": 1,
@@ -484,7 +484,7 @@
"subtype": "Sht20h", "subtype": "Sht20h",
"id": "Hum2", "id": "Hum2",
"widget": "anydataHum", "widget": "anydataHum",
"page": "Сенсоры", "page": "sensors",
"descr": "Влажность", "descr": "Влажность",
"int": 15, "int": 15,
"round": 1, "round": 1,
@@ -497,7 +497,7 @@
"subtype": "Sht30t", "subtype": "Sht30t",
"id": "tmp30", "id": "tmp30",
"widget": "anydataTmp", "widget": "anydataTmp",
"page": "Сенсоры", "page": "sensors",
"descr": "SHT30 Температура", "descr": "SHT30 Температура",
"int": 15, "int": 15,
"round": 1, "round": 1,
@@ -510,7 +510,7 @@
"subtype": "Sht30h", "subtype": "Sht30h",
"id": "Hum30", "id": "Hum30",
"widget": "anydataHum", "widget": "anydataHum",
"page": "Сенсоры", "page": "sensors",
"descr": "SHT30 Влажность", "descr": "SHT30 Влажность",
"int": 15, "int": 15,
"round": 1, "round": 1,
@@ -524,7 +524,7 @@
"subtype": "Sonar", "subtype": "Sonar",
"id": "sonar", "id": "sonar",
"widget": "anydataTmp", "widget": "anydataTmp",
"page": "Сенсоры", "page": "sensors",
"descr": "Расстояние (см)", "descr": "Расстояние (см)",
"pinTrig": 5, "pinTrig": 5,
"pinEcho": 4, "pinEcho": 4,
@@ -546,7 +546,7 @@
"num": 36 "num": 36
}, },
{ {
"header": "Исполнительные устройства" "header": "executive_devices"
}, },
{ {
"global": 0, "global": 0,
@@ -658,7 +658,7 @@
"num": 43 "num": 43
}, },
{ {
"header": "Экраны" "header": "screens"
}, },
{ {
"global": 0, "global": 0,

View File

@@ -29,7 +29,7 @@
} }
}, },
"modules": { "modules": {
"Виртуальные элементы": [ "virtual_elments": [
{ {
"path": "src/modules/virtual/Cron", "path": "src/modules/virtual/Cron",
"active": true "active": true
@@ -63,7 +63,7 @@
"active": false "active": false
} }
], ],
"Сенсоры": [ "sensors": [
{ {
"path": "src/modules/sensors/Acs712", "path": "src/modules/sensors/Acs712",
"active": true "active": true
@@ -193,7 +193,7 @@
"active": true "active": true
} }
], ],
"Исполнительные устройства": [ "executive_devices": [
{ {
"path": "src/modules/exec/ButtonIn", "path": "src/modules/exec/ButtonIn",
"active": true "active": true
@@ -267,7 +267,7 @@
"active": false "active": false
} }
], ],
"Экраны": [ "screens": [
{ {
"path": "src/modules/display/DwinI", "path": "src/modules/display/DwinI",
"active": false "active": false

View File

@@ -1,308 +0,0 @@
[
{
"name": "anydataRed",
"label": "Сообщение1",
"widget": "anydata",
"icon": "body",
"color": "red",
"descrColor": "red"
},
{
"name": "anydataDgr",
"label": "Сообщение2",
"widget": "anydata",
"after": "",
"color": "red",
"icon": "walk"
},
{
"name": "anydataDef",
"label": "Текст",
"widget": "anydata",
"after": "",
"icon": ""
},
{
"name": "anydataVlt",
"label": "Вольты",
"widget": "anydata",
"after": "V",
"icon": "speedometer"
},
{
"name": "anydataAmp",
"label": "Амперы",
"widget": "anydata",
"after": "A",
"icon": "speedometer"
},
{
"name": "anydataWt",
"label": "Ватты",
"widget": "anydata",
"after": "Wt",
"icon": "speedometer",
"color": [
{
"level": 0,
"value": ""
},
{
"level": 200,
"value": "#009933"
},
{
"level": 2000,
"value": "#FF9900"
},
{
"level": 4000,
"value": "red"
}
]
},
{
"name": "anydataWth",
"label": "Энергия",
"widget": "anydata",
"after": "kWh",
"icon": "speedometer"
},
{
"name": "anydataHtz",
"label": "Герцы",
"widget": "anydata",
"after": "Hz",
"icon": "speedometer"
},
{
"name": "anydataTmp",
"label": "Температура",
"widget": "anydata",
"after": "°С",
"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",
"label": "Давление",
"widget": "anydata",
"after": "mm",
"icon": "speedometer"
},
{
"name": "anydataHum",
"label": "Влажность",
"widget": "anydata",
"after": "%",
"icon": "water",
"color": "#88AADF"
},
{
"name": "anydataTm",
"label": "Время",
"widget": "anydata",
"after": "",
"icon": "speedometer"
},
{
"name": "button",
"label": "Кнопка",
"widget": "btn",
"size": "large",
"color": "green",
"send": "test"
},
{
"name": "toggle",
"label": "Переключатель",
"widget": "toggle",
"icon": "",
"iconOff": ""
},
{
"name": "chart1",
"label": "График без точек",
"widget": "chart",
"dateFormat": "HH:mm",
"maxCount": 86400,
"pointRadius": 0
},
{
"name": "chart2",
"label": "График с точками",
"widget": "chart",
"maxCount": 86400,
"dateFormat": "HH:mm"
},
{
"name": "chart3",
"label": "График Дневной",
"widget": "chart",
"dateFormat": "DD.MM.YYYY",
"maxCount": 86400,
"type": "bar"
},
{
"name": "fillgauge",
"label": "Бочка",
"widget": "fillgauge",
"circleColor": "#00FFFF",
"textColor": "#FFFFFF",
"waveTextColor": "#000000",
"waveColor": "#00FFFF"
},
{
"name": "inputDate",
"label": "Ввод даты",
"widget": "input",
"size": "small",
"color": "orange",
"type": "date"
},
{
"name": "inputDgt",
"label": "Ввод числа",
"widget": "input",
"color": "blue",
"type": "number"
},
{
"name": "inputTxt",
"label": "Ввод текста",
"widget": "input",
"size": "small",
"color": "orange",
"type": "text"
},
{
"name": "inputTm",
"label": "Ввод времени",
"widget": "input",
"color": "blue",
"type": "time"
},
{
"name": "progressLine",
"label": "Статус линия",
"widget": "progress-line",
"icon": "sunny",
"max": "100",
"stroke": "10"
},
{
"name": "progressRound",
"label": "Статус круг",
"widget": "progress-round",
"max": "100",
"stroke": "20",
"color": "#45ccce",
"background": "#777",
"semicircle": "1"
},
{
"name": "range",
"label": "Ползунок",
"widget": "range",
"descrColor": "red",
"after": "%",
"k": 0.0977,
"min": 0,
"max": 100,
"debounce": 500
},
{
"name": "range",
"label": "Ползунок (Servo)",
"widget": "range",
"descrColor": "red",
"after": "%",
"k": 1,
"min": 0,
"max": 180,
"debounce": 500
},
{
"name": "select",
"label": "Выпадающий",
"widget": "select",
"options": [
"Выключен",
"Включен"
],
"status": 0
},
{
"name": "anydataPpm",
"label": "PPM",
"widget": "anydata",
"after": "ppm",
"icon": "speedometer"
},
{
"name": "anydatamAmp",
"label": "миллиАмперы",
"widget": "anydata",
"after": "mAmp",
"icon": "speedometer"
},
{
"name": "anydatamVlt",
"label": "миллиВольты",
"widget": "anydata",
"after": "mVlt",
"icon": "speedometer"
},
{
"name": "anydatamWt",
"label": "миллиВатты",
"widget": "anydata",
"after": "mWt",
"icon": "speedometer"
},
{
"name": "anydataCm",
"label": "Сантиметры",
"widget": "anydata",
"after": "cm",
"icon": "speedometer"
},
{
"name": "nil",
"label": "Без виджета"
}
]

View File

@@ -246,11 +246,11 @@
"debounce": 500 "debounce": 500
}, },
{ {
"name": "range", "name": "rangeServo",
"label": "Ползунок (Servo)", "label": "Ползунок (Servo)",
"widget": "range", "widget": "range",
"descrColor": "red", "descrColor": "red",
"after": "%", "after": "°",
"k": 1, "k": 1,
"min": 0, "min": 0,
"max": 180, "max": 180,

View File

@@ -24,10 +24,18 @@
#define FIRMWARE_NAME "esp8266_4mb" #define FIRMWARE_NAME "esp8266_4mb"
#endif #endif
#ifdef esp8266_16mb
#define FIRMWARE_NAME "esp8266_16mb"
#endif
#ifdef esp32_4mb #ifdef esp32_4mb
#define FIRMWARE_NAME "esp32_4mb" #define FIRMWARE_NAME "esp32_4mb"
#endif #endif
#ifdef esp32_16mb
#define FIRMWARE_NAME "esp32_16mb"
#endif
#ifdef esp32s2_4mb #ifdef esp32s2_4mb
#define FIRMWARE_NAME "esp32s2_4mb" #define FIRMWARE_NAME "esp32s2_4mb"
#endif #endif

View File

@@ -14,6 +14,7 @@ boolean mqttConnect();
void mqttReconnect(); void mqttReconnect();
void mqttLoop(); void mqttLoop();
void mqttSubscribe(); void mqttSubscribe();
bool mqttIsConnect();
boolean publish(const String& topic, const String& data); boolean publish(const String& topic, const String& data);
boolean publishData(const String& topic, const String& data); boolean publishData(const String& topic, const String& data);
@@ -21,6 +22,7 @@ boolean publishChartMqtt(const String& topic, const String& data);
boolean publishJsonMqtt(const String& topic, const String& json); boolean publishJsonMqtt(const String& topic, const String& json);
boolean publishStatusMqtt(const String& topic, const String& data); boolean publishStatusMqtt(const String& topic, const String& data);
boolean publishEvent(const String& topic, const String& data); boolean publishEvent(const String& topic, const String& data);
void mqttSubscribeExternal(String topic, bool usePrefix);
bool publishChartFileToMqtt(String path, String id, int maxCount); bool publishChartFileToMqtt(String path, String id, int maxCount);

View File

@@ -15,6 +15,7 @@ extern bool jsonRead(const String& json, String key, float& value, bool e = true
extern bool jsonRead(const String& json, String key, String& value, bool e = true); extern bool jsonRead(const String& json, String key, String& value, bool e = true);
extern bool jsonRead(const String& json, String key, bool& value, bool e = true); extern bool jsonRead(const String& json, String key, bool& value, bool e = true);
extern bool jsonRead(const String& json, String key, int& value, bool e = true); extern bool jsonRead(const String& json, String key, int& value, bool e = true);
extern bool jsonReadArray(const String& json, String key, std::vector<String>& jArray, bool e = true);
extern String jsonReadStr(const String& json, String name, bool e = true); extern String jsonReadStr(const String& json, String name, bool e = true);
extern int jsonReadInt(const String& json, String name, bool e = true); extern int jsonReadInt(const String& json, String name, bool e = true);

View File

@@ -2,11 +2,11 @@
#include "Global.h" #include "Global.h"
#include "MqttClient.h" #include "MqttClient.h"
#include <vector>
// boolean isNetworkActive(); // boolean isNetworkActive();
inline boolean isNetworkActive() {return WiFi.status() == WL_CONNECTED;}; inline boolean isNetworkActive() {return WiFi.status() == WL_CONNECTED;};
void routerConnect(); void routerConnect();
bool startAPMode(); bool startAPMode();
boolean RouterFind(String ssid); boolean RouterFind(std::vector<String> jArray);
uint8_t RSSIquality(); uint8_t RSSIquality();
extern void wifiSignalInit(); extern void wifiSignalInit();

View File

@@ -27,13 +27,70 @@
"default_envs": "esp8266_4mb", "default_envs": "esp8266_4mb",
"comments_default_envs": "choose from: esp8266_4mb or esp32_4mb or esp32s2_4mb or esp8266_1mb or esp8266_1mb_ota or esp8285_1mb or esp8285_1mb_ota", "comments_default_envs": "choose from: esp8266_4mb or esp32_4mb or esp32s2_4mb or esp8266_1mb or esp8266_1mb_ota or esp8285_1mb or esp8285_1mb_ota",
"envs": [ "envs": [
"esp8266_4mb", {
"esp32_4mb", "name": "esp8266_4mb",
"esp8266_1mb", "firmware": "0x00000",
"esp8266_1mb_ota", "littlefs": "0x300000"
"esp8285_1mb", },
"esp8285_1mb_ota", {
"esp32s2_4mb" "name": "esp8266_16mb",
"firmware": "0x00000",
"littlefs": "0x200000"
},
{
"name": "esp32_4mb",
"boot_app0": "0xe000",
"bootloader_qio_80m": "0x1000",
"firmware": "0x10000",
"partitions": "0x8000",
"littlefs": "0x290000"
},
{
"name": "esp32_16mb",
"boot_app0": "0xe000",
"bootloader_qio_80m": "0x1000",
"firmware": "0x10000",
"partitions": "0x8000",
"littlefs": "0x910000"
},
{
"name": "esp8266_1mb",
"firmware": "0x00000000",
"littlefs": "0x000bb000"
},
{
"name": "esp8266_1mb_ota",
"firmware": "0x00000000",
"littlefs": "0x000eb000"
},
{
"name": "esp8266_2mb",
"firmware": "0x00000000",
"littlefs": "0x00100000"
},
{
"name": "esp8266_2mb_ota",
"firmware": "0x00000000",
"littlefs": "0x001c0000"
},
{
"name": "esp8285_1mb",
"firmware": "0x00000000",
"littlefs": "0x000bb000"
},
{
"name": "esp8285_1mb_ota",
"firmware": "0x00000000",
"littlefs": "0x000eb000"
},
{
"name": "esp32s2_4mb",
"boot_app0": "0xe000",
"bootloader_qio_80m": "0x1000",
"firmware": "0x10000",
"partitions": "0x8000",
"littlefs": "0x290000"
}
] ]
} }
}, },
@@ -125,10 +182,6 @@
"path": "src/modules/sensors/DS2401", "path": "src/modules/sensors/DS2401",
"active": false "active": false
}, },
{
"path": "src/modules/sensors/Ds2423",
"active": false
},
{ {
"path": "src/modules/sensors/Emon", "path": "src/modules/sensors/Emon",
"active": false "active": false
@@ -322,6 +375,10 @@
{ {
"path": "src/modules/exec/Thermostat", "path": "src/modules/exec/Thermostat",
"active": false "active": false
},
{
"path": "src/modules/sensors/Ds2423",
"active": false
} }
], ],
"screens": [ "screens": [
@@ -337,10 +394,18 @@
"path": "src/modules/display/NextionUpload", "path": "src/modules/display/NextionUpload",
"active": false "active": false
}, },
{
"path": "src/modules/display/Oled128",
"active": false
},
{ {
"path": "src/modules/display/Smi2_m", "path": "src/modules/display/Smi2_m",
"active": true "active": true
}, },
{
"path": "src/modules/display/TM16XX",
"active": true
},
{ {
"path": "src/modules/display/Ws2812b", "path": "src/modules/display/Ws2812b",
"active": false "active": false

View File

@@ -27,13 +27,70 @@
"default_envs": "esp8266_4mb", "default_envs": "esp8266_4mb",
"comments_default_envs": "choose from: esp8266_4mb or esp32_4mb or esp32s2_4mb or esp8266_1mb or esp8266_1mb_ota or esp8285_1mb or esp8285_1mb_ota", "comments_default_envs": "choose from: esp8266_4mb or esp32_4mb or esp32s2_4mb or esp8266_1mb or esp8266_1mb_ota or esp8285_1mb or esp8285_1mb_ota",
"envs": [ "envs": [
"esp8266_4mb", {
"esp32_4mb", "name": "esp8266_4mb",
"esp8266_1mb", "firmware": "0x00000",
"esp8266_1mb_ota", "littlefs": "0x300000"
"esp8285_1mb", },
"esp8285_1mb_ota", {
"esp32s2_4mb" "name": "esp8266_16mb",
"firmware": "0x00000",
"littlefs": "0x200000"
},
{
"name": "esp32_4mb",
"boot_app0": "0xe000",
"bootloader_qio_80m": "0x1000",
"firmware": "0x10000",
"partitions": "0x8000",
"littlefs": "0x290000"
},
{
"name": "esp32_16mb",
"boot_app0": "0xe000",
"bootloader_qio_80m": "0x1000",
"firmware": "0x10000",
"partitions": "0x8000",
"littlefs": "0x910000"
},
{
"name": "esp8266_1mb",
"firmware": "0x00000000",
"littlefs": "0x000bb000"
},
{
"name": "esp8266_1mb_ota",
"firmware": "0x00000000",
"littlefs": "0x000eb000"
},
{
"name": "esp8266_2mb",
"firmware": "0x00000000",
"littlefs": "0x00100000"
},
{
"name": "esp8266_2mb_ota",
"firmware": "0x00000000",
"littlefs": "0x001c0000"
},
{
"name": "esp8285_1mb",
"firmware": "0x00000000",
"littlefs": "0x000bb000"
},
{
"name": "esp8285_1mb_ota",
"firmware": "0x00000000",
"littlefs": "0x000eb000"
},
{
"name": "esp32s2_4mb",
"boot_app0": "0xe000",
"bootloader_qio_80m": "0x1000",
"firmware": "0x10000",
"partitions": "0x8000",
"littlefs": "0x290000"
}
] ]
} }
}, },
@@ -126,11 +183,11 @@
"active": false "active": false
}, },
{ {
"path": "src/modules/sensors/Ds2423", "path": "src/modules/sensors/Emon",
"active": false "active": false
}, },
{ {
"path": "src/modules/sensors/Emon", "path": "src/modules/sensors/ExampleModule",
"active": false "active": false
}, },
{ {
@@ -165,6 +222,10 @@
"path": "src/modules/sensors/Ina219", "path": "src/modules/sensors/Ina219",
"active": false "active": false
}, },
{
"path": "src/modules/sensors/Ina226",
"active": false
},
{ {
"path": "src/modules/sensors/IoTWiegand", "path": "src/modules/sensors/IoTWiegand",
"active": false "active": false
@@ -314,6 +375,10 @@
{ {
"path": "src/modules/exec/Thermostat", "path": "src/modules/exec/Thermostat",
"active": false "active": false
},
{
"path": "src/modules/sensors/Ds2423",
"active": false
} }
], ],
"screens": [ "screens": [
@@ -329,10 +394,18 @@
"path": "src/modules/display/NextionUpload", "path": "src/modules/display/NextionUpload",
"active": false "active": false
}, },
{
"path": "src/modules/display/Oled128",
"active": false
},
{ {
"path": "src/modules/display/Smi2_m", "path": "src/modules/display/Smi2_m",
"active": true "active": true
}, },
{
"path": "src/modules/display/TM16XX",
"active": true
},
{ {
"path": "src/modules/display/Ws2812b", "path": "src/modules/display/Ws2812b",
"active": false "active": false

View File

@@ -157,6 +157,28 @@ build_src_filter =
+<modules/*.cpp> +<modules/*.cpp>
${env:esp8266_4mb_fromitems.build_src_filter} ${env:esp8266_4mb_fromitems.build_src_filter}
[env:esp8266_16mb]
extra_scripts = pre:tools/patch8266_16m.py
lib_deps =
${common_env_data.lib_deps_external}
${env:esp8266_16mb_fromitems.lib_deps}
ESPAsyncUDP
build_flags = -Desp8266_16mb="esp8266_16mb"
framework = arduino
board = nodemcuv2
platform = espressif8266 @4.0.1
board_build.ldscript = eagle.flash.16m14m.ld
monitor_filters = esp8266_exception_decoder
upload_speed = 921600
monitor_speed = 115200
board_build.filesystem = littlefs
build_src_filter =
+<*.cpp>
+<classes/*.cpp>
+<utils/*.cpp>
+<modules/*.cpp>
${env:esp8266_16mb_fromitems.build_src_filter}
[env:esp32_4mb] [env:esp32_4mb]
lib_deps = lib_deps =
${common_env_data.lib_deps_external} ${common_env_data.lib_deps_external}
@@ -200,6 +222,29 @@ build_src_filter =
+<modules/*.cpp> +<modules/*.cpp>
${env:esp32s2_4mb_fromitems.build_src_filter} ${env:esp32s2_4mb_fromitems.build_src_filter}
[env:esp32_16mb]
lib_deps =
${common_env_data.lib_deps_external}
${env:esp32_16mb_fromitems.lib_deps}
build_flags = -Desp32_16mb="esp32_16mb"
framework = arduino
board = esp32dev
platform = espressif32 @5.1.1
monitor_filters = esp32_exception_decoder
upload_port = COM11
upload_speed = 921600
monitor_speed = 115200
debug_tool = esp-prog
board_build.partitions = tools/large_spiffs_16MB.csv
board_upload.flash_size = 16MB
board_build.filesystem = littlefs
build_src_filter =
+<*.cpp>
+<classes/*.cpp>
+<utils/*.cpp>
+<modules/*.cpp>
${env:esp32_16mb_fromitems.build_src_filter}
[env:esp8266_1mb_ota_fromitems] [env:esp8266_1mb_ota_fromitems]
lib_deps = lib_deps =
adafruit/Adafruit BME280 Library adafruit/Adafruit BME280 Library
@@ -412,6 +457,9 @@ lib_deps =
adafruit/Adafruit BusIO @ ^1.13.2 adafruit/Adafruit BusIO @ ^1.13.2
https://github.com/robotclass/RobotClass_LiquidCrystal_I2C https://github.com/robotclass/RobotClass_LiquidCrystal_I2C
marcoschwartz/LiquidCrystal_I2C@^1.1.4 marcoschwartz/LiquidCrystal_I2C@^1.1.4
https://github.com/maxint-rd/TM16xx
adafruit/Adafruit GFX Library @ ^1.11.5
adafruit/Adafruit BusIO @ ^1.13.2
build_src_filter = build_src_filter =
+<modules/virtual/Cron> +<modules/virtual/Cron>
+<modules/virtual/Loging> +<modules/virtual/Loging>
@@ -448,6 +496,7 @@ build_src_filter =
+<modules/exec/Pwm8266> +<modules/exec/Pwm8266>
+<modules/exec/TelegramLT> +<modules/exec/TelegramLT>
+<modules/display/Lcd2004> +<modules/display/Lcd2004>
+<modules/display/TM16XX>
[env:esp32_4mb_fromitems] [env:esp32_4mb_fromitems]
lib_deps = lib_deps =
@@ -461,13 +510,15 @@ lib_deps =
WEMOS SHT3x@1.0.0 WEMOS SHT3x@1.0.0
plerup/EspSoftwareSerial plerup/EspSoftwareSerial
gyverlibs/EncButton @ ^2.0 gyverlibs/EncButton @ ^2.0
https://github.com/RoboticsBrno/ServoESP32 https://github.com/RoboticsBrno/ServoESP32#v1.0.3
adafruit/Adafruit MCP23017 Arduino Library@^2.1.0 adafruit/Adafruit MCP23017 Arduino Library@^2.1.0
adafruit/Adafruit BusIO @ ^1.13.2 adafruit/Adafruit BusIO @ ^1.13.2
dfrobot/DFRobotDFPlayerMini @ ^1.0.5 dfrobot/DFRobotDFPlayerMini @ ^1.0.5
adafruit/Adafruit BusIO @ ^1.13.2 adafruit/Adafruit BusIO @ ^1.13.2
https://github.com/robotclass/RobotClass_LiquidCrystal_I2C https://github.com/robotclass/RobotClass_LiquidCrystal_I2C
marcoschwartz/LiquidCrystal_I2C@^1.1.4 marcoschwartz/LiquidCrystal_I2C@^1.1.4
https://github.com/maxint-rd/TM16xx
adafruit/Adafruit GFX Library @ ^1.11.5
build_src_filter = build_src_filter =
+<modules/virtual/Cron> +<modules/virtual/Cron>
+<modules/virtual/Loging> +<modules/virtual/Loging>
@@ -504,7 +555,7 @@ build_src_filter =
+<modules/exec/TelegramLT> +<modules/exec/TelegramLT>
+<modules/display/Lcd2004> +<modules/display/Lcd2004>
+<modules/display/Smi2_m> +<modules/display/Smi2_m>
+<modules/display/TM16XX>
[env:esp32s2_4mb_fromitems] [env:esp32s2_4mb_fromitems]
lib_deps = lib_deps =
@@ -521,3 +572,31 @@ build_src_filter =
+<modules/exec/Ftp> +<modules/exec/Ftp>
+<modules/exec/TelegramLT> +<modules/exec/TelegramLT>
[env:esp8266_16mb_fromitems]
lib_deps =
gyverlibs/EncButton @ ^2.0
build_src_filter =
+<modules/virtual/Cron>
+<modules/virtual/Loging>
+<modules/virtual/LogingDaily>
+<modules/virtual/Timer>
+<modules/virtual/Variable>
+<modules/virtual/VariableColor>
+<modules/virtual/VButton>
+<modules/exec/ButtonIn>
+<modules/exec/ButtonOut>
+<modules/exec/Enconder>
+<modules/exec/TelegramLT>
[env:esp32_16mb_fromitems]
lib_deps =
build_src_filter =
+<modules/virtual/Cron>
+<modules/virtual/Loging>
+<modules/virtual/LogingDaily>
+<modules/virtual/Timer>
+<modules/virtual/Variable>
+<modules/virtual/VButton>
+<modules/exec/ButtonOut>
+<modules/exec/TelegramLT>

View File

@@ -95,6 +95,10 @@ void mqttReconnect() {
mqttConnect(); mqttConnect();
} }
bool mqttIsConnect(){
return mqtt.connected();
}
void getMqttData() { void getMqttData() {
mqttServer = jsonReadStr(settingsFlashJson, F("mqttServer")); mqttServer = jsonReadStr(settingsFlashJson, F("mqttServer"));
mqttPort = jsonReadInt(settingsFlashJson, F("mqttPort")); mqttPort = jsonReadInt(settingsFlashJson, F("mqttPort"));
@@ -116,6 +120,16 @@ void mqttSubscribe() {
} }
} }
void mqttSubscribeExternal(String topic, bool usePrefix) {
SerialPrint("i", F("MQTT"), ("subscribed external" + topic).c_str());
// SerialPrint("i", F("MQTT"), mqttRootDevice);
if (usePrefix)
{
mqtt.subscribe((mqttPrefix + topic).c_str());
}
mqtt.subscribe(topic.c_str());
}
void mqttCallback(char* topic, uint8_t* payload, size_t length) { void mqttCallback(char* topic, uint8_t* payload, size_t length) {
String topicStr = String(topic); String topicStr = String(topic);
// SerialPrint("i", "=>MQTT", topicStr); // SerialPrint("i", "=>MQTT", topicStr);

View File

@@ -101,7 +101,7 @@ String ESP32GetResetReason(uint32_t cpu_no) {
} }
} }
#endif #endif
#ifdef esp32_4mb #if defined(esp32_4mb) || defined(esp32_16mb)
String ESP_getResetReason(void) { String ESP_getResetReason(void) {
return ESP32GetResetReason(0); // CPU 0 return ESP32GetResetReason(0); // CPU 0
} }

View File

@@ -7,24 +7,22 @@ String unsupportedFiles = String();
static const char TEXT_PLAIN[] PROGMEM = "text/plain"; static const char TEXT_PLAIN[] PROGMEM = "text/plain";
static const char FS_INIT_ERROR[] PROGMEM = "FS INIT ERROR"; static const char FS_INIT_ERROR[] PROGMEM = "FS INIT ERROR";
static const char FILE_NOT_FOUND[] PROGMEM = "FileNotFound"; static const char FILE_NOT_FOUND[] PROGMEM = "FileNotFound";
//static bool fsOK; // static bool fsOK;
//const char* fsName = "LittleFS"; // const char* fsName = "LittleFS";
void standWebServerInit() void standWebServerInit() {
{
// Кэшировать файлы для быстрой работы // Кэшировать файлы для быстрой работы
HTTP.serveStatic("/bundle.js", FileFS, "/", "max-age=31536000"); // кеширование на 1 год // если указана директория то все файлы будут отмечены как Directory Request Handler
HTTP.serveStatic("/bundle.css", FileFS, "/", "max-age=31536000"); // кеширование на 1 год // если указан файл то он будет отмечен как File Request Handler
HTTP.serveStatic("/bundle.js.gz", FileFS, "/", "max-age=31536000"); // кеширование на 1 год HTTP.serveStatic("/build", FileFS, "/build", "max-age=31536000"); // кеширование на 1 год
HTTP.serveStatic("/bundle.css.gz", FileFS, "/", "max-age=31536000"); // кеширование на 1 год HTTP.serveStatic("/favicon.ico", FileFS, "/favicon.ico", "max-age=31536000"); // кеширование на 1 год
HTTP.serveStatic("/favicon.png", FileFS, "/", "max-age=31536000"); // кеширование на 1 год
// HTTP.on("/devicelist.json", HTTP_GET, []() { // HTTP.on("/devicelist.json", HTTP_GET, []() {
// HTTP.send(200, "application/json", devListHeapJson); // HTTP.send(200, "application/json", devListHeapJson);
// }); // });
HTTP.on("/settings.h.json", HTTP_GET, []() { // HTTP.on("/settings.h.json", HTTP_GET, []() {
HTTP.send(200, "application/json", settingsFlashJson); // HTTP.send(200, "application/json", settingsFlashJson);
}); //});
// HTTP.on("/settings.f.json", HTTP_GET, []() { // HTTP.on("/settings.f.json", HTTP_GET, []() {
// HTTP.send(200, "application/json", readFile(F("settings.json"), 20000)); // HTTP.send(200, "application/json", readFile(F("settings.json"), 20000));
// }); // });
@@ -46,21 +44,19 @@ void standWebServerInit()
// HTTP.send(200, "text/plain", "ok"); // HTTP.send(200, "text/plain", "ok");
// }); // });
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);
@@ -101,39 +97,33 @@ void standWebServerInit()
//////////////////////////////// ////////////////////////////////
// Utils to return HTTP codes, and determine content-type // Utils to return HTTP codes, and determine content-type
void replyOK() void replyOK() {
{
HTTP.send(200, FPSTR(TEXT_PLAIN), ""); HTTP.send(200, FPSTR(TEXT_PLAIN), "");
} }
void replyOKWithMsg(String msg) void replyOKWithMsg(String msg) {
{
HTTP.send(200, FPSTR(TEXT_PLAIN), msg); HTTP.send(200, FPSTR(TEXT_PLAIN), msg);
} }
void replyNotFound(String msg) void replyNotFound(String msg) {
{
HTTP.send(404, FPSTR(TEXT_PLAIN), msg); HTTP.send(404, FPSTR(TEXT_PLAIN), msg);
} }
void replyBadRequest(String msg) void replyBadRequest(String msg) {
{ // DBG_OUTPUT_PORT.println(msg);
// DBG_OUTPUT_PORT.println(msg);
HTTP.send(400, FPSTR(TEXT_PLAIN), msg + "\r\n"); HTTP.send(400, FPSTR(TEXT_PLAIN), msg + "\r\n");
} }
void replyServerError(String msg) void replyServerError(String msg) {
{ // DBG_OUTPUT_PORT.println(msg);
// DBG_OUTPUT_PORT.println(msg);
HTTP.send(500, FPSTR(TEXT_PLAIN), msg + "\r\n"); HTTP.send(500, FPSTR(TEXT_PLAIN), msg + "\r\n");
} }
/* /*
Return the FS type, status and size info Return the FS type, status and size info
*/ */
void handleStatus() void handleStatus() {
{ // DBG_OUTPUT_PORT.println("handleStatus");
// DBG_OUTPUT_PORT.println("handleStatus");
String json; String json;
json.reserve(128); json.reserve(128);
@@ -141,22 +131,22 @@ void handleStatus()
json += FS_NAME; json += FS_NAME;
json += "\", \"isOk\":"; json += "\", \"isOk\":";
#ifdef ESP8266 #ifdef ESP8266
FSInfo fs_info; FSInfo fs_info;
FileFS.info(fs_info); FileFS.info(fs_info);
json += F("\"true\", \"totalBytes\":\""); json += F("\"true\", \"totalBytes\":\"");
json += fs_info.totalBytes; json += fs_info.totalBytes;
json += F("\", \"usedBytes\":\""); json += F("\", \"usedBytes\":\"");
json += fs_info.usedBytes; json += fs_info.usedBytes;
json += "\""; json += "\"";
#endif #endif
#ifdef ESP32 #ifdef ESP32
json += F("\"true\", \"totalBytes\":\""); json += F("\"true\", \"totalBytes\":\"");
json += String(FileFS.totalBytes()); json += String(FileFS.totalBytes());
json += F("\", \"usedBytes\":\""); json += F("\", \"usedBytes\":\"");
json += String(FileFS.usedBytes()); json += String(FileFS.usedBytes());
json += "\""; json += "\"";
#endif #endif
json += F(",\"unsupportedFiles\":\""); json += F(",\"unsupportedFiles\":\"");
@@ -168,74 +158,66 @@ void handleStatus()
#ifdef ESP32 #ifdef ESP32
String getContentType(String filename) { String getContentType(String filename) {
if (HTTP.hasArg("download")) { if (HTTP.hasArg("download")) {
return "application/octet-stream"; return "application/octet-stream";
} else if (filename.endsWith(".htm")) { } else if (filename.endsWith(".htm")) {
return "text/html"; return "text/html";
} else if (filename.endsWith(".html")) { } else if (filename.endsWith(".html")) {
return "text/html"; return "text/html";
} else if (filename.endsWith(".css")) { } else if (filename.endsWith(".css")) {
return "text/css"; return "text/css";
} else if (filename.endsWith(".js")) { } else if (filename.endsWith(".js")) {
return "application/javascript"; return "application/javascript";
} else if (filename.endsWith(".png")) { } else if (filename.endsWith(".png")) {
return "image/png"; return "image/png";
} else if (filename.endsWith(".gif")) { } else if (filename.endsWith(".gif")) {
return "image/gif"; return "image/gif";
} else if (filename.endsWith(".jpg")) { } else if (filename.endsWith(".jpg")) {
return "image/jpeg"; return "image/jpeg";
} else if (filename.endsWith(".ico")) { } else if (filename.endsWith(".ico")) {
return "image/x-icon"; return "image/x-icon";
} else if (filename.endsWith(".xml")) { } else if (filename.endsWith(".xml")) {
return "text/xml"; return "text/xml";
} else if (filename.endsWith(".pdf")) { } else if (filename.endsWith(".pdf")) {
return "application/x-pdf"; return "application/x-pdf";
} else if (filename.endsWith(".zip")) { } else if (filename.endsWith(".zip")) {
return "application/x-zip"; return "application/x-zip";
} else if (filename.endsWith(".gz")) { } else if (filename.endsWith(".gz")) {
return "application/x-gzip"; return "application/x-gzip";
} }
return "text/plain"; return "text/plain";
} }
#endif #endif
/* /*
Read the given file from the filesystem and stream it back to the client Read the given file from the filesystem and stream it back to the client
*/ */
bool handleFileRead(String path) bool handleFileRead(String path) {
{ // DBG_OUTPUT_PORT.println(String("handleFileRead: ") + path);
// DBG_OUTPUT_PORT.println(String("handleFileRead: ") + path); if (path.endsWith("/")) {
if (path.endsWith("/"))
{
path += "index.html"; path += "index.html";
} }
String contentType; String contentType;
if (HTTP.hasArg("download")) if (HTTP.hasArg("download")) {
{
contentType = F("application/octet-stream"); contentType = F("application/octet-stream");
} } else {
else #ifdef ESP32
{
#ifdef ESP32
contentType = getContentType(path); contentType = getContentType(path);
#endif #endif
#ifdef ESP8266 #ifdef ESP8266
contentType = mime::getContentType(path); contentType = mime::getContentType(path);
#endif #endif
} }
if (!FileFS.exists(path)) if (!FileFS.exists(path)) {
{
// File not found, try gzip version // File not found, try gzip version
path = path + ".gz"; path = path + ".gz";
} }
if (FileFS.exists(path)) if (FileFS.exists(path)) {
{
File file = FileFS.open(path, "r"); File file = FileFS.open(path, "r");
if (HTTP.streamFile(file, contentType) != file.size()) if (HTTP.streamFile(file, contentType) != file.size()) {
{ // DBG_OUTPUT_PORT.println("Sent less data than expected!");
// DBG_OUTPUT_PORT.println("Sent less data than expected!");
} }
file.close(); file.close();
return true; return true;
@@ -248,90 +230,69 @@ bool handleFileRead(String path)
As some FS (e.g. LittleFS) delete the parent folder when the last child has been removed, As some FS (e.g. LittleFS) delete the parent folder when the last child has been removed,
return the path of the closest parent still existing return the path of the closest parent still existing
*/ */
String lastExistingParent(String path) String lastExistingParent(String path) {
{ while (!path.isEmpty() && !FileFS.exists(path)) {
while (!path.isEmpty() && !FileFS.exists(path)) if (path.lastIndexOf('/') > 0) {
{
if (path.lastIndexOf('/') > 0)
{
path = path.substring(0, path.lastIndexOf('/')); path = path.substring(0, path.lastIndexOf('/'));
} } else {
else path = String(); // No slash => the top folder does not exist
{
path = String(); // No slash => the top folder does not exist
} }
} }
// DBG_OUTPUT_PORT.println(String("Last existing parent: ") + path); // DBG_OUTPUT_PORT.println(String("Last existing parent: ") + path);
return path; return path;
} }
/* /*
Handle a file upload request Handle a file upload request
*/ */
void handleFileUpload() void handleFileUpload() {
{ if (HTTP.uri() != "/edit") {
if (HTTP.uri() != "/edit")
{
return; return;
} }
HTTPUpload &upload = HTTP.upload(); HTTPUpload &upload = HTTP.upload();
if (upload.status == UPLOAD_FILE_START) if (upload.status == UPLOAD_FILE_START) {
{
String filename = upload.filename; String filename = upload.filename;
// Make sure paths always start with "/" // Make sure paths always start with "/"
if (!filename.startsWith("/")) if (!filename.startsWith("/")) {
{
filename = "/" + filename; filename = "/" + filename;
} }
// DBG_OUTPUT_PORT.println(String("handleFileUpload Name: ") + filename); // DBG_OUTPUT_PORT.println(String("handleFileUpload Name: ") + filename);
uploadFile = FileFS.open(filename, "w"); uploadFile = FileFS.open(filename, "w");
if (!uploadFile) if (!uploadFile) {
{
return replyServerError(F("CREATE FAILED")); return replyServerError(F("CREATE FAILED"));
} }
// DBG_OUTPUT_PORT.println(String("Upload: START, filename: ") + filename); // DBG_OUTPUT_PORT.println(String("Upload: START, filename: ") + filename);
} } else if (upload.status == UPLOAD_FILE_WRITE) {
else if (upload.status == UPLOAD_FILE_WRITE) if (uploadFile) {
{
if (uploadFile)
{
size_t bytesWritten = uploadFile.write(upload.buf, upload.currentSize); size_t bytesWritten = uploadFile.write(upload.buf, upload.currentSize);
if (bytesWritten != upload.currentSize) if (bytesWritten != upload.currentSize) {
{
return replyServerError(F("WRITE FAILED")); return replyServerError(F("WRITE FAILED"));
} }
} }
// DBG_OUTPUT_PORT.println(String("Upload: WRITE, Bytes: ") + upload.currentSize); // DBG_OUTPUT_PORT.println(String("Upload: WRITE, Bytes: ") + upload.currentSize);
} } else if (upload.status == UPLOAD_FILE_END) {
else if (upload.status == UPLOAD_FILE_END) if (uploadFile) {
{
if (uploadFile)
{
uploadFile.close(); uploadFile.close();
} }
// DBG_OUTPUT_PORT.println(String("Upload: END, Size: ") + upload.totalSize); // DBG_OUTPUT_PORT.println(String("Upload: END, Size: ") + upload.totalSize);
} }
} }
#ifdef ESP8266 #ifdef ESP8266
void deleteRecursive(String path) void deleteRecursive(String path) {
{
File file = FileFS.open(path, "r"); File file = FileFS.open(path, "r");
bool isDir = file.isDirectory(); bool isDir = file.isDirectory();
file.close(); file.close();
// If it's a plain file, delete it // If it's a plain file, delete it
if (!isDir) if (!isDir) {
{
FileFS.remove(path); FileFS.remove(path);
return; return;
} }
Dir dir = FileFS.openDir(path); Dir dir = FileFS.openDir(path);
while (dir.next()) while (dir.next()) {
{
deleteRecursive(path + '/' + dir.fileName()); deleteRecursive(path + '/' + dir.fileName());
} }
// Then delete the folder itself // Then delete the folder itself
FileFS.rmdir(path); FileFS.rmdir(path);
@@ -339,41 +300,37 @@ void deleteRecursive(String path)
#endif #endif
#ifdef ESP32 #ifdef ESP32
struct treename{ struct treename {
uint8_t type; uint8_t type;
char *name; char *name;
}; };
void deleteRecursive(String path) {
fs::File dir = FileFS.open(path);
void deleteRecursive( String path ){ if (!dir.isDirectory()) {
fs::File dir = FileFS.open( path ); Serial.printf("%s is a file\n", path);
dir.close();
if(!dir.isDirectory()){ Serial.printf("result of removing file %s: %d\n", path, FileFS.remove(path));
Serial.printf("%s is a file\n", path); return;
dir.close();
Serial.printf( "result of removing file %s: %d\n", path, FileFS.remove( path ) );
return;
} }
Serial.printf("%s is a directory\n", path); Serial.printf("%s is a directory\n", path);
fs::File entry, nextentry; fs::File entry, nextentry;
while ( entry = dir.openNextFile() ){ while (entry = dir.openNextFile()) {
if (entry.isDirectory()) {
if ( entry.isDirectory() ){ deleteRecursive(entry.path());
deleteRecursive( entry.path() ); } else {
} else{ String tmpname = path + "/" + strdup(entry.name()); // buffer file name
String tmpname = path+"/"+strdup( entry.name() ); // buffer file name entry.close();
entry.close(); Serial.printf("result of removing file %s: %d\n", tmpname, FileFS.remove(tmpname));
Serial.printf( "result of removing file %s: %d\n", tmpname, FileFS.remove( tmpname ) ); }
}
} }
dir.close(); dir.close();
Serial.printf( "result of removing directory %s: %d\n", path, FileFS.rmdir( path ) ); Serial.printf("result of removing directory %s: %d\n", path, FileFS.rmdir(path));
} }
#endif #endif
/* /*
@@ -383,23 +340,18 @@ if ( entry.isDirectory() ){
Delete file | parent of deleted file, or remaining ancestor Delete file | parent of deleted file, or remaining ancestor
Delete folder | parent of deleted folder, or remaining ancestor Delete folder | parent of deleted folder, or remaining ancestor
*/ */
void handleFileDelete() void handleFileDelete() {
{
String path = HTTP.arg(0); String path = HTTP.arg(0);
if (path.isEmpty() || path == "/") if (path.isEmpty() || path == "/") {
{
return replyBadRequest("BAD PATH"); return replyBadRequest("BAD PATH");
} }
// DBG_OUTPUT_PORT.println(String("handleFileDelete: ") + path); // DBG_OUTPUT_PORT.println(String("handleFileDelete: ") + path);
if (!FileFS.exists(path)) if (!FileFS.exists(path)) {
{
return replyNotFound(FPSTR(FILE_NOT_FOUND)); return replyNotFound(FPSTR(FILE_NOT_FOUND));
} }
deleteRecursive(path); deleteRecursive(path);
replyOKWithMsg(lastExistingParent(path)); replyOKWithMsg(lastExistingParent(path));
} }
@@ -414,93 +366,72 @@ void handleFileDelete()
Rename folder | parent of source folder Rename folder | parent of source folder
Move folder | parent of source folder, or remaining ancestor Move folder | parent of source folder, or remaining ancestor
*/ */
void handleFileCreate() void handleFileCreate() {
{
String path = HTTP.arg("path"); String path = HTTP.arg("path");
if (path.isEmpty()) if (path.isEmpty()) {
{
return replyBadRequest(F("PATH ARG MISSING")); return replyBadRequest(F("PATH ARG MISSING"));
} }
#ifdef USE_SPIFFS #ifdef USE_SPIFFS
if (checkForUnsupportedPath(path).length() > 0) if (checkForUnsupportedPath(path).length() > 0) {
{
return replyServerError(F("INVALID FILENAME")); return replyServerError(F("INVALID FILENAME"));
} }
#endif #endif
if (path == "/") if (path == "/") {
{
return replyBadRequest("BAD PATH"); return replyBadRequest("BAD PATH");
} }
if (FileFS.exists(path)) if (FileFS.exists(path)) {
{
return replyBadRequest(F("PATH FILE EXISTS")); return replyBadRequest(F("PATH FILE EXISTS"));
} }
String src = HTTP.arg("src"); String src = HTTP.arg("src");
if (src.isEmpty()) if (src.isEmpty()) {
{
// No source specified: creation // No source specified: creation
// DBG_OUTPUT_PORT.println(String("handleFileCreate: ") + path); // DBG_OUTPUT_PORT.println(String("handleFileCreate: ") + path);
if (path.endsWith("/")) if (path.endsWith("/")) {
{
// Create a folder // Create a folder
path.remove(path.length() - 1); path.remove(path.length() - 1);
if (!FileFS.mkdir(path)) if (!FileFS.mkdir(path)) {
{
return replyServerError(F("MKDIR FAILED")); return replyServerError(F("MKDIR FAILED"));
} }
} } else {
else
{
// Create a file // Create a file
File file = FileFS.open(path, "w"); File file = FileFS.open(path, "w");
if (file) if (file) {
{ #ifdef ESP8266
#ifdef ESP8266
file.write((const char *)0); file.write((const char *)0);
#endif #endif
#ifdef ESP32 #ifdef ESP32
file.write(0); file.write(0);
#endif #endif
file.close(); file.close();
} } else {
else
{
return replyServerError(F("CREATE FAILED")); return replyServerError(F("CREATE FAILED"));
} }
} }
if (path.lastIndexOf('/') > -1) if (path.lastIndexOf('/') > -1) {
{
path = path.substring(0, path.lastIndexOf('/')); path = path.substring(0, path.lastIndexOf('/'));
} }
replyOKWithMsg(path); replyOKWithMsg(path);
} } else {
else
{
// Source specified: rename // Source specified: rename
if (src == "/") if (src == "/") {
{
return replyBadRequest("BAD SRC"); return replyBadRequest("BAD SRC");
} }
if (!FileFS.exists(src)) if (!FileFS.exists(src)) {
{
return replyBadRequest(F("SRC FILE NOT FOUND")); return replyBadRequest(F("SRC FILE NOT FOUND"));
} }
// DBG_OUTPUT_PORT.println(String("handleFileCreate: ") + path + " from " + src); // DBG_OUTPUT_PORT.println(String("handleFileCreate: ") + path + " from " + src);
if (path.endsWith("/")) if (path.endsWith("/")) {
{
path.remove(path.length() - 1); path.remove(path.length() - 1);
} }
if (src.endsWith("/")) if (src.endsWith("/")) {
{
src.remove(src.length() - 1); src.remove(src.length() - 1);
} }
if (!FileFS.rename(src, path)) if (!FileFS.rename(src, path)) {
{
return replyServerError(F("RENAME FAILED")); return replyServerError(F("RENAME FAILED"));
} }
replyOKWithMsg(lastExistingParent(src)); replyOKWithMsg(lastExistingParent(src));
@@ -512,26 +443,22 @@ void handleFileCreate()
Also demonstrates the use of chunked responses. Also demonstrates the use of chunked responses.
*/ */
#ifdef ESP8266 #ifdef ESP8266
void handleFileList() void handleFileList() {
{ if (!HTTP.hasArg("dir")) {
if (!HTTP.hasArg("dir"))
{
return replyBadRequest(F("DIR ARG MISSING")); return replyBadRequest(F("DIR ARG MISSING"));
} }
String path = HTTP.arg("dir"); String path = HTTP.arg("dir");
if (path != "/" && !FileFS.exists(path)) if (path != "/" && !FileFS.exists(path)) {
{
return replyBadRequest("BAD PATH"); return replyBadRequest("BAD PATH");
} }
// DBG_OUTPUT_PORT.println(String("handleFileList: ") + path); // DBG_OUTPUT_PORT.println(String("handleFileList: ") + path);
Dir dir = FileFS.openDir(path); Dir dir = FileFS.openDir(path);
path.clear(); path.clear();
// use HTTP/1.1 Chunked response to avoid building a huge temporary string // use HTTP/1.1 Chunked response to avoid building a huge temporary string
if (!HTTP.chunkedResponseModeStart(200, "text/json")) if (!HTTP.chunkedResponseModeStart(200, "text/json")) {
{
HTTP.send(505, F("text/html"), F("HTTP1.1 required")); HTTP.send(505, F("text/html"), F("HTTP1.1 required"));
return; return;
} }
@@ -539,47 +466,36 @@ void handleFileList()
// use the same string for every line // use the same string for every line
String output; String output;
output.reserve(64); output.reserve(64);
while (dir.next()) while (dir.next()) {
{
#ifdef USE_SPIFFS #ifdef USE_SPIFFS
String error = checkForUnsupportedPath(dir.fileName()); String error = checkForUnsupportedPath(dir.fileName());
if (error.length() > 0) if (error.length() > 0) {
{ // DBG_OUTPUT_PORT.println(String("Ignoring ") + error + dir.fileName());
// DBG_OUTPUT_PORT.println(String("Ignoring ") + error + dir.fileName());
continue; continue;
} }
#endif #endif
if (output.length()) if (output.length()) {
{
// send string from previous iteration // send string from previous iteration
// as an HTTP chunk // as an HTTP chunk
HTTP.sendContent(output); HTTP.sendContent(output);
output = ','; output = ',';
} } else {
else
{
output = '['; output = '[';
} }
output += "{\"type\":\""; output += "{\"type\":\"";
if (dir.isDirectory()) if (dir.isDirectory()) {
{
output += "dir"; output += "dir";
} } else {
else
{
output += F("file\",\"size\":\""); output += F("file\",\"size\":\"");
output += dir.fileSize(); output += dir.fileSize();
} }
output += F("\",\"name\":\""); output += F("\",\"name\":\"");
// Always return names without leading "/" // Always return names without leading "/"
if (dir.fileName()[0] == '/') if (dir.fileName()[0] == '/') {
{
output += &(dir.fileName()[1]); output += &(dir.fileName()[1]);
} } else {
else
{
output += dir.fileName(); output += dir.fileName();
} }
@@ -595,65 +511,57 @@ void handleFileList()
#ifdef ESP32 #ifdef ESP32
void handleFileList() { void handleFileList() {
if (!HTTP.hasArg("dir")) { if (!HTTP.hasArg("dir")) {
HTTP.send(500, "text/plain", "BAD ARGS"); HTTP.send(500, "text/plain", "BAD ARGS");
return; return;
} }
String path = HTTP.arg("dir"); String path = HTTP.arg("dir");
// DBG_OUTPUT_PORT.println("handleFileList: " + path); // DBG_OUTPUT_PORT.println("handleFileList: " + path);
File root = FileFS.open(path);
path = String();
File root = FileFS.open(path); String output = "[";
path = String(); 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();
}
String output = "["; output += "\",\"name\":\"";
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 += String(file.name());
output += "\"}"; output += "\"}";
file = root.openNextFile(); file = root.openNextFile();
} }
} }
output += "]"; output += "]";
HTTP.send(200, "text/json", output); HTTP.send(200, "text/json", output);
} }
#endif #endif
/* /*
The "Not Found" handler catches all URI not explicitly declared in code The "Not Found" handler catches all URI not explicitly declared in code
First try to find and return the requested file from the filesystem, First try to find and return the requested file from the filesystem,
and if it fails, return a 404 page with debug information and if it fails, return a 404 page with debug information
*/ */
void handleNotFound() void handleNotFound() {
{
#ifdef ESP8266 #ifdef ESP8266
String uri = ESP8266WebServer::urlDecode(HTTP.uri()); // required to read paths with blanks String uri = ESP8266WebServer::urlDecode(HTTP.uri()); // required to read paths with blanks
#endif #endif
#ifdef ESP32 #ifdef ESP32
String uri = WebServer::urlDecode(HTTP.uri()); // required to read paths with blanks String uri = WebServer::urlDecode(HTTP.uri()); // required to read paths with blanks
#endif #endif
if (handleFileRead(uri)) if (handleFileRead(uri)) {
{
return; return;
} }
@@ -667,8 +575,7 @@ void handleNotFound()
message += F("\nArguments: "); message += F("\nArguments: ");
message += HTTP.args(); message += HTTP.args();
message += '\n'; message += '\n';
for (uint8_t i = 0; i < HTTP.args(); i++) for (uint8_t i = 0; i < HTTP.args(); i++) {
{
message += F(" NAME:"); message += F(" NAME:");
message += HTTP.argName(i); message += HTTP.argName(i);
message += F("\n VALUE:"); message += F("\n VALUE:");
@@ -678,7 +585,7 @@ void handleNotFound()
message += "path="; message += "path=";
message += HTTP.arg("path"); message += HTTP.arg("path");
message += '\n'; message += '\n';
// DBG_OUTPUT_PORT.print(message); // DBG_OUTPUT_PORT.print(message);
return replyNotFound(message); return replyNotFound(message);
} }
@@ -689,10 +596,8 @@ void handleNotFound()
embedded in the program code. embedded in the program code.
Otherwise, fails with a 404 page with debug information Otherwise, fails with a 404 page with debug information
*/ */
void handleGetEdit() void handleGetEdit() {
{ if (handleFileRead(F("/edit.htm"))) {
if (handleFileRead(F("/edit.htm")))
{
return; return;
} }

View File

@@ -74,7 +74,7 @@ bool upgradeBuild() {
handleUpdateStatus(true, PATH_ERROR); handleUpdateStatus(true, PATH_ERROR);
return ret; return ret;
} }
#if defined(esp8266_4mb) || defined(esp8266_1mb) || defined(esp8266_1mb_ota) || defined(esp8266_2mb) || defined(esp8266_2mb_ota) #if defined(esp8266_4mb) || defined(esp8266_16mb) || defined(esp8266_1mb) || defined(esp8266_1mb_ota) || defined(esp8266_2mb) || defined(esp8266_2mb_ota)
ESPhttpUpdate.rebootOnUpdate(false); ESPhttpUpdate.rebootOnUpdate(false);
t_httpUpdate_return retBuild = ESPhttpUpdate.update(wifiClient, getBinPath("firmware.bin")); t_httpUpdate_return retBuild = ESPhttpUpdate.update(wifiClient, getBinPath("firmware.bin"));
#endif #endif

View File

@@ -4,441 +4,482 @@ extern IoTScenario iotScen;
#ifdef STANDARD_WEB_SOCKETS #ifdef STANDARD_WEB_SOCKETS
void standWebSocketsInit() { void standWebSocketsInit() {
standWebSocket.begin(); standWebSocket.begin();
standWebSocket.onEvent(webSocketEvent); standWebSocket.onEvent(webSocketEvent);
SerialPrint("i", "WS", "WS server initialized"); SerialPrint("i", "WS", "WS server initialized");
} }
void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length) { void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload,
switch (type) { size_t length) {
case WStype_ERROR: { switch (type) {
Serial.printf("[%u] Error!\n", num); case WStype_ERROR: {
} break; Serial.printf("[%u] Error!\n", num);
} break;
case WStype_DISCONNECTED: { case WStype_DISCONNECTED: {
Serial.printf("[%u] Disconnected!\n", num); Serial.printf("[%u] Disconnected!\n", num);
} break; } break;
case WStype_CONNECTED: { case WStype_CONNECTED: {
// IPAddress ip = standWebSocket.remoteIP(num); // IPAddress ip = standWebSocket.remoteIP(num);
SerialPrint("i", "WS " + String(num), "WS client connected"); SerialPrint("i", "WS " + String(num), "WS client connected");
if (num >= 3) { if (num >= 3) {
SerialPrint("E", "WS", "Too many clients, connection closed!!!"); SerialPrint("E", "WS", "Too many clients, connection closed!!!");
jsonWriteInt(errorsHeapJson, "wse1", 1); jsonWriteInt(errorsHeapJson, "wse1", 1);
standWebSocket.close(); standWebSocket.close();
standWebSocketsInit(); standWebSocketsInit();
}
// Serial.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0],
// ip[1], ip[2], ip[3], payload); standWebSocket.sendTXT(num,
// "Connected");
} break;
case WStype_TEXT: {
bool endOfHeaderFound = false;
size_t maxAllowedHeaderSize =
15; // максимальное количество символов заголовка
size_t headerLenth = 0;
String headerStr;
for (size_t i = 0; i <= maxAllowedHeaderSize; i++) {
headerLenth++;
char s = (char)payload[i];
headerStr += s;
if (s == '|') {
endOfHeaderFound = true;
break;
}
}
if (!endOfHeaderFound) {
SerialPrint("E", "WS " + String(num), "Package without header");
}
//----------------------------------------------------------------------//
// Страница веб интерфейса dashboard
//----------------------------------------------------------------------//
// публикация всех виджетов
if (headerStr == "/|") {
sendFileToWsByFrames("/layout.json", "layout", "", num,
WEB_SOCKETS_FRAME_SIZE);
}
if (headerStr == "/params|") {
// публикация всех статус сообщений при подключении svelte приложения
String params = "{}";
for (std::list<IoTItem*>::iterator it = IoTItems.begin();
it != IoTItems.end(); ++it) {
if ((*it)->getSubtype() != "Loging") {
if ((*it)->getSubtype() != "LogingDaily") {
if ((*it)->iAmLocal)
jsonWriteStr(params, (*it)->getID(), (*it)->getValue());
} }
// Serial.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload); }
// standWebSocket.sendTXT(num, "Connected"); }
} break; sendStringToWs("params", params, num);
case WStype_TEXT: { // генерация события подключения в модулях
bool endOfHeaderFound = false; for (std::list<IoTItem*>::iterator it = IoTItems.begin();
size_t maxAllowedHeaderSize = 15; // максимальное количество символов заголовка it != IoTItems.end(); ++it) {
size_t headerLenth = 0; if ((*it)->iAmLocal) (*it)->onMqttWsAppConnectEvent();
String headerStr; }
for (size_t i = 0; i <= maxAllowedHeaderSize; i++) { }
headerLenth++;
char s = (char)payload[i];
headerStr += s;
if (s == '|') {
endOfHeaderFound = true;
break;
}
}
if (!endOfHeaderFound) {
SerialPrint("E", "WS " + String(num), "Package without header");
}
//----------------------------------------------------------------------// // отвечаем на запрос графиков
// Страница веб интерфейса dashboard if (headerStr == "/charts|") {
//----------------------------------------------------------------------// // обращение к логированию из ядра
// отправка данных графиков только в выбранный сокет
for (std::list<IoTItem*>::iterator it = IoTItems.begin();
it != IoTItems.end(); ++it) {
// сбрасываем даты графиков
// if ((*it)->getID().endsWith("-date")) {
// (*it)->setTodayDate();
// }
if ((*it)->getSubtype() == "Loging" || "LogingDaily") {
(*it)->setPublishDestination(TO_WS, num);
(*it)->publishValue();
}
}
}
// публикация всех виджетов //----------------------------------------------------------------------//
if (headerStr == "/|") { // Страница веб интерфейса configutation
sendFileToWsByFrames("/layout.json", "layout", "", num, WEB_SOCKETS_FRAME_SIZE); //----------------------------------------------------------------------//
}
if (headerStr == "/params|") { // отвечаем данными на запрос страницы
// публикация всех статус сообщений при подключении svelte приложения if (headerStr == "/config|") {
String params = "{}"; sendFileToWsByFrames("/items.json", "itemsj", "", num,
for (std::list<IoTItem*>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) { WEB_SOCKETS_FRAME_SIZE);
if ((*it)->getSubtype() != "Loging") { sendFileToWsByFrames("/widgets.json", "widget", "", num,
if ((*it)->getSubtype() != "LogingDaily") { WEB_SOCKETS_FRAME_SIZE);
if ((*it)->iAmLocal) jsonWriteStr(params, (*it)->getID(), (*it)->getValue()); sendFileToWsByFrames("/config.json", "config", "", num,
} WEB_SOCKETS_FRAME_SIZE);
} sendFileToWsByFrames("/scenario.txt", "scenar", "", num,
} WEB_SOCKETS_FRAME_SIZE);
sendStringToWs("params", params, num); sendStringToWs("settin", settingsFlashJson, num);
}
// генерация события подключения в модулях // обработка кнопки сохранить
for (std::list<IoTItem*>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) { if (headerStr == "/gifnoc|") {
if ((*it)->iAmLocal) (*it)->onMqttWsAppConnectEvent(); writeFileUint8tByFrames("config.json", payload, length, headerLenth,
} 256);
} }
if (headerStr == "/tuoyal|") {
writeFileUint8tByFrames("layout.json", payload, length, headerLenth,
256);
}
if (headerStr == "/oiranecs|") {
writeFileUint8tByFrames("scenario.txt", payload, length, headerLenth,
256);
clearConfigure();
configure("/config.json");
iotScen.loadScenario("/scenario.txt");
// создаем событие завершения конфигурирования для возможности
// выполнения блока кода при загрузке
createItemFromNet("onStart", "1", 1);
}
// отвечаем на запрос графиков //----------------------------------------------------------------------//
if (headerStr == "/charts|") { // Страница веб интерфейса connection
// обращение к логированию из ядра //----------------------------------------------------------------------//
// отправка данных графиков только в выбранный сокет
for (std::list<IoTItem*>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
// сбрасываем даты графиков
// if ((*it)->getID().endsWith("-date")) {
// (*it)->setTodayDate();
// }
if ((*it)->getSubtype() == "Loging" || "LogingDaily") {
(*it)->setPublishDestination(TO_WS, num);
(*it)->publishValue();
}
}
}
//----------------------------------------------------------------------// // отвечаем данными на запрос страницы
// Страница веб интерфейса configutation if (headerStr == "/connection|") {
//----------------------------------------------------------------------// sendStringToWs("settin", settingsFlashJson, num);
sendStringToWs("ssidli", ssidListHeapJson, num);
sendStringToWs("errors", errorsHeapJson, num);
// запуск асинхронного сканирования wifi сетей при переходе на страницу
// соединений RouterFind(jsonReadStr(settingsFlashJson,
// F("routerssid")));
}
// отвечаем данными на запрос страницы // обработка кнопки сохранить settings.json
if (headerStr == "/config|") { if (headerStr == "/sgnittes|") {
sendFileToWsByFrames("/items.json", "itemsj", "", num, WEB_SOCKETS_FRAME_SIZE); writeUint8tToString(payload, length, headerLenth, settingsFlashJson);
sendFileToWsByFrames("/widgets.json", "widget", "", num, WEB_SOCKETS_FRAME_SIZE); writeFileUint8tByFrames("settings.json", payload, length, headerLenth,
sendFileToWsByFrames("/config.json", "config", "", num, WEB_SOCKETS_FRAME_SIZE); 256);
sendFileToWsByFrames("/scenario.txt", "scenar", "", num, WEB_SOCKETS_FRAME_SIZE); sendStringToWs("errors", errorsHeapJson, num);
sendStringToWs("settin", settingsFlashJson, num); // если не было создано приема данных по udp - то создадим его
} addThisDeviceToList();
}
// обработка кнопки сохранить // обработка кнопки сохранить настройки mqtt
if (headerStr == "/gifnoc|") { if (headerStr == "/mqtt|") {
writeFileUint8tByFrames("config.json", payload, length, headerLenth, 256); sendStringToWs("settin", settingsFlashJson,
} num); // отправляем в ответ новые полученные настройки
if (headerStr == "/tuoyal|") { handleMqttStatus(false, 8); // меняем статус на неопределенный
writeFileUint8tByFrames("layout.json", payload, length, headerLenth, 256); mqttReconnect(); // начинаем переподключение
} sendStringToWs("errors", errorsHeapJson,
if (headerStr == "/oiranecs|") { num); // отправляем что статус неопределен
writeFileUint8tByFrames("scenario.txt", payload, length, headerLenth, 256); sendStringToWs("ssidli", ssidListHeapJson, num);
clearConfigure(); }
configure("/config.json");
iotScen.loadScenario("/scenario.txt");
// создаем событие завершения конфигурирования для возможности выполнения блока кода при загрузке
createItemFromNet("onStart", "1", 1);
}
//----------------------------------------------------------------------// // запуск асинхронного сканирования wifi сетей при нажатии выпадающего
// Страница веб интерфейса connection // списка
//----------------------------------------------------------------------// if (headerStr == "/scan|") {
std::vector<String> jArray;
jsonReadArray(settingsFlashJson, "routerssid", jArray);
RouterFind(jArray);
sendStringToWs("ssidli", ssidListHeapJson, num);
}
// отвечаем данными на запрос страницы //----------------------------------------------------------------------//
if (headerStr == "/connection|") { // Страница веб интерфейса list
sendStringToWs("settin", settingsFlashJson, num); //----------------------------------------------------------------------//
sendStringToWs("ssidli", ssidListHeapJson, num);
sendStringToWs("errors", errorsHeapJson, num);
// запуск асинхронного сканирования wifi сетей при переходе на страницу соединений
// RouterFind(jsonReadStr(settingsFlashJson, F("routerssid")));
}
// обработка кнопки сохранить settings.json // отвечаем данными на запрос страницы list
if (headerStr == "/sgnittes|") { if (headerStr == "/list|") {
writeUint8tToString(payload, length, headerLenth, settingsFlashJson); sendStringToWs("settin", settingsFlashJson, num);
writeFileUint8tByFrames("settings.json", payload, length, headerLenth, 256); // отправим список устройств в зависимости от того что выбрал user
sendStringToWs("errors", errorsHeapJson, num); // sendDeviceList(num);
// если не было создано приема данных по udp - то создадим его }
addThisDeviceToList();
}
// обработка кнопки сохранить настройки mqtt // отвечаем на запрос списка устройств (это отдельный запрос который
if (headerStr == "/mqtt|") { // делает приложение при подключении)
sendStringToWs("settin", settingsFlashJson, num); // отправляем в ответ новые полученные настройки if (headerStr == "/devlist|") {
handleMqttStatus(false, 8); // меняем статус на неопределенный // отправим список устройств в зависимости от того что выбрал user
mqttReconnect(); // начинаем переподключение sendDeviceList(num);
sendStringToWs("errors", errorsHeapJson, num); // отправляем что статус неопределен }
sendStringToWs("ssidli", ssidListHeapJson, num);
}
// запуск асинхронного сканирования wifi сетей при нажатии выпадающего списка // сохраняем данные листа
if (headerStr == "/scan|") { if (headerStr == "/tsil|") {
RouterFind(jsonReadStr(settingsFlashJson, F("routerssid"))); writeFileUint8tByFrames("devlist.json", payload, length, headerLenth,
sendStringToWs("ssidli", ssidListHeapJson, num); 256);
} }
//----------------------------------------------------------------------// //----------------------------------------------------------------------//
// Страница веб интерфейса list // Страница веб интерфейса system
//----------------------------------------------------------------------// //----------------------------------------------------------------------//
// отвечаем данными на запрос страницы list // отвечаем данными на запрос страницы
if (headerStr == "/list|") { if (headerStr == "/system|") {
sendStringToWs("settin", settingsFlashJson, num); sendStringToWs("errors", errorsHeapJson, num);
// отправим список устройств в зависимости от того что выбрал user sendStringToWs("settin", settingsFlashJson, num);
// sendDeviceList(num); }
}
// отвечаем на запрос списка устройств (это отдельный запрос который делает приложение при подключении) //----------------------------------------------------------------------//
if (headerStr == "/devlist|") { // Страница веб интерфейса dev
// отправим список устройств в зависимости от того что выбрал user //----------------------------------------------------------------------//
sendDeviceList(num); if (headerStr == "/dev|") {
} sendStringToWs("errors", errorsHeapJson, num);
sendStringToWs("settin", settingsFlashJson, num);
sendFileToWsByFrames("/config.json", "config", "", num,
WEB_SOCKETS_FRAME_SIZE);
sendFileToWsByFrames("/items.json", "itemsj", "", num,
WEB_SOCKETS_FRAME_SIZE);
// sendFileToWsByFrames("/layout.json", "layout", "", num,
// WEB_SOCKETS_FRAME_SIZE);
}
// сохраняем данные листа if (headerStr == "/test|") {
if (headerStr == "/tsil|") { }
writeFileUint8tByFrames("devlist.json", payload, length, headerLenth, 256);
}
//----------------------------------------------------------------------// //----------------------------------------------------------------------//
// Страница веб интерфейса system // отдельные команды веб интерфейса
//----------------------------------------------------------------------// //----------------------------------------------------------------------//
// отвечаем данными на запрос страницы // переписать любое поле в errors json
if (headerStr == "/system|") { if (headerStr == "/rorre|") {
sendStringToWs("errors", errorsHeapJson, num); writeUint8tValueToJsonString(payload, length, headerLenth,
sendStringToWs("settin", settingsFlashJson, num); errorsHeapJson);
} }
//----------------------------------------------------------------------// // команда перезагрузки esp
// Страница веб интерфейса dev if (headerStr == "/reboot|") {
//----------------------------------------------------------------------// ESP.restart();
if (headerStr == "/dev|") { }
sendStringToWs("errors", errorsHeapJson, num);
sendStringToWs("settin", settingsFlashJson, num);
sendFileToWsByFrames("/config.json", "config", "", num, WEB_SOCKETS_FRAME_SIZE);
sendFileToWsByFrames("/items.json", "itemsj", "", num, WEB_SOCKETS_FRAME_SIZE);
// sendFileToWsByFrames("/layout.json", "layout", "", num, WEB_SOCKETS_FRAME_SIZE);
}
if (headerStr == "/test|") { // команда очистки всех логов esp
} if (headerStr == "/clean|") {
cleanLogs();
}
//----------------------------------------------------------------------// // команда обновления прошивки esp
// отдельные команды веб интерфейса if (headerStr == "/update|") {
//----------------------------------------------------------------------// upgrade_firmware(3);
}
// переписать любое поле в errors json // Прием команд control c dashboard
if (headerStr == "/rorre|") { if (headerStr == "/control|") {
writeUint8tValueToJsonString(payload, length, headerLenth, errorsHeapJson); String msg;
} writeUint8tToString(payload, length, headerLenth, msg);
String key = selectFromMarkerToMarker(msg, "/", 0);
String value = selectFromMarkerToMarker(msg, "/", 1);
generateOrder(key, value);
SerialPrint(
"i", F("=>WS"),
"Msg from svelte web, WS No: " + String(num) + ", msg: " + msg);
}
// команда перезагрузки esp if (headerStr == "/tst|") {
if (headerStr == "/reboot|") { standWebSocket.sendTXT(num, "/tstr|");
ESP.restart(); }
}
// команда очистки всех логов esp // получаем команду посланную из модуля
if (headerStr == "/clean|") { if (headerStr == "/order|") {
cleanLogs(); String json;
} writeUint8tToString(payload, length, headerLenth, json);
// команда обновления прошивки esp String id, key, value;
if (headerStr == "/update|") { jsonRead(json, "id", id);
upgrade_firmware(3); jsonRead(json, "key", key);
} jsonRead(json, "value", value);
// Прием команд control c dashboard SerialPrint("i", F("=>WS"), "Msg from module, id: " + id);
if (headerStr == "/control|") {
String msg;
writeUint8tToString(payload, length, headerLenth, msg);
String key = selectFromMarkerToMarker(msg, "/", 0);
String value = selectFromMarkerToMarker(msg, "/", 1);
generateOrder(key, value);
SerialPrint("i", F("=>WS"), "Msg from svelte web, WS No: " + String(num) + ", msg: " + msg);
}
if (headerStr == "/tst|") { for (std::list<IoTItem*>::iterator it = IoTItems.begin();
standWebSocket.sendTXT(num, "/tstr|"); it != IoTItems.end(); ++it) {
} if ((*it)->getID() == id) {
(*it)->onModuleOrder(key, value);
}
}
}
// получаем команду посланную из модуля } break;
if (headerStr == "/order|") {
String json;
writeUint8tToString(payload, length, headerLenth, json);
String id, key, value; case WStype_BIN: {
jsonRead(json, "id", id); Serial.printf("[%u] get binary length: %u\n", num, length);
jsonRead(json, "key", key); // hexdump(payload, length);
jsonRead(json, "value", value); // standWebSocket.sendBIN(num, payload, length);
} break;
SerialPrint("i", F("=>WS"), "Msg from module, id: " + id); case WStype_FRAGMENT_TEXT_START: {
Serial.printf("[%u] fragment test start: %u\n", num, length);
} break;
for (std::list<IoTItem*>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) { case WStype_FRAGMENT_BIN_START: {
if ((*it)->getID() == id) { Serial.printf("[%u] fragment bin start: %u\n", num, length);
(*it)->onModuleOrder(key, value); } break;
}
}
}
} break; case WStype_FRAGMENT: {
Serial.printf("[%u] fragment: %u\n", num, length);
} break;
case WStype_BIN: { case WStype_FRAGMENT_FIN: {
Serial.printf("[%u] get binary length: %u\n", num, length); Serial.printf("[%u] fragment finish: %u\n", num, length);
// hexdump(payload, length); } break;
// standWebSocket.sendBIN(num, payload, length);
} break;
case WStype_FRAGMENT_TEXT_START: { case WStype_PING: {
Serial.printf("[%u] fragment test start: %u\n", num, length); Serial.printf("[%u] ping: %u\n", num, length);
} break; } break;
case WStype_FRAGMENT_BIN_START: { case WStype_PONG: {
Serial.printf("[%u] fragment bin start: %u\n", num, length); Serial.printf("[%u] pong: %u\n", num, length);
} break; } break;
case WStype_FRAGMENT: { default: { Serial.printf("[%u] not recognized: %u\n", num, length); } break;
Serial.printf("[%u] fragment: %u\n", num, length); }
} break;
case WStype_FRAGMENT_FIN: {
Serial.printf("[%u] fragment finish: %u\n", num, length);
} break;
case WStype_PING: {
Serial.printf("[%u] ping: %u\n", num, length);
} break;
case WStype_PONG: {
Serial.printf("[%u] pong: %u\n", num, length);
} break;
default: {
Serial.printf("[%u] not recognized: %u\n", num, length);
} break;
}
} }
// публикация статус сообщений в ws (недостаток в том что делаем бродкаст всем клиентам поднятым в свелте!!!) // публикация статус сообщений в ws (недостаток в том что делаем бродкаст всем
// клиентам поднятым в свелте!!!)
void publishStatusWs(const String& topic, const String& data) { void publishStatusWs(const String& topic, const String& data) {
String path = mqttRootDevice + "/" + topic; String path = mqttRootDevice + "/" + topic;
String json = "{}"; String json = "{}";
jsonWriteStr(json, "status", data); jsonWriteStr(json, "status", data);
jsonWriteStr(json, "topic", path); jsonWriteStr(json, "topic", path);
sendStringToWs("status", json, -1); sendStringToWs("status", json, -1);
} }
// публикация дополнительных json сообщений в ws // публикация дополнительных json сообщений в ws
void publishJsonWs(const String& topic, String& json) { void publishJsonWs(const String& topic, String& json) {
String path = mqttRootDevice + "/" + topic; String path = mqttRootDevice + "/" + topic;
jsonWriteStr(json, "topic", path); jsonWriteStr(json, "topic", path);
// TO DO отправка полей в веб // TO DO отправка полей в веб
// sendStringToWs("status", json, -1); // sendStringToWs("status", json, -1);
} }
// данные которые мы отправляем в сокеты переодически // данные которые мы отправляем в сокеты переодически
void periodicWsSend() { void periodicWsSend() {
sendStringToWs("ssidli", ssidListHeapJson, -1); sendStringToWs("ssidli", ssidListHeapJson, -1);
sendStringToWs("errors", errorsHeapJson, -1); sendStringToWs("errors", errorsHeapJson, -1);
// отправляем переодичестки только в авто режиме // отправляем переодичестки только в авто режиме
if (jsonReadInt(settingsFlashJson, F("udps")) != 0) { if (jsonReadInt(settingsFlashJson, F("udps")) != 0) {
sendStringToWs("devlis", devListHeapJson, -1); sendStringToWs("devlis", devListHeapJson, -1);
} }
} }
#ifdef ESP32 #ifdef ESP32
void hexdump(const void* mem, uint32_t len, uint8_t cols = 16) { void hexdump(const void* mem, uint32_t len, uint8_t cols = 16) {
const uint8_t* src = (const uint8_t*)mem; const uint8_t* src = (const uint8_t*)mem;
Serial.printf("\n[HEXDUMP] Address: 0x%08X len: 0x%X (%d)", (ptrdiff_t)src, len, len); Serial.printf("\n[HEXDUMP] Address: 0x%08X len: 0x%X (%d)", (ptrdiff_t)src,
for (uint32_t i = 0; i < len; i++) { len, len);
if (i % cols == 0) { for (uint32_t i = 0; i < len; i++) {
Serial.printf("\n[0x%08X] 0x%08X: ", (ptrdiff_t)src, i); if (i % cols == 0) {
} Serial.printf("\n[0x%08X] 0x%08X: ", (ptrdiff_t)src, i);
Serial.printf("%02X ", *src);
src++;
} }
Serial.printf("\n"); Serial.printf("%02X ", *src);
src++;
}
Serial.printf("\n");
} }
#endif #endif
#endif #endif
void sendFileToWsByFrames(const String& filename, const String& header, const String& json, int client_id, size_t frameSize) { void sendFileToWsByFrames(const String& filename, const String& header,
if (header.length() != 6) { const String& json, int client_id, size_t frameSize) {
SerialPrint("E", "FS", F("wrong header size")); if (header.length() != 6) {
return; SerialPrint("E", "FS", F("wrong header size"));
return;
}
auto path = filepath(filename);
auto file = FileFS.open(path, "r");
if (!file) {
SerialPrint("E", "FS", F("reed file error"));
return;
}
size_t totalSize = file.size();
// Serial.println("Send file '" + String(filename) + "', file size: " +
// String(totalSize));
char buf[32];
sprintf(buf, "%04d", json.length() + 12);
String data = header + "|" + String(buf) + "|" + json;
size_t headerSize = data.length();
auto frameBuf = new uint8_t[frameSize];
size_t maxPayloadSize = frameSize - headerSize;
uint8_t* payloadBuf = nullptr;
int i = 0;
while (file.available()) {
if (i == 0) {
data.toCharArray((char*)frameBuf, frameSize);
payloadBuf = &frameBuf[headerSize];
} else {
maxPayloadSize = frameSize;
headerSize = 0;
payloadBuf = &frameBuf[0];
} }
auto path = filepath(filename); size_t payloadSize = file.read(payloadBuf, maxPayloadSize);
auto file = FileFS.open(path, "r"); if (payloadSize) {
if (!file) { size_t size = headerSize + payloadSize;
SerialPrint("E", "FS", F("reed file error"));
return; bool fin = false;
if (size == frameSize) {
fin = false;
} else {
fin = true;
}
bool continuation = false;
if (i == 0) {
continuation = false;
} else {
continuation = true;
}
// Serial.println(String(i) + ") " + "ws: " + String(client_id) + " fr sz:
// " + String(size) + " fin: " + String(fin) + " cnt: " +
// String(continuation));
if (client_id == -1) {
standWebSocket.broadcastBIN(frameBuf, size, fin, continuation);
} else {
standWebSocket.sendBIN(client_id, frameBuf, size, fin, continuation);
}
} }
i++;
size_t totalSize = file.size(); }
// Serial.println("Send file '" + String(filename) + "', file size: " + String(totalSize)); payloadBuf = &frameBuf[0];
delete[] payloadBuf;
char buf[32]; file.close();
sprintf(buf, "%04d", json.length() + 12);
String data = header + "|" + String(buf) + "|" + json;
size_t headerSize = data.length();
auto frameBuf = new uint8_t[frameSize];
size_t maxPayloadSize = frameSize - headerSize;
uint8_t* payloadBuf = nullptr;
int i = 0;
while (file.available()) {
if (i == 0) {
data.toCharArray((char*)frameBuf, frameSize);
payloadBuf = &frameBuf[headerSize];
} else {
maxPayloadSize = frameSize;
headerSize = 0;
payloadBuf = &frameBuf[0];
}
size_t payloadSize = file.read(payloadBuf, maxPayloadSize);
if (payloadSize) {
size_t size = headerSize + payloadSize;
bool fin = false;
if (size == frameSize) {
fin = false;
} else {
fin = true;
}
bool continuation = false;
if (i == 0) {
continuation = false;
} else {
continuation = true;
}
// Serial.println(String(i) + ") " + "ws: " + String(client_id) + " fr sz: " + String(size) + " fin: " + String(fin) + " cnt: " + String(continuation));
if (client_id == -1) {
standWebSocket.broadcastBIN(frameBuf, size, fin, continuation);
} else {
standWebSocket.sendBIN(client_id, frameBuf, size, fin, continuation);
}
}
i++;
}
payloadBuf = &frameBuf[0];
delete[] payloadBuf;
file.close();
} }
void sendStringToWs(const String& header, String& payload, int client_id) { void sendStringToWs(const String& header, String& payload, int client_id) {
if (header.length() != 6) { if (!(WiFi.softAPgetStationNum() || isNetworkActive())) {
SerialPrint("E", "FS", F("wrong header size")); return;
return; }
}
String msg = header + "|0012|" + payload; if (header.length() != 6) {
size_t totalSize = msg.length(); SerialPrint("E", "FS", F("wrong header size"));
return;
}
char dataArray[totalSize]; String msg = header + "|0012|" + payload;
msg.toCharArray(dataArray, totalSize + 1); size_t totalSize = msg.length();
if (client_id == -1) {
standWebSocket.broadcastBIN((uint8_t*)dataArray, totalSize); char dataArray[totalSize];
} else { msg.toCharArray(dataArray, totalSize + 1);
standWebSocket.sendBIN(client_id, (uint8_t*)dataArray, totalSize); if (client_id == -1) {
} standWebSocket.broadcastBIN((uint8_t*)dataArray, totalSize);
} else {
standWebSocket.sendBIN(client_id, (uint8_t*)dataArray, totalSize);
}
} }
void sendDeviceList(uint8_t num) { void sendDeviceList(uint8_t num) {
if (jsonReadInt(settingsFlashJson, F("udps")) != 0) { if (jsonReadInt(settingsFlashJson, F("udps")) != 0) {
// если включен автопоиск то отдаем список из оперативной памяти // если включен автопоиск то отдаем список из оперативной памяти
SerialPrint("i", "FS", "heap list"); SerialPrint("i", "FS", "heap list");
sendStringToWs("devlis", devListHeapJson, num); sendStringToWs("devlis", devListHeapJson, num);
} else { } else {
// если выключен автопоиск то отдаем список из флешь памяти // если выключен автопоиск то отдаем список из флешь памяти
sendFileToWsByFrames("/devlist.json", "devlis", "", num, WEB_SOCKETS_FRAME_SIZE); sendFileToWsByFrames("/devlist.json", "devlis", "", num,
SerialPrint("i", "FS", "flash list"); WEB_SOCKETS_FRAME_SIZE);
} SerialPrint("i", "FS", "flash list");
}
} }

View File

@@ -341,7 +341,8 @@ enum SysOp {
sysop_getRSSI, sysop_getRSSI,
sysop_getIP, sysop_getIP,
sysop_mqttPub, sysop_mqttPub,
sysop_getUptime sysop_getUptime,
sysop_mqttIsConnect
}; };
IoTValue sysExecute(SysOp command, std::vector<IoTValue> &param) { IoTValue sysExecute(SysOp command, std::vector<IoTValue> &param) {
@@ -442,6 +443,9 @@ IoTValue sysExecute(SysOp command, std::vector<IoTValue> &param) {
value.valS = jsonReadStr(errorsHeapJson, F("upt")); value.valS = jsonReadStr(errorsHeapJson, F("upt"));
value.isDecimal = false; value.isDecimal = false;
break; break;
case sysop_mqttIsConnect:
value.valD = mqttIsConnect();
break;
} }
return value; return value;
@@ -496,6 +500,8 @@ class SysCallExprAST : public ExprAST {
operation = sysop_getTime; operation = sysop_getTime;
else if (Callee == F("getUptime")) else if (Callee == F("getUptime"))
operation = sysop_getUptime; operation = sysop_getUptime;
else if (Callee == F("mqttIsConnect"))
operation = sysop_mqttIsConnect;
else else
operation = sysop_notfound; operation = sysop_notfound;
} }

View File

@@ -35,6 +35,7 @@ void* getAPI_Pcf8574(String subtype, String params);
void* getAPI_Pwm8266(String subtype, String params); void* getAPI_Pwm8266(String subtype, String params);
void* getAPI_TelegramLT(String subtype, String params); void* getAPI_TelegramLT(String subtype, String params);
void* getAPI_Lcd2004(String subtype, String params); void* getAPI_Lcd2004(String subtype, String params);
void* getAPI_TM16XX(String subtype, String params);
void* getAPI(String subtype, String params) { void* getAPI(String subtype, String params) {
void* tmpAPI; void* tmpAPI;
@@ -73,5 +74,6 @@ if ((tmpAPI = getAPI_Pcf8574(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_Pwm8266(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_Pwm8266(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_TelegramLT(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_TelegramLT(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_Lcd2004(subtype, params)) != nullptr) return tmpAPI; if ((tmpAPI = getAPI_Lcd2004(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_TM16XX(subtype, params)) != nullptr) return tmpAPI;
return nullptr; return nullptr;
} }

View File

@@ -1,23 +1,22 @@
{ {
"menuSection": "Экраны", "menuSection": "screens",
"configItem": [
"configItem": [{ {
"global": 0, "global": 0,
"name": "LCD Dwin экран", "name": "LCD Dwin экран",
"type": "Reading", "type": "Reading",
"subtype": "DwinI", "subtype": "DwinI",
"id": "dwin", "id": "dwin",
"widget": "", "widget": "",
"page": "", "page": "",
"descr": "", "descr": "",
"int": 15,
"int": 15, "TX": 17,
"TX": 17, "RX": 16,
"RX": 16, "line": 2,
"line": 2, "speed": 115200
"speed": 115200 }
}], ],
"about": { "about": {
"authorName": "Ilya Belyakov", "authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe", "authorContact": "https://t.me/Biveraxe",
@@ -33,6 +32,7 @@
"propInfo": { "propInfo": {
"int": "" "int": ""
}, },
"title": "Экраны от компании Dwin",
"funcInfo": [ "funcInfo": [
{ {
"name": "rrrr", "name": "rrrr",
@@ -41,21 +41,13 @@
} }
] ]
}, },
"defActive": false, "defActive": false,
"usedLibs": { "usedLibs": {
"esp32_4mb": [ "esp32_4mb": [],
], "esp8266_4mb": [],
"esp8266_4mb": [ "esp8266_1mb": [],
], "esp8266_1mb_ota": [],
"esp8266_1mb": [ "esp8285_1mb": [],
], "esp8285_1mb_ota": []
"esp8266_1mb_ota": [
],
"esp8285_1mb": [
],
"esp8285_1mb_ota": [
]
} }
} }

View File

@@ -1,40 +1,38 @@
{ {
"menuSection": "Экраны", "menuSection": "screens",
"configItem": [
"configItem": [{ {
"global": 0, "global": 0,
"name": "LCD экран 2004", "name": "LCD экран 2004",
"type": "Reading", "type": "Reading",
"subtype": "Lcd2004", "subtype": "Lcd2004",
"id": "Lcd", "id": "Lcd",
"widget": "inputTxt", "widget": "inputTxt",
"page": "Экраны", "page": "screens",
"descr": "LCD Экран", "descr": "LCD Экран",
"addr": "0x27",
"addr": "0x27", "size": "20,4",
"size": "20,4", "coord": "0,0",
"coord": "0,0", "id2show": "",
"id2show": "", "prefix": "",
"prefix": "", "postfix": ""
"postfix": "" },
}, {
{ "name": "LCD экран 1602",
"name": "LCD экран 1602", "type": "Reading",
"type": "Reading", "subtype": "Lcd2004",
"subtype": "Lcd2004", "id": "Lcd",
"id": "Lcd", "widget": "inputTxt",
"widget": "inputTxt", "page": "screens",
"page": "Экраны", "descr": "LCD Экран",
"descr": "LCD Экран", "addr": "0x27",
"size": "16,2",
"addr": "0x27", "coord": "0,0",
"size": "16,2", "id2show": "",
"coord": "0,0", "prefix": "",
"id2show": "", "postfix": ""
"prefix": "", }
"postfix": "" ],
}],
"about": { "about": {
"authorName": "Ilya Belyakov", "authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe", "authorContact": "https://t.me/Biveraxe",
@@ -55,6 +53,7 @@
"prefix": "Символы до значения.", "prefix": "Символы до значения.",
"postfix": "Символы после значения." "postfix": "Символы после значения."
}, },
"title": "Символьный дисплей Lcd2004",
"funcInfo": [ "funcInfo": [
{ {
"name": "noBacklight", "name": "noBacklight",
@@ -84,33 +83,41 @@
{ {
"name": "x", "name": "x",
"descr": "Устанавливает первую координату", "descr": "Устанавливает первую координату",
"params": ["Номер строки первого символа"] "params": [
"Номер строки первого символа"
]
}, },
{ {
"name": "y", "name": "y",
"descr": "Устанавливает вторую координату", "descr": "Устанавливает вторую координату",
"params": ["Номер столбца первого символа"] "params": [
"Номер столбца первого символа"
]
}, },
{ {
"name": "prefix", "name": "prefix",
"descr": "Задает приставку слева от значения", "descr": "Задает приставку слева от значения",
"params": ["Строка"] "params": [
"Строка"
]
}, },
{ {
"name": "postfix", "name": "postfix",
"descr": "Задает приставку справа от значения", "descr": "Задает приставку справа от значения",
"params": ["Строка"] "params": [
"Строка"
]
}, },
{ {
"name": "id2show", "name": "id2show",
"descr": "Задает ИД элемента, значение которого хотим отображать на экране", "descr": "Задает ИД элемента, значение которого хотим отображать на экране",
"params": ["Имя элемента конфигурации"] "params": [
"Имя элемента конфигурации"
]
} }
] ]
}, },
"defActive": true, "defActive": true,
"usedLibs": { "usedLibs": {
"esp32_4mb": [ "esp32_4mb": [
"https://github.com/robotclass/RobotClass_LiquidCrystal_I2C", "https://github.com/robotclass/RobotClass_LiquidCrystal_I2C",

View File

@@ -1,6 +1,5 @@
{ {
"menuSection": "Экраны", "menuSection": "screens",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
@@ -17,7 +16,6 @@
"NEXT_RX": 17 "NEXT_RX": 17
} }
], ],
"about": { "about": {
"authorName": "AVAKS", "authorName": "AVAKS",
"authorContact": "https://t.me/@avaks_dev", "authorContact": "https://t.me/@avaks_dev",
@@ -36,15 +34,25 @@
"url": "файл прошивки" "url": "файл прошивки"
} }
}, },
"defActive": false, "defActive": false,
"usedLibs": { "usedLibs": {
"esp32_4mb": ["https://github.com/avaksru/ESPNexUpload.git"], "esp32_4mb": [
"esp8266_4mb": ["https://github.com/avaksru/ESPNexUpload.git"], "https://github.com/avaksru/ESPNexUpload.git"
"esp8266_1mb": ["https://github.com/avaksru/ESPNexUpload.git"], ],
"esp8266_1mb_ota": ["https://github.com/avaksru/ESPNexUpload.git"], "esp8266_4mb": [
"esp8285_1mb": ["https://github.com/avaksru/ESPNexUpload.git"], "https://github.com/avaksru/ESPNexUpload.git"
"esp8285_1mb_ota": ["https://github.com/avaksru/ESPNexUpload.git"] ],
"esp8266_1mb": [
"https://github.com/avaksru/ESPNexUpload.git"
],
"esp8266_1mb_ota": [
"https://github.com/avaksru/ESPNexUpload.git"
],
"esp8285_1mb": [
"https://github.com/avaksru/ESPNexUpload.git"
],
"esp8285_1mb_ota": [
"https://github.com/avaksru/ESPNexUpload.git"
]
} }
} }

View File

@@ -0,0 +1,174 @@
#include "Global.h"
#include "classes/IoTItem.h"
#include <GyverOLED.h>
GyverOLED<SSD1306_128x64, OLED_BUFFER> oled;
// GyverOLED<SSD1306_128x32, OLED_BUFFER> oled;
// GyverOLED<SSD1306_128x32, OLED_NO_BUFFER> oled;
// GyverOLED<SSD1306_128x64, OLED_NO_BUFFER> oled;
// GyverOLED<SSD1306_128x64, OLED_BUFFER, OLED_SPI, 8, 7, 6> oled;
// GyverOLED<SSH1106_128x64> oled;
class Oled128 : public IoTItem {
private:
unsigned int _x;
unsigned int _y;
unsigned int _k;
int _shrift;
String _id2show;
String _descr;
String _descr1;
int _prevStrSize;
bool _isShow = true; // экран показывает
public:
Oled128(String parameters) : IoTItem(parameters) {
String addr, size, xy, k;
_prevStrSize = 0;
jsonRead(parameters, "addr", addr);
if (addr == "") {
// scanI2C();
return;
}
jsonRead(parameters, "coord", xy);
_x = selectFromMarkerToMarker(xy, ",", 0).toInt();
_y = selectFromMarkerToMarker(xy, ",", 1).toInt();
jsonRead(parameters, "descr", _descr);
jsonRead(parameters, "id2show", _id2show);
jsonRead(parameters, "descr1", _descr1);
// jsonRead(parameters, "scale", _k);
jsonRead(parameters, "shrift", _shrift);
// Wire.begin(2,0); // Инициализация шины I2C для модуля E01
oled.init(); // инициализация экрана
}
void doByInterval() {
printBlankStr(_prevStrSize);
String tmpStr = "";
// if (_descr != "none") tmpStr = _descr + " " + getItemValue(_id2show);
if (_descr != "none")
tmpStr = _descr + " " + getItemValue(_id2show) + " " + _descr1;
else
tmpStr = getItemValue(_id2show);
// oled.setScale(2);
oled.setScale(_shrift);
oled.setCursorXY(_x, _y);
oled.print(tmpStr);
oled.update();
_prevStrSize = tmpStr.length();
}
IoTValue execute(String command, std::vector<IoTValue> &param) { // будет возможным использовать, когда сценарии запустятся
if (command == "scroll") {
String tmpStr = "";
oled.clear();
uint32_t tmr = millis();
oled.autoPrintln(false);
int val = 128;
for (;;) {
// oled.clear(); // ЗАКОММЕНТИРУЙ, ЕСЛИ ВКЛЮЧЕН БУФЕР
// oled.setScale(2);
oled.setScale(_shrift);
oled.setCursor(val, _y);
oled.print(tmpStr);
oled.update();
val--;
if (millis() - tmr > 5000)
; // return;
_isShow = true;
}
}
else if (command == "stopscroll") {
_isShow = true;
// display->backlight();
// else if (command == "noDisplay") {
// display->noDisplay();
// _isShow = false;
} else if (command == "display") {
// display.display();
_isShow = true;
} else if (command == "toggle") {
if (_isShow) {
// display->noDisplay();
_isShow = false;
} else {
// display.display();
_isShow = true;
}
} else if (command == "x") {
if (param.size()) {
_x = param[0].valD;
}
} else if (command == "y") {
if (param.size()) {
_y = param[0].valD;
}
} else if (command == "descr") {
if (param.size()) {
_descr = param[0].valS;
}
} else if (command == "descr1") {
if (param.size()) {
_descr1 = param[0].valS;
}
} else if (command == "id2show") {
if (param.size()) {
_id2show = param[0].valS;
}
}
doByInterval();
return {};
}
// печать пустой строки нужной длинны для затирания предыдущего значения на экране
void printBlankStr(int strSize) {
String tmpStr = "";
for (int i = 0; i < strSize; i++) tmpStr += " ";
// oled.setScale(2);
oled.setScale(_shrift);
oled.setCursorXY(_x, _y);
oled.print(tmpStr);
}
~Oled128(){};
};
void *getAPI_Oled128(String subtype, String param) {
if (subtype == F("Oled128")) {
return new Oled128(param);
} else {
return nullptr;
}
}

View File

@@ -0,0 +1,86 @@
{
"menuSection": "screens",
"configItem": [
{
"name": "OLED экран 128*64",
"type": "Reading",
"subtype": "Oled128",
"id": "oled",
"widget": "",
"page": "",
"descr": "T",
"descr1": "C",
"int": 1,
"addr": "0x3C",
"coord": "0,10",
"id2show": "id датчика",
"shrift": "2"
}
],
"about": {
"authorName": "Serghei Crasnicov",
"authorContact": "https://t.me/Serghei63",
"authorGit": "https://github.com/Serghei63",
"specialThanks": "Ilya Belyakov @Biveraxe",
"moduleName": "Oled128",
"moduleVersion": "1.0",
"moduleDesc": "Позволяет выводить на матричные Oled экраны по указанным позициям значения других элементов конфигурации.",
"usedRam": 15,
"propInfo": {
"int": "Период времени в секундах обновления информации на экране по конкретному элементу.",
"addr": "Адрес устройства на шине, обычно 0x3c.",
"coord": "Координата позиции для вывода данных элемента конфигурации.",
"id2show": "id элемента конфигурации.",
"shrift": "Шрифт текста от 1 до 4 "
},
"funcInfo": [
{
"name": "x",
"descr": "Устанавливает первую координату",
"params": [
"Номер строки первого символа"
]
},
{
"name": "y",
"descr": "Устанавливает вторую координату",
"params": [
"Номер столбца первого символа"
]
},
{
"name": "descr",
"descr": "Задает приставку слева от значения, если none значит пусто",
"params": [
"Строка"
]
},
{
"name": "descr1",
"descr": "Задает приставку справа от значения. Если descr none , то не выводится",
"params": [
"Строка"
]
},
{
"name": "id2show",
"descr": "Задает ИД элемента, значение которого хотим отображать на экране",
"params": [
"Имя элемента конфигурации"
]
}
]
},
"defActive": false,
"usedLibs": {
"esp32_4mb": [
"gyverlibs/GyverOLED @ 1.4"
],
"esp32_16mb": [
"gyverlibs/GyverOLED @ 1.4"
],
"esp8266_4mb": [
"gyverlibs/GyverOLED @ 1.4"
]
}
}

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Экраны", "menuSection": "screens",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
@@ -32,6 +32,7 @@
"id2show": "id элемента конфигурации.", "id2show": "id элемента конфигурации.",
"baud": "скорость обмена, бит/с" "baud": "скорость обмена, бит/с"
}, },
"title": "СМИ2-М трёхцветный Modbus-индикатор",
"funcInfo": [ "funcInfo": [
{ {
"name": "descr", "name": "descr",

View File

@@ -1,27 +1,26 @@
{ {
"menuSection": "Экраны", "menuSection": "screens",
"configItem": [
"configItem": [{ {
"global": 0, "global": 0,
"name": "7 сегментный дисплей TM16XX", "name": "7 сегментный дисплей TM16XX",
"type": "Writing", "type": "Writing",
"subtype": "TM16XX", "subtype": "TM16XX",
"id": "tm", "id": "tm",
"widget": "inputTxt", "widget": "inputTxt",
"page": "Экраны", "page": "screens",
"descr": "Экран", "descr": "Экран",
"round": 0, "round": 0,
"chip": 1637,
"chip": 1637, "numDigits": 4,
"numDigits": 4, "DIO": "13",
"DIO": "13", "CLK": "14",
"CLK": "14", "STB": "12",
"STB": "12", "intensity": "5",
"intensity": "5", "on": "1",
"on": "1", "id2show": ""
"id2show": "" }
}], ],
"about": { "about": {
"authorName": "Ilya Belyakov", "authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe", "authorContact": "https://t.me/Biveraxe",
@@ -74,60 +73,74 @@
{ {
"name": "x", "name": "x",
"descr": "Устанавливает первую координату", "descr": "Устанавливает первую координату",
"params": ["Номер строки первого символа"] "params": [
"Номер строки первого символа"
]
}, },
{ {
"name": "y", "name": "y",
"descr": "Устанавливает вторую координату", "descr": "Устанавливает вторую координату",
"params": ["Номер столбца первого символа"] "params": [
"Номер столбца первого символа"
]
}, },
{ {
"name": "descr", "name": "descr",
"descr": "Задает приставку слева от значения", "descr": "Задает приставку слева от значения",
"params": ["Строка"] "params": [
"Строка"
]
}, },
{ {
"name": "id2show", "name": "id2show",
"descr": "Задает ИД элемента, значение которого хотим отображать на экране", "descr": "Задает ИД элемента, значение которого хотим отображать на экране",
"params": ["Имя элемента конфигурации"] "params": [
"Имя элемента конфигурации"
]
} }
] ]
}, },
"defActive": true, "defActive": true,
"usedLibs": { "usedLibs": {
"esp32_4mb": [ "esp32_4mb": [
"https://github.com/maxint-rd/TM16xx", "https://github.com/maxint-rd/TM16xx",
"adafruit/Adafruit GFX Library @ ^1.11.5" "adafruit/Adafruit GFX Library @ ^1.11.5",
"adafruit/Adafruit BusIO @ ^1.13.2"
], ],
"esp8266_4mb": [ "esp8266_4mb": [
"https://github.com/maxint-rd/TM16xx", "https://github.com/maxint-rd/TM16xx",
"adafruit/Adafruit GFX Library @ ^1.11.5" "adafruit/Adafruit GFX Library @ ^1.11.5",
"adafruit/Adafruit BusIO @ ^1.13.2"
], ],
"esp8266_1mb": [ "esp8266_1mb": [
"https://github.com/maxint-rd/TM16xx", "https://github.com/maxint-rd/TM16xx",
"adafruit/Adafruit GFX Library @ ^1.11.5" "adafruit/Adafruit GFX Library @ ^1.11.5",
"adafruit/Adafruit BusIO @ ^1.13.2"
], ],
"esp8266_1mb_ota": [ "esp8266_1mb_ota": [
"https://github.com/maxint-rd/TM16xx", "https://github.com/maxint-rd/TM16xx",
"adafruit/Adafruit GFX Library @ ^1.11.5" "adafruit/Adafruit GFX Library @ ^1.11.5",
"adafruit/Adafruit BusIO @ ^1.13.2"
], ],
"esp8285_1mb": [ "esp8285_1mb": [
"https://github.com/maxint-rd/TM16xx", "https://github.com/maxint-rd/TM16xx",
"adafruit/Adafruit GFX Library @ ^1.11.5" "adafruit/Adafruit GFX Library @ ^1.11.5",
"adafruit/Adafruit BusIO @ ^1.13.2"
], ],
"esp8285_1mb_ota": [ "esp8285_1mb_ota": [
"https://github.com/maxint-rd/TM16xx", "https://github.com/maxint-rd/TM16xx",
"adafruit/Adafruit GFX Library @ ^1.11.5" "adafruit/Adafruit GFX Library @ ^1.11.5",
"adafruit/Adafruit BusIO @ ^1.13.2"
], ],
"esp8266_2mb": [ "esp8266_2mb": [
"https://github.com/maxint-rd/TM16xx", "https://github.com/maxint-rd/TM16xx",
"adafruit/Adafruit GFX Library @ ^1.11.5" "adafruit/Adafruit GFX Library @ ^1.11.5",
"adafruit/Adafruit BusIO @ ^1.13.2"
], ],
"esp8266_2mb_ota": [ "esp8266_2mb_ota": [
"https://github.com/maxint-rd/TM16xx", "https://github.com/maxint-rd/TM16xx",
"adafruit/Adafruit GFX Library @ ^1.11.5" "adafruit/Adafruit GFX Library @ ^1.11.5",
"adafruit/Adafruit BusIO @ ^1.13.2"
] ]
} }
} }

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Экраны", "menuSection": "screens",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
@@ -40,6 +40,7 @@
"max": "Максимальный порог индикатора на который реагировать.", "max": "Максимальный порог индикатора на который реагировать.",
"idshow": "id элемента конфигурации который нужно повесить индикацию." "idshow": "id элемента конфигурации который нужно повесить индикацию."
}, },
"title": "Адресная светодиодная матрица",
"funcInfo": [ "funcInfo": [
{ {
"name": "noShow", "name": "noShow",

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Исполнительные устройства", "menuSection": "executive_devices",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
@@ -46,7 +46,10 @@
"defActive": true, "defActive": true,
"usedLibs": { "usedLibs": {
"esp32_4mb": [], "esp32_4mb": [],
"esp32_16mb": [],
"esp32s2_4mb": [],
"esp8266_4mb": [], "esp8266_4mb": [],
"esp8266_16mb": [],
"esp8266_1mb": [], "esp8266_1mb": [],
"esp8266_1mb_ota": [], "esp8266_1mb_ota": [],
"esp8285_1mb": [], "esp8285_1mb": [],

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Исполнительные устройства", "menuSection": "executive_devices",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
@@ -45,7 +45,10 @@
"defActive": true, "defActive": true,
"usedLibs": { "usedLibs": {
"esp32_4mb": [], "esp32_4mb": [],
"esp32_16mb": [],
"esp32s2_4mb": [],
"esp8266_4mb": [], "esp8266_4mb": [],
"esp8266_16mb": [],
"esp8266_1mb": [], "esp8266_1mb": [],
"esp8266_1mb_ota": [], "esp8266_1mb_ota": [],
"esp8285_1mb": [], "esp8285_1mb": [],

View File

@@ -1,29 +1,29 @@
{ {
"menuSection": "Исполнительные устройства", "menuSection": "executive_devices",
"configItem": [
"configItem": [{ {
"global": 0, "global": 0,
"name": "Пассивный звуковой извещатель", "name": "Пассивный звуковой извещатель",
"type": "Writing", "type": "Writing",
"subtype": "Buzzer", "subtype": "Buzzer",
"id": "buzzer", "id": "buzzer",
"widget": "toggle", "widget": "toggle",
"page": "Кнопки", "page": "Кнопки",
"descr": "Buzzer", "descr": "Buzzer",
"int": 4000, "int": 4000,
"pin": 14, "pin": 14,
"freq": 2000, "freq": 2000,
"duration": 1000, "duration": 1000,
"beatLevel": 4, "beatLevel": 4,
"tempo": 120, "tempo": 120,
"tempoCorrection": 1, "tempoCorrection": 1,
"pauseBetween": 0, "pauseBetween": 0,
"transpose": 0, "transpose": 0,
"cycle": 0, "cycle": 0,
"indication": 1, "indication": 1,
"val": 0 "val": 0
}], }
],
"about": { "about": {
"authorName": "Alex K", "authorName": "Alex K",
"authorContact": "https://t.me/cmche", "authorContact": "https://t.me/cmche",
@@ -43,11 +43,11 @@
"int": "Количество миллисекунд между повторами одиночного сигнала", "int": "Количество миллисекунд между повторами одиночного сигнала",
"pin": "Управляемый пин", "pin": "Управляемый пин",
"freq": "Частота сигнала, Hz", "freq": "Частота сигнала, Hz",
"duration": "Длительность сигнала, ms", "duration": "Длительность сигнала, ms",
"beatLevel": "Долей в такте", "beatLevel": "Долей в такте",
"tempo": "Оригинальный темп мелодии, bpm", "tempo": "Оригинальный темп мелодии, bpm",
"tempoCorrection": "Коррекция темпа мелодии", "tempoCorrection": "Коррекция темпа мелодии",
"pauseBetween": "Дополнительная пауза между нот, в долях от длительности ноты", "pauseBetween": "Дополнительная пауза между нот, в долях от длительности ноты",
"transpose": "Транспонирование на количество полутонов. +/-12 - для повышения/понижения на октаву", "transpose": "Транспонирование на количество полутонов. +/-12 - для повышения/понижения на октаву",
"cycle": "Повтор мелодии/серии сигналов", "cycle": "Повтор мелодии/серии сигналов",
"indication": "Индикация в виджет, что идет сигнал, играет мелодия", "indication": "Индикация в виджет, что идет сигнал, играет мелодия",
@@ -57,17 +57,30 @@
{ {
"name": "tone", "name": "tone",
"descr": "Проигрывание одиночного сигнала (без индикации)", "descr": "Проигрывание одиночного сигнала (без индикации)",
"params": ["Частота", "Длительность (ms)"] "params": [
"Частота",
"Длительность (ms)"
]
}, },
{ {
"name": "tones", "name": "tones",
"descr": "Проигрывание серии сигналов, до 128", "descr": "Проигрывание серии сигналов, до 128",
"params": ["Частота 1-го сигнала", "Длительность 1-го сигнала (ms)","Частота 2-го сигала", "Длительность 2-го сигнала", "....итд"] "params": [
"Частота 1-го сигнала",
"Длительность 1-го сигнала (ms)",
"Частота 2-го сигала",
"Длительность 2-го сигнала",
"....итд"
]
}, },
{ {
"name": "melody", "name": "melody",
"descr": "Проигрывание мелодии, до 256 нот. Кодировка 'YYX.ZZZ'. Научная нотация: YY - обозначение ноты (C,CS,D,DS,E,F,FS,G,GS,A,AS,B), X - номер октавы (0-9), ZZZ - длительность в тысячных долях такта (0-999). Обязательно в двойных кавычках. 'AS4.50' - Ля# 4-й октавы, 1/2 такта. На Github лежит Excel файл для перекодировки.", "descr": "Проигрывание мелодии, до 256 нот. Кодировка 'YYX.ZZZ'. Научная нотация: YY - обозначение ноты (C,CS,D,DS,E,F,FS,G,GS,A,AS,B), X - номер октавы (0-9), ZZZ - длительность в тысячных долях такта (0-999). Обязательно в двойных кавычках. 'AS4.50' - Ля# 4-й октавы, 1/2 такта. На Github лежит Excel файл для перекодировки.",
"params": ["Код 1-ой ноты","Код 2-й ноты"," и тд"] "params": [
"Код 1-ой ноты",
"Код 2-й ноты",
" и тд"
]
}, },
{ {
"name": "notone", "name": "notone",
@@ -76,15 +89,19 @@
}, },
{ {
"name": "melodySetting", "name": "melodySetting",
"descr": "Перенастройка параметров мелодии: Долей в такте - (обычно 4), Оригинальный темп -(40-208 bpm), Коррекция темпа - в k раз быстрее/медленнее, Пауза между нот (стакато) - доля от длительности, Коррекция тональности (транспонирование) - в k раз выше/ниже, Повтор 1/0. Чтобы не изменялось значение вбить любой текст в ковычках ", "descr": "Перенастройка параметров мелодии: Долей в такте - (обычно 4), Оригинальный темп -(40-208 bpm), Коррекция темпа - в k раз быстрее/медленнее, Пауза между нот (стакато) - доля от длительности, Коррекция тональности (транспонирование) - в k раз выше/ниже, Повтор 1/0. Чтобы не изменялось значение вбить любой текст в ковычках ",
"params": ["Долей в такте", "Оригинальный темп", "Коррекция темпа", "Пауза между нот", "Коррекция тональности", "Повтор мелодии/серии сигналов"] "params": [
"Долей в такте",
"Оригинальный темп",
"Коррекция темпа",
"Пауза между нот",
"Коррекция тональности",
"Повтор мелодии/серии сигналов"
]
} }
] ]
}, },
"defActive": true, "defActive": true,
"usedLibs": { "usedLibs": {
"esp32_4mb": [], "esp32_4mb": [],
"esp8266_4mb": [], "esp8266_4mb": [],
@@ -94,5 +111,5 @@
"esp8285_1mb_ota": [], "esp8285_1mb_ota": [],
"esp8266_2mb": [], "esp8266_2mb": [],
"esp8266_2mb_ota": [] "esp8266_2mb_ota": []
} }
} }

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Исполнительные устройства", "menuSection": "executive_devices",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
@@ -12,8 +12,7 @@
"descr": "Громкость", "descr": "Громкость",
"needSave": 0, "needSave": 0,
"val": "0", "val": "0",
"round" : 0, "round": 0,
"step": 1, "step": 1,
"stepOnPress": 5, "stepOnPress": 5,
"pins": "4,5,2" "pins": "4,5,2"
@@ -37,7 +36,7 @@
"moduleDesc": "модуль для работы с Энкодером. Кнопочный вариант совместим с модулями Multitouch и ButtonIn", "moduleDesc": "модуль для работы с Энкодером. Кнопочный вариант совместим с модулями Multitouch и ButtonIn",
"retInfo": "Значение счетчика", "retInfo": "Значение счетчика",
"propInfo": { "propInfo": {
"step" : "Размер шага Энкодера, может принимать значение 0.0001 или 1000", "step": "Размер шага Энкодера, может принимать значение 0.0001 или 1000",
"stepOnPress": "Размер шага Энкодера при нажатой кнопке, 0 - отключает учет", "stepOnPress": "Размер шага Энкодера при нажатой кнопке, 0 - отключает учет",
"pins": "Подключеные пины (CLK, DT, SW)" "pins": "Подключеные пины (CLK, DT, SW)"
} }
@@ -50,6 +49,9 @@
"esp8266_4mb": [ "esp8266_4mb": [
"gyverlibs/EncButton @ ^2.0" "gyverlibs/EncButton @ ^2.0"
], ],
"esp8266_16mb": [
"gyverlibs/EncButton @ ^2.0"
],
"esp8266_1mb": [ "esp8266_1mb": [
"gyverlibs/EncButton @ ^2.0" "gyverlibs/EncButton @ ^2.0"
], ],

View File

@@ -1,22 +1,21 @@
{ {
"menuSection": "Исполнительные устройства", "menuSection": "executive_devices",
"configItem": [
"configItem": [{ {
"global": 0, "global": 0,
"name": "Camera OV2640 (ESPcam)", "name": "Camera OV2640 (ESPcam)",
"type": "Reading", "type": "Reading",
"subtype": "EspCam", "subtype": "EspCam",
"id": "EspCam", "id": "EspCam",
"widget": "", "widget": "",
"page": "", "page": "",
"descr": "", "descr": "",
"int": 60,
"int": 60, "useLed": 0,
"useLed": 0, "ticker": 0,
"ticker": 0, "webTicker": 0
"webTicker": 0 }
}], ],
"about": { "about": {
"authorName": "Ilya Belyakov", "authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe", "authorContact": "https://t.me/Biveraxe",
@@ -45,7 +44,9 @@
{ {
"name": "ledOn", "name": "ledOn",
"descr": "Включить подсветку", "descr": "Включить подсветку",
"params": ["Яркость 0-255"] "params": [
"Яркость 0-255"
]
}, },
{ {
"name": "ledOff", "name": "ledOff",
@@ -54,9 +55,7 @@
} }
] ]
}, },
"defActive": false, "defActive": false,
"usedLibs": { "usedLibs": {
"esp32_4mb": [ "esp32_4mb": [
"espressif/esp32-camera @ ^2.0.0" "espressif/esp32-camera @ ^2.0.0"

View File

@@ -1,46 +1,43 @@
{ {
"menuSection": "Исполнительные устройства", "menuSection": "executive_devices",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
"name": "FTP сервер", "name": "FTP сервер",
"type": "Reading", "type": "Reading",
"subtype": "ftp", "subtype": "ftp",
"id": "ftp", "id": "ftp",
"widget": "nil", "widget": "nil",
"page": "", "page": "",
"descr": "FTP сервер", "descr": "FTP сервер",
"login": "admin", "login": "admin",
"pass": "admin" "pass": "admin"
}
],
} "about": {
"authorName": "Bubnov Mikhail",
"authorContact": "https://t.me/Mit4bmw",
], "authorGit": "https://github.com/Mit4el",
"about": { "specialThanks": "",
"authorName": "Bubnov Mikhail", "moduleName": "FTPModule",
"authorContact": "https://t.me/Mit4bmw", "moduleVersion": "0.1",
"authorGit": "https://github.com/Mit4el", "usedRam": {
"specialThanks": "", "esp32_4mb": 15,
"moduleName": "FTPModule", "esp8266_4mb": 15
"moduleVersion": "0.1", },
"usedRam": { "title": "FTP-сервер",
"esp32_4mb": 15, "moduleDesc": "Запускает FTP-сервер на плате esp",
"esp8266_4mb": 15 "propInfo": {
}, "login": "Логин FTP сервера",
"title": "FTP-сервер", "pass": "Пароль FTP сервера"
"moduleDesc": "Запускает FTP-сервер на плате esp", }
"propInfo": { },
"login": "Логин FTP сервера", "defActive": false,
"pass": "Пароль FTP сервера" "usedLibs": {
} "esp32_4mb": [],
}, "esp32_16mb": [],
"defActive": false, "esp32s2_4mb": [],
"usedLibs": { "esp8266_4mb": [],
"esp32_4mb": [], "esp8266_16mb": []
"esp32s2_4mb": [], }
"esp8266_4mb": [] }
}
}

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Исполнительные устройства", "menuSection": "executive_devices",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
@@ -41,7 +41,8 @@
"name": "post", "name": "post",
"descr": "Отправить http запрос методом POST.", "descr": "Отправить http запрос методом POST.",
"params": [ "params": [
"URL","message" "URL",
"message"
] ]
} }
] ]

View File

@@ -1,22 +1,21 @@
{ {
"menuSection": "Исполнительные устройства", "menuSection": "executive_devices",
"configItem": [
"configItem": [{ {
"global": 0, "global": 0,
"name": "Сервопривод", "name": "Сервопривод",
"type": "Writing", "type": "Writing",
"subtype": "IoTServo", "subtype": "IoTServo",
"id": "servo", "id": "servo",
"widget": "range", "widget": "rangeServo",
"page": "servo", "page": "servo",
"descr": "угол", "descr": "угол",
"int": 1,
"int": 1, "pin": 12,
"pin": 12, "apin": -1,
"apin": -1, "amap": "0, 4096, 0, 180"
"amap": "0, 4096, 0, 180" }
}], ],
"about": { "about": {
"authorName": "Ilya Belyakov", "authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe", "authorContact": "https://t.me/Biveraxe",
@@ -41,16 +40,16 @@
{ {
"name": "rotate", "name": "rotate",
"descr": "Повернуть привод на значение", "descr": "Повернуть привод на значение",
"params": ["Числовое значение"] "params": [
"Числовое значение"
]
} }
] ]
}, },
"defActive": true, "defActive": true,
"usedLibs": { "usedLibs": {
"esp32_4mb": [ "esp32_4mb": [
"https://github.com/RoboticsBrno/ServoESP32" "https://github.com/RoboticsBrno/ServoESP32#v1.0.3"
], ],
"esp8266_4mb": [] "esp8266_4mb": []
} }

View File

@@ -1,21 +1,20 @@
{ {
"menuSection": "Исполнительные устройства", "menuSection": "executive_devices",
"configItem": [
"configItem": [{ {
"global": 0, "global": 0,
"name": "Расширитель портов Mcp23008", "name": "Расширитель портов Mcp23008",
"type": "Reading", "type": "Reading",
"subtype": "Mcp23008", "subtype": "Mcp23008",
"id": "Mcp", "id": "Mcp",
"widget": "", "widget": "",
"page": "", "page": "",
"descr": "", "descr": "",
"int": "0",
"int": "0", "addr": "0x20",
"addr": "0x20", "index": 1
"index": 1 }
}], ],
"about": { "about": {
"authorName": "Ilya Belyakov", "authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe", "authorContact": "https://t.me/Biveraxe",
@@ -35,9 +34,7 @@
"index": "Значения от 1 до 4, где при выборе 1 будет нумерация pin 100-115, при выборе 2 200-215 и т.д." "index": "Значения от 1 до 4, где при выборе 1 будет нумерация pin 100-115, при выборе 2 200-215 и т.д."
} }
}, },
"defActive": false, "defActive": false,
"usedLibs": { "usedLibs": {
"esp32_4mb": [ "esp32_4mb": [
"adafruit/Adafruit Mcp23017 Arduino Library@^2.1.0", "adafruit/Adafruit Mcp23017 Arduino Library@^2.1.0",

View File

@@ -1,21 +1,20 @@
{ {
"menuSection": "Исполнительные устройства", "menuSection": "executive_devices",
"configItem": [
"configItem": [{ {
"global": 0, "global": 0,
"name": "Расширитель портов Mcp23017", "name": "Расширитель портов Mcp23017",
"type": "Reading", "type": "Reading",
"subtype": "Mcp23017", "subtype": "Mcp23017",
"id": "Mcp", "id": "Mcp",
"widget": "", "widget": "",
"page": "", "page": "",
"descr": "", "descr": "",
"int": "0",
"int": "0", "addr": "0x20",
"addr": "0x20", "index": 1
"index": 1 }
}], ],
"about": { "about": {
"authorName": "Ilya Belyakov", "authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe", "authorContact": "https://t.me/Biveraxe",
@@ -35,9 +34,7 @@
"index": "Значения от 1 до 4, где при выборе 1 будет нумерация pin 100-115, при выборе 2 200-215 и т.д." "index": "Значения от 1 до 4, где при выборе 1 будет нумерация pin 100-115, при выборе 2 200-215 и т.д."
} }
}, },
"defActive": true, "defActive": true,
"usedLibs": { "usedLibs": {
"esp32_4mb": [ "esp32_4mb": [
"adafruit/Adafruit MCP23017 Arduino Library@^2.1.0", "adafruit/Adafruit MCP23017 Arduino Library@^2.1.0",

View File

@@ -1,21 +1,20 @@
{ {
"menuSection": "Исполнительные устройства", "menuSection": "executive_devices",
"configItem": [
"configItem": [{ {
"global": 0, "global": 0,
"name": "MP3 плеер", "name": "MP3 плеер",
"type": "Reading", "type": "Reading",
"subtype": "Mp3", "subtype": "Mp3",
"id": "mp3", "id": "mp3",
"widget": "", "widget": "",
"page": "", "page": "",
"descr": "", "descr": "",
"int": 1,
"int": 1, "pins": "14,12",
"pins": "14,12", "volume": 20
"volume": 20 }
}], ],
"about": { "about": {
"authorName": "Ilya Belyakov", "authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe", "authorContact": "https://t.me/Biveraxe",
@@ -59,12 +58,17 @@
{ {
"name": "volume", "name": "volume",
"descr": "Установить громкость", "descr": "Установить громкость",
"params": ["Значение громкости"] "params": [
"Значение громкости"
]
}, },
{ {
"name": "playFolder", "name": "playFolder",
"descr": "Проиграть файл из папки", "descr": "Проиграть файл из папки",
"params": ["Номер папки", "Номер файла"] "params": [
"Номер папки",
"Номер файла"
]
}, },
{ {
"name": "play", "name": "play",
@@ -83,9 +87,7 @@
} }
] ]
}, },
"defActive": true, "defActive": true,
"usedLibs": { "usedLibs": {
"esp32_4mb": [ "esp32_4mb": [
"dfrobot/DFRobotDFPlayerMini @ ^1.0.5" "dfrobot/DFRobotDFPlayerMini @ ^1.0.5"

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Исполнительные устройства", "menuSection": "executive_devices",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
@@ -52,4 +52,4 @@
"esp8266_2mb": [], "esp8266_2mb": [],
"esp8266_2mb_ota": [] "esp8266_2mb_ota": []
} }
} }

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Исполнительные устройства", "menuSection": "executive_devices",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,

View File

@@ -1,20 +1,20 @@
{ {
"menuSection": "Исполнительные устройства", "menuSection": "executive_devices",
"configItem": [
"configItem": [{ {
"global": 0, "global": 0,
"name": "Расширитель портов Pcf8574", "name": "Расширитель портов Pcf8574",
"type": "Reading", "type": "Reading",
"subtype": "Pcf8574", "subtype": "Pcf8574",
"id": "Pcf", "id": "Pcf",
"widget": "", "widget": "",
"page": "", "page": "",
"descr": "", "descr": "",
"int": "0", "int": "0",
"addr": "0x20", "addr": "0x20",
"index": 1 "index": 1
}], }
],
"about": { "about": {
"authorName": "Serghei Crasnicov", "authorName": "Serghei Crasnicov",
"authorContact": "https://t.me/Serghei63", "authorContact": "https://t.me/Serghei63",
@@ -27,11 +27,10 @@
"int": "Не используется", "int": "Не используется",
"addr": "Адрес устройства на шине, обычно 0x20", "addr": "Адрес устройства на шине, обычно 0x20",
"index": "Значения от 1 до 4, где при выборе 1 будет нумерация pin 100-115, при выборе 2 200-215 и т.д." "index": "Значения от 1 до 4, где при выборе 1 будет нумерация pin 100-115, при выборе 2 200-215 и т.д."
} },
"title": "Расширитель портов Pcf8574"
}, },
"defActive": true, "defActive": true,
"usedLibs": { "usedLibs": {
"esp32_4mb": [ "esp32_4mb": [
"adafruit/Adafruit BusIO @ ^1.13.2" "adafruit/Adafruit BusIO @ ^1.13.2"

View File

@@ -1,24 +1,24 @@
{ {
"menuSection": "Исполнительные устройства", "menuSection": "executive_devices",
"configItem": [
"configItem": [{ {
"global": 0, "global": 0,
"name": "PWM ESP32", "name": "PWM ESP32",
"type": "Writing", "type": "Writing",
"subtype": "Pwm32", "subtype": "Pwm32",
"id": "pwm", "id": "pwm",
"widget": "range", "widget": "range",
"page": "Кнопки", "page": "Кнопки",
"descr": "PWM", "descr": "PWM",
"int": 0, "int": 0,
"pin": 2, "pin": 2,
"freq": 5000, "freq": 5000,
"ledChannel": 2, "ledChannel": 2,
"PWM_resolution": 10, "PWM_resolution": 10,
"val": 0, "val": 0,
"apin": -1 "apin": -1
}], }
],
"about": { "about": {
"authorName": "Avaks", "authorName": "Avaks",
"authorContact": "https://t.me/Avaks", "authorContact": "https://t.me/Avaks",
@@ -42,9 +42,7 @@
"freq": "Частота" "freq": "Частота"
} }
}, },
"defActive": true, "defActive": true,
"usedLibs": { "usedLibs": {
"esp32_4mb": [] "esp32_4mb": []
} }

View File

@@ -1,22 +1,22 @@
{ {
"menuSection": "Исполнительные устройства", "menuSection": "executive_devices",
"configItem": [
"configItem": [{ {
"global": 0, "global": 0,
"name": "PWM ESP8266", "name": "PWM ESP8266",
"type": "Writing", "type": "Writing",
"subtype": "Pwm8266", "subtype": "Pwm8266",
"id": "pwm", "id": "pwm",
"widget": "range", "widget": "range",
"page": "Кнопки", "page": "Кнопки",
"descr": "PWM", "descr": "PWM",
"int": 0, "int": 0,
"pin": 15, "pin": 15,
"freq": 5000, "freq": 5000,
"val": 0, "val": 0,
"apin": -1 "apin": -1
}], }
],
"about": { "about": {
"authorName": "Avaks", "authorName": "Avaks",
"authorContact": "https://t.me/Avaks", "authorContact": "https://t.me/Avaks",
@@ -38,9 +38,7 @@
"freq": "Частота" "freq": "Частота"
} }
}, },
"defActive": true, "defActive": true,
"usedLibs": { "usedLibs": {
"esp8266_4mb": [], "esp8266_4mb": [],
"esp8266_1mb": [], "esp8266_1mb": [],

View File

@@ -1,19 +1,18 @@
{ {
"menuSection": "Исполнительные устройства", "menuSection": "executive_devices",
"configItem": [
"configItem": [{ {
"global": 0, "global": 0,
"name": "SD карта", "name": "SD карта",
"type": "Writing", "type": "Writing",
"subtype": "SDcard", "subtype": "SDcard",
"id": "sd", "id": "sd",
"widget": "", "widget": "",
"page": "", "page": "",
"descr": "", "descr": "",
"int": 1
"int": 1 }
}], ],
"about": { "about": {
"authorName": "Ilya Belyakov", "authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe", "authorContact": "https://t.me/Biveraxe",
@@ -31,9 +30,7 @@
"int": "Не используется." "int": "Не используется."
} }
}, },
"defActive": false, "defActive": false,
"usedLibs": { "usedLibs": {
"esp32_4mb": [ "esp32_4mb": [
"espressif/esp32-camera @ ^2.0.0" "espressif/esp32-camera @ ^2.0.0"

View File

@@ -1,18 +1,18 @@
{ {
"menuSection": "Исполнительные устройства", "menuSection": "executive_devices",
"configItem": [
"configItem": [{ {
"global": 0, "global": 0,
"name": "Доп. функции системы", "name": "Доп. функции системы",
"type": "Reading", "type": "Reading",
"subtype": "SysExt", "subtype": "SysExt",
"id": "SysExt", "id": "SysExt",
"widget": "", "widget": "",
"page": "", "page": "",
"descr": "", "descr": "",
"int": 15 "int": 15
}], }
],
"about": { "about": {
"authorName": "Ilya Belyakov", "authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe", "authorContact": "https://t.me/Biveraxe",
@@ -30,9 +30,7 @@
"int": "Не используется" "int": "Не используется"
} }
}, },
"defActive": false, "defActive": false,
"usedLibs": { "usedLibs": {
"esp32_4mb": [], "esp32_4mb": [],
"esp8266_4mb": [] "esp8266_4mb": []

View File

@@ -1,23 +1,22 @@
{ {
"menuSection": "Исполнительные устройства", "menuSection": "executive_devices",
"configItem": [
"configItem": [{ {
"global": 0, "global": 0,
"name": "Телеграм-Бот", "name": "Телеграм-Бот",
"type": "Writing", "type": "Writing",
"subtype": "Telegram", "subtype": "Telegram",
"id": "tg", "id": "tg",
"widget": "", "widget": "",
"page": "", "page": "",
"descr": "", "descr": "",
"int": 10, "int": 10,
"token": "",
"token": "", "autos": 1,
"autos": 1, "receiveMsg": 0,
"receiveMsg": 0, "chatID": ""
"chatID": "" }
}], ],
"about": { "about": {
"authorName": "Ilya Belyakov", "authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe", "authorContact": "https://t.me/Biveraxe",
@@ -38,25 +37,30 @@
"chatID": "ИД диалога с контактом. Необходим для отправки сообщений именно вам." "chatID": "ИД диалога с контактом. Необходим для отправки сообщений именно вам."
}, },
"funcInfo": [ "funcInfo": [
{ {
"name": "sendMsg", "name": "sendMsg",
"descr": "Отправить сообщение без повторений.", "descr": "Отправить сообщение без повторений.",
"params": ["Сообщение, может быть строкой, числом или ИД другого элемента для получения значения"] "params": [
"Сообщение, может быть строкой, числом или ИД другого элемента для получения значения"
]
}, },
{ {
"name": "sendOftenMsg", "name": "sendOftenMsg",
"descr": "Отправить сообщение в любом случае, даж если отправляли такое ранее.", "descr": "Отправить сообщение в любом случае, даж если отправляли такое ранее.",
"params": ["Сообщение, может быть строкой, числом или ИД другого элемента для получения значения"] "params": [
"Сообщение, может быть строкой, числом или ИД другого элемента для получения значения"
]
} }
] ]
}, },
"defActive": false, "defActive": false,
"usedLibs": { "usedLibs": {
"esp32_4mb": [ "esp32_4mb": [
"CTBot @2.1.9" "CTBot @2.1.9"
], ],
"esp32_16mb": [
"CTBot @2.1.9"
],
"esp8266_4mb": [ "esp8266_4mb": [
"CTBot @2.1.9" "CTBot @2.1.9"
] ]

View File

@@ -1,6 +1,5 @@
{ {
"menuSection": "Исполнительные устройства", "menuSection": "executive_devices",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
@@ -15,7 +14,6 @@
"chatID": "" "chatID": ""
} }
], ],
"about": { "about": {
"authorName": "AVAKS", "authorName": "AVAKS",
"authorContact": "https://t.me/@avaks_dev", "authorContact": "https://t.me/@avaks_dev",
@@ -51,13 +49,13 @@
} }
] ]
}, },
"defActive": true, "defActive": true,
"usedLibs": { "usedLibs": {
"esp32_4mb": [], "esp32_4mb": [],
"esp32_16mb": [],
"esp32s2_4mb": [], "esp32s2_4mb": [],
"esp8266_4mb": [], "esp8266_4mb": [],
"esp8266_16mb": [],
"esp8266_1mb": [], "esp8266_1mb": [],
"esp8266_1mb_ota": [], "esp8266_1mb_ota": [],
"esp8285_1mb": [], "esp8285_1mb": [],
@@ -65,4 +63,4 @@
"esp8266_2mb": [], "esp8266_2mb": [],
"esp8266_2mb_ota": [] "esp8266_2mb_ota": []
} }
} }

View File

@@ -1,6 +1,5 @@
{ {
"menuSection": "Исполнительные устройства", "menuSection": "executive_devices",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
@@ -73,7 +72,6 @@
"outside_id": "" "outside_id": ""
} }
], ],
"about": { "about": {
"authorName": "AVAKS", "authorName": "AVAKS",
"authorContact": "https://t.me/@avaks_dev", "authorContact": "https://t.me/@avaks_dev",
@@ -106,28 +104,34 @@
{ {
"name": "enable", "name": "enable",
"descr": "включить / выключить термостатирование (режим AUTO) применим к PID и Гистере́зис ", "descr": "включить / выключить термостатирование (режим AUTO) применим к PID и Гистере́зис ",
"params": ["thermostat.enable(1) - вкл, thermostat.enable(0) - выкл, "] "params": [
"thermostat.enable(1) - вкл, thermostat.enable(0) - выкл, "
]
}, },
{ {
"name": "KP", "name": "KP",
"descr": "Пропорциональный коэффициент PID .", "descr": "Пропорциональный коэффициент PID .",
"params": ["thermostat.KP(1) - задает значение коэффициента"] "params": [
"thermostat.KP(1) - задает значение коэффициента"
]
}, },
{ {
"name": "KI", "name": "KI",
"descr": "Интегральный коэффициент PID .", "descr": "Интегральный коэффициент PID .",
"params": ["thermostat.KI(1) - задает значение коэффициента"] "params": [
"thermostat.KI(1) - задает значение коэффициента"
]
}, },
{ {
"name": "KD", "name": "KD",
"descr": "Дифференциальный коэффициент PID .", "descr": "Дифференциальный коэффициент PID .",
"params": ["thermostat.KD(1) - задает значение коэффициента"] "params": [
"thermostat.KD(1) - задает значение коэффициента"
]
} }
] ]
}, },
"defActive": false, "defActive": false,
"usedLibs": { "usedLibs": {
"esp32_4mb": [], "esp32_4mb": [],
"esp8266_4mb": [], "esp8266_4mb": [],
@@ -138,4 +142,4 @@
"esp8266_2mb": [], "esp8266_2mb": [],
"esp8266_2mb_ota": [] "esp8266_2mb_ota": []
} }
} }

View File

@@ -69,6 +69,11 @@
"descr": "Отправить значение в топик MQTT", "descr": "Отправить значение в топик MQTT",
"params": ["Топик", "Значение"] "params": ["Топик", "Значение"]
}, },
{
"name": "mqttIsConnect",
"descr": "Получить состояние подключения к MQTT",
"params": []
},
{ {
"name": "getHours", "name": "getHours",
"descr": "Получить текущее число часов. Если время не получено из сети Интернет или внешнего RTC, то условие пропускается", "descr": "Получить текущее число часов. Если время не получено из сети Интернет или внешнего RTC, то условие пропускается",

View File

@@ -1,9 +1,9 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"name": "A02 Дальность", "name": "A02 Дальность",
"type": "Reading", "type": "Reading",
"subtype": "A02Distance", "subtype": "A02Distance",
"id": "dist", "id": "dist",
"widget": "anydataCm", "widget": "anydataCm",
@@ -21,10 +21,11 @@
"specialThanks": "", "specialThanks": "",
"moduleName": "A02Distance", "moduleName": "A02Distance",
"moduleVersion": "0.1", "moduleVersion": "0.1",
"moduleDesc": "A0221AU, A02YYUW Ультразвуковой датчик. Позволяет получить дальность с ультрозвуковых датчиков A0221AU, A02YYUW", "moduleDesc": "Позволяет получить дальность с ультрозвуковых датчиков A0221AU, A02YYUW",
"propInfo": { "propInfo": {
"int": "Количество секунд между опросами датчика." "int": "Количество секунд между опросами датчика."
} },
"title": "A0221AU, A02YYUW Ультразвуковой датчик дальности"
}, },
"defActive": true, "defActive": true,
"usedLibs": { "usedLibs": {

View File

@@ -1,9 +1,9 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"name": "Acs712 Ток", "name": "Acs712 Ток",
"type": "Reading", "type": "Reading",
"subtype": "Acs712", "subtype": "Acs712",
"id": "amp", "id": "amp",
"widget": "anydataAmp", "widget": "anydataAmp",
@@ -13,10 +13,10 @@
"pin": 39, "pin": 39,
"int": 5, "int": 5,
"rms": 1, "rms": 1,
"vref": 5000, "vref": 5000,
"sens": 100, "sens": 100,
"adczero" : 512, "adczero": 512,
"btn-setZero": "nil" "btn-setZero": "nil"
} }
], ],
"about": { "about": {
@@ -34,14 +34,15 @@
"rms": "1 - подсчет средне-квадратического тока (переменный), 0 - подсчет средне-арифмитического тока (постоянный)", "rms": "1 - подсчет средне-квадратического тока (переменный), 0 - подсчет средне-арифмитического тока (постоянный)",
"vref": "Vref (мВ) - Опороное наряжение питания Acs712, по умолчанию = 5000мВ", "vref": "Vref (мВ) - Опороное наряжение питания Acs712, по умолчанию = 5000мВ",
"sens": "Чувствительность датчика тока: 5A = 185mВ/A , 20A = 100mВ/A , 30A = 66mВ/A ", "sens": "Чувствительность датчика тока: 5A = 185mВ/A , 20A = 100mВ/A , 30A = 66mВ/A ",
"adczero" : "Переменная калибровки нулевого значения отсчетов АЦП при нулевой нагрузке. Для ESP8266 - 512, Для ESP32 -2048, это 2.5В = 0А (1,65 с делителем) для Acs712 20A и 30A при стабильном токе 5В", "adczero": "Переменная калибровки нулевого значения отсчетов АЦП при нулевой нагрузке. Для ESP8266 - 512, Для ESP32 -2048, это 2.5В = 0А (1,65 с делителем) для Acs712 20A и 30A при стабильном токе 5В",
"btn-setZero": "Кнопка калибровки нулевого значения отсчетов АЦП при нулевой нагрузке. Нагрузка в момент калибровки должна быть отключена! После перезагрузки будет установлено в значение по умолчанию adczero. Для сохранение смотрим лог, и изменияем adczero" "btn-setZero": "Кнопка калибровки нулевого значения отсчетов АЦП при нулевой нагрузке. Нагрузка в момент калибровки должна быть отключена! После перезагрузки будет установлено в значение по умолчанию adczero. Для сохранение смотрим лог, и изменияем adczero"
} },
"title": "Acs712 Датчик тока"
}, },
"defActive": true, "defActive": true,
"usedLibs": { "usedLibs": {
"esp32_4mb": [], "esp32_4mb": [],
"esp32s2_4mb": [], "esp32s2_4mb": [],
"esp8266_4mb": [], "esp8266_4mb": [],
"esp8266_1mb": [], "esp8266_1mb": [],
"esp8266_1mb_ota": [], "esp8266_1mb_ota": [],

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
@@ -12,7 +12,7 @@
"descr": "AHTXX Температура", "descr": "AHTXX Температура",
"int": 15, "int": 15,
"addr": "0x38", "addr": "0x38",
"shtType":1, "shtType": 1,
"round": 1 "round": 1
}, },
{ {
@@ -26,7 +26,7 @@
"descr": "AHTXX Влажность", "descr": "AHTXX Влажность",
"int": 15, "int": 15,
"addr": "0x38", "addr": "0x38",
"shtType":1, "shtType": 1,
"round": 1 "round": 1
} }
], ],
@@ -61,6 +61,18 @@
], ],
"esp8266_4mb": [ "esp8266_4mb": [
"https://github.com/enjoyneering/AHTxx.git" "https://github.com/enjoyneering/AHTxx.git"
],
"esp8266_1mb": [
"https://github.com/enjoyneering/AHTxx.git"
],
"esp8266_1mb_ota": [
"https://github.com/enjoyneering/AHTxx.git"
],
"esp8285_1mb": [
"https://github.com/enjoyneering/AHTxx.git"
],
"esp8285_1mb_ota": [
"https://github.com/enjoyneering/AHTxx.git"
] ]
} }
} }

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,

View File

@@ -1,19 +1,19 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [
"configItem": [{ {
"global": 0, "global": 0,
"name": "Cенсор освещенность Bh1750", "name": "Cенсор освещенность Bh1750",
"type": "Reading", "type": "Reading",
"subtype": "Bh1750", "subtype": "Bh1750",
"id": "Bh1750", "id": "Bh1750",
"widget": "anydata", "widget": "anydata",
"page": "Сенсоры", "page": "Сенсоры",
"descr": "Освещённость", "descr": "Освещённость",
"round": 1, "round": 1,
"int": 15 "int": 15
}], }
],
"about": { "about": {
"authorName": "Ilya Belyakov", "authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe", "authorContact": "https://t.me/Biveraxe",

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"name": "bluetooth сканер", "name": "bluetooth сканер",
@@ -42,7 +42,10 @@
"esp32_4mb": 1261449, "esp32_4mb": 1261449,
"esp8266_4mb": 0 "esp8266_4mb": 0
}, },
"subTypes": ["BleSens", "BleScan"], "subTypes": [
"BleSens",
"BleScan"
],
"title": "Сканер Bluetooth", "title": "Сканер Bluetooth",
"moduleDesc": "Позволяет получить данные с Bluetooth часов и термометров Mijia, Xiaomi, Cleargrass, ...", "moduleDesc": "Позволяет получить данные с Bluetooth часов и термометров Mijia, Xiaomi, Cleargrass, ...",
"propInfo": { "propInfo": {
@@ -61,4 +64,4 @@
"https://github.com/avaksru/decoder.git" "https://github.com/avaksru/decoder.git"
] ]
} }
} }

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "executive_devices",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
@@ -14,7 +14,7 @@
"multiply": 1, "multiply": 1,
"pin": 4, "pin": 4,
"index": 0, "index": 0,
"addr": "", "addr": "",
"int": 10, "int": 10,
"round": 0, "round": 0,
"needSave": 0 "needSave": 0

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,

View File

@@ -7,16 +7,16 @@
#include "Global.h" #include "Global.h"
#include "classes/IoTItem.h" #include "classes/IoTItem.h"
//!Здесь подключаем стороннюю библиотеку при необходимости (ExternalLibrary заменить) //! Здесь подключаем стороннюю библиотеку при необходимости (ExternalLibrary заменить)
//#include <ExternalLibrary.h> // #include <ExternalLibrary.h>
#include "ExternalLibrary.h" //удалить, только для примера. Внешние библиотеки правильно в <> #include "ExternalLibrary.h" //удалить, только для примера. Внешние библиотеки правильно в <>
//! Объяевляем класс IoTGpio для работы с GPIO //! Объяевляем класс IoTGpio для работы с GPIO
extern IoTGpio IoTgpio; extern IoTGpio IoTgpio;
//========================================================================================================= //=========================================================================================================
//========================================================================================================= //=========================================================================================================
// Объявление сторонней библиотекит с использованием глобавльных объектов // Объявление сторонней библиотекит с использованием глобавльных объектов
//======================================================================================================= //=======================================================================================================
//! Объявляем стороннюю библиотеку при необходимости (ExternalLibrary заменить) //! Объявляем стороннюю библиотеку при необходимости (ExternalLibrary заменить)
// !!! ЗДЕСЬ И ДАЛЕЕ libXX НАЗВАТЬ уникальным именем) // !!! ЗДЕСЬ И ДАЛЕЕ libXX НАЗВАТЬ уникальным именем)
@@ -25,9 +25,15 @@ ExternalLibrary *libXX = nullptr;
// Функция инициализации библиотечного класса, возвращает Единстрвенный указать на библиотеку // Функция инициализации библиотечного класса, возвращает Единстрвенный указать на библиотеку
// instanceLibXX НАЗВАТЬ по наименованию модуля (instanceДатчикХ) // instanceLibXX НАЗВАТЬ по наименованию модуля (instanceДатчикХ)
// ПРИ НЕОБХДИМОСТИ передаем любые нужные параметры для инициализации библиотеки (в данном случае PIN) // ПРИ НЕОБХДИМОСТИ передаем любые нужные параметры для инициализации библиотеки (в данном случае PIN)
// !!! ВЫзвать данную функцию нужно хотябы один раз, //
// !!! ВЫзвать данную функцию нужно хотябы один раз,
// но в каждом конструкторе класса модуля ExampleModule_A, ExampleModule_B и т.д. // но в каждом конструкторе класса модуля ExampleModule_A, ExampleModule_B и т.д.
// или можно вывывать постоянно при обращении к библиотеке, типа: instanceLibXX().READ_LIB_DATA_OTHER(); // или можно вывывать постоянно при обращении к библиотеке, типа: instanceLibXX().READ_LIB_DATA_OTHER();
//
// !!!!!! В деструкторах ~ExampleModule_B() и ~ExampleModule_A() надо УДАЛЯТЬ объект libXX, ЕСЛИ в функцию instanceLibXX чтото передается.
// Удаляем класс библиотеки, а то при переконфигурации в нем не поменяются PIN и дугие параметры передаваемые в библиотеку.
// P.S. Не для всех, если используется map или vector то лучше не надо.
ExternalLibrary *instanceLibXX(int pin) ExternalLibrary *instanceLibXX(int pin)
{ {
if (!libXX) if (!libXX)
@@ -39,7 +45,6 @@ ExternalLibrary *instanceLibXX(int pin)
return libXX; return libXX;
} }
//========================================================================================================= //=========================================================================================================
//========================================================================================================= //=========================================================================================================
// Первый класс модуля для определения 1-го элемента (параметра) // Первый класс модуля для определения 1-го элемента (параметра)
@@ -69,7 +74,7 @@ public:
// jsonReadStr, jsonReadBool, jsonReadInt // jsonReadStr, jsonReadBool, jsonReadInt
ExampleModule_A(String parameters) : IoTItem(parameters) ExampleModule_A(String parameters) : IoTItem(parameters)
{ {
//Читаем пользовательскую переменную PIN, должна быть объявлена в в modeinfo.json // Читаем пользовательскую переменную PIN, должна быть объявлена в в modeinfo.json
_pin = jsonReadInt(parameters, "pin"); _pin = jsonReadInt(parameters, "pin");
// другой вариант чтения парметров модуля // другой вариант чтения парметров модуля
jsonRead(parameters, F("int"), _interval, false); jsonRead(parameters, F("int"), _interval, false);
@@ -111,7 +116,12 @@ public:
} }
} }
~ExampleModule_A(){}; ~ExampleModule_A()
{
// Удаляем класс библиотеки, а то при переконфигурации в нем не поменяются PIN и дугие параметры передаваемые в библиотеку.
delete libXX;
libXX = nullptr;
};
}; };
//========================================================================================================= //=========================================================================================================
@@ -126,14 +136,15 @@ public:
class ExampleModule_B : public IoTItem class ExampleModule_B : public IoTItem
{ {
private: private:
//Пользовательские переменные // Пользовательские переменные
unsigned int _pin; unsigned int _pin;
public: public:
ExampleModule_B(String parameters) : IoTItem(parameters) ExampleModule_B(String parameters) : IoTItem(parameters)
{ {
//Читаем пользовательскую переменную PIN, должна быть объявлена в в modeinfo.json // Читаем пользовательскую переменную PIN, должна быть объявлена в в modeinfo.json
_pin = jsonReadInt(parameters, "pin"); _pin = jsonReadInt(parameters, "pin");
//Можно инициализировать библиотеку один раз, а потом используем указатель // Можно инициализировать библиотеку один раз, а потом используем указатель
instanceLibXX(_pin); instanceLibXX(_pin);
libXX->READ_LIB_DATA_OTHER(); libXX->READ_LIB_DATA_OTHER();
} }
@@ -146,7 +157,7 @@ public:
regEvent(value.valD, "ExampleModule"); // обязательный вызов хотяб один для регистрации события в ядре IoTM regEvent(value.valD, "ExampleModule"); // обязательный вызов хотяб один для регистрации события в ядре IoTM
} }
//================ обработка кнопок из конфигурации =================== //================ обработка кнопок из конфигурации ===================
// Хук (переопределение виртуальной функции) для обработки кнопки (в value будут данные с собственной панели ввода) // Хук (переопределение виртуальной функции) для обработки кнопки (в value будут данные с собственной панели ввода)
// Что бы кнопка была без поля ввода, нужно в modeinfo.json указать "btn-Example": nil // Что бы кнопка была без поля ввода, нужно в modeinfo.json указать "btn-Example": nil
void onModuleOrder(String &key, String &value) void onModuleOrder(String &key, String &value)
@@ -158,7 +169,7 @@ public:
} }
} }
//================ обработка команд из сценария=================== //================ обработка команд из сценария===================
// Хук (переопределение виртуальной функции) для обработки команды из сценария (в param будут даныые переданные в функции в сценарии) // Хук (переопределение виртуальной функции) для обработки команды из сценария (в param будут даныые переданные в функции в сценарии)
IoTValue execute(String command, std::vector<IoTValue> &param) IoTValue execute(String command, std::vector<IoTValue> &param)
{ {
@@ -204,10 +215,14 @@ public:
// Прсото пример кокой-то функции // Прсото пример кокой-то функции
} }
~ExampleModule_B(){}; ~ExampleModule_B()
{
// Удаляем класс библиотеки, а то при переконфигурации в нем не поменяются PIN и дугие параметры передаваемые в библиотеку.
delete libXX;
libXX = nullptr;
};
}; };
//========================================================================================================= //=========================================================================================================
//========================================================================================================= //=========================================================================================================
// Функция для связи модуля с ядром IoTM // Функция для связи модуля с ядром IoTM

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
@@ -24,9 +24,9 @@
"page": "Сенсоры", "page": "Сенсоры",
"descr": "Давление", "descr": "Давление",
"int": 15, "int": 15,
"pin": "32", "pin": "32",
"round": 1, "round": 1,
"btn-Example": 100 "btn-Example": 100
} }
], ],
"about": { "about": {
@@ -46,31 +46,37 @@
"propInfo": { "propInfo": {
"pin": "Аналоговый GPIO номер, к которому подключен датчик.", "pin": "Аналоговый GPIO номер, к которому подключен датчик.",
"int": "Количество секунд между опросами датчика", "int": "Количество секунд между опросами датчика",
"btn-Example": "Кнопка Example. В поле указать ......" "btn-Example": "Кнопка Example. В поле указать ......"
}, },
"funcInfo": [ "funcInfo": [
{ {
"name": "expampleFunc", "name": "expampleFunc",
"descr": "Пример функции вызываемой из сценария. Принимает Id другого модуля и смотрит его значение", "descr": "Пример функции вызываемой из сценария. Принимает Id другого модуля и смотрит его значение",
"params": ["ID стороннего модуля"] "params": [
"ID стороннего модуля"
]
}, },
{ {
"name": "expample2", "name": "expample2",
"descr": "Второй Пример функции вызываемой из сценария.", "descr": "Второй Пример функции вызываемой из сценария.",
"params": ["Описание педедаваемого параметра", "params": [
"параметр 2"] "Описание педедаваемого параметра",
"параметр 2"
]
}, },
{ {
"name": "expampleAny", "name": "expampleAny",
"descr": "Третий Пример функции вызываемой из сценария. С неограниченным числом параметров", "descr": "Третий Пример функции вызываемой из сценария. С неограниченным числом параметров",
"params": ["Описание педедаваемых параметров"] "params": [
"Описание педедаваемых параметров"
]
} }
] ]
}, },
"defActive": false, "defActive": false,
"usedLibs": { "usedLibs": {
"esp32_4mb": [], "esp32_4mb": [],
"esp32s2_4mb": [], "esp32s2_4mb": [],
"esp8266_4mb": [], "esp8266_4mb": [],
"esp8266_1mb": [], "esp8266_1mb": [],
"esp8266_1mb_ota": [], "esp8266_1mb_ota": [],

View File

@@ -13,16 +13,24 @@ private:
int red = 0; int red = 0;
int offline = 0; int offline = 0;
bool dataFromNode = false; bool dataFromNode = false;
String _topic = "";
bool _isJson;
bool _addPrefix;
bool _debug;
public: public:
ExternalMQTT(String parameters) : IoTItem(parameters) ExternalMQTT(String parameters) : IoTItem(parameters)
{ {
_MAC = jsonReadStr(parameters, "MAC");
_sensor = jsonReadStr(parameters, "sensor"); _sensor = jsonReadStr(parameters, "sensor");
jsonRead(parameters, F("orange"), orange); jsonRead(parameters, F("orange"), orange);
jsonRead(parameters, F("red"), red); jsonRead(parameters, F("red"), red);
jsonRead(parameters, F("offline"), offline); jsonRead(parameters, F("offline"), offline);
_topic = jsonReadStr(parameters, "topic");
_isJson = jsonReadBool(parameters, "isJson");
_addPrefix = jsonReadBool(parameters, "addPrefix");
_debug = jsonReadBool(parameters, "debug");
dataFromNode = false; dataFromNode = false;
mqttSubscribeExternal(_topic, _addPrefix);
} }
char *TimeToString(unsigned long t) char *TimeToString(unsigned long t)
{ {
@@ -38,38 +46,58 @@ public:
{ {
if (msg.indexOf("HELLO") == -1) if (msg.indexOf("HELLO") == -1)
{ {
if (_debug)
// SerialPrint("i", "onMqttRecive", "Прилетело " + topic); {
// SerialPrint("i", "onMqttRecive", "Прилетело " + msg); SerialPrint("i", "onMqttRecive", "Прилетело " + topic + " msg: " + msg);
// SerialPrint("i", "onMqttRecive", "Прилетело " + msg);
}
String dev = selectToMarkerLast(topic, "/"); String dev = selectToMarkerLast(topic, "/");
dev.toUpperCase(); dev.toUpperCase();
dev.replace(":", ""); dev.replace(":", "");
if (_MAC == "") if (_topic != topic)
{ {
SerialPrint("i", "onMqttRecive", dev + " --> " + msg); return;
} }
DynamicJsonDocument doc(JSON_BUFFER_SIZE); if (_isJson)
DeserializationError error = deserializeJson(doc, msg);
if (error)
{ {
SerialPrint("E", F("onMqttRecive"), error.f_str()); DynamicJsonDocument doc(JSON_BUFFER_SIZE);
} DeserializationError error = deserializeJson(doc, msg);
JsonObject jsonObject = doc.as<JsonObject>(); if (error)
for (JsonPair kv : jsonObject)
{
String key = kv.key().c_str();
String val = kv.value();
if (_MAC == dev && _sensor == key)
{ {
dataFromNode = true; SerialPrint("E", F("onMqttRecive"), error.f_str());
_minutesPassed = 0;
setValue(val);
// setNewWidgetAttributes();
} }
JsonObject jsonObject = doc.as<JsonObject>();
// Serial.println("Key: " + key); for (JsonPair kv : jsonObject)
// Serial.println("Value: " + val); {
String key = kv.key().c_str();
String val = kv.value();
if (_debug)
{
SerialPrint("i", "onMqttRecive", "Прилетело MAC: " + dev + " key=" + key + " val=" + val);
}
if (_sensor == key)
{
dataFromNode = true;
_minutesPassed = 0;
setValue(val);
// setNewWidgetAttributes();
}
// Serial.println("Key: " + key);
// Serial.println("Value: " + val);
}
}
else
{
if (_debug)
{
SerialPrint("i", "onMqttRecive", "Прилетело MAC: " + dev + " val=" + msg);
}
dataFromNode = true;
_minutesPassed = 0;
setValue(msg);
// setNewWidgetAttributes();
} }
} }
} }
@@ -116,7 +144,22 @@ public:
} }
sendSubWidgetsValues(_id, json); sendSubWidgetsValues(_id, json);
} }
/*
IoTValue execute(String command, std::vector<IoTValue> &param)
{
if (command == "mqttSubscribe")
{
if (param.size() == 2)
{
if (!param[0].isDecimal && param[1].isDecimal)
{
mqttSubscribeExternal(param[0].valS, (bool)param[0].valD);
}
}
}
return {};
}
*/
~ExternalMQTT(){}; ~ExternalMQTT(){};
}; };

View File

@@ -1,6 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
@@ -11,23 +10,25 @@
"widget": "", "widget": "",
"page": "", "page": "",
"descr": "", "descr": "",
"MAC": "",
"sensor": "", "sensor": "",
"topic": "",
"addPrefix": 0,
"isJson": 1,
"round": "", "round": "",
"orange": 60, "orange": 60,
"red": 120, "red": 120,
"offline": 180, "offline": 180,
"int": 60 "int": 60,
"debug": 0
} }
], ],
"about": { "about": {
"authorName": "AVAKS", "authorName": "AVAKS",
"authorContact": "https://t.me/@avaks_dev", "authorContact": "https://t.me/@avaks_dev",
"authorGit": "https://github.com/avaksru", "authorGit": "https://github.com/avaksru",
"specialThanks": "", "specialThanks": "",
"moduleName": "ExternalMQTT", "moduleName": "ExternalMQTT",
"moduleVersion": "1", "moduleVersion": "1.2",
"usedRam": { "usedRam": {
"esp32_4mb": 15, "esp32_4mb": 15,
"esp8266_4mb": 15 "esp8266_4mb": 15
@@ -40,15 +41,18 @@
"orange": "количество минут после которого окрасить виджет в оранжевый цвет", "orange": "количество минут после которого окрасить виджет в оранжевый цвет",
"red": "количество минут после которого окрасить виджет в красный цвет", "red": "количество минут после которого окрасить виджет в красный цвет",
"offline": "количество минут после которого отобразить что устройство offline, если все три orange red и offline поставить в ноль - то функция окраски выключится", "offline": "количество минут после которого отобразить что устройство offline, если все три orange red и offline поставить в ноль - то функция окраски выключится",
"MAC": "MAC адрес беспроводного датчика", "sensor": "Тип сенсора: температура / влажность / время / ... Он же ключ в json пакете ",
"sensor": "Тип сенсора: температура / влажность / время / ... " "topic":"Подписаться на произвольный топик (полный путь), в модуле данный топик буде проверяться с отправителем, например homed/fd/zigbee/temp",
"addPrefix":"1 (число), будет добавлен стандартный префикс из настроек, 0 - не добавлять префикс",
"isJson":"1 - ожидаем в топике json, 0 - в топике просто значение (при 0 поле sensor заполнять не требуется)",
"debug":"1 - выводить дополнительный лог в сериал"
} }
}, },
"defActive": false, "defActive": false,
"usedLibs": { "usedLibs": {
"esp32_4mb": [], "esp32_4mb": [],
"esp32s2_4mb": [],
"esp8266_4mb": [], "esp8266_4mb": [],
"esp8266_1mb": [], "esp8266_1mb": [],
"esp8266_1mb_ota": [], "esp8266_1mb_ota": [],
@@ -57,4 +61,4 @@
"esp8266_2mb": [], "esp8266_2mb": [],
"esp8266_2mb_ota": [] "esp8266_2mb_ota": []
} }
} }

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,

View File

@@ -1,22 +1,22 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [
"configItem": [{ {
"name": "HX710 Cенсор давления", "name": "HX710 Cенсор давления",
"type": "Reading", "type": "Reading",
"subtype": "Hx710", "subtype": "Hx710",
"id": "hxp", "id": "hxp",
"widget": "anydataDef", "widget": "anydataDef",
"page": "Давление", "page": "Давление",
"descr": "HX press", "descr": "HX press",
"int": 15, "int": 15,
"plus": 0, "plus": 0,
"multiply": 1, "multiply": 1,
"round": 1, "round": 1,
"data": 14, "data": 14,
"clock": 15 "clock": 15
}], }
],
"about": { "about": {
"authorName": "Serghei Crasnicov", "authorName": "Serghei Crasnicov",
"authorContact": "https://t.me/Serghei63", "authorContact": "https://t.me/Serghei63",
@@ -44,9 +44,7 @@
} }
] ]
}, },
"defActive": false, "defActive": false,
"usedLibs": { "usedLibs": {
"esp32_4mb": [ "esp32_4mb": [
"https://github.com/kurimawxx00/hx710B_pressure_sensor" "https://github.com/kurimawxx00/hx710B_pressure_sensor"

View File

@@ -1,24 +1,24 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [
"configItem": [{ {
"name": "HX711 Cенсор весов", "name": "HX711 Cенсор весов",
"type": "Reading", "type": "Reading",
"subtype": "Hx711", "subtype": "Hx711",
"id": "hx", "id": "hx",
"widget": "anydataDef", "widget": "anydataDef",
"page": "Весы", "page": "Весы",
"descr": "HX вес", "descr": "HX вес",
"int": 15, "int": 15,
"map": "1024,1024,1,100", "map": "1024,1024,1,100",
"plus": 0, "plus": 0,
"multiply": 1, "multiply": 1,
"round": 1, "round": 1,
"data": 3, "data": 3,
"clock": 2, "clock": 2,
"chan": 2 "chan": 2
}], }
],
"about": { "about": {
"authorName": "Serghei Crasnicov", "authorName": "Serghei Crasnicov",
"authorContact": "https://t.me/Serghei63", "authorContact": "https://t.me/Serghei63",
@@ -48,7 +48,9 @@
{ {
"name": "sleepMode", "name": "sleepMode",
"descr": "Перевести в режим сна", "descr": "Перевести в режим сна",
"params": ["=1 режим сна, =0 проснуться"] "params": [
"=1 режим сна, =0 проснуться"
]
}, },
{ {
"name": "read", "name": "read",
@@ -57,9 +59,7 @@
} }
] ]
}, },
"defActive": false, "defActive": false,
"usedLibs": { "usedLibs": {
"esp32_4mb": [ "esp32_4mb": [
"GyverHX711@1.2" "GyverHX711@1.2"

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,

View File

@@ -1,139 +1,135 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [
"configItem": [{ {
"global": 0, "global": 0,
"name": "INA219 Tок", "name": "INA219 Tок",
"type": "Reading", "type": "Reading",
"subtype": "Ina219curr", "subtype": "Ina219curr",
"id": "ina219_A", "id": "ina219_A",
"widget": "anydataAmp", "widget": "anydataAmp",
"page": "INA 219", "page": "INA 219",
"descr": "Сила тока", "descr": "Сила тока",
"addr": "0x40", "addr": "0x40",
"plus": 0, "plus": 0,
"multiply": 1, "multiply": 1,
"round": 3, "round": 3,
"int": 10 "int": 10
},
{
"global": 0,
"name": "INA219 Напряжение",
"type": "Reading",
"subtype": "Ina219voltage",
"id": "ina219_V",
"widget": "anydataVlt",
"page": "INA 219",
"descr": "Напряжения",
"addr": "0x40",
"plus": 0,
"multiply": 1,
"round": 3,
"int": 10
},
{
"global": 0,
"name": "INA219 Мощность",
"type": "Reading",
"subtype": "Ina219power",
"id": "ina219_W",
"widget": "anydataWt",
"page": "INA 219",
"descr": "Мощность",
"addr": "0x40",
"plus": 0,
"multiply": 1,
"round": 3,
"int": 10
},
{
"global": 0,
"name": "INA219 Шунт",
"type": "Reading",
"subtype": "Ina219shuntvoltage",
"id": "ina219_Vsh",
"widget": "anydataVlt",
"page": "INA 219",
"descr": "Напряжение шунта",
"addr": "0x40",
"plus": 0,
"multiply": 1,
"round": 3,
"int": 10
},
{
"global": 0,
"name": "INA219 Настройки",
"type": "Reading",
"subtype": "Ina219setting",
"id": "ina219_set",
"widget": "nil",
"page": "",
"descr": "",
"addr": "0x40",
"shunt": 0.1,
"maxV": 3.2,
"adjClbr": 0,
"resol": 4,
"btn-getClbr":"nil"
}],
"about": {
"authorName": "Serghei Crasnicov",
"authorContact": "https://t.me/Serghei63",
"authorGit": "https://github.com/Serghei63",
"specialThanks": "Дмитрий, Serg, v2.0 - Mitchel @Mit4bmw",
"moduleName": "Ina219",
"moduleVersion": "2.0",
"usedRam": {
"esp32_4mb": 15,
"esp8266_4mb": 15
},
"subTypes": [
"Ina219curr",
"Ina219voltage",
"Ina219power",
"Ina219shuntvoltage",
"Ina219setting"
],
"title": "Милливатметр постоянного тока",
"moduleDesc": "Измеряет постоянный ток до 3.2 ампера, напряжение до 26 вольт и мощность на нагрузке. Модуль INA219 Настройки - для изменении настроек нужен постоянно в конфигурации, должен стоять перед рдугими модулями с тем же адресом, без него работает на значенях по умолчанию",
"propInfo": {
"int": "Количество секунд между опросами датчика.",
"addr": "Адрес датчика на шине, обычно 0x40. Если оставить поле пустым, то запуститься сканер I2C и подключение к адресу 0x40",
"shunt": "Сопротивление шунта, штатно 0.1Ом. Изменить если его перепаяли",
"maxV": "Максимальный ожидаемый ток, штатно 3.2А, для указаного шунта",
"adjClbr": "Задать смещение (подкрутить) калибровочное значение на указанное значение. -20 = Уменьшить калибровочное значение на 20",
"resol": "Установка режима усреднения для измерения напряжения и тока, рекомендуется для повышения стабильности показаний на шумной нагрузке. Варианты 1(без усреднения),2,4,8,16,32,64,128",
"btn-getClbr": "Кнопка запроса текущей калибровки, выводится в лог"
},
"funcInfo": [
{
"name": "sleep",
"descr": "INA219 Настройки. Установка / снятие режима сна датчика INA219",
"params": ["1- вкл сна/ 0-выкл сна"]
}
]
}, },
{
"defActive": false, "global": 0,
"name": "INA219 Напряжение",
"usedLibs": { "type": "Reading",
"esp32_4mb": [ "subtype": "Ina219voltage",
"https://github.com/GyverLibs/GyverINA" "id": "ina219_V",
], "widget": "anydataVlt",
"esp32s2_4mb": [ "page": "INA 219",
"https://github.com/GyverLibs/GyverINA" "descr": "Напряжения",
], "addr": "0x40",
"plus": 0,
"esp8266_4mb": [ "multiply": 1,
"https://github.com/GyverLibs/GyverINA" "round": 3,
], "int": 10
"esp8266_16mb": [ },
"https://github.com/GyverLibs/GyverINA" {
] "global": 0,
"name": "INA219 Мощность",
"type": "Reading",
"subtype": "Ina219power",
"id": "ina219_W",
"widget": "anydataWt",
"page": "INA 219",
"descr": "Мощность",
"addr": "0x40",
"plus": 0,
"multiply": 1,
"round": 3,
"int": 10
},
{
"global": 0,
"name": "INA219 Шунт",
"type": "Reading",
"subtype": "Ina219shuntvoltage",
"id": "ina219_Vsh",
"widget": "anydataVlt",
"page": "INA 219",
"descr": "Напряжение шунта",
"addr": "0x40",
"plus": 0,
"multiply": 1,
"round": 3,
"int": 10
},
{
"global": 0,
"name": "INA219 Настройки",
"type": "Reading",
"subtype": "Ina219setting",
"id": "ina219_set",
"widget": "nil",
"page": "",
"descr": "",
"addr": "0x40",
"shunt": 0.1,
"maxV": 3.2,
"adjClbr": 0,
"resol": 4,
"btn-getClbr": "nil"
} }
],
} "about": {
"authorName": "Serghei Crasnicov",
"authorContact": "https://t.me/Serghei63",
"authorGit": "https://github.com/Serghei63",
"specialThanks": "Дмитрий, Serg, v2.0 - Mitchel @Mit4bmw",
"moduleName": "Ina219",
"moduleVersion": "2.0",
"usedRam": {
"esp32_4mb": 15,
"esp8266_4mb": 15
},
"subTypes": [
"Ina219curr",
"Ina219voltage",
"Ina219power",
"Ina219shuntvoltage",
"Ina219setting"
],
"title": "Милливатметр постоянного тока",
"moduleDesc": "Измеряет постоянный ток до 3.2 ампера, напряжение до 26 вольт и мощность на нагрузке. Модуль INA219 Настройки - для изменении настроек нужен постоянно в конфигурации, должен стоять перед рдугими модулями с тем же адресом, без него работает на значенях по умолчанию",
"propInfo": {
"int": "Количество секунд между опросами датчика.",
"addr": "Адрес датчика на шине, обычно 0x40. Если оставить поле пустым, то запуститься сканер I2C и подключение к адресу 0x40",
"shunt": "Сопротивление шунта, штатно 0.1Ом. Изменить если его перепаяли",
"maxV": "Максимальный ожидаемый ток, штатно 3.2А, для указаного шунта",
"adjClbr": "Задать смещение (подкрутить) калибровочное значение на указанное значение. -20 = Уменьшить калибровочное значение на 20",
"resol": "Установка режима усреднения для измерения напряжения и тока, рекомендуется для повышения стабильности показаний на шумной нагрузке. Варианты 1(без усреднения),2,4,8,16,32,64,128",
"btn-getClbr": "Кнопка запроса текущей калибровки, выводится в лог"
},
"funcInfo": [
{
"name": "sleep",
"descr": "INA219 Настройки. Установка / снятие режима сна датчика INA219",
"params": [
"1- вкл сна/ 0-выкл сна"
]
}
]
},
"defActive": false,
"usedLibs": {
"esp32_4mb": [
"https://github.com/GyverLibs/GyverINA"
],
"esp32s2_4mb": [
"https://github.com/GyverLibs/GyverINA"
],
"esp8266_4mb": [
"https://github.com/GyverLibs/GyverINA"
],
"esp8266_16mb": [
"https://github.com/GyverLibs/GyverINA"
]
}
}

View File

@@ -1,139 +1,135 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [
"configItem": [{ {
"global": 0, "global": 0,
"name": "INA226 Tок", "name": "INA226 Tок",
"type": "Reading", "type": "Reading",
"subtype": "Ina226curr", "subtype": "Ina226curr",
"id": "ina226_A", "id": "ina226_A",
"widget": "anydataAmp", "widget": "anydataAmp",
"page": "INA 226", "page": "INA 226",
"descr": "Сила тока", "descr": "Сила тока",
"addr": "0x40", "addr": "0x40",
"plus": 0, "plus": 0,
"multiply": 1, "multiply": 1,
"round": 3, "round": 3,
"int": 10 "int": 10
},
{
"global": 0,
"name": "INA226 Напряжение",
"type": "Reading",
"subtype": "Ina226voltage",
"id": "ina226_V",
"widget": "anydataVlt",
"page": "INA 226",
"descr": "Напряжения",
"addr": "0x40",
"plus": 0,
"multiply": 1,
"round": 3,
"int": 10
},
{
"global": 0,
"name": "INA226 Мощность",
"type": "Reading",
"subtype": "Ina226power",
"id": "ina226_W",
"widget": "anydataWt",
"page": "INA 226",
"descr": "Мощность",
"addr": "0x40",
"plus": 0,
"multiply": 1,
"round": 3,
"int": 10
},
{
"global": 0,
"name": "INA226 Шунт",
"type": "Reading",
"subtype": "Ina226shuntvoltage",
"id": "ina226_Vsh",
"widget": "anydataVlt",
"page": "INA 226",
"descr": "Напряжение шунта",
"addr": "0x40",
"plus": 0,
"multiply": 1,
"round": 3,
"int": 10
},
{
"global": 0,
"name": "INA226 Настройки",
"type": "Reading",
"subtype": "Ina226setting",
"id": "ina226_set",
"widget": "nil",
"page": "",
"descr": "",
"addr": "0x40",
"shunt": 0.1,
"maxV": 3.2,
"adjClbr": 0,
"resol": 4,
"btn-getClbr":"nil"
}],
"about": {
"authorName": "Serghei Crasnicov",
"authorContact": "https://t.me/Serghei63",
"authorGit": "https://github.com/Serghei63",
"specialThanks": "v2.0 - Mitchel @Mit4bmw",
"moduleName": "Ina226",
"moduleVersion": "2.0",
"usedRam": {
"esp32_4mb": 15,
"esp8266_4mb": 15
},
"subTypes": [
"Ina226curr",
"Ina226voltage",
"Ina226power",
"Ina226shuntvoltage",
"Ina226setting"
],
"title": "Милливатметр постоянного тока",
"moduleDesc": "Стандартные значения для модуля INA226 (Сопротивление шунта - 0.1 Ом, Максимальный ожидаемый ток - 0.8 А, Адрес на шине I2c - 0x40). Модуль INA226 Настройки - для изменении настроек нужен постоянно в конфигурации, должен стоять перед рдугими модулями с тем же адресом, без него работает на значенях по умолчанию",
"propInfo": {
"int": "Количество секунд между опросами датчика.",
"addr": "Адрес датчика на шине, обычно 0x40. Если оставить поле пустым, то запуститься сканер I2C и подключение к адресу 0x40",
"shunt": "Сопротивление шунта, штатно 0.1Ом. Изменить если его перепаяли",
"maxV": "Максимальный ожидаемый ток, штатно 0.8А, для указаного шунта",
"adjClbr": "Задать смещение (подкрутить) калибровочное значение на указанное значение. -20 = Уменьшить калибровочное значение на 20",
"resol": "Установка режима усреднения (колическва замеров) для измерения напряжения и тока, рекомендуется для повышения стабильности показаний на шумной нагрузке. Пропорционально увеличивает время оцифровки. Варианты 0(без усреднения), от 1 до 7 - соответстввует 4,16,64,128,256,512,1024",
"btn-getClbr": "Кнопка запроса текущей калибровки, выводится в лог"
},
"funcInfo": [
{
"name": "sleep",
"descr": "INA226 Настройки. Установка / снятие режима сна датчика INA226",
"params": ["1- вкл сна/ 0-выкл сна"]
}
]
}, },
{
"defActive": false, "global": 0,
"name": "INA226 Напряжение",
"usedLibs": { "type": "Reading",
"esp32_4mb": [ "subtype": "Ina226voltage",
"https://github.com/GyverLibs/GyverINA" "id": "ina226_V",
], "widget": "anydataVlt",
"esp32s2_4mb": [ "page": "INA 226",
"https://github.com/GyverLibs/GyverINA" "descr": "Напряжения",
], "addr": "0x40",
"plus": 0,
"esp8266_4mb": [ "multiply": 1,
"https://github.com/GyverLibs/GyverINA" "round": 3,
], "int": 10
"esp8266_16mb": [ },
"https://github.com/GyverLibs/GyverINA" {
] "global": 0,
"name": "INA226 Мощность",
"type": "Reading",
"subtype": "Ina226power",
"id": "ina226_W",
"widget": "anydataWt",
"page": "INA 226",
"descr": "Мощность",
"addr": "0x40",
"plus": 0,
"multiply": 1,
"round": 3,
"int": 10
},
{
"global": 0,
"name": "INA226 Шунт",
"type": "Reading",
"subtype": "Ina226shuntvoltage",
"id": "ina226_Vsh",
"widget": "anydataVlt",
"page": "INA 226",
"descr": "Напряжение шунта",
"addr": "0x40",
"plus": 0,
"multiply": 1,
"round": 3,
"int": 10
},
{
"global": 0,
"name": "INA226 Настройки",
"type": "Reading",
"subtype": "Ina226setting",
"id": "ina226_set",
"widget": "nil",
"page": "",
"descr": "",
"addr": "0x40",
"shunt": 0.1,
"maxV": 3.2,
"adjClbr": 0,
"resol": 4,
"btn-getClbr": "nil"
} }
],
} "about": {
"authorName": "Serghei Crasnicov",
"authorContact": "https://t.me/Serghei63",
"authorGit": "https://github.com/Serghei63",
"specialThanks": "v2.0 - Mitchel @Mit4bmw",
"moduleName": "Ina226",
"moduleVersion": "2.0",
"usedRam": {
"esp32_4mb": 15,
"esp8266_4mb": 15
},
"subTypes": [
"Ina226curr",
"Ina226voltage",
"Ina226power",
"Ina226shuntvoltage",
"Ina226setting"
],
"title": "Милливатметр постоянного тока",
"moduleDesc": "Стандартные значения для модуля INA226 (Сопротивление шунта - 0.1 Ом, Максимальный ожидаемый ток - 0.8 А, Адрес на шине I2c - 0x40). Модуль INA226 Настройки - для изменении настроек нужен постоянно в конфигурации, должен стоять перед рдугими модулями с тем же адресом, без него работает на значенях по умолчанию",
"propInfo": {
"int": "Количество секунд между опросами датчика.",
"addr": "Адрес датчика на шине, обычно 0x40. Если оставить поле пустым, то запуститься сканер I2C и подключение к адресу 0x40",
"shunt": "Сопротивление шунта, штатно 0.1Ом. Изменить если его перепаяли",
"maxV": "Максимальный ожидаемый ток, штатно 0.8А, для указаного шунта",
"adjClbr": "Задать смещение (подкрутить) калибровочное значение на указанное значение. -20 = Уменьшить калибровочное значение на 20",
"resol": "Установка режима усреднения (колическва замеров) для измерения напряжения и тока, рекомендуется для повышения стабильности показаний на шумной нагрузке. Пропорционально увеличивает время оцифровки. Варианты 0(без усреднения), от 1 до 7 - соответстввует 4,16,64,128,256,512,1024",
"btn-getClbr": "Кнопка запроса текущей калибровки, выводится в лог"
},
"funcInfo": [
{
"name": "sleep",
"descr": "INA226 Настройки. Установка / снятие режима сна датчика INA226",
"params": [
"1- вкл сна/ 0-выкл сна"
]
}
]
},
"defActive": false,
"usedLibs": {
"esp32_4mb": [
"https://github.com/GyverLibs/GyverINA"
],
"esp32s2_4mb": [
"https://github.com/GyverLibs/GyverINA"
],
"esp8266_4mb": [
"https://github.com/GyverLibs/GyverINA"
],
"esp8266_16mb": [
"https://github.com/GyverLibs/GyverINA"
]
}
}

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
@@ -73,12 +73,15 @@
"ABC": "Автокалибровка. По умолчанию включена. Раз в сутки на 20 мин. надо выставлять на свежий воздух.", "ABC": "Автокалибровка. По умолчанию включена. Раз в сутки на 20 мин. надо выставлять на свежий воздух.",
"pin": "пин получения значений по ШИМ. Esp8266: GPIO 15 - D8, ESP32: GPIO 21, > MHZ19: PWM желтый провод", "pin": "пин получения значений по ШИМ. Esp8266: GPIO 15 - D8, ESP32: GPIO 21, > MHZ19: PWM желтый провод",
"maxRetriesNotAvailable": "Максимальное количество попыток опроса сенсора по ШИМ. (может задерживать контроллер)" "maxRetriesNotAvailable": "Максимальное количество попыток опроса сенсора по ШИМ. (может задерживать контроллер)"
} },
"title": "Mhz19 Датчик уровеня концентрации CO2"
}, },
"defActive": false, "defActive": false,
"usedLibs": { "usedLibs": {
"esp32_4mb": [], "esp32_4mb": [],
"esp32s2_4mb": ["plerup/EspSoftwareSerial"], "esp32s2_4mb": [
"plerup/EspSoftwareSerial"
],
"esp8266_4mb": [] "esp8266_4mb": []
} }
} }

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
@@ -13,17 +13,14 @@
"needSave": 0, "needSave": 0,
"val": "0", "val": "0",
"int": 15, "int": 15,
"pin": "35", "pin": "35",
"R1":"10000", "R1": "10000",
"R0":"10000", "R0": "10000",
"Beta":"3950.0", "Beta": "3950.0",
"T0":"25", "T0": "25",
"Vs":"3.3", "Vs": "3.3",
"round" : 1 "round": 1
} }
], ],
"about": { "about": {
"authorName": "Serghei Crasnicov", "authorName": "Serghei Crasnicov",
@@ -44,11 +41,11 @@
"retInfo": "", "retInfo": "",
"propInfo": { "propInfo": {
"pin": "Аналоговый пин (для esp8266 = 0, для esp32 алаоговый gpio, например 35)", "pin": "Аналоговый пин (для esp8266 = 0, для esp32 алаоговый gpio, например 35)",
"R1":"Сопротивление подтягивающего резистора, должен быть равен сопротивлению термистера", "R1": "Сопротивление подтягивающего резистора, должен быть равен сопротивлению термистера",
"Vs":"Напряжение питания датчика, Для точности измерить и ввести своё, по умолчанию 3.3В", "Vs": "Напряжение питания датчика, Для точности измерить и ввести своё, по умолчанию 3.3В",
"R0":"Сопротивление термистора при температуре То, например 10 КОм при 25С", "R0": "Сопротивление термистора при температуре То, например 10 КОм при 25С",
"T0":"Базовая температура, температура измерения сопротивление термистора (Rterm), обычно 25С", "T0": "Базовая температура, температура измерения сопротивление термистора (Rterm), обычно 25С",
"Beta":"Beta термистора" "Beta": "Beta термистора"
} }
}, },
"defActive": false, "defActive": false,
@@ -62,4 +59,4 @@
"esp8266_2mb": [], "esp8266_2mb": [],
"esp8266_2mb_ota": [] "esp8266_2mb_ota": []
} }
} }

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
@@ -115,8 +115,8 @@
"Pzem004pf", "Pzem004pf",
"Pzem004cmd" "Pzem004cmd"
], ],
"title": "Счетчик электроэнергии PZEM 004 t версии 3.0 (с модбасом). Возможно подключение трех счетчиков к одной esp для трехфазных сетей. Для этого нужно настроить разные адреса modbus в платах pzem", "title": "Счетчик электроэнергии PZEM 004 t версии 3.0 (с модбасом)",
"moduleDesc": "Считает потраченную электроэнергию, измеряет напряжение, частоту, силу тока и прочие параметры", "moduleDesc": "Считает потраченную электроэнергию, измеряет напряжение, частоту, силу тока и прочие параметры. Возможно подключение трех счетчиков к одной esp для трехфазных сетей. Для этого нужно настроить разные адреса modbus в платах pzem",
"propInfo": { "propInfo": {
"addr": "Адрес modbus", "addr": "Адрес modbus",
"int": "Количество секунд между опросами датчика. Желателно устанавливать одинаковые интервалы для параметров (для одного адреса Pzem) что опрос происходил один раз, остальные из 500мс буфера.", "int": "Количество секунд между опросами датчика. Желателно устанавливать одинаковые интервалы для параметров (для одного адреса Pzem) что опрос происходил один раз, остальные из 500мс буфера.",

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
@@ -18,7 +18,7 @@
"ticker": 0, "ticker": 0,
"int": 5, "int": 5,
"btn-setUTime": "0", "btn-setUTime": "0",
"btn-setSysTime": "nil" "btn-setSysTime": "nil"
} }
], ],
"about": { "about": {
@@ -51,19 +51,37 @@
{ {
"name": "getTime", "name": "getTime",
"descr": "Получить строковое значение времени по указанному формату.", "descr": "Получить строковое значение времени по указанному формату.",
"params": ["Формат как у функции date() в PHP"] "params": [
"Формат как у функции date() в PHP"
]
} }
] ]
}, },
"defActive": true, "defActive": true,
"usedLibs": { "usedLibs": {
"esp32_4mb": ["https://github.com/tremaru/iarduino_RTC"], "esp32_4mb": [
"esp8266_4mb": ["https://github.com/tremaru/iarduino_RTC"], "https://github.com/tremaru/iarduino_RTC"
"esp8266_1mb": ["https://github.com/tremaru/iarduino_RTC"], ],
"esp8266_1mb_ota": ["https://github.com/tremaru/iarduino_RTC"], "esp8266_4mb": [
"esp8285_1mb": ["https://github.com/tremaru/iarduino_RTC"], "https://github.com/tremaru/iarduino_RTC"
"esp8285_1mb_ota": ["https://github.com/tremaru/iarduino_RTC"], ],
"esp8266_2mb": ["https://github.com/tremaru/iarduino_RTC"], "esp8266_1mb": [
"esp8266_2mb_ota": ["https://github.com/tremaru/iarduino_RTC"] "https://github.com/tremaru/iarduino_RTC"
],
"esp8266_1mb_ota": [
"https://github.com/tremaru/iarduino_RTC"
],
"esp8285_1mb": [
"https://github.com/tremaru/iarduino_RTC"
],
"esp8285_1mb_ota": [
"https://github.com/tremaru/iarduino_RTC"
],
"esp8266_2mb": [
"https://github.com/tremaru/iarduino_RTC"
],
"esp8266_2mb_ota": [
"https://github.com/tremaru/iarduino_RTC"
]
} }
} }

View File

@@ -1,19 +1,19 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"name": "(S8) Cенсор качества воздуха", "name": "(S8) Cенсор качества воздуха",
"num": 3, "num": 3,
"type": "Reading", "type": "Reading",
"subtype": "S8co", "subtype": "S8co",
"id": "s8co", "id": "s8co",
"widget": "anydataPpm", "widget": "anydataPpm",
"page": "Сенсоры", "page": "Сенсоры",
"descr": "S8_CO2", "descr": "S8_CO2",
"int": 15, "int": 15,
"round": 1, "round": 1,
"rxPin": 13, "rxPin": 13,
"txPin": 15 "txPin": 15
} }
], ],
"about": { "about": {
@@ -35,9 +35,7 @@
}, },
"defActive": true, "defActive": true,
"usedLibs": { "usedLibs": {
"esp32_4mb": [ "esp32_4mb": [],
], "esp8266_4mb": []
"esp8266_4mb": [
]
} }
} }

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
@@ -14,7 +14,7 @@
"round": 0, "round": 0,
"lowPeriodic": 1, "lowPeriodic": 1,
"autoCalibration": 1, "autoCalibration": 1,
"btn-Recalibration": 0 "btn-Recalibration": 0
}, },
{ {
"global": 0, "global": 0,
@@ -61,13 +61,11 @@
"title": "Датчик температуры и влажности Scd40", "title": "Датчик температуры и влажности Scd40",
"moduleDesc": "Позволяет получить значения температуры и влажности с Scd40.", "moduleDesc": "Позволяет получить значения температуры и влажности с Scd40.",
"propInfo": { "propInfo": {
"int": "Количество секунд между опросами библиотеки (датчик опрашивается библиотекой по своему таймеру, см. lowPeriodic).", "int": "Количество секунд между опросами библиотеки (датчик опрашивается библиотекой по своему таймеру, см. lowPeriodic).",
"offset": "Смещение температуры представляет собой разницу между температурой, измеренной SCD4x, и фактической температурой окружающей среды температура. По умолчанию смещение температуры в библиотеке/датчике установлено на 4°C.", "offset": "Смещение температуры представляет собой разницу между температурой, измеренной SCD4x, и фактической температурой окружающей среды температура. По умолчанию смещение температуры в библиотеке/датчике установлено на 4°C.",
"lowPeriodic": "Медленные режим опроса датчика библиотекой. 0-каждые 5сек, 1-каждые 30сек", "lowPeriodic": "Медленные режим опроса датчика библиотекой. 0-каждые 5сек, 1-каждые 30сек",
"autoCalibration": "Автоматическая калибровка, по умолчанию включена AutomaticSelfCalibration, 0 - выключена", "autoCalibration": "Автоматическая калибровка, по умолчанию включена AutomaticSelfCalibration, 0 - выключена",
"btn-Recalibration": "Кнопка принудительной калибровки. В поле указать Целевая концентрация CO₂ в миллионных долях. Перед калибровкой необходимо находтся в течение > 3 минут в среде с однородной и постоянной концентрацией CO₂. Выдает в лог Значение коррекции FRC в co₂ ppm" "btn-Recalibration": "Кнопка принудительной калибровки. В поле указать Целевая концентрация CO₂ в миллионных долях. Перед калибровкой необходимо находтся в течение > 3 минут в среде с однородной и постоянной концентрацией CO₂. Выдает в лог Значение коррекции FRC в co₂ ppm"
} }
}, },
"defActive": false, "defActive": false,

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
@@ -61,7 +61,8 @@
"continuousMode": "1 - Непрерывный режим, 0 - Режим с остановкой (щедящий)", "continuousMode": "1 - Непрерывный режим, 0 - Режим с остановкой (щедящий)",
"maxRetriesNotAvailable": "Количество попыток ожидания ответа сенсора при опросе (не нужно менять)", "maxRetriesNotAvailable": "Количество попыток ожидания ответа сенсора при опросе (не нужно менять)",
"retryDelayMs": "Задержка между попытками, миллисекунды (не нужно менять)" "retryDelayMs": "Задержка между попытками, миллисекунды (не нужно менять)"
} },
"title": "Sds011 Датчик концентрации пыли в воздухе"
}, },
"defActive": false, "defActive": false,
"usedLibs": { "usedLibs": {

View File

@@ -1,31 +1,31 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
"name": "SGP30 Cенсор качества воздуха", "name": "SGP30 Cенсор качества воздуха",
"num": 3, "num": 3,
"type": "Reading", "type": "Reading",
"subtype": "Sgp30t", "subtype": "Sgp30t",
"id": "sgp30t", "id": "sgp30t",
"widget": "anydatappm", "widget": "anydatappm",
"page": "Сенсоры", "page": "Сенсоры",
"descr": "TVOC", "descr": "TVOC",
"int": 30, "int": 30,
"round": 1 "round": 1
}, },
{ {
"global": 0, "global": 0,
"name": "SGP30 Cенсор газа", "name": "SGP30 Cенсор газа",
"num": 4, "num": 4,
"type": "Reading", "type": "Reading",
"subtype": "Sgp30e", "subtype": "Sgp30e",
"id": "sgp30e", "id": "sgp30e",
"widget": "anydatappm", "widget": "anydatappm",
"page": "Сенсоры", "page": "Сенсоры",
"descr": "eCO2", "descr": "eCO2",
"int": 30, "int": 30,
"round": 1 "round": 1
} }
], ],
"about": { "about": {

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"name": "UART", "name": "UART",
@@ -44,22 +44,31 @@
{ {
"name": "println", "name": "println",
"descr": "Отправить в UART строку текста и признак завершения строки (перевод строки).", "descr": "Отправить в UART строку текста и признак завершения строки (перевод строки).",
"params": ["Строка текста"] "params": [
"Строка текста"
]
}, },
{ {
"name": "print", "name": "print",
"descr": "Отправить в UART строку текста.", "descr": "Отправить в UART строку текста.",
"params": ["Строка текста"] "params": [
"Строка текста"
]
}, },
{ {
"name": "printHex", "name": "printHex",
"descr": "Отправить в UART HEX-строку.", "descr": "Отправить в UART HEX-строку.",
"params": ["HEX-строка."] "params": [
"HEX-строка."
]
}, },
{ {
"name": "printFFF", "name": "printFFF",
"descr": "Отправить в UART текстовую строку и hex метку 3 байта 0xFF0xFF0xFF.", "descr": "Отправить в UART текстовую строку и hex метку 3 байта 0xFF0xFF0xFF.",
"params": ["Строка текста", "1 - обернуть строку в кавычки, 0 - отправить без кавычек"] "params": [
"Строка текста",
"1 - обернуть строку в кавычки, 0 - отправить без кавычек"
]
} }
] ]
}, },

View File

@@ -235,7 +235,11 @@ public:
} }
} }
} }
~ld2410m(){}; ~ld2410m()
{
delete ld2410;
radar = nullptr;
};
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -291,7 +295,11 @@ public:
} }
} }
~ld2410t(){}; ~ld2410t()
{
delete ld2410;
radar = nullptr;
};
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -346,7 +354,11 @@ public:
} }
} }
} }
~ld2410d(){}; ~ld2410d()
{
delete ld2410;
radar = nullptr;
};
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -404,7 +416,11 @@ public:
} }
} }
} }
~ld2410e(){}; ~ld2410e()
{
delete ld2410;
radar = nullptr;
};
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void *getAPI_ld2410(String subtype, String param) void *getAPI_ld2410(String subtype, String param)

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Сенсоры", "menuSection": "sensors",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,

View File

@@ -1,5 +1,5 @@
{ {
"menuSection": "Виртуальные элементы", "menuSection": "virtual_elments",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
@@ -50,8 +50,10 @@
"defActive": true, "defActive": true,
"usedLibs": { "usedLibs": {
"esp32_4mb": [], "esp32_4mb": [],
"esp32_16mb": [],
"esp32s2_4mb": [], "esp32s2_4mb": [],
"esp8266_4mb": [], "esp8266_4mb": [],
"esp8266_16mb": [],
"esp8266_1mb": [], "esp8266_1mb": [],
"esp8266_1mb_ota": [], "esp8266_1mb_ota": [],
"esp8285_1mb": [], "esp8285_1mb": [],

View File

@@ -1,19 +1,19 @@
{ {
"menuSection": "Виртуальные элементы", "menuSection": "virtual_elments",
"configItem": [ "configItem": [
{ {
"global": 0, "global": 0,
"name": "GoogleSheet", "name": "GoogleSheet",
"type": "Reading", "type": "Reading",
"subtype": "GoogleSheet", "subtype": "GoogleSheet",
"id": "sheet", "id": "sheet",
"widget": "nil", "widget": "nil",
"page": "", "page": "",
"descr": "", "descr": "",
"int": 5, "int": 5,
"logid": "", "logid": "",
"scid": "", "scid": "",
"shname": "Logger" "shname": "Logger"
} }
], ],
"about": { "about": {
@@ -33,8 +33,8 @@
"propInfo": { "propInfo": {
"int": "Интервал логирования в минутах", "int": "Интервал логирования в минутах",
"logid": "ID величины которую будем логировать", "logid": "ID величины которую будем логировать",
"scid": "Идентификатор развертывания Google Apps (script id)", "scid": "Идентификатор развертывания Google Apps (script id)",
"shname": "Наименование листа в таблице (sheet name)" "shname": "Наименование листа в таблице (sheet name)"
}, },
"retInfo": "", "retInfo": "",
"funcInfo": [ "funcInfo": [
@@ -43,7 +43,7 @@
"descr": "Использовать не чаще раз в минуту! Логирование элементов в GoogleSheet, ID элементов указывать через запятую, от одного до N (проверено на 16шт). В данной функции поиск элементов идет по их значению, если несколько элементов с одинаковым значение, может быть не правильно указан его id в Таблице.", "descr": "Использовать не чаще раз в минуту! Логирование элементов в GoogleSheet, ID элементов указывать через запятую, от одного до N (проверено на 16шт). В данной функции поиск элементов идет по их значению, если несколько элементов с одинаковым значение, может быть не правильно указан его id в Таблице.",
"params": [ "params": [
"id Идентификатор 1-го элеменета", "id Идентификатор 1-го элеменета",
"id Идентификатор N-го элеменета" "id Идентификатор N-го элеменета"
] ]
}, },
{ {

Some files were not shown because too many files have changed in this diff Show More