first working version

This commit is contained in:
Dmitry Borisenko
2019-12-24 11:53:26 +03:00
parent af4715c895
commit 0c6cb1719f
101 changed files with 5567 additions and 0 deletions

505
Cmd.ino Normal file
View File

@@ -0,0 +1,505 @@
void CMD_init() {
sCmd.addCommand("button", button);
sCmd.addCommand("buttonSet", buttonSet);
sCmd.addCommand("pinSet", pinSet);
sCmd.addCommand("pwm", pwm);
sCmd.addCommand("pwmSet", pwmSet);
sCmd.addCommand("switch", switch_);
sCmd.addCommand("analog", analog);
sCmd.addCommand("ph", ph);
sCmd.addCommand("level", level);
sCmd.addCommand("dallas", dallas);
sCmd.addCommand("logging", logging);
sCmd.addCommand("input", input);
sCmd.addCommand("valueUpSet", valueUpSet);
sCmd.addCommand("valueDownSet", valueDownSet);
sCmd.addCommand("text", text);
sCmd.addCommand("textSet", textSet);
// sCmd.addCommand("time", time);
// sCmd.addCommand("timeSet", timeSet);
sCmd.addCommand("timerStart", timerStart);
sCmd.addCommand("timerStop", timerStop);
sCmd.addCommand("mqtt", mqttOrderSend);
sCmd.addCommand("http", httpOrderSend);
//!sCmd.addCommand("push", pushControl);
//handleCMD_ticker();
}
//==========================================================================================================
//==========================================Модуль кнопок===================================================
void button() {
String button_number = sCmd.next();
String button_param = sCmd.next();
String viget_name = sCmd.next();
String page_name = sCmd.next();
String start_state = sCmd.next();
String page_number = sCmd.next();
jsonWrite(optionJson, "button_param" + button_number, button_param);
jsonWrite(configJson, "buttonSet" + button_number, start_state);
if (isDigitStr (button_param)) {
pinMode(button_param.toInt(), OUTPUT);
digitalWrite(button_param.toInt(), start_state.toInt());
}
if (button_param == "scenario") {
jsonWrite(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, ",");
}
}
createViget (viget_name, page_name, page_number, "vigets/viget.toggle.json", "buttonSet" + button_number);
}
void buttonSet() {
String button_number = sCmd.next();
String button_state = sCmd.next();
String button_param = jsonRead(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") {
jsonWrite(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 ("buttonSet", button_number);
jsonWrite(configJson, "buttonSet" + button_number, button_state);
sendSTATUS("buttonSet" + button_number, button_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 pwm() {
static boolean flag = true;
String pwm_number = sCmd.next();
String pwm_pin = sCmd.next();
String viget_name = sCmd.next();
viget_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();
jsonWrite(optionJson, "pwm_pin" + pwm_number, pwm_pin);
pinMode(pwm_pin_int, INPUT);
analogWrite(pwm_pin_int, start_state.toInt());
jsonWrite(configJson, "pwmSet" + pwm_number, start_state);
createViget (viget_name, page_name, page_number, "vigets/viget.range.json", "pwmSet" + pwm_number);
}
void pwmSet() {
String pwm_number = sCmd.next();
String pwm_state = sCmd.next();
int pwm_state_int = pwm_state.toInt();
int pin = jsonReadtoInt(optionJson, "pwm_pin" + pwm_number);
analogWrite(pin, pwm_state_int);
eventGen ("pwmSet", pwm_number);
jsonWrite(configJson, "pwmSet" + pwm_number, pwm_state);
sendSTATUS("pwmSet" + 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 ("switchSet", String(switch_number));
jsonWrite(configJson, "switchSet" + String(switch_number), "1");
}
if (buttons[switch_number].rose()) {
eventGen ("switchSet", String(switch_number));
jsonWrite(configJson, "switchSet" + String(switch_number), "0");
}
}
switch_number++;
if (switch_number == NUM_BUTTONS) switch_number = 0;
}
//=====================================================================================================================================
//=========================================Добавление окна ввода переменной============================================================
void input() {
String name_ = sCmd.next();
String number = name_.substring(5);
String start_value = sCmd.next();
String step_ = sCmd.next();
String value_name = sCmd.next();
String page_name = sCmd.next();
String page_number = sCmd.next();
int psn1 = start_value.indexOf("."); //ищем позицию запятой
int digits = 0;
if (psn1 != -1) { //если она есть
String last_part = deleteBeforeDelimiter(start_value, ".");
digits = last_part.length() + 1;
}
createViget ("", page_name, page_number, "vigets/viget.button.json", "valueDownSet" + number, "title", "-");
createViget (value_name, page_name, String(page_number.toInt() + 1), "vigets/viget.alertbg.json", name_);
createViget ("", page_name, String(page_number.toInt() + 2), "vigets/viget.button.json", "valueUpSet" + number , "title", "+");
//jsonWrite(valuesJson, name_, start_value);
//saveValues ();
sendSTATUS(name_, start_value);
jsonWrite(configJson, name_ + "step", step_);
jsonWrite(configJson, name_ + "digits", digits);
}
void valueUpSet() {
String number = sCmd.next();
float val = jsonRead(configJson, "value" + number).toFloat();
float step_ = jsonRead(configJson, "value" + number + "step").toFloat();
int digits = jsonRead(configJson, "value" + number + "digits").toInt();
val = val + step_;
String val_str = String(val);
val_str = selectToMarkerPlus (val_str, ".", digits);
jsonWrite(configJson, "value" + number, val_str);
//jsonWrite(valuesJson, "value" + number, val_str);
//saveValues ();
sendSTATUS("value" + number, val_str);
}
void valueDownSet() {
String number = sCmd.next();
float val = jsonRead(configJson, "value" + number).toFloat();
float step_ = jsonRead(configJson, "value" + number + "step").toFloat();
int digits = jsonRead(configJson, "value" + number + "digits").toInt();
val = val - step_;
String val_str = String(val);
val_str = selectToMarkerPlus (val_str, ".", digits);
jsonWrite(configJson, "value" + number, val_str);
//jsonWrite(valuesJson, "value" + number, val_str);
//saveValues ();
sendSTATUS("value" + number, val_str);
}
//=====================================================================================================================================
//=========================================Добавление текстового виджета============================================================
void text() {
String number = sCmd.next();
String viget_name = sCmd.next();
String page_name = sCmd.next();
String page_number = sCmd.next();
createViget (viget_name, page_name, page_number, "vigets/viget.alertsm.json", "textSet" + number);
}
void textSet() {
String number = sCmd.next();
String text = sCmd.next();
text.replace("_", " ");
if (text.indexOf("-time") >= 0) {
text.replace("-time", "");
String time = GetTime();
time.replace(":", ".");
text = GetDataDigital() + " " + time + " " + text;
}
jsonWrite(configJson, "textSet" + number, text);
sendSTATUS("textSet" + number, text);
}
//=================================================Глобальные команды удаленного управления===========================================================
void mqttOrderSend() {
String id = sCmd.next();
String order = sCmd.next();
String all_line = prefix + "/" + id + "/order";
//Serial.print(all_line);
//Serial.print("->");
//Serial.println(order);
int send_status = client.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);
}
//==============================================================================================================================
//============================выполнение команд (в лупе) по очереди из строки 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, ","); //осекаем выполненную команду
}
}
//=============================выполнение команд (через период) по очереди из строки order=======================================
/*void handleCMD_ticker() {
ts.add(CMD, CMD_update_int, [&](void*) {
if (!busy) {
if (order_ticker != "") {
String tmp = selectToMarker(order_ticker, ","); //выделяем из страки order первую команду pus title body
if (tmp != "no_command") sCmd.readStr(tmp); //выполняем первую команду
Serial.println("order_ticker => " + order_ticker);
order_ticker = deleteBeforeDelimiter(order_ticker, ","); //осекаем выполненную команду
}
}
}, nullptr, true);
}*/
//=======================================================================================================================================
//=======================================================================================================================================
void txtExecution(String file) {
String command_all = readFile(file, 2048) + "\r\n"; //2048
command_all.replace("\r\n", "\n");
command_all.replace("\r", "\n");
while (command_all.length() != 0) {
String tmp = selectToMarker (command_all, "\n");
//if (tmp.indexOf("//") < 0)
sCmd.readStr(tmp);
command_all = deleteBeforeDelimiter(command_all, "\n");
}
}
void stringExecution(String str) {
String command_all = str + "\r\n"; //"\r\n"
command_all.replace("\r\n", "\n");
command_all.replace("\r", "\n");
while (command_all.length() != 0) {
String tmp = selectToMarker (command_all, "\n");
//if (tmp.indexOf("//") < 0)
sCmd.readStr(tmp);
command_all = deleteBeforeDelimiter(command_all, "\n");
}
}
//======================================================================================================================
//===============================================Создание виджетов=======================================================
void createViget (String viget_name, String page_name, String page_number, String file, String topic) {
String viget;
viget = readFile(file, 1024);
if (viget == "Failed") return;
if (viget == "Large") return;
viget_name.replace("#", " ");
page_name.replace("#", " ");
jsonWrite(viget, "page", page_name);
jsonWrite(viget, "pageId", page_number);
jsonWrite(viget, "descr", viget_name);
jsonWrite(viget, "topic", prex + "/" + topic);
all_vigets += viget + "\r\n";
viget = "";
}
void createViget (String viget_name, String page_name, String page_number, String file, String topic, String key, String value) {
String viget;
viget = readFile(file, 1024);
if (viget == "Failed") return;
if (viget == "Large") return;
viget_name.replace("#", " ");
page_name.replace("#", " ");
value.replace("#", " ");
viget = vidgetConfigWrite(viget, key, value);
jsonWrite(viget, "page", page_name);
jsonWrite(viget, "pageId", page_number);
jsonWrite(viget, "descr", viget_name);
jsonWrite(viget, "topic", prex + "/" + topic);
all_vigets += viget + "\r\n";
viget = "";
}
void createViget (String viget_name, String page_name, String page_number, String file, String topic, String key, String value, String key2, String value2) {
String viget;
viget = readFile(file, 1024);
if (viget == "Failed") return;
if (viget == "Large") return;
viget_name.replace("#", " ");
page_name.replace("#", " ");
value.replace("#", " ");
viget = vidgetConfigWrite(viget, key, value);
viget = vidgetConfigWrite(viget, key2, value2);
jsonWrite(viget, "page", page_name);
jsonWrite(viget, "pageId", page_number);
jsonWrite(viget, "descr", viget_name);
jsonWrite(viget, "topic", prex + "/" + topic);
all_vigets += viget + "\r\n";
viget = "";
}
String vidgetConfigWrite(String viget, String key, String value) {
if (viget == "") return "";
if (viget == "{}") return "";
int psn1 = viget.indexOf("{");
if (psn1 != -1) {
psn1 = viget.indexOf("{", psn1 + 1);
if (psn1 != -1) {
int psn2 = viget.indexOf("}", psn1);
String WigetConfig = viget.substring(psn1, psn2) + "}";
jsonWrite(WigetConfig, key, value);
String part1 = viget.substring(0, psn1);
viget = part1 + WigetConfig + "}";
return viget;
}
}
}
//============разное
/*
void delAlert() {
String alert_id = sCmd.next();
delViget(alert_id);
sendAllWigets();
}
void delViget(String text_in_viget) {
String viget = all_vigets;
while (viget.length() != 0) {
String tmp = selectToMarkerPlus (viget, "\r\n", 2);
if (tmp.indexOf(text_in_viget) > 0) {
all_vigets.replace(tmp, "");
//Serial.println(all_vigets);
viget = deleteBeforeDelimiter(viget, "\r\n");
} else {
viget = deleteBeforeDelimiter(viget, "\r\n");
}
}
}
*/

50
Init.ino Normal file
View File

@@ -0,0 +1,50 @@
void All_init() {
server.on("/all_modules_init", HTTP_GET, [](AsyncWebServerRequest * request) {
Device_init();
request->send(200, "text/text", "OK"); // отправляем ответ о выполнении
});
server.on("/scenario", HTTP_GET, [](AsyncWebServerRequest * request) {
if (request->hasArg("status")) {
jsonWrite(configSetup, "scenario", request->getParam("status")->value());
}
saveConfig();
Scenario_init();
request->send(200, "text/text", "OK"); // отправляем ответ о выполнении
});
server.on("/cleanlog", HTTP_GET, [](AsyncWebServerRequest * request) {
SPIFFS.remove("/log.analog.txt");
SPIFFS.remove("/log.dallas.txt");
SPIFFS.remove("/log.level.txt");
SPIFFS.remove("/log.ph.txt");
SPIFFS.remove("/log.txt");
request->send(200, "text/text", "OK"); // отправляем ответ о выполнении
});
Device_init();
Scenario_init();
Timer_countdown_init();
}
void Device_init() {
ts.remove(LEVEL);
ts.remove(ANALOG_);
ts.remove(PH);
ts.remove(DALLAS);
all_vigets = "";
txtExecution("config.all.txt");
//outcoming_date();
}
//-------------------------------сценарии-----------------------------------------------------
void Scenario_init() {
if (jsonRead(configSetup, "scenario") == "1") {
scenario = readFile(scenarioFileNameS, 2048);
}
}

85
Scenario.ino Normal file
View File

@@ -0,0 +1,85 @@
void handleScenario() {
if (jsonRead(configSetup, "scenario") == "1") {
if ((jsonRead(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); //из первой страки берем имя параметра button1 и вставляем в него Set и получаем buttonSet1
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;
}
} //преобразуем из button1 в вид buttonSet1 ,param_name = buttonSet1
String order = jsonRead(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("value") != -1) {
value = jsonRead(configJson, value);
}
boolean flag = false; //если одно из значений совпало то только тогда начинаем выполнять комнады
if (sign == "=") {
if (jsonRead(configJson, param_name) == value) flag = true;
}
if (sign == "!=") {
if (jsonRead(configJson, param_name) != value) flag = true;
}
if (sign == "<") {
if (jsonRead(configJson, param_name).toFloat() < value.toFloat()) flag = true;
}
if (sign == ">") {
if (jsonRead(configJson, param_name).toFloat() > value.toFloat()) flag = true;
}
if (sign == ">=") {
if (jsonRead(configJson, param_name).toFloat() >= value.toFloat()) flag = true;
}
if (sign == "<=") {
if (jsonRead(configJson, param_name).toFloat() <= value.toFloat()) flag = true;
}
if (flag) {
tmp = deleteBeforeDelimiter(tmp, "\n"); //удаляем строку самого сценария оставляя только команды
stringExecution(tmp); //выполняем все команды
Serial.println("[SCENARIO] '" + condition + "'");
//Serial.println(" " + tmp);
}
}
}
str = deleteBeforeDelimiter(str, "end\n"); //удаляем первый сценарий
//-----------------------------------------------------------------------------------------------------------------------
}
String tmp2 = jsonRead(optionJson, "scenario_status"); //читаем файл событий
tmp2 = deleteBeforeDelimiter(tmp2, ","); //удаляем выполненное событие
jsonWrite(optionJson, "scenario_status", tmp2); //записываем обновленный файл событий
i = 0;
}
}
}
void eventGen (String event_name, String number) { //событие выглядит как имя плюс set плюс номер: button+Set+1
if (jsonRead(configSetup, "scenario") == "1") {
String tmp = jsonRead(optionJson, "scenario_status") ; //генерирование события
//Serial.println(event_name);
jsonWrite(optionJson, "scenario_status", tmp + event_name + number + ",");
}
}

315
Sensors.ino Normal file
View File

@@ -0,0 +1,315 @@
//===============================================================================================================================
//=========================================Модуль аналогового сенсора============================================================
void analog() {
static boolean flag = true;
String viget_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();
jsonWrite(optionJson, "analog_start", analog_start);
jsonWrite(optionJson, "analog_end", analog_end);
jsonWrite(optionJson, "analog_start_out", analog_start_out);
jsonWrite(optionJson, "analog_end_out", analog_end_out);
if (type == "text") createViget (viget_name, page_name, page_number, "vigets/viget.alertsm.json", "analog");
if (type == "gauge") createViget (viget_name, page_name, page_number, "vigets/viget.fillgauge.json", "analog");
if (type == "gauge2") createViget (viget_name, page_name, page_number, "vigets/viget.gauge.json", "analog", "maximum", analog_end_out);
if (type == "termometr") createViget (viget_name, page_name, page_number, "vigets/viget.termometr.json", "analog", "titleString", viget_name);
ts.add(ANALOG_, analog_update_int, [&](void*) {
static int analog_old;
int analog_in = analogRead(35);
jsonWrite(configJson, "analog_in", analog_in);
int analog = map(analog_in,
jsonReadtoInt(optionJson, "analog_start") ,
jsonReadtoInt(optionJson, "analog_end"),
jsonReadtoInt(optionJson, "analog_start_out"),
jsonReadtoInt(optionJson, "analog_end_out"));
jsonWrite(configJson, "analog", analog);
// if (analog_old != analog) {
eventGen ("analog", "");
sendSTATUS("analog", String(analog));
if (client.connected()) {
Serial.println("[i] sensor analog send date " + String(analog));
}
// }
analog_old = analog;
}, nullptr, true);
}
//===============================================================================================================================
//=========================================Модуль аналогового сенсора============================================================
void ph() {
String viget_name = sCmd.next();
String page_name = sCmd.next();
String type = sCmd.next();
String offset = sCmd.next();
String page_number = sCmd.next();
jsonWrite(optionJson, "ph_offset", offset);
if (type == "text") createViget (viget_name, page_name, page_number, "vigets/viget.alertsm.json", "ph");
if (type == "gauge") createViget (viget_name, page_name, page_number, "vigets/viget.fillgauge.json", "ph");
if (type == "gauge2") createViget (viget_name, page_name, page_number, "vigets/viget.gauge.json", "ph");
if (type == "termometr") createViget (viget_name, page_name, page_number, "vigets/viget.termometr.json", "ph", "titleString", viget_name);
ts.add(PH, ph_shooting_interval, [&](void*) {
static float pHValue_old;
static int counter;
float offset = jsonRead(optionJson, "ph_offset").toFloat();
int analog = analogRead(A0);
analog = medianFilter.filtered(analog);
float voltage = analog * 3.2 / 1024;
float pHValue = 3.5 * voltage + offset;
String pHValue_str = String(pHValue);
pHValue_str = selectToMarkerPlus(pHValue_str, "." , 2);
counter++;
if (counter > ph_times_to_send) {
counter = 0;
jsonWrite(configJson, "ph", pHValue_str);
//if (pHValue_old != pHValue) {
eventGen ("ph", "");
sendSTATUS("ph", pHValue_str);
if (client.connected()) {
Serial.println("[i] sensor ph send date " + pHValue_str);
Serial.println("voltage " + String(voltage));
}
//}
pHValue_old = pHValue;
}
}, nullptr, true);
}
//===================================================================================================================================
//=========================================Модуль измерения уровня в баке============================================================
void level() {
static boolean flag = true;
String viget_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();
jsonWrite(optionJson, "empty_level", empty_level);
jsonWrite(optionJson, "full_level", full_level);
pinMode(14, OUTPUT);
pinMode(12, INPUT);
if (type == "text") createViget (viget_name, page_name, page_number, "vigets/viget.alertsm.json", "level");
if (type == "gauge") createViget (viget_name, page_name, page_number, "vigets/viget.fillgauge.json", "level");
if (type == "gauge2") createViget (viget_name, page_name, page_number, "vigets/viget.gauge.json", "level", "maximum", "100");
if (type == "termometr") createViget (viget_name, page_name, page_number, "vigets/viget.termometr.json", "level", "titleString", viget_name);
ts.add(LEVEL, tank_level_shooting_interval, [&](void*) {
long duration_;
int distance_cm;
int level;
static int level_old; //переменная static сохраняет свое значение между вызовами функции
static int counter;
digitalWrite(14, LOW);
delayMicroseconds(2);
digitalWrite(14, HIGH);
delayMicroseconds(10);
digitalWrite(14, LOW);
duration_ = pulseIn(12, 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;
jsonWrite(configJson, "level_in", distance_cm);
level = map(distance_cm,
jsonReadtoInt(optionJson, "empty_level"),
jsonReadtoInt(optionJson, "full_level"), 0, 100);
//jsonWrite(configJson, "level", level);
//if (level_old != level) {
eventGen ("level", "");
sendSTATUS("level", String(level));
if (client.connected()) {
Serial.println("[i] sensor tank level send date " + String(level));
}
//}
level_old = level;
}
}, nullptr, true);
}
//==========================================================================================================================================
//=========================================Модуль температурного сенсора ds18b20============================================================
void dallas() {
static boolean flag = true;
String pin = sCmd.next();
String viget_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);
if (type == "text") createViget (viget_name, page_name, page_number, "vigets/viget.alertsm.json", "dallas");
if (type == "gauge") createViget (viget_name, page_name, page_number, "vigets/viget.fillgauge.json", "dallas");
if (type == "gauge2") createViget (viget_name, page_name, page_number, "vigets/viget.gauge.json", "dallas");
if (type == "termometr") createViget (viget_name, page_name, page_number, "vigets/viget.termometr.json", "dallas", "titleString", viget_name);
ts.add(DALLAS, temp_update_int, [&](void*) {
float temp = 0;
static float temp_old;
sensors.requestTemperatures();
temp = sensors.getTempCByIndex(0);
jsonWrite(configJson, "dallas", String(temp));
//if (temp_old != temp) {
eventGen ("dallas", "");
sendSTATUS("dallas", String(temp));
if (client.connected()) {
Serial.println("[i] sensor dallas send date " + String(temp));
}
//}
temp_old = temp;
}, nullptr, true);
}
//======================================================================================================================
//===============================================Логирование============================================================
void logging() {
static boolean flag = true;
String sensor_name = sCmd.next();
String period_min = sCmd.next();
String maxCount = sCmd.next();
String viget_name = sCmd.next();
viget_name.replace("#", " ");
String page_name = sCmd.next();
String page_number = sCmd.next();
if (sensor_name == "analog") jsonWrite(optionJson, "analog_logging_count", maxCount);
if (sensor_name == "level") jsonWrite(optionJson, "level_logging_count", maxCount);
if (sensor_name == "dallas") jsonWrite(optionJson, "dallas_logging_count", maxCount);
if (sensor_name == "ph") jsonWrite(optionJson, "ph_logging_count", maxCount);
if (sensor_name == "analog") createViget (viget_name, page_name, page_number, "vigets/viget.chart.json", "loganalog", "maxCount", maxCount);
if (sensor_name == "level") createViget (viget_name, page_name, page_number, "vigets/viget.chart.json", "loglevel", "maxCount", maxCount);
if (sensor_name == "dallas") createViget (viget_name, page_name, page_number, "vigets/viget.chart.json", "logdallas", "maxCount", maxCount);
if (sensor_name == "ph") createViget (viget_name, page_name, page_number, "vigets/viget.chart.json", "logph", "maxCount", maxCount);
if (sensor_name == "analog") {
flagLoggingAnalog = true;
ts.remove(ANALOG_LOG);
ts.add(ANALOG_LOG, period_min.toInt() * 1000 * 60, [&](void*) {
deleteOldDate("log.analog.txt", jsonReadtoInt(optionJson, "analog_logging_count"), jsonRead(configJson, "analog"), false);
}, nullptr, true);
}
if (sensor_name == "level") {
flagLoggingLevel = true;
ts.remove(LEVEL_LOG);
ts.add(LEVEL_LOG, period_min.toInt() * 1000 * 60, [&](void*) {
deleteOldDate("log.level.txt", jsonReadtoInt(optionJson, "level_logging_count"), jsonRead(configJson, "level"), false);
}, nullptr, true);
}
if (sensor_name == "dallas") {
flagLoggingDallas = true;
ts.remove(DALLAS_LOG);
ts.add(DALLAS_LOG, period_min.toInt() * 1000 * 60, [&](void*) {
deleteOldDate("log.dallas.txt", jsonReadtoInt(optionJson, "dallas_logging_count"), jsonRead(configJson, "dallas"), false);
}, nullptr, true);
}
if (sensor_name == "ph") {
flagLoggingPh = true;
ts.remove(PH_LOG);
ts.add(PH_LOG, period_min.toInt() * 1000 * 60, [&](void*) {
deleteOldDate("log.ph.txt", jsonReadtoInt(optionJson, "ph_logging_count"), jsonRead(configJson, "ph"), false);
}, nullptr, true);
}
}
void deleteOldDate(String file, int seted_number_of_lines, String date_to_add, boolean date_time) {
String current_time;
if (date_time) {
current_time = GetDataDigital() + " " + GetTimeWOsec();
current_time.replace(".", "");
current_time.replace(":", "");
} else {
current_time = "";
}
String log_date = readFile(file, 5000);
getMemoryLoad("[i] after logging procedure");
//предел количества строк 255
log_date.replace("\r\n", "\n");
log_date.replace("\r", "\n");
int current_number_of_lines = count(log_date, "\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, "\n");
log_date += current_time + " " + date_to_add + "\n";
writeFile(file, log_date);
} else {
if (date_time) {
addFile(file, current_time + " " + date_to_add);
} else {
addFile(file, date_to_add);
}
}
}

20
Time_esp32.ino Normal file
View File

@@ -0,0 +1,20 @@
#ifdef ESP32
void Time_Init() {
//init and get the time
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
printLocalTime();
}
void printLocalTime() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("[E] Failed to obtain time");
return;
}
Serial.println(&timeinfo, "[V] %A, %B %d %Y %H:%M:%S");
}
#endif

112
Time_esp8266.ino Normal file
View File

@@ -0,0 +1,112 @@
#ifdef ESP8266
#include <time.h>
void Time_Init() {
server.on("/Time", HTTP_GET, [](AsyncWebServerRequest * request) {
//handle_Time();
request->send(200, "text/text", "OK"); // отправляем ответ о выполнении
});
server.on("/timeZone", HTTP_GET, [](AsyncWebServerRequest * request) {
//handle_time_zone();
request->send(200, "text/text", "OK"); // отправляем ответ о выполнении
});
timeSynch(jsonReadtoInt(configSetup, "timezone"));
}
void timeSynch(int zone) {
if (WiFi.status() == WL_CONNECTED) {
// Настройка соединения с NTP сервером
configTime(zone * 3600, 0, "pool.ntp.org", "ru.pool.ntp.org");
// int i = 0;
// Serial.println("\nWaiting for time");
// while (!time(nullptr) && i < 10) {
// Serial.print(".");
// i++;
// delay(1000);
// }
Serial.println("");
Serial.println("ITime Ready!");
delay(1000);
Serial.println(GetTime());
Serial.println(GetDate());
}
}
/*// Установка параметров времянной зоны по запросу вида http://192.168.0.101/timeZone?timeZone=3
void handle_time_zone() {
if (request->hasArg("timeZone")) {
jsonWrite(configSetup, "timeZone", request->getParam("timeZone")->value());
}
saveConfig();
//request->send(200, "text/text", "OK");
}
void handle_Time() {
timeSynch(jsonReadtoInt(configSetup, "timezone"));
//request->send(200, "text/text", "OK");
}
*/
#endif
// Получение текущего времени
String GetTime() {
time_t now = time(nullptr); // получаем время с помощью библиотеки time.h
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
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
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;
}

184
Timers.ino Normal file
View File

@@ -0,0 +1,184 @@
//================================================================================================================
//=========================================Таймера=================================================================
void Timer_countdown_init() {
ts.add(TIMER_COUNTDOWN, 1000, [&](void*) {
String old_line = jsonRead(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));
jsonWrite(configJson, "timerSet" + String(number), "0");
eventGen ("timerSet", 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("value") != -1) {
period_of_time = jsonRead(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);
jsonWrite(configJson, "timerSet" + number, "1");
}
void addTimer(String number, String time) {
String tmp = jsonRead(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 + ",";
}
jsonWrite(optionJson, "timers", tmp);
//Serial.println("ura");
}
void timerStop() {
String number = sCmd.next();
delTimer(number);
}
void delTimer (String number) {
String tmp = jsonRead(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, ""); //удаляем таймер
jsonWrite(optionJson, "timers", tmp);
}
}
int readTimer(int number) {
String tmp = jsonRead(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();
}
/*void timer() {
String seted_time = sCmd.next();
String order = sCmd.next();
order.replace("_", " ");
if (seted_time == current_time) {
order_loop += order + ",";
}
}*/
//------------------------------таймеры------------------------------------------------------
void time() {
String time_number = sCmd.next();
String time = sCmd.next();
String time_to_add = time_number + "-" + time;
String replace_line = jsonRead(optionJson, "times") ;
int psn1 = replace_line.indexOf(time_number + "-") ; //ищем позицию времени которое надо заменить
if (psn1 != -1) { //если оно есть
int psn2 = replace_line.indexOf(",", psn1); //от этой позиции находим позицию запятой
String timer = replace_line.substring(psn1, psn2); //выделяем таймер который надо заменить
///tmp.replace(timer, new_timer); //заменяем таймер на новый (во всей стороке)
replace_line.replace(timer + ",", "");
replace_line += time_to_add + ",";
} else { //если его нет
replace_line += time_to_add + ",";
}
jsonWrite(optionJson, "times", replace_line);
jsonWrite(configJson, "timeSet" + time_number, "1");
ts.add(TIMERS, 1000, [&](void*) {
current_time = GetTime();
Serial.println(current_time);
String seted_times = jsonRead(optionJson, "times");
while (seted_times.length() != 0) {
String tmp = selectToMarker (seted_times, ",");
String time_number = selectToMarker(tmp, "-");
String seted_time = deleteBeforeDelimiter(tmp, "-");
Serial.println(seted_time);
if (current_time == seted_time) {
jsonWrite(configJson, "timeSet" + time_number, "0");
eventGen ("timeSet", time_number);
}
seted_times = deleteBeforeDelimiter(seted_times, ",");
}
}, nullptr, true);
}

222
Web_server.ino Normal file
View File

@@ -0,0 +1,222 @@
void Web_server_init() {
//========================================OTA============================================
#ifdef OTA_enable
//Send OTA events to the browser
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, http_username, http_password));
#elif defined(ESP8266)
server.addHandler(new SPIFFSEditor(http_username, http_password));
#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("/", SPIFFS, "/favicon.ico").setCacheControl("max-age=31536000");
server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.htm")
.setAuthentication(http_username, http_password);
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);
});
}
//========================================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(configJson.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
//===================================================================================================================================

188
WiFi.ino Normal file
View File

@@ -0,0 +1,188 @@
void WIFI_init() {
// --------------------Получаем ssid password со страницы
server.on("/ssid", HTTP_GET, [](AsyncWebServerRequest * request) {
if (request->hasArg("ssid")) {
jsonWrite(configSetup, "ssid", request->getParam("ssid")->value());
}
if (request->hasArg("password")) {
jsonWrite(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")) {
jsonWrite(configSetup, "ssidAP", request->getParam("ssidAP")->value());
}
if (request->hasArg("passwordAP")) {
jsonWrite(configSetup, "passwordAP", request->getParam("passwordAP")->value());
}
saveConfig(); // Функция сохранения данных во Flash
request->send(200, "text/text", "OK"); // отправляем ответ о выполнении
});
// Попытка подключения к точке доступа
WiFi.mode(WIFI_STA);
byte tries = 20;
String _ssid = jsonRead(configSetup, "ssid");
String _password = jsonRead(configSetup, "password");
//WiFi.persistent(false);
if (_ssid == "" && _password == "") {
WiFi.begin();
}
else {
WiFi.begin(_ssid.c_str(), _password.c_str());
}
// Делаем проверку подключения до тех пор пока счетчик tries
// не станет равен нулю или не получим подключение
while (--tries && WiFi.status() != WL_CONNECTED)
{
if (WiFi.status() == WL_CONNECT_FAILED) {
Serial.println("[E] password is not correct");
tries = 1;
jsonWrite(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.println("[V] IP address: ");
Serial.println(WiFi.localIP());
jsonWrite(configJson, "ip", WiFi.localIP().toString());
}
}
bool StartAPMode() {
/*
Serial.println("WiFi up AP");
IPAddress apIP(192, 168, 4, 1);
IPAddress staticGateway(192, 168, 4, 1);
IPAddress staticSubnet(255, 255, 255, 0);
WiFi.disconnect();
WiFi.mode(WIFI_AP);
WiFi.softAPConfig(apIP, staticGateway, staticSubnet);
String _ssidAP = jsonRead(configSetup, "ssidAP");
String _passwordAP = jsonRead(configSetup, "passwordAP");
WiFi.softAP(_ssidAP.c_str(), _passwordAP.c_str());
jsonWrite(configJson, "ip", apIP.toString());
*/
Serial.println("WiFi up AP");
WiFi.disconnect();
WiFi.mode(WIFI_AP);
String _ssidAP = jsonRead(configSetup, "ssidAP");
String _passwordAP = jsonRead(configSetup, "passwordAP");
WiFi.softAP(_ssidAP.c_str(), _passwordAP.c_str());
IPAddress myIP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(myIP);
if (jsonReadtoInt(optionJson, "pass_status") != 1) {
ts.add(ROUTER_SEARCHING, 30 * 1000, [&](void*) {
Serial.println("->try find router");
if (RouterFind(jsonRead(configSetup, "ssid"))) {
ts.remove(ROUTER_SEARCHING);
WIFI_init();
MQTT_init();
}
}, nullptr, true);
}
return true;
}
boolean RouterFind(String ssid) {
int n = WiFi.scanComplete ();
if (n == -2) { //Сканирование не было запущено, запускаем
WiFi.scanNetworks (true, false); //async, show_hidden
return false;
}
if (n == -1) { //Сканирование все еще выполняется
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("<=>");
Serial.println(WiFi.SSID(i));
}
}
WiFi.scanDelete();
return false;
}
}
/*
boolean RouterFind(String ssid) {
int n = WiFi.scanComplete();
Serial.print("status=");
Serial.println(n);
if (n == -2) { //Сканирование не было запущено, запускаем
Serial.println("->enter to scanning function");
WiFi.mode(WIFI_AP);
WiFi.scanNetworks (true, false, false, 5000); //async, show_hidden
Serial.println("->out of scanning function");
return false;
}
if (n == -1) { //Сканирование все еще выполняется
Serial.println("->scanning in progress");
return false;
}
if (n > 0) { //Найдено несколько сетей
for (int i = 0; i <= n; i++) {
if (WiFi.SSID(i) == ssid) {
Serial.println("router found");
WiFi.scanDelete();
return true;
} else {
Serial.print(i);
Serial.print(")");
Serial.print(ssid);
Serial.print("<=>");
Serial.println(WiFi.SSID(i));
}
}
WiFi.scanDelete();
Serial.println("->scanning deleted");
return false;
}
}
void wifi_reset() {
WiFi.mode(WIFI_STA);
WiFi.disconnect(true, true);
}
*/

72
certificates.ino Normal file
View File

@@ -0,0 +1,72 @@
/*
const char* local_root_ca1 = \
"-----BEGIN CERTIFICATE-----\n" \
"MIIFdDCCBFygAwIBAgIQJ2buVutJ846r13Ci/ITeIjANBgkqhkiG9w0BAQwFADBv\n" \
"MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk\n" \
"ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF\n" \
"eHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFow\n" \
"gYUxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO\n" \
"BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMSswKQYD\n" \
"VQQDEyJDT01PRE8gUlNBIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkq\n" \
"hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAkehUktIKVrGsDSTdxc9EZ3SZKzejfSNw\n" \
"AHG8U9/E+ioSj0t/EFa9n3Byt2F/yUsPF6c947AEYe7/EZfH9IY+Cvo+XPmT5jR6\n" \
"2RRr55yzhaCCenavcZDX7P0N+pxs+t+wgvQUfvm+xKYvT3+Zf7X8Z0NyvQwA1onr\n" \
"ayzT7Y+YHBSrfuXjbvzYqOSSJNpDa2K4Vf3qwbxstovzDo2a5JtsaZn4eEgwRdWt\n" \
"4Q08RWD8MpZRJ7xnw8outmvqRsfHIKCxH2XeSAi6pE6p8oNGN4Tr6MyBSENnTnIq\n" \
"m1y9TBsoilwie7SrmNnu4FGDwwlGTm0+mfqVF9p8M1dBPI1R7Qu2XK8sYxrfV8g/\n" \
"vOldxJuvRZnio1oktLqpVj3Pb6r/SVi+8Kj/9Lit6Tf7urj0Czr56ENCHonYhMsT\n" \
"8dm74YlguIwoVqwUHZwK53Hrzw7dPamWoUi9PPevtQ0iTMARgexWO/bTouJbt7IE\n" \
"IlKVgJNp6I5MZfGRAy1wdALqi2cVKWlSArvX31BqVUa/oKMoYX9w0MOiqiwhqkfO\n" \
"KJwGRXa/ghgntNWutMtQ5mv0TIZxMOmm3xaG4Nj/QN370EKIf6MzOi5cHkERgWPO\n" \
"GHFrK+ymircxXDpqR+DDeVnWIBqv8mqYqnK8V0rSS527EPywTEHl7R09XiidnMy/\n" \
"s1Hap0flhFMCAwEAAaOB9DCB8TAfBgNVHSMEGDAWgBStvZh6NLQm9/rEJlTvA73g\n" \
"JMtUGjAdBgNVHQ4EFgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQD\n" \
"AgGGMA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0gBAowCDAGBgRVHSAAMEQGA1UdHwQ9\n" \
"MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9BZGRUcnVzdEV4dGVy\n" \
"bmFsQ0FSb290LmNybDA1BggrBgEFBQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6\n" \
"Ly9vY3NwLnVzZXJ0cnVzdC5jb20wDQYJKoZIhvcNAQEMBQADggEBAGS/g/FfmoXQ\n" \
"zbihKVcN6Fr30ek+8nYEbvFScLsePP9NDXRqzIGCJdPDoCpdTPW6i6FtxFQJdcfj\n" \
"Jw5dhHk3QBN39bSsHNA7qxcS1u80GH4r6XnTq1dFDK8o+tDb5VCViLvfhVdpfZLY\n" \
"Uspzgb8c8+a4bmYRBbMelC1/kZWSWfFMzqORcUx8Rww7Cxn2obFshj5cqsQugsv5\n" \
"B5a6SE2Q8pTIqXOi6wZ7I53eovNNVZ96YUWYGGjHXkBrI/V5eu+MtWuLt29G9Hvx\n" \
"PUsE2JOAWVrgQSQdso8VYFhH2+9uRv0V9dlfmrPb2LjkQLPNlzmuhbsdjrzch5vR\n" \
"pu/xO28QOG8=\n" \
"-----END CERTIFICATE-----\n";
const char* local_root_ca2 = \
"-----BEGIN CERTIFICATE-----\n" \
"MIIGCDCCA/CgAwIBAgIQKy5u6tl1NmwUim7bo3yMBzANBgkqhkiG9w0BAQwFADCB\n" \
"hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G\n" \
"A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV\n" \
"BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTQwMjEy\n" \
"MDAwMDAwWhcNMjkwMjExMjM1OTU5WjCBkDELMAkGA1UEBhMCR0IxGzAZBgNVBAgT\n" \
"EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR\n" \
"Q09NT0RPIENBIExpbWl0ZWQxNjA0BgNVBAMTLUNPTU9ETyBSU0EgRG9tYWluIFZh\n" \
"bGlkYXRpb24gU2VjdXJlIFNlcnZlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP\n" \
"ADCCAQoCggEBAI7CAhnhoFmk6zg1jSz9AdDTScBkxwtiBUUWOqigwAwCfx3M28Sh\n" \
"bXcDow+G+eMGnD4LgYqbSRutA776S9uMIO3Vzl5ljj4Nr0zCsLdFXlIvNN5IJGS0\n" \
"Qa4Al/e+Z96e0HqnU4A7fK31llVvl0cKfIWLIpeNs4TgllfQcBhglo/uLQeTnaG6\n" \
"ytHNe+nEKpooIZFNb5JPJaXyejXdJtxGpdCsWTWM/06RQ1A/WZMebFEh7lgUq/51\n" \
"UHg+TLAchhP6a5i84DuUHoVS3AOTJBhuyydRReZw3iVDpA3hSqXttn7IzW3uLh0n\n" \
"c13cRTCAquOyQQuvvUSH2rnlG51/ruWFgqUCAwEAAaOCAWUwggFhMB8GA1UdIwQY\n" \
"MBaAFLuvfgI9+qbxPISOre44mOzZMjLUMB0GA1UdDgQWBBSQr2o6lFoL2JDqElZz\n" \
"30O0Oija5zAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNV\n" \
"HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGwYDVR0gBBQwEjAGBgRVHSAAMAgG\n" \
"BmeBDAECATBMBgNVHR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9kb2NhLmNv\n" \
"bS9DT01PRE9SU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBxBggrBgEFBQcB\n" \
"AQRlMGMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9E\n" \
"T1JTQUFkZFRydXN0Q0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21v\n" \
"ZG9jYS5jb20wDQYJKoZIhvcNAQEMBQADggIBAE4rdk+SHGI2ibp3wScF9BzWRJ2p\n" \
"mj6q1WZmAT7qSeaiNbz69t2Vjpk1mA42GHWx3d1Qcnyu3HeIzg/3kCDKo2cuH1Z/\n" \
"e+FE6kKVxF0NAVBGFfKBiVlsit2M8RKhjTpCipj4SzR7JzsItG8kO3KdY3RYPBps\n" \
"P0/HEZrIqPW1N+8QRcZs2eBelSaz662jue5/DJpmNXMyYE7l3YphLG5SEXdoltMY\n" \
"dVEVABt0iN3hxzgEQyjpFv3ZBdRdRydg1vs4O2xyopT4Qhrf7W8GjEXCBgCq5Ojc\n" \
"2bXhc3js9iPc0d1sjhqPpepUfJa3w/5Vjo1JXvxku88+vZbrac2/4EjxYoIQ5QxG\n" \
"V/Iz2tDIY+3GH5QFlkoakdH368+PUq4NCNk+qKBR6cGHdNXJ93SrLlP7u3r7l+L4\n" \
"HyaPs9Kg4DdbKDsx5Q5XLVq4rXmsXiBmGqW5prU5wfWYQ//u+aen/e7KJD2AFsQX\n" \
"j4rBYKEMrltDR5FL1ZoXX/nUh8HCjLfn4g8wGTeGrODcQgPmlKidrv0PJFGUzpII\n" \
"0fxQ8ANAe4hZ7Q7drNJ3gjTcBpUC2JD5Leo31Rpg0Gcg19hCC0Wvgmje3WYkN5Ap\n" \
"lBlGGSW4gNfL1IYoakRwJiNiqZ+Gb7+6kHDSVneFeO/qJakXzlByjAA6quPbYzSf\n" \
"+AZxAeKCINT+b72x\n" \
"-----END CERTIFICATE-----\n";
*/

2
data/.exclude.files Normal file
View File

@@ -0,0 +1,2 @@
/*.js.gz
/.exclude.files

BIN
data/ace.js.gz Normal file

Binary file not shown.

144
data/config.all.json Normal file
View File

@@ -0,0 +1,144 @@
{
"configs": [
"/config.live.json",
"/config.setup.json",
"/config.option.json"
],
"class":"col-sm-offset-1 col-sm-10",
"content": [
{
"type": "h5",
"title": "{{SSDP}}",
"class":"alert-warning"
},
{
"type": "h4",
"title": "Device ID: {{chipID}}"
},
{
"type": "h4",
"title": "IP address: {{ip}}"
},
{
"type": "hr"
},
{
"type": "h2",
"title": "Конфигурация устройства"
},
{
"type":"file",
"state":"config.all.txt",
"style":"width:100%;height:400px",
"title": "Сохранить",
"action": "/all_modules_init",
"class":"btn btn-block btn-success"
},
{
"type": "link",
"title": "Инструкция",
"action": "https://github.com/DmitryBorisenko33/esp8266_iot-manager_modules_firmware/wiki/Instruction",
"class": "btn btn-block btn-primary"
},
{
"type": "h2",
"title": "Сценарии"
},
{
"type": "checkbox",
"name":"scenario",
"title": "Включить сценарии",
"action": "/scenario?status=[[scenario]]",
"state": "{{scenario}}"
},
{
"type": "h6",
"title": ""
},
{
"type":"file",
"state":"scenario.all.txt",
"style":"width:100%;height:400px",
"title": "Сохранить и включить",
"action": "/scenario?status=1",
"class":"btn btn-block btn-success"
},
{
"type": "h2",
"title": "Данные модулей"
},
{
"type": "hr"
},
{
"type": "h4",
"title": "Модуль уровня воды (level)",
"style": "width:100%"
},
{
"type": "h6",
"title": "Расстояние от датчика до воды: {{level_in}} см"
},
{
"type": "h6",
"title": " Заполнение бака: {{level}} %"
},
{
"type": "hr"
},
{
"type": "h4",
"title": "Модуль аналогового входа (analog)",
"style": "width:100%"
},
{
"type": "h6",
"title": "Прочитанное значение: {{analog_in}}"
},
{
"type": "h6",
"title": "Преобразованное значение: {{analog}}"
},
{
"type": "hr"
},
{
"type": "h4",
"title": "Модуль температурного датчика (dallas)",
"style": "width:100%"
},
{
"type": "h6",
"title": "Текущее значение: {{dallas}} °C"
},
{
"type": "hr"
},
{
"type": "h4",
"title": "Модуль pH сенсора от df robot (ph)",
"style": "width:100%"
},
{
"type": "h6",
"title": "Текущее значение: {{ph}}"
},
{
"type": "hr"
},
{
"type": "link",
"title": "Очистить все логи",
"action": "/cleanlog",
"class": "btn btn-block btn-success"
},
{
"type": "link",
"title": "Главная",
"action": "/page.htm?index",
"class": "btn btn-block btn-danger btn-sm"
}
]
}

19
data/config.all.txt Normal file
View File

@@ -0,0 +1,19 @@
button 1 na Включить#все Освещение 0 1
button 2 13 Прихожая Освещение 0 2
button 3 14 Кухня Освещение 0 3
pwm 1 3 Яркость#коредор: Освещение 1023 4
pwm 2 4 Яркость#ванная: Освещение 510 5
analog Аналоговый#вход,#% Датчики text 1 1024 1 1024 6
logging analog 1 144 график Датчики 7
input value1 20.0 5 порог.#значение Датчики 8
button 4 na Вкл#по#analog>20 Датчики 0 11
//dallas 2 Водонагреватель,#t°C Датчики termometr 14
//level Вода#в#баке,#% Датчики gauge 125 20 15
//ph pH Датчики text 0 16
input value2 8.0 1 период#сек Таймер 117
button 5 na Вкл#обратный#таймер Таймер 0 20
button 6 5 Включится#по#таймеру Таймер 0 21
switch 1 0 20
text 1 Квартира Двери 22
button 7 scenario Сценарии Настройки 1 23
button 8 line1,line2, 2строки#сценариев Освещение 1 24

1
data/config.json Normal file
View File

@@ -0,0 +1 @@
{"SSDP":"MODULES","chipID":"12884479-1458415","ssidAP":"WiFi","passwordAP":"","ssid":"MGTS_GPON_DC15","password":"HKC4MRE4","timezone":3,"mqttServer":"91.204.228.124","mqttPort":1883,"mqttUser":"rise","mqttPass":"23ri22se32","scenario":"1","timers":"0","pushingbox_id":"v670C4F8A2581A11"}

BIN
data/css/build.css.gz Normal file

Binary file not shown.

572
data/edit.htm Normal file
View File

@@ -0,0 +1,572 @@
<!DOCTYPE html>
<html>
<head>
<title>ESP Editor</title>
<style type="text/css" media="screen">
.contextMenu{z-index:300;position:absolute;left:5px;border:1px solid #444;background-color:#f5f5f5;display:none;box-shadow:0 0 10px rgba(0,0,0,.4);font-size:12px;font-family:sans-serif;font-weight:bold}
.contextMenu ul{list-style:none;top:0;left:0;margin:0;padding:0}
.contextMenu li{position:relative;min-width:60px;cursor:pointer}
.contextMenu span{color:#444;display:inline-block;padding:6px}
.contextMenu li:hover{background:#444}
.contextMenu li:hover span{color:#EEE}
.css-treeview ul,.css-treeview li{padding:0;margin:0;list-style:none}
.css-treeview input{position:absolute;opacity:0}
.css-treeview{font:normal 11px Verdana,Arial,Sans-serif;-moz-user-select:none;-webkit-user-select:none;user-select:none}
.css-treeview span{color:#00f;cursor:pointer}
.css-treeview span:hover{text-decoration:underline}
.css-treeview input+label+ul{margin:0 0 0 22px}
.css-treeview input ~ ul{display:none}
.css-treeview label,.css-treeview label::before{cursor:pointer}
.css-treeview input:disabled+label{cursor:default;opacity:.6}
.css-treeview input:checked:not(:disabled) ~ ul{display:block}
.css-treeview label,.css-treeview label::before{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAACgCAYAAAAFOewUAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAApxJREFUeNrslM1u00AQgGdthyalFFOK+ClIIKQKyqUVQvTEE3DmAhLwAhU8QZoH4A2Q2gMSFace4MCtJ8SPBFwAkRuiHKpA6sRN/Lu7zG5i14kctaUqRGhGXnu9O/Pt7MzsMiklvF+9t2kWTDvyIrAsA0aKRRi1T0C/hJ4LUbt5/8rNpWVlp8RSr9J40b48fxFaTQ9+ft8EZ6MJYb0Ok+dnYGpmPgXwKIAvLx8vYXc5GdMAQJgQEkpjRTh36TS2U+DWW/D17WuYgm8pwJyY1npZsZKOxImOV1I/h4+O6vEg5GCZBpgmA6hX8wHKUHDRBXQYicQ4rlc3Tf0VMs8DHBS864F2YFspjgUYjKX/Az3gsdQd2eeBHwmdGWXHcgBGSkZXOXohcEXebRoQcAgjqediNY+AVyu3Z3sAKqfKoGMsewBeEIOPgQxxPJIjcGH6qtL/0AdADzKGnuuD+2tLK7Q8DhHHbOBW+KEzcHLuYc82MkEUekLiwuvVH+guQBQzOG4XdAb8EOcRcqQvDkY2iCLuxECJ43JobMXoutqGgDa2T7UqLKwt9KRyuxKVByqVXXqIoCCUCAqhUOioTWC7G4TQEOD0APy2/7G2Xpu1J4+lxeQ4TXBbITDpoVelRN/BVFbwu5oMMJUBhoXy5tmdRcMwymP2OLQaLjx9/vnBo6V3K6izATmSnMa0Dq7ferIohJhr1p01zrlz49rZF4OMs8JkX23vVQzYp+wbYGV/KpXKjvspl8tsIKCrMNAYFxj2GKS5ZWxg4ewKsJfaGMIY5KXqPz8LBBj6+yDvVP79+yDp/9F9oIx3OisHWwe7Oal0HxCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgwD8E/BZgAP0qhKj3rXO7AAAAAElFTkSuQmCC") no-repeat}
.css-treeview label,.css-treeview span,.css-treeview label::before{display:inline-block;height:16px;line-height:16px;vertical-align:middle}
.css-treeview label{background-position:18px 0}
.css-treeview label::before{content:"";width:16px;margin:0 22px 0 0;vertical-align:middle;background-position:0 -32px}
.css-treeview input:checked+label::before{background-position:0 -16px}
@media screen and (-webkit-min-device-pixel-ratio:0){.css-treeview{-webkit-animation:webkit-adjacent-element-selector-bugfix infinite 1s}@-webkit-keyframes webkit-adjacent-element-selector-bugfix{from{padding:0}to{padding:0}}}
#uploader{position:absolute;top:0;right:0;left:0;height:28px;line-height:24px;padding-left:10px;background-color:#444;color:#EEE}#tree{position:absolute;top:28px;bottom:0;left:0;width:200px;padding:8px}
#editor,#preview{position:absolute;top:28px;right:0;bottom:0;left:200px}
#preview{background-color:#EEE;padding:5px}
</style>
<script>
var urlXXX = 'http://192.168.211.181';//bolt
if (window.location.search.substring(1).split("=")[1]) {
urlXXX = 'http://'+window.location.search.substring(1).split("=")[1];
} else {
urlXXX = 'http://'+window.location.hostname;
}
function createFileUploader(element, tree, editor){
var xmlHttp;
var input = document.createElement("input");
input.type = "file";
input.multiple = false;
input.name = "data";
document.getElementById(element).appendChild(input);
var path = document.createElement("input");
path.id = "upload-path";
path.type = "text";
path.name = "path";
path.defaultValue = "/";
document.getElementById(element).appendChild(path);
var button = document.createElement("button");
button.innerHTML = 'Upload';
document.getElementById(element).appendChild(button);
var mkdir = document.createElement("button");
mkdir.innerHTML = 'MkDir';
document.getElementById(element).appendChild(mkdir);
var mkfile = document.createElement("button");
mkfile.innerHTML = 'MkFile';
document.getElementById(element).appendChild(mkfile);
function httpPostProcessRequest(){
if (xmlHttp.readyState == 4){
if(xmlHttp.status != 200) alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
else {
tree.refreshPath(path.value);
}
}
}
function createPath(p){
xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = httpPostProcessRequest;
var formData = new FormData();
formData.append("path", p);
xmlHttp.open("PUT", urlXXX+"/edit");
xmlHttp.send(formData);
}
mkfile.onclick = function(e){
if(path.value.indexOf(".") === -1) return;
createPath(path.value);
editor.loadUrl(path.value);
};
mkdir.onclick = function(e){
if(path.value.length < 2) return;
var dir = path.value
if(dir.indexOf(".") !== -1){
if(dir.lastIndexOf("/") === 0) return;
dir = dir.substring(0, dir.lastIndexOf("/"));
}
createPath(dir);
};
button.onclick = function(e){
if(input.files.length === 0){
return;
}
xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = httpPostProcessRequest;
var formData = new FormData();
formData.append("data", input.files[0], path.value);
xmlHttp.open("POST", urlXXX+"/edit");
xmlHttp.send(formData);
}
input.onchange = function(e){
if(input.files.length === 0) return;
var filename = input.files[0].name;
var ext = /(?:\.([^.]+))?$/.exec(filename)[1];
var name = /(.*)\.[^.]+$/.exec(filename)[1];
if(typeof name !== undefined){
//1197 bolt if(name.length > 8) name = name.substring(0, 8);
filename = name;
}
if(typeof ext !== undefined){
if(ext === "html") ext = "htm";
else if(ext === "jpeg") ext = "jpg";
filename = filename + "." + ext;
}
if(path.value === "/" || path.value.lastIndexOf("/") === 0){
path.value = "/"+filename;
} else {
path.value = path.value.substring(0, path.value.lastIndexOf("/")+1)+filename;
}
}
}
function createTree(element, editor){
var preview = document.getElementById("preview");
var treeRoot = document.createElement("div");
treeRoot.className = "css-treeview";
document.getElementById(element).appendChild(treeRoot);
function loadDownload(path){
document.getElementById('download-frame').src = path+"?download=true";
}
function loadPreview(path){
document.getElementById("editor").style.display = "none";
preview.style.display = "block";
preview.innerHTML = '<img src="'+ urlXXX +path+'" style="max-width:100%; max-height:100%; margin:auto; display:block;" />';
}
function fillFolderMenu(el, path){
var list = document.createElement("ul");
el.appendChild(list);
var action = document.createElement("li");
list.appendChild(action);
var isChecked = document.getElementById(path).checked;
var expnd = document.createElement("li");
list.appendChild(expnd);
if(isChecked){
expnd.innerHTML = "<span>Collapse</span>";
expnd.onclick = function(e){
document.getElementById(path).checked = false;
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
};
var refrsh = document.createElement("li");
list.appendChild(refrsh);
refrsh.innerHTML = "<span>Refresh</span>";
refrsh.onclick = function(e){
var leaf = document.getElementById(path).parentNode;
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
httpGet(leaf, path);
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
};
} else {
expnd.innerHTML = "<span>Expand</span>";
expnd.onclick = function(e){
document.getElementById(path).checked = true;
var leaf = document.getElementById(path).parentNode;
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
httpGet(leaf, path);
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
};
}
var upload = document.createElement("li");
list.appendChild(upload);
upload.innerHTML = "<span>Upload</span>";
upload.onclick = function(e){
var pathEl = document.getElementById("upload-path");
if(pathEl){
var subPath = pathEl.value;
if(subPath.lastIndexOf("/") < 1) pathEl.value = path+subPath;
else pathEl.value = path.substring(subPath.lastIndexOf("/"))+subPath;
}
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
};
var delFile = document.createElement("li");
list.appendChild(delFile);
delFile.innerHTML = "<span>Delete</span>";
delFile.onclick = function(e){
httpDelete(path);
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
};
}
function fillFileMenu(el, path){
var list = document.createElement("ul");
el.appendChild(list);
var action = document.createElement("li");
list.appendChild(action);
if(isTextFile(path)){
action.innerHTML = "<span>Edit</span>";
action.onclick = function(e){
editor.loadUrl(path);
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
};
} else if(isImageFile(path)){
action.innerHTML = "<span>Preview</span>";
action.onclick = function(e){
loadPreview(path);
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
};
}
var download = document.createElement("li");
list.appendChild(download);
download.innerHTML = "<span>Download</span>";
download.onclick = function(e){
loadDownload(path);
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
};
var delFile = document.createElement("li");
list.appendChild(delFile);
delFile.innerHTML = "<span>Delete</span>";
delFile.onclick = function(e){
httpDelete(path);
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
};
}
function showContextMenu(e, path, isfile){
var divContext = document.createElement("div");
var scrollTop = document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop;
var scrollLeft = document.body.scrollLeft ? document.body.scrollLeft : document.documentElement.scrollLeft;
var left = e.clientX + scrollLeft;
var top = e.clientY + scrollTop;
divContext.className = 'contextMenu';
divContext.style.display = 'block';
divContext.style.left = left + 'px';
divContext.style.top = top + 'px';
if(isfile) fillFileMenu(divContext, path);
else fillFolderMenu(divContext, path);
document.body.appendChild(divContext);
var width = divContext.offsetWidth;
var height = divContext.offsetHeight;
divContext.onmouseout = function(e){
if(e.clientX < left || e.clientX > (left + width) || e.clientY < top || e.clientY > (top + height)){
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(divContext);
}
};
}
function createTreeLeaf(path, name, size){
var leaf = document.createElement("li");
leaf.id = (((path == "/")?"":path)+"/"+name).toLowerCase();
var label = document.createElement("span");
label.textContent = name.toLowerCase();
leaf.appendChild(label);
leaf.onclick = function(e){
if(isTextFile(leaf.id)){
editor.loadUrl(leaf.id);
} else if(isImageFile(leaf.id)){
loadPreview(leaf.id);
}
};
leaf.oncontextmenu = function(e){
e.preventDefault();
e.stopPropagation();
showContextMenu(e, leaf.id, true);
};
return leaf;
}
function createTreeBranch(path, name, disabled){
var leaf = document.createElement("li");
var check = document.createElement("input");
check.type = "checkbox";
check.id = (((path == "/")?"":path)+"/"+name).toLowerCase();
if(typeof disabled !== "undefined" && disabled) check.disabled = "disabled";
leaf.appendChild(check);
var label = document.createElement("label");
label.for = check.id;
label.textContent = name.toLowerCase();
leaf.appendChild(label);
check.onchange = function(e){
if(check.checked){
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
httpGet(leaf, check.id);
}
};
label.onclick = function(e){
if(!check.checked){
check.checked = true;
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
httpGet(leaf, check.id);
} else {
check.checked = false;
}
};
leaf.oncontextmenu = function(e){
e.preventDefault();
e.stopPropagation();
showContextMenu(e, check.id, false);
}
return leaf;
}
function addList(parent, path, items){
var list = document.createElement("ul");
parent.appendChild(list);
var ll = items.length;
//Сортировка файлов
items.sort(function(a,b){return (a.name < b.name) ? 1 : ((b.name < a.name) ? -1 : 0);});
for(var i = 0; i < ll; i++){
var item = items[i];
var itemEl;
if(item.type === "file"){
itemEl = createTreeLeaf(path, item.name, item.size);
} else {
itemEl = createTreeBranch(path, item.name);
}
list.appendChild(itemEl);
}
}
function isTextFile(path){
var ext = /(?:\.([^.]+))?$/.exec(path)[1];
if(typeof ext !== undefined){
switch(ext){
case "txt":
case "htm":
case "html":
case "js":
case "json":
case "c":
case "h":
case "cpp":
case "css":
case "xml":
return true;
}
}
return false;
}
function isImageFile(path){
var ext = /(?:\.([^.]+))?$/.exec(path)[1];
if(typeof ext !== undefined){
switch(ext){
case "png":
case "jpg":
case "gif":
case "ico":
return true;
}
}
return false;
}
this.refreshPath = function(path){
if(path.lastIndexOf('/') < 1){
path = '/';
treeRoot.removeChild(treeRoot.childNodes[0]);
httpGet(treeRoot, "/");
} else {
path = path.substring(0, path.lastIndexOf('/'));
var leaf = document.getElementById(path).parentNode;
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
httpGet(leaf, path);
}
};
function delCb(path){
return function(){
if (xmlHttp.readyState == 4){
if(xmlHttp.status != 200){
alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
} else {
if(path.lastIndexOf('/') < 1){
path = '/';
treeRoot.removeChild(treeRoot.childNodes[0]);
httpGet(treeRoot, "/");
} else {
path = path.substring(0, path.lastIndexOf('/'));
var leaf = document.getElementById(path).parentNode;
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
httpGet(leaf, path);
}
}
}
}
}
function httpDelete(filename){
xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = delCb(filename);
var formData = new FormData();
formData.append("path", filename);
xmlHttp.open("DELETE", urlXXX+"/edit");
xmlHttp.send(formData);
}
function getCb(parent, path){
return function(){
if (xmlHttp.readyState == 4){
//clear loading
if(xmlHttp.status == 200) addList(parent, path, JSON.parse(xmlHttp.responseText));
}
}
}
function httpGet(parent, path){
xmlHttp = new XMLHttpRequest(parent, path);
xmlHttp.onreadystatechange = getCb(parent, path);
//Для отключения кэша random() иначе будут старые данные
xmlHttp.open("GET", urlXXX+"/edit?list=" + path +"&rand="+Math.random(), true);
xmlHttp.send(null);
//start loading
}
httpGet(treeRoot, "/");
return this;
}
function createEditor(element, file, lang, theme, type){
function getLangFromFilename(filename){
var lang = "plain";
var ext = /(?:\.([^.]+))?$/.exec(filename)[1];
if(typeof ext !== undefined){
switch(ext){
case "txt": lang = "plain"; break;
case "htm": lang = "html"; break;
case "js": lang = "javascript"; break;
case "c": lang = "c_cpp"; break;
case "cpp": lang = "c_cpp"; break;
case "css":
case "scss":
case "php":
case "html":
case "json":
case "xml":
lang = ext;
}
}
return lang;
}
if(typeof file === "undefined") file = "/index.htm";
if(typeof lang === "undefined"){
lang = getLangFromFilename(file);
}
if(typeof theme === "undefined") theme = "textmate";
if(typeof type === "undefined"){
type = "text/"+lang;
if(lang === "c_cpp") type = "text/plain";
}
var xmlHttp = null;
var editor = ace.edit(element);
//post
function httpPostProcessRequest(){
if (xmlHttp.readyState == 4){
if(xmlHttp.status != 200) alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
}
}
function httpPost(filename, data, type){
xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = httpPostProcessRequest;
var formData = new FormData();
formData.append("data", new Blob([data], { type: type }), filename);
xmlHttp.open("POST", urlXXX + "/edit");
xmlHttp.send(formData);
}
//get
function httpGetProcessRequest(){
if (xmlHttp.readyState == 4){
document.getElementById("preview").style.display = "none";
document.getElementById("editor").style.display = "block";
if(xmlHttp.status == 200) editor.setValue(xmlHttp.responseText);
else editor.setValue("");
editor.clearSelection();
}
}
function httpGet(theUrl){
xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = httpGetProcessRequest;
if (theUrl.indexOf("/") == 0)
theUrl = urlXXX + theUrl;//bolt
xmlHttp.open("GET", theUrl+"?rand="+Math.random(), true);
xmlHttp.send(null);
}
if(lang !== "plain") editor.getSession().setMode("ace/mode/"+lang);
editor.setTheme("ace/theme/"+theme);
editor.$blockScrolling = Infinity;
editor.getSession().setUseSoftTabs(true);
editor.getSession().setTabSize(2);
editor.setHighlightActiveLine(true);
editor.setShowPrintMargin(false);
editor.commands.addCommand({
name: 'saveCommand',
bindKey: {win: 'Ctrl-S', mac: 'Command-S'},
exec: function(editor) {
httpPost(file, editor.getValue()+"", type);
},
readOnly: false
});
editor.commands.addCommand({
name: 'undoCommand',
bindKey: {win: 'Ctrl-Z', mac: 'Command-Z'},
exec: function(editor) {
editor.getSession().getUndoManager().undo(false);
},
readOnly: false
});
editor.commands.addCommand({
name: 'redoCommand',
bindKey: {win: 'Ctrl-Shift-Z', mac: 'Command-Shift-Z'},
exec: function(editor) {
editor.getSession().getUndoManager().redo(false);
},
readOnly: false
});
httpGet(file);
editor.loadUrl = function(filename){
file = filename;
lang = getLangFromFilename(file);
type = "text/"+lang;
if(lang !== "plain") editor.getSession().setMode("ace/mode/"+lang);
httpGet(file);
}
return editor;
}
function onBodyLoad(){
var vars = {};
// var s = "http://192.168.211.180/edit/index.htm";
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) { vars[key] = value; });
// var parts = s.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) { vars[key] = value; });
if (typeof vars.url !== "undefined" && vars.url != "")
urlXXX = "http://" + vars.url;/**/
var editor = createEditor("editor", vars.file, vars.lang, vars.theme);
var tree = createTree("tree", editor);
createFileUploader("uploader", tree, editor);
};
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.6/ace.js" type="text/javascript" charset="utf-8"></script>
<script>
(function() {
window.require(["ace/ace"], function(a) {
a && a.config.init(true);
if (!window.ace)
window.ace = a;
for (var key in a) if (a.hasOwnProperty(key))
window.ace[key] = a[key];
});
})();
</script>
</head>
<body onload="onBodyLoad();">
<div id="uploader"></div>
<div id="tree"></div>
<div id="editor"></div>
<div id="preview" style="display:none;"></div>
<iframe id=download-frame style='display:none;'></iframe>
</body>
</html>

BIN
data/edit.htm.gz Normal file

Binary file not shown.

BIN
data/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

75
data/index.htm Normal file
View File

@@ -0,0 +1,75 @@
<!DOCTYPE html>
<html>
<head>
<!--
Web Developer: Renats Kevrels (ex. Zozula)
Site: http://www.onclick.lv
Contact: info [at] onclick.lv
Skype: renat2985
Twitter: @Ramzies
Facebook: http://www.facebook.com/renat2985
GitHub: https://github.com/renat2985
From: Latvia, Valmiera
-->
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico">
<script defer src="js/build.chart.js?v07.04.2018" charset="utf-8"></script>
<!-- <link rel="stylesheet" type="text/css" href="css/chartist.min.css">
<script src="js/chartist.min.js" charset="utf-8"></script>
<script type="text/javascript" src="js/chart.js"></script> -->
<link rel="stylesheet" type="text/css" href="css/build.css?v07.04.2018">
<!-- <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/style.css"> -->
<script defer type="text/javascript" src="js/function.js?v07.04.2018"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<script type="text/javascript">
var jsonResponse;
//function selectTextareaLine(tarea,lineNum) {
// lineNum--;
// var lines = tarea.value.split("\n");
// var startPos = 0, endPos = tarea.value.length;
// for(var x = 0; x < lines.length; x++) {
// if(x == lineNum) {break;}
// startPos += (lines[x].length+1);
// }
// var endPos = lines[lineNum].length+startPos;
// if(typeof(tarea.selectionStart) != "undefined") {
// tarea.focus();
// tarea.selectionStart = startPos;
// tarea.selectionEnd = endPos;
// return true;
// }
// return false;
//}
window.onload = function() {
setContent('first');
}
</script>
</head>
<body>
<div class="container loader-bg">
<ul id="url-content" class="hidden" onclick="document.getElementById('content').style.zIndex=0;"></ul>
<div id="headers"></div>
<div class="row hidden" id="container_column">
<h1 id="title"></h1>
<div id="content" onclick="this.style.zIndex=10"></div>
</div>
<div id="footer"></div>
<div id="edit-content" class="hidden" onclick="document.getElementById('content').style.zIndex=0;">
<a target="_blank" style="position:fixed;right:0;color:#000;" href="https://github.com/tretyakovsa/Sonoff_WiFi_switch/wiki/%D0%92%D0%BE%D0%B7%D0%BC%D0%BE%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D0%B8-page.htm%3F*" title="Github wiki"><i class="help-img"></i>wiki</a>
<textarea class="form-control" onkeyup="isValidJson(this.value,'edit-json')" spellcheck="false" id="edit-json"></textarea>
<div id="error-json"></div>
<div class="btn-group btn-block">
<input class="btn btn-success" style="width:40%" id="edit-view" onclick="setContent('edit');this.value='Loading...';html('url-content', ' ');" value="View" type="button">
<input class="btn btn-danger" style="width:40%" id="edit-save" onclick="var urlPages=window.location.search.substring(1).split('&')[0];httpDelete('/'+urlPages+'.json.gz');send_request_edit(this, val('edit-json'),(urlPages?urlPages:'index')+'.json');toggle('edit-content');toggle('url-content');" value="Save" type="button">
<a class="btn btn-info" style="width:20%" href="#" id="download-json" download="" title="Save to PC"><i class="download-img"></i></a>
</div>
</div>
</div>
</body>
</html>

BIN
data/index.htm.gz Normal file

Binary file not shown.

56
data/index.json Normal file
View File

@@ -0,0 +1,56 @@
{
"configs": [
"/config.live.json",
"/config.setup.json"
],
"title": "Главная",
"class": "col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6",
"content": [
{
"type": "h5",
"title": "{{SSDP}}",
"class": "alert-warning"
},
{
"type": "h4",
"title": "Device ID: {{chipID}}"
},
{
"type": "h4",
"title": "IP address: {{ip}}"
},
{
"type": "link",
"title": "Конфигурация устройства",
"action": "/page.htm?config.all",
"class": "btn btn-block btn-primary"
},
{
"type": "hr"
},
{
"type": "link",
"title": "Конфигурация WIFI",
"action": "/page.htm?setup",
"class": "btn btn-block btn-success"
},
{
"type": "link",
"title": "Конфигурация MQTT",
"action": "/page.htm?mqtt",
"class": "btn btn-block btn-success"
},
{
"type": "link",
"title": "Конфигурация push",
"action": "/page.htm?pushingbox",
"class": "btn btn-block btn-success"
},
{
"type": "link",
"title": "Скачать приложение IoT Manager",
"action": "https://github.com/DmitryBorisenko33/esp8266_iot-manager_modules_firmware/raw/master/iot_manager/IoT%20Manager%201.5.5.apk",
"class": "btn btn-block btn-success"
}
]
}

BIN
data/js/build.chart.js.gz Normal file

Binary file not shown.

BIN
data/js/function.js.gz Normal file

Binary file not shown.

BIN
data/lang/lang.en.json.gz Normal file

Binary file not shown.

BIN
data/lang/lang.lv.json.gz Normal file

Binary file not shown.

BIN
data/lang/lang.ru.json.gz Normal file

Binary file not shown.

BIN
data/lang/lang.ua.json.gz Normal file

Binary file not shown.

BIN
data/mode-html.js.gz Normal file

Binary file not shown.

73
data/mqtt.json Normal file
View File

@@ -0,0 +1,73 @@
{
"configs": [
"/config.setup.json"
],
"class":"col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6",
"content": [
{
"type": "h5",
"title": "{{SSDP}}",
"class":"alert-warning"
},
{
"type": "h4",
"title": "Server name:"
},
{
"type": "input",
"title": "",
"name":"1",
"state": "{{mqttServer}}"
},
{
"type": "h4",
"title": "Port:"
},
{
"type": "input",
"title": "",
"name":"2",
"state": "{{mqttPort}}"
},
{
"type": "h4",
"title": "User name:"
},
{
"type": "input",
"title": "",
"name":"3",
"state": "{{mqttUser}}"
},
{
"type": "h4",
"title": "Password:"
},
{
"type": "input",
"title": "",
"name":"4",
"state": "{{mqttPass}}"
},
{
"type":"h3",
"name":"my-block",
"style":"position:fixed;top:30%;left:50%;width:400px;margin-left:-200px;text-align:center;",
"class":"hidden"
},
{
"type": "button",
"title":"Сохранить и проверить соединение",
"action": "mqttSave?mqttServer=[[1]]&mqttPort=[[2]]&mqttUser=[[3]]&mqttPass=[[4]]",
"response":"[[my-block]]",
"class": "btn btn-block btn-success",
"style": "width:100%;display:inline"
},
{
"type": "link",
"title": "Главная",
"action": "/page.htm?index",
"class": "btn btn-block btn-danger btn-sm"
}
]
}

BIN
data/page.htm.gz Normal file

Binary file not shown.

92
data/push.json Normal file
View File

@@ -0,0 +1,92 @@
{
"configs": [
"/config.setup.json"
],
"class":"col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6",
"content": [
{
"type": "h5",
"title": "{{SSDP}}",
"class":"alert-warning"
},
{
"type": "h4",
"title": "Host name:"
},
{
"type": "input",
"title": "",
"name":"1",
"state": "{{pushHost}}"
},
{
"type": "h4",
"title": "Port:"
},
{
"type": "input",
"title": "",
"name":"2",
"state": "{{pushPort}}"
},
{
"type": "h4",
"title": "Fingerprint:"
},
{
"type": "input",
"title": "",
"name":"3",
"state": "{{pushFingerprint}}"
},
{
"type": "h4",
"title": "Access Token:"
},
{
"type": "input",
"title": "",
"name":"4",
"state": "{{pushAccessToken}}"
},
{
"type":"h3",
"name":"my-block",
"style":"position:fixed;top:30%;left:50%;width:400px;margin-left:-200px;text-align:center;",
"class":"hidden"
},
{
"type": "button",
"title":"Сохранить и проверить соединение",
"action": "pushDate?pushHost=[[1]]&pushPort=[[2]]&pushFingerprint=[[3]]&pushAccessToken=[[4]]",
"response":"[[my-block]]",
"class": "btn btn-block btn-success",
"style": "width:100%;display:inline"
},
{
"type": "hr"
},
{
"type": "checkbox",
"name":"start-push",
"title": "Отправлять push при включении устройства",
"action": "startPush?status=[[start-push]]",
"state": "{{startPush}}"
},
{
"type": "hr"
},
{
"type": "link",
"title": "Перезагрузить устройство",
"action": "javascript:if(confirm(renameBlock(jsonResponse,'Перезагрузить?'))){send_request(this,'/restart?device=ok');}",
"class": "btn btn-block btn-warning"
},
{
"type": "link",
"title": "Главная",
"action": "/page.htm?index",
"class": "btn btn-block btn-danger btn-sm"
}
]
}

46
data/pushingbox.json Normal file
View File

@@ -0,0 +1,46 @@
{
"configs": [
"/config.setup.json"
],
"class":"col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6",
"content": [
{
"type": "h5",
"title": "{{SSDP}}",
"class":"alert-warning"
},
{
"type": "h4",
"title": "Device id:"
},
{
"type": "input",
"title": "",
"name":"1",
"state": "{{pushingbox_id}}"
},
{
"type": "button",
"title":"Сохранить",
"action": "pushingboxDate?pushingbox_id=[[1]]",
"class": "btn btn-block btn-success",
"style": "width:100%;display:inline"
},
{
"type": "hr"
},
{
"type": "link",
"title": "Перезагрузить устройство",
"action": "javascript:if(confirm(renameBlock(jsonResponse,'Перезагрузить?'))){send_request(this,'/restart?device=ok');}",
"class": "btn btn-block btn-warning"
},
{
"type": "link",
"title": "Главная",
"action": "/page.htm?index",
"class": "btn btn-block btn-danger btn-sm"
}
]
}

31
data/scenario.all.txt Normal file
View File

@@ -0,0 +1,31 @@
button1 = 1
buttonSet 2 1
buttonSet 3 1
pwmSet 2 1024
end
button1 = 0
buttonSet 2 0
buttonSet 3 0
pwmSet 2 0
end
analog > value1
buttonSet 4 1
end
button5 = 1
timerStart 1 value2 sec
end
button5 = 0
timerStart 2 value2 sec
end
timer1 = 0
buttonSet 6 1
end
timer2 = 0
buttonSet 6 0
end
switch1 = 1
textSet 1 закрыто-time
end
switch1 = 0
textSet 1 открыто-time
end

154
data/setup.json Normal file
View File

@@ -0,0 +1,154 @@
{
"configs": [
"/config.setup.json"
],
"title": "Конфигурация",
"class":"col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6",
"content": [
{
"type": "h5",
"title": "{{SSDP}}",
"class":"alert-warning"
},
{
"type": "link",
"title": "Главная",
"action": "/",
"class": "btn btn-block btn-danger"
},
{
"type": "hr"
},
{
"type": "h2",
"title": "Имя устройства"
},
{
"type": "input",
"title": "Имя устройства",
"name":"ssdp",
"state": "{{SSDP}}",
"pattern": "[0-9a-zA-Zа-яА-Я.\\- ]{1,20}"
},
{
"type": "button",
"title": "Сохранить",
"action": "ssdp?ssdp=[[ssdp]]",
"class": "btn btn-block btn-success"
},
{
"type": "hr"
},
{
"type": "h2",
"title": "Подключение к Wi-Fi роутеру"
},
{
"type": "input",
"title":"Сеть",
"name":"ssid",
"state": "{{ssid}}"
},
{
"type": "password",
"title": "Введите пароль",
"name":"ssidPass",
"state": "{{password}}",
"pattern": ".{8,20}"
},
{
"type": "button",
"title": "Сохранить",
"class": "btn btn-block btn-success",
"action": "ssid?ssid=[[ssid]]&password=[[ssidPass]]"
},
{
"type": "hr"
},
{
"type": "h2",
"title": "Временная зона GMT"
},
{
"type": "input",
"title": "{{LangSpace}}",
"name":"timeZone",
"state": "{{timezone}}",
"pattern": "[0-9-]{1,3}"
},
{
"type": "button",
"module":"",
"title": "Сохранить",
"class": "btn btn-block btn-success",
"action": "timeZone?timeZone=[[timeZone]]"
},
{
"type": "link",
"title": "Автоопределение зоны",
"action": "javascript:set_time_zone(this);",
"class": "btn btn-block btn-primary"
},
{
"type": "time",
"name":"times1",
"title": "На устройстве сейчас",
"state":"{{time}}"
},
{
"type": "button",
"response":"[[&#116imes1]]",
"title": "Синхронизировать",
"class": "btn btn-block btn-primary",
"action": "Time"
},
{
"type": "hr"
},
{
"type": "h2",
"title": "Точка доступа"
},
{
"type": "text",
"title": "После того как устройство подключается к роутеру, его Wi-Fi исчезнет.",
"class": "alert alert-warning",
"style": "width:45%;float:right;"
},
{
"type": "input",
"title": "Имя WI-FI сети",
"name":"ssidap",
"state": "{{ssidAP}}",
"style": "width:50%;display:inline",
"pattern": ".{1,20}"
},
{
"type": "password",
"title": "Пароль",
"name":"ssidApPass",
"state": "{{passwordAP}}",
"style": "width:50%;display:inline",
"pattern": ".{8,20}"
},
{
"type": "button",
"title": "Сохранить",
"action": "ssidap?ssidAP=[[ssidap]]&passwordAP=[[ssidApPass]]",
"class": "btn btn-block btn-success",
"style": "width:50%;display:inline"
},
{
"type": "hr"
},
{
"type": "hr"
},
{
"type": "link",
"title": "Перезагрузить устройство",
"action": "javascript:if(confirm(renameBlock(jsonResponse,'Перезагрузить?'))){send_request(this,'/restart?device=ok');}",
"class": "btn btn-block btn-warning"
}
]
}

57
data/soket.json Normal file
View File

@@ -0,0 +1,57 @@
{
"configs": [
"/config.live.json",
"/config.option.json",
"/config.setup.json",
"/lang/lang.ru.json",
"socket {{ip}}:81/"
],
"title": "Главная",
"class":"col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6",
"content": [
{
"type": "h5",
"title": "{{SSDP}}",
"class":"alert-warning"
},
{
"type": "h4",
"title": "Module tank level:",
"style": "width:80%;float:left;"
},
{
"type": "h4",
"title": "{{module_tank_level_s}}",
"style": "width:20%;float:right;"
},
{
"type": "h4",
"title": "Module analog:",
"style": "width:80%;float:left;"
},
{
"type": "h4",
"title": "{{module_analog_s}}",
"style": "width:20%;float:right;"
},
{
"type": "h4",
"title": "Module ds18b20:",
"style": "width:80%;float:left;"
},
{
"type": "h4",
"title": "{{module_ds18b20_s}}",
"style": "width:20%;float:right;"
},
{
"type": "link",
"title": "Главная",
"action": "/page.htm?index",
"class": "btn btn-block btn-danger btn-sm",
"style": "width:100%;float:right;"
}
]
}

View File

@@ -0,0 +1,12 @@
{
"id" : "",
"page" : "",
"widget" : "anydata",
"class1": "col-xs-4 text-center",
"class2": "stable",
"style2": "font-size:12px;float:center;",
"class3":"stable",
"style3": "font-size:25px;float:center;font-weight:bold;",
"descr" : "",
"topic" : ""
}

View File

@@ -0,0 +1,12 @@
{
"id" : "",
"page" : "",
"widget" : "anydata",
"class1" : "item col-xs-12 text-center",
"class2": "ballanced",
"style2": "font-size:20px;float:left;font-weight:bold;",
"class3":"ballanced",
"style3": "font-size:17px;float:right;",
"descr" : "",
"topic" : ""
}

View File

@@ -0,0 +1,18 @@
{
"id": "",
"pageId":"",
"page": "",
"widget": "simple-btn",
"class1": "col-xs-4 text-center",
"class2": "ballanced",
"style2": "font-size:15px;float:left;font-weight:bold;",
"topic": "",
"class3": "button button-block",
"style3": "float:right;",
"widgetConfig": {
"fill": "#F5F5F5",
"fillPressed": "#4169E1",
"title": "-",
"delay":500
}
}

View File

@@ -0,0 +1,13 @@
{
"id" : "",
"pageId": "",
"widget" : "chart",
"topic" : "",
"widgetConfig": {
"maxCount": 200,
"type": "line",
"height": 200
}
}

View File

@@ -0,0 +1,23 @@
{
"id": "",
"page": "",
"pageId": "",
"widget": "fillgauge",
"descr": "",
"class2": "text-center ballanced",
"style2": "font-size:25px;font-weight:bold;padding-top:10px;padding-bottom:10px;",
"class3" : "text-center",
"style3": "padding-top:10px;padding-bottom:10px;",
"topic": "",
"width": "250px",
"height": "250px",
"widgetConfig": {
"circleColor": "#228B22",
"textColor": "#FFFFFF",
"waveTextColor": "#050000",
"waveColor": "#40E0D0",
"circleThickness": 0.05,
"textVertPosition": 0.5,
"waveAnimateTime": 500
}
}

View File

@@ -0,0 +1,18 @@
{
"id" : "",
"pageId": "",
"widget" : "gauge",
"topic" : "",
"class1" : "item no-border no-padding text-center",
"descr" : "",
"widgetConfig" : {
"type" : "full",
"cap" : "round",
"append" : "",
"size" : 300,
"thick" : 20,
"maximum": 1024,
"color" : "#11c1f3",
"backgroundColor": "rgba(0,0,0, 0.2)"
}
}

View File

@@ -0,0 +1,16 @@
{
"id": "",
"pageId": "",
"descr": "",
"class1": "col-xs-3 text-center",
"page": "",
"widget": "steel",
"topic": "",
"widgetConfig": {
"width": 60,
"height": 60,
"type": "Led",
"blink": false,
"LedColor": "RED_LED"
}
}

View File

@@ -0,0 +1,13 @@
{
"id": "",
"page": "",
"descr": "",
"widget": "range",
"class3": "ballanced",
"style3": "font-size:25px;float:left;font-weight:bold;",
"topic": "",
"widgetConfig": {
"maxValue": 1023,
"minValue": 0
}
}

View File

@@ -0,0 +1,13 @@
{
"id" : "1",
"page" : "",
"pageId":"",
"widget" : "anydata",
"class1" : "item rounded text-center no-padding",
"class2": "ballanced",
"style2": "",
"class3":"ballanced",
"style3": "font-size:10px;float:right;",
"descr" : "",
"topic" : ""
}

View File

@@ -0,0 +1,15 @@
{
"id": "",
"page": "",
"pageId": "",
"widget": "steel",
"topic": "/DS",
"widgetConfig": {
"width": "auto",
"height": 150,
"type": "Linear",
"titleString": "Спальня",
"unitString": "°C",
"threshold": 30
}
}

View File

@@ -0,0 +1,11 @@
{
"id": "",
"page": "",
"pageId": "",
"widget": "toggle",
"descrStyle": "font-size:20px;float:left;font-weight:bold;",
"descrStyleOff": "font-size:20px;float:left;",
"color": "#8997ff",
"descr": "",
"topic": ""
}

BIN
data/worker-html.js.gz Normal file

Binary file not shown.

BIN
data_new/ace.js.gz Normal file

Binary file not shown.

BIN
data_new/chart.json.gz Normal file

Binary file not shown.

144
data_new/config.all.json Normal file
View File

@@ -0,0 +1,144 @@
{
"configs": [
"/config.live.json",
"/config.setup.json",
"/config.option.json"
],
"class":"col-sm-offset-1 col-sm-10",
"content": [
{
"type": "h5",
"title": "{{SSDP}}",
"class":"alert-warning"
},
{
"type": "h4",
"title": "Device ID: {{chipID}}"
},
{
"type": "h4",
"title": "IP address: {{ip}}"
},
{
"type": "hr"
},
{
"type": "h2",
"title": "Конфигурация устройства"
},
{
"type":"file",
"state":"config.all.txt",
"style":"width:100%;height:400px",
"title": "Сохранить",
"action": "/all_modules_init",
"class":"btn btn-block btn-success"
},
{
"type": "link",
"title": "Инструкция",
"action": "https://github.com/DmitryBorisenko33/esp8266_iot-manager_modules_firmware/wiki/Instruction",
"class": "btn btn-block btn-primary"
},
{
"type": "h2",
"title": "Сценарии"
},
{
"type": "checkbox",
"name":"scenario",
"title": "Включить сценарии",
"action": "/scenario?status=[[scenario]]",
"state": "{{scenario}}"
},
{
"type": "h6",
"title": ""
},
{
"type":"file",
"state":"scenario.all.txt",
"style":"width:100%;height:400px",
"title": "Сохранить и включить",
"action": "/scenario?status=1",
"class":"btn btn-block btn-success"
},
{
"type": "h2",
"title": "Данные модулей"
},
{
"type": "hr"
},
{
"type": "h4",
"title": "Модуль уровня воды (level)",
"style": "width:100%"
},
{
"type": "h6",
"title": "Расстояние от датчика до воды: {{level_in}} см"
},
{
"type": "h6",
"title": " Заполнение бака: {{level}} %"
},
{
"type": "hr"
},
{
"type": "h4",
"title": "Модуль аналогового входа (analog)",
"style": "width:100%"
},
{
"type": "h6",
"title": "Прочитанное значение: {{analog_in}}"
},
{
"type": "h6",
"title": "Преобразованное значение: {{analog}}"
},
{
"type": "hr"
},
{
"type": "h4",
"title": "Модуль температурного датчика (dallas)",
"style": "width:100%"
},
{
"type": "h6",
"title": "Текущее значение: {{dallas}} °C"
},
{
"type": "hr"
},
{
"type": "h4",
"title": "Модуль pH сенсора от df robot (ph)",
"style": "width:100%"
},
{
"type": "h6",
"title": "Текущее значение: {{ph}}"
},
{
"type": "hr"
},
{
"type": "link",
"title": "Очистить все логи",
"action": "/cleanlog",
"class": "btn btn-block btn-success"
},
{
"type": "link",
"title": "Главная",
"action": "/page.htm?index",
"class": "btn btn-block btn-danger btn-sm"
}
]
}

19
data_new/config.all.txt Normal file
View File

@@ -0,0 +1,19 @@
button 1 na Включить#все Освещение 0 1
button 2 13 Прихожая Освещение 0 2
button 3 14 Кухня Освещение 0 3
pwm 1 3 Яркость#коредор: Освещение 1023 4
pwm 2 4 Яркость#ванная: Освещение 510 5
analog Аналоговый#вход,#% Датчики text 1 1024 1 1024 6
logging analog 1 144 график Датчики 7
input value1 20.0 5 порог.#значение Датчики 8
button 4 na Вкл#по#analog>20 Датчики 0 11
//dallas 2 Водонагреватель,#t°C Датчики termometr 14
//level Вода#в#баке,#% Датчики gauge 125 20 15
//ph pH Датчики text 0 16
input value2 8.0 1 период#сек Таймер 117
button 5 na Вкл#обратный#таймер Таймер 0 20
button 6 5 Включится#по#таймеру Таймер 0 21
switch 1 0 20
text 1 Квартира Двери 22
button 7 scenario Сценарии Настройки 1 23
button 8 line1,line2, 2строки#сценариев Освещение 1 24

1
data_new/config.json Normal file
View File

@@ -0,0 +1 @@
{"SSDP":"MODULES","chipID":"12884479-1458415","ssidAP":"WiFi","passwordAP":"","ssid":"MGTS_GPON_1002","password":"TTNYJ4QJ","timezone":3,"mqttServer":"91.204.228.124","mqttPort":1883,"mqttUser":"rise","mqttPass":"23ri22se32","scenario":"1","timers":"0","pushingbox_id":"v670C4F8A2581A11"}

View File

@@ -0,0 +1 @@
{"SSDP":"MODULES","ssidAP":"WiFi","passwordAP":"","ssid":"MGTS_GPON_10B0","password":"8ed76da8","timezone":3,"mqttServer":"","mqttPort":0,"mqttUser":"","mqttPass":"","chipID":"9139530-1458400","scenario":"1","timers":"1","pushHost":"api.pushbullet.com","pushPort":443,"pushAccessToken":"","module_push":"0","pushFingerprint":"fef1573c6feeef932eaed0228e91878e048e73a2"}

View File

@@ -0,0 +1 @@
{"SSDP":"MODULES","ssidAP":"WiFi","passwordAP":"","ssid":"your_ssid","password":"your_password","timezone":3,"mqttServer":"","mqttPort":0,"mqttUser":"","mqttPass":"","chipID":"9139530-1458400","scenario":"1","timers":"1","pushHost":"api.pushbullet.com","pushPort":443,"pushAccessToken":"","module_push":"0","pushFingerprint":"fef1573c6feeef932eaed0228e91878e048e73a2"}

BIN
data_new/css/build.css.gz Normal file

Binary file not shown.

BIN
data_new/donate.htm.gz Normal file

Binary file not shown.

BIN
data_new/edit.htm.gz Normal file

Binary file not shown.

Binary file not shown.

BIN
data_new/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
data_new/img/swatches.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
data_new/img/swatches1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

57
data_new/index.htm Normal file
View File

@@ -0,0 +1,57 @@
<!DOCTYPE html>
<html>
<head>
<!--
Web Developer: Renats Kevrels (ex. Zozula)
Site: http://www.onclick.lv
Contact: info [at] onclick.lv
Skype: renat2985
Twitter: @Ramzies
Facebook: http://www.facebook.com/renat2985
GitHub: https://github.com/renat2985
From: Latvia, Valmiera
-->
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico">
<script defer src="js/build.chart.js?v17.12.2018" charset="utf-8"></script>
<!-- <link rel="stylesheet" type="text/css" href="css/chartist.min.css">
<script src="js/chartist.min.js" charset="utf-8"></script>
<script type="text/javascript" src="js/chart.js"></script> -->
<link rel="stylesheet" type="text/css" href="css/build.css?v17.12.2018">
<!-- <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/style.css"> -->
<script defer type="text/javascript" src="js/function.js?v17.12.2018"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title id="h-title"></title>
<script type="text/javascript">
var jsonResponse;
window.onload = function() {
setContent('first');
}
</script>
</head>
<body>
<div id="news"></div>
<div class="container loader-bg">
<ul id="url-content" class="hidden" onclick="document.getElementById('content').style.zIndex=0;"></ul>
<div id="headers"></div>
<div class="row hidden" id="container_column">
<h1 id="title"></h1>
<div id="content" onclick="this.style.zIndex=10"></div>
</div>
<div id="footer"></div>
<div id="edit-content" class="hidden" onclick="document.getElementById('content').style.zIndex=0;">
<a target="_blank" style="position:fixed;right:0;color:#000;" href="https://github.com/tretyakovsa/Sonoff_WiFi_switch/wiki/%D0%92%D0%BE%D0%B7%D0%BC%D0%BE%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D0%B8-page.htm%3F*" title="GitHub Wiki"><i class="help-img"></i>wiki</a>
<textarea class="form-control" onkeyup="isValidJson(this.value,'edit-json')" spellcheck="false" id="edit-json"></textarea>
<div id="error-json"></div>
<div class="btn-group btn-block">
<input class="btn btn-success" style="width:40%" id="edit-view" onclick="setContent('edit');this.value='Loading...';html('url-content', ' ');" value="View" type="button">
<input class="btn btn-danger" style="width:40%" id="edit-save" onclick="var urlPages=window.location.search.substring(1).split('&')[0];httpDelete('/'+urlPages+'.json.gz');send_request_edit(this, val('edit-json'),(urlPages?urlPages:'index')+'.json');toggle('edit-content');toggle('url-content');" value="Save" type="button">
<a class="btn btn-info" style="width:20%" href="#" id="download-json" download="" title="Save to PC"><i class="download-img"></i></a>
</div>
</div>
</div>
</body>
</html>

BIN
data_new/index.htm.gz Normal file

Binary file not shown.

56
data_new/index.json Normal file
View File

@@ -0,0 +1,56 @@
{
"configs": [
"/config.live.json",
"/config.setup.json"
],
"title": "Главная",
"class": "col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6",
"content": [
{
"type": "h5",
"title": "{{SSDP}}",
"class": "alert-warning"
},
{
"type": "h4",
"title": "Device ID: {{chipID}}"
},
{
"type": "h4",
"title": "IP address: {{ip}}"
},
{
"type": "link",
"title": "Конфигурация устройства",
"action": "/page.htm?config.all",
"class": "btn btn-block btn-primary"
},
{
"type": "hr"
},
{
"type": "link",
"title": "Конфигурация WIFI",
"action": "/page.htm?setup",
"class": "btn btn-block btn-success"
},
{
"type": "link",
"title": "Конфигурация MQTT",
"action": "/page.htm?mqtt",
"class": "btn btn-block btn-success"
},
{
"type": "link",
"title": "Конфигурация push",
"action": "/page.htm?pushingbox",
"class": "btn btn-block btn-success"
},
{
"type": "link",
"title": "Скачать приложение IoT Manager",
"action": "https://github.com/DmitryBorisenko33/esp8266_iot-manager_modules_firmware/raw/master/iot_manager/IoT%20Manager%201.5.5.apk",
"class": "btn btn-block btn-success"
}
]
}

Binary file not shown.

BIN
data_new/js/function.js.gz Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
data_new/mode-css.js.gz Normal file

Binary file not shown.

BIN
data_new/mode-html.js.gz Normal file

Binary file not shown.

Binary file not shown.

73
data_new/mqtt.json Normal file
View File

@@ -0,0 +1,73 @@
{
"configs": [
"/config.setup.json"
],
"class":"col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6",
"content": [
{
"type": "h5",
"title": "{{SSDP}}",
"class":"alert-warning"
},
{
"type": "h4",
"title": "Server name:"
},
{
"type": "input",
"title": "",
"name":"1",
"state": "{{mqttServer}}"
},
{
"type": "h4",
"title": "Port:"
},
{
"type": "input",
"title": "",
"name":"2",
"state": "{{mqttPort}}"
},
{
"type": "h4",
"title": "User name:"
},
{
"type": "input",
"title": "",
"name":"3",
"state": "{{mqttUser}}"
},
{
"type": "h4",
"title": "Password:"
},
{
"type": "input",
"title": "",
"name":"4",
"state": "{{mqttPass}}"
},
{
"type":"h3",
"name":"my-block",
"style":"position:fixed;top:30%;left:50%;width:400px;margin-left:-200px;text-align:center;",
"class":"hidden"
},
{
"type": "button",
"title":"Сохранить и проверить соединение",
"action": "mqttSave?mqttServer=[[1]]&mqttPort=[[2]]&mqttUser=[[3]]&mqttPass=[[4]]",
"response":"[[my-block]]",
"class": "btn btn-block btn-success",
"style": "width:100%;display:inline"
},
{
"type": "link",
"title": "Главная",
"action": "/page.htm?index",
"class": "btn btn-block btn-danger btn-sm"
}
]
}

BIN
data_new/page.htm.gz Normal file

Binary file not shown.

92
data_new/push.json Normal file
View File

@@ -0,0 +1,92 @@
{
"configs": [
"/config.setup.json"
],
"class":"col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6",
"content": [
{
"type": "h5",
"title": "{{SSDP}}",
"class":"alert-warning"
},
{
"type": "h4",
"title": "Host name:"
},
{
"type": "input",
"title": "",
"name":"1",
"state": "{{pushHost}}"
},
{
"type": "h4",
"title": "Port:"
},
{
"type": "input",
"title": "",
"name":"2",
"state": "{{pushPort}}"
},
{
"type": "h4",
"title": "Fingerprint:"
},
{
"type": "input",
"title": "",
"name":"3",
"state": "{{pushFingerprint}}"
},
{
"type": "h4",
"title": "Access Token:"
},
{
"type": "input",
"title": "",
"name":"4",
"state": "{{pushAccessToken}}"
},
{
"type":"h3",
"name":"my-block",
"style":"position:fixed;top:30%;left:50%;width:400px;margin-left:-200px;text-align:center;",
"class":"hidden"
},
{
"type": "button",
"title":"Сохранить и проверить соединение",
"action": "pushDate?pushHost=[[1]]&pushPort=[[2]]&pushFingerprint=[[3]]&pushAccessToken=[[4]]",
"response":"[[my-block]]",
"class": "btn btn-block btn-success",
"style": "width:100%;display:inline"
},
{
"type": "hr"
},
{
"type": "checkbox",
"name":"start-push",
"title": "Отправлять push при включении устройства",
"action": "startPush?status=[[start-push]]",
"state": "{{startPush}}"
},
{
"type": "hr"
},
{
"type": "link",
"title": "Перезагрузить устройство",
"action": "javascript:if(confirm(renameBlock(jsonResponse,'Перезагрузить?'))){send_request(this,'/restart?device=ok');}",
"class": "btn btn-block btn-warning"
},
{
"type": "link",
"title": "Главная",
"action": "/page.htm?index",
"class": "btn btn-block btn-danger btn-sm"
}
]
}

46
data_new/pushingbox.json Normal file
View File

@@ -0,0 +1,46 @@
{
"configs": [
"/config.setup.json"
],
"class":"col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6",
"content": [
{
"type": "h5",
"title": "{{SSDP}}",
"class":"alert-warning"
},
{
"type": "h4",
"title": "Device id:"
},
{
"type": "input",
"title": "",
"name":"1",
"state": "{{pushingbox_id}}"
},
{
"type": "button",
"title":"Сохранить",
"action": "pushingboxDate?pushingbox_id=[[1]]",
"class": "btn btn-block btn-success",
"style": "width:100%;display:inline"
},
{
"type": "hr"
},
{
"type": "link",
"title": "Перезагрузить устройство",
"action": "javascript:if(confirm(renameBlock(jsonResponse,'Перезагрузить?'))){send_request(this,'/restart?device=ok');}",
"class": "btn btn-block btn-warning"
},
{
"type": "link",
"title": "Главная",
"action": "/page.htm?index",
"class": "btn btn-block btn-danger btn-sm"
}
]
}

31
data_new/scenario.all.txt Normal file
View File

@@ -0,0 +1,31 @@
button1 = 1
buttonSet 2 1
buttonSet 3 1
pwmSet 2 1024
end
button1 = 0
buttonSet 2 0
buttonSet 3 0
pwmSet 2 0
end
analog > value1
buttonSet 4 1
end
button5 = 1
timerStart 1 value2 sec
end
button5 = 0
timerStart 2 value2 sec
end
timer1 = 0
buttonSet 6 1
end
timer2 = 0
buttonSet 6 0
end
switch1 = 1
textSet 1 закрыто-time
end
switch1 = 0
textSet 1 открыто-time
end

154
data_new/setup.json Normal file
View File

@@ -0,0 +1,154 @@
{
"configs": [
"/config.setup.json"
],
"title": "Конфигурация",
"class":"col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6",
"content": [
{
"type": "h5",
"title": "{{SSDP}}",
"class":"alert-warning"
},
{
"type": "link",
"title": "Главная",
"action": "/",
"class": "btn btn-block btn-danger"
},
{
"type": "hr"
},
{
"type": "h2",
"title": "Имя устройства"
},
{
"type": "input",
"title": "Имя устройства",
"name":"ssdp",
"state": "{{SSDP}}",
"pattern": "[0-9a-zA-Zа-яА-Я.\\- ]{1,20}"
},
{
"type": "button",
"title": "Сохранить",
"action": "ssdp?ssdp=[[ssdp]]",
"class": "btn btn-block btn-success"
},
{
"type": "hr"
},
{
"type": "h2",
"title": "Подключение к Wi-Fi роутеру"
},
{
"type": "input",
"title":"Сеть",
"name":"ssid",
"state": "{{ssid}}"
},
{
"type": "password",
"title": "Введите пароль",
"name":"ssidPass",
"state": "{{password}}",
"pattern": ".{8,20}"
},
{
"type": "button",
"title": "Сохранить",
"class": "btn btn-block btn-success",
"action": "ssid?ssid=[[ssid]]&password=[[ssidPass]]"
},
{
"type": "hr"
},
{
"type": "h2",
"title": "Временная зона GMT"
},
{
"type": "input",
"title": "{{LangSpace}}",
"name":"timeZone",
"state": "{{timezone}}",
"pattern": "[0-9-]{1,3}"
},
{
"type": "button",
"module":"",
"title": "Сохранить",
"class": "btn btn-block btn-success",
"action": "timeZone?timeZone=[[timeZone]]"
},
{
"type": "link",
"title": "Автоопределение зоны",
"action": "javascript:set_time_zone(this);",
"class": "btn btn-block btn-primary"
},
{
"type": "time",
"name":"times1",
"title": "На устройстве сейчас",
"state":"{{time}}"
},
{
"type": "button",
"response":"[[&#116imes1]]",
"title": "Синхронизировать",
"class": "btn btn-block btn-primary",
"action": "Time"
},
{
"type": "hr"
},
{
"type": "h2",
"title": "Точка доступа"
},
{
"type": "text",
"title": "После того как устройство подключается к роутеру, его Wi-Fi исчезнет.",
"class": "alert alert-warning",
"style": "width:45%;float:right;"
},
{
"type": "input",
"title": "Имя WI-FI сети",
"name":"ssidap",
"state": "{{ssidAP}}",
"style": "width:50%;display:inline",
"pattern": ".{1,20}"
},
{
"type": "password",
"title": "Пароль",
"name":"ssidApPass",
"state": "{{passwordAP}}",
"style": "width:50%;display:inline",
"pattern": ".{8,20}"
},
{
"type": "button",
"title": "Сохранить",
"action": "ssidap?ssidAP=[[ssidap]]&passwordAP=[[ssidApPass]]",
"class": "btn btn-block btn-success",
"style": "width:50%;display:inline"
},
{
"type": "hr"
},
{
"type": "hr"
},
{
"type": "link",
"title": "Перезагрузить устройство",
"action": "javascript:if(confirm(renameBlock(jsonResponse,'Перезагрузить?'))){send_request(this,'/restart?device=ok');}",
"class": "btn btn-block btn-warning"
}
]
}

57
data_new/soket.json Normal file
View File

@@ -0,0 +1,57 @@
{
"configs": [
"/config.live.json",
"/config.option.json",
"/config.setup.json",
"/lang/lang.ru.json",
"socket {{ip}}:81/"
],
"title": "Главная",
"class":"col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6",
"content": [
{
"type": "h5",
"title": "{{SSDP}}",
"class":"alert-warning"
},
{
"type": "h4",
"title": "Module tank level:",
"style": "width:80%;float:left;"
},
{
"type": "h4",
"title": "{{module_tank_level_s}}",
"style": "width:20%;float:right;"
},
{
"type": "h4",
"title": "Module analog:",
"style": "width:80%;float:left;"
},
{
"type": "h4",
"title": "{{module_analog_s}}",
"style": "width:20%;float:right;"
},
{
"type": "h4",
"title": "Module ds18b20:",
"style": "width:80%;float:left;"
},
{
"type": "h4",
"title": "{{module_ds18b20_s}}",
"style": "width:20%;float:right;"
},
{
"type": "link",
"title": "Главная",
"action": "/page.htm?index",
"class": "btn btn-block btn-danger btn-sm",
"style": "width:100%;float:right;"
}
]
}

View File

@@ -0,0 +1,12 @@
{
"id" : "",
"page" : "",
"widget" : "anydata",
"class1": "col-xs-4 text-center",
"class2": "stable",
"style2": "font-size:12px;float:center;",
"class3":"stable",
"style3": "font-size:25px;float:center;font-weight:bold;",
"descr" : "",
"topic" : ""
}

View File

@@ -0,0 +1,12 @@
{
"id" : "",
"page" : "",
"widget" : "anydata",
"class1" : "item col-xs-12 text-center",
"class2": "ballanced",
"style2": "font-size:20px;float:left;font-weight:bold;",
"class3":"ballanced",
"style3": "font-size:17px;float:right;",
"descr" : "",
"topic" : ""
}

View File

@@ -0,0 +1,18 @@
{
"id": "",
"pageId":"",
"page": "",
"widget": "simple-btn",
"class1": "col-xs-4 text-center",
"class2": "ballanced",
"style2": "font-size:15px;float:left;font-weight:bold;",
"topic": "",
"class3": "button button-block",
"style3": "float:right;",
"widgetConfig": {
"fill": "#F5F5F5",
"fillPressed": "#4169E1",
"title": "-",
"delay":500
}
}

13
data_new/viget.chart.json Normal file
View File

@@ -0,0 +1,13 @@
{
"id" : "",
"pageId": "",
"widget" : "chart",
"topic" : "",
"widgetConfig": {
"maxCount": 200,
"type": "line",
"height": 200
}
}

View File

@@ -0,0 +1,23 @@
{
"id": "",
"page": "",
"pageId": "",
"widget": "fillgauge",
"descr": "",
"class2": "text-center ballanced",
"style2": "font-size:25px;font-weight:bold;padding-top:10px;padding-bottom:10px;",
"class3" : "text-center",
"style3": "padding-top:10px;padding-bottom:10px;",
"topic": "",
"width": "250px",
"height": "250px",
"widgetConfig": {
"circleColor": "#228B22",
"textColor": "#FFFFFF",
"waveTextColor": "#050000",
"waveColor": "#40E0D0",
"circleThickness": 0.05,
"textVertPosition": 0.5,
"waveAnimateTime": 500
}
}

18
data_new/viget.gauge.json Normal file
View File

@@ -0,0 +1,18 @@
{
"id" : "",
"pageId": "",
"widget" : "gauge",
"topic" : "",
"class1" : "item no-border no-padding text-center",
"descr" : "",
"widgetConfig" : {
"type" : "full",
"cap" : "round",
"append" : "",
"size" : 300,
"thick" : 20,
"maximum": 1024,
"color" : "#11c1f3",
"backgroundColor": "rgba(0,0,0, 0.2)"
}
}

16
data_new/viget.led.json Normal file
View File

@@ -0,0 +1,16 @@
{
"id": "",
"pageId": "",
"descr": "",
"class1": "col-xs-3 text-center",
"page": "",
"widget": "steel",
"topic": "",
"widgetConfig": {
"width": 60,
"height": 60,
"type": "Led",
"blink": false,
"LedColor": "RED_LED"
}
}

13
data_new/viget.range.json Normal file
View File

@@ -0,0 +1,13 @@
{
"id": "",
"page": "",
"descr": "",
"widget": "range",
"class3": "ballanced",
"style3": "font-size:25px;float:left;font-weight:bold;",
"topic": "",
"widgetConfig": {
"maxValue": 1023,
"minValue": 0
}
}

View File

@@ -0,0 +1,13 @@
{
"id" : "1",
"page" : "",
"pageId":"",
"widget" : "anydata",
"class1" : "item rounded text-center no-padding",
"class2": "ballanced",
"style2": "",
"class3":"ballanced",
"style3": "font-size:10px;float:right;",
"descr" : "",
"topic" : ""
}

View File

@@ -0,0 +1,15 @@
{
"id": "",
"page": "",
"pageId": "",
"widget": "steel",
"topic": "/DS",
"widgetConfig": {
"width": "auto",
"height": 150,
"type": "Linear",
"titleString": "Спальня",
"unitString": "°C",
"threshold": 30
}
}

View File

@@ -0,0 +1,11 @@
{
"id": "",
"page": "",
"pageId": "",
"widget": "toggle",
"descrStyle": "font-size:20px;float:left;font-weight:bold;",
"descrStyleOff": "font-size:20px;float:left;",
"color": "#8997ff",
"descr": "",
"topic": ""
}

BIN
data_new/worker-html.js.gz Normal file

Binary file not shown.

View File

@@ -0,0 +1,197 @@
/*
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 <lwip/sockets.h>
#include <lwip/netdb.h>
#include <errno.h>
#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;
}

View File

@@ -0,0 +1,92 @@
/*
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 <WiFi.h>
#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_ */

View File

@@ -0,0 +1,261 @@
/* 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 <esp32-hal-log.h>
#include <lwip/sockets.h>
#include <lwip/err.h>
#include <lwip/sockets.h>
#include <lwip/sys.h>
#include <lwip/netdb.h>
#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;
}

View File

@@ -0,0 +1,37 @@
/* 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

View File

@@ -0,0 +1,78 @@
#include "set.h"
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
Serial.println("--------------started----------------");
//--------------------------------------------------------------
SPIFFS.begin();
configSetup = readFile("config.json", 4096);
Serial.println(configSetup);
jsonWrite(configJson, "SSDP", jsonRead(configSetup, "SSDP"));
jsonWrite(configJson, "lang", jsonRead(configSetup, "lang"));
Serial.println("SPIFFS_init");
#ifdef ESP32
uint32_t chipID_u = ESP.getEfuseMac();
chipID = String(chipID_u);
jsonWrite(configSetup, "chipID", chipID);
#endif
#ifdef ESP8266
chipID = String( ESP.getChipId() ) + "-" + String( ESP.getFlashChipId());
jsonWrite(configSetup, "chipID", chipID);
#endif
prex = prefix + "/" + chipID;
Serial.println(chipID);
//--------------------------------------------------------------
CMD_init();
Serial.println("[V] CMD_init");
//--------------------------------------------------------------
All_init();
Serial.println("[V] All_init");
//--------------------------------------------------------------
WIFI_init();
Serial.println("[V] WIFI_init");
//--------------------------------------------------------------
Web_server_init();
Serial.println("[V] Web_server_init");
//--------------------------------------------------------------
Time_Init();
Serial.println("[V] Time_Init");
//--------------------------------------------------------------
MQTT_init();
Serial.println("[V] MQTT_init");
//--------------------------------------------------------------
getMemoryLoad("[i] After loading");
ts.add(TEST, 1000, [&](void*) {
//getMemoryLoad("[i] Periodic check");
}, nullptr, true);
}
void loop() {
#ifdef OTA_enable
ArduinoOTA.handle();
#endif
#ifdef WS_enable
ws.cleanupClients();
#endif
handleMQTT();
handleCMD_loop();
handleButton();
handleScenario();
ts.update();
}

279
main.ino Normal file
View File

@@ -0,0 +1,279 @@
//=============================================JSON===========================================================
// ------------- Чтение значения json
String jsonRead(String &json, String name) {
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(json);
return root[name].as<String>();
}
// ------------- Чтение значения json
int jsonReadtoInt(String &json, String name) {
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(json);
return root[name];
}
// ------------- Запись значения json String
String jsonWrite(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 jsonWrite(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 jsonWrite(String &json, String name, float volume) {
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(json);
root[name] = volume;
json = "";
root.printTo(json);
return json;
}
//=============================================CONFIG===========================================================
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;
}
}
//============================================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);
jsonWrite(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";
}
// ------------- Чтение строки из файла
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('\r\n'); //'\r'
}
//return "|-|-|";
configFile.close();
}
//=======================================УПРАВЛЕНИЕ ВИДЖЕТАМИ MQTT======================================================================
void sendCONFIG(String topik, String widgetConfig, String key, String date) {
yield();
topik = prefix + "/" + 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.publish(MQTT::Publish(topik, t).set_qos(1));
yield();
}
//=============================================================================================================
#ifdef led_status
void led_blink(int pin, int fq, String blink_satus) {
pinMode(pin, OUTPUT);
if (blink_satus == "on") tone(pin, fq);
if (blink_satus == "off") {
noTone(pin);
digitalWrite(pin, HIGH);
}
}
#endif
void getMemoryLoad(String text) {
#ifdef ESP8266
int all_memory = 53312;
#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.println(String(memory_load) + "%");
}
//esp32 full memory = 362868
//esp8266 full memory = 53312

370
mqtt.ino Normal file
View File

@@ -0,0 +1,370 @@
//===============================================ИНИЦИАЛИЗАЦИЯ================================================
void MQTT_init() {
server.on("/mqttSave", HTTP_GET, [](AsyncWebServerRequest * request) {
if (request->hasArg("mqttServer")) {
jsonWrite(configSetup, "mqttServer", request->getParam("mqttServer")->value());
}
if (request->hasArg("mqttPort")) {
int port = (request->getParam("mqttPort")->value()).toInt();
jsonWrite(configSetup, "mqttPort", port);
}
if (request->hasArg("mqttUser")) {
jsonWrite(configSetup, "mqttUser", request->getParam("mqttUser")->value());
}
if (request->hasArg("mqttPass")) {
jsonWrite(configSetup, "mqttPass", request->getParam("mqttPass")->value());
}
saveConfig();
client.disconnect();
MQTT_Connecting(false);
String tmp = "{}";
jsonWrite(tmp, "title", "<button class=\"close\" onclick=\"toggle('my-block')\">×</button>" + stateMQTT());
jsonWrite(tmp, "class", "pop-up");
request->send(200, "text/text", tmp); // отправляем ответ о выполнении
});
//проверка подключения к серверу
ts.add(WIFI_MQTT_CONNECTION_CHECK, wifi_mqtt_reconnecting, [&](void*) {
if (WiFi.status() == WL_CONNECTED) {
Serial.println("[V] WiFi-ok");
if (client.connected()) {
Serial.println("[V] MQTT-ok");
} else {
MQTT_Connecting(true);
}
} else {
Serial.println("[E] Lost WiFi connection");
ts.remove(WIFI_MQTT_CONNECTION_CHECK);
StartAPMode();
}
}, nullptr, true);
}
//================================================ОБНОВЛЕНИЕ====================================================
void handleMQTT() {
if (WiFi.status() == WL_CONNECTED) {
if (client.connected()) {
client.loop();
}
}
}
//===============================================ПОДКЛЮЧЕНИЕ========================================================
void MQTT_Connecting(boolean out_date_send) {
String mqtt_server = jsonRead(configSetup, "mqttServer");
if ((mqtt_server != "")) {
static boolean first = true;
if (!first) Serial.println("[E] Lost MQTT connection, start reconnecting");
first = false;
//ssl//espClient.setCACert(local_root_ca1);
client.setServer(mqtt_server.c_str(), jsonReadtoInt(configSetup, "mqttPort"));
// подключаемся к MQTT серверу
if (WiFi.status() == WL_CONNECTED) {
if (!client.connected()) {
Serial.println("[V] Connecting to MQTT server commenced");
//busy = true;
if (client.connect(chipID.c_str(), jsonRead(configSetup, "mqttUser").c_str(), jsonRead(configSetup, "mqttPass").c_str())) {
Serial.println("[V] MQTT connected");
client.setCallback(callback);
client.subscribe(prefix.c_str()); // Для приема получения HELLOW и подтверждения связи
client.subscribe((prefix + "/" + chipID + "/+/control").c_str()); // Подписываемся на топики control
client.subscribe((prefix + "/" + chipID + "/order").c_str()); // Подписываемся на топики order
//client.subscribe((prefix + "/" + chipID + "/test").c_str()); //Для приема получения work и подтверждения связи (для приложения mqtt IOT MQTT Panel)
/* String tmp_line = id_of_other_device;
while (tmp_line.length() != 0) {
String id = selectToMarker(tmp_line, ","); //2058631-1589487 1
id = selectFromMarkerToMarker(id, " ", 0);
client.subscribe((prefix + "/" + id + "/+/status").c_str(), 0);
Serial.println("->subscribed to device, id: " + id);
tmp_line = deleteBeforeDelimiter(tmp_line, ",");
}*/
client.subscribe((prefix + "/ids").c_str()); // Подписываемся на топики ids
sendMQTT("test", "work");
Serial.println("[V] Callback set, subscribe done");
//busy = false;
if (out_date_send) outcoming_date(); //отправляем данные в виджеты
} else {
//Serial.println(stateMQTT());
Serial.println("[E] try again in " + String(wifi_mqtt_reconnecting / 1000) + " sec");
}
}
}
} else {
Serial.println("[E] No date for MQTT connection");
}
}
//=====================================================ВХОДЯЩИЕ ДАННЫЕ========================================================
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 (str == "work") outcoming_date(); //Для приема получения work и подтверждения связи (для приложения mqtt IOT MQTT Panel)
//превращает название топика в команду, а значение в параметр команды
if (topic_str.indexOf("control") > 0) { //IoTmanager/800324-1458415/RelaySet1/control 1 /IoTmanager/9139530-1458400/RelaySet1/control -> 1
//Serial.println(topic_str);
String topic = selectFromMarkerToMarker(topic_str, "/", 3); //RelaySet1
String number = selectToMarkerLast(topic, "Set"); //1
topic.replace(number, ""); //RelaySet
String final_line = topic + " " + number + " " + str; //RelaySet 1 1
//Serial.println(final_line);
order_loop += final_line + ",";
}
if (topic_str.indexOf("order") > 0) {
str.replace("_", " ");
//Serial.println(str);
order_loop += str + ",";
}
}
//данные которые отправляем при подключении или отбновлении страницы
void outcoming_date() {
//busy = true;
sendAllWigets();
sendAllData();
if (flagLoggingAnalog) sendLogData("log.analog.txt", "loganalog");
if (flagLoggingPh) sendLogData("log.ph.txt", "logph");
if (flagLoggingDallas) sendLogData("log.dallas.txt", "logdallas");
if (flagLoggingLevel) sendLogData("log.level.txt", "loglevel");
Serial.println("[V] Sending all date to iot manager completed");
//busy = false;
}
//======================================CONFIG==================================================
///IoTmanager/2058631-1589487/config {----viget----}
///sendMQTT("config", data);
boolean sendMQTT(String end_of_topik, String data) {
String topik = prefix + "/" + chipID + "/" + end_of_topik;
boolean send_status = client.beginPublish(topik.c_str(), data.length(), false);
client.print(data);
client.endPublish();
return send_status;
}
//======================================STATUS==================================================
///IoTmanager/2058631-1589487/rel1/status {"status":"1"}
///sendSTATUS(topic, state)
void sendSTATUS(String topik, String state) {
topik = prefix + "/" + chipID + "/" + topik + "/" + "status";
String json_ = "{}";
jsonWrite(json_, "status", state);
//long st_time = millis();
int send_status = client.publish (topik.c_str(), json_.c_str(), false);
//long end_time = millis();
//Serial.println("send status = " + String(send_status) + ", timeout = " + String(end_time - st_time));
}
/*void sendSTATUS(String topik, String state, String type, String param) {
topik = prefix + "/" + chipID + "/" + topik + "/" + "status";
String json_ = "{}";
jsonWrite(json_, "status", state);
jsonWrite(json_, type, param);
//long st_time = millis();
int send_status = client.publish (topik.c_str(), json_.c_str(), false);
//long end_time = millis();
//Serial.println("send status = " + String(send_status) + ", timeout = " + String(end_time - st_time));
}*/
//======================================CONTROL==================================================
///IoTmanager/2058631-1589487/rel1/control 1
void sendCONTROL(String id, String topik, String state) {
String all_line = prefix + "/" + id + "/" + topik + "/control";
//long st_time = millis();
int send_status = client.publish (all_line.c_str(), state.c_str(), false);
//long end_time = millis();
//Serial.println("send control = " + String(send_status) + ", timeout = " + String(end_time - st_time));
}
//=====================================================ОТПРАВЛЯЕМ ВИДЖЕТЫ========================================================
void sendAllWigets() {
if (all_vigets != "") {
int counter = 0;
String line;
int psn_1 = 0;
int psn_2;
do {
psn_2 = all_vigets.indexOf("\r\n", psn_1);
line = all_vigets.substring(psn_1, psn_2);
jsonWrite(line, "id", String(counter));
counter++;
sendMQTT("config", line);
Serial.println("[V] " + line);
psn_1 = psn_2 + 1;
} while (psn_2 + 2 < all_vigets.length());
getMemoryLoad("[i] after send all vigets");
}
}
//=====================================================ОТПРАВЛЯЕМ ДАННЫЕ В ВИДЖЕТЫ ПРИ ОБНОВЛЕНИИ СТРАНИЦЫ========================================================
void sendAllData() { //берет строку json и ключи превращает в топики а значения колючей в них посылает
String current_config = configJson; //{"SSDP":"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("}", ""); //"SSDP":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1"
current_config += ","; //"SSDP":"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 != ssdpS && topic != "lang" && topic != "ip" && topic.indexOf("_in") < 0) {
sendSTATUS(topic, state);
//Serial.println("-->" + topic + " " + state);
}
current_config = deleteBeforeDelimiter(current_config, ",");
}
}
void sendLogData(String file, String topic) {
String log_date = readFile(file, 5000) + "\r\n";
getMemoryLoad("[i] after send log date");
log_date.replace("\r\n", "\n");
log_date.replace("\r", "\n");
while (log_date.length() != 0) {
String tmp = selectToMarker (log_date, "\n");
//sendSTATUS(topic, selectFromMarkerToMarker(tmp, " ", 2));
if (tmp != "") sendSTATUS(topic, tmp);
log_date = deleteBeforeDelimiter(log_date, "\n");
}
}
String stateMQTT() {
int state = client.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 (jsonRead(configSetup, "scenario") == "1") {
//String all_text = readFile("scenario.all.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.subscribe((prefix + "/" + 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 (jsonRead(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.publish ((prefix + "/" + id).c_str(), "CHECK", true));
}
all_text = deleteBeforeDelimiter(all_text, "\n");
}
}
}*/
/*
//-----------------------------------------------------------------------------------------------------------------------------------------------
//jsonWrite(tmp, "status", "1");
String current_config = configJson; //{"SSDP":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1"}
current_config.replace("{", "");
current_config.replace("}", ""); //"SSDP":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1"
current_config += ","; //"SSDP":"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 (viget.lastIndexOf(topic) > 0) {
jsonWrite(tmp, "status", state);
//}
current_config = deleteBeforeDelimiter(current_config, ",");
}
//-------------------------------------------------------------------------------------------------------------------------------------------------
*/

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