diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index dfe07704..00000000 --- a/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..65469d13 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch +lib/libraies-master + diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000..e80666bf --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..4f7fce41 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,23 @@ +{ + "terminal.integrated.env.windows": { + "PATH": "C:\\Users\\ytrikoz\\.platformio\\penv\\Scripts;C:\\Users\\ytrikoz\\.platformio\\penv;C:\\Program Files (x86)\\Borland\\Delphi7\\Bin;C:\\Program Files (x86)\\Borland\\Delphi7\\Projects\\Bpl\\;C:\\WINDOWS\\system32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\;C:\\WINDOWS\\System32\\OpenSSH\\;C:\\Program Files\\Git\\cmd\\;c:\\android-studio\\jre\\jre\\bin\\;C:\\Program Files (x86)\\Microsoft SQL Server\\150\\DTS\\Binn\\;C:\\Front\\Shared\\;C:\\Program Files (x86)\\Plantronics\\Spokes3G\\;C:\\Program Files\\Microsoft SQL Server\\130\\Tools\\Binn\\;C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\170\\Tools\\Binn\\;C:\\Program Files\\nodejs\\;C:\\ProgramData\\chocolatey\\bin;C:\\Program Files\\dotnet\\;C:\\Users\\ytrikoz\\AppData\\Local\\Microsoft\\WindowsApps;C:\\Users\\ytrikoz\\AppData\\Local\\Programs\\Microsoft VS Code\\bin;C:\\Users\\ytrikoz\\AppData\\Roaming\\npm;C:\\MinGW\\bin;;C:\\Program Files (x86)\\West Wind Html Help Builder;C:\\Program Files (x86)\\Borland\\Delphi7\\Bin;C:\\Program Files (x86)\\Borland\\Delphi7\\Projects\\Bpl\\;C:\\WINDOWS\\system32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\;C:\\WINDOWS\\System32\\OpenSSH\\;C:\\Program Files\\Git\\cmd\\;c:\\android-studio\\jre\\jre\\bin\\;C:\\Program Files (x86)\\Microsoft SQL Server\\150\\DTS\\Binn\\;C:\\Front\\Shared\\;C:\\Program Files (x86)\\Plantronics\\Spokes3G\\;C:\\Program Files\\Microsoft SQL Server\\130\\Tools\\Binn\\;C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\170\\Tools\\Binn\\;C:\\Program Files\\nodejs\\;C:\\ProgramData\\chocolatey\\bin;C:\\Program Files\\dotnet\\;C:\\Users\\ytrikoz\\AppData\\Local\\Microsoft\\WindowsApps;C:\\Users\\ytrikoz\\AppData\\Local\\Programs\\Microsoft VS Code\\bin;C:\\Users\\ytrikoz\\AppData\\Roaming\\npm;C:\\MinGW\\bin;;C:\\Program Files (x86)\\West Wind Html Help Builder", + "PLATFORMIO_CALLER": "vscode" + }, + "files.associations": { + "*.cpp": "cpp", + "functional": "cpp", + "*.tcc": "cpp", + "optional": "cpp", + "ratio": "cpp", + "system_error": "cpp", + "array": "cpp", + "regex": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "bitset": "cpp", + "chrono": "cpp", + "algorithm": "cpp", + "random": "cpp" + } +} \ No newline at end of file diff --git a/CH341SER_WIN_3.5.ZIP b/CH341SER_WIN_3.5.ZIP deleted file mode 100644 index 0850ee30..00000000 Binary files a/CH341SER_WIN_3.5.ZIP and /dev/null differ diff --git a/Cmd.ino b/Cmd.ino deleted file mode 100644 index 6e1b58a1..00000000 --- a/Cmd.ino +++ /dev/null @@ -1,599 +0,0 @@ -void CMD_init() { - - sCmd.addCommand("button", button); - sCmd.addCommand("buttonSet", buttonSet); - sCmd.addCommand("buttonChange", buttonChange); - - sCmd.addCommand("pinSet", pinSet); - sCmd.addCommand("pinChange", pinChange); - - sCmd.addCommand("pwm", pwm); - sCmd.addCommand("pwmSet", pwmSet); - - sCmd.addCommand("switch", switch_); - -#ifdef analog_enable - sCmd.addCommand("analog", analog); -#endif -#ifdef level_enable - sCmd.addCommand("level", level); -#endif -#ifdef dallas_enable - sCmd.addCommand("dallas", dallas); -#endif -#ifdef dht_enable - sCmd.addCommand("dhtT", dhtT); - sCmd.addCommand("dhtH", dhtH); - sCmd.addCommand("dhtPerception", dhtP); - sCmd.addCommand("dhtComfort", dhtC); - sCmd.addCommand("dhtDewpoint", dhtD); -#endif - -#ifdef bmp_enable - sCmd.addCommand("bmp280T", bmp280T); - sCmd.addCommand("bmp280P", bmp280P); -#endif - -#ifdef bme_enable - sCmd.addCommand("bme280T", bme280T); - sCmd.addCommand("bme280P", bme280P); - sCmd.addCommand("bme280H", bme280H); - sCmd.addCommand("bme280A", bme280A); -#endif - -#ifdef stepper_enable - sCmd.addCommand("stepper", stepper); - sCmd.addCommand("stepperSet", stepperSet); -#endif - -#ifdef servo_enable - sCmd.addCommand("servo", servo_); - sCmd.addCommand("servoSet", servoSet); -#endif - -#ifdef serial_enable - sCmd.addCommand("serialBegin", serialBegin); - sCmd.addCommand("serialWrite", serialWrite); -#endif - -#ifdef logging_enable - sCmd.addCommand("logging", logging); -#endif - - sCmd.addCommand("inputDigit", inputDigit); - sCmd.addCommand("digitSet", digitSet); - - sCmd.addCommand("inputTime", inputTime); - sCmd.addCommand("timeSet", timeSet); - - sCmd.addCommand("timerStart", timerStart); - sCmd.addCommand("timerStop", timerStop); - - sCmd.addCommand("text", text); - sCmd.addCommand("textSet", textSet); - - sCmd.addCommand("mqtt", mqttOrderSend); - sCmd.addCommand("http", httpOrderSend); - -#ifdef push_enable - sCmd.addCommand("push", pushControl); -#endif - - sCmd.addCommand("update", update_firmware); - sCmd.addCommand("firmware", firmware); - - - handle_time_init(); -} - - - -//========================================================================================================== -//==========================================Модуль кнопок=================================================== -void button() { - - String button_number = sCmd.next(); - String button_param = sCmd.next(); - String widget_name = sCmd.next(); - String page_name = sCmd.next(); - String start_state = sCmd.next(); - String page_number = sCmd.next(); - - jsonWriteStr(optionJson, "button_param" + button_number, button_param); - jsonWriteStr(configJson, "button" + button_number, start_state); - - if (isDigitStr (button_param)) { - pinMode(button_param.toInt(), OUTPUT); - digitalWrite(button_param.toInt(), start_state.toInt()); - } - - if (button_param == "scenario") { - jsonWriteStr(configSetup, "scenario", start_state); - Scenario_init(); - saveConfig(); - } - - if (button_param.indexOf("line") != -1) { - String str = button_param; - while (str.length() != 0) { - if (str == "") return; - String tmp = selectToMarker (str, ","); //line1, - String number = deleteBeforeDelimiter(tmp, "e"); //1, - number.replace(",", ""); - Serial.println(number); - int number_int = number.toInt(); - scenario_line_status[number_int] = start_state.toInt(); - str = deleteBeforeDelimiter(str, ","); - } - } - createWidget (widget_name, page_name, page_number, "widgets/widget.toggle.json", "button" + button_number); -} - -void buttonSet() { - - String button_number = sCmd.next(); - String button_state = sCmd.next(); - String button_param = jsonReadStr(optionJson, "button_param" + button_number); - - if (button_param != "na" || button_param != "scenario" || button_param.indexOf("line") != -1) { - digitalWrite(button_param.toInt(), button_state.toInt()); - } - - if (button_param == "scenario") { - jsonWriteStr(configSetup, "scenario", button_state); - Scenario_init(); - saveConfig(); - } - - if (button_param.indexOf("line") != -1) { - String str = button_param; - while (str.length() != 0) { - if (str == "") return; - String tmp = selectToMarker (str, ","); //line1, - String number = deleteBeforeDelimiter(tmp, "e"); //1, - number.replace(",", ""); - Serial.println(number); - int number_int = number.toInt(); - scenario_line_status[number_int] = button_state.toInt(); - str = deleteBeforeDelimiter(str, ","); - } - } - - eventGen ("button", button_number); - - jsonWriteStr(configJson, "button" + button_number, button_state); - sendSTATUS("button" + button_number, button_state); -} - -void buttonChange() { - String button_number = sCmd.next(); - String current_state = jsonReadStr(configJson, "button" + button_number); - if (current_state == "1") { - current_state = "0"; - } else if (current_state == "0") { - current_state = "1"; - } - order_loop += "buttonSet " + button_number + " " + current_state + ","; - jsonWriteStr(configJson, "button" + button_number, current_state); - sendSTATUS("button" + button_number, current_state); -} - -void pinSet() { - String pin_number = sCmd.next(); - String pin_state = sCmd.next(); - pinMode(pin_number.toInt(), OUTPUT); - digitalWrite(pin_number.toInt(), pin_state.toInt()); -} - -void pinChange() { - String pin_number = sCmd.next(); - pinMode(pin_number.toInt(), OUTPUT); - digitalWrite(pin_number.toInt(), !digitalRead(pin_number.toInt())); -} -//================================================================================================================== -//==========================================Модуль управления ШИМ=================================================== -void pwm() { - - static boolean flag = true; - String pwm_number = sCmd.next(); - String pwm_pin = sCmd.next(); - String widget_name = sCmd.next(); - widget_name.replace("#", " "); - String page_name = sCmd.next(); - String start_state = sCmd.next(); - String page_number = sCmd.next(); - - - uint8_t pwm_pin_int = pwm_pin.toInt(); - jsonWriteStr(optionJson, "pwm_pin" + pwm_number, pwm_pin); - pinMode(pwm_pin_int, INPUT); - analogWrite(pwm_pin_int, start_state.toInt()); - //analogWriteFreq(32000); - jsonWriteStr(configJson, "pwm" + pwm_number, start_state); - - createWidget (widget_name, page_name, page_number, "widgets/widget.range.json", "pwm" + pwm_number); -} - -void pwmSet() { - - String pwm_number = sCmd.next(); - String pwm_state = sCmd.next(); - int pwm_state_int = pwm_state.toInt(); - - int pin = jsonReadInt(optionJson, "pwm_pin" + pwm_number); - analogWrite(pin, pwm_state_int); - - eventGen ("pwm", pwm_number); - - jsonWriteStr(configJson, "pwm" + pwm_number, pwm_state); - sendSTATUS("pwm" + pwm_number, pwm_state); -} -//================================================================================================================== -//==========================================Модуль физической кнопки================================================ -void switch_ () { - - String switch_number = sCmd.next(); - String switch_pin = sCmd.next(); - String switch_delay = sCmd.next(); - - buttons[switch_number.toInt()].attach(switch_pin.toInt()); - buttons[switch_number.toInt()].interval(switch_delay.toInt()); - but[switch_number.toInt()] = true; -} - -void handleButton() { - - static uint8_t switch_number = 1; - - if (but[switch_number]) { - buttons[switch_number].update(); - if (buttons[switch_number].fell()) { - - eventGen ("switch", String(switch_number)); - - jsonWriteStr(configJson, "switch" + String(switch_number), "1"); - } - if (buttons[switch_number].rose()) { - - eventGen ("switch", String(switch_number)); - - jsonWriteStr(configJson, "switch" + String(switch_number), "0"); - } - } - switch_number++; - if (switch_number == NUM_BUTTONS) switch_number = 0; -} - -//===================================================================================================================================== -//=========================================Добавление окна ввода цифры================================================================= -void inputDigit() { - String value_name = sCmd.next(); - String number = value_name.substring(5); - String widget_name = sCmd.next(); - widget_name.replace("#", " "); - String page_name = sCmd.next(); - page_name.replace("#", " "); - String start_state = sCmd.next(); - String page_number = sCmd.next(); - jsonWriteStr(configJson, "digit" + number, start_state); - createWidget (widget_name, page_name, page_number, "widgets/widget.inputNum.json", "digit" + number); -} -void digitSet() { - String number = sCmd.next(); - String value = sCmd.next(); - jsonWriteStr(configJson, "digit" + number, value); - sendSTATUS("digit" + number, value); -} -//===================================================================================================================================== -//=========================================Добавление окна ввода времени=============================================================== -void inputTime() { - String value_name = sCmd.next(); - String number = value_name.substring(4); - String widget_name = sCmd.next(); - widget_name.replace("#", " "); - String page_name = sCmd.next(); - page_name.replace("#", " "); - String start_state = sCmd.next(); - String page_number = sCmd.next(); - jsonWriteStr(configJson, "time" + number, start_state); - createWidget (widget_name, page_name, page_number, "widgets/widget.inputTime.json", "time" + number); -} -void timeSet() { - String number = sCmd.next(); - String value = sCmd.next(); - jsonWriteStr(configJson, "time" + number, value); - sendSTATUS("time" + number, value); -} - -void handle_time_init() { - ts.add(TIME, 1000, [&](void*) { - - String tmp = GetTime(); - jsonWriteStr(configJson, "time", tmp); - tmp.replace(":", "-"); - jsonWriteStr(configJson, "timenow", tmp); - eventGen ("timenow", ""); - - }, nullptr, true); -} - -//===================================================================================================================================== -//=========================================Добавление текстового виджета============================================================ -void text() { - - String number = sCmd.next(); - String widget_name = sCmd.next(); - String page_name = sCmd.next(); - String page_number = sCmd.next(); - - createWidget (widget_name, page_name, page_number, "widgets/widget.anyData.json", "text" + number); -} - - -void textSet() { - - String number = sCmd.next(); - String text = sCmd.next(); - text.replace("_", " "); - - if (text.indexOf("-time") >= 0) { - text.replace("-time", ""); - text.replace("#", " "); - String time = GetTime(); - time.replace(":", "."); - text = text + " " + GetDataDigital() + " " + time; - } - - jsonWriteStr(configJson, "text" + number, text); - sendSTATUS("text" + number, text); -} -//===================================================================================================================================== -//=========================================Модуль шагового мотора====================================================================== -#ifdef stepper_enable -//stepper 1 12 13 -void stepper() { - String stepper_number = sCmd.next(); - String pin_step = sCmd.next(); - String pin_dir = sCmd.next(); - - jsonWriteStr(optionJson, "stepper" + stepper_number, pin_step + " " + pin_dir); - pinMode(pin_step.toInt(), OUTPUT); - pinMode(pin_dir.toInt(), OUTPUT); -} - -//stepperSet 1 100 5 -void stepperSet() { - String stepper_number = sCmd.next(); - String steps = sCmd.next(); - jsonWriteStr(optionJson, "steps" + stepper_number, steps); - String stepper_speed = sCmd.next(); - String pin_step = selectToMarker (jsonReadStr(optionJson, "stepper" + stepper_number), " "); - String pin_dir = deleteBeforeDelimiter (jsonReadStr(optionJson, "stepper" + stepper_number), " "); - Serial.println(pin_step); - Serial.println(pin_dir); - if (steps.toInt() > 0) digitalWrite(pin_dir.toInt(), HIGH); - if (steps.toInt() < 0) digitalWrite(pin_dir.toInt(), LOW); - if (stepper_number == "1") { - ts.add(STEPPER1, stepper_speed.toInt(), [&](void*) { - int steps_int = abs(jsonReadInt(optionJson, "steps1") * 2); - static int count; - count++; - String pin_step = selectToMarker (jsonReadStr(optionJson, "stepper1"), " "); - digitalWrite(pin_step.toInt(), !digitalRead(pin_step.toInt())); - yield(); - if (count > steps_int) { - digitalWrite(pin_step.toInt(), LOW); - ts.remove(STEPPER1); - count = 0; - } - }, nullptr, true); - } - if (stepper_number == "2") { - ts.add(STEPPER2, stepper_speed.toInt(), [&](void*) { - int steps_int = abs(jsonReadInt(optionJson, "steps2") * 2); - static int count; - count++; - String pin_step = selectToMarker (jsonReadStr(optionJson, "stepper2"), " "); - digitalWrite(pin_step.toInt(), !digitalRead(pin_step.toInt())); - yield(); - if (count > steps_int) { - digitalWrite(pin_step.toInt(), LOW); - ts.remove(STEPPER2); - count = 0; - } - }, nullptr, true); - } -} -#endif -//==================================================================================================================================================== -//=================================================================Сервоприводы======================================================================= -#ifdef servo_enable -//servo 1 13 50 Мой#сервопривод Сервоприводы 0 100 0 180 2 -void servo_() { - String servo_number = sCmd.next(); - String servo_pin = sCmd.next(); - String start_state = sCmd.next(); - int start_state_int = start_state.toInt(); - String widget_name = sCmd.next(); - String page_name = sCmd.next(); - - String min_value = sCmd.next(); - String max_value = sCmd.next(); - - String min_deg = sCmd.next(); - String max_deg = sCmd.next(); - - String page_number = sCmd.next(); - - jsonWriteStr(optionJson, "servo_pin" + servo_number, servo_pin); - start_state_int = map(start_state_int, min_value.toInt(), max_value.toInt(), min_deg.toInt(), max_deg.toInt()); - - if (servo_number == "1") { -#ifdef ESP8266 - myServo1.attach(servo_pin.toInt()); - myServo1.write(start_state_int); -#endif -#ifdef ESP32 - myServo1.attach(servo_pin.toInt(), 500, 2400); - myServo1.write(start_state_int); -#endif - } - - if (servo_number == "2") { -#ifdef ESP8266 - myServo2.attach(servo_pin.toInt()); - myServo2.write(start_state_int); -#endif -#ifdef ESP32 - myServo2.attach(servo_pin.toInt(), 500, 2400); - myServo2.write(start_state_int); -#endif - } - - jsonWriteStr(optionJson, "s_min_val" + servo_number, min_value); - jsonWriteStr(optionJson, "s_max_val" + servo_number, max_value); - jsonWriteStr(optionJson, "s_min_deg" + servo_number, min_deg); - jsonWriteStr(optionJson, "s_max_deg" + servo_number, max_deg); - - jsonWriteStr(configJson, "servo" + servo_number, start_state); - - createWidgetParam (widget_name, page_name, page_number, "widgets/widget.range.json", "servo" + servo_number, "min", min_value, "max", max_value, "k", "1"); -} - -void servoSet() { - String servo_number = sCmd.next(); - String servo_state = sCmd.next(); - int servo_state_int = servo_state.toInt(); - - int pin = jsonReadInt(optionJson, "servo_pin" + servo_number); - - servo_state_int = map(servo_state_int, - jsonReadInt(optionJson, "s_min_val" + servo_number), - jsonReadInt(optionJson, "s_max_val" + servo_number), - jsonReadInt(optionJson, "s_min_deg" + servo_number), - jsonReadInt(optionJson, "s_max_deg" + servo_number)); - - if (servo_number == "1") { -#ifdef ESP8266 - myServo1.write(servo_state_int); -#endif -#ifdef ESP32 - myServo1.write(servo_state_int); -#endif - } - - if (servo_number == "2") { -#ifdef ESP8266 - myServo2.write(servo_state_int); -#endif -#ifdef ESP32 - myServo2.write(servo_state_int); -#endif - } - - //Serial.println(servo_state_int); - - eventGen ("servo", servo_number); - - jsonWriteStr(configJson, "servo" + servo_number, servo_state); - sendSTATUS("servo" + servo_number, servo_state); -} -#endif -//==================================================================================================================================================== -//===================================================================================serial=========================================================== -#ifdef serial_enable -void serialBegin() { - //String s_speed = sCmd.next(); - //String rxPin = sCmd.next(); - //String txPin = sCmd.next(); - //SoftwareSerial mySerial(rxPin.toInt(), txPin.toInt()); - //mySerial.begin(s_speed.toInt()); -} - -void serialWrite() { - //String text = sCmd.next(); - //mySerial.println(text); -} -#endif -//==================================================================================================================================================== -//=================================================Глобальные команды удаленного управления=========================================================== - -void mqttOrderSend() { - - String id = sCmd.next(); - String order = sCmd.next(); - - String all_line = jsonReadStr(configSetup, "mqttPrefix") + "/" + id + "/order"; - //Serial.print(all_line); - //Serial.print("->"); - //Serial.println(order); - int send_status = client_mqtt.publish (all_line.c_str(), order.c_str(), false); -} - -void httpOrderSend() { - - String ip = sCmd.next(); - String order = sCmd.next(); - order.replace("_", "%20"); - String url = "http://" + ip + "/cmd?command=" + order; - getURL(url); -} - -void update_firmware() { - upgrade = true; -} - -void firmware() { - String widget_name = sCmd.next(); - String page_name = sCmd.next(); - String page_number = sCmd.next(); - jsonWriteStr(configJson, "firm1", firmware_version); - choose_widget_and_create(widget_name, page_name, page_number, "any-data", "firm1"); -} - -//============================================================================================================================== -//============================выполнение команд (в лупе) по очереди из строки order============================================= -void handleCMD_loop() { - - if (order_loop != "") { - - String tmp = selectToMarker(order_loop, ","); //выделяем из страки order первую команду rel 5 1, - sCmd.readStr(tmp); //выполняем первую команду - Serial.println("[ORDER] => " + order_loop); - order_loop = deleteBeforeDelimiter(order_loop, ","); //осекаем выполненную команду - } -} - -//======================================================================================================================================= -//======================================================================================================================================= -void txtExecution(String file) { - - String command_all = readFile(file, 2048) + "\r\n"; - - command_all.replace("\r\n", "\n"); - command_all.replace("\r", "\n"); - - while (command_all.length() != 0) { - - String tmp = selectToMarker (command_all, "\n"); - sCmd.readStr(tmp); - command_all = deleteBeforeDelimiter(command_all, "\n"); - } - command_all = ""; -} - -void stringExecution(String str) { - - str = str + "\r\n"; - - str.replace("\r\n", "\n"); - str.replace("\r", "\n"); - - while (str.length() != 0) { - - String tmp = selectToMarker (str, "\n"); - sCmd.readStr(tmp); - - str = deleteBeforeDelimiter(str, "\n"); - } -} diff --git a/ESP32FS.7z b/ESP32FS.7z deleted file mode 100644 index 68ebe690..00000000 Binary files a/ESP32FS.7z and /dev/null differ diff --git a/ESP8266FS.7z b/ESP8266FS.7z deleted file mode 100644 index 94e2111c..00000000 Binary files a/ESP8266FS.7z and /dev/null differ diff --git a/FS.ino b/FS.ino deleted file mode 100644 index 5b4b5ee6..00000000 --- a/FS.ino +++ /dev/null @@ -1,38 +0,0 @@ -void File_system_init() { - - Serial.begin(115200); - //Serial.setDebugOutput(true); - Serial.println("--------------started----------------"); - //-------------------------------------------------------------- - SPIFFS.begin(); - configSetup = readFile("config.json", 4096); - configSetup.replace(" ", ""); - configSetup.replace("\r\n", ""); - Serial.println(configSetup); - jsonWriteStr(configJson, "name", jsonReadStr(configSetup, "name")); - jsonWriteStr(configJson, "lang", jsonReadStr(configSetup, "lang")); - - -#ifdef ESP32 - uint32_t chipID_u = ESP.getEfuseMac(); - chipID = String(chipID_u); - jsonWriteStr(configSetup, "chipID", chipID); -#endif - -#ifdef ESP8266 - chipID = String( ESP.getChipId() ) + "-" + String(ESP.getFlashChipId()); - jsonWriteStr(configSetup, "chipID", chipID); - Serial.setDebugOutput(0); -#endif - - jsonWriteStr(configSetup, "firmware_version", firmware_version); - - prex = jsonReadStr(configSetup, "mqttPrefix") + "/" + chipID; - Serial.println(chipID); - -} - -void get_esp_info() { - - -} diff --git a/Init.ino b/Init.ino deleted file mode 100644 index 49922054..00000000 --- a/Init.ino +++ /dev/null @@ -1,246 +0,0 @@ -void All_init() { - - server.on("/init", HTTP_GET, [](AsyncWebServerRequest * request) { - String value; - if (request->hasArg("arg")) { - value = request->getParam("arg")->value(); - } - if (value == "0") { //выкл сценариев - jsonWriteStr(configSetup, "scenario", value); - saveConfig(); - Scenario_init(); - request->send(200, "text/text", "OK"); - } - if (value == "1") { //вкл сценариев - jsonWriteStr(configSetup, "scenario", value); - saveConfig(); - Scenario_init(); - request->send(200, "text/text", "OK"); - } - if (value == "2") { //инициализация - Device_init(); - request->send(200, "text/text", "OK"); - } - if (value == "3") { -#ifdef logging_enable - clean_log_date(); -#endif - request->send(200, "text/text", "OK"); - } - if (value == "4") { - Scenario_init(); - request->send(200, "text/text", "OK"); - } - if (value == "5") { - i2c_scanning = true; - request->redirect("/?utilities"); - } - }); - - prsets_init(); - Device_init(); - Scenario_init(); - Timer_countdown_init(); -} - -void Device_init() { - - logging_value_names_list = ""; - enter_to_logging_counter = LOG1 - 1; - - analog_value_names_list = ""; - enter_to_analog_counter = 0; - - level_value_name = ""; - - dhtT_value_name = ""; - dhtH_value_name = ""; - - bmp280T_value_name = ""; - bmp280P_value_name = ""; - - bme280T_value_name = ""; - bme280P_value_name = ""; - bme280H_value_name = ""; - bme280A_value_name = ""; - - int array_sz = sizeof(sensors_reading_map) / sizeof(sensors_reading_map[0]); - - for (int i = 0; i <= array_sz; i++) { - sensors_reading_map[i] = 0; - } - - for (int i = LOG1; i <= LOG5; i++) { - ts.remove(i); - } - -#ifdef layout_in_ram - all_widgets = ""; -#else - SPIFFS.remove("/layout.txt"); -#endif - - txtExecution("firmware.c.txt"); - //outcoming_date(); -} -//-------------------------------сценарии----------------------------------------------------- - -void Scenario_init() { - if (jsonReadStr(configSetup, "scenario") == "1") { - scenario = readFile("firmware.s.txt", 2048); - } -} - -void prsets_init() { - server.on("/preset", HTTP_GET, [](AsyncWebServerRequest * request) { - String value; - if (request->hasArg("arg")) { - value = request->getParam("arg")->value(); - } - if (value == "1") { - writeFile("firmware.c.txt", readFile("configs/relay.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/relay.s.txt", 2048)); - } - if (value == "2") { - writeFile("firmware.c.txt", readFile("configs/relay_t.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/relay_t.s.txt", 2048)); - } - if (value == "3") { - writeFile("firmware.c.txt", readFile("configs/relay_c.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/relay_c.s.txt", 2048)); - } - if (value == "4") { - writeFile("firmware.c.txt", readFile("configs/relay_s.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/relay_s.s.txt", 2048)); - } - if (value == "5") { - writeFile("firmware.c.txt", readFile("configs/relay_sw.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/relay_sw.s.txt", 2048)); - } - if (value == "6") { - writeFile("firmware.c.txt", readFile("configs/relay_br.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/relay_br.s.txt", 2048)); - } - if (value == "7") { - writeFile("firmware.c.txt", readFile("configs/relay_sr.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/relay_sr.s.txt", 2048)); - } - if (value == "8") { - writeFile("firmware.c.txt", readFile("configs/pwm.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/pwm.s.txt", 2048)); - } - if (value == "9") { - writeFile("firmware.c.txt", readFile("configs/dht11.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/dht11.s.txt", 2048)); - } - if (value == "10") { - writeFile("firmware.c.txt", readFile("configs/dht22.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/dht22.s.txt", 2048)); - } - if (value == "11") { - writeFile("firmware.c.txt", readFile("configs/analog.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/analog.s.txt", 2048)); - } - if (value == "12") { - writeFile("firmware.c.txt", readFile("configs/dallas.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/dallas.s.txt", 2048)); - } - if (value == "13") { - writeFile("firmware.c.txt", readFile("configs/termostat.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/termostat.s.txt", 2048)); - } - if (value == "14") { - writeFile("firmware.c.txt", readFile("configs/level.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/level.s.txt", 2048)); - } - if (value == "15") { - writeFile("firmware.c.txt", readFile("configs/moution_r.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/moution_r.s.txt", 2048)); - } - if (value == "16") { - writeFile("firmware.c.txt", readFile("configs/moution_s.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/moution_s.s.txt", 2048)); - } - if (value == "17") { - writeFile("firmware.c.txt", readFile("configs/stepper.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/stepper.s.txt", 2048)); - } - if (value == "18") { - writeFile("firmware.c.txt", readFile("configs/servo.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/servo.s.txt", 2048)); - } - if (value == "19") { - writeFile("firmware.c.txt", readFile("configs/firmware.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/firmware.s.txt", 2048)); - } - Device_init(); - Scenario_init(); - request->redirect("/?configuration"); - }); -} - -void up_time() { - uint32_t ss = millis() / 1000; - uint32_t mm = ss / 60; - uint32_t hh = mm / 60; - uint32_t dd = hh / 24; - - String out = ""; - - if (ss != 0) { - out = "[i] uptime = " + String(ss) + " sec"; - jsonWriteStr(configJson, "uptime", String(ss) + " sec"); - } - if (mm != 0) { - out = "[i] uptime = " + String(mm) + " min"; - jsonWriteStr(configJson, "uptime", String(mm) + " min"); - } - if (hh != 0) { - out = "[i] uptime = " + String(hh) + " hours"; - jsonWriteStr(configJson, "uptime", String(hh) + " hours"); - } - if (dd != 0) { - out = "[i] uptime = " + String(dd) + " days"; - jsonWriteStr(configJson, "uptime", String(dd) + " days"); - } - Serial.println(out + ", mqtt_lost_error: " + String(mqtt_lost_error) + ", wifi_lost_error: " + String(wifi_lost_error)); -} - -void statistics_init() { - ts.add(STATISTICS, statistics_update, [&](void*) { - - statistics(); - - }, nullptr, true); -} - -void statistics() { - if (WiFi.status() == WL_CONNECTED) { - String urls = "http://backup.privet.lv/visitors/?"; - //----------------------------------------------------------------- - urls += WiFi.macAddress().c_str(); - urls += "&"; - //----------------------------------------------------------------- -#ifdef ESP8266 - urls += "iot-manager_esp8266"; -#endif -#ifdef ESP32 - urls += "iot-manager_esp32"; -#endif - urls += "&"; - //----------------------------------------------------------------- -#ifdef ESP8266 - urls += ESP.getResetReason(); - //Serial.println(ESP.getResetReason()); -#endif -#ifdef ESP32 - urls += "Power on"; -#endif - urls += "&"; - //----------------------------------------------------------------- - urls += "ver: " + firmware_version; - //----------------------------------------------------------------- - String stat = getURL(urls); - //Serial.println(stat); - } -} diff --git a/Logging.ino b/Logging.ino deleted file mode 100644 index 8f25bad1..00000000 --- a/Logging.ino +++ /dev/null @@ -1,153 +0,0 @@ -#ifdef logging_enable -//===============================================Логирование============================================================ -//logging temp1 1 10 Температура Датчики 2 -void logging() { - String value_name = sCmd.next(); - String period_min = sCmd.next(); - String maxCount = sCmd.next(); - String widget_name = sCmd.next(); - widget_name.replace("#", " "); - String page_name = sCmd.next(); - String page_number = sCmd.next(); - logging_value_names_list += value_name + ","; - enter_to_logging_counter++; //считаем количество входов в эту функцию - jsonWriteStr(optionJson, value_name + "_c", maxCount); //создаем в файловой системе переменную количества точек на графике с отметкой _c что значит count - createChart (widget_name, page_name, page_number, "widgets/widget.chart.json", value_name + "_ch", maxCount); //создаем график в приложении с топиком _ch /prefix/3234045-1589487/value_name_ch - if (enter_to_logging_counter == LOG1) { - ts.add(LOG1, period_min.toInt() * 1000 * 60, [&](void*) { - String tmp_buf_1 = selectFromMarkerToMarker(logging_value_names_list, ",", 0); - deleteOldDate("log." + tmp_buf_1 + ".txt", jsonReadInt(optionJson, tmp_buf_1 + "_c"), jsonReadStr(configJson, tmp_buf_1)); - Serial.println("[i] LOGGING for sensor '" + tmp_buf_1 + "' done"); - }, nullptr, false); - } - if (enter_to_logging_counter == LOG2) { - ts.add(LOG2, period_min.toInt() * 1000 * 60, [&](void*) { - String tmp_buf_2 = selectFromMarkerToMarker(logging_value_names_list, ",", 1); - deleteOldDate("log." + tmp_buf_2 + ".txt", jsonReadInt(optionJson, tmp_buf_2 + "_c"), jsonReadStr(configJson, tmp_buf_2)); - Serial.println("[i] LOGGING for sensor '" + tmp_buf_2 + "' done"); - }, nullptr, false); - } - if (enter_to_logging_counter == LOG3) { - ts.add(LOG3, period_min.toInt() * 1000 * 60, [&](void*) { - String tmp_buf_3 = selectFromMarkerToMarker(logging_value_names_list, ",", 2); - deleteOldDate("log." + tmp_buf_3 + ".txt", jsonReadInt(optionJson, tmp_buf_3 + "_c"), jsonReadStr(configJson, tmp_buf_3)); - Serial.println("[i] LOGGING for sensor '" + tmp_buf_3 + "' done"); - }, nullptr, false); - } - if (enter_to_logging_counter == LOG4) { - ts.add(LOG4, period_min.toInt() * 1000 * 60, [&](void*) { - String tmp_buf_4 = selectFromMarkerToMarker(logging_value_names_list, ",", 3); - deleteOldDate("log." + tmp_buf_4 + ".txt", jsonReadInt(optionJson, tmp_buf_4 + "_c"), jsonReadStr(configJson, tmp_buf_4)); - Serial.println("[i] LOGGING for sensor '" + tmp_buf_4 + "' done"); - }, nullptr, false); - } - if (enter_to_logging_counter == LOG5) { - ts.add(LOG5, period_min.toInt() * 1000 * 60, [&](void*) { - String tmp_buf_5 = selectFromMarkerToMarker(logging_value_names_list, ",", 4); - deleteOldDate("log." + tmp_buf_5 + ".txt", jsonReadInt(optionJson, tmp_buf_5 + "_c"), jsonReadStr(configJson, tmp_buf_5)); - Serial.println("[i] LOGGING for sensor '" + tmp_buf_5 + "' done"); - }, nullptr, false); - } -} - -//=========================================Удаление стрых данных и запись новых================================================================== -void deleteOldDate(String file, int seted_number_of_lines, String date_to_add) { - String log_date = readFile(file, 5000); - int current_number_of_lines = count(log_date, "\r\n"); - Serial.println("=====> [i] in log file " + file + " " + current_number_of_lines + " lines"); - - if (current_number_of_lines > seted_number_of_lines + 1) { - SPIFFS.remove("/" + file); - current_number_of_lines = 0; - } - if (current_number_of_lines == 0) { - SPIFFS.remove("/" + file); - current_number_of_lines = 0; - } - if (current_number_of_lines > seted_number_of_lines) { - log_date = deleteBeforeDelimiter(log_date, "\r\n"); - if (GetTimeUnix() != "failed") { - log_date += GetTimeUnix() + " " + date_to_add + "\r\n"; - writeFile(file, log_date); - } - } else { - if (GetTimeUnix() != "failed") { - addFile(file, GetTimeUnix() + " " + date_to_add); - } - } - log_date = ""; -} - -//=========================================Выбор какие данные отправлять================================================================== -void choose_log_date_and_send() { - String all_line = logging_value_names_list; - while (all_line.length() != 0) { - String tmp = selectToMarker (all_line, ","); - sendLogData("log." + tmp + ".txt", tmp + "_ch"); - all_line = deleteBeforeDelimiter(all_line, ","); - } - all_line = ""; -} -//=========================================Отправка данных=================================================================================== -void sendLogData(String file, String topic) { - String log_date = readFile(file, 5000); - if (log_date != "Failed") { - log_date.replace("\r\n", "\n"); - log_date.replace("\r", "\n"); - String buf = "{}"; - String json_array; - String unix_time; - String value; - while (log_date.length() != 0) { - String tmp = selectToMarker (log_date, "\n"); - log_date = deleteBeforeDelimiter(log_date, "\n"); - unix_time = selectToMarker (tmp, " "); - jsonWriteInt(buf, "x", unix_time.toInt()); - value = deleteBeforeDelimiter(tmp, " "); - jsonWriteFloat(buf, "y1", value.toFloat()); - if (log_date.length() < 3) { - json_array += buf; - } else { - json_array += buf + ","; - } - buf = "{}"; - } - unix_time = ""; - value = ""; - log_date = ""; - json_array = "{\"status\":[" + json_array + "]}"; - Serial.println(json_array); - sendCHART(topic, json_array); - json_array = ""; - getMemoryLoad("[i] after send log date"); - } -} - -/* - //---------------------------------------------- - File configFile = SPIFFS.open("/" + file, "r"); - if (!configFile) { - return; - } - configFile.seek(0, SeekSet); //поставим курсор в начало файла - while (configFile.position() != configFile.size()) { - String tmp = configFile.readStringUntil('\r\n'); - String unix_time = selectToMarker (tmp, " "); - String value = deleteBeforeDelimiter(tmp, " "); - String final_line = "{\"status\":{\"x\":" + unix_time + ",\"y1\":" + value + "}}"; - //Serial.println(final_line); - sendCHART(topic, final_line); - } - getMemoryLoad("[i] after send log date"); -*/ -//=========================================Очистка данных=================================================================================== -void clean_log_date() { - String all_line = logging_value_names_list; - while (all_line.length() != 0) { - String tmp = selectToMarker (all_line, ","); - SPIFFS.remove("/log." + tmp + ".txt"); - all_line = deleteBeforeDelimiter(all_line, ","); - } - all_line = ""; -} -#endif diff --git a/README.md b/README.md deleted file mode 100644 index 9c112b87..00000000 --- a/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# esp32-esp8266_iot-manager_modules_firmware - -It is based on esp8266 and esp32 automation system. Each module has a web interface for its initial configuration. The modules are managed using the "iot manager" application. This application is released for both android and ios platform. The application connects to a MQTT broker, you can add several brokers and switch between them. All modules also connect to same broker. All esp8266 esp32 are combined and appear in the application as widgets. - -There are two configuration options in the web interface of the modules: - -1. Select a ready-made preset. - -The following presets are available: - -- On off relay -- On off relay according to the schedule specified in the application -- On off the relay after a period of time specified in the application -- On off relay groups on different devices with one button in the application -- Light switch module -- PWM controlled by the slider in the application -- Reading and logging analog input into graph with scaling function -- Reading and logging in the graph of the following sensors: - -DHT22, DHT33, DHT44, AM2302, RHT03 -DS18B20 -JSN-SR04T, HC-SR04, HY-SRF05 -BME280 BMP280 and other i2c sensors - --ds18b20 termostat controlled from application with graph (you can use any sensor for termostat any other supported). - -2. Configure with special scripts. A simple programming language was invented which can very flexibly configure the module. - -People who do not know how to program can use ready-made presets (option 1), and people who want to play with the system can use scripts (option 2). - -Scenarios: - -The web interface has the ability to configure Scenarios. An event occurs on one esp, and a reaction to this event can setup to occurs on another. - -Logging of sensors data in this project made with out any server. All data for graf storring in esp flash. You can look any time your sensor history for 2 - 3 days or week in mobile app in graf. And for this option needed only esp. - - diff --git a/Scenario.ino b/Scenario.ino deleted file mode 100644 index 52828b79..00000000 --- a/Scenario.ino +++ /dev/null @@ -1,94 +0,0 @@ -void handleScenario() { - - if (jsonReadStr(configSetup, "scenario") == "1") { - if ((jsonReadStr(optionJson, "scenario_status") != "")) { - int i = 0; - String str = scenario; //читаем переменную с сценариями (то что из файла на странице) - str += "\n"; - str.replace("\r\n", "\n"); - str.replace("\r", "\n"); - while (str.length() != 0) { - //----------------------------------------------------------------------------------------------------------------------- - String tmp = selectToMarker (str, "end"); //выделяем первый сценарий из файла вместе с командами - if (tmp == "") return; - i++; - - if (scenario_line_status[i] == 1) { - //Serial.println(i); - String condition = selectToMarker (tmp, "\n"); //выделяем первую строку самого сценария button1 = 1 (условие) - String param_name = selectFromMarkerToMarker(condition, " " , 0); - String order = jsonReadStr(optionJson, "scenario_status"); //читаем весь файл событий - String param = selectToMarker (order, ","); //читаем первое событие из файла событий - if (param_name == param) { //если поступившее событие равно событию заданному buttonSet1 в файле начинаем его обработку - - String sign = selectFromMarkerToMarker(condition, " " , 1); //читаем знак (=) - String value = selectFromMarkerToMarker(condition, " " , 2); //читаем значение (1) - if (value.indexOf("digit") != -1) { - // value = add_set(value); - value = jsonReadStr(configJson, value); - } - if (value.indexOf("time") != -1) { - // value = add_set(value); - value = jsonReadStr(configJson, value); - } - boolean flag = false; //если одно из значений совпало то только тогда начинаем выполнять комнады - if (sign == "=") { - if (jsonReadStr(configJson, param_name) == value) flag = true; - } - if (sign == "!=") { - if (jsonReadStr(configJson, param_name) != value) flag = true; - } - if (sign == "<") { - if (jsonReadStr(configJson, param_name).toInt() < value.toInt()) flag = true; - } - if (sign == ">") { - if (jsonReadStr(configJson, param_name).toInt() > value.toInt()) flag = true; - } - if (sign == ">=") { - if (jsonReadStr(configJson, param_name).toInt() >= value.toInt()) flag = true; - } - if (sign == "<=") { - if (jsonReadStr(configJson, param_name).toInt() <= value.toInt()) flag = true; - } - - if (flag) { - tmp = deleteBeforeDelimiter(tmp, "\n"); //удаляем строку самого сценария оставляя только команды - stringExecution(tmp); //выполняем все команды - - Serial.println("[SCENARIO] '" + condition + "'"); - //Serial.println(" " + tmp); - } - } - } - str = deleteBeforeDelimiter(str, "end\n"); //удаляем первый сценарий - //----------------------------------------------------------------------------------------------------------------------- - } - String tmp2 = jsonReadStr(optionJson, "scenario_status"); //читаем файл событий - tmp2 = deleteBeforeDelimiter(tmp2, ","); //удаляем выполненное событие - jsonWriteStr(optionJson, "scenario_status", tmp2); //записываем обновленный файл событий - i = 0; - } - } -} - -void eventGen (String event_name, String number) { //событие выглядит как имя плюс set плюс номер: button+Set+1 - - if (jsonReadStr(configSetup, "scenario") == "1") { - String tmp = jsonReadStr(optionJson, "scenario_status") ; //генерирование события - //Serial.println(event_name); - jsonWriteStr(optionJson, "scenario_status", tmp + event_name + number + ","); - } -} - -String add_set(String param_name) { - String num1 = param_name.substring(param_name.length() - 1); - String num2 = param_name.substring(param_name.length() - 2, param_name.length() - 1); - if (isDigitStr(num1) && isDigitStr(num2)) { - param_name = param_name.substring(0, param_name.length() - 2) + "Set" + num2 + num1; - } else { - if (isDigitStr(num1)) { - param_name = param_name.substring(0, param_name.length() - 1) + "Set" + num1; - } - } - return param_name; -} diff --git a/Sensors.ino b/Sensors.ino deleted file mode 100644 index 6f234457..00000000 --- a/Sensors.ino +++ /dev/null @@ -1,556 +0,0 @@ -void sensors_init() { - ts.add(SENSORS, 1000, [&](void*) { - static int counter; - counter++; - -#ifdef level_enable - if (sensors_reading_map[0] == 1) level_reading(); -#endif - - if (counter > 10) { - counter = 0; - -#ifdef analog_enable - if (sensors_reading_map[1] == 1) analog_reading1(); - if (sensors_reading_map[2] == 1) analog_reading2(); -#endif - -#ifdef dallas_enable - if (sensors_reading_map[3] == 1) dallas_reading(); -#endif - -#ifdef dht_enable - if (sensors_reading_map[4] == 1) dhtT_reading(); - if (sensors_reading_map[5] == 1) dhtH_reading(); - if (sensors_reading_map[6] == 1) dhtP_reading(); - if (sensors_reading_map[7] == 1) dhtC_reading(); - if (sensors_reading_map[8] == 1) dhtD_reading(); -#endif - -#ifdef bmp_enable - if (sensors_reading_map[9] == 1) bmp280T_rading(); - if (sensors_reading_map[10] == 1) bmp280P_reading(); -#endif - -#ifdef bme_enable - if (sensors_reading_map[11] == 1) bme280T_reading(); - if (sensors_reading_map[12] == 1) bme280P_reading(); - if (sensors_reading_map[13] == 1) bme280H_reading(); - if (sensors_reading_map[14] == 1) bme280A_reading(); -#endif - } - }, nullptr, true); -} - -//========================================================================================================================================= -//=========================================Модуль измерения уровня в баке================================================================== -#ifdef level_enable -//level L 14 12 Вода#в#баке,#% Датчики fill-gauge 125 20 1 -void level() { - String value_name = sCmd.next(); - String trig = sCmd.next(); - String echo = sCmd.next(); - String widget_name = sCmd.next(); - String page_name = sCmd.next(); - String type = sCmd.next(); - String empty_level = sCmd.next(); - String full_level = sCmd.next(); - String page_number = sCmd.next(); - level_value_name = value_name; - jsonWriteStr(optionJson, "e_lev", empty_level); - jsonWriteStr(optionJson, "f_lev", full_level); - jsonWriteStr(optionJson, "trig", trig); - jsonWriteStr(optionJson, "echo", echo); - pinMode(trig.toInt(), OUTPUT); - pinMode(echo.toInt(), INPUT); - choose_widget_and_create(widget_name, page_name, page_number, type, value_name); - sensors_reading_map[0] = 1; -} - -void level_reading() { - long duration_; - int distance_cm; - int level; - static int counter; - int trig = jsonReadInt(optionJson, "trig"); - int echo = jsonReadInt(optionJson, "echo"); - digitalWrite(trig, LOW); - delayMicroseconds(2); - digitalWrite(trig, HIGH); - delayMicroseconds(10); - digitalWrite(trig, LOW); - duration_ = pulseIn(echo, HIGH, 30000); // 3000 µs = 50cm // 30000 µs = 5 m - distance_cm = duration_ / 29 / 2; - distance_cm = medianFilter.filtered(distance_cm);//отсечение промахов медианным фильтром - counter++; - if (counter > tank_level_times_to_send) { - counter = 0; - level = map(distance_cm, - jsonReadInt(optionJson, "e_lev"), - jsonReadInt(optionJson, "f_lev"), 0, 100); - jsonWriteInt(configJson, level_value_name, level); - eventGen (level_value_name, ""); - sendSTATUS(level_value_name, String(level)); - Serial.println("[i] sensor '" + level_value_name + "' data: " + String(level)); - } -} -#endif -//========================================================================================================================================= -//=========================================Модуль аналогового сенсора====================================================================== -#ifdef analog_enable -//analog adc 0 Аналоговый#вход,#% Датчики any-data 1 1023 1 100 1 -void analog() { - String value_name = sCmd.next(); - String pin = sCmd.next(); - String widget_name = sCmd.next(); - String page_name = sCmd.next(); - String type = sCmd.next(); - String analog_start = sCmd.next(); - String analog_end = sCmd.next(); - String analog_start_out = sCmd.next(); - String analog_end_out = sCmd.next(); - String page_number = sCmd.next(); - analog_value_names_list += value_name + ","; - enter_to_analog_counter++; - jsonWriteStr(optionJson, value_name + "_st", analog_start); - jsonWriteStr(optionJson, value_name + "_end", analog_end); - jsonWriteStr(optionJson, value_name + "_st_out", analog_start_out); - jsonWriteStr(optionJson, value_name + "_end_out", analog_end_out); - choose_widget_and_create(widget_name, page_name, page_number, type, value_name); - if (enter_to_analog_counter == 1) { - sensors_reading_map[1] = 1; - } - if (enter_to_analog_counter == 2) { - sensors_reading_map[2] = 1; - } -} - -void analog_reading1() { - String value_name = selectFromMarkerToMarker(analog_value_names_list, ",", 0); -#ifdef ESP32 - int analog_in = analogRead(34); -#endif -#ifdef ESP8266 - int analog_in = analogRead(A0); -#endif - int analog = map(analog_in, - jsonReadInt(optionJson, value_name + "_st") , - jsonReadInt(optionJson, value_name + "_end"), - jsonReadInt(optionJson, value_name + "_st_out"), - jsonReadInt(optionJson, value_name + "_end_out")); - jsonWriteInt(configJson, value_name, analog); - eventGen (value_name, ""); - sendSTATUS(value_name, String(analog)); - Serial.println("[i] sensor '" + value_name + "' data: " + String(analog)); -} - -void analog_reading2() { - String value_name = selectFromMarkerToMarker(analog_value_names_list, ",", 1); -#ifdef ESP32 - int analog_in = analogRead(35); -#endif -#ifdef ESP8266 - int analog_in = analogRead(A0); -#endif - int analog = map(analog_in, - jsonReadInt(optionJson, value_name + "_st") , - jsonReadInt(optionJson, value_name + "_end"), - jsonReadInt(optionJson, value_name + "_st_out"), - jsonReadInt(optionJson, value_name + "_end_out")); - jsonWriteInt(configJson, value_name, analog); - eventGen (value_name, ""); - sendSTATUS(value_name, String(analog)); - Serial.println("[i] sensor '" + value_name + "' data: " + String(analog)); -} -#endif -//========================================================================================================================================= -//=========================================Модуль температурного сенсора ds18b20=========================================================== -#ifdef dallas_enable -void dallas() { - String value_name = sCmd.next(); - String pin = sCmd.next(); - String address = sCmd.next(); - String widget_name = sCmd.next(); - String page_name = sCmd.next(); - String type = sCmd.next(); - String page_number = sCmd.next(); - oneWire = new OneWire((uint8_t) pin.toInt()); - sensors.setOneWire(oneWire); - sensors.begin(); - sensors.setResolution(12); - choose_widget_and_create(widget_name, page_name, page_number, type, "dallas"); - sensors_reading_map[3] = 1; -} - -void dallas_reading() { - float temp = 0; - sensors.requestTemperatures(); - temp = sensors.getTempCByIndex(0); - jsonWriteStr(configJson, "dallas", String(temp)); - eventGen ("dallas", ""); - sendSTATUS("dallas", String(temp)); - Serial.println("[i] sensor 'dallas' send date " + String(temp)); -} -#endif -//========================================================================================================================================= -//=========================================Модуль сенсоров DHT============================================================================= -#ifdef dht_enable -//dhtT t 2 dht11 Температура#DHT,#t°C Датчики any-data 1 -void dhtT() { - String value_name = sCmd.next(); - String pin = sCmd.next(); - String sensor_type = sCmd.next(); - String widget_name = sCmd.next(); - String page_name = sCmd.next(); - String type = sCmd.next(); - String page_number = sCmd.next(); - dhtT_value_name = value_name; - if (sensor_type == "dht11") { - dht.setup(pin.toInt(), DHTesp::DHT11); - } - if (sensor_type == "dht22") { - dht.setup(pin.toInt(), DHTesp::DHT22); - } - choose_widget_and_create(widget_name, page_name, page_number, type, value_name); - sensors_reading_map[4] = 1; -} - -void dhtT_reading() { - float value = 0; - static int counter; - if (dht.getStatus() != 0 && counter < 5) { - sendSTATUS(dhtT_value_name, String(dht.getStatusString())); - counter++; - } else { - counter = 0; - value = dht.getTemperature(); - if (String(value) != "nan") { - eventGen (dhtT_value_name, ""); - jsonWriteStr(configJson, dhtT_value_name, String(value)); - sendSTATUS(dhtT_value_name, String(value)); - Serial.println("[i] sensor '" + dhtT_value_name + "' data: " + String(value)); - } - } -} - -//dhtH h 2 dht11 Влажность#DHT,#t°C Датчики any-data 1 -void dhtH() { - String value_name = sCmd.next(); - String pin = sCmd.next(); - String sensor_type = sCmd.next(); - String widget_name = sCmd.next(); - String page_name = sCmd.next(); - String type = sCmd.next(); - String page_number = sCmd.next(); - dhtH_value_name = value_name; - if (sensor_type == "dht11") { - dht.setup(pin.toInt(), DHTesp::DHT11); - } - if (sensor_type == "dht22") { - dht.setup(pin.toInt(), DHTesp::DHT22); - } - choose_widget_and_create(widget_name, page_name, page_number, type, value_name); - sensors_reading_map[5] = 1; -} - -void dhtH_reading() { - float value = 0; - static int counter; - if (dht.getStatus() != 0 && counter < 5) { - sendSTATUS(dhtH_value_name, String(dht.getStatusString())); - counter++; - } else { - counter = 0; - value = dht.getHumidity(); - if (String(value) != "nan") { - eventGen (dhtH_value_name, ""); - jsonWriteStr(configJson, dhtH_value_name, String(value)); - sendSTATUS(dhtH_value_name, String(value)); - Serial.println("[i] sensor '" + dhtH_value_name + "' data: " + String(value)); - } - } -} - -//dhtPerception Восприятие: Датчики 4 -void dhtP() { - String widget_name = sCmd.next(); - String page_name = sCmd.next(); - String page_number = sCmd.next(); - choose_widget_and_create(widget_name, page_name, page_number, "any-data", "dhtPerception"); - sensors_reading_map[6] = 1; -} - -void dhtP_reading() { - byte value; - if (dht.getStatus() != 0) { - sendSTATUS("dhtPerception", String(dht.getStatusString())); - } else { - value = dht.computePerception(jsonReadStr(configJson, dhtT_value_name).toFloat(), jsonReadStr(configJson, dhtH_value_name).toFloat(), false); - String final_line = perception(value); - jsonWriteStr(configJson, "dhtPerception", final_line); - eventGen ("dhtPerception", ""); - sendSTATUS("dhtPerception", final_line); - if (client_mqtt.connected()) { - Serial.println("[i] sensor 'dhtPerception' data: " + final_line); - } - } -} - -String perception(byte value) { - if (value == 0) return "Сухой воздух"; - if (value == 1) return "Комфортно"; - if (value == 2) return "Уютно"; - if (value == 3) return "Хорошо"; - if (value == 4) return "Неудобно"; - if (value == 5) return "Довольно неудобно"; - if (value == 6) return "Очень неудобно"; - if (value == 7) return "Сильно неудобно, полный звиздец"; -} - -//dhtComfort Степень#комфорта: Датчики 3 -void dhtC() { - String widget_name = sCmd.next(); - String page_name = sCmd.next(); - String page_number = sCmd.next(); - choose_widget_and_create(widget_name, page_name, page_number, "any-data", "dhtComfort"); - sensors_reading_map[7] = 1; -} - -void dhtC_reading() { - float value; - ComfortState cf; - if (dht.getStatus() != 0) { - sendSTATUS("dhtComfort", String(dht.getStatusString())); - } else { - value = dht.getComfortRatio(cf, jsonReadStr(configJson, dhtT_value_name).toFloat(), jsonReadStr(configJson, dhtH_value_name).toFloat(), false); - String final_line = get_comfort_status(cf); - jsonWriteStr(configJson, "dhtComfort", final_line); - eventGen ("dhtComfort", ""); - sendSTATUS("dhtComfort", final_line); - Serial.println("[i] sensor 'dhtComfort' send date " + final_line); - } -} - -String get_comfort_status(ComfortState cf) { - String comfortStatus; - switch (cf) { - case Comfort_OK: - comfortStatus = "Отлично"; - break; - case Comfort_TooHot: - comfortStatus = "Очень жарко"; - break; - case Comfort_TooCold: - comfortStatus = "Очень холодно"; - break; - case Comfort_TooDry: - comfortStatus = "Очень сухо"; - break; - case Comfort_TooHumid: - comfortStatus = "Очень влажно"; - break; - case Comfort_HotAndHumid: - comfortStatus = "Жарко и влажно"; - break; - case Comfort_HotAndDry: - comfortStatus = "Жарко и сухо"; - break; - case Comfort_ColdAndHumid: - comfortStatus = "Холодно и влажно"; - break; - case Comfort_ColdAndDry: - comfortStatus = "Холодно и сухо"; - break; - default: - comfortStatus = "Неизвестно"; - break; - }; - return comfortStatus; -} - - -//dhtDewpoint Точка#росы: Датчики 5 -void dhtD() { - String widget_name = sCmd.next(); - String page_name = sCmd.next(); - String page_number = sCmd.next(); - choose_widget_and_create(widget_name, page_name, page_number, "any-data", "dhtDewpoint"); - sensors_reading_map[8] = 1; -} - -void dhtD_reading() { - float value; - if (dht.getStatus() != 0) { - sendSTATUS("dhtDewpoint", String(dht.getStatusString())); - } else { - value = dht.computeDewPoint(jsonReadStr(configJson, dhtT_value_name).toFloat(), jsonReadStr(configJson, dhtH_value_name).toFloat(), false); - jsonWriteInt(configJson, "dhtDewpoint", value); - eventGen ("dhtDewpoint", ""); - sendSTATUS("dhtDewpoint", String(value)); - Serial.println("[i] sensor 'dhtDewpoint' data: " + String(value)); - } -} -#endif -//=========================================i2c bus esp8266 scl-4 sda-5 ==================================================================== -//========================================================================================================================================= -//=========================================Модуль сенсоров bmp280========================================================================== -#ifdef bmp_enable -//bmp280T temp1 0x76 Температура#bmp280 Датчики any-data 1 -void bmp280T() { - String value_name = sCmd.next(); - String address = sCmd.next(); - String widget_name = sCmd.next(); - String page_name = sCmd.next(); - String type = sCmd.next(); - String page_number = sCmd.next(); - bmp280T_value_name = value_name; - choose_widget_and_create(widget_name, page_name, page_number, type, value_name); - bmp.begin(hexStringToUint8(address)); - bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, /* Operating Mode. */ - Adafruit_BMP280::SAMPLING_X2, /* Temp. oversampling */ - Adafruit_BMP280::SAMPLING_X16, /* Pressure oversampling */ - Adafruit_BMP280::FILTER_X16, /* Filtering. */ - Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */ - //bmp_temp->printSensorDetails(); - sensors_reading_map[9] = 1; -} - -void bmp280T_rading() { - float value = 0; - sensors_event_t temp_event, pressure_event; - bmp_temp->getEvent(&temp_event); - value = temp_event.temperature; - jsonWriteStr(configJson, bmp280T_value_name, String(value)); - eventGen(bmp280T_value_name, ""); - sendSTATUS(bmp280T_value_name, String(value)); - Serial.println("[i] sensor '" + bmp280T_value_name + "' data: " + String(value)); -} - -//bmp280P press1 0x76 Давление#bmp280 Датчики any-data 2 -void bmp280P() { - String value_name = sCmd.next(); - String address = sCmd.next(); - String widget_name = sCmd.next(); - String page_name = sCmd.next(); - String type = sCmd.next(); - String page_number = sCmd.next(); - bmp280P_value_name = value_name; - choose_widget_and_create(widget_name, page_name, page_number, type, value_name); - bmp.begin(hexStringToUint8(address)); - bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, /* Operating Mode. */ - Adafruit_BMP280::SAMPLING_X2, /* Temp. oversampling */ - Adafruit_BMP280::SAMPLING_X16, /* Pressure oversampling */ - Adafruit_BMP280::FILTER_X16, /* Filtering. */ - Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */ - //bmp_temp->printSensorDetails(); - sensors_reading_map[10] = 1; -} - -void bmp280P_reading() { - float value = 0; - sensors_event_t temp_event, pressure_event; - bmp_pressure->getEvent(&pressure_event); - value = pressure_event.pressure; - value = value / 1.333224; - jsonWriteStr(configJson, bmp280P_value_name, String(value)); - eventGen(bmp280P_value_name, ""); - sendSTATUS(bmp280P_value_name, String(value)); - Serial.println("[i] sensor '" + bmp280P_value_name + "' data: " + String(value)); -} -#endif -//========================================================================================================================================= -//=============================================Модуль сенсоров bme280====================================================================== -#ifdef bme_enable -//bme280T temp1 0x76 Температура#bmp280 Датчики any-data 1 -void bme280T() { - String value_name = sCmd.next(); - String address = sCmd.next(); - String widget_name = sCmd.next(); - String page_name = sCmd.next(); - String type = sCmd.next(); - String page_number = sCmd.next(); - bme280T_value_name = value_name; - choose_widget_and_create(widget_name, page_name, page_number, type, value_name); - bme.begin(hexStringToUint8(address)); - sensors_reading_map[11] = 1; -} - -void bme280T_reading() { - float value = 0; - value = bme.readTemperature(); - jsonWriteStr(configJson, bme280T_value_name, String(value)); - eventGen(bme280T_value_name, ""); - sendSTATUS(bme280T_value_name, String(value)); - Serial.println("[i] sensor '" + bme280T_value_name + "' data: " + String(value)); -} - -//bme280P pres1 0x76 Давление#bmp280 Датчики any-data 1 -void bme280P() { - String value_name = sCmd.next(); - String address = sCmd.next(); - String widget_name = sCmd.next(); - String page_name = sCmd.next(); - String type = sCmd.next(); - String page_number = sCmd.next(); - bme280P_value_name = value_name; - choose_widget_and_create(widget_name, page_name, page_number, type, value_name); - bme.begin(hexStringToUint8(address)); - sensors_reading_map[12] = 1; -} - -void bme280P_reading() { - float value = 0; - value = bme.readPressure(); - value = value / 1.333224; - jsonWriteStr(configJson, bme280P_value_name, String(value)); - eventGen(bme280P_value_name, ""); - sendSTATUS(bme280P_value_name, String(value)); - Serial.println("[i] sensor '" + bme280P_value_name + "' data: " + String(value)); -} - -//bme280H hum1 0x76 Влажность#bmp280 Датчики any-data 1 -void bme280H() { - String value_name = sCmd.next(); - String address = sCmd.next(); - String widget_name = sCmd.next(); - String page_name = sCmd.next(); - String type = sCmd.next(); - String page_number = sCmd.next(); - bme280H_value_name = value_name; - choose_widget_and_create(widget_name, page_name, page_number, type, value_name); - bme.begin(hexStringToUint8(address)); - sensors_reading_map[13] = 1; -} - -void bme280H_reading() { - float value = 0; - value = bme.readHumidity(); - jsonWriteStr(configJson, bme280H_value_name, String(value)); - eventGen(bme280H_value_name, ""); - sendSTATUS(bme280H_value_name, String(value)); - Serial.println("[i] sensor '" + bme280H_value_name + "' data: " + String(value)); -} - -//bme280A altit1 0x76 Высота#bmp280 Датчики any-data 1 -void bme280A() { - String value_name = sCmd.next(); - String address = sCmd.next(); - String widget_name = sCmd.next(); - String page_name = sCmd.next(); - String type = sCmd.next(); - String page_number = sCmd.next(); - bme280A_value_name = value_name; - choose_widget_and_create(widget_name, page_name, page_number, type, value_name); - bme.begin(hexStringToUint8(address)); - sensors_reading_map[14] = 1; -} - -void bme280A_reading() { - float value = 0; - value = bme.readAltitude(1013.25); - jsonWriteStr(configJson, bme280A_value_name, String(value)); - eventGen(bme280A_value_name, ""); - sendSTATUS(bme280A_value_name, String(value)); - Serial.println("[i] sensor '" + bme280A_value_name + "' data: " + String(value)); -} -#endif diff --git a/Ticker_for_TickerScheduler/Ticker/Ticker.cpp b/Ticker_for_TickerScheduler/Ticker/Ticker.cpp deleted file mode 100644 index b53b429d..00000000 --- a/Ticker_for_TickerScheduler/Ticker/Ticker.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - Ticker.cpp - esp8266 library that calls functions periodically - - Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include -#include - -#include "c_types.h" -#include "eagle_soc.h" -#include "ets_sys.h" -#include "osapi.h" - -static const int ONCE = 0; -static const int REPEAT = 1; - -#include "Ticker.h" - -Ticker::Ticker() -: _timer(nullptr) -{ -} - -Ticker::~Ticker() -{ - detach(); -} - -void Ticker::_attach_ms(uint32_t milliseconds, bool repeat, callback_with_arg_t callback, uint32_t arg) -{ - if (_timer) - { - os_timer_disarm(_timer); - } - else - { - _timer = new ETSTimer; - } - - os_timer_setfn(_timer, reinterpret_cast(callback), reinterpret_cast(arg)); - os_timer_arm(_timer, milliseconds, (repeat)?REPEAT:ONCE); -} - -void Ticker::detach() -{ - if (!_timer) - return; - - os_timer_disarm(_timer); - delete _timer; - _timer = nullptr; - _callback_function = nullptr; -} - -bool Ticker::active() const -{ - return (bool)_timer; -} - -void Ticker::_static_callback(void* arg) -{ - Ticker* _this = (Ticker*)arg; - if (_this == nullptr) - { - return; - } - if (_this->_callback_function) - { - _this->_callback_function(); - } -} diff --git a/Ticker_for_TickerScheduler/Ticker/Ticker.h b/Ticker_for_TickerScheduler/Ticker/Ticker.h deleted file mode 100644 index 15474594..00000000 --- a/Ticker_for_TickerScheduler/Ticker/Ticker.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - Ticker.h - esp8266 library that calls functions periodically - - Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef TICKER_H -#define TICKER_H - -#include -#include -#include -#include -#include - -extern "C" { - typedef struct _ETSTIMER_ ETSTimer; -} - -class Ticker -{ -public: - Ticker(); - ~Ticker(); - typedef void (*callback_t)(void); - typedef void (*callback_with_arg_t)(void*); - typedef std::function callback_function_t; - - void attach_scheduled(float seconds, callback_function_t callback) - { - attach(seconds,std::bind(schedule_function, callback)); - } - - void attach(float seconds, callback_function_t callback) - { - _callback_function = callback; - attach(seconds, _static_callback, (void*)this); - } - - void attach_ms_scheduled(uint32_t milliseconds, callback_function_t callback) - { - attach_ms(milliseconds, std::bind(schedule_function, callback)); - } - - void attach_ms(uint32_t milliseconds, callback_function_t callback) - { - _callback_function = callback; - attach_ms(milliseconds, _static_callback, (void*)this); - } - - template - void attach(float seconds, void (*callback)(TArg), TArg arg) - { - static_assert(sizeof(TArg) <= sizeof(uint32_t), "attach() callback argument size must be <= 4 bytes"); - // C-cast serves two purposes: - // static_cast for smaller integer types, - // reinterpret_cast + const_cast for pointer types - uint32_t arg32 = (uint32_t)arg; - _attach_ms(seconds * 1000, true, reinterpret_cast(callback), arg32); - } - - template - void attach_ms(uint32_t milliseconds, void (*callback)(TArg), TArg arg) - { - static_assert(sizeof(TArg) <= sizeof(uint32_t), "attach_ms() callback argument size must be <= 4 bytes"); - uint32_t arg32 = (uint32_t)arg; - _attach_ms(milliseconds, true, reinterpret_cast(callback), arg32); - } - - void once_scheduled(float seconds, callback_function_t callback) - { - once(seconds, std::bind(schedule_function, callback)); - } - - void once(float seconds, callback_function_t callback) - { - _callback_function = callback; - once(seconds, _static_callback, (void*)this); - } - - void once_ms_scheduled(uint32_t milliseconds, callback_function_t callback) - { - once_ms(milliseconds, std::bind(schedule_function, callback)); - } - - void once_ms(uint32_t milliseconds, callback_function_t callback) - { - _callback_function = callback; - once_ms(milliseconds, _static_callback, (void*)this); - } - - template - void once(float seconds, void (*callback)(TArg), TArg arg) - { - static_assert(sizeof(TArg) <= sizeof(uint32_t), "attach() callback argument size must be <= 4 bytes"); - uint32_t arg32 = (uint32_t)(arg); - _attach_ms(seconds * 1000, false, reinterpret_cast(callback), arg32); - } - - template - void once_ms(uint32_t milliseconds, void (*callback)(TArg), TArg arg) - { - static_assert(sizeof(TArg) <= sizeof(uint32_t), "attach_ms() callback argument size must be <= 4 bytes"); - uint32_t arg32 = (uint32_t)(arg); - _attach_ms(milliseconds, false, reinterpret_cast(callback), arg32); - } - - void detach(); - bool active() const; - -protected: - void _attach_ms(uint32_t milliseconds, bool repeat, callback_with_arg_t callback, uint32_t arg); - static void _static_callback (void* arg); - -protected: - ETSTimer* _timer; - callback_function_t _callback_function = nullptr; -}; - - -#endif//TICKER_H diff --git a/Ticker_for_TickerScheduler/Ticker/examples/TickerBasic/TickerBasic.ino b/Ticker_for_TickerScheduler/Ticker/examples/TickerBasic/TickerBasic.ino deleted file mode 100644 index 2fabd983..00000000 --- a/Ticker_for_TickerScheduler/Ticker/examples/TickerBasic/TickerBasic.ino +++ /dev/null @@ -1,45 +0,0 @@ -/* - Basic Ticker usage - - Ticker is an object that will call a given function with a certain period. - Each Ticker calls one function. You can have as many Tickers as you like, - memory being the only limitation. - - A function may be attached to a ticker and detached from the ticker. - There are two variants of the attach function: attach and attach_ms. - The first one takes period in seconds, the second one in milliseconds. - - The built-in LED will be blinking. -*/ - -#include - -Ticker flipper; - -int count = 0; - -void flip() { - int state = digitalRead(LED_BUILTIN); // get the current state of GPIO1 pin - digitalWrite(LED_BUILTIN, !state); // set pin to the opposite state - - ++count; - // when the counter reaches a certain value, start blinking like crazy - if (count == 20) { - flipper.attach(0.1, flip); - } - // when the counter reaches yet another value, stop blinking - else if (count == 120) { - flipper.detach(); - } -} - -void setup() { - pinMode(LED_BUILTIN, OUTPUT); - digitalWrite(LED_BUILTIN, LOW); - - // flip the pin every 0.3s - flipper.attach(0.3, flip); -} - -void loop() { -} diff --git a/Ticker_for_TickerScheduler/Ticker/examples/TickerFunctional/TickerFunctional.ino b/Ticker_for_TickerScheduler/Ticker/examples/TickerFunctional/TickerFunctional.ino deleted file mode 100644 index 33c94359..00000000 --- a/Ticker_for_TickerScheduler/Ticker/examples/TickerFunctional/TickerFunctional.ino +++ /dev/null @@ -1,64 +0,0 @@ -#include "Arduino.h" -#include "Ticker.h" - -#define LED1 2 -#define LED2 4 -#define LED3 12 -#define LED4 14 -#define LED5 15 - - -class ExampleClass { - public: - ExampleClass(int pin, int duration) : _pin(pin), _duration(duration) { - pinMode(_pin, OUTPUT); - _myTicker.attach_ms(_duration, std::bind(&ExampleClass::classBlink, this)); - } - ~ExampleClass() {}; - - int _pin, _duration; - Ticker _myTicker; - - void classBlink() { - digitalWrite(_pin, !digitalRead(_pin)); - } -}; - -void staticBlink() { - digitalWrite(LED2, !digitalRead(LED2)); -} - -void scheduledBlink() { - digitalWrite(LED3, !digitalRead(LED2)); -} - -void parameterBlink(int p) { - digitalWrite(p, !digitalRead(p)); -} - -Ticker staticTicker; -Ticker scheduledTicker; -Ticker parameterTicker; -Ticker lambdaTicker; - -ExampleClass example(LED1, 100); - - -void setup() { - pinMode(LED2, OUTPUT); - staticTicker.attach_ms(100, staticBlink); - - pinMode(LED3, OUTPUT); - scheduledTicker.attach_ms_scheduled(100, scheduledBlink); - - pinMode(LED4, OUTPUT); - parameterTicker.attach_ms(100, std::bind(parameterBlink, LED4)); - - pinMode(LED5, OUTPUT); - lambdaTicker.attach_ms(100, []() { - digitalWrite(LED5, !digitalRead(LED5)); - }); -} - -void loop() { -} diff --git a/Ticker_for_TickerScheduler/Ticker/examples/TickerParameter/TickerParameter.ino b/Ticker_for_TickerScheduler/Ticker/examples/TickerParameter/TickerParameter.ino deleted file mode 100644 index 67c6256b..00000000 --- a/Ticker_for_TickerScheduler/Ticker/examples/TickerParameter/TickerParameter.ino +++ /dev/null @@ -1,35 +0,0 @@ -/* - Passing paramters to Ticker callbacks - - Apart from void(void) functions, the Ticker library supports - functions taking one argument. This argument's size has to be less or - equal to 4 bytes (so char, short, int, float, void*, char* types will do). - - This sample runs two tickers that both call one callback function, - but with different arguments. - - The built-in LED will be pulsing. -*/ - -#include - -Ticker tickerSetHigh; -Ticker tickerSetLow; - -void setPin(int state) { - digitalWrite(LED_BUILTIN, state); -} - -void setup() { - pinMode(LED_BUILTIN, OUTPUT); - digitalWrite(1, LOW); - - // every 25 ms, call setPin(0) - tickerSetLow.attach_ms(25, setPin, 0); - - // every 26 ms, call setPin(1) - tickerSetHigh.attach_ms(26, setPin, 1); -} - -void loop() { -} diff --git a/Ticker_for_TickerScheduler/Ticker/library.properties b/Ticker_for_TickerScheduler/Ticker/library.properties deleted file mode 100644 index a759351e..00000000 --- a/Ticker_for_TickerScheduler/Ticker/library.properties +++ /dev/null @@ -1,10 +0,0 @@ -name=Ticker -version=1.0 -author=Ivan Grokhtokov -maintainer=Ivan Grokhtokov -sentence=Allows to call functions with a given interval. -paragraph= -category=Timing -url= -architectures=esp8266 -dot_a_linkage=true diff --git a/Time.ino b/Time.ino deleted file mode 100644 index 365d40e4..00000000 --- a/Time.ino +++ /dev/null @@ -1,143 +0,0 @@ -void Time_Init() { - server.on("/time", HTTP_GET, [](AsyncWebServerRequest * request) { - if (request->hasArg("timezone")) { - jsonWriteStr(configSetup, "timezone", request->getParam("timezone")->value()); - } - if (request->hasArg("ntp")) { - jsonWriteStr(configSetup, "ntp", request->getParam("ntp")->value()); - } - saveConfig(); - reconfigTime(); - request->send(200, "text/text", "OK"); // отправляем ответ о выполнении - }); - - ts.add(TIME_SYNC, 30000, [&](void*) { - time_check(); - }, nullptr, true); -} - -void time_check() { - if (GetTimeUnix() == "failed") { - Serial.println("[i] Time is not synchronized, start synchronization"); - reconfigTime(); - } -} - -void reconfigTime() { - if (WiFi.status() == WL_CONNECTED) { - String ntp = jsonReadStr(configSetup, "ntp"); - configTime(0, 0, ntp.c_str()); - int i = 0; - Serial.println("[i] Awaiting for time "); -#ifdef ESP32 - struct tm timeinfo; - while (!getLocalTime(&timeinfo) && i <= 4) { - Serial.print("."); - i++; - delay(1000); - } -#endif -#ifdef ESP8266 - //while (!time(nullptr) && i < 4) { - // Serial.print("."); - // i++; - delay(2000); - //} -#endif - if (GetTimeUnix() != "failed") { - Serial.print("[V] Time synchronized = "); - Serial.print(GetDataDigital()); - Serial.print(" "); - Serial.println(GetTime()); - } else { - Serial.println("[E] Time server or internet connection error, will try again in 30 sec"); - } - } else { - Serial.println("[E] Get time impossible, no wifi connection"); - } -} - -//Получаем время в формате linux gmt -String GetTimeUnix() { - time_t now = time(nullptr); - if (now < 30000) { - return "failed"; - } else { - return String(now); - } -} -// Получение текущего времени -String GetTime() { - time_t now = time(nullptr); // получаем время с помощью библиотеки time.h - int zone = 3600 * jsonReadStr(configSetup, "timezone").toInt(); - now = now + zone; - String Time = ""; // Строка для результатов времени - Time += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 - int i = Time.indexOf(":"); //Ишем позицию первого символа : - Time = Time.substring(i - 2, i + 6); // Выделяем из строки 2 символа перед символом : и 6 символов после - return Time; // Возврашаем полученное время -} - -String GetTimeWOsec() { - time_t now = time(nullptr); // получаем время с помощью библиотеки time.h - int zone = 3600 * jsonReadStr(configSetup, "timezone").toInt(); - now = now + zone; - String Time = ""; // Строка для результатов времени - Time += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 - int i = Time.indexOf(":"); //Ишем позицию первого символа : - Time = Time.substring(i - 2, i + 3); // Выделяем из строки 2 символа перед символом : и 6 символов после - return Time; // Возврашаем полученное время -} - -// Получение даты -String GetDate() { - time_t now = time(nullptr); // получаем время с помощью библиотеки time.h - int zone = 3600 * jsonReadStr(configSetup, "timezone").toInt(); - now = now + zone; - String Data = ""; // Строка для результатов времени - Data += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 - Data.replace("\n", ""); - uint8_t i = Data.lastIndexOf(" "); //Ишем позицию последнего символа пробел - String Time = Data.substring(i - 8, i + 1); // Выделяем время и пробел - Data.replace(Time, ""); // Удаляем из строки 8 символов времени и пробел - return Data; // Возврашаем полученную дату -} - -String GetDataDigital() { - String date = GetDate(); - - date = deleteBeforeDelimiter(date, " "); - - date.replace("Jan", "01"); - date.replace("Feb", "02"); - date.replace("Mar", "03"); - date.replace("Apr", "04"); - date.replace("May", "05"); - date.replace("Jun", "06"); - date.replace("Jul", "07"); - date.replace("Aug", "08"); - date.replace("Sep", "09"); - date.replace("Oct", "10"); - date.replace("Nov", "11"); - date.replace("Dec", "12"); - - String month = date.substring(0, 2); - String day = date.substring(3, 5); - String year = date.substring(8, 10); - - String out = day; - out += "."; - out += month; - out += "."; - out += year; - - return out; -} - -int timeToMin(String Time) { - //"00:00:00" время в секунды - long min = selectToMarker(Time, ":").toInt() * 60; //общее количество секунд в полных часах - Time = deleteBeforeDelimiter (Time, ":"); // Теперь здесь минуты секунды - min += selectToMarker(Time, ":").toInt(); // Добавим секунды из полных минут - return min; -} diff --git a/Timers.ino b/Timers.ino deleted file mode 100644 index 941f0c0d..00000000 --- a/Timers.ino +++ /dev/null @@ -1,89 +0,0 @@ -//================================================================================================================ -//=========================================Таймеры================================================================= -void Timer_countdown_init() { - - ts.add(TIMER_COUNTDOWN, 1000, [&](void*) { - - String old_line = jsonReadStr(optionJson, "timers"); - if (old_line != "") { - //Serial.println(old_line); - int i = 0; - do { - String timer = selectFromMarkerToMarker(old_line, "," , i); - Serial.print("timer no " + String (i) + ": "); - Serial.println(timer); - if (timer == "not found" || timer == "") return; - int number = selectToMarker (timer, ":").toInt(); - int time = readTimer(number); - if (time == 0) { - delTimer (String (number)); - jsonWriteStr(configJson, "timer" + String(number), "0"); - eventGen ("timer", String(number)); - } else { - time--; - addTimer(String (number), String (time)); - } - i++; - } while (i <= 9); - } - }, nullptr, true); -} - -void timerStart() { - String number = sCmd.next(); - String period_of_time = sCmd.next(); - String type = sCmd.next(); - if (period_of_time.indexOf("digit") != -1) { - //period_of_time = add_set(period_of_time); - period_of_time = jsonReadStr(configJson, period_of_time); - } - if (type == "sec") period_of_time = period_of_time; - if (type == "min") period_of_time = String(period_of_time.toInt() * 60); - if (type == "hours") period_of_time = String(period_of_time.toInt() * 60 * 60); - addTimer(number, period_of_time); - jsonWriteStr(configJson, "timer" + number, "1"); -} -void addTimer(String number, String time) { - String tmp = jsonReadStr(optionJson, "timers"); //1:60,2:120, - String new_timer = number + ":" + time; - int psn1 = tmp.indexOf(number + ":"); //0 ищем позицию таймера который надо заменить - if (psn1 != -1) { //если он есть - int psn2 = tmp.indexOf(",", psn1); //4 от этой позиции находим позицию запятой - String timer = tmp.substring(psn1, psn2); //1:60 выделяем таймер который надо заменить - ///tmp.replace(timer, new_timer); //заменяем таймер на новый (во всей стороке) - tmp.replace(timer + ",", ""); - tmp += new_timer + ","; - } else { //если его нет - tmp += new_timer + ","; - } - jsonWriteStr(optionJson, "timers", tmp); - //Serial.println("ura"); -} - -void timerStop() { - String number = sCmd.next(); - delTimer(number); -} - -void delTimer (String number) { - String tmp = jsonReadStr(optionJson, "timers"); //1:60,2:120, - int psn1 = tmp.indexOf(number + ":"); //0 ищем позицию таймера который надо удалить - if (psn1 != -1) { //если он есть - int psn2 = tmp.indexOf(",", psn1); //4 от этой позиции находим позицию запятой - String timer = tmp.substring(psn1, psn2) + ","; //1:60, выделяем таймер который надо удалить - tmp.replace(timer, ""); //удаляем таймер - jsonWriteStr(optionJson, "timers", tmp); - } -} - -int readTimer(int number) { - String tmp = jsonReadStr(optionJson, "timers"); //1:60,2:120, - int psn1 = tmp.indexOf(String(number) + ":"); //0 ищем позицию таймера который надо прочитать - String timer; - if (psn1 != -1) { //если он есть - int psn2 = tmp.indexOf(",", psn1); //4 от этой позиции находим позицию запятой - timer = tmp.substring(psn1, psn2); //1:60 выделяем таймер который надо прочитать - timer = deleteBeforeDelimiter(timer, ":"); - } - return timer.toInt(); -} diff --git a/Upgrade.ino b/Upgrade.ino deleted file mode 100644 index f576bfe6..00000000 --- a/Upgrade.ino +++ /dev/null @@ -1,277 +0,0 @@ -void initUpgrade() { - -#ifdef ESP8266 - if (WiFi.status() == WL_CONNECTED) last_version = getURL("http://91.204.228.124:1100/update/esp8266/version.txt"); -#endif -#ifdef ESP32 - if (WiFi.status() == WL_CONNECTED) last_version = getURL("http://91.204.228.124:1100/update/esp32/version.txt"); -#endif - jsonWriteStr(configSetup, "last_version", last_version); - Serial.print("[i] Last firmware version: "); - Serial.println(last_version); - - server.on("/check", HTTP_GET, [](AsyncWebServerRequest * request) { - upgrade_url = true; - Serial.print("[i] Last firmware version: "); - Serial.println(last_version); - String tmp = "{}"; - if (WiFi.status() == WL_CONNECTED) { - if (mb_4_of_memory) { - if (last_version != "") { - if (last_version != "error") { - if (last_version == firmware_version) { - jsonWriteStr(tmp, "title", "Последняя версия прошивки уже установлена."); - jsonWriteStr(tmp, "class", "pop-up"); - } else { - jsonWriteStr(tmp, "title", "Имеется новая версия прошивкиИдет обновление прошивки, после обновления страница перезагрузится автоматически...')\">Установить"); - jsonWriteStr(tmp, "class", "pop-up"); - } - } else { - jsonWriteStr(tmp, "title", "Ошибка... Cервер не найден. Попробуйте позже..."); - jsonWriteStr(tmp, "class", "pop-up"); - } - } else { - jsonWriteStr(tmp, "title", "Нажмите на кнопку \"обновить прошивку\" повторно..."); - jsonWriteStr(tmp, "class", "pop-up"); - } - } else { - jsonWriteStr(tmp, "title", "Обновление по воздуху не поддерживается, модуль имеет меньше 4 мб памяти..."); - jsonWriteStr(tmp, "class", "pop-up"); - } - } else { - jsonWriteStr(tmp, "title", "Устройство не подключен к роутеру..."); - jsonWriteStr(tmp, "class", "pop-up"); - } - request->send(200, "text/text", tmp); - }); - - server.on("/upgrade", HTTP_GET, [](AsyncWebServerRequest * request) { - upgrade = true; - String tmp = "{}"; - request->send(200, "text/text", "ok"); - }); -} - -void do_upgrade_url() { - if (upgrade_url) { - upgrade_url = false; -#ifdef ESP32 - last_version = getURL("http://91.204.228.124:1100/update/esp32/version.txt"); - jsonWriteStr(configSetup, "last_version", last_version); -#endif -#ifdef ESP8266 - last_version = getURL("http://91.204.228.124:1100/update/esp8266/version.txt"); - jsonWriteStr(configSetup, "last_version", last_version); -#endif - } -} - -void upgrade_firmware() { - - String scenario_for_update; - String config_for_update; - String configSetup_for_update; - scenario_for_update = readFile("firmware.s.txt", 4000); - config_for_update = readFile("firmware.c.txt", 4000); - configSetup_for_update = configSetup; - - Serial.println("Start upgrade SPIFFS, please wait..."); - - WiFiClient client_for_upgrade; - -#ifdef ESP32 - httpUpdate.rebootOnUpdate(false); - t_httpUpdate_return ret = httpUpdate.updateSpiffs(client_for_upgrade, "http://91.204.228.124:1100/update/esp32/esp32-esp8266_iot-manager_modules_firmware.spiffs.bin"); -#endif -#ifdef ESP8266 - ESPhttpUpdate.rebootOnUpdate(false); - t_httpUpdate_return ret = ESPhttpUpdate.updateSpiffs(client_for_upgrade, "http://91.204.228.124:1100/update/esp8266/esp32-esp8266_iot-manager_modules_firmware.spiffs.bin"); -#endif - - if (ret == HTTP_UPDATE_OK) { - - writeFile("firmware.s.txt", scenario_for_update); - writeFile("firmware.c.txt", config_for_update); - writeFile("config.json", configSetup_for_update); - saveConfig(); - - Serial.println("SPIFFS upgrade done!"); - Serial.println("Start upgrade BUILD, please wait..."); - -#ifdef ESP32 - //httpUpdate.rebootOnUpdate(true); - t_httpUpdate_return ret = httpUpdate.update(client_for_upgrade, "http://91.204.228.124:1100/update/esp32/esp32-esp8266_iot-manager_modules_firmware.ino.bin"); -#endif -#ifdef ESP8266 - //ESPhttpUpdate.rebootOnUpdate(true); - t_httpUpdate_return ret = ESPhttpUpdate.update(client_for_upgrade, "http://91.204.228.124:1100/update/esp8266/esp32-esp8266_iot-manager_modules_firmware.ino.bin"); -#endif - - if (ret == HTTP_UPDATE_OK) { - - Serial.println("BUILD upgrade done!"); - Serial.println("Restart ESP...."); - ESP.restart(); - } else { - Serial.println("!!!!BUILD upgrade ERROR"); - } - } else { - Serial.println("!!!!SPIFFS upgrade ERROR"); - } -} - -void do_upgrade() { - if (upgrade) { - upgrade = false; - upgrade_firmware(); - } -} - -/* - void upgrade_status(t_httpUpdate_return set) { - switch (set) { - case HTTP_UPDATE_FAILED: - Serial.printf("UPDATE_FAILED Error (%d): %s", httpUpdate.getLastError(), httpUpdate.getLastErrorString().c_str()); - break; - - case HTTP_UPDATE_NO_UPDATES: - Serial.println("NO_UPDATES"); - break; - - case HTTP_UPDATE_OK: - Serial.println("HTTP_UPDATE_OK"); - break; - } - } -*/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/* - // ----------------------- Обновление с сайта - void webUpgrade() { - - #ifdef ESP8266 - String spiffsData = "http://91.204.228.124:1100/update/esp8266/esp32-esp8266_iot-manager_modules_firmware.spiffs.bin"; - String buildData = "http://91.204.228.124:1100/update/esp8266/esp32-esp8266_iot-manager_modules_firmware.ino.bin"; - #endif - - #ifdef ESP32 - String spiffsData = "http://91.204.228.124:1100/update/esp32/esp32-esp8266_iot-manager_modules_firmware.spiffs.bin"; - String buildData = "http://91.204.228.124:1100/update/esp32/esp32-esp8266_iot-manager_modules_firmware.ino.bin"; - #endif - - if (spiffsData != "") { // Если нужно прошить FS - String scenario_for_update; - String config_for_update; - String configSetup_for_update; - Serial.println(spiffsData); - scenario_for_update = readFile("firmware.s.txt", 2048); - config_for_update = readFile("config.all.txt", 2048); - configSetup_for_update = configSetup; - ESPhttpUpdate.rebootOnUpdate(false); // Отключим перезагрузку после обновления - updateHTTP(spiffsData, true); - writeFile("firmware.s.txt", scenario_for_update); - writeFile("config.all.txt", config_for_update); - writeFile("config.json", configSetup_for_update); - saveConfig(); - } - - if (buildData != "") { // Если нужно прошить build - Serial.println(buildData); - ESPhttpUpdate.rebootOnUpdate(true); // Включим перезагрузку после обновления - updateHTTP(buildData, false); - } - } - // ------------------ Обновление по url - void updateHTTP(String url, boolean mode) { - if (url == "") return; - ESPhttpUpdate.setLedPin(LED_BUILTIN, LOW); - if (mode) { - Serial.println("Update Spiffs..."); - t_httpUpdate_return ret = ESPhttpUpdate.updateSpiffs(url); - UpdateStatus(ret , "Spiffs"); - } else { - Serial.println("Update Build..."); - t_httpUpdate_return ret = ESPhttpUpdate.update(url); - UpdateStatus(ret , "build"); - } - } - void UpdateStatus(t_httpUpdate_return set, String mode) { - - switch (set) { - - case HTTP_UPDATE_FAILED: - Serial.println(mode + "_FAILED"); - var = "{}"; - jsonWriteStr(var, "title", "_FAILED"); - jsonWriteStr(var, "class", "pop-up"); - //request->send(200, "text/text", var); - break; - - case HTTP_UPDATE_NO_UPDATES: - Serial.println(mode + "_NO_UPDATES"); - var = "{}"; - jsonWriteStr(var, "title", "_NO_UPDATES"); - jsonWriteStr(var, "class", "pop-up"); - //request->send(200, "text/text", var); - break; - - case HTTP_UPDATE_OK: - Serial.println(mode + "_UPDATE_OK"); - var = "{}"; - jsonWriteStr(var, "title", "_UPDATE_OK"); - jsonWriteStr(var, "class", "pop-up"); - //request->send(200, "text/text", var); - break; - } - } -*/ diff --git a/Web_server.ino b/Web_server.ino deleted file mode 100644 index f4e01087..00000000 --- a/Web_server.ino +++ /dev/null @@ -1,231 +0,0 @@ -void Web_server_init() { - /********************************************************************************* - ***************************************OTA**************************************** - *********************************************************************************/ -#ifdef OTA_enable - ArduinoOTA.onStart([]() { - events.send("Update Start", "ota"); - }); - ArduinoOTA.onEnd([]() { - events.send("Update End", "ota"); - }); - ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { - char p[32]; - sprintf(p, "Progress: %u%%\n", (progress / (total / 100))); - events.send(p, "ota"); - }); - ArduinoOTA.onError([](ota_error_t error) { - if (error == OTA_AUTH_ERROR) events.send("Auth Failed", "ota"); - else if (error == OTA_BEGIN_ERROR) events.send("Begin Failed", "ota"); - else if (error == OTA_CONNECT_ERROR) events.send("Connect Failed", "ota"); - else if (error == OTA_RECEIVE_ERROR) events.send("Recieve Failed", "ota"); - else if (error == OTA_END_ERROR) events.send("End Failed", "ota"); - }); - ArduinoOTA.setHostname(hostName); - ArduinoOTA.begin(); -#endif - /********************************************************************************* - **************************************MDNS**************************************** - *********************************************************************************/ -#ifdef MDNS_enable - MDNS.addService("http", "tcp", 80); -#endif - //SPIFFS.begin(); - /********************************************************************************* - **************************************WS****************************************** - *********************************************************************************/ -#ifdef WS_enable - ws.onEvent(onWsEvent); - server.addHandler(&ws); - - events.onConnect([](AsyncEventSourceClient * client) { - //!!!client->send("hello!", NULL, millis(), 1000); - }); - - server.addHandler(&events); -#endif - /********************************************************************************* - **************************************WEB**************************************** - *********************************************************************************/ -#ifdef ESP32 - server.addHandler(new SPIFFSEditor(SPIFFS, jsonReadStr(configSetup, "web_login").c_str(), jsonReadStr(configSetup, "web_pass").c_str())); -#elif defined(ESP8266) - server.addHandler(new SPIFFSEditor(jsonReadStr(configSetup, "web_login").c_str(), jsonReadStr(configSetup, "web_pass").c_str())); -#endif - - /* server.on("/heap", HTTP_GET, [](AsyncWebServerRequest * request) { - request->send(200, "text/plain", String(ESP.getFreeHeap())); - });*/ - - server.serveStatic("/css/", SPIFFS, "/css/").setCacheControl("max-age=31536000"); - server.serveStatic("/js/", SPIFFS, "/js/").setCacheControl("max-age=31536000"); - server.serveStatic("/favicon.ico", SPIFFS, "/favicon.ico").setCacheControl("max-age=31536000"); - - server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.htm") - .setAuthentication(jsonReadStr(configSetup, "web_login").c_str(), jsonReadStr(configSetup, "web_pass").c_str()); - - server.onNotFound([](AsyncWebServerRequest * request) { - Serial.printf("NOT_FOUND: "); - if (request->method() == HTTP_GET) - Serial.printf("GET"); - else if (request->method() == HTTP_POST) - Serial.printf("POST"); - else if (request->method() == HTTP_DELETE) - Serial.printf("DELETE"); - else if (request->method() == HTTP_PUT) - Serial.printf("PUT"); - else if (request->method() == HTTP_PATCH) - Serial.printf("PATCH"); - else if (request->method() == HTTP_HEAD) - Serial.printf("HEAD"); - else if (request->method() == HTTP_OPTIONS) - Serial.printf("OPTIONS"); - else - Serial.printf("UNKNOWN"); - Serial.printf(" http://%s%s\n", request->host().c_str(), request->url().c_str()); - - if (request->contentLength()) { - Serial.printf("_CONTENT_TYPE: %s\n", request->contentType().c_str()); - Serial.printf("_CONTENT_LENGTH: %u\n", request->contentLength()); - } - - int headers = request->headers(); - int i; - for (i = 0; i < headers; i++) { - AsyncWebHeader* h = request->getHeader(i); - Serial.printf("_HEADER[%s]: %s\n", h->name().c_str(), h->value().c_str()); - } - - int params = request->params(); - for (i = 0; i < params; i++) { - AsyncWebParameter* p = request->getParam(i); - if (p->isFile()) { - Serial.printf("_FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size()); - } else if (p->isPost()) { - Serial.printf("_POST[%s]: %s\n", p->name().c_str(), p->value().c_str()); - } else { - Serial.printf("_GET[%s]: %s\n", p->name().c_str(), p->value().c_str()); - } - } - - request->send(404); - }); - - - server.onFileUpload([](AsyncWebServerRequest * request, const String & filename, size_t index, uint8_t *data, size_t len, bool final) { - if (!index) - Serial.printf("UploadStart: %s\n", filename.c_str()); - Serial.printf("%s", (const char*)data); - if (final) - Serial.printf("UploadEnd: %s (%u)\n", filename.c_str(), index + len); - }); - - - server.onRequestBody([](AsyncWebServerRequest * request, uint8_t *data, size_t len, size_t index, size_t total) { - if (!index) - Serial.printf("BodyStart: %u\n", total); - Serial.printf("%s", (const char*)data); - if (index + len == total) - Serial.printf("BodyEnd: %u\n", total); - }); - - server.begin(); - - // --------------------Выдаем данные configJson //config.live.json - динамические данные - server.on("/config.live.json", HTTP_GET, [](AsyncWebServerRequest * request) { - request->send(200, "application/json", configJson); - }); - // --------------------Выдаем данные optionJson //config.option.json - данные не являющиеся событиями - server.on("/config.option.json", HTTP_GET, [](AsyncWebServerRequest * request) { - request->send(200, "application/json", optionJson); - }); - // -------------------Выдаем данные configSetup //config.setup.json - для хранения постоянных данных - server.on("/config.setup.json", HTTP_GET, [](AsyncWebServerRequest * request) { - request->send(200, "application/json", configSetup); - }); - - // ------------------Выполнение команды из запроса - //http://192.168.88.45/cmd?command=rel%201%201 - server.on("/cmd", HTTP_GET, [](AsyncWebServerRequest * request) { - String com = request->getParam("command")->value(); - Serial.println(com); - order_loop += com + ","; - request->send(200, "text/text", "OK"); // отправляем ответ о выполнении - }); -} -/********************************************************************************************************************************* - *********************************************************WS********************************************************************** - ********************************************************************************************************************************/ -#ifdef WS_enable -void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len) { - if (type == WS_EVT_CONNECT) { - Serial.printf("ws[%s][%u] connect\n", server->url(), client->id()); - client->printf(json.c_str(), client->id()); - //client->ping(); - } else if (type == WS_EVT_DISCONNECT) { - Serial.printf("ws[%s][%u] disconnect\n", server->url(), client->id()); - } else if (type == WS_EVT_ERROR) { - Serial.printf("ws[%s][%u] error(%u): %s\n", server->url(), client->id(), *((uint16_t*)arg), (char*)data); - } else if (type == WS_EVT_PONG) { - Serial.printf("ws[%s][%u] pong[%u]: %s\n", server->url(), client->id(), len, (len) ? (char*)data : ""); - } else if (type == WS_EVT_DATA) { - AwsFrameInfo * info = (AwsFrameInfo*)arg; - String msg = ""; - if (info->final && info->index == 0 && info->len == len) { - //the whole message is in a single frame and we got all of it's data - Serial.printf("ws[%s][%u] %s-message[%llu]: ", server->url(), client->id(), (info->opcode == WS_TEXT) ? "text" : "binary", info->len); - - if (info->opcode == WS_TEXT) { - for (size_t i = 0; i < info->len; i++) { - msg += (char) data[i]; - } - } else { - char buff[3]; - for (size_t i = 0; i < info->len; i++) { - sprintf(buff, "%02x ", (uint8_t) data[i]); - msg += buff ; - } - } - Serial.printf("%s\n", msg.c_str()); - - if (info->opcode == WS_TEXT) - client->text("{}"); - else - client->binary("{}"); - } else { - //message is comprised of multiple frames or the frame is split into multiple packets - if (info->index == 0) { - if (info->num == 0) - Serial.printf("ws[%s][%u] %s-message start\n", server->url(), client->id(), (info->message_opcode == WS_TEXT) ? "text" : "binary"); - Serial.printf("ws[%s][%u] frame[%u] start[%llu]\n", server->url(), client->id(), info->num, info->len); - } - - Serial.printf("ws[%s][%u] frame[%u] %s[%llu - %llu]: ", server->url(), client->id(), info->num, (info->message_opcode == WS_TEXT) ? "text" : "binary", info->index, info->index + len); - - if (info->opcode == WS_TEXT) { - for (size_t i = 0; i < len; i++) { - msg += (char) data[i]; - } - } else { - char buff[3]; - for (size_t i = 0; i < len; i++) { - sprintf(buff, "%02x ", (uint8_t) data[i]); - msg += buff ; - } - } - Serial.printf("%s\n", msg.c_str()); - - if ((info->index + len) == info->len) { - Serial.printf("ws[%s][%u] frame[%u] end[%llu]\n", server->url(), client->id(), info->num, info->len); - if (info->final) { - Serial.printf("ws[%s][%u] %s-message end\n", server->url(), client->id(), (info->message_opcode == WS_TEXT) ? "text" : "binary"); - if (info->message_opcode == WS_TEXT) - client->text("I got your text message"); - else - client->binary("I got your binary message"); - } - } - } - } -} -#endif diff --git a/WiFi.ino b/WiFi.ino deleted file mode 100644 index 501e5a8f..00000000 --- a/WiFi.ino +++ /dev/null @@ -1,213 +0,0 @@ -void WIFI_init() { - - // --------------------Получаем ssid password со страницы - server.on("/ssid", HTTP_GET, [](AsyncWebServerRequest * request) { - if (request->hasArg("ssid")) { - jsonWriteStr(configSetup, "ssid", request->getParam("ssid")->value()); - } - if (request->hasArg("password")) { - jsonWriteStr(configSetup, "password", request->getParam("password")->value()); - } - saveConfig(); // Функция сохранения данных во Flash - request->send(200, "text/text", "OK"); // отправляем ответ о выполнении - }); - // --------------------Получаем ssidAP passwordAP со страницы - server.on("/ssidap", HTTP_GET, [](AsyncWebServerRequest * request) { - if (request->hasArg("ssidAP")) { - jsonWriteStr(configSetup, "ssidAP", request->getParam("ssidAP")->value()); - } - if (request->hasArg("passwordAP")) { - jsonWriteStr(configSetup, "passwordAP", request->getParam("passwordAP")->value()); - } - saveConfig(); // Функция сохранения данных во Flash - request->send(200, "text/text", "OK"); // отправляем ответ о выполнении - }); - - // --------------------Получаем логин и пароль для web со страницы - server.on("/web", HTTP_GET, [](AsyncWebServerRequest * request) { - if (request->hasArg("web_login")) { - jsonWriteStr(configSetup, "web_login", request->getParam("web_login")->value()); - } - if (request->hasArg("web_pass")) { - jsonWriteStr(configSetup, "web_pass", request->getParam("web_pass")->value()); - } - saveConfig(); // Функция сохранения данных во Flash - //Web_server_init(); - request->send(200, "text/text", "OK"); // отправляем ответ о выполнении - }); - - server.on("/restart", HTTP_GET, [](AsyncWebServerRequest * request) { - if (request->hasArg("device")) { - if (request->getParam("device")->value() == "ok") ESP.restart(); - } - request->send(200, "text/text", "OK"); // отправляем ответ о выполнении - }); - ROUTER_Connecting(); -} - -void ROUTER_Connecting() { - - led_blink("slow"); - - WiFi.mode(WIFI_STA); - - byte tries = 20; - String _ssid = jsonReadStr(configSetup, "ssid"); - String _password = jsonReadStr(configSetup, "password"); - //WiFi.persistent(false); - - if (_ssid == "" && _password == "") { - WiFi.begin(); - } - else { - WiFi.begin(_ssid.c_str(), _password.c_str()); - Serial.print("ssid: "); - Serial.println(_ssid); - } - // Делаем проверку подключения до тех пор пока счетчик tries - // не станет равен нулю или не получим подключение - while (--tries && WiFi.status() != WL_CONNECTED) - { - if (WiFi.status() == WL_CONNECT_FAILED) { - Serial.println("[E] password is not correct"); - tries = 1; - jsonWriteInt(optionJson, "pass_status", 1); - } - Serial.print("."); - delay(1000); - } - - if (WiFi.status() != WL_CONNECTED) - { - // Если не удалось подключиться запускаем в режиме AP - Serial.println(""); - // WiFi.disconnect(true); - StartAPMode(); - - } - else { - // Иначе удалось подключиться отправляем сообщение - // о подключении и выводим адрес IP - Serial.println(""); - Serial.println("[V] WiFi connected"); - Serial.print("[V] IP address: http://"); - Serial.print(WiFi.localIP()); - Serial.println(""); - jsonWriteStr(configJson, "ip", WiFi.localIP().toString()); - - led_blink("off"); - - //add_dev_in_list("dev.txt", chipID, WiFi.localIP().toString()); - - } -} - -bool StartAPMode() { - Serial.println("WiFi up AP"); - WiFi.disconnect(); - - WiFi.mode(WIFI_AP); - - String _ssidAP = jsonReadStr(configSetup, "ssidAP"); - String _passwordAP = jsonReadStr(configSetup, "passwordAP"); - WiFi.softAP(_ssidAP.c_str(), _passwordAP.c_str()); - IPAddress myIP = WiFi.softAPIP(); - led_blink("on"); - Serial.print("AP IP address: "); - Serial.println(myIP); - jsonWriteStr(configJson, "ip", myIP.toString()); - - if (jsonReadInt(optionJson, "pass_status") != 1) { - ts.add(ROUTER_SEARCHING, 10 * 1000, [&](void*) { - Serial.println("->try find router"); - if (RouterFind(jsonReadStr(configSetup, "ssid"))) { - ts.remove(ROUTER_SEARCHING); - WiFi.scanDelete(); - ROUTER_Connecting(); - MQTT_init(); - } - }, nullptr, true); - } - return true; -} - - -boolean RouterFind(String ssid) { - int n = WiFi.scanComplete (); - Serial.println("n = " + String(n)); - if (n == -2) { //Сканирование не было запущено, запускаем - Serial.println("[WIFI][i] scanning has not been triggered, starting scanning"); - WiFi.scanNetworks (true, false); //async, show_hidden - return false; - } - if (n == -1) { //Сканирование все еще выполняется - Serial.println("[WIFI][i] scanning still in progress"); - return false; - } - if (n == 0) { //ни одна сеть не найдена - Serial.println("[WIFI][i] no any wifi sations, starting scanning"); - WiFi.scanNetworks (true, false); - return false; - } - if (n > 0) { - for (int i = 0; i <= n; i++) { - if (WiFi.SSID (i) == ssid) { - WiFi.scanDelete(); - return true; - } else { - Serial.print(i); - Serial.print(")"); - //Serial.print(ssid); - //Serial.print("<=>"); - if (i == n) { - Serial.print(WiFi.SSID(i)); - Serial.println("; "); - } else { - Serial.print(WiFi.SSID(i)); - Serial.println("; "); - } - } - } - WiFi.scanDelete(); - return false; - } -} - -/* - String scanWIFI() { - uint8_t n = WiFi.scanNetworks(); - DynamicJsonBuffer jsonBuffer; - JsonObject& json = jsonBuffer.createObject(); - JsonArray& networks = json.createNestedArray("networks"); - for (uint8_t i = 0; i < n; i++) { - JsonObject& data = networks.createNestedObject(); - String ssidMy = WiFi.SSID(i); - data["ssid"] = ssidMy; - data["pass"] = (WiFi.encryptionType(i) == ENC_TYPE_NONE) ? "" : "*"; - int8_t dbm = WiFi.RSSI(i); - data["dbm"] = dbm; - if (ssidMy == jsonReadStr(configSetup, "ssid")) { - jsonWriteStr(configJson, "dbm", dbm); - } - } - String root; - json.printTo(root); - return root; - } -*/ -/* - { - "type":"wifi", - "title":"{{LangWiFi1}}", - "name":"ssid", - "state":"{{ssid}}", - "pattern":".{1,}" - }, - { - "type":"password", - "title":"{{LangPass}}", - "name":"ssidPass", - "state":"{{ssidPass}}", - "pattern":".{8,}" - }, -*/ diff --git a/Widgets.ino b/Widgets.ino deleted file mode 100644 index 63320300..00000000 --- a/Widgets.ino +++ /dev/null @@ -1,88 +0,0 @@ -//====================================================================================================================== -//===============================================Создание виджетов======================================================= -void createWidget (String widget_name, String page_name, String page_number, String file, String topic) { - - String widget; - widget = readFile(file, 1024); - - if (widget == "Failed") return; - if (widget == "Large") return; - - widget_name.replace("#", " "); - page_name.replace("#", " "); - - jsonWriteStr(widget, "page", page_name); - jsonWriteStr(widget, "order", page_number); - jsonWriteStr(widget, "descr", widget_name); - jsonWriteStr(widget, "topic", prex + "/" + topic); - -#ifdef layout_in_ram - all_widgets += widget + "\r\n"; -#else - addFile("layout.txt", widget); -#endif - widget = ""; -} - -void createWidgetParam (String widget_name, String page_name, String page_number, String file, String topic, String name1, String param1, String name2, String param2, String name3, String param3) { - - String widget; - widget = readFile(file, 1024); - - if (widget == "Failed") return; - if (widget == "Large") return; - - widget_name.replace("#", " "); - page_name.replace("#", " "); - - jsonWriteStr(widget, "page", page_name); - jsonWriteStr(widget, "order", page_number); - jsonWriteStr(widget, "descr", widget_name); - jsonWriteStr(widget, "topic", prex + "/" + topic); - - if (name1 != "") jsonWriteStr(widget, name1, param1); - if (name2 != "") jsonWriteStr(widget, name2, param2); - if (name3 != "") jsonWriteStr(widget, name3, param3); - -#ifdef layout_in_ram - all_widgets += widget + "\r\n"; -#else - addFile("layout.txt", widget); -#endif - widget = ""; -} - -void createChart (String widget_name, String page_name, String page_number, String file, String topic, String maxCount) { - - String widget; - widget = readFile(file, 1024); - - if (widget == "Failed") return; - if (widget == "Large") return; - - widget_name.replace("#", " "); - page_name.replace("#", " "); - - jsonWriteStr(widget, "page", page_name); - jsonWriteStr(widget, "order", page_number); - //jsonWriteStr(widget, "descr", widget_name); - jsonWriteStr(widget, "series", widget_name); - jsonWriteStr(widget, "maxCount", maxCount); - jsonWriteStr(widget, "topic", prex + "/" + topic); - -#ifdef layout_in_ram - all_widgets += widget + "\r\n"; -#else - addFile("layout.txt", widget); -#endif - widget = ""; -} - -void choose_widget_and_create(String widget_name, String page_name, String page_number, String type, String topik) { - - if (type == "any-data") createWidget (widget_name, page_name, page_number, "widgets/widget.anyData.json", topik); - if (type == "progress-line") createWidget (widget_name, page_name, page_number, "widgets/widget.progLine.json", topik); - if (type == "progress-round") createWidget (widget_name, page_name, page_number, "widgets/widget.progRound.json", topik); - if (type == "fill-gauge") createWidget (widget_name, page_name, page_number, "widgets/widget.fillGauge.json", topik); - -} diff --git a/bus.ino b/bus.ino deleted file mode 100644 index 17486aab..00000000 --- a/bus.ino +++ /dev/null @@ -1,33 +0,0 @@ -void do_i2c_scanning() { - if (i2c_scanning) { - i2c_scanning = false; - String tmp = i2c_scan(); - if (tmp == "error") { - tmp = i2c_scan(); - Serial.println(tmp); - jsonWriteStr(configJson, "i2c", tmp); - } else { - Serial.println(tmp); - jsonWriteStr(configJson, "i2c", tmp); - } - } -} - -String i2c_scan() { - String out; - byte count = 0; - Wire.begin(); - for (byte i = 8; i < 120; i++) { - Wire.beginTransmission(i); - if (Wire.endTransmission() == 0) { - count++; - out += String(count) + ". 0x" + String(i, HEX) + "; "; - delay(1); - } - } - if (count == 0) { - return "error"; - } else { - return out; - } -} diff --git a/data_excess/.exclude.files b/data_excess/.exclude.files deleted file mode 100644 index 955397fa..00000000 --- a/data_excess/.exclude.files +++ /dev/null @@ -1,2 +0,0 @@ -/*.js.gz -/.exclude.files diff --git a/data_excess/ace.js.gz b/data_excess/ace.js.gz deleted file mode 100644 index 7b175c1c..00000000 Binary files a/data_excess/ace.js.gz and /dev/null differ diff --git a/data_excess/config-all.json b/data_excess/config-all.json deleted file mode 100644 index 4b62c9cd..00000000 --- a/data_excess/config-all.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "IoTmanager", - "chipID": "", - "ssidAP": "WiFi", - "passwordAP": "", - "ssid": "your_ssid", - "password": "your_password", - "timezone": 3, - "ntp": "pool.ntp.org", - "mqttServer": "", - "mqttPort": 0, - "mqttPrefix": "/IoTmanager", - "mqttUser": "", - "mqttPass": "", - "scenario": "1", - "pushingbox_id": "", - "web_login": "admin", - "web_pass": "admin", - "udponoff": "1" -} \ No newline at end of file diff --git a/data_excess/edit.htm.gz b/data_excess/edit.htm.gz deleted file mode 100644 index bdfe12d3..00000000 Binary files a/data_excess/edit.htm.gz and /dev/null differ diff --git a/data_excess/favicon.ico b/data_excess/favicon.ico deleted file mode 100644 index 198474d2..00000000 Binary files a/data_excess/favicon.ico and /dev/null differ diff --git a/data_excess/mode-html.js.gz b/data_excess/mode-html.js.gz deleted file mode 100644 index 26b53532..00000000 Binary files a/data_excess/mode-html.js.gz and /dev/null differ diff --git a/data_excess/page.htm.gz b/data_excess/page.htm.gz deleted file mode 100644 index 2213e165..00000000 Binary files a/data_excess/page.htm.gz and /dev/null differ diff --git a/data_excess/robots.txt b/data_excess/robots.txt deleted file mode 100644 index 13375629..00000000 --- a/data_excess/robots.txt +++ /dev/null @@ -1,2 +0,0 @@ -User-agent: * -Disallow: * \ No newline at end of file diff --git a/data_excess/worker-html.js.gz b/data_excess/worker-html.js.gz deleted file mode 100644 index ec8aa87a..00000000 Binary files a/data_excess/worker-html.js.gz and /dev/null differ diff --git a/data_for_edit_for_esp32_ace.js.gz/ace.js.gz b/data_for_edit_for_esp32_ace.js.gz/ace.js.gz deleted file mode 100644 index 7b175c1c..00000000 Binary files a/data_for_edit_for_esp32_ace.js.gz/ace.js.gz and /dev/null differ diff --git a/dependencies/WiFiClientSecure/WiFiClientSecure.cpp b/dependencies/WiFiClientSecure/WiFiClientSecure.cpp deleted file mode 100644 index 3b2c495b..00000000 --- a/dependencies/WiFiClientSecure/WiFiClientSecure.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* - WiFiClientSecure.cpp - Client Secure class for ESP32 - Copyright (c) 2016 Hristo Gochkov All right reserved. - Additions Copyright (C) 2017 Evandro Luis Copercini. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include "WiFiClientSecure.h" -#include -#include -#include - -#undef connect -#undef write -#undef read - - -WiFiClientSecure::WiFiClientSecure() -{ - _connected = false; - - sslclient = new sslclient_context; - ssl_init(sslclient); - sslclient->socket = -1; - - _CA_cert = NULL; - _cert = NULL; - _private_key = NULL; - next = NULL; -} - - -WiFiClientSecure::WiFiClientSecure(int sock) -{ - _connected = false; - - sslclient = new sslclient_context; - ssl_init(sslclient); - sslclient->socket = sock; - - if (sock >= 0) { - _connected = true; - } - - _CA_cert = NULL; - _cert = NULL; - _private_key = NULL; - next = NULL; -} - -WiFiClientSecure::~WiFiClientSecure() -{ - stop(); -} - -WiFiClientSecure &WiFiClientSecure::operator=(const WiFiClientSecure &other) -{ - stop(); - sslclient->socket = other.sslclient->socket; - _connected = other._connected; - return *this; -} - -void WiFiClientSecure::stop() -{ - if (sslclient->socket >= 0) { - close(sslclient->socket); - sslclient->socket = -1; - _connected = false; - } - stop_ssl_socket(sslclient, _CA_cert, _cert, _private_key); -} - -int WiFiClientSecure::connect(IPAddress ip, uint16_t port) -{ - return connect(ip, port, _CA_cert, _cert, _private_key); -} - -int WiFiClientSecure::connect(const char *host, uint16_t port) -{ - return connect(host, port, _CA_cert, _cert, _private_key); -} - -int WiFiClientSecure::connect(IPAddress ip, uint16_t port, const char *_CA_cert, const char *_cert, const char *_private_key) -{ - int ret = start_ssl_client(sslclient, ip, port, _CA_cert, _cert, _private_key); - if (ret < 0) { - log_e("lwip_connect_r: %d", errno); - stop(); - return 0; - } - _connected = true; - return 1; -} - -int WiFiClientSecure::connect(const char *host, uint16_t port, const char *_CA_cert, const char *_cert, const char *_private_key) -{ - struct hostent *server; - server = gethostbyname(host); - if (server == NULL) { - return 0; - } - IPAddress srv((const uint8_t *)(server->h_addr)); - return connect(srv, port, _CA_cert, _cert, _private_key); -} - - -size_t WiFiClientSecure::write(uint8_t data) -{ - return write(&data, 1); -} - -int WiFiClientSecure::read() -{ - uint8_t data = 0; - int res = read(&data, 1); - if (res < 0) { - return res; - } - return data; -} - -size_t WiFiClientSecure::write(const uint8_t *buf, size_t size) -{ - if (!_connected) { - return 0; - } - int res = send_ssl_data(sslclient, buf, size); - if (res < 0) { - - stop(); - res = 0; - } - return res; -} - -int WiFiClientSecure::read(uint8_t *buf, size_t size) -{ - if (!available()) { - return -1; - } - int res = get_ssl_receive(sslclient, buf, size); - if (res < 0) { - - stop(); - } - return res; -} - -int WiFiClientSecure::available() -{ - if (!_connected) { - return 0; - } - int res = data_to_read(sslclient); - if (res < 0 ) { - stop(); - } - return res; -} - -uint8_t WiFiClientSecure::connected() -{ - uint8_t dummy = 0; - read(&dummy, 0); - - return _connected; -} - -void WiFiClientSecure::setCACert (const char *rootCA) -{ - _CA_cert = rootCA; -} - -void WiFiClientSecure::setCertificate (const char *client_ca) -{ - _cert = client_ca; -} - -void WiFiClientSecure::setPrivateKey (const char *private_key) -{ - _private_key = private_key; -} - diff --git a/dependencies/WiFiClientSecure/WiFiClientSecure.h b/dependencies/WiFiClientSecure/WiFiClientSecure.h deleted file mode 100644 index 5ffc3ae0..00000000 --- a/dependencies/WiFiClientSecure/WiFiClientSecure.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - WiFiClientSecure.h - Base class that provides Client SSL to ESP32 - Copyright (c) 2011 Adrian McEwen. All right reserved. - Additions Copyright (C) 2017 Evandro Luis Copercini. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef WiFiClientSecure_h -#define WiFiClientSecure_h -#include "Arduino.h" -#include "IPAddress.h" -#include -#include "ssl_client.h" - -class WiFiClientSecure : public Client -{ -protected: - bool _connected; - sslclient_context *sslclient; - - const char *_CA_cert; - const char *_cert; - const char *_private_key; - -public: - WiFiClientSecure *next; - WiFiClientSecure(); - WiFiClientSecure(int socket); - ~WiFiClientSecure(); - int connect(IPAddress ip, uint16_t port); - int connect(const char *host, uint16_t port); - int connect(IPAddress ip, uint16_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key); - int connect(const char *host, uint16_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key); - size_t write(uint8_t data); - size_t write(const uint8_t *buf, size_t size); - int available(); - int read(); - int read(uint8_t *buf, size_t size); - int peek() - { - return 0; - } - void flush() {} - void stop(); - uint8_t connected(); - - void setCACert(const char *rootCA); - void setCertificate(const char *client_ca); - void setPrivateKey (const char *private_key); - - operator bool() - { - return connected(); - } - WiFiClientSecure &operator=(const WiFiClientSecure &other); - bool operator==(const bool value) - { - return bool() == value; - } - bool operator!=(const bool value) - { - return bool() != value; - } - bool operator==(const WiFiClientSecure &); - bool operator!=(const WiFiClientSecure &rhs) - { - return !this->operator==(rhs); - }; - - int socket() - { - return sslclient->socket = -1; - } - - //friend class WiFiServer; - using Print::write; -}; - -#endif /* _WIFICLIENT_H_ */ diff --git a/dependencies/WiFiClientSecure/ssl_client.cpp b/dependencies/WiFiClientSecure/ssl_client.cpp deleted file mode 100644 index 15c2cb81..00000000 --- a/dependencies/WiFiClientSecure/ssl_client.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/* Provide SSL/TLS functions to ESP32 with Arduino IDE -* -* Adapted from the ssl_client1 example of mbedtls. -* -* Original Copyright (C) 2006-2015, ARM Limited, All Rights Reserved, Apache 2.0 License. -* Additions Copyright (C) 2017 Evandro Luis Copercini, Apache 2.0 License. -*/ - -#include "Arduino.h" -#include -#include -#include -#include -#include -#include -#include "ssl_client.h" - -const char *pers = "esp32-tls"; - -static int handle_error(int err) -{ -#ifdef MBEDTLS_ERROR_C - char error_buf[100]; - mbedtls_strerror(err, error_buf, 100); - log_e("%s", error_buf); -#endif - log_e("MbedTLS message code: %d", err); - return err; -} - - -void ssl_init(sslclient_context *ssl_client) -{ - mbedtls_ssl_init(&ssl_client->ssl_ctx); - mbedtls_ssl_config_init(&ssl_client->ssl_conf); - mbedtls_ctr_drbg_init(&ssl_client->drbg_ctx); -} - - -int start_ssl_client(sslclient_context *ssl_client, uint32_t ipAddress, uint32_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key) -{ - char buf[512]; - int ret, flags, timeout; - int enable = 1; - log_i("Free heap before TLS %u", xPortGetFreeHeapSize()); - - log_i("Starting socket"); - ssl_client->socket = -1; - - ssl_client->socket = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (ssl_client->socket < 0) { - log_e("ERROR opening socket"); - return ssl_client->socket; - } - - struct sockaddr_in serv_addr; - memset(&serv_addr, 0, sizeof(serv_addr)); - serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = ipAddress; - serv_addr.sin_port = htons(port); - - if (lwip_connect(ssl_client->socket, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == 0) { - timeout = 30000; - lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); - lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); - lwip_setsockopt(ssl_client->socket, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable)); - lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable)); - } else { - log_e("Connect to Server failed!"); - return -1; - } - - fcntl( ssl_client->socket, F_SETFL, fcntl( ssl_client->socket, F_GETFL, 0 ) | O_NONBLOCK ); - - log_i("Seeding the random number generator"); - mbedtls_entropy_init(&ssl_client->entropy_ctx); - - ret = mbedtls_ctr_drbg_seed(&ssl_client->drbg_ctx, mbedtls_entropy_func, - &ssl_client->entropy_ctx, (const unsigned char *) pers, strlen(pers)); - if (ret < 0) { - return handle_error(ret); - } - - log_i("Setting up the SSL/TLS structure..."); - - if ((ret = mbedtls_ssl_config_defaults(&ssl_client->ssl_conf, - MBEDTLS_SSL_IS_CLIENT, - MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { - return handle_error(ret); - } - - /* MBEDTLS_SSL_VERIFY_REQUIRED if a CA certificate is defined on Arduino IDE and - MBEDTLS_SSL_VERIFY_NONE if not. - */ - if (rootCABuff != NULL) { - log_i("Loading CA cert"); - mbedtls_x509_crt_init(&ssl_client->ca_cert); - mbedtls_ssl_conf_authmode(&ssl_client->ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED); - ret = mbedtls_x509_crt_parse(&ssl_client->ca_cert, (const unsigned char *)rootCABuff, strlen(rootCABuff) + 1); - mbedtls_ssl_conf_ca_chain(&ssl_client->ssl_conf, &ssl_client->ca_cert, NULL); - //mbedtls_ssl_conf_verify(&ssl_client->ssl_ctx, my_verify, NULL ); - if (ret < 0) { - return handle_error(ret); - } - } else { - mbedtls_ssl_conf_authmode(&ssl_client->ssl_conf, MBEDTLS_SSL_VERIFY_NONE); - log_i("WARNING: Use certificates for a more secure communication!"); - } - - if (cli_cert != NULL && cli_key != NULL) { - mbedtls_x509_crt_init(&ssl_client->client_cert); - mbedtls_pk_init(&ssl_client->client_key); - - log_i("Loading CRT cert"); - - ret = mbedtls_x509_crt_parse(&ssl_client->client_cert, (const unsigned char *)cli_cert, strlen(cli_cert) + 1); - if (ret < 0) { - return handle_error(ret); - } - - log_i("Loading private key"); - ret = mbedtls_pk_parse_key(&ssl_client->client_key, (const unsigned char *)cli_key, strlen(cli_key) + 1, NULL, 0); - - if (ret != 0) { - return handle_error(ret); - } - - mbedtls_ssl_conf_own_cert(&ssl_client->ssl_conf, &ssl_client->client_cert, &ssl_client->client_key); - } - - /* - // TODO: implement match CN verification - - log_i("Setting hostname for TLS session..."); - - // Hostname set here should match CN in server certificate - if((ret = mbedtls_ssl_set_hostname(&ssl_client->ssl_ctx, host)) != 0) - { - return handle_error(ret); - - } - */ - - mbedtls_ssl_conf_rng(&ssl_client->ssl_conf, mbedtls_ctr_drbg_random, &ssl_client->drbg_ctx); - - if ((ret = mbedtls_ssl_setup(&ssl_client->ssl_ctx, &ssl_client->ssl_conf)) != 0) { - return handle_error(ret); - } - - mbedtls_ssl_set_bio(&ssl_client->ssl_ctx, &ssl_client->socket, mbedtls_net_send, mbedtls_net_recv, NULL ); - - log_i("Performing the SSL/TLS handshake..."); - - while ((ret = mbedtls_ssl_handshake(&ssl_client->ssl_ctx)) != 0) { - if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != -76) { //workaround for bug: https://github.com/espressif/esp-idf/issues/434 - return handle_error(ret); - } - delay(10); - vPortYield(); - } - - - if (cli_cert != NULL && cli_key != NULL) { - log_i("Protocol is %s Ciphersuite is %s", mbedtls_ssl_get_version(&ssl_client->ssl_ctx), mbedtls_ssl_get_ciphersuite(&ssl_client->ssl_ctx)); - if ((ret = mbedtls_ssl_get_record_expansion(&ssl_client->ssl_ctx)) >= 0) { - log_i("Record expansion is %d", ret); - } else { - log_i("Record expansion is unknown (compression)"); - } - } - - log_i("Verifying peer X.509 certificate..."); - - if ((flags = mbedtls_ssl_get_verify_result(&ssl_client->ssl_ctx)) != 0) { - log_e("Failed to verify peer certificate!"); - bzero(buf, sizeof(buf)); - mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", flags); - log_e("verification info: %s", buf); - stop_ssl_socket(ssl_client, rootCABuff, cli_cert, cli_key); //It's not safe continue. - return handle_error(ret); - } else { - log_i("Certificate verified."); - } - - log_i("Free heap after TLS %u", xPortGetFreeHeapSize()); - - return ssl_client->socket; -} - - -void stop_ssl_socket(sslclient_context *ssl_client, const char *rootCABuff, const char *cli_cert, const char *cli_key) -{ - log_i("Cleaning SSL connection."); - - if (ssl_client->socket >= 0) { - close(ssl_client->socket); - ssl_client->socket = -1; - } - - mbedtls_ssl_free(&ssl_client->ssl_ctx); - mbedtls_ssl_config_free(&ssl_client->ssl_conf); - mbedtls_ctr_drbg_free(&ssl_client->drbg_ctx); - mbedtls_entropy_free(&ssl_client->entropy_ctx); - - if (rootCABuff != NULL) { - mbedtls_x509_crt_free(&ssl_client->ca_cert); - } - - if (cli_cert != NULL) { - mbedtls_x509_crt_free(&ssl_client->client_cert); - } - - if (cli_key != NULL) { - mbedtls_pk_free(&ssl_client->client_key); - } -} - - -int data_to_read(sslclient_context *ssl_client) -{ - int ret, res; - ret = mbedtls_ssl_read(&ssl_client->ssl_ctx, NULL, 0); - //log_e("RET: %i",ret); //for low level debug - res = mbedtls_ssl_get_bytes_avail(&ssl_client->ssl_ctx); - //log_e("RES: %i",res); - if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret < 0 && ret != -76) { - return handle_error(ret); - } - - return res; -} - - -int send_ssl_data(sslclient_context *ssl_client, const uint8_t *data, uint16_t len) -{ - //log_i("Writing HTTP request..."); //for low level debug - int ret = -1; - - while ((ret = mbedtls_ssl_write(&ssl_client->ssl_ctx, data, len)) <= 0) { - if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != -76) { - return handle_error(ret); - } - } - - len = ret; - //log_i("%d bytes written", len); //for low level debug - return ret; -} - - -int get_ssl_receive(sslclient_context *ssl_client, uint8_t *data, int length) -{ - //log_i( "Reading HTTP response..."); //for low level debug - int ret = -1; - - ret = mbedtls_ssl_read(&ssl_client->ssl_ctx, data, length); - - //log_i( "%d bytes readed", ret); //for low level debug - return ret; -} diff --git a/dependencies/WiFiClientSecure/ssl_client.h b/dependencies/WiFiClientSecure/ssl_client.h deleted file mode 100644 index 5fc98ad7..00000000 --- a/dependencies/WiFiClientSecure/ssl_client.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Provide SSL/TLS functions to ESP32 with Arduino IDE - * by Evandro Copercini - 2017 - Apache 2.0 License - */ - -#ifndef ARD_SSL_H -#define ARD_SSL_H -#include "mbedtls/platform.h" -#include "mbedtls/net.h" -#include "mbedtls/debug.h" -#include "mbedtls/ssl.h" -#include "mbedtls/entropy.h" -#include "mbedtls/ctr_drbg.h" -#include "mbedtls/error.h" - -typedef struct sslclient_context { - int socket; - mbedtls_net_context net_ctx; - mbedtls_ssl_context ssl_ctx; - mbedtls_ssl_config ssl_conf; - - mbedtls_ctr_drbg_context drbg_ctx; - mbedtls_entropy_context entropy_ctx; - - mbedtls_x509_crt ca_cert; - mbedtls_x509_crt client_cert; - mbedtls_pk_context client_key; -} sslclient_context; - - -void ssl_init(sslclient_context *ssl_client); -int start_ssl_client(sslclient_context *ssl_client, uint32_t ipAddress, uint32_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key); -void stop_ssl_socket(sslclient_context *ssl_client, const char *rootCABuff, const char *cli_cert, const char *cli_key); -int data_to_read(sslclient_context *ssl_client); -int send_ssl_data(sslclient_context *ssl_client, const uint8_t *data, uint16_t len); -int get_ssl_receive(sslclient_context *ssl_client, uint8_t *data, int length); - -#endif diff --git a/esp32-esp8266_iot-manager_modules_firmware.ino b/esp32-esp8266_iot-manager_modules_firmware.ino deleted file mode 100644 index 2d4b9031..00000000 --- a/esp32-esp8266_iot-manager_modules_firmware.ino +++ /dev/null @@ -1,89 +0,0 @@ -#include "set.h" - -void setup() { - //-------------------------------------------------------------- - File_system_init(); - Serial.println("SPIFFS_init"); - //-------------------------------------------------------------- - CMD_init(); - Serial.println("[V] CMD_init"); - //-------------------------------------------------------------- - sensors_init(); - Serial.println("[V] sensors_init"); - //-------------------------------------------------------------- - All_init(); - Serial.println("[V] All_init"); - //-------------------------------------------------------------- - WIFI_init(); - Serial.println("[V] WIFI_init"); - //-------------------------------------------------------------- - statistics_init(); - Serial.println("[V] statistics_init"); - //-------------------------------------------------------------- - initUpgrade(); - Serial.println("[V] initUpgrade"); - //-------------------------------------------------------------- - Web_server_init(); - Serial.println("[V] Web_server_init"); - //-------------------------------------------------------------- - MQTT_init(); - Serial.println("[V] MQTT_init"); - //-------------------------------------------------------------- - Time_Init(); - Serial.println("[V] Time_Init"); - //-------------------------------------------------------------- -#ifdef push_enable - Push_init(); - Serial.println("[V] Push_init"); -#endif - //-------------------------------------------------------------- -#ifdef UDP_enable - UDP_init(); - Serial.println("[V] UDP_init"); -#endif - //-------------------------------------------------------------- - - - - ts.add(TEST, 10000, [&](void*) { - getMemoryLoad("[i] periodic check of"); - //ws.textAll(json); - }, nullptr, true); - - - just_load = false; -} - - -void loop() { - -#ifdef OTA_enable - ArduinoOTA.handle(); -#endif - -#ifdef WS_enable - ws.cleanupClients(); -#endif - - not_async_actions(); - - handleMQTT(); - handleCMD_loop(); - handleButton(); - handleScenario(); -#ifdef UDP_enable - handleUdp(); -#endif - ts.update(); -} - -void not_async_actions() { - do_mqtt_connection(); - do_upgrade_url(); - do_upgrade(); -#ifdef UDP_enable - do_udp_data_parse(); - do_mqtt_send_settings_to_udp(); -#endif - do_i2c_scanning(); -} diff --git a/include/Cmd.h b/include/Cmd.h new file mode 100644 index 00000000..47577e82 --- /dev/null +++ b/include/Cmd.h @@ -0,0 +1,36 @@ + +#pragma once + +#include "Arduino.h" + +extern void CMD_init(); +extern void button(); +extern void buttonSet(); +extern void buttonChange(); +extern void pinSet(); +extern void pinChange(); +extern void handle_time_init(); +extern void pwm(); +extern void switch_(); +extern void pwmSet(); +extern void stepper(); +extern void stepperSet(); +extern void servo_(); +extern void servoSet(); +extern void serialBegin(); +extern void serialWrite(); +extern void logging(); +extern void inputDigit(); +extern void digitSet(); +extern void inputTime(); +extern void button(); +extern void timeSet(); +extern void text(); +extern void textSet(); +extern void mqttOrderSend(); +extern void httpOrderSend(); +extern void firmware(); +extern void update_firmware(); +extern void Scenario_init(); +extern void txtExecution(String file); +extern void stringExecution(String str); diff --git a/include/FileSystem.h b/include/FileSystem.h new file mode 100644 index 00000000..ccec5ffb --- /dev/null +++ b/include/FileSystem.h @@ -0,0 +1,6 @@ +#pragma once + +#include +#include + +extern void File_system_init(); \ No newline at end of file diff --git a/include/Init.h b/include/Init.h new file mode 100644 index 00000000..c593153c --- /dev/null +++ b/include/Init.h @@ -0,0 +1,5 @@ +#pragma once + +extern void Scenario_init(); +extern void Device_init(); +extern void prsets_init(); diff --git a/include/Logging.h b/include/Logging.h new file mode 100644 index 00000000..e3be11af --- /dev/null +++ b/include/Logging.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +extern void logging(); +extern void deleteOldDate(String file, int seted_number_of_lines, String date_to_add); \ No newline at end of file diff --git a/include/Mqtt.h b/include/Mqtt.h new file mode 100644 index 00000000..21805a4e --- /dev/null +++ b/include/Mqtt.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +extern boolean MQTT_Connecting(); +extern boolean sendMQTT(String end_of_topik, String data); +extern boolean sendCHART(String topik, String data); +extern void sendSTATUS(String topik, String state); +extern void sendCONTROL(String id, String topik, String state); + +extern void do_mqtt_connection(); \ No newline at end of file diff --git a/include/Scenario.h b/include/Scenario.h new file mode 100644 index 00000000..06875256 --- /dev/null +++ b/include/Scenario.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +extern void eventGen(String event_name, String number); \ No newline at end of file diff --git a/include/Sensors.h b/include/Sensors.h new file mode 100644 index 00000000..84a96345 --- /dev/null +++ b/include/Sensors.h @@ -0,0 +1,3 @@ +#pragma once + +void sensors_init(); \ No newline at end of file diff --git a/include/Strings_.h b/include/Strings_.h new file mode 100644 index 00000000..106957e0 --- /dev/null +++ b/include/Strings_.h @@ -0,0 +1,138 @@ +#pragma once + +// #include +#include + +#include +#include + +class char_array { + private: + char *p_stringarray; //initial input array + char *p_inputstring; //holds actual length data + //char **pp_database_string; //allocate data database.cpp + int stringsize; //holds array size to allocate memory + int charinput; //holds array input size + + public: + inline char_array(); //inline so other functions can call on it + inline ~char_array(); + inline void getinput(char *&); //retrieves user input + inline void grabline(char *&); //retrieve line with whitespace included NOT COMPLETE, may not need + inline int sortline(char **&, char *&); //sorts line into an array of strings and returns number of separate strings + inline int arraysize(); //returns size of string array + inline void printinput(); //print input string + inline void changedefaultsize(); //change default input size NOT COMPLETE +}; + +inline char_array::char_array() //constructor +{ + stringsize = 0; + charinput = 64; + p_stringarray = new char[charinput]; +} + +inline char_array::~char_array() //destructor +{ + delete[] p_inputstring; + delete[] p_stringarray; +} + +inline void char_array::getinput(char *&p_stringin) { + stringsize = 0; + + scanf("%63s", p_stringarray); //get input string + + while (p_stringarray[stringsize] != 0) //finding out the size of string array + { + stringsize++; + } + stringsize++; + + p_inputstring = new char[stringsize]; //reallocate memory block and set array inside + for (int i = 0; i < stringsize; i++) { + p_inputstring[i] = p_stringarray[i]; + } + + p_inputstring[stringsize - 1] = '\x00'; + + p_stringin = new char[stringsize]; //set pp_stringin + + p_stringin = p_inputstring; +} + +inline void char_array::grabline(char *&p_stringin) { + stringsize = 0; + std::cin.getline(p_stringarray, charinput); + while (p_stringarray[stringsize] != 0) { + stringsize++; + } + stringsize++; + p_inputstring = new char[stringsize]; + + for (int i = 0; i < stringsize; i++) { + p_inputstring[i] = p_stringarray[i]; + } + + p_stringin = new char[stringsize]; + p_stringin = p_inputstring; +} + +inline int char_array::sortline(char **&pp_stringin, char *&p_string) { + int position = 0; //position in string + int charcount = 1; //how many characters there are + int wordnum; //which word is being processed + int wordcount = 1; //number of words in string + int bookmark = 0; //holds last known position + + while (p_string[position] == ' ') { + position++; + } + + wordnum = position; //borrow wordnum to hold position value + while (p_string[position] != '\x00') //find total inputted string word length + { + if ((p_string[position] == ' ') && ((p_string[position + 1] != ' ') || (p_string[position + 1] != '\x00'))) { + wordcount++; + } + position++; + } + position = wordnum; //set position to original value + for (wordnum = 0; wordnum < wordcount; wordnum++) { + charcount = 1; + while (p_string[position] == ' ') { + position++; + } + while ((p_string[position] != ' ') && (p_string[position] != '\x00')) { + position++; + charcount++; + } + pp_stringin[wordnum] = new char[charcount]; + + for (int i = 0; i < charcount; i++) { + pp_stringin[wordnum][i] = p_string[i + bookmark]; + } + pp_stringin[wordnum][charcount - 1] = '\x00'; + bookmark = position + 1; + } + + return wordcount; +} + +inline int char_array::arraysize() { + if (stringsize != 0) { + return stringsize; + } else { + printf("Array size is set at 0\n"); + return 0; + } +} + +inline void char_array::printinput() { + printf("%s", p_inputstring); +} + +inline void char_array::changedefaultsize() { + printf("Input new default input string size: "); + scanf("%i", charinput); +} \ No newline at end of file diff --git a/include/TimeUtils.h b/include/TimeUtils.h new file mode 100644 index 00000000..6527d93d --- /dev/null +++ b/include/TimeUtils.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +extern int timeToMin(String Time); +extern String GetDataDigital(); +extern String GetDate(); +extern String GetTimeWOsec(); +extern String GetTime(); +extern String GetTimeUnix(); +extern void reconfigTime(); +extern void saveConfig(); +extern String GetTimeUnix(); +extern void time_check(); diff --git a/include/Timers.h b/include/Timers.h new file mode 100644 index 00000000..0b74a588 --- /dev/null +++ b/include/Timers.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +extern void Timer_countdown_init(); +extern void addTimer(String number, String time); +extern int readTimer(int number); +extern void delTimer(String number); +extern void timerStop(); +extern void delTimer(String number); \ No newline at end of file diff --git a/include/Upgrade.h b/include/Upgrade.h new file mode 100644 index 00000000..6a399da7 --- /dev/null +++ b/include/Upgrade.h @@ -0,0 +1,3 @@ +#pragma once + +extern void initUpgrade(); diff --git a/include/WiFiUtils.h b/include/WiFiUtils.h new file mode 100644 index 00000000..de80d0e0 --- /dev/null +++ b/include/WiFiUtils.h @@ -0,0 +1,4 @@ +#pragma once + +extern bool StartAPMode(); +extern void ROUTER_Connecting(); \ No newline at end of file diff --git a/include/Widgets.h b/include/Widgets.h new file mode 100644 index 00000000..fdb7e103 --- /dev/null +++ b/include/Widgets.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +extern void createWidget(String widget_name, String page_name, String page_number, String file, String topic); +extern void createWidgetParam(String widget_name, String page_name, String page_number, String file, String topic, String name1, String param1, String name2, String param2, String name3, String param3); +extern void choose_widget_and_create(String widget_name, String page_name, String page_number, String type, String topik); +extern void createChart(String widget_name, String page_name, String page_number, String file, String topic, String maxCount); diff --git a/include/i2c_bus.h b/include/i2c_bus.h new file mode 100644 index 00000000..68440aae --- /dev/null +++ b/include/i2c_bus.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +extern void do_i2c_scanning(); + +extern String i2c_scan(); \ No newline at end of file diff --git a/include/main.h b/include/main.h new file mode 100644 index 00000000..27d7c0f7 --- /dev/null +++ b/include/main.h @@ -0,0 +1,31 @@ + +#pragma once + +#include + +void getMemoryLoad(String text); + +extern String jsonReadStr(String& json, String name); +extern int jsonReadInt(String& json, String name); +extern String jsonWriteInt(String& json, String name, int volume); +extern String jsonWriteStr(String& json, String name, String volume); +extern void saveConfig(); +extern String jsonWriteFloat(String& json, String name, float volume); + +extern String getURL(String urls); + +extern String writeFile(String fileName, String strings); +extern String readFile(String fileName, size_t len); +extern String addFile(String fileName, String strings); + +extern String selectFromMarkerToMarker(String str, String found, int number); +extern String selectToMarker(String str, String found); +extern String deleteAfterDelimiter(String str, String found); +extern String deleteBeforeDelimiter(String str, String found); +extern String deleteBeforeDelimiterTo(String str, String found); + +extern void servo_(); +extern boolean isDigitStr(String str); +extern String jsonWriteStr(String& json, String name, String volume); + +extern void led_blink(String satus); \ No newline at end of file diff --git a/include/push_pushingbox.h b/include/push_pushingbox.h new file mode 100644 index 00000000..ff3f9cf9 --- /dev/null +++ b/include/push_pushingbox.h @@ -0,0 +1,63 @@ +#pragma once + +#include "main.h" +#include "set.h" + +inline void Push_init() { + server.on("/pushingboxDate", HTTP_GET, [](AsyncWebServerRequest* request) { + if (request->hasArg("pushingbox_id")) { + jsonWriteStr(configSetup, "pushingbox_id", request->getParam("pushingbox_id")->value()); + } + + saveConfig(); + + request->send(200, "text/text", "ok"); // отправляем ответ о выполнении + }); +} + +inline void pushControl() { + String title = sCmd.next(); + title.replace("#", " "); + String body = sCmd.next(); + body.replace("#", " "); + + static String body_old; + + const char* logServer = "api.pushingbox.com"; + String deviceId = jsonReadStr(configSetup, "pushingbox_id"); + + Serial.println("- starting client"); + + WiFiClient client_push; + + Serial.println("- connecting to pushing server: " + String(logServer)); + if (!client_push.connect(logServer, 80)) { + Serial.println("- not connected"); + } else { + Serial.println("- succesfully connected"); + + String postStr = "devid="; + postStr += String(deviceId); + + postStr += "&title="; + postStr += String(title); + + postStr += "&body="; + postStr += String(body); + + postStr += "\r\n\r\n"; + + Serial.println("- sending data..."); + + client_push.print("POST /pushingbox HTTP/1.1\n"); + client_push.print("Host: api.pushingbox.com\n"); + client_push.print("Connection: close\n"); + client_push.print("Content-Type: application/x-www-form-urlencoded\n"); + client_push.print("Content-Length: "); + client_push.print(postStr.length()); + client_push.print("\n\n"); + client_push.print(postStr); + } + client_push.stop(); + Serial.println("- stopping the client"); +} diff --git a/set.h b/include/set.h similarity index 80% rename from set.h rename to include/set.h index c1de1f87..a6d4d9fd 100644 --- a/set.h +++ b/include/set.h @@ -1,3 +1,7 @@ +#pragma once + +#include + /******************************************************************* **********************FIRMWARE SETTINGS**************************** ******************************************************************/ @@ -26,66 +30,57 @@ boolean mb_4_of_memory = true; /*================================================================*/ #define wifi_mqtt_reconnecting 20000 #define blink_pin 2 -#define tank_level_times_to_send 10 //после скольки выстрелов делать отправку данных +#define tank_level_times_to_send 10 //после скольки выстрелов делать отправку данных #define statistics_update 1000 * 60 * 60 * 2 /*================================================================*/ - +//===============общие библиотеки и объекты=============================== +#include +#include +#include +#include +#include +#include //===============библиотеки и объекты для ESP8266======================= #ifdef ESP8266 -#include #include -#include #include +#include +#include ESP8266HTTPUpdateServer httpUpdater; #include WiFiUDP Udp; #include Servo myServo1; Servo myServo2; - #ifdef MDNS_enable #include #endif - #endif - //===============библиотеки и объекты для ESP32=========================== #ifdef ESP32 -#include +#include +#include #include #include #include -#include +#include #include -#include "AsyncUDP.h" AsyncUDP udp; -#include +#include Servo myServo1; Servo myServo2; - #ifdef MDNS_enable #include #endif - #endif - -//===============общие библиотеки и объекты=============================== -#include -#include "time.h" - #ifdef OTA_enable #include #endif -#include -#include -#include - -#include AsyncWebServer server(80); #ifdef WS_enable @@ -93,10 +88,25 @@ AsyncWebSocket ws("/ws"); #endif AsyncEventSource events("/events"); -#include - #include -enum {ROUTER_SEARCHING, WIFI_MQTT_CONNECTION_CHECK, SENSORS, STEPPER1, STEPPER2, LOG1, LOG2, LOG3, LOG4, LOG5, TIMER_COUNTDOWN, TIME, TIME_SYNC, STATISTICS, UDP, UDP_DB, TEST }; +#include +enum { ROUTER_SEARCHING, + WIFI_MQTT_CONNECTION_CHECK, + SENSORS, + STEPPER1, + STEPPER2, + LOG1, + LOG2, + LOG3, + LOG4, + LOG5, + TIMER_COUNTDOWN, + TIME, + TIME_SYNC, + STATISTICS, + UDP, + UDP_DB, + TEST }; TickerScheduler ts(TEST + 1); #include @@ -109,21 +119,21 @@ StringCommand sCmd; #include #define NUM_BUTTONS 6 boolean but[NUM_BUTTONS]; -Bounce * buttons = new Bounce[NUM_BUTTONS]; +Bounce *buttons = new Bounce[NUM_BUTTONS]; #ifdef level_enable -#include "GyverFilters.h" //настраивается в GyverHacks.h - MEDIAN_FILTER_SIZE +#include "GyverFilters.h" //настраивается в GyverHacks.h - MEDIAN_FILTER_SIZE GMedian medianFilter; #endif #ifdef dallas_enable -#include #include +#include OneWire *oneWire; DallasTemperature sensors; #endif -#ifdef dht_enable +#ifdef dht_enable #include DHTesp dht; #endif @@ -132,14 +142,14 @@ DHTesp dht; #ifdef bmp_enable #include -Adafruit_BMP280 bmp; // use I2C interface +Adafruit_BMP280 bmp; // use I2C interface Adafruit_Sensor *bmp_temp = bmp.getTemperatureSensor(); Adafruit_Sensor *bmp_pressure = bmp.getPressureSensor(); #endif #ifdef bme_enable #include -Adafruit_BME280 bme; // use I2C interface +Adafruit_BME280 bme; // use I2C interface Adafruit_Sensor *bme_temp = bme.getTemperatureSensor(); Adafruit_Sensor *bme_pressure = bme.getPressureSensor(); Adafruit_Sensor *bme_humidity = bme.getHumiditySensor(); @@ -148,10 +158,9 @@ Adafruit_Sensor *bme_humidity = bme.getHumiditySensor(); //#include //SoftwareSerial mySerial(14, 12); - //===============FIRMWARE VARS======================== boolean just_load = true; -const char* hostName = "IoT Manager"; +const char *hostName = "IoT Manager"; //JSON String configSetup = "{}"; String configJson = "{}"; @@ -179,7 +188,7 @@ String bme280P_value_name; String bme280H_value_name; String bme280A_value_name; -int sensors_reading_map [] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +int sensors_reading_map[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //============================0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12,13,14 //LOGGING @@ -188,7 +197,7 @@ int enter_to_logging_counter; //NTP and TIME String current_time; //SCENARIO -int scenario_line_status [] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; +int scenario_line_status[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; //ERRORS int wifi_lost_error = 0; int mqtt_lost_error = 0; @@ -204,10 +213,10 @@ boolean i2c_scanning = false; boolean udp_busy = false; unsigned int udp_port = 4210; #ifdef ESP8266 -IPAddress udp_multicastIP (255, 255, 255, 255); +IPAddress udp_multicastIP(255, 255, 255, 255); #endif #ifdef ESP32 -IPAddress udp_multicastIP (239, 255, 255, 255); +IPAddress udp_multicastIP(239, 255, 255, 255); #endif String received_ip; String received_udp_line; diff --git a/lib/ESP8266-StringCommand/StringCommand.cpp b/lib/ESP8266-StringCommand/StringCommand.cpp new file mode 100644 index 00000000..f6c0e0d4 --- /dev/null +++ b/lib/ESP8266-StringCommand/StringCommand.cpp @@ -0,0 +1,132 @@ +/** + * SerialCommand - A Wiring/Arduino library to tokenize and parse commands + * received over a serial port. + * + * Copyright (C) 2012 Stefan Rado + * Copyright (C) 2011 Steven Cogswell + * http://husks.wordpress.com + * + * Version 20120522 + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this library. If not, see . + */ +#include "StringCommand.h" + +/** + * Constructor makes sure some things are set. + */ +StringCommand::StringCommand() + : commandList(NULL), + commandCount(0), + defaultHandler(NULL), + term('\n'), // default terminator for commands, newline character + last(NULL) +{ + strcpy(delim, " "); // strtok_r needs a null-terminated string + clearBuffer(); +} + +/** + * Adds a "command" and a handler function to the list of available commands. + * This is used for matching a found token in the buffer, and gives the pointer + * to the handler function to deal with it. + */ +void StringCommand::addCommand(const char *command, void (*function)()) { + #ifdef SERIALCOMMAND_DEBUG + Serial.print("Adding command ("); + Serial.print(commandCount); + Serial.print("): "); + Serial.println(command); + #endif + + commandList = (StringCommandCallback *) realloc(commandList, (commandCount + 1) * sizeof(StringCommandCallback)); + strncpy(commandList[commandCount].command, command, SERIALCOMMAND_MAXCOMMANDLENGTH); + commandList[commandCount].function = function; + commandCount++; +} + +/** + * This sets up a handler to be called in the event that the receveived command string + * isn't in the list of commands. + */ +void StringCommand::setDefaultHandler(void (*function)(const char *)) { + defaultHandler = function; +} + + +/** + * This checks the Serial stream for characters, and assembles them into a buffer. + * When the terminator character (default '\n') is seen, it starts parsing the + * buffer for a prefix command, and calls handlers setup by addCommand() member + */ +void StringCommand::readStr(String sBuffer ) { + sBuffer.toCharArray(buffer, SERIALCOMMAND_BUFFER); + #ifdef SERIALCOMMAND_DEBUG + Serial.print("Received: "); + Serial.println(buffer); + #endif + + char *command = strtok_r(buffer, delim, &last); // Search for command at start of buffer + if (command != NULL) { + boolean matched = false; + for (int i = 0; i < commandCount; i++) { + #ifdef SERIALCOMMAND_DEBUG + Serial.print("Comparing ["); + Serial.print(command); + Serial.print("] to ["); + Serial.print(commandList[i].command); + Serial.println("]"); + #endif + + + + // Compare the found command against the list of known commands for a match + if (strncmp(command, commandList[i].command, SERIALCOMMAND_MAXCOMMANDLENGTH) == 0) { + #ifdef SERIALCOMMAND_DEBUG + Serial.print("Matched Command: "); + Serial.println(command); + #endif + + // Execute the stored handler function for the command + (*commandList[i].function)(); + matched = true; + break; + } + } + + + if (!matched && (defaultHandler != NULL)) { + (*defaultHandler)(command); + } + + + clearBuffer(); + } +} + +/* + * Clear the input buffer. + */ +void StringCommand::clearBuffer() { + buffer[0] = '\0'; + bufPos = 0; +} + +/** + * Retrieve the next token ("word" or "argument") from the command buffer. + * Returns NULL if no more tokens exist. + */ +char *StringCommand::next() { + return strtok_r(NULL, delim, &last); +} diff --git a/lib/ESP8266-StringCommand/StringCommand.h b/lib/ESP8266-StringCommand/StringCommand.h new file mode 100644 index 00000000..fccb2fb8 --- /dev/null +++ b/lib/ESP8266-StringCommand/StringCommand.h @@ -0,0 +1,75 @@ +/** + * SerialCommand - A Wiring/Arduino library to tokenize and parse commands + * received over a serial port. + * + * Copyright (C) 2012 Stefan Rado + * Copyright (C) 2011 Steven Cogswell + * http://husks.wordpress.com + * + * Version 20120522 + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this library. If not, see . + */ +#ifndef StringCommand_h +#define StringCommand_h + +#if defined(WIRING) && WIRING >= 100 + #include +#elif defined(ARDUINO) && ARDUINO >= 100 + #include +#else + #include +#endif +#include + +// Size of the input buffer in bytes (maximum length of one command plus arguments) +#define SERIALCOMMAND_BUFFER 128 //256 +// Maximum length of a command excluding the terminating null +#define SERIALCOMMAND_MAXCOMMANDLENGTH 16 + +// Uncomment the next line to run the library in debug mode (verbose messages) +//#define SERIALCOMMAND_DEBUG + + +class StringCommand { + public: + StringCommand(); // Constructor + void addCommand(const char *command, void(*function)()); // Add a command to the processing dictionary. + void setDefaultHandler(void (*function)(const char *)); // A handler to call when no valid command received. + + void readStr(String sBuffer ); // Main entry point. + void clearBuffer(); // Clears the input buffer. + char *next(); // Returns pointer to next token found in command buffer (for getting arguments to commands). + + private: + // Command/handler dictionary + struct StringCommandCallback { + char command[SERIALCOMMAND_MAXCOMMANDLENGTH + 1]; + void (*function)(); + }; // Data structure to hold Command/Handler function key-value pairs + StringCommandCallback *commandList; // Actual definition for command/handler array + byte commandCount; + + // Pointer to the default handler function + void (*defaultHandler)(const char *); + + char delim[2]; // null-terminated list of character to be used as delimeters for tokenizing (default " ") + char term; // Character that signals end of command (default '\n') + + char buffer[SERIALCOMMAND_BUFFER + 1]; // Buffer of stored characters while waiting for terminator character + byte bufPos; // Current position in the buffer + char *last; // State variable used by strtok_r during processing +}; + +#endif //StringCommand_h diff --git a/Ticker_for_TickerScheduler/Ticker/keywords.txt b/lib/ESP8266-StringCommand/keywords.txt similarity index 59% rename from Ticker_for_TickerScheduler/Ticker/keywords.txt rename to lib/ESP8266-StringCommand/keywords.txt index 1ecd8d0e..c9799b2c 100644 --- a/Ticker_for_TickerScheduler/Ticker/keywords.txt +++ b/lib/ESP8266-StringCommand/keywords.txt @@ -1,29 +1,23 @@ -####################################### -# Syntax Coloring Map For Wire -####################################### - ####################################### # Datatypes (KEYWORD1) ####################################### +StringCommand KEYWORD1 + ####################################### # Methods and Functions (KEYWORD2) ####################################### -attach KEYWORD2 -attach_ms KEYWORD2 -once KEYWORD2 -once_ms KEYWORD2 -detach KEYWORD2 -active KEYWORD2 +addCommand KEYWORD2 +setDefaultHandler KEYWORD2 +readString KEYWORD2 +clearBuffer KEYWORD2 +next KEYWORD2 ####################################### # Instances (KEYWORD2) ####################################### -Ticker KEYWORD2 - ####################################### # Constants (LITERAL1) -####################################### - +####################################### diff --git a/lib/ESP8266-StringCommand/readme.md b/lib/ESP8266-StringCommand/readme.md new file mode 100644 index 00000000..731ee5e2 --- /dev/null +++ b/lib/ESP8266-StringCommand/readme.md @@ -0,0 +1,5 @@ +StringCommand +============= +Библиотека для ESP8266 позволяющая связать запуск пользовательских функций с строковой переменной. + + diff --git a/lib/ESPrelay/.gitattributes b/lib/ESPrelay/.gitattributes new file mode 100644 index 00000000..bdb0cabc --- /dev/null +++ b/lib/ESPrelay/.gitattributes @@ -0,0 +1,17 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/lib/ESPrelay/TheThingsMQTT.cpp b/lib/ESPrelay/TheThingsMQTT.cpp new file mode 100644 index 00000000..4faf78f3 --- /dev/null +++ b/lib/ESPrelay/TheThingsMQTT.cpp @@ -0,0 +1,215 @@ +/* +Copyright (c) 2016 TheThings. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Original Maker: Mateo Velez - Metavix for TheThings Inc +Modified and Maintened by: Jose Garcia - TheThings Inc + +*/ + +#include "TheThingsMQTT.h" + + +TheThings::TheThings(char* token){ + initialize(token, NULL); +} + + +TheThings::TheThings(char* token, char* clientName) { + initialize(token, clientName); +} + + +void TheThings::begin(void (*callback)(char*,uint8_t*,unsigned int)) { + this->callback = callback; + _client.setServer(_server, MQTT_PORT); + _client.setCallback(callback); +} + + +bool TheThings::add(char* variableLabel, float value) { + return add(variableLabel, value, "NULL", "NULL"); +} + + +bool TheThings::add(char* variableLabel, float value, char *context) { + return add(variableLabel, value, context, "NULL"); +} + + +bool TheThings::add(char* variableLabel, float value, char *context, char *timestamp) { + (val+currentValue)->_variableLabel = variableLabel; + (val+currentValue)->_value = value; + (val+currentValue)->_context = context; + (val+currentValue)->_timestamp = timestamp; + currentValue++; + if (currentValue > MAX_VALUES) { + Serial.println(F("You are sending more than the maximum of consecutive variables")); + currentValue = MAX_VALUES; + } + return true; +} + + +bool TheThings::connected(){ + return _client.connected(); +} + + +char* TheThings::getMac(){ + // Obtains the MAC of the device + Serial.println("entra"); + byte mac[6]; + WiFi.macAddress(mac); + char macAddr[18]; + sprintf(macAddr, "%2X%2X%2X%2X%2X%2X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + return macAddr; +} + + +void TheThings::initialize(char* token, char* clientName){ + _server = SERVER; + _token = token; + currentValue = 0; + val = (Value *)malloc(MAX_VALUES*sizeof(Value)); + if(clientName!=NULL){ + _clientName = clientName; + } +} + + +bool TheThings::loop() { + if (!_client.connected()) { + reconnect(); + } + return _client.loop(); +} + + +void TheThings::reconnect() { + while (!_client.connected()) { + Serial.print("Attempting MQTT connection..."); + if (_client.connect(_clientName, _token, NULL)) { + Serial.println("connected"); + break; + } else { + Serial.print("failed, rc="); + Serial.print(_client.state()); + Serial.println(" try again in 3 seconds"); + delay(3000); + } + } +} + + +void TheThings::setDebug(bool debug){ + _debug = debug; +} + + +void TheThings:: setBroker(char* broker){ + if (_debug){ + Serial.println("Broker set for Business Account"); + } + _server = broker; +} + + +bool TheThings::subscribe() { + char topic[150]; + sprintf(topic, "%s%s", FIRST_PART_TOPIC, _token); + if (!_client.connected()) { + reconnect(); + } + if (_debug){ + Serial.println("Subscribed to: "); + Serial.println(topic); + } + return _client.subscribe(topic); +} + + +bool TheThings::publish() { + + char topic[150]; + char payload[500]; + String str; + sprintf(topic, "%s%s", FIRST_PART_TOPIC, _token); + sprintf(payload, "["); + for (int i = 0; i <= currentValue; ) { + str = String((val+i)->_value, 1); + sprintf(payload,"%s{\"key\":\"%s\",\"value\":%s",payload,(val+i)->_variableLabel, str.c_str()); + if ((val+i)->_timestamp != "NULL") { + sprintf(payload, "%s, \"timestamp\": %s", payload, (val+i)->_timestamp); + } + if ((val+i)->_context != "NULL") { + sprintf(payload, "%s, \"context\": {%s}", payload, (val+i)->_context); + } + i++; + if (i >= currentValue) { + sprintf(payload, "%s}]", payload); + break; + } else { + sprintf(payload, "%s},", payload); + } + } + if (_debug){ + Serial.println("publishing to TOPIC: "); + Serial.println(topic); + Serial.print("JSON dict: "); + Serial.println(payload); + } + currentValue = 0; + return _client.publish(topic, payload, 512); +} + + +bool TheThings::wifiConnection(char* ssid, char* pass) { + WiFi.begin(ssid, pass); + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(F("WiFi connected")); + Serial.println(F("IP address: ")); + Serial.println(WiFi.localIP()); + if(_clientName==NULL){ + _clientName = getMac(); + } +} + +bool TheThings::wifiConnection2() { + WiFiManager wifiManager; + wifiManager.setTimeout(180); + + //if(!wifiManager.autoConnect("AutoConnectAP")) { + if(!wifiManager.autoConnect()) { + Serial.println("failed to connect and hit timeout"); + delay(3000); + ESP.reset(); + delay(5000); + } +} + +int TheThings::state() { + return _client.state(); +} + diff --git a/lib/ESPrelay/TheThingsMQTT.h b/lib/ESPrelay/TheThingsMQTT.h new file mode 100644 index 00000000..c176003d --- /dev/null +++ b/lib/ESPrelay/TheThingsMQTT.h @@ -0,0 +1,58 @@ + +#ifndef TheThingsMQTT_H +#define TheThingsMQTT_H +//#include +#include +#include + +#define MQTT_PORT 1883 +#define SERVER "mqtt.thethings.io" +#define MAX_VALUES 5 +#define FIRST_PART_TOPIC "v2/things/" + +#define META_DEBUG Serial + +typedef struct Value { + char* _variableLabel; + float _value; + char* _context; + char* _timestamp; +} Value; + +class TheThings { + private: + void (*callback)(char*, uint8_t*, unsigned int); + char* getMac(); + void initialize(char* token, char* clientName); + WiFiClient espClient; + PubSubClient _client = PubSubClient(espClient); + WiFiManager wifiManager; + char* _clientName = NULL; + bool _debug = false; + uint8_t currentValue; + char* _password; + char* _server; + char* _ssid; + char* _token; + Value* val; + + public: + TheThings(char* token); + TheThings(char* token, char* clientName); + bool add(char* variableLabel, float value); + bool add(char* variableLabel, float value, char* context); + bool add(char* variableLabel, float value, char* context, char* timestamp); + void begin(void (*callback)(char*, uint8_t*, unsigned int)); + bool connected(); + bool loop(); + bool subscribe(); + bool publish(); + void setBroker(char* broker); + void reconnect(); + void setDebug(bool debug); + bool wifiConnection(char* ssid, char* pass); + bool wifiConnection2(); + int state(); +}; + +#endif diff --git a/lib/ESPrelay/TickerScheduler.cpp b/lib/ESPrelay/TickerScheduler.cpp new file mode 100644 index 00000000..b3badc25 --- /dev/null +++ b/lib/ESPrelay/TickerScheduler.cpp @@ -0,0 +1,116 @@ +#include "TickerScheduler.h" + +TickerScheduler::TickerScheduler(uint8_t size) +{ + this->items = new TickerSchedulerItem[size]; + this->size = size; +} + +TickerScheduler::~TickerScheduler() +{ + for (uint8_t i = 0; i < this->size; i++) + { + this->remove(i); + yield(); + } + + delete[] this->items; + this->items = NULL; + this->size = 0; +} + +void TickerScheduler::handleTickerFlag(volatile bool * flag) +{ + if (!*flag) + *flag = true; +} + +void TickerScheduler::handleTicker(tscallback_t f, void * arg, volatile bool * flag) +{ + if (*flag) + { + yield(); + *flag = false; + yield(); + f(arg); + yield(); + } +} + +bool TickerScheduler::add(uint8_t i, uint32_t period, tscallback_t f, void* arg, boolean shouldFireNow) +{ + if (i >= this->size || this->items[i].is_used) + return false; + + this->items[i].cb = f; + this->items[i].cb_arg = arg; + this->items[i].flag = shouldFireNow; + this->items[i].period = period; + this->items[i].is_used = true; + + enable(i); + + return true; +} + +bool TickerScheduler::remove(uint8_t i) +{ + if (i >= this->size || !this->items[i].is_used) + return false; + + this->items[i].is_used = false; + this->items[i].t.detach(); + this->items[i].flag = false; + this->items[i].cb = NULL; + + return true; +} + +bool TickerScheduler::disable(uint8_t i) +{ + if (i >= this->size || !this->items[i].is_used) + return false; + + this->items[i].t.detach(); + + return true; +} + +bool TickerScheduler::enable(uint8_t i) +{ + if (i >= this->size || !this->items[i].is_used) + return false; + + volatile bool * flag = &this->items[i].flag; + this->items[i].t.attach_ms(this->items[i].period, TickerScheduler::handleTickerFlag, flag); + + return true; +} + +void TickerScheduler::disableAll() +{ + for (uint8_t i = 0; i < this->size; i++) + disable(i); +} + +void TickerScheduler::enableAll() +{ + for (uint8_t i = 0; i < this->size; i++) + enable(i); +} + +void TickerScheduler::update() +{ + for (uint8_t i = 0; i < this->size; i++) + { + if (this->items[i].is_used) + { + #ifdef ARDUINO_ARCH_AVR + this->items[i].t.Tick(); + #endif + + handleTicker(this->items[i].cb, this->items[i].cb_arg, &this->items[i].flag); + } + yield(); + } +} diff --git a/lib/ESPrelay/TickerScheduler.h b/lib/ESPrelay/TickerScheduler.h new file mode 100644 index 00000000..71acb3b0 --- /dev/null +++ b/lib/ESPrelay/TickerScheduler.h @@ -0,0 +1,79 @@ +#pragma once + +#include +#include + +class Ticker { + typedef void (*ticker_callback_t)(bool *); + + private: + bool is_attached = false; + uint32_t period = 0; + uint32_t last_tick = 0; + ticker_callback_t callback; + bool *callback_argument; + + public: + void Tick() { + if (is_attached && millis() - last_tick >= period) { + callback(callback_argument); + last_tick = millis(); + } + } + + void detach() { + this->is_attached = true; + } + + template + void attach_ms(uint32_t milliseconds, void (*callback)(TArg), TArg arg) { + this->period = milliseconds; + this->callback = callback; + this->callback_argument = arg; + this->is_attached = true; + } +}; + +#ifdef ARDUINO_ARCH_ESP8266 +#include + +#include +#endif + +void tickerFlagHandle(volatile bool *flag); + +#ifdef _GLIBCXX_FUNCTIONAL +typedef std::function tscallback_t; +#else +typedef void (*tscallback_t)(void *); +#endif + +struct TickerSchedulerItem { + Ticker t; + volatile bool flag = false; + tscallback_t cb; + void *cb_arg; + uint32_t period; + volatile bool is_used = false; +}; + +class TickerScheduler { + private: + uint8_t size; + TickerSchedulerItem *items = NULL; + + void handleTicker(tscallback_t, void *, volatile bool *flag); + static void handleTickerFlag(volatile bool *flag); + + public: + TickerScheduler(uint8_t size); + ~TickerScheduler(); + + bool add(uint8_t i, uint32_t period, tscallback_t, void *, boolean shouldFireNow = false); + bool remove(uint8_t i); + bool enable(uint8_t i); + bool disable(uint8_t i); + void enableAll(); + void disableAll(); + void update(); +}; diff --git a/lib/ESPrelay/subscribe_and_publish.ino b/lib/ESPrelay/subscribe_and_publish.ino new file mode 100644 index 00000000..3148ccd4 --- /dev/null +++ b/lib/ESPrelay/subscribe_and_publish.ino @@ -0,0 +1,182 @@ +/**************************************** + * Include Libraries + ****************************************/ +#include "TheThingsMQTT.h" +#include "TickerScheduler.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +/**************************************** + * Define Constants + ****************************************/ +#define TOKEN "" // Your TheThings TOKEN +#define WIFINAME "" //Your SSID +#define WIFIPASS "" // Your Wifi Pass + +TheThings client(TOKEN); + +#define DHTPIN 14 // Pin which is cosnnected to the DHT sensor. +// Uncomment the type of sensor in use: +//#define DHTTYPE DHT11 // DHT 11 +#define DHTTYPE DHT22 // DHT 22 (AM2302) +//#define DHTTYPE DHT21 // DHT 21 (AM2301) + +DHT_Unified dht(DHTPIN, DHTTYPE); + +uint32_t delayMS; +#define TRIGGER_PIN 0 +#define FRECUENCY 2000 +char *AP="TEST_BQ"; +String prefix="rel"; +const char WiFiAPPSK[] = "prueba"; + +WiFiManager wifiManager; + +#define RELAY1 12 +#define RELAY2 13 + +#define MEASUREMENT_TIME 30000 // Time in milisecons + +float Temperature,Humidity; +TickerScheduler ts(1); + +/**************************************** + * Auxiliar Functions + ****************************************/ + +//void configWiFi(){ +// wifiManager.resetSettings(); +// if(!wifiManager.autoConnect(AP,WiFiAPPSK)) { +// Serial.println("Reconfiguration called"); +// delay(3000); +// //reset and try again, or maybe put it to deep sleep +// ESP.reset(); +// delay(15000); +// } +//} + +void callback(char* topic, byte* payload, unsigned int length) { + Serial.print("Message arrived"); + // handle message arrived + String text = ""; + for (int i = 0; i < length; i++) + text.concat((char)payload[i]); + Serial.println(text); + text.replace(" ", ""); + text.toUpperCase(); + if (text.indexOf("\"KEY\":\"REL1\"") >= 0) { + if (text.indexOf("\"VALUE\":\"ON\"") >= 0) digitalWrite(RELAY1,HIGH); + else if (text.indexOf("\"VALUE\":\"OFF\"") >= 0) digitalWrite(RELAY1,LOW); + } + else if (text.indexOf("\"KEY\":\"REL2\"") >= 0) { + if (text.indexOf("\"VALUE\":\"ON\"") >= 0) digitalWrite(RELAY2,HIGH); + else if (text.indexOf("\"VALUE\":\"OFF\"") >= 0) digitalWrite(RELAY2,LOW); + } +} + +float temperatureMeasurement(sensors_event_t event, DHT_Unified dht){ + // Get temperature event and print its value. + dht.temperature().getEvent(&event); + if (isnan(event.temperature)) { + Serial.println("Error reading temperature!"); + } + else { + Serial.print("Temperature: "); + Serial.print(event.temperature); + Serial.println(" *C"); + return event.temperature; + } +} + +float humidityMeasurement(sensors_event_t event, DHT_Unified dht){ + // Get humidity event and print its value. + dht.humidity().getEvent(&event); + if (isnan(event.relative_humidity)) { + Serial.println("Error reading humidity!"); + } + else { + Serial.print("Humidity: "); + Serial.print(event.relative_humidity); + Serial.println("%"); + return event.relative_humidity; + } +} + +void measureAndSend(){ + sensors_event_t event; + Temperature=temperatureMeasurement(event,dht); + Humidity=humidityMeasurement(event,dht); + client.add("Temperature", Temperature); + client.add("Humidity", Humidity); + client.publish(); +} + +/**************************************** + * Main Functions + ****************************************/ + + +void setup() { + // put your setup code here, to run once: + Serial.begin(115200); + delay(100); + pinMode(RELAY1,OUTPUT); + pinMode(RELAY2,OUTPUT); + + dht.begin(); + sensor_t sensor; + + + +// pinMode(TRIGGER_PIN, INPUT); +// attachInterrupt(digitalPinToInterrupt(TRIGGER_PIN), configWiFi, RISING); +// +// //sets timeout until configuration portal gets turned off +// //useful to make it all retry or go to sleep +// //in seconds +// wifiManager.setTimeout(280); +// +// //fetches ssid and pass and tries to connect +// //if it does not connect it starts an access point with the specified name +// //here "AutoConnectAP" +// //and goes into a blocking loop awaiting configuration +// if(!wifiManager.autoConnect(AP,WiFiAPPSK)) { +// Serial.println("failed to connect and hit timeout"); +// delay(3000); +// //reset and try again, or maybe put it to deep sleep +// //ESP.reset(); +// delay(FRECUENCY); +// } +// //if you get here you have connected to the WiFi +// Serial.println("connected...yeey :)"); + + client.wifiConnection(WIFINAME, WIFIPASS); + + //client.wifiConnection2(); + client.begin(callback); + client.subscribe(); //Insert the dataSource and Variable's Labels + + ts.add(0, MEASUREMENT_TIME, [&](void*) { measureAndSend(); }, nullptr, false); + ts.enableAll(); + + } + +void loop() { + // put your main code here, to run repeatedly: + ts.update(); + + if(!client.connected()){ + client.reconnect(); + client.subscribe(); //Insert the dataSource and Variable's Labels + } + client.loop(); + +} diff --git a/lib/README b/lib/README new file mode 100644 index 00000000..6debab1e --- /dev/null +++ b/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/main.ino b/main.ino deleted file mode 100644 index 01d90421..00000000 --- a/main.ino +++ /dev/null @@ -1,447 +0,0 @@ -//============================================================================================================ -//=============================================JSON=========================================================== -// ------------- Чтение значения json ------------------------------------------------------------------------ -String jsonReadStr(String &json, String name) { - DynamicJsonBuffer jsonBuffer; - JsonObject& root = jsonBuffer.parseObject(json); - return root[name].as(); -} - -// ------------- Чтение значения json ------------------------------------------------------------------------ -int jsonReadInt(String &json, String name) { - DynamicJsonBuffer jsonBuffer; - JsonObject& root = jsonBuffer.parseObject(json); - return root[name]; -} - -// ------------- Запись значения json String ----------------------------------------------------------------- -String jsonWriteStr(String &json, String name, String volume) { - DynamicJsonBuffer jsonBuffer; - JsonObject& root = jsonBuffer.parseObject(json); - root[name] = volume; - json = ""; - root.printTo(json); - return json; -} - -// ------------- Запись значения json int --------------------------------------------------------------------- -String jsonWriteInt(String &json, String name, int volume) { - DynamicJsonBuffer jsonBuffer; - JsonObject& root = jsonBuffer.parseObject(json); - root[name] = volume; - json = ""; - root.printTo(json); - return json; -} - -// ------------- Запись значения json float ------------------------------------------------------------------- -String jsonWriteFloat(String &json, String name, float volume) { - DynamicJsonBuffer jsonBuffer; - JsonObject& root = jsonBuffer.parseObject(json); - root[name] = volume; - json = ""; - root.printTo(json); - return json; -} - -/* - DynamicJsonBuffer jsonBuffer; - JsonObject& root = jsonBuffer.parseObject(json); - root[name] = volume; - json = ""; - root.printTo(json); - return json; - - DynamicJsonDocument jsonBuffer(1024); - deserializeJson(jsonBuffer,json); - jsonBuffer[name] = volume; - json = ""; - serializeJson(jsonBuffer,json); - return json; -*/ -/* - String jsonWriteArray(String &json, String value1, String value2, String value3) { - const int capacity = JSON_ARRAY_SIZE(1) + 3 * JSON_OBJECT_SIZE(3); - StaticJsonBuffer jb; - JsonArray& arr = jb.createArray(); - JsonObject& obj1 = jb.createObject(); - obj1[value1] = 1; - obj1[value2] = 2; - obj1[value3] = 3; - arr.add(obj1); - arr.printTo(json); - return json; - } -*/ - -//============================================================================================================ -//=============================================BIT AND BYTE=================================================== -uint8_t hexStringToUint8(String hex) { - uint8_t tmp = strtol(hex.c_str(), NULL, 0); - if (tmp >= 0x00 && tmp <= 0xFF) { - return tmp; - } -} - -uint16_t hexStringToUint16(String hex) { - uint16_t tmp = strtol(hex.c_str(), NULL, 0); - if (tmp >= 0x0000 && tmp <= 0xFFFF) { - return tmp; - } -} -//============================================================================================================== -//=============================================CONFIG=========================================================== -void saveConfig () { - writeFile("config.json", configSetup); -} -//============================================================================================================== -//=============================================STRING=========================================================== -// --------Выделяем строку от конца строки до маркера----------------------------------------------------------- -String selectToMarkerLast (String str, String found) { - int p = str.lastIndexOf(found); - return str.substring(p + found.length()); -} - -// --------Выделяем строку до маркера--------------------------------------------------------------------------- -String selectToMarker (String str, String found) { - int p = str.indexOf(found); - return str.substring(0, p); -} -// --------Удаляем все после символа разделителя (вместе с символом разделителя)-------------------------------- -String deleteAfterDelimiter (String str, String found) { - int p = str.indexOf(found); - return str.substring(0, p); -} - -//---------Удаляем все до символа разделителя (вместе с символом разделителя)----------------------------------- -String deleteBeforeDelimiter(String str, String found) { - int p = str.indexOf(found) + found.length(); - return str.substring(p); -} -//----------------------Удаляем все до символа разделителя (без символа разделителя)---------------------------- -String deleteBeforeDelimiterTo(String str, String found) { - int p = str.indexOf(found); - return str.substring(p); -} - -// -------------------Выделяем строку от конца строки до маркера ------------------------------------------------ -String deleteToMarkerLast (String str, String found) { - int p = str.lastIndexOf(found); - return str.substring(0, p); -} -// -------------------Выделяем строку от конца строки до маркера + ---------------------------------------------- -String selectToMarkerPlus (String str, String found, int plus) { - int p = str.indexOf(found); - return str.substring(0, p + plus); -} -//--------------------Выделяем строку от маркера до маркера ----------------------------------------------------- -String selectFromMarkerToMarker(String str, String found, int number) { - if (str.indexOf(found) == -1) return "not found"; // если строки поиск нет сразу выход - str += found; // добавим для корректного поиска - uint8_t i = 0; // Индекс перебора - do { - if (i == number) return selectToMarker(str, found); // если индекс совпал с позицией законцим вернем резултат - str = deleteBeforeDelimiter(str, found); // отбросим проверенный блок до разделителя - i++; // увеличим индекс - } while (str.length() != 0); // повторим пока строка не пустая - return "not found"; // Достигли пустой строки и ничего не нашли -} -//--------------------Посчитать ----------------------------------------------------------------------------------- -int count(String str, String found) { - if (str.indexOf(found) == -1) return 0; // если строки поиск нет сразу выход - str += found; // добавим для корректного поиска - uint8_t i = 0; // Индекс перебора - while (str.length() != 0) { - str = deleteBeforeDelimiter(str, found); // отбросим проверенный блок до разделителя - i++; // увеличим индекс - } - return i; // Достигли пустой строки и ничего не нашли -} - -//--------------------проверка на цифры --------------------------------------------------------------------------- -boolean isDigitStr (String str) { - if (str.length() == 1) { - return Digit (str); - } - if (str.length() > 1) { - for (int i = 0; i < str.length(); i++) { - if (!Digit (String(str.charAt(i)))) return false; - } - return true; - } -} -boolean Digit (String str) { - if (str == "0" || str == "1" || str == "2" || str == "3" || str == "4" || str == "5" || str == "6" || str == "7" || str == "8" || str == "9") { - return true; - } else { - return false; - } -} -//================================================================================================================== -//============================================URL=================================================================== -// ----------------------Запрос на удаленный URL -String getURL(String urls) { - String answer = ""; - HTTPClient http; - http.begin(urls); //HTTP - int httpCode = http.GET(); - if (httpCode == HTTP_CODE_OK) { - answer = http.getString(); - } - else { - answer = "error"; - } - http.end(); - return answer; -} -//=================================================================================================================== -//===========================================FILES=================================================================== -// ------------- Добавление файла ----------------------------------------------------------------------------------- -String safeDataToFile(String data, String Folder) { - //String fileName = GetDate(); - String fileName; - fileName.toLowerCase(); - fileName = deleteBeforeDelimiter(fileName, " "); - fileName.replace(" ", "."); - fileName.replace("..", "."); - fileName = Folder + "/" + fileName + ".txt"; - // addFile(fileName, GetTime() + "/" + data); - Serial.println(fileName); - jsonWriteStr(configJson, "test", fileName); -} -// ------------- Чтение файла в строку ------------------------------------------------------------------------------- -String readFile(String fileName, size_t len ) { - File configFile = SPIFFS.open("/" + fileName, "r"); - if (!configFile) { - return "Failed"; - } - size_t size = configFile.size(); - if (size > len) { - configFile.close(); - return "Large"; - } - String temp = configFile.readString(); - configFile.close(); - return temp; -} -// ------------- Размер файла ---------------------------------------------------------------------------------------- -String sizeFile(String fileName) { - File configFile = SPIFFS.open("/" + fileName, "r"); - if (!configFile) { - return "Failed"; - } - size_t size = configFile.size(); - configFile.close(); - return String(size); -} -// ------------- Запись строки в файл --------------------------------------------------------------------------------- -String writeFile(String fileName, String strings ) { - File configFile = SPIFFS.open("/" + fileName, "w"); - if (!configFile) { - return "Failed to open config file"; - } - configFile.print(strings); - //strings.printTo(configFile); - configFile.close(); - return "Write sucsses"; -} -// ------------- Добовление строки в файл ------------------------------------------------------------------------------ -String addFile(String fileName, String strings ) { - File configFile = SPIFFS.open("/" + fileName, "a"); - if (!configFile) { - return "Failed to open config file"; - } - configFile.println(strings); - configFile.close(); - return "Write sucsses"; -} -// ------------- Чтение строки из файла --------------------------------------------------------------------------------- -//возвращает стоку из файла в которой есть искомое слово found -String readFileString(String fileName, String found) { - File configFile = SPIFFS.open("/" + fileName, "r"); - if (!configFile) { - return "Failed"; - } - if (configFile.find(found.c_str())) { - return configFile.readStringUntil('\n'); //'\r' - } - configFile.close(); -} -//========================================================================================================================= -//=======================================УПРАВЛЕНИЕ ВИДЖЕТАМИ MQTT========================================================= -void sendCONFIG(String topik, String widgetConfig, String key, String date) { - yield(); - topik = jsonReadStr(configSetup, "mqttPrefix") + "/" + chipID + "/" + topik + "/status"; - String outer = "{\"widgetConfig\":"; - String inner = "{\""; - inner = inner + key; - inner = inner + "\":\""; - inner = inner + date; - inner = inner + "\""; - inner = inner + "}}"; - String t = outer + inner; - //Serial.println(t); - //client_mqtt.publish(MQTT::Publish(topik, t).set_qos(1)); - yield(); -} -//========================================================================================================================= -//=========================================МИГАНИЕ СВЕТОДИОДОМ============================================================= -void led_blink(String satus) { -#ifdef ESP8266 -#ifdef blink_pin - pinMode(blink_pin, OUTPUT); - if (satus == "off") { - noTone(blink_pin); - digitalWrite(blink_pin, HIGH); - } - if (satus == "on") { - noTone(blink_pin); - digitalWrite(blink_pin, LOW); - } - if (satus == "slow") tone(blink_pin, 1); - if (satus == "fast") tone(blink_pin, 20); -#endif -#endif -} -//========================================================================================================================= -//=========================================ОСТАВШАЯСЯ ОПЕРАТИВНАЯ ПАМЯТЬ=================================================== -void getMemoryLoad(String text) { -#ifdef ESP8266 - int all_memory = 52864; -#endif -#ifdef ESP32 - int all_memory = 362868; -#endif - int memory_remain = ESP.getFreeHeap(); - int memory_used = all_memory - memory_remain; - int memory_load = (memory_used * 100) / all_memory; - if (memory_load > 65) Serial.print("Attention!!! too match memory used!!!"); - Serial.print(text + " memory used:"); - Serial.print(String(memory_load) + "%; "); - Serial.print("memory remain: "); - Serial.println(String(memory_remain) + " k bytes"); - -} -//esp32 full memory = 362868 k bytes -//esp8266 full memory = 52864 k bytes - - - -//=================================================================== -/* - void web_print (String text) { - if (WiFi.status() == WL_CONNECTED) { - jsonWriteStr(json, "test1", jsonReadStr(json, "test2")); - jsonWriteStr(json, "test2", jsonReadStr(json, "test3")); - jsonWriteStr(json, "test3", jsonReadStr(json, "test4")); - jsonWriteStr(json, "test4", jsonReadStr(json, "test5")); - jsonWriteStr(json, "test5", jsonReadStr(json, "test6")); - - jsonWriteStr(json, "test6", GetTime() + " " + text); - - ws.textAll(json); - } - } -*/ -//=================================================================== -/* - "socket": [ - "ws://{{ip}}/ws" - ], -*/ -//=================================================================== -/* - { - "type": "h4", - "title": "('{{build2}}'=='{{firmware_version}}'?'NEW':'OLD')" - }, -*/ -//=================================================================== -/* - { - "type": "button", - "title": "Конфигурация устройства", - "socket": "test2", - "class": "btn btn-block btn-primary" - }, - { - "type": "hr" - }, - { - "type": "h6", - "title": "{{test1}}" - }, - { - "type": "h6", - "title": "{{test2}}" - }, - { - "type": "h6", - "title": "{{test3}}" - }, - { - "type": "h6", - "title": "{{test4}}" - }, - { - "type": "h6", - "title": "{{test5}}" - }, - { - "type": "h6", - "title": "{{test6}}" - }, - { - "type": "hr" - }, -*/ -//=================================================================== - - - -/* - String getResetReason(uint8_t core) { - int reason = rtc_get_reset_reason(core); - switch (reason) { - case 1 : return "Power on"; break; //Vbat power on reset - case 3 : return "Software reset digital core"; break; //Software reset digital core - case 4 : return "Legacy watch dog reset digital core"; break; //Legacy watch dog reset digital core - case 5 : return "Deep Sleep reset digital core"; break; //Deep Sleep reset digital core - case 6 : return "Reset by SLC module, reset digital core"; break; //Reset by SLC module, reset digital core - case 7 : return "Timer Group0 Watch dog reset digital core"; break; //Timer Group0 Watch dog reset digital core - case 8 : return "Timer Group1 Watch dog reset digital core"; break; //Timer Group1 Watch dog reset digital core - case 9 : return "RTC Watch dog Reset digital core"; break; // - case 10 : return "Instrusion tested to reset CPU"; break; - case 11 : return "Time Group reset CPU"; break; - case 12 : return "Software reset CPU"; break; - case 13 : return "RTC Watch dog Reset CPU"; break; - case 14 : return "for APP CPU, reseted by PRO CPU"; break; - case 15 : return "Reset when the vdd voltage is not stable"; break; - case 16 : return "RTC Watch dog reset digital core and rtc module"; break; - default : return "NO_MEAN"; - } - } - - - String EspClass::getResetReason(void) { - char buff[32]; - if (resetInfo.reason == REASON_DEFAULT_RST) { // normal startup by power on - strcpy_P(buff, PSTR("Power on")); - } else if (resetInfo.reason == REASON_WDT_RST) { // hardware watch dog reset - strcpy_P(buff, PSTR("Hardware Watchdog")); - } else if (resetInfo.reason == REASON_EXCEPTION_RST) { // exception reset, GPIO status won’t change - strcpy_P(buff, PSTR("Exception")); - } else if (resetInfo.reason == REASON_SOFT_WDT_RST) { // software watch dog reset, GPIO status won’t change - strcpy_P(buff, PSTR("Software Watchdog")); - } else if (resetInfo.reason == REASON_SOFT_RESTART) { // software restart ,system_restart , GPIO status won’t change - strcpy_P(buff, PSTR("Software/System restart")); - } else if (resetInfo.reason == REASON_DEEP_SLEEP_AWAKE) { // wake up from deep-sleep - strcpy_P(buff, PSTR("Deep-Sleep Wake")); - } else if (resetInfo.reason == REASON_EXT_SYS_RST) { // external system reset - strcpy_P(buff, PSTR("External System")); - } else { - strcpy_P(buff, PSTR("Unknown")); - } - return String(buff); - } -*/ diff --git a/mqtt.ino b/mqtt.ino deleted file mode 100644 index 4a877914..00000000 --- a/mqtt.ino +++ /dev/null @@ -1,348 +0,0 @@ -//===============================================ИНИЦИАЛИЗАЦИЯ================================================ -void MQTT_init() { - - ts.add(WIFI_MQTT_CONNECTION_CHECK, wifi_mqtt_reconnecting, [&](void*) { - up_time(); - if (WiFi.status() == WL_CONNECTED) { - Serial.println("[VV] WiFi-ok"); - if (client_mqtt.connected()) { - Serial.println("[VV] MQTT-ok"); - led_blink("off"); - } else { - MQTT_Connecting(); - if (!just_load) mqtt_lost_error++; - } - } else { - Serial.println("[E] Lost WiFi connection"); - wifi_lost_error++; - ts.remove(WIFI_MQTT_CONNECTION_CHECK); - StartAPMode(); - } - }, nullptr, true); - - - server.on("/mqttSave", HTTP_GET, [](AsyncWebServerRequest * request) { - if (request->hasArg("mqttServer")) { - jsonWriteStr(configSetup, "mqttServer", request->getParam("mqttServer")->value()); - } - if (request->hasArg("mqttPort")) { - int port = (request->getParam("mqttPort")->value()).toInt(); - jsonWriteInt(configSetup, "mqttPort", port); - } - if (request->hasArg("mqttPrefix")) { - jsonWriteStr(configSetup, "mqttPrefix", request->getParam("mqttPrefix")->value()); - } - if (request->hasArg("mqttUser")) { - jsonWriteStr(configSetup, "mqttUser", request->getParam("mqttUser")->value()); - } - if (request->hasArg("mqttPass")) { - jsonWriteStr(configSetup, "mqttPass", request->getParam("mqttPass")->value()); - } - saveConfig(); - mqtt_connection = true; - - request->send(200, "text/text", "ok"); - }); - - server.on("/mqttCheck", HTTP_GET, [](AsyncWebServerRequest * request) { - String tmp = "{}"; - jsonWriteStr(tmp, "title", "" + stateMQTT()); - jsonWriteStr(tmp, "class", "pop-up"); - request->send(200, "text/text", tmp); - }); - - -} - - - -void do_mqtt_connection() { - if (mqtt_connection) { - mqtt_connection = false; - client_mqtt.disconnect(); - MQTT_Connecting(); - } -} - -//================================================ОБНОВЛЕНИЕ==================================================== - -void handleMQTT() { - if (WiFi.status() == WL_CONNECTED) { - if (client_mqtt.connected()) { - client_mqtt.loop(); - } - } -} -//===============================================ПОДКЛЮЧЕНИЕ======================================================== -boolean MQTT_Connecting() { - String mqtt_server = jsonReadStr(configSetup, "mqttServer"); - if ((mqtt_server != "")) { - Serial.println("[E] Lost MQTT connection, start reconnecting"); - led_blink("fast"); - client_mqtt.setServer(mqtt_server.c_str(), jsonReadInt(configSetup, "mqttPort")); - if (WiFi.status() == WL_CONNECTED) { - if (!client_mqtt.connected()) { - Serial.println("[V] Connecting to MQTT server commenced"); - if (client_mqtt.connect(chipID.c_str(), jsonReadStr(configSetup, "mqttUser").c_str(), jsonReadStr(configSetup, "mqttPass").c_str())) { - Serial.println("[VV] MQTT connected"); - led_blink("off"); - client_mqtt.setCallback(callback); - client_mqtt.subscribe(jsonReadStr(configSetup, "mqttPrefix").c_str()); // Для приема получения HELLOW и подтверждения связи - client_mqtt.subscribe((jsonReadStr(configSetup, "mqttPrefix") + "/" + chipID + "/+/control").c_str()); // Подписываемся на топики control - client_mqtt.subscribe((jsonReadStr(configSetup, "mqttPrefix") + "/" + chipID + "/order").c_str()); // Подписываемся на топики order - Serial.println("[V] Callback set, subscribe done"); - return true; - } else { - Serial.println("[E] try again in " + String(wifi_mqtt_reconnecting / 1000) + " sec"); - led_blink("fast"); - return false; - } - } - } - } else { - Serial.println("[E] No date for MQTT connection"); - return false; - } -} - -//=====================================================ВХОДЯЩИЕ ДАННЫЕ======================================================== -void callback(char* topic, byte * payload, unsigned int length) { - Serial.print("[MQTT] "); - Serial.print(topic); - String topic_str = String(topic); - - String str; - for (int i = 0; i < length; i++) { - str += (char)payload[i]; - } - Serial.println(" => " + str); - - if (str == "HELLO") outcoming_date(); - - //превращает название топика в команду, а значение в параметр команды - if (topic_str.indexOf("control") > 0) { //IoTmanager/800324-1458415/button-sw2/control 1 //IoTmanager/800324-1458415/button99/control 1 - String topic = selectFromMarkerToMarker(topic_str, "/", 3); //button1 //button99 - topic = add_set(topic); //buttonSet1 //buttonSet99 - String number = selectToMarkerLast(topic, "Set"); //1 //99 - topic.replace(number, ""); //buttonSet //buttonSet - String final_line = topic + " " + number + " " + str; //buttonSet 1 1 //buttonSet 99 1 - order_loop += final_line + ","; - } - - if (topic_str.indexOf("order") > 0) { - str.replace("_", " "); - //Serial.println(str); - order_loop += str + ","; - } - if (topic_str.indexOf("update") > 0) { - if (str == "1") { - upgrade = true; - } - } -} - -//данные которые отправляем при подключении или отбновлении страницы -void outcoming_date() { - - sendAllWigets(); - sendAllData(); - -#ifdef logging_enable - choose_log_date_and_send(); -#endif - - Serial.println("[V] Sending all date to iot manager completed"); -} - - -//======================================CONFIG================================================== -boolean sendMQTT(String end_of_topik, String data) { - String topik = jsonReadStr(configSetup, "mqttPrefix") + "/" + chipID + "/" + end_of_topik; - boolean send_status = client_mqtt.beginPublish(topik.c_str(), data.length(), false); - client_mqtt.print(data); - client_mqtt.endPublish(); - return send_status; -} -boolean sendCHART(String topik, String data) { - topik = jsonReadStr(configSetup, "mqttPrefix") + "/" + chipID + "/" + topik + "/" + "status"; - boolean send_status = client_mqtt.beginPublish(topik.c_str(), data.length(), false); - client_mqtt.print(data); - client_mqtt.endPublish(); - return send_status; -} -boolean sendCHART_test(String topik, String data) { - topik = jsonReadStr(configSetup, "mqttPrefix") + "/" + chipID + "/" + topik + "/" + "status"; - boolean send_status = client_mqtt.publish (topik.c_str(), data.c_str(), false); - return send_status; -} -//======================================STATUS================================================== -void sendSTATUS(String topik, String state) { - topik = jsonReadStr(configSetup, "mqttPrefix") + "/" + chipID + "/" + topik + "/" + "status"; - String json_ = "{}"; - jsonWriteStr(json_, "status", state); - int send_status = client_mqtt.publish (topik.c_str(), json_.c_str(), false); -} -//======================================CONTROL================================================== -void sendCONTROL(String id, String topik, String state) { - String all_line = jsonReadStr(configSetup, "mqttPrefix") + "/" + id + "/" + topik + "/control"; - int send_status = client_mqtt.publish (all_line.c_str(), state.c_str(), false); -} - -//=====================================================ОТПРАВЛЯЕМ ВИДЖЕТЫ======================================================== - -#ifdef layout_in_ram -void sendAllWigets() { - if (all_widgets != "") { - int counter = 0; - String line; - int psn_1 = 0; - int psn_2; - do { - psn_2 = all_widgets.indexOf("\r\n", psn_1); //\r\n - line = all_widgets.substring(psn_1, psn_2); - line.replace("\n", ""); - line.replace("\r\n", ""); - //jsonWriteStr(line, "id", String(counter)); - //jsonWriteStr(line, "pageId", String(counter)); - counter++; - sendMQTT("config", line); - Serial.println("[V] " + line); - psn_1 = psn_2 + 1; - } while (psn_2 + 2 < all_widgets.length()); - getMemoryLoad("[i] after send all widgets"); - } -} -#endif - -#ifndef layout_in_ram -void sendAllWigets() { - File configFile = SPIFFS.open("/layout.txt", "r"); - if (!configFile) { - return; - } - configFile.seek(0, SeekSet); //поставим курсор в начало файла - while (configFile.position() != configFile.size()) { - String widget_to_send = configFile.readStringUntil('\r\n'); - Serial.println("[V] " + widget_to_send); - sendMQTT("config", widget_to_send); - } -} -#endif -//=====================================================ОТПРАВЛЯЕМ ДАННЫЕ В ВИДЖЕТЫ ПРИ ОБНОВЛЕНИИ СТРАНИЦЫ======================================================== -void sendAllData() { //берет строку json и ключи превращает в топики а значения колючей в них посылает - - String current_config = configJson; //{"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1"} - getMemoryLoad("[i] after send all date"); - current_config.replace("{", ""); - current_config.replace("}", ""); //"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1" - current_config += ","; //"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1", - - while (current_config.length() != 0) { - - String tmp = selectToMarker (current_config, ","); - String topic = selectToMarker (tmp, ":"); - topic.replace("\"", ""); - String state = selectToMarkerLast (tmp, ":"); - state.replace("\"", ""); - if (topic != "name" && topic != "lang" && topic != "ip" && topic.indexOf("_in") < 0) { - sendSTATUS(topic, state); - //Serial.println("-->" + topic + " " + state); - } - current_config = deleteBeforeDelimiter(current_config, ","); - } -} - - - -String stateMQTT() { - - int state = client_mqtt.state(); - - switch (state) { - case -4: return "the server didn't respond within the keepalive time"; - break; - case -3: return "the network connection was broken"; - break; - case -2: return "the network connection failed"; - break; - case -1: return "the client is disconnected cleanly"; - break; - case 0: return "the client is connected"; - break; - case 1: return "the server doesn't support the requested version of MQTT"; - break; - case 2: return "the server rejected the client identifier"; - break; - case 3: return "the server was unable to accept the connection"; - break; - case 4: return "the username/password were rejected"; - break; - case 5: return "the client was not authorized to connect"; - break; - } -} -/*void scenario_devices_topiks_subscribe() { - - //SCENARIO ANALOG > 5 800324-1458415 rel1 0 - if (jsonReadStr(configSetup, "scenario") == "1") { - //String all_text = readFile("firmware.s.txt", 1024) + "\r\n"; - String all_text = scenario + "\r\n"; - all_text.replace("\r\n", "\n"); - all_text.replace("\r", "\n"); - while (all_text.length() != 0) { - String line_ = selectToMarker (all_text, "\n"); - String id = selectFromMarkerToMarker(line_, " ", 4); - if (id != "not found") { - client_mqtt.subscribe((jsonReadStr(configSetup, "mqttPrefix") + "/" + id + "/+/status").c_str(), 0); - Serial.println("subscribed to device, id: " + id); - } - all_text = deleteBeforeDelimiter(all_text, "\n"); - } - } - } -*/ -/*void scenario_devices_test_msg_send() { - - if (jsonReadStr(configSetup, "scenario") == "1") { - - String all_text = scenario + "\r\n"; - all_text.replace("\r\n", "\n"); - all_text.replace("\r", "\n"); - while (all_text.length() != 0) { - String line_ = selectToMarker (all_text, "\n"); - String id = selectFromMarkerToMarker(line_, " ", 4); - if (id != "not found") { - //Serial.println(); - Serial.println(client_mqtt.publish ((jsonReadStr(configSetup, "mqttPrefix") + "/" + id).c_str(), "CHECK", true)); - - } - all_text = deleteBeforeDelimiter(all_text, "\n"); - } - } - }*/ - -/* - //----------------------------------------------------------------------------------------------------------------------------------------------- - //jsonWriteStr(tmp, "status", "1"); - - String current_config = configJson; //{"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1"} - current_config.replace("{", ""); - current_config.replace("}", ""); //"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1" - current_config += ","; //"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1", - - while (current_config.length() != 0) { - - String tmp = selectToMarker (current_config, ","); //"rel1":"1" - String topic = selectToMarker (tmp, ":"); //"rel1" - topic.replace("\"", ""); //rel1 - Serial.println(topic); - String state = selectToMarkerLast (tmp, ":"); //"1" - state.replace("\"", ""); //1 - - //if (widget.lastIndexOf(topic) > 0) { - jsonWriteStr(tmp, "status", state); - //} - current_config = deleteBeforeDelimiter(current_config, ","); - } - //------------------------------------------------------------------------------------------------------------------------------------------------- -*/ diff --git a/pictures/1.png b/pictures/1.png deleted file mode 100644 index ba8205a6..00000000 Binary files a/pictures/1.png and /dev/null differ diff --git a/pictures/esp32_1.png b/pictures/esp32_1.png deleted file mode 100644 index e2e98228..00000000 Binary files a/pictures/esp32_1.png and /dev/null differ diff --git a/pictures/esp32_2.png b/pictures/esp32_2.png deleted file mode 100644 index 85bc62ad..00000000 Binary files a/pictures/esp32_2.png and /dev/null differ diff --git a/pictures/esp8266_1.png b/pictures/esp8266_1.png deleted file mode 100644 index 016f8407..00000000 Binary files a/pictures/esp8266_1.png and /dev/null differ diff --git a/pictures/esp8266_1mb_1.png b/pictures/esp8266_1mb_1.png deleted file mode 100644 index f3c8a2b4..00000000 Binary files a/pictures/esp8266_1mb_1.png and /dev/null differ diff --git a/pictures/esp8266_1mb_2.png b/pictures/esp8266_1mb_2.png deleted file mode 100644 index 0506116f..00000000 Binary files a/pictures/esp8266_1mb_2.png and /dev/null differ diff --git a/pictures/esp8266_2.png b/pictures/esp8266_2.png deleted file mode 100644 index ec8cde52..00000000 Binary files a/pictures/esp8266_2.png and /dev/null differ diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 00000000..edffafe0 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,27 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env] +lib_deps= + ModuleInterface@3.5.1 + ArduinoJson@5.* + AsyncTCP + ESP Async WebServer + ESP32Servo + Bounce2 + PubSubClient + iothubclientlonghaultests_bld + ESP8266-StringCommand + +[env:esp32dev] +platform = espressif32 +board = esp32dev +framework = arduino + diff --git a/push_pushingbox.ino b/push_pushingbox.ino deleted file mode 100644 index 6d5ddcb3..00000000 --- a/push_pushingbox.ino +++ /dev/null @@ -1,62 +0,0 @@ -#ifdef push_enable -void Push_init() { - server.on("/pushingboxDate", HTTP_GET, [](AsyncWebServerRequest * request) { - - if (request->hasArg("pushingbox_id")) { - jsonWriteStr(configSetup, "pushingbox_id", request->getParam("pushingbox_id")->value()); - } - - saveConfig(); - - request->send(200, "text/text", "ok"); // отправляем ответ о выполнении - }); -} - -void pushControl() { - - String title = sCmd.next(); - title.replace("#", " "); - String body = sCmd.next(); - body.replace("#", " "); - - static String body_old; - - const char* logServer = "api.pushingbox.com"; - String deviceId = jsonReadStr(configSetup, "pushingbox_id"); - - Serial.println("- starting client"); - - WiFiClient client_push; - - Serial.println("- connecting to pushing server: " + String(logServer)); - if (!client_push.connect(logServer, 80)) { - Serial.println("- not connected"); - } else { - Serial.println("- succesfully connected"); - - String postStr = "devid="; - postStr += String(deviceId); - - postStr += "&title="; - postStr += String(title); - - postStr += "&body="; - postStr += String(body); - - postStr += "\r\n\r\n"; - - Serial.println("- sending data..."); - - client_push.print("POST /pushingbox HTTP/1.1\n"); - client_push.print("Host: api.pushingbox.com\n"); - client_push.print("Connection: close\n"); - client_push.print("Content-Type: application/x-www-form-urlencoded\n"); - client_push.print("Content-Length: "); - client_push.print(postStr.length()); - client_push.print("\n\n"); - client_push.print(postStr); - } - client_push.stop(); - Serial.println("- stopping the client"); -} -#endif diff --git a/src/Cmd.cpp b/src/Cmd.cpp new file mode 100644 index 00000000..8708d58f --- /dev/null +++ b/src/Cmd.cpp @@ -0,0 +1,574 @@ +#include "Cmd.h" + +#include "Scenario.h" +#include "TimeUtils.h" +#include "Widgets.h" +#include "main.h" +#include "push_pushingbox.h" +#include "set.h" + +void CMD_init() { + sCmd.addCommand("button", button); + sCmd.addCommand("buttonSet", buttonSet); + sCmd.addCommand("buttonChange", buttonChange); + + sCmd.addCommand("pinSet", pinSet); + sCmd.addCommand("pinChange", pinChange); + + sCmd.addCommand("pwm", pwm); + sCmd.addCommand("pwmSet", pwmSet); + + sCmd.addCommand("switch", switch_); + +#ifdef analog_enable + sCmd.addCommand("analog", analog); +#endif +#ifdef level_enable + sCmd.addCommand("level", level); +#endif +#ifdef dallas_enable + sCmd.addCommand("dallas", dallas); +#endif +#ifdef dht_enable + sCmd.addCommand("dhtT", dhtT); + sCmd.addCommand("dhtH", dhtH); + sCmd.addCommand("dhtPerception", dhtP); + sCmd.addCommand("dhtComfort", dhtC); + sCmd.addCommand("dhtDewpoint", dhtD); +#endif + +#ifdef bmp_enable + sCmd.addCommand("bmp280T", bmp280T); + sCmd.addCommand("bmp280P", bmp280P); +#endif + +#ifdef bme_enable + sCmd.addCommand("bme280T", bme280T); + sCmd.addCommand("bme280P", bme280P); + sCmd.addCommand("bme280H", bme280H); + sCmd.addCommand("bme280A", bme280A); +#endif + +#ifdef stepper_enable + sCmd.addCommand("stepper", stepper); + sCmd.addCommand("stepperSet", stepperSet); +#endif + +#ifdef servo_enable + sCmd.addCommand("servo", servo_); + sCmd.addCommand("servoSet", servoSet); +#endif + +#ifdef serial_enable + sCmd.addCommand("serialBegin", serialBegin); + sCmd.addCommand("serialWrite", serialWrite); +#endif + +#ifdef logging_enable + sCmd.addCommand("logging", logging); +#endif + + sCmd.addCommand("inputDigit", inputDigit); + sCmd.addCommand("digitSet", digitSet); + + sCmd.addCommand("inputTime", inputTime); + sCmd.addCommand("timeSet", timeSet); + + sCmd.addCommand("timerStart", timerStart); + sCmd.addCommand("timerStop", timerStop); + + sCmd.addCommand("text", text); + sCmd.addCommand("textSet", textSet); + + sCmd.addCommand("mqtt", mqttOrderSend); + sCmd.addCommand("http", httpOrderSend); + +#ifdef push_enable + sCmd.addCommand("push", pushControl); +#endif + + sCmd.addCommand("update", update_firmware); + sCmd.addCommand("firmware", firmware); + + handle_time_init(); +} + +void button() { + String button_number = sCmd.next(); + String button_param = sCmd.next(); + String widget_name = sCmd.next(); + String page_name = sCmd.next(); + String start_state = sCmd.next(); + String page_number = sCmd.next(); + + jsonWriteStr(optionJson, "button_param" + button_number, button_param); + jsonWriteStr(configJson, "button" + button_number, start_state); + + if (isDigitStr(button_param)) { + pinMode(button_param.toInt(), OUTPUT); + digitalWrite(button_param.toInt(), start_state.toInt()); + } + + if (button_param == "scenario") { + jsonWriteStr(configSetup, "scenario", start_state); + Scenario_init(); + saveConfig(); + } + + if (button_param.indexOf("line") != -1) { + String str = button_param; + while (str.length() != 0) { + if (str == "") return; + String tmp = selectToMarker(str, ","); //line1, + String number = deleteBeforeDelimiter(tmp, "e"); //1, + number.replace(",", ""); + Serial.println(number); + int number_int = number.toInt(); + scenario_line_status[number_int] = start_state.toInt(); + str = deleteBeforeDelimiter(str, ","); + } + } + createWidget(widget_name, page_name, page_number, "widgets/widget.toggle.json", "button" + button_number); +} + +void buttonSet() { + String button_number = sCmd.next(); + String button_state = sCmd.next(); + String button_param = jsonReadStr(optionJson, "button_param" + button_number); + + if (button_param != "na" || button_param != "scenario" || button_param.indexOf("line") != -1) { + digitalWrite(button_param.toInt(), button_state.toInt()); + } + + if (button_param == "scenario") { + jsonWriteStr(configSetup, "scenario", button_state); + Scenario_init(); + saveConfig(); + } + + if (button_param.indexOf("line") != -1) { + String str = button_param; + while (str.length() != 0) { + if (str == "") return; + String tmp = selectToMarker(str, ","); //line1, + String number = deleteBeforeDelimiter(tmp, "e"); //1, + number.replace(",", ""); + Serial.println(number); + int number_int = number.toInt(); + scenario_line_status[number_int] = button_state.toInt(); + str = deleteBeforeDelimiter(str, ","); + } + } + + eventGen("button", button_number); + + jsonWriteStr(configJson, "button" + button_number, button_state); + sendSTATUS("button" + button_number, button_state); +} + +void buttonChange() { + String button_number = sCmd.next(); + String current_state = jsonReadStr(configJson, "button" + button_number); + if (current_state == "1") { + current_state = "0"; + } else if (current_state == "0") { + current_state = "1"; + } + order_loop += "buttonSet " + button_number + " " + current_state + ","; + jsonWriteStr(configJson, "button" + button_number, current_state); + sendSTATUS("button" + button_number, current_state); +} + +void pinSet() { + String pin_number = sCmd.next(); + String pin_state = sCmd.next(); + pinMode(pin_number.toInt(), OUTPUT); + digitalWrite(pin_number.toInt(), pin_state.toInt()); +} + +void pinChange() { + String pin_number = sCmd.next(); + pinMode(pin_number.toInt(), OUTPUT); + digitalWrite(pin_number.toInt(), !digitalRead(pin_number.toInt())); +} + +void pwm() { + // TODO Unused + // static boolean flag = true; + String pwm_number = sCmd.next(); + String pwm_pin = sCmd.next(); + String widget_name = sCmd.next(); + widget_name.replace("#", " "); + String page_name = sCmd.next(); + String start_state = sCmd.next(); + String page_number = sCmd.next(); + + uint8_t pwm_pin_int = pwm_pin.toInt(); + jsonWriteStr(optionJson, "pwm_pin" + pwm_number, pwm_pin); + pinMode(pwm_pin_int, INPUT); + analogWrite(pwm_pin_int, start_state.toInt()); + jsonWriteStr(configJson, "pwm" + pwm_number, start_state); + createWidget(widget_name, page_name, page_number, "widgets/widget.range.json", "pwm" + pwm_number); +} + +void pwmSet() { + String pwm_number = sCmd.next(); + String pwm_state = sCmd.next(); + int pwm_state_int = pwm_state.toInt(); + + int pin = jsonReadInt(optionJson, "pwm_pin" + pwm_number); + analogWrite(pin, pwm_state_int); + + eventGen("pwm", pwm_number); + + jsonWriteStr(configJson, "pwm" + pwm_number, pwm_state); + sendSTATUS("pwm" + pwm_number, pwm_state); +} +//================================================================================================================== +//==========================================Модуль физической кнопки================================================ +void switch_() { + String switch_number = sCmd.next(); + String switch_pin = sCmd.next(); + String switch_delay = sCmd.next(); + + buttons[switch_number.toInt()].attach(switch_pin.toInt()); + buttons[switch_number.toInt()].interval(switch_delay.toInt()); + but[switch_number.toInt()] = true; +} + +void handleButton() { + static uint8_t switch_number = 1; + + if (but[switch_number]) { + buttons[switch_number].update(); + if (buttons[switch_number].fell()) { + eventGen("switch", String(switch_number)); + + jsonWriteStr(configJson, "switch" + String(switch_number), "1"); + } + if (buttons[switch_number].rose()) { + eventGen("switch", String(switch_number)); + + jsonWriteStr(configJson, "switch" + String(switch_number), "0"); + } + } + switch_number++; + if (switch_number == NUM_BUTTONS) switch_number = 0; +} + +void inputDigit() { + String value_name = sCmd.next(); + String number = value_name.substring(5); + String widget_name = sCmd.next(); + widget_name.replace("#", " "); + String page_name = sCmd.next(); + page_name.replace("#", " "); + String start_state = sCmd.next(); + String page_number = sCmd.next(); + jsonWriteStr(configJson, "digit" + number, start_state); + createWidget(widget_name, page_name, page_number, "widgets/widget.inputNum.json", "digit" + number); +} + +void digitSet() { + String number = sCmd.next(); + String value = sCmd.next(); + jsonWriteStr(configJson, "digit" + number, value); + sendSTATUS("digit" + number, value); +} + +void inputTime() { + String value_name = sCmd.next(); + String number = value_name.substring(4); + String widget_name = sCmd.next(); + widget_name.replace("#", " "); + String page_name = sCmd.next(); + page_name.replace("#", " "); + String start_state = sCmd.next(); + String page_number = sCmd.next(); + jsonWriteStr(configJson, "time" + number, start_state); + createWidget(widget_name, page_name, page_number, "widgets/widget.inputTime.json", "time" + number); +} + +void timeSet() { + String number = sCmd.next(); + String value = sCmd.next(); + jsonWriteStr(configJson, "time" + number, value); + sendSTATUS("time" + number, value); +} + +void handle_time_init() { + ts.add( + TIME, 1000, [&](void*) { + String tmp = GetTime(); + jsonWriteStr(configJson, "time", tmp); + tmp.replace(":", "-"); + jsonWriteStr(configJson, "timenow", tmp); + eventGen("timenow", ""); + }, + nullptr, true); +} + +void text() { + String number = sCmd.next(); + String widget_name = sCmd.next(); + String page_name = sCmd.next(); + String page_number = sCmd.next(); + + createWidget(widget_name, page_name, page_number, "widgets/widget.anyData.json", "text" + number); +} + +void textSet() { + String number = sCmd.next(); + String text = sCmd.next(); + text.replace("_", " "); + + if (text.indexOf("-time") >= 0) { + text.replace("-time", ""); + text.replace("#", " "); + String time = GetTime(); + time.replace(":", "."); + text = text + " " + GetDataDigital() + " " + time; + } + + jsonWriteStr(configJson, "text" + number, text); + sendSTATUS("text" + number, text); +} + +#ifdef stepper_enable +//stepper 1 12 13 +void stepper() { + String stepper_number = sCmd.next(); + String pin_step = sCmd.next(); + String pin_dir = sCmd.next(); + + jsonWriteStr(optionJson, "stepper" + stepper_number, pin_step + " " + pin_dir); + pinMode(pin_step.toInt(), OUTPUT); + pinMode(pin_dir.toInt(), OUTPUT); +} + +//stepperSet 1 100 5 +void stepperSet() { + String stepper_number = sCmd.next(); + String steps = sCmd.next(); + jsonWriteStr(optionJson, "steps" + stepper_number, steps); + String stepper_speed = sCmd.next(); + String pin_step = selectToMarker(jsonReadStr(optionJson, "stepper" + stepper_number), " "); + String pin_dir = deleteBeforeDelimiter(jsonReadStr(optionJson, "stepper" + stepper_number), " "); + Serial.println(pin_step); + Serial.println(pin_dir); + if (steps.toInt() > 0) digitalWrite(pin_dir.toInt(), HIGH); + if (steps.toInt() < 0) digitalWrite(pin_dir.toInt(), LOW); + if (stepper_number == "1") { + ts.add( + STEPPER1, stepper_speed.toInt(), [&](void*) { + int steps_int = abs(jsonReadInt(optionJson, "steps1") * 2); + static int count; + count++; + String pin_step = selectToMarker(jsonReadStr(optionJson, "stepper1"), " "); + digitalWrite(pin_step.toInt(), !digitalRead(pin_step.toInt())); + yield(); + if (count > steps_int) { + digitalWrite(pin_step.toInt(), LOW); + ts.remove(STEPPER1); + count = 0; + } + }, + nullptr, true); + } + if (stepper_number == "2") { + ts.add( + STEPPER2, stepper_speed.toInt(), [&](void*) { + int steps_int = abs(jsonReadInt(optionJson, "steps2") * 2); + static int count; + count++; + String pin_step = selectToMarker(jsonReadStr(optionJson, "stepper2"), " "); + digitalWrite(pin_step.toInt(), !digitalRead(pin_step.toInt())); + yield(); + if (count > steps_int) { + digitalWrite(pin_step.toInt(), LOW); + ts.remove(STEPPER2); + count = 0; + } + }, + nullptr, true); + } +} +#endif +//==================================================================================================================================================== +//=================================================================Сервоприводы======================================================================= +#ifdef servo_enable +//servo 1 13 50 Мой#сервопривод Сервоприводы 0 100 0 180 2 +void servo_() { + String servo_number = sCmd.next(); + String servo_pin = sCmd.next(); + String start_state = sCmd.next(); + int start_state_int = start_state.toInt(); + String widget_name = sCmd.next(); + String page_name = sCmd.next(); + + String min_value = sCmd.next(); + String max_value = sCmd.next(); + + String min_deg = sCmd.next(); + String max_deg = sCmd.next(); + + String page_number = sCmd.next(); + + jsonWriteStr(optionJson, "servo_pin" + servo_number, servo_pin); + start_state_int = map(start_state_int, min_value.toInt(), max_value.toInt(), min_deg.toInt(), max_deg.toInt()); + + if (servo_number == "1") { +#ifdef ESP8266 + myServo1.attach(servo_pin.toInt()); + myServo1.write(start_state_int); +#endif +#ifdef ESP32 + myServo1.attach(servo_pin.toInt(), 500, 2400); + myServo1.write(start_state_int); +#endif + } + + if (servo_number == "2") { +#ifdef ESP8266 + myServo2.attach(servo_pin.toInt()); + myServo2.write(start_state_int); +#endif +#ifdef ESP32 + myServo2.attach(servo_pin.toInt(), 500, 2400); + myServo2.write(start_state_int); +#endif + } + + jsonWriteStr(optionJson, "s_min_val" + servo_number, min_value); + jsonWriteStr(optionJson, "s_max_val" + servo_number, max_value); + jsonWriteStr(optionJson, "s_min_deg" + servo_number, min_deg); + jsonWriteStr(optionJson, "s_max_deg" + servo_number, max_deg); + + jsonWriteStr(configJson, "servo" + servo_number, start_state); + + createWidgetParam(widget_name, page_name, page_number, "widgets/widget.range.json", "servo" + servo_number, "min", min_value, "max", max_value, "k", "1"); +} + +void servoSet() { + String servo_number = sCmd.next(); + String servo_state = sCmd.next(); + int servo_state_int = servo_state.toInt(); + + // TODO Unused + //int pin = jsonReadInt(optionJson, "servo_pin" + servo_number); + + servo_state_int = map(servo_state_int, + jsonReadInt(optionJson, "s_min_val" + servo_number), + jsonReadInt(optionJson, "s_max_val" + servo_number), + jsonReadInt(optionJson, "s_min_deg" + servo_number), + jsonReadInt(optionJson, "s_max_deg" + servo_number)); + + if (servo_number == "1") { +#ifdef ESP8266 + myServo1.write(servo_state_int); +#endif +#ifdef ESP32 + myServo1.write(servo_state_int); +#endif + } + + if (servo_number == "2") { +#ifdef ESP8266 + myServo2.write(servo_state_int); +#endif +#ifdef ESP32 + myServo2.write(servo_state_int); +#endif + } + + eventGen("servo", servo_number); + + jsonWriteStr(configJson, "servo" + servo_number, servo_state); + sendSTATUS("servo" + servo_number, servo_state); +} +#endif +//==================================================================================================================================================== +//===================================================================================serial=========================================================== +#ifdef serial_enable +void serialBegin() { + //String s_speed = sCmd.next(); + //String rxPin = sCmd.next(); + //String txPin = sCmd.next(); + //SoftwareSerial mySerial(rxPin.toInt(), txPin.toInt()); + //mySerial.begin(s_speed.toInt()); +} + +void serialWrite() { + //String text = sCmd.next(); + //mySerial.println(text); +} +#endif +//==================================================================================================================================================== +//=================================================Глобальные команды удаленного управления=========================================================== + +void mqttOrderSend() { + String id = sCmd.next(); + String order = sCmd.next(); + + String all_line = jsonReadStr(configSetup, "mqttPrefix") + "/" + id + "/order"; + client_mqtt.publish(all_line.c_str(), order.c_str(), false); +} + +void httpOrderSend() { + String ip = sCmd.next(); + String order = sCmd.next(); + order.replace("_", "%20"); + String url = "http://" + ip + "/cmd?command=" + order; + getURL(url); +} + +void update_firmware() { + upgrade = true; +} + +void firmware() { + String widget_name = sCmd.next(); + String page_name = sCmd.next(); + String page_number = sCmd.next(); + jsonWriteStr(configJson, "firm1", firmware_version); + choose_widget_and_create(widget_name, page_name, page_number, "any-data", "firm1"); +} + +//============================================================================================================================== +//============================выполнение команд (в лупе) по очереди из строки order============================================= +void handleCMD_loop() { + if (order_loop != "") { + String tmp = selectToMarker(order_loop, ","); //выделяем из страки order первую команду rel 5 1, + sCmd.readStr(tmp); //выполняем первую команду + Serial.println("[ORDER] => " + order_loop); + order_loop = deleteBeforeDelimiter(order_loop, ","); //осекаем выполненную команду + } +} + +void txtExecution(String file) { + String command_all = readFile(file, 2048) + "\r\n"; + + command_all.replace("\r\n", "\n"); + command_all.replace("\r", "\n"); + + while (command_all.length() != 0) { + String tmp = selectToMarker(command_all, "\n"); + sCmd.readStr(tmp); + command_all = deleteBeforeDelimiter(command_all, "\n"); + } + command_all = ""; +} + +void stringExecution(String str) { + str = str + "\r\n"; + + str.replace("\r\n", "\n"); + str.replace("\r", "\n"); + + while (str.length()) { + String tmp = selectToMarker(str, "\n"); + sCmd.readStr(tmp); + + str = deleteBeforeDelimiter(str, "\n"); + } +} diff --git a/src/FileSystem.cpp b/src/FileSystem.cpp new file mode 100644 index 00000000..2f2a8f61 --- /dev/null +++ b/src/FileSystem.cpp @@ -0,0 +1,40 @@ + +#include +#include + +#include "main.h" +#include "set.h" + +void File_system_init() { + Serial.begin(115200); + //Serial.setDebugOutput(true); + Serial.println("--------------started----------------"); + //-------------------------------------------------------------- + SPIFFS.begin(); + configSetup = readFile("config.json", 4096); + configSetup.replace(" ", ""); + configSetup.replace("\r\n", ""); + Serial.println(configSetup); + jsonWriteStr(configJson, "name", jsonReadStr(configSetup, "name")); + jsonWriteStr(configJson, "lang", jsonReadStr(configSetup, "lang")); + +#ifdef ESP32 + uint32_t chipID_u = ESP.getEfuseMac(); + chipID = String(chipID_u); + jsonWriteStr(configSetup, "chipID", chipID); +#endif + +#ifdef ESP8266 + chipID = String(ESP.getChipId()) + "-" + String(ESP.getFlashChipId()); + jsonWriteStr(configSetup, "chipID", chipID); + Serial.setDebugOutput(0); +#endif + + jsonWriteStr(configSetup, "firmware_version", firmware_version); + + prex = jsonReadStr(configSetup, "mqttPrefix") + "/" + chipID; + Serial.println(chipID); +} + +void get_esp_info() { +} diff --git a/src/Init.cpp b/src/Init.cpp new file mode 100644 index 00000000..a0854c55 --- /dev/null +++ b/src/Init.cpp @@ -0,0 +1,251 @@ +#include "Init.h" + +#include "Scenario.h" +#include "Timers.h" +#include "Widgets.h" +#include "main.h" +#include "set.h" + +void All_init() { + server.on("/init", HTTP_GET, [](AsyncWebServerRequest* request) { + String value; + if (request->hasArg("arg")) { + value = request->getParam("arg")->value(); + } + if (value == "0") { //выкл сценариев + jsonWriteStr(configSetup, "scenario", value); + saveConfig(); + Scenario_init(); + request->send(200, "text/text", "OK"); + } + if (value == "1") { //вкл сценариев + jsonWriteStr(configSetup, "scenario", value); + saveConfig(); + Scenario_init(); + request->send(200, "text/text", "OK"); + } + if (value == "2") { //инициализация + Device_init(); + request->send(200, "text/text", "OK"); + } + if (value == "3") { +#ifdef logging_enable + clean_log_date(); +#endif + request->send(200, "text/text", "OK"); + } + if (value == "4") { + Scenario_init(); + request->send(200, "text/text", "OK"); + } + if (value == "5") { + i2c_scanning = true; + request->redirect("/?utilities"); + } + }); + + prsets_init(); + Device_init(); + Scenario_init(); + Timer_countdown_init(); +} + +void Device_init() { + logging_value_names_list = ""; + enter_to_logging_counter = LOG1 - 1; + + analog_value_names_list = ""; + enter_to_analog_counter = 0; + + level_value_name = ""; + + dhtT_value_name = ""; + dhtH_value_name = ""; + + bmp280T_value_name = ""; + bmp280P_value_name = ""; + + bme280T_value_name = ""; + bme280P_value_name = ""; + bme280H_value_name = ""; + bme280A_value_name = ""; + + int array_sz = sizeof(sensors_reading_map) / sizeof(sensors_reading_map[0]); + + for (int i = 0; i <= array_sz; i++) { + sensors_reading_map[i] = 0; + } + + for (int i = LOG1; i <= LOG5; i++) { + ts.remove(i); + } + +#ifdef layout_in_ram + all_widgets = ""; +#else + SPIFFS.remove("/layout.txt"); +#endif + + txtExecution("firmware.c.txt"); + //outcoming_date(); +} + +void Scenario_init() { + if (jsonReadStr(configSetup, "scenario") == "1") { + scenario = readFile("firmware.s.txt", 2048); + } +} + +void prsets_init() { + server.on("/preset", HTTP_GET, [](AsyncWebServerRequest* request) { + String value; + if (request->hasArg("arg")) { + value = request->getParam("arg")->value(); + } + if (value == "1") { + writeFile("firmware.c.txt", readFile("configs/relay.c.txt", 2048)); + writeFile("firmware.s.txt", readFile("configs/relay.s.txt", 2048)); + } + if (value == "2") { + writeFile("firmware.c.txt", readFile("configs/relay_t.c.txt", 2048)); + writeFile("firmware.s.txt", readFile("configs/relay_t.s.txt", 2048)); + } + if (value == "3") { + writeFile("firmware.c.txt", readFile("configs/relay_c.c.txt", 2048)); + writeFile("firmware.s.txt", readFile("configs/relay_c.s.txt", 2048)); + } + if (value == "4") { + writeFile("firmware.c.txt", readFile("configs/relay_s.c.txt", 2048)); + writeFile("firmware.s.txt", readFile("configs/relay_s.s.txt", 2048)); + } + if (value == "5") { + writeFile("firmware.c.txt", readFile("configs/relay_sw.c.txt", 2048)); + writeFile("firmware.s.txt", readFile("configs/relay_sw.s.txt", 2048)); + } + if (value == "6") { + writeFile("firmware.c.txt", readFile("configs/relay_br.c.txt", 2048)); + writeFile("firmware.s.txt", readFile("configs/relay_br.s.txt", 2048)); + } + if (value == "7") { + writeFile("firmware.c.txt", readFile("configs/relay_sr.c.txt", 2048)); + writeFile("firmware.s.txt", readFile("configs/relay_sr.s.txt", 2048)); + } + if (value == "8") { + writeFile("firmware.c.txt", readFile("configs/pwm.c.txt", 2048)); + writeFile("firmware.s.txt", readFile("configs/pwm.s.txt", 2048)); + } + if (value == "9") { + writeFile("firmware.c.txt", readFile("configs/dht11.c.txt", 2048)); + writeFile("firmware.s.txt", readFile("configs/dht11.s.txt", 2048)); + } + if (value == "10") { + writeFile("firmware.c.txt", readFile("configs/dht22.c.txt", 2048)); + writeFile("firmware.s.txt", readFile("configs/dht22.s.txt", 2048)); + } + if (value == "11") { + writeFile("firmware.c.txt", readFile("configs/analog.c.txt", 2048)); + writeFile("firmware.s.txt", readFile("configs/analog.s.txt", 2048)); + } + if (value == "12") { + writeFile("firmware.c.txt", readFile("configs/dallas.c.txt", 2048)); + writeFile("firmware.s.txt", readFile("configs/dallas.s.txt", 2048)); + } + if (value == "13") { + writeFile("firmware.c.txt", readFile("configs/termostat.c.txt", 2048)); + writeFile("firmware.s.txt", readFile("configs/termostat.s.txt", 2048)); + } + if (value == "14") { + writeFile("firmware.c.txt", readFile("configs/level.c.txt", 2048)); + writeFile("firmware.s.txt", readFile("configs/level.s.txt", 2048)); + } + if (value == "15") { + writeFile("firmware.c.txt", readFile("configs/moution_r.c.txt", 2048)); + writeFile("firmware.s.txt", readFile("configs/moution_r.s.txt", 2048)); + } + if (value == "16") { + writeFile("firmware.c.txt", readFile("configs/moution_s.c.txt", 2048)); + writeFile("firmware.s.txt", readFile("configs/moution_s.s.txt", 2048)); + } + if (value == "17") { + writeFile("firmware.c.txt", readFile("configs/stepper.c.txt", 2048)); + writeFile("firmware.s.txt", readFile("configs/stepper.s.txt", 2048)); + } + if (value == "18") { + writeFile("firmware.c.txt", readFile("configs/servo.c.txt", 2048)); + writeFile("firmware.s.txt", readFile("configs/servo.s.txt", 2048)); + } + if (value == "19") { + writeFile("firmware.c.txt", readFile("configs/firmware.c.txt", 2048)); + writeFile("firmware.s.txt", readFile("configs/firmware.s.txt", 2048)); + } + Device_init(); + Scenario_init(); + request->redirect("/?configuration"); + }); +} + +void up_time() { + uint32_t ss = millis() / 1000; + uint32_t mm = ss / 60; + uint32_t hh = mm / 60; + uint32_t dd = hh / 24; + + String out = ""; + + if (ss != 0) { + out = "[i] uptime = " + String(ss) + " sec"; + jsonWriteStr(configJson, "uptime", String(ss) + " sec"); + } + if (mm != 0) { + out = "[i] uptime = " + String(mm) + " min"; + jsonWriteStr(configJson, "uptime", String(mm) + " min"); + } + if (hh != 0) { + out = "[i] uptime = " + String(hh) + " hours"; + jsonWriteStr(configJson, "uptime", String(hh) + " hours"); + } + if (dd != 0) { + out = "[i] uptime = " + String(dd) + " days"; + jsonWriteStr(configJson, "uptime", String(dd) + " days"); + } + Serial.println(out + ", mqtt_lost_error: " + String(mqtt_lost_error) + ", wifi_lost_error: " + String(wifi_lost_error)); +} + +void statistics() { + if (WiFi.status() == WL_CONNECTED) { + String urls = "http://backup.privet.lv/visitors/?"; + //----------------------------------------------------------------- + urls += WiFi.macAddress().c_str(); + urls += "&"; + //----------------------------------------------------------------- +#ifdef ESP8266 + urls += "iot-manager_esp8266"; +#endif +#ifdef ESP32 + urls += "iot-manager_esp32"; +#endif + urls += "&"; + //----------------------------------------------------------------- +#ifdef ESP8266 + urls += ESP.getResetReason(); + //Serial.println(ESP.getResetReason()); +#endif +#ifdef ESP32 + urls += "Power on"; +#endif + urls += "&"; + //----------------------------------------------------------------- + urls += "ver: " + firmware_version; + //----------------------------------------------------------------- + String stat = getURL(urls); + //Serial.println(stat); + } +} + +void statistics_init() { + ts.add( + STATISTICS, statistics_update, [&](void*) { + statistics(); + }, + nullptr, true); +} diff --git a/src/Logging.cpp b/src/Logging.cpp new file mode 100644 index 00000000..b23028ce --- /dev/null +++ b/src/Logging.cpp @@ -0,0 +1,176 @@ +#include "Logging.h" + +#include "Mqtt.h" +#include "TimeUtils.h" +#include "Widgets.h" +#include "main.h" +#include "set.h" + +#ifdef logging_enable +//===============================================Логирование============================================================ +//logging temp1 1 10 Температура Датчики 2 +void logging() { + String value_name = sCmd.next(); + String period_min = sCmd.next(); + String maxCount = sCmd.next(); + String widget_name = sCmd.next(); + widget_name.replace("#", " "); + String page_name = sCmd.next(); + String page_number = sCmd.next(); + logging_value_names_list += value_name + ","; + // считаем количество входов в эту функцию + enter_to_logging_counter++; + //создаем в файловой системе переменную количества точек на графике с отметкой _c что значит count + jsonWriteStr(optionJson, value_name + "_c", maxCount); + + //создаем график в приложении с топиком _ch /prefix/3234045-1589487/value_name_ch + createChart(widget_name, page_name, page_number, "widgets/widget.chart.json", value_name + "_ch", maxCount); + if (enter_to_logging_counter == LOG1) { + ts.add( + LOG1, period_min.toInt() * 1000 * 60, [&](void*) { + String tmp_buf_1 = selectFromMarkerToMarker(logging_value_names_list, ",", 0); + deleteOldDate("log." + tmp_buf_1 + ".txt", jsonReadInt(optionJson, tmp_buf_1 + "_c"), jsonReadStr(configJson, tmp_buf_1)); + Serial.println("[i] LOGGING for sensor '" + tmp_buf_1 + "' done"); + }, + nullptr, false); + } + if (enter_to_logging_counter == LOG2) { + ts.add( + LOG2, period_min.toInt() * 1000 * 60, [&](void*) { + String tmp_buf_2 = selectFromMarkerToMarker(logging_value_names_list, ",", 1); + deleteOldDate("log." + tmp_buf_2 + ".txt", jsonReadInt(optionJson, tmp_buf_2 + "_c"), jsonReadStr(configJson, tmp_buf_2)); + Serial.println("[i] LOGGING for sensor '" + tmp_buf_2 + "' done"); + }, + nullptr, false); + } + if (enter_to_logging_counter == LOG3) { + ts.add( + LOG3, period_min.toInt() * 1000 * 60, [&](void*) { + String tmp_buf_3 = selectFromMarkerToMarker(logging_value_names_list, ",", 2); + deleteOldDate("log." + tmp_buf_3 + ".txt", jsonReadInt(optionJson, tmp_buf_3 + "_c"), jsonReadStr(configJson, tmp_buf_3)); + Serial.println("[i] LOGGING for sensor '" + tmp_buf_3 + "' done"); + }, + nullptr, false); + } + if (enter_to_logging_counter == LOG4) { + ts.add( + LOG4, period_min.toInt() * 1000 * 60, [&](void*) { + String tmp_buf_4 = selectFromMarkerToMarker(logging_value_names_list, ",", 3); + deleteOldDate("log." + tmp_buf_4 + ".txt", jsonReadInt(optionJson, tmp_buf_4 + "_c"), jsonReadStr(configJson, tmp_buf_4)); + Serial.println("[i] LOGGING for sensor '" + tmp_buf_4 + "' done"); + }, + nullptr, false); + } + if (enter_to_logging_counter == LOG5) { + ts.add( + LOG5, period_min.toInt() * 1000 * 60, [&](void*) { + String tmp_buf_5 = selectFromMarkerToMarker(logging_value_names_list, ",", 4); + deleteOldDate("log." + tmp_buf_5 + ".txt", jsonReadInt(optionJson, tmp_buf_5 + "_c"), jsonReadStr(configJson, tmp_buf_5)); + Serial.println("[i] LOGGING for sensor '" + tmp_buf_5 + "' done"); + }, + nullptr, false); + } +} + +//=========================================Удаление стрых данных и запись новых================================================================== +void deleteOldDate(String file, int seted_number_of_lines, String date_to_add) { + String log_date = readFile(file, 5000); + int current_number_of_lines = count(log_date, "\r\n"); + Serial.println("=====> [i] in log file " + file + " " + current_number_of_lines + " lines"); + + if (current_number_of_lines > seted_number_of_lines + 1) { + SPIFFS.remove("/" + file); + current_number_of_lines = 0; + } + if (current_number_of_lines == 0) { + SPIFFS.remove("/" + file); + current_number_of_lines = 0; + } + if (current_number_of_lines > seted_number_of_lines) { + log_date = deleteBeforeDelimiter(log_date, "\r\n"); + if (GetTimeUnix() != "failed") { + log_date += GetTimeUnix() + " " + date_to_add + "\r\n"; + writeFile(file, log_date); + } + } else { + if (GetTimeUnix() != "failed") { + addFile(file, GetTimeUnix() + " " + date_to_add); + } + } + log_date = ""; +} + +//=========================================Выбор какие данные отправлять================================================================== +void choose_log_date_and_send() { + String all_line = logging_value_names_list; + while (all_line.length() != 0) { + String tmp = selectToMarker(all_line, ","); + sendLogData("log." + tmp + ".txt", tmp + "_ch"); + all_line = deleteBeforeDelimiter(all_line, ","); + } + all_line = ""; +} + +//=========================================Отправка данных=================================================================================== +void sendLogData(String file, String topic) { + String log_date = readFile(file, 5000); + if (log_date != "Failed") { + log_date.replace("\r\n", "\n"); + log_date.replace("\r", "\n"); + String buf = "{}"; + String json_array; + String unix_time; + String value; + while (log_date.length() != 0) { + String tmp = selectToMarker(log_date, "\n"); + log_date = deleteBeforeDelimiter(log_date, "\n"); + unix_time = selectToMarker(tmp, " "); + jsonWriteInt(buf, "x", unix_time.toInt()); + value = deleteBeforeDelimiter(tmp, " "); + jsonWriteFloat(buf, "y1", value.toFloat()); + if (log_date.length() < 3) { + json_array += buf; + } else { + json_array += buf + ","; + } + buf = "{}"; + } + unix_time = ""; + value = ""; + log_date = ""; + json_array = "{\"status\":[" + json_array + "]}"; + Serial.println(json_array); + sendCHART(topic, json_array); + json_array = ""; + getMemoryLoad("[i] after send log date"); + } +} + +/* + //---------------------------------------------- + File configFile = SPIFFS.open("/" + file, "r"); + if (!configFile) { + return; + } + configFile.seek(0, SeekSet); //поставим курсор в начало файла + while (configFile.position() != configFile.size()) { + String tmp = configFile.readStringUntil('\r\n'); + String unix_time = selectToMarker (tmp, " "); + String value = deleteBeforeDelimiter(tmp, " "); + String final_line = "{\"status\":{\"x\":" + unix_time + ",\"y1\":" + value + "}}"; + //Serial.println(final_line); + sendCHART(topic, final_line); + } + getMemoryLoad("[i] after send log date"); +*/ +//=========================================Очистка данных=================================================================================== +void clean_log_date() { + String all_line = logging_value_names_list; + while (all_line.length() != 0) { + String tmp = selectToMarker(all_line, ","); + SPIFFS.remove("/log." + tmp + ".txt"); + all_line = deleteBeforeDelimiter(all_line, ","); + } + all_line = ""; +} +#endif diff --git a/src/Mqtt.cpp b/src/Mqtt.cpp new file mode 100644 index 00000000..6a947ae8 --- /dev/null +++ b/src/Mqtt.cpp @@ -0,0 +1,352 @@ +#include "Mqtt.h" + +#include + +#include "WiFi.h" +#include "main.h" +#include "set.h" + +//===============================================ИНИЦИАЛИЗАЦИЯ================================================ +void MQTT_init() { + ts.add( + WIFI_MQTT_CONNECTION_CHECK, wifi_mqtt_reconnecting, [&](void*) { + up_time(); + if (WiFi.status() == WL_CONNECTED) { + Serial.println("[VV] WiFi-ok"); + if (client_mqtt.connected()) { + Serial.println("[VV] MQTT-ok"); + led_blink("off"); + } else { + MQTT_Connecting(); + if (!just_load) mqtt_lost_error++; + } + } else { + Serial.println("[E] Lost WiFi connection"); + wifi_lost_error++; + ts.remove(WIFI_MQTT_CONNECTION_CHECK); + StartAPMode(); + } + }, + nullptr, true); + + server.on("/mqttSave", HTTP_GET, [](AsyncWebServerRequest* request) { + if (request->hasArg("mqttServer")) { + jsonWriteStr(configSetup, "mqttServer", request->getParam("mqttServer")->value()); + } + if (request->hasArg("mqttPort")) { + int port = (request->getParam("mqttPort")->value()).toInt(); + jsonWriteInt(configSetup, "mqttPort", port); + } + if (request->hasArg("mqttPrefix")) { + jsonWriteStr(configSetup, "mqttPrefix", request->getParam("mqttPrefix")->value()); + } + if (request->hasArg("mqttUser")) { + jsonWriteStr(configSetup, "mqttUser", request->getParam("mqttUser")->value()); + } + if (request->hasArg("mqttPass")) { + jsonWriteStr(configSetup, "mqttPass", request->getParam("mqttPass")->value()); + } + saveConfig(); + mqtt_connection = true; + + request->send(200, "text/text", "ok"); + }); + + server.on("/mqttCheck", HTTP_GET, [](AsyncWebServerRequest* request) { + String tmp = "{}"; + jsonWriteStr(tmp, "title", "" + stateMQTT()); + jsonWriteStr(tmp, "class", "pop-up"); + request->send(200, "text/text", tmp); + }); +} + +void do_mqtt_connection() { + if (mqtt_connection) { + mqtt_connection = false; + client_mqtt.disconnect(); + MQTT_Connecting(); + } +} + +void handleMQTT() { + if (WiFi.status() == WL_CONNECTED) { + if (client_mqtt.connected()) { + client_mqtt.loop(); + } + } +} + +boolean MQTT_Connecting() { + bool res = false; + String mqtt_server = jsonReadStr(configSetup, "mqttServer"); + if ((mqtt_server != "")) { + Serial.println("[E] Lost MQTT connection, start reconnecting"); + led_blink("fast"); + client_mqtt.setServer(mqtt_server.c_str(), jsonReadInt(configSetup, "mqttPort")); + if (WiFi.status() == WL_CONNECTED) { + if (!client_mqtt.connected()) { + Serial.println("[V] Connecting to MQTT server commenced"); + if (client_mqtt.connect(chipID.c_str(), jsonReadStr(configSetup, "mqttUser").c_str(), jsonReadStr(configSetup, "mqttPass").c_str())) { + Serial.println("[VV] MQTT connected"); + led_blink("off"); + client_mqtt.setCallback(callback); + client_mqtt.subscribe(jsonReadStr(configSetup, "mqttPrefix").c_str()); // Для приема получения HELLOW и подтверждения связи + client_mqtt.subscribe((jsonReadStr(configSetup, "mqttPrefix") + "/" + chipID + "/+/control").c_str()); // Подписываемся на топики control + client_mqtt.subscribe((jsonReadStr(configSetup, "mqttPrefix") + "/" + chipID + "/order").c_str()); // Подписываемся на топики order + Serial.println("[V] Callback set, subscribe done"); + res = true; + } else { + Serial.println("[E] try again in " + String(wifi_mqtt_reconnecting / 1000) + " sec"); + led_blink("fast"); + } + } + } + } else { + Serial.println("[E] No date for MQTT connection"); + } + return res; +} + +//=====================================================ВХОДЯЩИЕ ДАННЫЕ======================================================== +void callback(char* topic, byte* payload, unsigned int length) { + Serial.print("[MQTT] "); + Serial.print(topic); + String topic_str = String(topic); + + String str; + for (int i = 0; i < length; i++) { + str += (char)payload[i]; + } + Serial.println(" => " + str); + + if (str == "HELLO") outcoming_date(); + + //превращает название топика в команду, а значение в параметр команды + if (topic_str.indexOf("control") > 0) { //IoTmanager/800324-1458415/button-sw2/control 1 //IoTmanager/800324-1458415/button99/control 1 + String topic = selectFromMarkerToMarker(topic_str, "/", 3); //button1 //button99 + topic = add_set(topic); //buttonSet1 //buttonSet99 + String number = selectToMarkerLast(topic, "Set"); //1 //99 + topic.replace(number, ""); //buttonSet //buttonSet + String final_line = topic + " " + number + " " + str; //buttonSet 1 1 //buttonSet 99 1 + order_loop += final_line + ","; + } + + if (topic_str.indexOf("order") > 0) { + str.replace("_", " "); + //Serial.println(str); + order_loop += str + ","; + } + if (topic_str.indexOf("update") > 0) { + if (str == "1") { + upgrade = true; + } + } +} + +//данные которые отправляем при подключении или отбновлении страницы +void outcoming_date() { + sendAllWigets(); + sendAllData(); + +#ifdef logging_enable + choose_log_date_and_send(); +#endif + + Serial.println("[V] Sending all date to iot manager completed"); +} + +boolean sendMQTT(String end_of_topik, String data) { + String topik = jsonReadStr(configSetup, "mqttPrefix") + "/" + chipID + "/" + end_of_topik; + boolean send_status = client_mqtt.beginPublish(topik.c_str(), data.length(), false); + client_mqtt.print(data); + client_mqtt.endPublish(); + return send_status; +} + +boolean sendCHART(String topik, String data) { + topik = jsonReadStr(configSetup, "mqttPrefix") + "/" + chipID + "/" + topik + "/" + "status"; + boolean send_status = client_mqtt.beginPublish(topik.c_str(), data.length(), false); + client_mqtt.print(data); + client_mqtt.endPublish(); + return send_status; +} + +void sendSTATUS(String topik, String state) { + topik = jsonReadStr(configSetup, "mqttPrefix") + "/" + chipID + "/" + topik + "/" + "status"; + String json_ = "{}"; + jsonWriteStr(json_, "status", state); + client_mqtt.publish(topik.c_str(), json_.c_str(), false); +} + +void sendCONTROL(String id, String topik, String state) { + String all_line = jsonReadStr(configSetup, "mqttPrefix") + "/" + id + "/" + topik + "/control"; + client_mqtt.publish(all_line.c_str(), state.c_str(), false); +} + +//=====================================================ОТПРАВЛЯЕМ ВИДЖЕТЫ======================================================== + +#ifdef layout_in_ram +void sendAllWigets() { + if (all_widgets != "") { + int counter = 0; + String line; + int psn_1 = 0; + int psn_2; + do { + psn_2 = all_widgets.indexOf("\r\n", psn_1); //\r\n + line = all_widgets.substring(psn_1, psn_2); + line.replace("\n", ""); + line.replace("\r\n", ""); + //jsonWriteStr(line, "id", String(counter)); + //jsonWriteStr(line, "pageId", String(counter)); + counter++; + sendMQTT("config", line); + Serial.println("[V] " + line); + psn_1 = psn_2 + 1; + } while (psn_2 + 2 < all_widgets.length()); + getMemoryLoad("[i] after send all widgets"); + } +} +#endif + +#ifndef layout_in_ram +void sendAllWigets() { + File configFile = SPIFFS.open("/layout.txt", "r"); + if (!configFile) { + return; + } + configFile.seek(0, SeekSet); //поставим курсор в начало файла + while (configFile.position() != configFile.size()) { + String widget_to_send = configFile.readStringUntil("\r\n"); + Serial.println("[V] " + widget_to_send); + sendMQTT("config", widget_to_send); + } +} +#endif +//=====================================================ОТПРАВЛЯЕМ ДАННЫЕ В ВИДЖЕТЫ ПРИ ОБНОВЛЕНИИ СТРАНИЦЫ======================================================== +void sendAllData() { //берет строку json и ключи превращает в топики а значения колючей в них посылает + + String current_config = configJson; //{"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1"} + getMemoryLoad("[i] after send all date"); + current_config.replace("{", ""); + current_config.replace("}", ""); //"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1" + current_config += ","; //"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1", + + while (current_config.length() != 0) { + String tmp = selectToMarker(current_config, ","); + String topic = selectToMarker(tmp, ":"); + topic.replace("\"", ""); + String state = selectToMarkerLast(tmp, ":"); + state.replace("\"", ""); + if (topic != "name" && topic != "lang" && topic != "ip" && topic.indexOf("_in") < 0) { + sendSTATUS(topic, state); + //Serial.println("-->" + topic + " " + state); + } + current_config = deleteBeforeDelimiter(current_config, ","); + } +} + +String stateMQTT() { + int state = client_mqtt.state(); + switch (state) { + case -4: + return "the server didn't respond within the keepalive time"; + break; + case -3: + return "the network connection was broken"; + break; + case -2: + return "the network connection failed"; + break; + case -1: + return "the client is disconnected cleanly"; + break; + case 0: + return "the client is connected"; + break; + case 1: + return "the server doesn't support the requested version of MQTT"; + break; + case 2: + return "the server rejected the client identifier"; + break; + case 3: + return "the server was unable to accept the connection"; + break; + case 4: + return "the username/password were rejected"; + break; + case 5: + return "the client was not authorized to connect"; + break; + default: + return "unspecified"; + break; + } +} + +/*void scenario_devices_topiks_subscribe() { + + //SCENARIO ANALOG > 5 800324-1458415 rel1 0 + if (jsonReadStr(configSetup, "scenario") == "1") { + //String all_text = readFile("firmware.s.txt", 1024) + "\r\n"; + String all_text = scenario + "\r\n"; + all_text.replace("\r\n", "\n"); + all_text.replace("\r", "\n"); + while (all_text.length() != 0) { + String line_ = selectToMarker (all_text, "\n"); + String id = selectFromMarkerToMarker(line_, " ", 4); + if (id != "not found") { + client_mqtt.subscribe((jsonReadStr(configSetup, "mqttPrefix") + "/" + id + "/+/status").c_str(), 0); + Serial.println("subscribed to device, id: " + id); + } + all_text = deleteBeforeDelimiter(all_text, "\n"); + } + } + } +*/ +/*void scenario_devices_test_msg_send() { + + if (jsonReadStr(configSetup, "scenario") == "1") { + + String all_text = scenario + "\r\n"; + all_text.replace("\r\n", "\n"); + all_text.replace("\r", "\n"); + while (all_text.length() != 0) { + String line_ = selectToMarker (all_text, "\n"); + String id = selectFromMarkerToMarker(line_, " ", 4); + if (id != "not found") { + //Serial.println(); + Serial.println(client_mqtt.publish ((jsonReadStr(configSetup, "mqttPrefix") + "/" + id).c_str(), "CHECK", true)); + + } + all_text = deleteBeforeDelimiter(all_text, "\n"); + } + } + }*/ + +/* + //----------------------------------------------------------------------------------------------------------------------------------------------- + //jsonWriteStr(tmp, "status", "1"); + + String current_config = configJson; //{"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1"} + current_config.replace("{", ""); + current_config.replace("}", ""); //"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1" + current_config += ","; //"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1", + + while (current_config.length() != 0) { + + String tmp = selectToMarker (current_config, ","); //"rel1":"1" + String topic = selectToMarker (tmp, ":"); //"rel1" + topic.replace("\"", ""); //rel1 + Serial.println(topic); + String state = selectToMarkerLast (tmp, ":"); //"1" + state.replace("\"", ""); //1 + + //if (widget.lastIndexOf(topic) > 0) { + jsonWriteStr(tmp, "status", state); + //} + current_config = deleteBeforeDelimiter(current_config, ","); + } + //------------------------------------------------------------------------------------------------------------------------------------------------- +*/ diff --git a/src/Scenario.cpp b/src/Scenario.cpp new file mode 100644 index 00000000..85c023c6 --- /dev/null +++ b/src/Scenario.cpp @@ -0,0 +1,98 @@ +#include "Scenario.h" + +#include "main.h" +#include "set.h" + +void handleScenario() { + if (jsonReadStr(configSetup, "scenario") == "1") { + if ((jsonReadStr(optionJson, "scenario_status") != "")) { + int i = 0; + String str = scenario; //читаем переменную с сценариями (то что из файла на странице) + str += "\n"; + str.replace("\r\n", "\n"); + str.replace("\r", "\n"); + while (str.length() != 0) { + //----------------------------------------------------------------------------------------------------------------------- + String tmp = selectToMarker(str, "end"); //выделяем первый сценарий из файла вместе с командами + if (tmp == "") return; + i++; + + if (scenario_line_status[i] == 1) { + //Serial.println(i); + String condition = selectToMarker(tmp, "\n"); //выделяем первую строку самого сценария button1 = 1 (условие) + String param_name = selectFromMarkerToMarker(condition, " ", 0); + String order = jsonReadStr(optionJson, "scenario_status"); //читаем весь файл событий + String param = selectToMarker(order, ","); //читаем первое событие из файла событий + if (param_name == param) { //если поступившее событие равно событию заданному buttonSet1 в файле начинаем его обработку + + String sign = selectFromMarkerToMarker(condition, " ", 1); //читаем знак (=) + String value = selectFromMarkerToMarker(condition, " ", 2); //читаем значение (1) + if (value.indexOf("digit") != -1) { + // value = add_set(value); + value = jsonReadStr(configJson, value); + } + if (value.indexOf("time") != -1) { + // value = add_set(value); + value = jsonReadStr(configJson, value); + } + boolean flag = false; //если одно из значений совпало то только тогда начинаем выполнять комнады + if (sign == "=") { + if (jsonReadStr(configJson, param_name) == value) flag = true; + } + if (sign == "!=") { + if (jsonReadStr(configJson, param_name) != value) flag = true; + } + if (sign == "<") { + if (jsonReadStr(configJson, param_name).toInt() < value.toInt()) flag = true; + } + if (sign == ">") { + if (jsonReadStr(configJson, param_name).toInt() > value.toInt()) flag = true; + } + if (sign == ">=") { + if (jsonReadStr(configJson, param_name).toInt() >= value.toInt()) flag = true; + } + if (sign == "<=") { + if (jsonReadStr(configJson, param_name).toInt() <= value.toInt()) flag = true; + } + + if (flag) { + //удаляем строку самого сценария оставляя только команды + tmp = deleteBeforeDelimiter(tmp, "\n"); + //выполняем все команды + stringExecution(tmp); + Serial.println("[SCENARIO] '" + condition + "'"); + } + } + } + str = deleteBeforeDelimiter(str, "end\n"); //удаляем первый сценарий + //----------------------------------------------------------------------------------------------------------------------- + } + String tmp2 = jsonReadStr(optionJson, "scenario_status"); //читаем файл событий + tmp2 = deleteBeforeDelimiter(tmp2, ","); //удаляем выполненное событие + jsonWriteStr(optionJson, "scenario_status", tmp2); //записываем обновленный файл событий + i = 0; + } + } +} + +//событие выглядит как имя плюс set плюс номер: button+Set+1 +void eventGen(String event_name, String number) { + if (jsonReadStr(configSetup, "scenario") == "1") { + String tmp = jsonReadStr(optionJson, "scenario_status"); //генерирование события + //Serial.println(event_name); + jsonWriteStr(optionJson, "scenario_status", tmp + event_name + number + ","); + } +} + +String add_set(String param_name) { + String num1 = param_name.substring(param_name.length() - 1); + String num2 = param_name.substring(param_name.length() - 2, param_name.length() - 1); + if (isDigitStr(num1) && isDigitStr(num2)) { + param_name = param_name.substring(0, param_name.length() - 2) + "Set" + num2 + num1; + } else { + if (isDigitStr(num1)) { + param_name = param_name.substring(0, param_name.length() - 1) + "Set" + num1; + } + } + return param_name; +} diff --git a/src/Sensors.cpp b/src/Sensors.cpp new file mode 100644 index 00000000..d5cc2319 --- /dev/null +++ b/src/Sensors.cpp @@ -0,0 +1,561 @@ +#include "Sensors.h" + +#include "set.h" + +void sensors_init() { + ts.add( + SENSORS, 1000, [&](void*) { + static int counter; + counter++; + +#ifdef level_enable + if (sensors_reading_map[0] == 1) level_reading(); +#endif + + if (counter > 10) { + counter = 0; + +#ifdef analog_enable + if (sensors_reading_map[1] == 1) analog_reading1(); + if (sensors_reading_map[2] == 1) analog_reading2(); +#endif + +#ifdef dallas_enable + if (sensors_reading_map[3] == 1) dallas_reading(); +#endif + +#ifdef dht_enable + if (sensors_reading_map[4] == 1) dhtT_reading(); + if (sensors_reading_map[5] == 1) dhtH_reading(); + if (sensors_reading_map[6] == 1) dhtP_reading(); + if (sensors_reading_map[7] == 1) dhtC_reading(); + if (sensors_reading_map[8] == 1) dhtD_reading(); +#endif + +#ifdef bmp_enable + if (sensors_reading_map[9] == 1) bmp280T_rading(); + if (sensors_reading_map[10] == 1) bmp280P_reading(); +#endif + +#ifdef bme_enable + if (sensors_reading_map[11] == 1) bme280T_reading(); + if (sensors_reading_map[12] == 1) bme280P_reading(); + if (sensors_reading_map[13] == 1) bme280H_reading(); + if (sensors_reading_map[14] == 1) bme280A_reading(); +#endif + } + }, + nullptr, true); +} + +//========================================================================================================================================= +//=========================================Модуль измерения уровня в баке================================================================== +#ifdef level_enable +//level L 14 12 Вода#в#баке,#% Датчики fill-gauge 125 20 1 +void level() { + String value_name = sCmd.next(); + String trig = sCmd.next(); + String echo = sCmd.next(); + String widget_name = sCmd.next(); + String page_name = sCmd.next(); + String type = sCmd.next(); + String empty_level = sCmd.next(); + String full_level = sCmd.next(); + String page_number = sCmd.next(); + level_value_name = value_name; + jsonWriteStr(optionJson, "e_lev", empty_level); + jsonWriteStr(optionJson, "f_lev", full_level); + jsonWriteStr(optionJson, "trig", trig); + jsonWriteStr(optionJson, "echo", echo); + pinMode(trig.toInt(), OUTPUT); + pinMode(echo.toInt(), INPUT); + choose_widget_and_create(widget_name, page_name, page_number, type, value_name); + sensors_reading_map[0] = 1; +} + +void level_reading() { + long duration_; + int distance_cm; + int level; + static int counter; + int trig = jsonReadInt(optionJson, "trig"); + int echo = jsonReadInt(optionJson, "echo"); + digitalWrite(trig, LOW); + delayMicroseconds(2); + digitalWrite(trig, HIGH); + delayMicroseconds(10); + digitalWrite(trig, LOW); + duration_ = pulseIn(echo, HIGH, 30000); // 3000 µs = 50cm // 30000 µs = 5 m + distance_cm = duration_ / 29 / 2; + distance_cm = medianFilter.filtered(distance_cm); //отсечение промахов медианным фильтром + counter++; + if (counter > tank_level_times_to_send) { + counter = 0; + level = map(distance_cm, + jsonReadInt(optionJson, "e_lev"), + jsonReadInt(optionJson, "f_lev"), 0, 100); + jsonWriteInt(configJson, level_value_name, level); + eventGen(level_value_name, ""); + sendSTATUS(level_value_name, String(level)); + Serial.println("[i] sensor '" + level_value_name + "' data: " + String(level)); + } +} +#endif +//========================================================================================================================================= +//=========================================Модуль аналогового сенсора====================================================================== +#ifdef analog_enable +//analog adc 0 Аналоговый#вход,#% Датчики any-data 1 1023 1 100 1 +void analog() { + String value_name = sCmd.next(); + String pin = sCmd.next(); + String widget_name = sCmd.next(); + String page_name = sCmd.next(); + String type = sCmd.next(); + String analog_start = sCmd.next(); + String analog_end = sCmd.next(); + String analog_start_out = sCmd.next(); + String analog_end_out = sCmd.next(); + String page_number = sCmd.next(); + analog_value_names_list += value_name + ","; + enter_to_analog_counter++; + jsonWriteStr(optionJson, value_name + "_st", analog_start); + jsonWriteStr(optionJson, value_name + "_end", analog_end); + jsonWriteStr(optionJson, value_name + "_st_out", analog_start_out); + jsonWriteStr(optionJson, value_name + "_end_out", analog_end_out); + choose_widget_and_create(widget_name, page_name, page_number, type, value_name); + if (enter_to_analog_counter == 1) { + sensors_reading_map[1] = 1; + } + if (enter_to_analog_counter == 2) { + sensors_reading_map[2] = 1; + } +} + +void analog_reading1() { + String value_name = selectFromMarkerToMarker(analog_value_names_list, ",", 0); +#ifdef ESP32 + int analog_in = analogRead(34); +#endif +#ifdef ESP8266 + int analog_in = analogRead(A0); +#endif + int analog = map(analog_in, + jsonReadInt(optionJson, value_name + "_st"), + jsonReadInt(optionJson, value_name + "_end"), + jsonReadInt(optionJson, value_name + "_st_out"), + jsonReadInt(optionJson, value_name + "_end_out")); + jsonWriteInt(configJson, value_name, analog); + eventGen(value_name, ""); + sendSTATUS(value_name, String(analog)); + Serial.println("[i] sensor '" + value_name + "' data: " + String(analog)); +} + +void analog_reading2() { + String value_name = selectFromMarkerToMarker(analog_value_names_list, ",", 1); +#ifdef ESP32 + int analog_in = analogRead(35); +#endif +#ifdef ESP8266 + int analog_in = analogRead(A0); +#endif + int analog = map(analog_in, + jsonReadInt(optionJson, value_name + "_st"), + jsonReadInt(optionJson, value_name + "_end"), + jsonReadInt(optionJson, value_name + "_st_out"), + jsonReadInt(optionJson, value_name + "_end_out")); + jsonWriteInt(configJson, value_name, analog); + eventGen(value_name, ""); + sendSTATUS(value_name, String(analog)); + Serial.println("[i] sensor '" + value_name + "' data: " + String(analog)); +} +#endif +//========================================================================================================================================= +//=========================================Модуль температурного сенсора ds18b20=========================================================== +#ifdef dallas_enable +void dallas() { + String value_name = sCmd.next(); + String pin = sCmd.next(); + String address = sCmd.next(); + String widget_name = sCmd.next(); + String page_name = sCmd.next(); + String type = sCmd.next(); + String page_number = sCmd.next(); + oneWire = new OneWire((uint8_t)pin.toInt()); + sensors.setOneWire(oneWire); + sensors.begin(); + sensors.setResolution(12); + choose_widget_and_create(widget_name, page_name, page_number, type, "dallas"); + sensors_reading_map[3] = 1; +} + +void dallas_reading() { + float temp = 0; + sensors.requestTemperatures(); + temp = sensors.getTempCByIndex(0); + jsonWriteStr(configJson, "dallas", String(temp)); + eventGen("dallas", ""); + sendSTATUS("dallas", String(temp)); + Serial.println("[i] sensor 'dallas' send date " + String(temp)); +} +#endif +//========================================================================================================================================= +//=========================================Модуль сенсоров DHT============================================================================= +#ifdef dht_enable +//dhtT t 2 dht11 Температура#DHT,#t°C Датчики any-data 1 +void dhtT() { + String value_name = sCmd.next(); + String pin = sCmd.next(); + String sensor_type = sCmd.next(); + String widget_name = sCmd.next(); + String page_name = sCmd.next(); + String type = sCmd.next(); + String page_number = sCmd.next(); + dhtT_value_name = value_name; + if (sensor_type == "dht11") { + dht.setup(pin.toInt(), DHTesp::DHT11); + } + if (sensor_type == "dht22") { + dht.setup(pin.toInt(), DHTesp::DHT22); + } + choose_widget_and_create(widget_name, page_name, page_number, type, value_name); + sensors_reading_map[4] = 1; +} + +void dhtT_reading() { + float value = 0; + static int counter; + if (dht.getStatus() != 0 && counter < 5) { + sendSTATUS(dhtT_value_name, String(dht.getStatusString())); + counter++; + } else { + counter = 0; + value = dht.getTemperature(); + if (String(value) != "nan") { + eventGen(dhtT_value_name, ""); + jsonWriteStr(configJson, dhtT_value_name, String(value)); + sendSTATUS(dhtT_value_name, String(value)); + Serial.println("[i] sensor '" + dhtT_value_name + "' data: " + String(value)); + } + } +} + +//dhtH h 2 dht11 Влажность#DHT,#t°C Датчики any-data 1 +void dhtH() { + String value_name = sCmd.next(); + String pin = sCmd.next(); + String sensor_type = sCmd.next(); + String widget_name = sCmd.next(); + String page_name = sCmd.next(); + String type = sCmd.next(); + String page_number = sCmd.next(); + dhtH_value_name = value_name; + if (sensor_type == "dht11") { + dht.setup(pin.toInt(), DHTesp::DHT11); + } + if (sensor_type == "dht22") { + dht.setup(pin.toInt(), DHTesp::DHT22); + } + choose_widget_and_create(widget_name, page_name, page_number, type, value_name); + sensors_reading_map[5] = 1; +} + +void dhtH_reading() { + float value = 0; + static int counter; + if (dht.getStatus() != 0 && counter < 5) { + sendSTATUS(dhtH_value_name, String(dht.getStatusString())); + counter++; + } else { + counter = 0; + value = dht.getHumidity(); + if (String(value) != "nan") { + eventGen(dhtH_value_name, ""); + jsonWriteStr(configJson, dhtH_value_name, String(value)); + sendSTATUS(dhtH_value_name, String(value)); + Serial.println("[i] sensor '" + dhtH_value_name + "' data: " + String(value)); + } + } +} + +//dhtPerception Восприятие: Датчики 4 +void dhtP() { + String widget_name = sCmd.next(); + String page_name = sCmd.next(); + String page_number = sCmd.next(); + choose_widget_and_create(widget_name, page_name, page_number, "any-data", "dhtPerception"); + sensors_reading_map[6] = 1; +} + +void dhtP_reading() { + byte value; + if (dht.getStatus() != 0) { + sendSTATUS("dhtPerception", String(dht.getStatusString())); + } else { + value = dht.computePerception(jsonReadStr(configJson, dhtT_value_name).toFloat(), jsonReadStr(configJson, dhtH_value_name).toFloat(), false); + String final_line = perception(value); + jsonWriteStr(configJson, "dhtPerception", final_line); + eventGen("dhtPerception", ""); + sendSTATUS("dhtPerception", final_line); + if (client_mqtt.connected()) { + Serial.println("[i] sensor 'dhtPerception' data: " + final_line); + } + } +} + +String perception(byte value) { + if (value == 0) return "Сухой воздух"; + if (value == 1) return "Комфортно"; + if (value == 2) return "Уютно"; + if (value == 3) return "Хорошо"; + if (value == 4) return "Неудобно"; + if (value == 5) return "Довольно неудобно"; + if (value == 6) return "Очень неудобно"; + if (value == 7) return "Сильно неудобно, полный звиздец"; +} + +//dhtComfort Степень#комфорта: Датчики 3 +void dhtC() { + String widget_name = sCmd.next(); + String page_name = sCmd.next(); + String page_number = sCmd.next(); + choose_widget_and_create(widget_name, page_name, page_number, "any-data", "dhtComfort"); + sensors_reading_map[7] = 1; +} + +void dhtC_reading() { + float value; + ComfortState cf; + if (dht.getStatus() != 0) { + sendSTATUS("dhtComfort", String(dht.getStatusString())); + } else { + value = dht.getComfortRatio(cf, jsonReadStr(configJson, dhtT_value_name).toFloat(), jsonReadStr(configJson, dhtH_value_name).toFloat(), false); + String final_line = get_comfort_status(cf); + jsonWriteStr(configJson, "dhtComfort", final_line); + eventGen("dhtComfort", ""); + sendSTATUS("dhtComfort", final_line); + Serial.println("[i] sensor 'dhtComfort' send date " + final_line); + } +} + +String get_comfort_status(ComfortState cf) { + String comfortStatus; + switch (cf) { + case Comfort_OK: + comfortStatus = "Отлично"; + break; + case Comfort_TooHot: + comfortStatus = "Очень жарко"; + break; + case Comfort_TooCold: + comfortStatus = "Очень холодно"; + break; + case Comfort_TooDry: + comfortStatus = "Очень сухо"; + break; + case Comfort_TooHumid: + comfortStatus = "Очень влажно"; + break; + case Comfort_HotAndHumid: + comfortStatus = "Жарко и влажно"; + break; + case Comfort_HotAndDry: + comfortStatus = "Жарко и сухо"; + break; + case Comfort_ColdAndHumid: + comfortStatus = "Холодно и влажно"; + break; + case Comfort_ColdAndDry: + comfortStatus = "Холодно и сухо"; + break; + default: + comfortStatus = "Неизвестно"; + break; + }; + return comfortStatus; +} + +//dhtDewpoint Точка#росы: Датчики 5 +void dhtD() { + String widget_name = sCmd.next(); + String page_name = sCmd.next(); + String page_number = sCmd.next(); + choose_widget_and_create(widget_name, page_name, page_number, "any-data", "dhtDewpoint"); + sensors_reading_map[8] = 1; +} + +void dhtD_reading() { + float value; + if (dht.getStatus() != 0) { + sendSTATUS("dhtDewpoint", String(dht.getStatusString())); + } else { + value = dht.computeDewPoint(jsonReadStr(configJson, dhtT_value_name).toFloat(), jsonReadStr(configJson, dhtH_value_name).toFloat(), false); + jsonWriteInt(configJson, "dhtDewpoint", value); + eventGen("dhtDewpoint", ""); + sendSTATUS("dhtDewpoint", String(value)); + Serial.println("[i] sensor 'dhtDewpoint' data: " + String(value)); + } +} +#endif +//=========================================i2c bus esp8266 scl-4 sda-5 ==================================================================== +//========================================================================================================================================= +//=========================================Модуль сенсоров bmp280========================================================================== +#ifdef bmp_enable +//bmp280T temp1 0x76 Температура#bmp280 Датчики any-data 1 +void bmp280T() { + String value_name = sCmd.next(); + String address = sCmd.next(); + String widget_name = sCmd.next(); + String page_name = sCmd.next(); + String type = sCmd.next(); + String page_number = sCmd.next(); + bmp280T_value_name = value_name; + choose_widget_and_create(widget_name, page_name, page_number, type, value_name); + bmp.begin(hexStringToUint8(address)); + bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, /* Operating Mode. */ + Adafruit_BMP280::SAMPLING_X2, /* Temp. oversampling */ + Adafruit_BMP280::SAMPLING_X16, /* Pressure oversampling */ + Adafruit_BMP280::FILTER_X16, /* Filtering. */ + Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */ + //bmp_temp->printSensorDetails(); + sensors_reading_map[9] = 1; +} + +void bmp280T_rading() { + float value = 0; + sensors_event_t temp_event, pressure_event; + bmp_temp->getEvent(&temp_event); + value = temp_event.temperature; + jsonWriteStr(configJson, bmp280T_value_name, String(value)); + eventGen(bmp280T_value_name, ""); + sendSTATUS(bmp280T_value_name, String(value)); + Serial.println("[i] sensor '" + bmp280T_value_name + "' data: " + String(value)); +} + +//bmp280P press1 0x76 Давление#bmp280 Датчики any-data 2 +void bmp280P() { + String value_name = sCmd.next(); + String address = sCmd.next(); + String widget_name = sCmd.next(); + String page_name = sCmd.next(); + String type = sCmd.next(); + String page_number = sCmd.next(); + bmp280P_value_name = value_name; + choose_widget_and_create(widget_name, page_name, page_number, type, value_name); + bmp.begin(hexStringToUint8(address)); + bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, /* Operating Mode. */ + Adafruit_BMP280::SAMPLING_X2, /* Temp. oversampling */ + Adafruit_BMP280::SAMPLING_X16, /* Pressure oversampling */ + Adafruit_BMP280::FILTER_X16, /* Filtering. */ + Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */ + //bmp_temp->printSensorDetails(); + sensors_reading_map[10] = 1; +} + +void bmp280P_reading() { + float value = 0; + sensors_event_t temp_event, pressure_event; + bmp_pressure->getEvent(&pressure_event); + value = pressure_event.pressure; + value = value / 1.333224; + jsonWriteStr(configJson, bmp280P_value_name, String(value)); + eventGen(bmp280P_value_name, ""); + sendSTATUS(bmp280P_value_name, String(value)); + Serial.println("[i] sensor '" + bmp280P_value_name + "' data: " + String(value)); +} +#endif +//========================================================================================================================================= +//=============================================Модуль сенсоров bme280====================================================================== +#ifdef bme_enable +//bme280T temp1 0x76 Температура#bmp280 Датчики any-data 1 +void bme280T() { + String value_name = sCmd.next(); + String address = sCmd.next(); + String widget_name = sCmd.next(); + String page_name = sCmd.next(); + String type = sCmd.next(); + String page_number = sCmd.next(); + bme280T_value_name = value_name; + choose_widget_and_create(widget_name, page_name, page_number, type, value_name); + bme.begin(hexStringToUint8(address)); + sensors_reading_map[11] = 1; +} + +void bme280T_reading() { + float value = 0; + value = bme.readTemperature(); + jsonWriteStr(configJson, bme280T_value_name, String(value)); + eventGen(bme280T_value_name, ""); + sendSTATUS(bme280T_value_name, String(value)); + Serial.println("[i] sensor '" + bme280T_value_name + "' data: " + String(value)); +} + +//bme280P pres1 0x76 Давление#bmp280 Датчики any-data 1 +void bme280P() { + String value_name = sCmd.next(); + String address = sCmd.next(); + String widget_name = sCmd.next(); + String page_name = sCmd.next(); + String type = sCmd.next(); + String page_number = sCmd.next(); + bme280P_value_name = value_name; + choose_widget_and_create(widget_name, page_name, page_number, type, value_name); + bme.begin(hexStringToUint8(address)); + sensors_reading_map[12] = 1; +} + +void bme280P_reading() { + float value = 0; + value = bme.readPressure(); + value = value / 1.333224; + jsonWriteStr(configJson, bme280P_value_name, String(value)); + eventGen(bme280P_value_name, ""); + sendSTATUS(bme280P_value_name, String(value)); + Serial.println("[i] sensor '" + bme280P_value_name + "' data: " + String(value)); +} + +//bme280H hum1 0x76 Влажность#bmp280 Датчики any-data 1 +void bme280H() { + String value_name = sCmd.next(); + String address = sCmd.next(); + String widget_name = sCmd.next(); + String page_name = sCmd.next(); + String type = sCmd.next(); + String page_number = sCmd.next(); + bme280H_value_name = value_name; + choose_widget_and_create(widget_name, page_name, page_number, type, value_name); + bme.begin(hexStringToUint8(address)); + sensors_reading_map[13] = 1; +} + +void bme280H_reading() { + float value = 0; + value = bme.readHumidity(); + jsonWriteStr(configJson, bme280H_value_name, String(value)); + eventGen(bme280H_value_name, ""); + sendSTATUS(bme280H_value_name, String(value)); + Serial.println("[i] sensor '" + bme280H_value_name + "' data: " + String(value)); +} + +//bme280A altit1 0x76 Высота#bmp280 Датчики any-data 1 +void bme280A() { + String value_name = sCmd.next(); + String address = sCmd.next(); + String widget_name = sCmd.next(); + String page_name = sCmd.next(); + String type = sCmd.next(); + String page_number = sCmd.next(); + bme280A_value_name = value_name; + choose_widget_and_create(widget_name, page_name, page_number, type, value_name); + bme.begin(hexStringToUint8(address)); + sensors_reading_map[14] = 1; +} + +void bme280A_reading() { + float value = 0; + value = bme.readAltitude(1013.25); + jsonWriteStr(configJson, bme280A_value_name, String(value)); + eventGen(bme280A_value_name, ""); + sendSTATUS(bme280A_value_name, String(value)); + Serial.println("[i] sensor '" + bme280A_value_name + "' data: " + String(value)); +} +#endif diff --git a/src/TimeUtils.cpp b/src/TimeUtils.cpp new file mode 100644 index 00000000..b64a5a3f --- /dev/null +++ b/src/TimeUtils.cpp @@ -0,0 +1,149 @@ +#include "TimeUtils.h" + +#include "main.h" +#include "set.h" + +void Time_Init() { + server.on("/time", HTTP_GET, [](AsyncWebServerRequest* request) { + if (request->hasArg("timezone")) { + jsonWriteStr(configSetup, "timezone", request->getParam("timezone")->value()); + } + if (request->hasArg("ntp")) { + jsonWriteStr(configSetup, "ntp", request->getParam("ntp")->value()); + } + saveConfig(); + reconfigTime(); + request->send(200, "text/text", "OK"); + }); + + ts.add( + TIME_SYNC, 30000, [&](void*) { + time_check(); + }, + nullptr, true); +} + +void time_check() { + if (GetTimeUnix() == "failed") { + Serial.println("[i] Time is not synchronized, start synchronization"); + reconfigTime(); + } +} + +void reconfigTime() { + if (WiFi.status() == WL_CONNECTED) { + String ntp = jsonReadStr(configSetup, "ntp"); + configTime(0, 0, ntp.c_str()); + int i = 0; + Serial.println("[i] Awaiting for time "); +#ifdef ESP32 + struct tm timeinfo; + while (!getLocalTime(&timeinfo) && i <= 4) { + Serial.print("."); + i++; + delay(1000); + } +#endif +#ifdef ESP8266 + //while (!time(nullptr) && i < 4) { + // Serial.print("."); + // i++; + delay(2000); + //} +#endif + if (GetTimeUnix() != "failed") { + Serial.print("[V] Time synchronized = "); + Serial.print(GetDataDigital()); + Serial.print(" "); + Serial.println(GetTime()); + } else { + Serial.println("[E] Time server or internet connection error, will try again in 30 sec"); + } + } else { + Serial.println("[E] Get time impossible, no wifi connection"); + } +} + +//Получаем время в формате linux gmt +String GetTimeUnix() { + time_t now = time(nullptr); + if (now < 30000) { + return "failed"; + } else { + return String(now); + } +} + +// Получение текущего времени +String GetTime() { + time_t now = time(nullptr); // получаем время с помощью библиотеки time.h + int zone = 3600 * jsonReadStr(configSetup, "timezone").toInt(); + now = now + zone; + String Time = ""; // Строка для результатов времени + Time += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 + int i = Time.indexOf(":"); //Ишем позицию первого символа : + Time = Time.substring(i - 2, i + 6); // Выделяем из строки 2 символа перед символом : и 6 символов после + return Time; // Возврашаем полученное время +} + +String GetTimeWOsec() { + time_t now = time(nullptr); // получаем время с помощью библиотеки time.h + int zone = 3600 * jsonReadStr(configSetup, "timezone").toInt(); + now = now + zone; + String Time = ""; // Строка для результатов времени + Time += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 + int i = Time.indexOf(":"); //Ишем позицию первого символа : + Time = Time.substring(i - 2, i + 3); // Выделяем из строки 2 символа перед символом : и 6 символов после + return Time; // Возврашаем полученное время +} + +// Получение даты +String GetDate() { + time_t now = time(nullptr); // получаем время с помощью библиотеки time.h + int zone = 3600 * jsonReadStr(configSetup, "timezone").toInt(); + now = now + zone; + String Data = ""; // Строка для результатов времени + Data += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 + Data.replace("\n", ""); + uint8_t i = Data.lastIndexOf(" "); //Ишем позицию последнего символа пробел + String Time = Data.substring(i - 8, i + 1); // Выделяем время и пробел + Data.replace(Time, ""); // Удаляем из строки 8 символов времени и пробел + return Data; // Возврашаем полученную дату +} + +String GetDataDigital() { + String date = GetDate(); + date = deleteBeforeDelimiter(date, " "); + date.replace("Jan", "01"); + date.replace("Feb", "02"); + date.replace("Mar", "03"); + date.replace("Apr", "04"); + date.replace("May", "05"); + date.replace("Jun", "06"); + date.replace("Jul", "07"); + date.replace("Aug", "08"); + date.replace("Sep", "09"); + date.replace("Oct", "10"); + date.replace("Nov", "11"); + date.replace("Dec", "12"); + + String month = date.substring(0, 2); + String day = date.substring(3, 5); + String year = date.substring(8, 10); + + String out = day; + out += "."; + out += month; + out += "."; + out += year; + + return out; +} + +int timeToMin(String Time) { + //"00:00:00" время в секунды + long min = selectToMarker(Time, ":").toInt() * 60; //общее количество секунд в полных часах + Time = deleteBeforeDelimiter(Time, ":"); // Теперь здесь минуты секунды + min += selectToMarker(Time, ":").toInt(); // Добавим секунды из полных минут + return min; +} diff --git a/src/Timers.cpp b/src/Timers.cpp new file mode 100644 index 00000000..c2ff61b4 --- /dev/null +++ b/src/Timers.cpp @@ -0,0 +1,93 @@ +#include "Timers.h" + +#include "Scenario.h" +#include "main.h" +#include "set.h" + +void Timer_countdown_init() { + ts.add( + TIMER_COUNTDOWN, 1000, [&](void*) { + String old_line = jsonReadStr(optionJson, "timers"); + if (old_line != "") { + //Serial.println(old_line); + int i = 0; + do { + String timer = selectFromMarkerToMarker(old_line, ",", i); + Serial.print("timer no " + String(i) + ": "); + Serial.println(timer); + if (timer == "not found" || timer == "") return; + int number = selectToMarker(timer, ":").toInt(); + int time = readTimer(number); + if (time == 0) { + delTimer(String(number)); + jsonWriteStr(configJson, "timer" + String(number), "0"); + eventGen("timer", String(number)); + } else { + time--; + addTimer(String(number), String(time)); + } + i++; + } while (i <= 9); + } + }, + nullptr, true); +} + +void timerStart() { + String number = sCmd.next(); + String period_of_time = sCmd.next(); + String type = sCmd.next(); + if (period_of_time.indexOf("digit") != -1) { + period_of_time = jsonReadStr(configJson, period_of_time); + } + if (type == "sec") period_of_time = period_of_time; + if (type == "min") period_of_time = String(period_of_time.toInt() * 60); + if (type == "hours") period_of_time = String(period_of_time.toInt() * 60 * 60); + addTimer(number, period_of_time); + jsonWriteStr(configJson, "timer" + number, "1"); +} + +void addTimer(String number, String time) { + String tmp = jsonReadStr(optionJson, "timers"); //1:60,2:120, + String new_timer = number + ":" + time; + int psn1 = tmp.indexOf(number + ":"); //0 ищем позицию таймера который надо заменить + if (psn1 != -1) { //если он есть + int psn2 = tmp.indexOf(",", psn1); //4 от этой позиции находим позицию запятой + String timer = tmp.substring(psn1, psn2); //1:60 выделяем таймер который надо заменить + ///tmp.replace(timer, new_timer); //заменяем таймер на новый (во всей стороке) + tmp.replace(timer + ",", ""); + tmp += new_timer + ","; + } else { //если его нет + tmp += new_timer + ","; + } + jsonWriteStr(optionJson, "timers", tmp); + //Serial.println("ura"); +} + +void timerStop() { + String number = sCmd.next(); + delTimer(number); +} + +void delTimer(String number) { + String tmp = jsonReadStr(optionJson, "timers"); //1:60,2:120, + int psn1 = tmp.indexOf(number + ":"); //0 ищем позицию таймера который надо удалить + if (psn1 != -1) { //если он есть + int psn2 = tmp.indexOf(",", psn1); //4 от этой позиции находим позицию запятой + String timer = tmp.substring(psn1, psn2) + ","; //1:60, выделяем таймер который надо удалить + tmp.replace(timer, ""); //удаляем таймер + jsonWriteStr(optionJson, "timers", tmp); + } +} + +int readTimer(int number) { + String tmp = jsonReadStr(optionJson, "timers"); //1:60,2:120, + int psn1 = tmp.indexOf(String(number) + ":"); //0 ищем позицию таймера который надо прочитать + String timer; + if (psn1 != -1) { //если он есть + int psn2 = tmp.indexOf(",", psn1); //4 от этой позиции находим позицию запятой + timer = tmp.substring(psn1, psn2); //1:60 выделяем таймер который надо прочитать + timer = deleteBeforeDelimiter(timer, ":"); + } + return timer.toInt(); +} diff --git a/src/Upgrade.cpp b/src/Upgrade.cpp new file mode 100644 index 00000000..5a815aee --- /dev/null +++ b/src/Upgrade.cpp @@ -0,0 +1,235 @@ +#include "Upgrade.h" + +#include "main.h" +#include "set.h" + +static const char* UPGRADE_URL PROGMEM = "http://91.204.228.124:1100/update/"; + +const String getUpgradeUrl() { + String url = FPSTR(UPGRADE_URL); +#ifdef ESP32 + url += "esp32"; +#else + url += "esp8266"; +#endif + url += "/version.txt"; + return url; +} + +void initUpgrade() { + String last_version = WiFi.status() == WL_CONNECTED ? getURL(getUpgradeUrl()) : ""; + jsonWriteStr(configSetup, "last_version", last_version); + + Serial.printf("[i] Last firmware version: %s\n", last_version); + + server.on("/check", HTTP_GET, [last_version](AsyncWebServerRequest* request) { + upgrade_url = true; + Serial.printf("[i] Last firmware version: %s\n", last_version); + String tmp = "{}"; + if (WiFi.status() == WL_CONNECTED) { + if (mb_4_of_memory) { + if (last_version != "") { + if (last_version != "error") { + if (last_version == firmware_version) { + jsonWriteStr(tmp, "title", "Последняя версия прошивки уже установлена."); + jsonWriteStr(tmp, "class", "pop-up"); + } else { + jsonWriteStr(tmp, "title", "Имеется новая версия прошивкиИдет обновление прошивки, после обновления страница перезагрузится автоматически...')\">Установить"); + jsonWriteStr(tmp, "class", "pop-up"); + } + } else { + jsonWriteStr(tmp, "title", "Ошибка... Cервер не найден. Попробуйте позже..."); + jsonWriteStr(tmp, "class", "pop-up"); + } + } else { + jsonWriteStr(tmp, "title", "Нажмите на кнопку \"обновить прошивку\" повторно..."); + jsonWriteStr(tmp, "class", "pop-up"); + } + } else { + jsonWriteStr(tmp, "title", "Обновление по воздуху не поддерживается, модуль имеет меньше 4 мб памяти..."); + jsonWriteStr(tmp, "class", "pop-up"); + } + } else { + jsonWriteStr(tmp, "title", "Устройство не подключен к роутеру..."); + jsonWriteStr(tmp, "class", "pop-up"); + } + request->send(200, "text/text", tmp); + }); + + server.on("/upgrade", HTTP_GET, [](AsyncWebServerRequest* request) { + upgrade = true; + String tmp = "{}"; + request->send(200, "text/text", "ok"); + }); +} + +void do_upgrade_url() { + if (upgrade_url) { + upgrade_url = false; +#ifdef ESP32 + last_version = getURL("http://91.204.228.124:1100/update/esp32/version.txt"); + jsonWriteStr(configSetup, "last_version", last_version); +#endif +#ifdef ESP8266 + last_version = getURL("http://91.204.228.124:1100/update/esp8266/version.txt"); + jsonWriteStr(configSetup, "last_version", last_version); +#endif + } +} + +void upgrade_firmware() { + String scenario_for_update; + String config_for_update; + String configSetup_for_update; + scenario_for_update = readFile("firmware.s.txt", 4000); + config_for_update = readFile("firmware.c.txt", 4000); + configSetup_for_update = configSetup; + + Serial.println("Start upgrade SPIFFS, please wait..."); + + WiFiClient client_for_upgrade; + +#ifdef ESP32 + httpUpdate.rebootOnUpdate(false); + t_httpUpdate_return ret = httpUpdate.updateSpiffs(client_for_upgrade, "http://91.204.228.124:1100/update/esp32/esp32-esp8266_iot-manager_modules_firmware.spiffs.bin"); +#endif +#ifdef ESP8266 + ESPhttpUpdate.rebootOnUpdate(false); + t_httpUpdate_return ret = ESPhttpUpdate.updateSpiffs(client_for_upgrade, "http://91.204.228.124:1100/update/esp8266/esp32-esp8266_iot-manager_modules_firmware.spiffs.bin"); +#endif + + if (ret == HTTP_UPDATE_OK) { + writeFile("firmware.s.txt", scenario_for_update); + writeFile("firmware.c.txt", config_for_update); + writeFile("config.json", configSetup_for_update); + saveConfig(); + + Serial.println("SPIFFS upgrade done!"); + Serial.println("Start upgrade BUILD, please wait..."); + +#ifdef ESP32 + //httpUpdate.rebootOnUpdate(true); + t_httpUpdate_return ret = httpUpdate.update(client_for_upgrade, "http://91.204.228.124:1100/update/esp32/esp32-esp8266_iot-manager_modules_firmware.ino.bin"); +#endif +#ifdef ESP8266 + //ESPhttpUpdate.rebootOnUpdate(true); + t_httpUpdate_return ret = ESPhttpUpdate.update(client_for_upgrade, "http://91.204.228.124:1100/update/esp8266/esp32-esp8266_iot-manager_modules_firmware.ino.bin"); +#endif + + if (ret == HTTP_UPDATE_OK) { + Serial.println("BUILD upgrade done!"); + Serial.println("Restart ESP...."); + ESP.restart(); + } else { + Serial.println("!!!!BUILD upgrade ERROR"); + } + } else { + Serial.println("!!!!SPIFFS upgrade ERROR"); + } +} + +void do_upgrade() { + if (upgrade) { + upgrade = false; + upgrade_firmware(); + } +} + +/* + void upgrade_status(t_httpUpdate_return set) { + switch (set) { + case HTTP_UPDATE_FAILED: + Serial.printf("UPDATE_FAILED Error (%d): %s", httpUpdate.getLastError(), httpUpdate.getLastErrorString().c_str()); + break; + + case HTTP_UPDATE_NO_UPDATES: + Serial.println("NO_UPDATES"); + break; + + case HTTP_UPDATE_OK: + Serial.println("HTTP_UPDATE_OK"); + break; + } + } +*/ + +/* + // ----------------------- Обновление с сайта + void webUpgrade() { + + #ifdef ESP8266 + String spiffsData = "http://91.204.228.124:1100/update/esp8266/esp32-esp8266_iot-manager_modules_firmware.spiffs.bin"; + String buildData = "http://91.204.228.124:1100/update/esp8266/esp32-esp8266_iot-manager_modules_firmware.ino.bin"; + #endif + + #ifdef ESP32 + String spiffsData = "http://91.204.228.124:1100/update/esp32/esp32-esp8266_iot-manager_modules_firmware.spiffs.bin"; + String buildData = "http://91.204.228.124:1100/update/esp32/esp32-esp8266_iot-manager_modules_firmware.ino.bin"; + #endif + + if (spiffsData != "") { // Если нужно прошить FS + String scenario_for_update; + String config_for_update; + String configSetup_for_update; + Serial.println(spiffsData); + scenario_for_update = readFile("firmware.s.txt", 2048); + config_for_update = readFile("config.all.txt", 2048); + configSetup_for_update = configSetup; + ESPhttpUpdate.rebootOnUpdate(false); // Отключим перезагрузку после обновления + updateHTTP(spiffsData, true); + writeFile("firmware.s.txt", scenario_for_update); + writeFile("config.all.txt", config_for_update); + writeFile("config.json", configSetup_for_update); + saveConfig(); + } + + if (buildData != "") { // Если нужно прошить build + Serial.println(buildData); + ESPhttpUpdate.rebootOnUpdate(true); // Включим перезагрузку после обновления + updateHTTP(buildData, false); + } + } + // ------------------ Обновление по url + void updateHTTP(String url, boolean mode) { + if (url == "") return; + ESPhttpUpdate.setLedPin(LED_BUILTIN, LOW); + if (mode) { + Serial.println("Update Spiffs..."); + t_httpUpdate_return ret = ESPhttpUpdate.updateSpiffs(url); + UpdateStatus(ret , "Spiffs"); + } else { + Serial.println("Update Build..."); + t_httpUpdate_return ret = ESPhttpUpdate.update(url); + UpdateStatus(ret , "build"); + } + } + void UpdateStatus(t_httpUpdate_return set, String mode) { + + switch (set) { + + case HTTP_UPDATE_FAILED: + Serial.println(mode + "_FAILED"); + var = "{}"; + jsonWriteStr(var, "title", "_FAILED"); + jsonWriteStr(var, "class", "pop-up"); + //request->send(200, "text/text", var); + break; + + case HTTP_UPDATE_NO_UPDATES: + Serial.println(mode + "_NO_UPDATES"); + var = "{}"; + jsonWriteStr(var, "title", "_NO_UPDATES"); + jsonWriteStr(var, "class", "pop-up"); + //request->send(200, "text/text", var); + break; + + case HTTP_UPDATE_OK: + Serial.println(mode + "_UPDATE_OK"); + var = "{}"; + jsonWriteStr(var, "title", "_UPDATE_OK"); + jsonWriteStr(var, "class", "pop-up"); + //request->send(200, "text/text", var); + break; + } + } +*/ diff --git a/src/Web_server.cpp b/src/Web_server.cpp new file mode 100644 index 00000000..98a6b2b5 --- /dev/null +++ b/src/Web_server.cpp @@ -0,0 +1,231 @@ +#include "main.h" +#include "set.h" + +void Web_server_init() { +#ifdef OTA_enable + ArduinoOTA.onStart([]() { + events.send("Update Start", "ota"); + }); + ArduinoOTA.onEnd([]() { + events.send("Update End", "ota"); + }); + ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { + char p[32]; + sprintf(p, "Progress: %u%%\n", (progress / (total / 100))); + events.send(p, "ota"); + }); + ArduinoOTA.onError([](ota_error_t error) { + if (error == OTA_AUTH_ERROR) + events.send("Auth Failed", "ota"); + else if (error == OTA_BEGIN_ERROR) + events.send("Begin Failed", "ota"); + else if (error == OTA_CONNECT_ERROR) + events.send("Connect Failed", "ota"); + else if (error == OTA_RECEIVE_ERROR) + events.send("Recieve Failed", "ota"); + else if (error == OTA_END_ERROR) + events.send("End Failed", "ota"); + }); + ArduinoOTA.setHostname(hostName); + ArduinoOTA.begin(); +#endif + /********************************************************************************* + **************************************MDNS**************************************** + *********************************************************************************/ +#ifdef MDNS_enable + MDNS.addService("http", "tcp", 80); +#endif + //SPIFFS.begin(); + /********************************************************************************* + **************************************WS****************************************** + *********************************************************************************/ +#ifdef WS_enable + ws.onEvent(onWsEvent); + server.addHandler(&ws); + + events.onConnect([](AsyncEventSourceClient *client) { + //!!!client->send("hello!", NULL, millis(), 1000); + }); + + server.addHandler(&events); +#endif + +#ifdef ESP32 + server.addHandler(new SPIFFSEditor(SPIFFS, jsonReadStr(configSetup, "web_login").c_str(), jsonReadStr(configSetup, "web_pass").c_str())); +#elif defined(ESP8266) + server.addHandler(new SPIFFSEditor(jsonReadStr(configSetup, "web_login").c_str(), jsonReadStr(configSetup, "web_pass").c_str())); +#endif + + /* server.on("/heap", HTTP_GET, [](AsyncWebServerRequest * request) { + request->send(200, "text/plain", String(ESP.getFreeHeap())); + });*/ + + server.serveStatic("/css/", SPIFFS, "/css/").setCacheControl("max-age=31536000"); + server.serveStatic("/js/", SPIFFS, "/js/").setCacheControl("max-age=31536000"); + server.serveStatic("/favicon.ico", SPIFFS, "/favicon.ico").setCacheControl("max-age=31536000"); + + server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.htm").setAuthentication(jsonReadStr(configSetup, "web_login").c_str(), jsonReadStr(configSetup, "web_pass").c_str()); + + server.onNotFound([](AsyncWebServerRequest *request) { + Serial.printf("NOT_FOUND: "); + if (request->method() == HTTP_GET) + Serial.printf("GET"); + else if (request->method() == HTTP_POST) + Serial.printf("POST"); + else if (request->method() == HTTP_DELETE) + Serial.printf("DELETE"); + else if (request->method() == HTTP_PUT) + Serial.printf("PUT"); + else if (request->method() == HTTP_PATCH) + Serial.printf("PATCH"); + else if (request->method() == HTTP_HEAD) + Serial.printf("HEAD"); + else if (request->method() == HTTP_OPTIONS) + Serial.printf("OPTIONS"); + else + Serial.printf("UNKNOWN"); + Serial.printf(" http://%s%s\n", request->host().c_str(), request->url().c_str()); + + if (request->contentLength()) { + Serial.printf("_CONTENT_TYPE: %s\n", request->contentType().c_str()); + Serial.printf("_CONTENT_LENGTH: %u\n", request->contentLength()); + } + + int headers = request->headers(); + int i; + for (i = 0; i < headers; i++) { + AsyncWebHeader *h = request->getHeader(i); + Serial.printf("_HEADER[%s]: %s\n", h->name().c_str(), h->value().c_str()); + } + + int params = request->params(); + for (i = 0; i < params; i++) { + AsyncWebParameter *p = request->getParam(i); + if (p->isFile()) { + Serial.printf("_FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size()); + } else if (p->isPost()) { + Serial.printf("_POST[%s]: %s\n", p->name().c_str(), p->value().c_str()); + } else { + Serial.printf("_GET[%s]: %s\n", p->name().c_str(), p->value().c_str()); + } + } + + request->send(404); + }); + + server.onFileUpload([](AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final) { + if (!index) + Serial.printf("UploadStart: %s\n", filename.c_str()); + Serial.printf("%s", (const char *)data); + if (final) + Serial.printf("UploadEnd: %s (%u)\n", filename.c_str(), index + len); + }); + + server.onRequestBody([](AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) { + if (!index) + Serial.printf("BodyStart: %u\n", total); + Serial.printf("%s", (const char *)data); + if (index + len == total) + Serial.printf("BodyEnd: %u\n", total); + }); + + server.begin(); + + // --------------------Выдаем данные configJson //config.live.json - динамические данные + server.on("/config.live.json", HTTP_GET, [](AsyncWebServerRequest *request) { + request->send(200, "application/json", configJson); + }); + // --------------------Выдаем данные optionJson //config.option.json - данные не являющиеся событиями + server.on("/config.option.json", HTTP_GET, [](AsyncWebServerRequest *request) { + request->send(200, "application/json", optionJson); + }); + // -------------------Выдаем данные configSetup //config.setup.json - для хранения постоянных данных + server.on("/config.setup.json", HTTP_GET, [](AsyncWebServerRequest *request) { + request->send(200, "application/json", configSetup); + }); + + // ------------------Выполнение команды из запроса + //http://192.168.88.45/cmd?command=rel%201%201 + server.on("/cmd", HTTP_GET, [](AsyncWebServerRequest *request) { + String com = request->getParam("command")->value(); + Serial.println(com); + order_loop += com + ","; + request->send(200, "text/text", "OK"); // отправляем ответ о выполнении + }); +} +/********************************************************************************************************************************* + *********************************************************WS********************************************************************** + ********************************************************************************************************************************/ +#ifdef WS_enable +void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) { + if (type == WS_EVT_CONNECT) { + Serial.printf("ws[%s][%u] connect\n", server->url(), client->id()); + client->printf(json.c_str(), client->id()); + //client->ping(); + } else if (type == WS_EVT_DISCONNECT) { + Serial.printf("ws[%s][%u] disconnect\n", server->url(), client->id()); + } else if (type == WS_EVT_ERROR) { + Serial.printf("ws[%s][%u] error(%u): %s\n", server->url(), client->id(), *((uint16_t *)arg), (char *)data); + } else if (type == WS_EVT_PONG) { + Serial.printf("ws[%s][%u] pong[%u]: %s\n", server->url(), client->id(), len, (len) ? (char *)data : ""); + } else if (type == WS_EVT_DATA) { + AwsFrameInfo *info = (AwsFrameInfo *)arg; + String msg = ""; + if (info->final && info->index == 0 && info->len == len) { + //the whole message is in a single frame and we got all of it's data + Serial.printf("ws[%s][%u] %s-message[%llu]: ", server->url(), client->id(), (info->opcode == WS_TEXT) ? "text" : "binary", info->len); + + if (info->opcode == WS_TEXT) { + for (size_t i = 0; i < info->len; i++) { + msg += (char)data[i]; + } + } else { + char buff[3]; + for (size_t i = 0; i < info->len; i++) { + sprintf(buff, "%02x ", (uint8_t)data[i]); + msg += buff; + } + } + Serial.printf("%s\n", msg.c_str()); + + if (info->opcode == WS_TEXT) + client->text("{}"); + else + client->binary("{}"); + } else { + //message is comprised of multiple frames or the frame is split into multiple packets + if (info->index == 0) { + if (info->num == 0) + Serial.printf("ws[%s][%u] %s-message start\n", server->url(), client->id(), (info->message_opcode == WS_TEXT) ? "text" : "binary"); + Serial.printf("ws[%s][%u] frame[%u] start[%llu]\n", server->url(), client->id(), info->num, info->len); + } + + Serial.printf("ws[%s][%u] frame[%u] %s[%llu - %llu]: ", server->url(), client->id(), info->num, (info->message_opcode == WS_TEXT) ? "text" : "binary", info->index, info->index + len); + + if (info->opcode == WS_TEXT) { + for (size_t i = 0; i < len; i++) { + msg += (char)data[i]; + } + } else { + char buff[3]; + for (size_t i = 0; i < len; i++) { + sprintf(buff, "%02x ", (uint8_t)data[i]); + msg += buff; + } + } + Serial.printf("%s\n", msg.c_str()); + + if ((info->index + len) == info->len) { + Serial.printf("ws[%s][%u] frame[%u] end[%llu]\n", server->url(), client->id(), info->num, info->len); + if (info->final) { + Serial.printf("ws[%s][%u] %s-message end\n", server->url(), client->id(), (info->message_opcode == WS_TEXT) ? "text" : "binary"); + if (info->message_opcode == WS_TEXT) + client->text("I got your text message"); + else + client->binary("I got your binary message"); + } + } + } + } +} +#endif diff --git a/src/WiFiUtils.cpp b/src/WiFiUtils.cpp new file mode 100644 index 00000000..15ebc535 --- /dev/null +++ b/src/WiFiUtils.cpp @@ -0,0 +1,163 @@ +#include "main.h" +#include "set.h" + +void WIFI_init() { + // --------------------Получаем ssid password со страницы + server.on("/ssid", HTTP_GET, [](AsyncWebServerRequest* request) { + if (request->hasArg("ssid")) { + jsonWriteStr(configSetup, "ssid", request->getParam("ssid")->value()); + } + if (request->hasArg("password")) { + jsonWriteStr(configSetup, "password", request->getParam("password")->value()); + } + saveConfig(); // Функция сохранения данных во Flash + request->send(200, "text/text", "OK"); // отправляем ответ о выполнении + }); + // --------------------Получаем ssidAP passwordAP со страницы + server.on("/ssidap", HTTP_GET, [](AsyncWebServerRequest* request) { + if (request->hasArg("ssidAP")) { + jsonWriteStr(configSetup, "ssidAP", request->getParam("ssidAP")->value()); + } + if (request->hasArg("passwordAP")) { + jsonWriteStr(configSetup, "passwordAP", request->getParam("passwordAP")->value()); + } + saveConfig(); // Функция сохранения данных во Flash + request->send(200, "text/text", "OK"); // отправляем ответ о выполнении + }); + + // --------------------Получаем логин и пароль для web со страницы + server.on("/web", HTTP_GET, [](AsyncWebServerRequest* request) { + if (request->hasArg("web_login")) { + jsonWriteStr(configSetup, "web_login", request->getParam("web_login")->value()); + } + if (request->hasArg("web_pass")) { + jsonWriteStr(configSetup, "web_pass", request->getParam("web_pass")->value()); + } + saveConfig(); // Функция сохранения данных во Flash + //Web_server_init(); + request->send(200, "text/text", "OK"); // отправляем ответ о выполнении + }); + + server.on("/restart", HTTP_GET, [](AsyncWebServerRequest* request) { + if (request->hasArg("device")) { + if (request->getParam("device")->value() == "ok") ESP.restart(); + } + request->send(200, "text/text", "OK"); // отправляем ответ о выполнении + }); + ROUTER_Connecting(); +} + +void ROUTER_Connecting() { + led_blink("slow"); + + WiFi.mode(WIFI_STA); + + byte tries = 20; + String _ssid = jsonReadStr(configSetup, "ssid"); + String _password = jsonReadStr(configSetup, "password"); + //WiFi.persistent(false); + + if (_ssid == "" && _password == "") { + WiFi.begin(); + } else { + WiFi.begin(_ssid.c_str(), _password.c_str()); + Serial.print("ssid: "); + Serial.println(_ssid); + } + // Делаем проверку подключения до тех пор пока счетчик tries + // не станет равен нулю или не получим подключение + while (--tries && WiFi.status() != WL_CONNECTED) { + if (WiFi.status() == WL_CONNECT_FAILED) { + Serial.println("[E] password is not correct"); + tries = 1; + jsonWriteInt(optionJson, "pass_status", 1); + } + Serial.print("."); + delay(1000); + } + + Serial.println(); + if (WiFi.status() != WL_CONNECTED) { + StartAPMode(); + } else { + Serial.println("[V] WiFi connected"); + Serial.print("[V] IP address: http://"); + Serial.print(WiFi.localIP()); + Serial.println(); + + jsonWriteStr(configJson, "ip", WiFi.localIP().toString()); + led_blink("off"); + } +} + +bool StartAPMode() { + Serial.println("WiFi up AP"); + WiFi.disconnect(); + + WiFi.mode(WIFI_AP); + + String _ssidAP = jsonReadStr(configSetup, "ssidAP"); + String _passwordAP = jsonReadStr(configSetup, "passwordAP"); + WiFi.softAP(_ssidAP.c_str(), _passwordAP.c_str()); + IPAddress myIP = WiFi.softAPIP(); + led_blink("on"); + Serial.print("AP IP address: "); + Serial.println(myIP); + jsonWriteStr(configJson, "ip", myIP.toString()); + + if (jsonReadInt(optionJson, "pass_status") != 1) { + ts.add( + ROUTER_SEARCHING, 10 * 1000, [&](void*) { + Serial.println("->try find router"); + if (RouterFind(jsonReadStr(configSetup, "ssid"))) { + ts.remove(ROUTER_SEARCHING); + WiFi.scanDelete(); + ROUTER_Connecting(); + MQTT_init(); + } + }, + nullptr, true); + } + return true; +} + +boolean RouterFind(String ssid) { + int n = WiFi.scanComplete(); + Serial.println("n = " + String(n)); + if (n == -2) { //Сканирование не было запущено, запускаем + Serial.println("[WIFI][i] scanning has not been triggered, starting scanning"); + WiFi.scanNetworks(true, false); //async, show_hidden + return false; + } + if (n == -1) { //Сканирование все еще выполняется + Serial.println("[WIFI][i] scanning still in progress"); + return false; + } + if (n == 0) { //ни одна сеть не найдена + Serial.println("[WIFI][i] no any wifi sations, starting scanning"); + WiFi.scanNetworks(true, false); + return false; + } + if (n > 0) { + for (int i = 0; i <= n; i++) { + if (WiFi.SSID(i) == ssid) { + WiFi.scanDelete(); + return true; + } else { + Serial.print(i); + Serial.print(")"); + //Serial.print(ssid); + //Serial.print("<=>"); + if (i == n) { + Serial.print(WiFi.SSID(i)); + Serial.println("; "); + } else { + Serial.print(WiFi.SSID(i)); + Serial.println("; "); + } + } + } + WiFi.scanDelete(); + return false; + } +} diff --git a/src/Widgets.cpp b/src/Widgets.cpp new file mode 100644 index 00000000..b9de8aa5 --- /dev/null +++ b/src/Widgets.cpp @@ -0,0 +1,82 @@ +#include "Widgets.h" + +#include "main.h" +#include "set.h" + +void createWidget(String widget_name, String page_name, String page_number, String file, String topic) { + String widget; + widget = readFile(file, 1024); + if (widget == "Failed") return; + if (widget == "Large") return; + widget_name.replace("#", " "); + page_name.replace("#", " "); + jsonWriteStr(widget, "page", page_name); + jsonWriteStr(widget, "order", page_number); + jsonWriteStr(widget, "descr", widget_name); + jsonWriteStr(widget, "topic", prex + "/" + topic); +#ifdef layout_in_ram + all_widgets += widget + "\r\n"; +#else + addFile("layout.txt", widget); +#endif + widget = ""; +} + +void createWidgetParam(String widget_name, String page_name, String page_number, String file, String topic, String name1, String param1, String name2, String param2, String name3, String param3) { + String widget; + widget = readFile(file, 1024); + + if (widget == "Failed") return; + if (widget == "Large") return; + + widget_name.replace("#", " "); + page_name.replace("#", " "); + + jsonWriteStr(widget, "page", page_name); + jsonWriteStr(widget, "order", page_number); + jsonWriteStr(widget, "descr", widget_name); + jsonWriteStr(widget, "topic", prex + "/" + topic); + + if (name1 != "") jsonWriteStr(widget, name1, param1); + if (name2 != "") jsonWriteStr(widget, name2, param2); + if (name3 != "") jsonWriteStr(widget, name3, param3); + +#ifdef layout_in_ram + all_widgets += widget + "\r\n"; +#else + addFile("layout.txt", widget); +#endif + widget = ""; +} + +void createChart(String widget_name, String page_name, String page_number, String file, String topic, String maxCount) { + String widget; + widget = readFile(file, 1024); + + if (widget == "Failed") return; + if (widget == "Large") return; + + widget_name.replace("#", " "); + page_name.replace("#", " "); + + jsonWriteStr(widget, "page", page_name); + jsonWriteStr(widget, "order", page_number); + //jsonWriteStr(widget, "descr", widget_name); + jsonWriteStr(widget, "series", widget_name); + jsonWriteStr(widget, "maxCount", maxCount); + jsonWriteStr(widget, "topic", prex + "/" + topic); + +#ifdef layout_in_ram + all_widgets += widget + "\r\n"; +#else + addFile("layout.txt", widget); +#endif + widget = ""; +} + +void choose_widget_and_create(String widget_name, String page_name, String page_number, String type, String topik) { + if (type == "any-data") createWidget(widget_name, page_name, page_number, "widgets/widget.anyData.json", topik); + if (type == "progress-line") createWidget(widget_name, page_name, page_number, "widgets/widget.progLine.json", topik); + if (type == "progress-round") createWidget(widget_name, page_name, page_number, "widgets/widget.progRound.json", topik); + if (type == "fill-gauge") createWidget(widget_name, page_name, page_number, "widgets/widget.fillGauge.json", topik); +} diff --git a/src/i2c_bus.cpp b/src/i2c_bus.cpp new file mode 100644 index 00000000..e44155c8 --- /dev/null +++ b/src/i2c_bus.cpp @@ -0,0 +1,38 @@ +#include "i2c_bus.h" + +#include "main.h" +#include "set.h" + +void do_i2c_scanning() { + if (i2c_scanning) { + i2c_scanning = false; + String tmp = i2c_scan(); + if (tmp == "error") { + tmp = i2c_scan(); + Serial.println(tmp); + jsonWriteStr(configJson, "i2c", tmp); + } else { + Serial.println(tmp); + jsonWriteStr(configJson, "i2c", tmp); + } + } +} + +String i2c_scan() { + String out; + byte count = 0; + Wire.begin(); + for (byte i = 8; i < 120; i++) { + Wire.beginTransmission(i); + if (Wire.endTransmission() == 0) { + count++; + out += String(count) + ". 0x" + String(i, HEX) + "; "; + delay(1); + } + } + if (count == 0) { + return "error"; + } else { + return out; + } +} diff --git a/src/iot_firmware.cpp b/src/iot_firmware.cpp new file mode 100644 index 00000000..f265ebcd --- /dev/null +++ b/src/iot_firmware.cpp @@ -0,0 +1,88 @@ +#include "Cmd.h" +#include "FileSystem.h" +#include "Sensors.h" +#include "set.h" + +void setup() { + File_system_init(); + Serial.println("SPIFFS_init"); + + CMD_init(); + Serial.println("[V] CMD_init"); + + sensors_init(); + Serial.println("[V] sensors_init"); + + All_init(); + Serial.println("[V] All_init"); + //-------------------------------------------------------------- + WIFI_init(); + Serial.println("[V] WIFI_init"); + //-------------------------------------------------------------- + statistics_init(); + Serial.println("[V] statistics_init"); + //-------------------------------------------------------------- + initUpgrade(); + Serial.println("[V] initUpgrade"); + //-------------------------------------------------------------- + Web_server_init(); + Serial.println("[V] Web_server_init"); + //-------------------------------------------------------------- + MQTT_init(); + Serial.println("[V] MQTT_init"); + //-------------------------------------------------------------- + Time_Init(); + Serial.println("[V] Time_Init"); + //-------------------------------------------------------------- +#ifdef push_enable + Push_init(); + Serial.println("[V] Push_init"); +#endif + //-------------------------------------------------------------- +#ifdef UDP_enable + UDP_init(); + Serial.println("[V] UDP_init"); +#endif + //-------------------------------------------------------------- + + ts.add( + TEST, 10000, [&](void*) { + getMemoryLoad("[i] periodic check of"); + //ws.textAll(json); + }, + nullptr, true); + + just_load = false; +} + +void loop() { +#ifdef OTA_enable + ArduinoOTA.handle(); +#endif + +#ifdef WS_enable + ws.cleanupClients(); +#endif + + not_async_actions(); + + handleMQTT(); + handleCMD_loop(); + handleButton(); + handleScenario(); +#ifdef UDP_enable + handleUdp(); +#endif + ts.update(); +} + +void not_async_actions() { + do_mqtt_connection(); + do_upgrade_url(); + do_upgrade(); +#ifdef UDP_enable + do_udp_data_parse(); + do_mqtt_send_settings_to_udp(); +#endif + do_i2c_scanning(); +} diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 00000000..7b923734 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,399 @@ +#include "main.h" + +#include "set.h" + +String jsonReadStr(String& json, String name) { + DynamicJsonBuffer jsonBuffer; + JsonObject& root = jsonBuffer.parseObject(json); + return root[name].as(); +} + +int jsonReadInt(String& json, String name) { + DynamicJsonBuffer jsonBuffer; + JsonObject& root = jsonBuffer.parseObject(json); + return root[name]; +} + +String jsonWriteStr(String& json, String name, String volume) { + DynamicJsonBuffer jsonBuffer; + JsonObject& root = jsonBuffer.parseObject(json); + root[name] = volume; + json = ""; + root.printTo(json); + return json; +} + +String jsonWriteInt(String& json, String name, int volume) { + DynamicJsonBuffer jsonBuffer; + JsonObject& root = jsonBuffer.parseObject(json); + root[name] = volume; + json = ""; + root.printTo(json); + return json; +} + +String jsonWriteFloat(String& json, String name, float volume) { + DynamicJsonBuffer jsonBuffer; + JsonObject& root = jsonBuffer.parseObject(json); + root[name] = volume; + json = ""; + root.printTo(json); + return json; +} + +//============================================================================================================ +//=============================================BIT AND BYTE=================================================== +uint8_t hexStringToUint8(String hex) { + uint8_t tmp = strtol(hex.c_str(), NULL, 0); + if (tmp >= 0x00 && tmp <= 0xFF) { + return tmp; + } +} + +uint16_t hexStringToUint16(String hex) { + uint16_t tmp = strtol(hex.c_str(), NULL, 0); + if (tmp >= 0x0000 && tmp <= 0xFFFF) { + return tmp; + } +} + +void saveConfig() { + writeFile("config.json", configSetup); +} + +// --------Выделяем строку от конца строки до маркера----------------------------------------------------------- +String selectToMarkerLast(String str, String found) { + int p = str.lastIndexOf(found); + return str.substring(p + found.length()); +} + +String selectToMarker(String str, String found) { + int p = str.indexOf(found); + return str.substring(0, p); +} + +String deleteAfterDelimiter(String str, String found) { + int p = str.indexOf(found); + return str.substring(0, p); +} + +String deleteBeforeDelimiter(String str, String found) { + int p = str.indexOf(found) + found.length(); + return str.substring(p); +} + +String deleteBeforeDelimiterTo(String str, String found) { + int p = str.indexOf(found); + return str.substring(p); +} + +// -------------------Выделяем строку от конца строки до маркера ------------------------------------------------ +String deleteToMarkerLast(String str, String found) { + int p = str.lastIndexOf(found); + return str.substring(0, p); +} +// -------------------Выделяем строку от конца строки до маркера + ---------------------------------------------- +String selectToMarkerPlus(String str, String found, int plus) { + int p = str.indexOf(found); + return str.substring(0, p + plus); +} +//--------------------Выделяем строку от маркера до маркера ----------------------------------------------------- +String selectFromMarkerToMarker(String str, String found, int number) { + if (str.indexOf(found) == -1) return "not found"; // если строки поиск нет сразу выход + str += found; // добавим для корректного поиска + uint8_t i = 0; // Индекс перебора + do { + if (i == number) return selectToMarker(str, found); // если индекс совпал с позицией законцим вернем резултат + str = deleteBeforeDelimiter(str, found); // отбросим проверенный блок до разделителя + i++; // увеличим индекс + } while (str.length() != 0); // повторим пока строка не пустая + return "not found"; // Достигли пустой строки и ничего не нашли +} +//--------------------Посчитать ----------------------------------------------------------------------------------- +int count(String str, String found) { + if (str.indexOf(found) == -1) return 0; // если строки поиск нет сразу выход + str += found; // добавим для корректного поиска + uint8_t i = 0; // Индекс перебора + while (str.length() != 0) { + str = deleteBeforeDelimiter(str, found); // отбросим проверенный блок до разделителя + i++; // увеличим индекс + } + return i; // Достигли пустой строки и ничего не нашли +} + +boolean isDigitStr(String str) { + if (str.length() == 1) { + return Digit(str); + } + if (str.length() > 1) { + for (int i = 0; i < str.length(); i++) { + if (!Digit(String(str.charAt(i)))) return false; + } + return true; + } +} +boolean Digit(String str) { + if (str == "0" || str == "1" || str == "2" || str == "3" || str == "4" || str == "5" || str == "6" || str == "7" || str == "8" || str == "9") { + return true; + } else { + return false; + } +} + +String getURL(String urls) { + String answer = ""; + HTTPClient http; + http.begin(urls); //HTTP + int httpCode = http.GET(); + if (httpCode == HTTP_CODE_OK) { + answer = http.getString(); + } else { + answer = "error"; + } + http.end(); + return answer; +} +//=================================================================================================================== +//===========================================FILES=================================================================== +// ------------- Добавление файла ----------------------------------------------------------------------------------- +String safeDataToFile(String data, String Folder) { + //String fileName = GetDate(); + String fileName; + fileName.toLowerCase(); + fileName = deleteBeforeDelimiter(fileName, " "); + fileName.replace(" ", "."); + fileName.replace("..", "."); + fileName = Folder + "/" + fileName + ".txt"; + // addFile(fileName, GetTime() + "/" + data); + Serial.println(fileName); + jsonWriteStr(configJson, "test", fileName); +} +// ------------- Чтение файла в строку ------------------------------------------------------------------------------- +String readFile(String fileName, size_t len) { + File configFile = SPIFFS.open("/" + fileName, "r"); + if (!configFile) { + return "Failed"; + } + size_t size = configFile.size(); + if (size > len) { + configFile.close(); + return "Large"; + } + String temp = configFile.readString(); + configFile.close(); + return temp; +} +// ------------- Размер файла ---------------------------------------------------------------------------------------- +String sizeFile(String fileName) { + File configFile = SPIFFS.open("/" + fileName, "r"); + if (!configFile) { + return "Failed"; + } + size_t size = configFile.size(); + configFile.close(); + return String(size); +} +// ------------- Запись строки в файл --------------------------------------------------------------------------------- +String writeFile(String fileName, String strings) { + File configFile = SPIFFS.open("/" + fileName, "w"); + if (!configFile) { + return "Failed to open config file"; + } + configFile.print(strings); + //strings.printTo(configFile); + configFile.close(); + return "Write sucsses"; +} +// ------------- Добовление строки в файл ------------------------------------------------------------------------------ +String addFile(String fileName, String strings) { + File configFile = SPIFFS.open("/" + fileName, "a"); + if (!configFile) { + return "Failed to open config file"; + } + configFile.println(strings); + configFile.close(); + return "Write sucsses"; +} +// ------------- Чтение строки из файла --------------------------------------------------------------------------------- +//возвращает стоку из файла в которой есть искомое слово found + +String readFileString(const String& filename, const String& str_to_found) { + String res = "failed"; + auto file = SPIFFS.open("/" + filename, "r"); + if (file && file.find(str_to_found.c_str())) { + res = file.readStringUntil('\n'); + } + file.close(); + return res; +} + +void sendCONFIG(String topik, String widgetConfig, String key, String date) { + yield(); + topik = jsonReadStr(configSetup, "mqttPrefix") + "/" + chipID + "/" + topik + "/status"; + String outer = "{\"widgetConfig\":"; + String inner = "{\""; + inner = inner + key; + inner = inner + "\":\""; + inner = inner + date; + inner = inner + "\""; + inner = inner + "}}"; + String t = outer + inner; + //Serial.println(t); + //client_mqtt.publish(MQTT::Publish(topik, t).set_qos(1)); + yield(); +} + +void led_blink(String satus) { +#ifdef ESP8266 +#ifdef blink_pin + pinMode(blink_pin, OUTPUT); + if (satus == "off") { + noTone(blink_pin); + digitalWrite(blink_pin, HIGH); + } + if (satus == "on") { + noTone(blink_pin); + digitalWrite(blink_pin, LOW); + } + if (satus == "slow") tone(blink_pin, 1); + if (satus == "fast") tone(blink_pin, 20); +#endif +#endif +} +//========================================================================================================================= +//=========================================ОСТАВШАЯСЯ ОПЕРАТИВНАЯ ПАМЯТЬ=================================================== +void getMemoryLoad(String text) { +#ifdef ESP8266 + int all_memory = 52864; +#endif +#ifdef ESP32 + int all_memory = 362868; +#endif + int memory_remain = ESP.getFreeHeap(); + int memory_used = all_memory - memory_remain; + int memory_load = (memory_used * 100) / all_memory; + if (memory_load > 65) Serial.print("Attention!!! too match memory used!!!"); + Serial.print(text + " memory used:"); + Serial.print(String(memory_load) + "%; "); + Serial.print("memory remain: "); + Serial.println(String(memory_remain) + " k bytes"); +} +//esp32 full memory = 362868 k bytes +//esp8266 full memory = 52864 k bytes + +//=================================================================== +/* + void web_print (String text) { + if (WiFi.status() == WL_CONNECTED) { + jsonWriteStr(json, "test1", jsonReadStr(json, "test2")); + jsonWriteStr(json, "test2", jsonReadStr(json, "test3")); + jsonWriteStr(json, "test3", jsonReadStr(json, "test4")); + jsonWriteStr(json, "test4", jsonReadStr(json, "test5")); + jsonWriteStr(json, "test5", jsonReadStr(json, "test6")); + + jsonWriteStr(json, "test6", GetTime() + " " + text); + + ws.textAll(json); + } + } +*/ +//=================================================================== +/* + "socket": [ + "ws://{{ip}}/ws" + ], +*/ +//=================================================================== +/* + { + "type": "h4", + "title": "('{{build2}}'=='{{firmware_version}}'?'NEW':'OLD')" + }, +*/ +//=================================================================== +/* + { + "type": "button", + "title": "Конфигурация устройства", + "socket": "test2", + "class": "btn btn-block btn-primary" + }, + { + "type": "hr" + }, + { + "type": "h6", + "title": "{{test1}}" + }, + { + "type": "h6", + "title": "{{test2}}" + }, + { + "type": "h6", + "title": "{{test3}}" + }, + { + "type": "h6", + "title": "{{test4}}" + }, + { + "type": "h6", + "title": "{{test5}}" + }, + { + "type": "h6", + "title": "{{test6}}" + }, + { + "type": "hr" + }, +*/ +//=================================================================== + +/* + String getResetReason(uint8_t core) { + int reason = rtc_get_reset_reason(core); + switch (reason) { + case 1 : return "Power on"; break; //Vbat power on reset + case 3 : return "Software reset digital core"; break; //Software reset digital core + case 4 : return "Legacy watch dog reset digital core"; break; //Legacy watch dog reset digital core + case 5 : return "Deep Sleep reset digital core"; break; //Deep Sleep reset digital core + case 6 : return "Reset by SLC module, reset digital core"; break; //Reset by SLC module, reset digital core + case 7 : return "Timer Group0 Watch dog reset digital core"; break; //Timer Group0 Watch dog reset digital core + case 8 : return "Timer Group1 Watch dog reset digital core"; break; //Timer Group1 Watch dog reset digital core + case 9 : return "RTC Watch dog Reset digital core"; break; // + case 10 : return "Instrusion tested to reset CPU"; break; + case 11 : return "Time Group reset CPU"; break; + case 12 : return "Software reset CPU"; break; + case 13 : return "RTC Watch dog Reset CPU"; break; + case 14 : return "for APP CPU, reseted by PRO CPU"; break; + case 15 : return "Reset when the vdd voltage is not stable"; break; + case 16 : return "RTC Watch dog reset digital core and rtc module"; break; + default : return "NO_MEAN"; + } + } + + + String EspClass::getResetReason(void) { + char buff[32]; + if (resetInfo.reason == REASON_DEFAULT_RST) { // normal startup by power on + strcpy_P(buff, PSTR("Power on")); + } else if (resetInfo.reason == REASON_WDT_RST) { // hardware watch dog reset + strcpy_P(buff, PSTR("Hardware Watchdog")); + } else if (resetInfo.reason == REASON_EXCEPTION_RST) { // exception reset, GPIO status won’t change + strcpy_P(buff, PSTR("Exception")); + } else if (resetInfo.reason == REASON_SOFT_WDT_RST) { // software watch dog reset, GPIO status won’t change + strcpy_P(buff, PSTR("Software Watchdog")); + } else if (resetInfo.reason == REASON_SOFT_RESTART) { // software restart ,system_restart , GPIO status won’t change + strcpy_P(buff, PSTR("Software/System restart")); + } else if (resetInfo.reason == REASON_DEEP_SLEEP_AWAKE) { // wake up from deep-sleep + strcpy_P(buff, PSTR("Deep-Sleep Wake")); + } else if (resetInfo.reason == REASON_EXT_SYS_RST) { // external system reset + strcpy_P(buff, PSTR("External System")); + } else { + strcpy_P(buff, PSTR("Unknown")); + } + return String(buff); + } +*/ diff --git a/udp.ino b/src/udp.cpp similarity index 100% rename from udp.ino rename to src/udp.cpp diff --git a/sync.ffs_db b/sync.ffs_db deleted file mode 100644 index d62dff32..00000000 Binary files a/sync.ffs_db and /dev/null differ diff --git a/test/README b/test/README new file mode 100644 index 00000000..df5066e6 --- /dev/null +++ b/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PIO Unit Testing and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PIO Unit Testing: +- https://docs.platformio.org/page/plus/unit-testing.html