Merge pull request #17 from Mit4el/ver4dev

обновление с основы
This commit is contained in:
Mit4el
2023-10-03 22:56:25 +03:00
committed by GitHub
37 changed files with 747 additions and 813 deletions

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,

View File

@@ -3,8 +3,14 @@
"name": "IoTmanagerVer4", "name": "IoTmanagerVer4",
"apssid": "IoTmanager", "apssid": "IoTmanager",
"appass": "", "appass": "",
"routerssid": ["iot","wifi"], "routerssid": [
"routerpass": ["hostel3333","pswd"], "iot",
"wifi"
],
"routerpass": [
"hostel3333",
"pswd"
],
"timezone": 2, "timezone": 2,
"ntp": "pool.ntp.org", "ntp": "pool.ntp.org",
"weblogin": "admin", "weblogin": "admin",
@@ -406,6 +412,10 @@
"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

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

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

@@ -20,4 +20,5 @@ void periodicWsSend();
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, const String& json, int client_id, size_t frameSize);
void sendStringToWs(const String& header, String& payload, int client_id); void sendStringToWs(const String& header, String& payload, int client_id);
void sendDeviceList(uint8_t num); void sendDeviceList(uint8_t num);
int getNumWSClients();

View File

@@ -11,7 +11,7 @@ struct IoTValue {
class IoTItem { class IoTItem {
public: public:
IoTItem(const String& parameters); IoTItem(const String& parameters);
virtual ~IoTItem() {} virtual ~IoTItem() {};
virtual void loop(); virtual void loop();
virtual void doByInterval(); virtual void doByInterval();
virtual IoTValue execute(String command, std::vector<IoTValue>& param); virtual IoTValue execute(String command, std::vector<IoTValue>& param);
@@ -35,9 +35,12 @@ class IoTItem {
void setInterval(long interval); void setInterval(long interval);
void setIntFromNet(int interval); void setIntFromNet(int interval);
unsigned long currentMillis; // unsigned long currentMillis;
unsigned long prevMillis; // unsigned long prevMillis;
unsigned long difference; // unsigned long difference;
unsigned long nextMillis=0; // достаточно 1 переменной, надо экономить память
// задержка следующего вызова, не изменяет текущий _interval
void suspendNextDoByInt(unsigned long _delay); // 0 - force
IoTValue value; // хранение основного значения, которое обновляется из сценария, execute(), loop() или doByInterval() IoTValue value; // хранение основного значения, которое обновляется из сценария, execute(), loop() или doByInterval()

View File

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

View File

@@ -3,8 +3,8 @@
"name": "IoTmanagerVer4", "name": "IoTmanagerVer4",
"apssid": "IoTmanager", "apssid": "IoTmanager",
"appass": "", "appass": "",
"routerssid": ["iot","wifi"], "routerssid": "iot",
"routerpass": ["hostel3333","pswd"], "routerpass": "hostel3333",
"timezone": 2, "timezone": 2,
"ntp": "pool.ntp.org", "ntp": "pool.ntp.org",
"weblogin": "admin", "weblogin": "admin",
@@ -406,6 +406,10 @@
"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

View File

@@ -32,6 +32,11 @@
"firmware": "0x00000", "firmware": "0x00000",
"littlefs": "0x300000" "littlefs": "0x300000"
}, },
{
"name": "esp8266_16mb",
"firmware": "0x00000",
"littlefs": "0x200000"
},
{ {
"name": "esp32_4mb", "name": "esp32_4mb",
"boot_app0": "0xe000", "boot_app0": "0xe000",
@@ -40,6 +45,14 @@
"partitions": "0x8000", "partitions": "0x8000",
"littlefs": "0x290000" "littlefs": "0x290000"
}, },
{
"name": "esp32_16mb",
"boot_app0": "0xe000",
"bootloader_qio_80m": "0x1000",
"firmware": "0x10000",
"partitions": "0x8000",
"littlefs": "0x910000"
},
{ {
"name": "esp8266_1mb", "name": "esp8266_1mb",
"firmware": "0x00000000", "firmware": "0x00000000",
@@ -381,6 +394,10 @@
"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

View File

@@ -10,8 +10,8 @@
IoTScenario iotScen; // объект управления сценарием IoTScenario iotScen; // объект управления сценарием
String volStrForSave = ""; String volStrForSave = "";
unsigned long currentMillis; // unsigned long currentMillis; // это сдесь лишнее
unsigned long prevMillis; // unsigned long prevMillis;
void elementsLoop() { void elementsLoop() {
// передаем управление каждому элементу конфигурации для выполнения своих функций // передаем управление каждому элементу конфигурации для выполнения своих функций

View File

@@ -5,7 +5,7 @@ void mqttInit() {
ts.add( ts.add(
WIFI_MQTT_CONNECTION_CHECK, MQTT_RECONNECT_INTERVAL, WIFI_MQTT_CONNECTION_CHECK, MQTT_RECONNECT_INTERVAL,
[&](void*) { [&](void*) {
if (WiFi.status() == WL_CONNECTED) { if (isNetworkActive()) {
SerialPrint("i", F("WIFI"), "http://" + jsonReadStr(settingsFlashJson, F("ip"))); SerialPrint("i", F("WIFI"), "http://" + jsonReadStr(settingsFlashJson, F("ip")));
wifiUptimeCalc(); wifiUptimeCalc();
if (mqtt.connected()) { if (mqtt.connected()) {
@@ -121,13 +121,16 @@ void mqttSubscribe() {
} }
void mqttSubscribeExternal(String topic, bool usePrefix) { void mqttSubscribeExternal(String topic, bool usePrefix) {
SerialPrint("i", F("MQTT"), ("subscribed external" + topic).c_str());
// SerialPrint("i", F("MQTT"), mqttRootDevice); // SerialPrint("i", F("MQTT"), mqttRootDevice);
String _sb_topic = topic;
if (usePrefix) if (usePrefix)
{ {
mqtt.subscribe((mqttPrefix + topic).c_str()); _sb_topic = mqttPrefix + "/" + topic;
} }
mqtt.subscribe(topic.c_str()); mqtt.subscribe(_sb_topic.c_str());
SerialPrint("i", F("MQTT"), ("subscribed external " + _sb_topic).c_str());
} }
void mqttCallback(char* topic, uint8_t* payload, size_t length) { void mqttCallback(char* topic, uint8_t* payload, size_t length) {

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

@@ -450,25 +450,27 @@ void sendFileToWsByFrames(const String& filename, const String& header,
} }
void sendStringToWs(const String& header, String& payload, int client_id) { void sendStringToWs(const String& header, String& payload, int client_id) {
if (!(WiFi.softAPgetStationNum() || isNetworkActive())) { if ((!getNumAPClients() && !isNetworkActive()) || !getNumWSClients()) {
return; // standWebSocket.disconnect(); // это и ниже надо сделать при -
} // standWebSocket.close(); // - отключении AP И WiFi(STA), надо менять ядро WiFi. Сейчас не закрывается сессия клиента при пропаже AP И WiFi(STA)
return;
}
if (header.length() != 6) { if (header.length() != 6) {
SerialPrint("E", "FS", F("wrong header size")); SerialPrint("E", "FS", F("wrong header size"));
return; return;
} }
String msg = header + "|0012|" + payload; String msg = header + "|0012|" + payload;
size_t totalSize = msg.length(); size_t totalSize = msg.length();
char dataArray[totalSize]; char dataArray[totalSize];
msg.toCharArray(dataArray, totalSize + 1); msg.toCharArray(dataArray, totalSize + 1);
if (client_id == -1) { if (client_id == -1) {
standWebSocket.broadcastBIN((uint8_t*)dataArray, totalSize); standWebSocket.broadcastBIN((uint8_t*)dataArray, totalSize);
} else { } else {
standWebSocket.sendBIN(client_id, (uint8_t*)dataArray, totalSize); standWebSocket.sendBIN(client_id, (uint8_t*)dataArray, totalSize);
} }
} }
void sendDeviceList(uint8_t num) { void sendDeviceList(uint8_t num) {
@@ -483,3 +485,7 @@ void sendDeviceList(uint8_t num) {
SerialPrint("i", "FS", "flash list"); SerialPrint("i", "FS", "flash list");
} }
} }
int getNumWSClients() {
return standWebSocket.connectedClients(false);
}

View File

@@ -7,9 +7,7 @@
IoTItem::IoTItem(const String& parameters) { IoTItem::IoTItem(const String& parameters) {
jsonRead(parameters, F("int"), _interval, false); jsonRead(parameters, F("int"), _interval, false);
if (_interval == 0) enableDoByInt = false; // выключаем использование периодического выполнения в модуле setInterval(_interval);
if (_interval > 0) _interval = _interval * 1000; // если int положителен, то считаем, что получены секунды
if (_interval < 0) _interval = _interval * -1; // если int отрицательный, то миллисекунды
jsonRead(parameters, F("subtype"), _subtype, false); jsonRead(parameters, F("subtype"), _subtype, false);
jsonRead(parameters, F("id"), _id); jsonRead(parameters, F("id"), _id);
if (!jsonRead(parameters, F("multiply"), _multiply, false)) _multiply = 1; if (!jsonRead(parameters, F("multiply"), _multiply, false)) _multiply = 1;
@@ -38,12 +36,16 @@ IoTItem::IoTItem(const String& parameters) {
setValue(valAsStr, false); setValue(valAsStr, false);
} }
void IoTItem::suspendNextDoByInt(unsigned long _delay) { // 0 - force
nextMillis = millis() + _delay;
}
void IoTItem::loop() { void IoTItem::loop() {
if (enableDoByInt) { if (enableDoByInt) {
currentMillis = millis(); unsigned long currentMillis = millis(); // _interval должен быть < 2147483647 мс (24 суток)
difference = currentMillis - prevMillis; if (nextMillis - currentMillis > 2147483647UL /*ULONG_MAX/2*/ ) {
if (difference >= _interval) { nextMillis = currentMillis + _interval;
prevMillis = millis(); // SerialPrint(F("i"), _id, "this->doByInterval");
this->doByInterval(); this->doByInterval();
} }
} }
@@ -202,7 +204,13 @@ bool IoTItem::isStrInID(const String& str) {
} }
void IoTItem::setInterval(long interval) { void IoTItem::setInterval(long interval) {
_interval = interval; if (interval == 0) enableDoByInt = false; // выключаем использование периодического выполнения в модуле
else {
enableDoByInt = true;
if (interval > 0) _interval = interval * 1000; // если int положителен, то считаем, что получены секунды
else if (interval < 0) _interval = interval * -1; // если int отрицательный, то миллисекунды
}
// SerialPrint(F("i"), F("IoTItem"), "setInterval: " + _interval.toString);
} }
IoTGpio* IoTItem::getGpioDriver() { IoTGpio* IoTItem::getGpioDriver() {

View File

@@ -43,13 +43,16 @@ public:
#if defined ESP8266 #if defined ESP8266
if (!http.begin(_host, 80, _url)) if (!http.begin(_host, 80, _url))
{ {
#elif defined ESP32
if (!http.begin(String("http://") + _host + _url))
{
#endif
// Serial.println("connection failed"); // Serial.println("connection failed");
SerialPrint("I", F("NextionUpdate"), "connection failed "); SerialPrint("I", F("NextionUpdate"), "connection failed ");
} }
#elif defined ESP32
if (!http.begin(String("http://") + _host + _url))
{
// Serial.println("connection failed");
SerialPrint("I", F("NextionUpdate"), "connection failed ");
}
#endif
SerialPrint("I", F("NextionUpdate"), "Requesting file: " + (String)_url); SerialPrint("I", F("NextionUpdate"), "Requesting file: " + (String)_url);
int code = http.GET(); int code = http.GET();

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

@@ -3,24 +3,28 @@
extern IoTGpio IoTgpio; extern IoTGpio IoTgpio;
class ButtonOut : public IoTItem { class ButtonOut : public IoTItem {
private: private:
int _pin, _inv; int _pin;
bool _inv;
public: public:
ButtonOut(String parameters): IoTItem(parameters) { ButtonOut(String parameters): IoTItem(parameters) {
jsonRead(parameters, "pin", _pin); jsonRead(parameters, "pin", _pin);
jsonRead(parameters, "inv", _inv); jsonRead(parameters, "inv", _inv);
_round = 0; _round = 0;
IoTgpio.pinMode(_pin, OUTPUT); IoTgpio.pinMode(_pin, OUTPUT);
IoTgpio.digitalWrite(_pin, _inv?!value.valD:value.valD); IoTgpio.digitalWrite(_pin, _inv?!value.valD:value.valD);
enableDoByInt = false;
} }
void doByInterval() { void doByInterval() {
//value.valD = IoTgpio.analogRead(_pin); int val = _inv?1:0;
IoTgpio.digitalWrite(_pin, val);
// SerialPrint("I", "ButtonOut","single pulse end");
value.valD = 0;
regEvent(0, "ButtonOut");
enableDoByInt = false;
//regEvent(value.valD, "ButtonOut"); //обязательный вызов хотяб один //regEvent(value.valD, "ButtonOut"); //обязательный вызов хотяб один
} }
@@ -30,24 +34,40 @@ class ButtonOut : public IoTItem {
// param - вектор ("массив") значений параметров переданных вместе с командой: ID.Команда("пар1", 22, 33) -> param[0].ValS = "пар1", param[1].ValD = 22 // param - вектор ("массив") значений параметров переданных вместе с командой: ID.Команда("пар1", 22, 33) -> param[0].ValS = "пар1", param[1].ValD = 22
if (command == "change") { if (command == "change") {
value.valD = 1 - IoTgpio.digitalRead(_pin); value.valD = 1 - (int)value.valD;
IoTgpio.digitalWrite(_pin, value.valD); IoTgpio.digitalWrite(_pin, _inv?!value.valD:value.valD);
regEvent(value.valD, "ButtonOut"); regEvent(value.valD, "ButtonOut");
} }
else if (command == "pulse") {
if (param[0].isDecimal && (param[0].valD != 0)) {
value.valD = !_inv?1:0;
enableDoByInt = true;
// SerialPrint("I", "ButtonOut","single pulse start");
regEvent((String)(int)!_inv?1:0, "ButtonOut");
suspendNextDoByInt(param[0].valD);
IoTgpio.digitalWrite(_pin, !_inv?1:0);
}
}
return {}; // команда поддерживает возвращаемое значения. Т.е. по итогу выполнения команды или общения с внешней системой, можно вернуть значение в сценарий для дальнейшей обработки return {}; // команда поддерживает возвращаемое значения. Т.е. по итогу выполнения команды или общения с внешней системой, можно вернуть значение в сценарий для дальнейшей обработки
} }
void setValue(const IoTValue& Value, bool genEvent = true) { void setValue(const IoTValue& Value, bool genEvent = true) {
value = Value; value = Value;
IoTgpio.digitalWrite(_pin, _inv?!value.valD:value.valD); if ((value.valD == !_inv?1:0) && (_interval != 0)) {
value.valD = !_inv?1:0;
enableDoByInt = true;
// SerialPrint("I", "ButtonOut","single pulse start");
suspendNextDoByInt(_interval);
} else {
enableDoByInt = false;
}
regEvent((String)(int)value.valD, "ButtonOut", false, genEvent); regEvent((String)(int)value.valD, "ButtonOut", false, genEvent);
IoTgpio.digitalWrite(_pin, _inv?!value.valD:value.valD);
} }
String getValue() { String getValue() {
return (String)(int)value.valD; return (String)(int)value.valD;
} }
//=======================================================================================================
~ButtonOut() {}; ~ButtonOut() {};
}; };

View File

@@ -39,6 +39,11 @@
"name": "change", "name": "change",
"descr": "Инвертирует значение переключателя", "descr": "Инвертирует значение переключателя",
"params": [] "params": []
},
{
"name": "pulse",
"descr": "Генерирует одиночный импульс",
"params": ["Длительность (ms)"]
} }
] ]
}, },

View File

@@ -79,16 +79,7 @@ public:
case 1: case 1:
// for doByIntervals // for doByIntervals
if (enableDoByInt) IoTItem::loop();
{
currentMillis = millis();
difference = currentMillis - prevMillis;
if (difference >= _interval)
{
prevMillis = millis();
this->doByInterval();
}
}
break; break;
case 2: case 2:

View File

@@ -10,7 +10,7 @@ public:
void sendHttpPOST(String url, String msg) void sendHttpPOST(String url, String msg)
{ {
if (WiFi.status() == WL_CONNECTED) if (isNetworkActive())
{ {
WiFiClient client; WiFiClient client;

View File

@@ -7,7 +7,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,

View File

@@ -3,6 +3,11 @@
#include "Arduino.h" #include "Arduino.h"
#include "MySensorsGate.h" #include "MySensorsGate.h"
// временное решение
unsigned long currentMillis;
unsigned long prevMillis;
unsigned long difference;
#ifdef MYSENSORS #ifdef MYSENSORS
// callback библиотеки mysensors // callback библиотеки mysensors
void receive(const MyMessage& message) { void receive(const MyMessage& message) {

View File

@@ -13,7 +13,7 @@ class TelegramLT : public IoTItem {
} }
void sendTelegramMsg(bool often, String msg) { void sendTelegramMsg(bool often, String msg) {
if (WiFi.status() == WL_CONNECTED && (often || !often && _prevMsg != msg)) { if (isNetworkActive() && (often || !often && _prevMsg != msg)) {
WiFiClient client; WiFiClient client;
HTTPClient http; HTTPClient http;
http.begin(client, "http://live-control.com/iotm/telegram.php"); http.begin(client, "http://live-control.com/iotm/telegram.php");

View File

@@ -246,6 +246,11 @@ protected:
pv_last = pv; pv_last = pv;
} }
// временное решение
unsigned long currentMillis;
unsigned long prevMillis;
unsigned long difference;
void loop() void loop()
{ {
if (enableDoByInt) if (enableDoByInt)

View File

@@ -64,13 +64,7 @@ class AnalogAdc : public IoTItem {
_avgSumm = _avgSumm + IoTgpio.analogRead(_pin); _avgSumm = _avgSumm + IoTgpio.analogRead(_pin);
_avgCount++; _avgCount++;
} }
IoTItem::loop();
currentMillis = millis();
difference = currentMillis - prevMillis;
if (difference >= _interval) {
prevMillis = millis();
this->doByInterval();
}
} }
~AnalogAdc(){}; ~AnalogAdc(){};

View File

@@ -107,13 +107,7 @@ public:
adc = IoTgpio.analogRead(_pin); adc = IoTgpio.analogRead(_pin);
// Блок вызова doByInterval, так как если определили loop, то сам он не вызовится // Блок вызова doByInterval, так как если определили loop, то сам он не вызовится
currentMillis = millis(); IoTItem::loop();
difference = currentMillis - prevMillis;
if (difference >= _interval)
{
prevMillis = millis();
this->doByInterval();
}
} }
~ExampleModule_A() ~ExampleModule_A()

View File

@@ -17,6 +17,7 @@ private:
bool _isJson; bool _isJson;
bool _addPrefix; bool _addPrefix;
bool _debug; bool _debug;
bool sendOk = false;
public: public:
ExternalMQTT(String parameters) : IoTItem(parameters) ExternalMQTT(String parameters) : IoTItem(parameters)
@@ -26,10 +27,12 @@ public:
jsonRead(parameters, F("red"), red); jsonRead(parameters, F("red"), red);
jsonRead(parameters, F("offline"), offline); jsonRead(parameters, F("offline"), offline);
_topic = jsonReadStr(parameters, "topic"); _topic = jsonReadStr(parameters, "topic");
_isJson = jsonReadBool(parameters, "isJson"); jsonRead(parameters, "isJson", _isJson);
_addPrefix = jsonReadBool(parameters, "addPrefix"); jsonRead(parameters, "addPrefix", _addPrefix);
_debug = jsonReadBool(parameters, "debug"); jsonRead(parameters, "debug", _debug);
dataFromNode = false; dataFromNode = false;
if (mqttIsConnect())
sendOk = true;
mqttSubscribeExternal(_topic, _addPrefix); mqttSubscribeExternal(_topic, _addPrefix);
} }
char *TimeToString(unsigned long t) char *TimeToString(unsigned long t)
@@ -58,6 +61,7 @@ public:
{ {
return; return;
} }
if (_isJson) if (_isJson)
{ {
DynamicJsonDocument doc(JSON_BUFFER_SIZE); DynamicJsonDocument doc(JSON_BUFFER_SIZE);
@@ -106,6 +110,11 @@ public:
{ {
_minutesPassed++; _minutesPassed++;
setNewWidgetAttributes(); setNewWidgetAttributes();
if (mqttIsConnect() && !sendOk)
{
sendOk = true;
mqttSubscribeExternal(_topic, _addPrefix);
}
} }
void onMqttWsAppConnectEvent() void onMqttWsAppConnectEvent()
{ {

View File

@@ -157,16 +157,17 @@ public:
void loop() void loop()
{ {
ts_sds.update(); ts_sds.update();
if (enableDoByInt) IoTItem::loop();
{ // if (enableDoByInt)
currentMillis = millis(); // {
difference = currentMillis - prevMillis; // currentMillis = millis();
if (difference >= _interval) // difference = currentMillis - prevMillis;
{ // if (difference >= _interval)
prevMillis = millis(); // {
this->doByInterval(); // prevMillis = millis();
} // this->doByInterval();
} // }
// }
} }
//======================================================================================================= //=======================================================================================================
// doByInterval() // doByInterval()

View File

@@ -10,7 +10,7 @@ private:
String scid = ""; String scid = "";
String shname = ""; String shname = "";
// bool init = false; // bool init = false;
int interval = 1; // int interval = 1;
// long interval; // long interval;
String URL = ("http://iotmanager.org/projects/google.php?/macros/s/"); // F("https://script.google.com/macros/s/"); String URL = ("http://iotmanager.org/projects/google.php?/macros/s/"); // F("https://script.google.com/macros/s/");
String urlFinal; String urlFinal;
@@ -24,14 +24,17 @@ public:
jsonRead(parameters, F("logid"), logid); jsonRead(parameters, F("logid"), logid);
jsonRead(parameters, F("scid"), scid); jsonRead(parameters, F("scid"), scid);
jsonRead(parameters, F("shname"), shname); jsonRead(parameters, F("shname"), shname);
jsonRead(parameters, F("int"), interval); // jsonRead(parameters, F("int"), interval);
interval = interval * 1000 * 60; // так как у нас в минутах long interval;
jsonRead(parameters, F("int"), interval); // в минутах
setInterval(interval * 60);
// interval = interval * 1000 * 60; // так как у нас в минутах
urlFinal = URL + scid + F("/exec?") + F("sheet=") + shname; urlFinal = URL + scid + F("/exec?") + F("sheet=") + shname;
} }
void doByInterval() void doByInterval()
{ {
if (WiFi.status() == WL_CONNECTED) if (isNetworkActive())
{ {
String value = getItemValue(logid); String value = getItemValue(logid);
if (value != "") if (value != "")
@@ -39,23 +42,23 @@ public:
} }
} }
void loop() // void loop()
{ // {
if (enableDoByInt) // if (enableDoByInt)
{ // {
currentMillis = millis(); // currentMillis = millis();
difference = currentMillis - prevMillis; // difference = currentMillis - prevMillis;
if (difference >= interval) // if (difference >= interval)
{ // {
prevMillis = millis(); // prevMillis = millis();
this->doByInterval(); // this->doByInterval();
} // }
} // }
} // }
IoTValue execute(String command, std::vector<IoTValue> &param) IoTValue execute(String command, std::vector<IoTValue> &param)
{ {
if (WiFi.status() == WL_CONNECTED) if (isNetworkActive())
{ {
if (command == F("logGoogle")) if (command == F("logGoogle"))
{ // Логирование определенного элемента по его идентификатору в GoogleSheet { // Логирование определенного элемента по его идентификатору в GoogleSheet

View File

@@ -23,7 +23,7 @@ class Loging : public IoTItem {
String prevDate = ""; String prevDate = "";
bool firstTimeInit = true; bool firstTimeInit = true;
long interval; // long interval;
public: public:
Loging(String parameters) : IoTItem(parameters) { Loging(String parameters) : IoTItem(parameters) {
@@ -34,8 +34,9 @@ class Loging : public IoTItem {
points = 300; points = 300;
SerialPrint("E", F("Loging"), "'" + id + "' user set more points than allowed, value reset to 300"); SerialPrint("E", F("Loging"), "'" + id + "' user set more points than allowed, value reset to 300");
} }
jsonRead(parameters, F("int"), interval); long interval;
interval = interval * 1000 * 60; // приводим к милисекундам jsonRead(parameters, F("int"), interval); // в минутах
setInterval(interval * 60);
//jsonRead(parameters, F("keepdays"), keepdays, false); //jsonRead(parameters, F("keepdays"), keepdays, false);
// создадим экземпляр класса даты // создадим экземпляр класса даты
@@ -303,18 +304,18 @@ class Loging : public IoTItem {
return ""; return "";
} }
void loop() { // void loop() {
if (enableDoByInt) { // if (enableDoByInt) {
currentMillis = millis(); // currentMillis = millis();
difference = currentMillis - prevMillis; // difference = currentMillis - prevMillis;
if (difference >= interval) { // if (difference >= interval) {
prevMillis = millis(); // prevMillis = millis();
if (interval != 0) { // if (interval != 0) {
this->doByInterval(); // this->doByInterval();
} // }
} // }
} // }
} // }
void regEvent(const String &value, const String &consoleInfo, bool error = false, bool genEvent = true) { void regEvent(const String &value, const String &consoleInfo, bool error = false, bool genEvent = true) {
String userDate = getItemValue(id + "-date"); String userDate = getItemValue(id + "-date");

View File

@@ -25,7 +25,7 @@ class LogingDaily : public IoTItem {
String prevDate = ""; String prevDate = "";
bool firstTimeInit = true; bool firstTimeInit = true;
long interval; // long interval;
public: public:
LogingDaily(String parameters) : IoTItem(parameters) { LogingDaily(String parameters) : IoTItem(parameters) {
@@ -40,8 +40,9 @@ class LogingDaily : public IoTItem {
points = 365; points = 365;
SerialPrint("E", F("LogingDaily"), "'" + id + "' user set more points than allowed, value reset to 365"); SerialPrint("E", F("LogingDaily"), "'" + id + "' user set more points than allowed, value reset to 365");
} }
jsonRead(parameters, F("int"), interval); long interval;
interval = interval * 1000 * 60; // приводим к милисекундам jsonRead(parameters, F("int"), interval); // в минутах
setInterval(interval * 60);
} }
void doByInterval() { void doByInterval() {
@@ -225,16 +226,16 @@ class LogingDaily : public IoTItem {
return ""; return "";
} }
void loop() { // void loop() {
if (enableDoByInt) { // if (enableDoByInt) {
currentMillis = millis(); // currentMillis = millis();
difference = currentMillis - prevMillis; // difference = currentMillis - prevMillis;
if (difference >= interval) { // if (difference >= interval) {
prevMillis = millis(); // prevMillis = millis();
this->doByInterval(); // this->doByInterval();
} // }
} // }
} // }
// просто максимальное количество точек // просто максимальное количество точек
int calculateMaxCount() { int calculateMaxCount() {

View File

@@ -11,22 +11,23 @@ class Weather : public IoTItem
private: private:
String _location; String _location;
String _param; String _param;
long interval; // long interval;
public: public:
Weather(String parameters) : IoTItem(parameters) Weather(String parameters) : IoTItem(parameters)
{ {
_location = jsonReadStr(parameters, "location"); _location = jsonReadStr(parameters, "location");
_param = jsonReadStr(parameters, "param"); _param = jsonReadStr(parameters, "param");
jsonRead(parameters, F("int"), interval); long interval;
interval = interval * 1000 * 60 * 60; // интервал проверки погоды в часах jsonRead(parameters, F("int"), interval); // интервал проверки погоды в часах
setInterval(interval * 60 * 60);
} }
void getWeather() void getWeather()
{ {
String ret; String ret;
if (WiFi.status() == WL_CONNECTED) if (isNetworkActive())
{ {
// char c; // char c;
String payload; String payload;
@@ -113,19 +114,21 @@ public:
regEvent(value.valS, "Weather"); regEvent(value.valS, "Weather");
} }
} }
void loop()
{ // void loop()
if (enableDoByInt) // {
{ // if (enableDoByInt)
currentMillis = millis(); // {
difference = currentMillis - prevMillis; // currentMillis = millis();
if (difference >= interval) // difference = currentMillis - prevMillis;
{ // if (difference >= interval)
prevMillis = millis(); // {
this->doByInterval(); // prevMillis = millis();
} // this->doByInterval();
} // }
} // }
// }
IoTValue execute(String command, std::vector<IoTValue> &param) IoTValue execute(String command, std::vector<IoTValue> &param)
{ {
if (command == "get") if (command == "get")

View File

@@ -11,11 +11,11 @@ void SerialPrint(const String& errorLevel, const String& module, const String& m
tosend += msg; tosend += msg;
Serial.println(tosend); Serial.println(tosend);
if (isNetworkActive()) { // if (isNetworkActive()) { // все проверки происходят в sendStringToWs()
if (jsonReadInt(settingsFlashJson, F("log")) != 0) { if (jsonReadInt(settingsFlashJson, F("log")) != 0) {
sendStringToWs(F("corelg"), tosend, -1); sendStringToWs(F("corelg"), tosend, -1);
}
} }
// }
if (errorLevel == "E") { if (errorLevel == "E") {
cleanString(tosend); cleanString(tosend);

View File

@@ -20,7 +20,7 @@ void updateDeviceStatus() {
// jsonRead(settingsFlashJson, F("serverip"), serverIP); // jsonRead(settingsFlashJson, F("serverip"), serverIP);
String url = serverIP + F("/projects/esprebootstat.php"); String url = serverIP + F("/projects/esprebootstat.php");
// SerialPrint("i", "Stat", "url " + url); // SerialPrint("i", "Stat", "url " + url);
if ((WiFi.status() == WL_CONNECTED)) { if ((isNetworkActive())) {
WiFiClient client; WiFiClient client;
HTTPClient http; HTTPClient http;
http.begin(client, url); http.begin(client, url);

View File

@@ -171,40 +171,31 @@ boolean RouterFind(std::vector<String> jArray)
return res; return res;
} }
// boolean isNetworkActive() { boolean isNetworkActive() {
// return WiFi.status() == WL_CONNECTED; return WiFi.status() == WL_CONNECTED;
// } }
uint8_t RSSIquality() uint8_t getNumAPClients() {
{ return WiFi.softAPgetStationNum();
uint8_t res = 0; }
if (WiFi.status() == WL_CONNECTED)
{ uint8_t RSSIquality() {
int rssi = WiFi.RSSI(); uint8_t res = 0;
if (rssi >= -50) if (isNetworkActive()) {
{ int rssi = WiFi.RSSI();
res = 6; //"Excellent"; if (rssi >= -50) {
} res = 6; //"Excellent";
else if (rssi < -50 && rssi >= -60) } else if (rssi < -50 && rssi >= -60) {
{ res = 5; //"Very good";
res = 5; //"Very good"; } else if (rssi < -60 && rssi >= -70) {
} res = 4; //"Good";
else if (rssi < -60 && rssi >= -70) } else if (rssi < -70 && rssi >= -80) {
{ res = 3; //"Low";
res = 4; //"Good"; } else if (rssi < -80 && rssi > -100) {
} res = 2; //"Very low";
else if (rssi < -70 && rssi >= -80) } else if (rssi <= -100) {
{ res = 1; //"No signal";
res = 3; //"Low"; }
} }
else if (rssi < -80 && rssi > -100) return res;
{
res = 2; //"Very low";
}
else if (rssi <= -100)
{
res = 1; //"No signal";
}
}
return res;
} }