Merge pull request #10 from Mit4el/ver4dev

Модуль ftp
This commit is contained in:
2023-06-25 19:05:27 +03:00
committed by GitHub
41 changed files with 6105 additions and 152 deletions

View File

@@ -0,0 +1,97 @@
#include "Global.h"
#include "classes/IoTItem.h"
#include <SimpleFTPServer.h>
#define DEFAULT_STORAGE_TYPE_ESP32 STORAGE_LITTLEFS
class FTPModule : public IoTItem
{
private:
String login;
String pass;
FtpServer ftpSrv; // set #define FTP_DEBUG in ESP8266FtpServer.h to see ftp verbose on serial
public:
FTPModule(String parameters) : IoTItem(parameters)
{
jsonRead(parameters, F("login"), login);
jsonRead(parameters, F("pass"), pass);
ftpSrv.setCallback(FTPModule::_callback);
ftpSrv.setTransferCallback(FTPModule::_transferCallback);
ftpSrv.begin(login.c_str(), pass.c_str(), "Welcome IoTManager FTP server"); // username, password for ftp. (default 21, 50009 for PASV)
SerialPrint("I", "FtpServer " + (String)_id, "begin");
}
void loop()
{
ftpSrv.handleFTP();
}
static void _callback(FtpOperation ftpOperation, unsigned int freeSpace, unsigned int totalSpace)
{
switch (ftpOperation)
{
case FTP_CONNECT:
SerialPrint("i", "FTP", F("Connected!"));
break;
case FTP_DISCONNECT:
SerialPrint("i", "FTP", F("Disconnected!"));
break;
case FTP_FREE_SPACE_CHANGE:
SerialPrint("i", "FTP", "Free space change, free " + (String)freeSpace + " of " + (String)totalSpace);
break;
default:
break;
}
}
static void _transferCallback(FtpTransferOperation ftpOperation, const char *name, unsigned int transferredSize)
{
switch (ftpOperation)
{
case FTP_UPLOAD_START:
SerialPrint("i","FTP", F("Upload start!"));
break;
case FTP_UPLOAD:
SerialPrint("i","FTP", "Upload of file " + (String)name + " byte " + (String)transferredSize);
break;
case FTP_TRANSFER_STOP:
SerialPrint("i","FTP", F("Finish transfer!"));
break;
case FTP_TRANSFER_ERROR:
SerialPrint("E","FTP", F("Transfer error!"));
break;
default:
break;
}
/* FTP_UPLOAD_START = 0,
* FTP_UPLOAD = 1,
*
* FTP_DOWNLOAD_START = 2,
* FTP_DOWNLOAD = 3,
*
* FTP_TRANSFER_STOP = 4,
* FTP_DOWNLOAD_STOP = 4,
* FTP_UPLOAD_STOP = 4,
*
* FTP_TRANSFER_ERROR = 5,
* FTP_DOWNLOAD_ERROR = 5,
* FTP_UPLOAD_ERROR = 5
*/
}
~FTPModule(){};
};
void *getAPI_FTPModule(String subtype, String param)
{
if (subtype == F("ftp"))
{
return new FTPModule(param);
}
//}
return nullptr;
}

View File

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

View File

@@ -49,6 +49,7 @@
"defActive": false,
"usedLibs": {
"esp32_4mb": [],
"esp32s2_4mb": [],
"esp8266_4mb": [],
"esp8266_1mb": [],
"esp8266_1mb_ota": [],

View File

@@ -58,7 +58,7 @@
"int": "Количество секунд между опросами датчика."
}
},
"defActive": true,
"defActive": false,
"usedLibs": {
"esp32_4mb": [
"https://github.com/jbechter/arduino-onewire-DS2423",

View File

@@ -11,126 +11,198 @@
#include <Wire.h>
#include <Adafruit_INA219.h>
#include <map>
Adafruit_INA219 ina219;
// Adafruit_INA219 ina219;
// Структура для хранения данных с датчика
struct Ina219Value
{
float shuntvoltage = 0;
float busvoltage = 0;
};
// глобальные списки необходимы для хранения данных, полученных разными датчиками из модуля. Ключ - адрес
std::map<uint8_t, Ina219Value *> ina219ValueArray;
float shuntvoltage = 0;
float busvoltage = 0;
float current_mA = 0;
float loadvoltage = 0;
float power_mW = 0;
// глобальные списки необходимы для хранения объектов используемых разными датчиками из модуля. Ключ - адрес
std::map<uint8_t, Adafruit_INA219 *> ina219Array;
// shuntvoltage = ina219.getShuntVoltage_mV(); // Получение напряжение на шунте
// busvoltage = ina219.getBusVoltage_V(); // Получение значение напряжения V
// current_mA = ina219.getCurrent_mA(); // Получение значение тока в мА
// power_mW = ina219.getPower_mW(); // Получение значение мощности
// loadvoltage = busvoltage + (shuntvoltage / 1000); // Расчет напряжение на нагрузки
// Функция инициализации библиотечного класса, возвращает Единстрвенный указать на библиотеку
Adafruit_INA219 *instanceIna219(uint8_t ADDR)
{
/** default I2C address **/
if (ADDR == 0)
ADDR = INA219_ADDRESS; // 1000000 (A0+A1=GND)
class Ina219loadvoltage : public IoTItem {
public:
Ina219loadvoltage(String parameters) : IoTItem(parameters) {
// учитываем, что библиотека может работать с несколькими линиями на разных пинах, поэтому инициируем библиотеку, если линия ранее не использовалась
if (ina219Array.find(ADDR) == ina219Array.end())
{
ina219Array[ADDR] = new Adafruit_INA219((uint8_t)ADDR);
ina219Array[ADDR]->begin();
ina219ValueArray[ADDR] = new Ina219Value;
}
return ina219Array[ADDR];
}
// Wire.begin(2,0); // Инициализация шины I2C для модуля E01
/*
float shuntvoltage = 0;
float busvoltage = 0;
float current_mA = 0;
float loadvoltage = 0;
float power_mW = 0;
*/
// shuntvoltage = ina219.getShuntVoltage_mV(); // Получение напряжение на шунте
// busvoltage = ina219.getBusVoltage_V(); // Получение значение напряжения V
// current_mA = ina219.getCurrent_mA(); // Получение значение тока в мА
// power_mW = ina219.getPower_mW(); // Получение значение мощности
// loadvoltage = busvoltage + (shuntvoltage / 1000); // Расчет напряжение на нагрузки
class Ina219loadvoltage : public IoTItem
{
private:
uint8_t _addr = 0;
public:
Ina219loadvoltage(String parameters) : IoTItem(parameters)
{
String sAddr;
jsonRead(parameters, "addr", sAddr);
if (sAddr == "")
scanI2C();
else
_addr = hexStringToUint8(sAddr);
}
void doByInterval() {
loadvoltage = busvoltage + (shuntvoltage / 1000);
value.valD = loadvoltage;
regEvent(value.valD, "Ina219loadvoltage");
void doByInterval()
{
value.valD = ina219ValueArray[_addr]->busvoltage + (ina219ValueArray[_addr]->shuntvoltage / 1000);
regEvent(value.valD, "Ina219loadvoltage");
}
~Ina219loadvoltage(){};
};
class Ina219busvoltage : public IoTItem {
public:
Ina219busvoltage(String parameters) : IoTItem(parameters) {
class Ina219busvoltage : public IoTItem
{
private:
uint8_t _addr = 0;
// Wire.begin(2,0); // Инициализация шины I2C для модуля E01
public:
Ina219busvoltage(String parameters) : IoTItem(parameters)
{
String sAddr;
jsonRead(parameters, "addr", sAddr);
if (sAddr == "")
scanI2C();
else
_addr = hexStringToUint8(sAddr);
}
void doByInterval() {
busvoltage = ina219.getBusVoltage_V();
value.valD = busvoltage;
regEvent(value.valD, "Ina219busvoltage");
void doByInterval()
{
ina219ValueArray[_addr]->busvoltage = instanceIna219(_addr)->getBusVoltage_V();
value.valD = ina219ValueArray[_addr]->busvoltage;
regEvent(value.valD, "Ina219busvoltage");
}
~Ina219busvoltage(){};
};
class Ina219shuntvoltage : public IoTItem
{
private:
uint8_t _addr = 0;
class Ina219curr : public IoTItem {
public:
Ina219curr(String parameters) : IoTItem(parameters) {
// Wire.begin(2,0); // Инициализация шины I2C для модуля E01
public:
Ina219shuntvoltage(String parameters) : IoTItem(parameters)
{
String sAddr;
jsonRead(parameters, "addr", sAddr);
if (sAddr == "")
scanI2C();
else
_addr = hexStringToUint8(sAddr);
}
void doByInterval() {
current_mA = ina219.getCurrent_mA();
value.valD = current_mA;
regEvent(value.valD, "Ina219curr");
}
~Ina219curr(){};
};
class Ina219shuntvoltage : public IoTItem {
public:
Ina219shuntvoltage(String parameters) : IoTItem(parameters) {
// Wire.begin(2,0); // Инициализация шины I2C для модуля E01
}
void doByInterval() {
shuntvoltage = ina219.getShuntVoltage_mV();
value.valD = shuntvoltage;
regEvent(value.valD, "Ina219shuntvoltage");
void doByInterval()
{
ina219ValueArray[_addr]->shuntvoltage = instanceIna219(_addr)->getShuntVoltage_mV();
value.valD = ina219ValueArray[_addr]->shuntvoltage;
regEvent(value.valD, "Ina219shuntvoltage");
}
~Ina219shuntvoltage(){};
};
class Power_mW : public IoTItem {
public:
Power_mW(String parameters) : IoTItem(parameters) {
class Ina219curr : public IoTItem
{
private:
uint8_t _addr = 0;
// Wire.begin(2,0); // Инициализация шины I2C для модуля E01
public:
Ina219curr(String parameters) : IoTItem(parameters)
{
String sAddr;
jsonRead(parameters, "addr", sAddr);
if (sAddr == "")
scanI2C();
else
_addr = hexStringToUint8(sAddr);
}
void doByInterval() {
power_mW = ina219.getPower_mW();
value.valD = power_mW;
regEvent(value.valD, "Ina219power"); // TODO: найти способ понимания ошибки получения данных
void doByInterval()
{
value.valD = instanceIna219(_addr)->getCurrent_mA();
regEvent(value.valD, "Ina219curr");
}
~Power_mW(){};
~Ina219curr(){};
};
void* getAPI_Ina219(String subtype, String param) {
if (subtype == F("Ina219curr")) {
ina219.begin();
class Ina219Power_mW : public IoTItem
{
private:
uint8_t _addr = 0;
public:
Ina219Power_mW(String parameters) : IoTItem(parameters)
{
String sAddr;
jsonRead(parameters, "addr", sAddr);
if (sAddr == "")
scanI2C();
else
_addr = hexStringToUint8(sAddr);
}
void doByInterval()
{
value.valD = instanceIna219(_addr)->getPower_mW();
regEvent(value.valD, "Ina219power"); // TODO: найти способ понимания ошибки получения данных
}
~Ina219Power_mW(){};
};
void *getAPI_Ina219(String subtype, String param)
{
if (subtype == F("Ina219curr"))
{
return new Ina219curr(param);
} else if (subtype == F("Ina219shuntvoltage")) {
ina219.begin();
}
else if (subtype == F("Ina219shuntvoltage"))
{
return new Ina219shuntvoltage(param);
} else if (subtype == F("power_mW")) {
ina219.begin();
return new Power_mW(param);
} else if (subtype == F("Ina219busvoltage")) {
ina219.begin();
}
else if (subtype == F("Ina219power_mW"))
{
return new Ina219Power_mW(param);
}
else if (subtype == F("Ina219busvoltage"))
{
return new Ina219busvoltage(param);
} else if (subtype == F("Ina219loadvoltage")) {
ina219.begin();
}
else if (subtype == F("Ina219loadvoltage"))
{
return new Ina219loadvoltage(param);
} else {
return nullptr;
}
else
{
return nullptr;
}
}

View File

@@ -10,6 +10,10 @@
"widget": "anydatamAmp",
"page": "INA 219",
"descr": "219 Датчик тока",
"addr": "0x40",
"plus": 0,
"multiply": 1,
"round": 3,
"int": 10
},
{
@@ -21,17 +25,25 @@
"widget": "anydataVlt",
"page": "INA 219",
"descr": "219 Датчик напряжения",
"addr": "0x40",
"plus": 0,
"multiply": 1,
"round": 3,
"int": 10
},
{
"global": 0,
"name": "INA219 Мощность",
"type": "Reading",
"subtype": "power_mW",
"subtype": "Ina219power_mW",
"id": "Ina219power",
"widget": "anydatamWtt",
"widget": "anydatamWt",
"page": "INA 219",
"descr": "219 Мощность",
"addr": "0x40",
"plus": 0,
"multiply": 1,
"round": 3,
"int": 10
},
{
@@ -43,6 +55,10 @@
"widget": "anydataVlt",
"page": "INA 219",
"descr": "219 Напряжение нагрузки",
"addr": "0x40",
"plus": 0,
"multiply": 1,
"round": 3,
"int": 10
},
{
@@ -54,6 +70,10 @@
"widget": "anydatamVlt",
"page": "INA 219",
"descr": "219 Напряжение шунта",
"addr": "0x40",
"plus": 0,
"multiply": 1,
"round": 3,
"int": 10
}],
@@ -61,9 +81,9 @@
"authorName": "Serghei Crasnicov",
"authorContact": "https://t.me/Serghei63",
"authorGit": "https://github.com/Serghei63",
"specialThanks": "Дмитрий , Serg",
"specialThanks": "Дмитрий, Serg, v2.0 - Mitchel @Mit4bmw",
"moduleName": "Ina219",
"moduleVersion": "1.0",
"moduleVersion": "2.0",
"usedRam": {
"esp32_4mb": 15,
"esp8266_4mb": 15
@@ -71,14 +91,15 @@
"subTypes": [
"Ina219curr",
"Ina219busvoltage",
"power_mW",
"Ina219power_mW",
"Ina219loadvoltage",
"Ina219shuntvoltage"
],
"title": "Милливатметр постоянного тока",
"moduleDesc": "Измеряет постоянный ток до 3.2 ампера, напряжение до 26 вольт и мощность на нагрузке",
"moduleDesc": "Измеряет постоянный ток до 3.2 ампера, напряжение до 26 вольт и мощность на нагрузке. Для расчета Наряжения нагрузки, необходимы Напряжение шунта и Датчик Напряжения",
"propInfo": {
"int": "Количество секунд между опросами датчика."
"int": "Количество секунд между опросами датчика.",
"addr": "Адрес датчика на шине, обычно 0x40. Если оставить поле пустым, то запуститься сканер I2C и подключение к адресу 0x40"
}
},

View File

@@ -51,7 +51,7 @@
"Beta":"Beta термистора"
}
},
"defActive": true,
"defActive": false,
"usedLibs": {
"esp32_4mb": [],
"esp8266_4mb": [],

View File

@@ -30,7 +30,7 @@ void printSerialNumber(uint16_t serial0, uint16_t serial1, uint16_t serial2)
}
// Функция инициализации библиотечного класса, возвращает Единстрвенный указать на библиотеку
SensirionI2CScd4x *instance()
SensirionI2CScd4x *instanceScd4x()
{
if (!scd4x)
{ // Если библиотека ранее инициализировалась, т о просто вернем указатель
@@ -41,7 +41,7 @@ SensirionI2CScd4x *instance()
//Останавливаем периодический опрос датчика вбиблиотеке для запроса Сер.номера (на всякий случай)
// stop potentially previously started measurement
errorCodeScd4x = instance()->stopPeriodicMeasurement();
errorCodeScd4x = instanceScd4x()->stopPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute stopPeriodicMeasurement(): ");
@@ -52,7 +52,7 @@ SensirionI2CScd4x *instance()
uint16_t serial0;
uint16_t serial1;
uint16_t serial2;
errorCodeScd4x = instance()->getSerialNumber(serial0, serial1, serial2);
errorCodeScd4x = instanceScd4x()->getSerialNumber(serial0, serial1, serial2);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute getSerialNumber(): ");
@@ -66,7 +66,7 @@ SensirionI2CScd4x *instance()
//Обратно стартуем периодический опрос датчика библиотекой (по описанию библиотеки каждые 5сек)
// Start Measurement
errorCodeScd4x = instance()->startPeriodicMeasurement();
errorCodeScd4x = instanceScd4x()->startPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute startPeriodicMeasurement(): ");
@@ -102,7 +102,7 @@ public:
float humidity = 0.0f;
bool isDataReady = false;
//Запрашиваем библиотеку о готовности отправить запрос
errorCodeScd4x = instance()->getDataReadyFlag(isDataReady);
errorCodeScd4x = instanceScd4x()->getDataReadyFlag(isDataReady);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute getDataReadyFlag(): ");
@@ -115,7 +115,7 @@ public:
return;
}
//Если все нормально забираем у библиотеки данные
errorCodeScd4x = instance()->readMeasurement(co2, temperature, humidity);
errorCodeScd4x = instanceScd4x()->readMeasurement(co2, temperature, humidity);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute readMeasurement(): ");
@@ -158,7 +158,7 @@ public:
{
//Останавливаем периодический опрос датчика вбиблиотеке для запроса Сер.номера (на всякий случай)
// stop potentially previously started measurement
errorCodeScd4x = instance()->stopPeriodicMeasurement();
errorCodeScd4x = instanceScd4x()->stopPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute stopPeriodicMeasurement(): ");
@@ -166,7 +166,7 @@ public:
}
delay(500); // Из описания performForcedRecalibration 2. Stop periodic measurement. Wait 500 ms.
uint16_t frcCorrection;
errorCodeScd4x = instance()->performForcedRecalibration(targetCo2, frcCorrection);
errorCodeScd4x = instanceScd4x()->performForcedRecalibration(targetCo2, frcCorrection);
if (errorCodeScd4x)
{
@@ -182,7 +182,7 @@ public:
//Обратно стартуем периодический опрос датчика библиотекой (по описанию библиотеки каждые 5сек)
// Start Measurement
errorCodeScd4x = instance()->startPeriodicMeasurement();
errorCodeScd4x = instanceScd4x()->startPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute startPeriodicMeasurement(): ");
@@ -197,14 +197,14 @@ public:
{
//Останавливаем периодический опрос датчика вбиблиотеке для запроса Сер.номера (на всякий случай)
// stop potentially previously started measurement
errorCodeScd4x = instance()->stopPeriodicMeasurement();
errorCodeScd4x = instanceScd4x()->stopPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute stopPeriodicMeasurement(): ");
Serial.println(errorMessageScd4x);
}
errorCodeScd4x = instance()->startLowPowerPeriodicMeasurement();
errorCodeScd4x = instanceScd4x()->startLowPowerPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute startLowPowerPeriodicMeasurement(): ");
@@ -216,7 +216,7 @@ public:
Serial.println("startLowPowerPeriodicMeasurement(): OK!");
}
errorCodeScd4x = instance()->setAutomaticSelfCalibration((uint16_t)autoCalibration);
errorCodeScd4x = instanceScd4x()->setAutomaticSelfCalibration((uint16_t)autoCalibration);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute setAutomaticSelfCalibration(): ");
@@ -230,7 +230,7 @@ public:
//Обратно стартуем периодический опрос датчика библиотекой (по описанию библиотеки каждые 5сек)
// Start Measurement
errorCodeScd4x = instance()->startPeriodicMeasurement();
errorCodeScd4x = instanceScd4x()->startPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute startPeriodicMeasurement(): ");
@@ -262,7 +262,7 @@ public:
float temperature = 0.0f;
float humidity = 0.0f;
bool isDataReady = false;
errorCodeScd4x = instance()->getDataReadyFlag(isDataReady);
errorCodeScd4x = instanceScd4x()->getDataReadyFlag(isDataReady);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute getDataReadyFlag(): ");
@@ -274,7 +274,7 @@ public:
{
return;
}
errorCodeScd4x = instance()->readMeasurement(co2, temperature, humidity);
errorCodeScd4x = instanceScd4x()->readMeasurement(co2, temperature, humidity);
if (errorCodeScd4x)
{
Serial.print("errorCodeScd4x trying to execute readMeasurement(): ");
@@ -308,14 +308,14 @@ public:
{
//Останавливаем периодический опрос датчика вбиблиотеке для запроса Сер.номера (на всякий случай)
// stop potentially previously started measurement
errorCodeScd4x = instance()->stopPeriodicMeasurement();
errorCodeScd4x = instanceScd4x()->stopPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute stopPeriodicMeasurement(): ");
Serial.println(errorMessageScd4x);
}
errorCodeScd4x = instance()->setTemperatureOffset((uint16_t)offsetT);
errorCodeScd4x = instanceScd4x()->setTemperatureOffset((uint16_t)offsetT);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute setTemperatureOffset(): ");
@@ -329,7 +329,7 @@ public:
//Обратно стартуем периодический опрос датчика библиотекой (по описанию библиотеки каждые 5сек)
// Start Measurement
errorCodeScd4x = instance()->startPeriodicMeasurement();
errorCodeScd4x = instanceScd4x()->startPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute startPeriodicMeasurement(): ");
@@ -357,7 +357,7 @@ public:
float temperature = 0.0f;
float humidity = 0.0f;
bool isDataReady = false;
errorCodeScd4x = instance()->getDataReadyFlag(isDataReady);
errorCodeScd4x = instanceScd4x()->getDataReadyFlag(isDataReady);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute getDataReadyFlag(): ");
@@ -369,7 +369,7 @@ public:
{
return;
}
errorCodeScd4x = instance()->readMeasurement(co2, temperature, humidity);
errorCodeScd4x = instanceScd4x()->readMeasurement(co2, temperature, humidity);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute readMeasurement(): ");

View File

@@ -70,7 +70,7 @@
}
},
"defActive": true,
"defActive": false,
"usedLibs": {
"esp32_4mb": [
"Sensirion I2C SCD4x @0.4.0",

View File

@@ -2,8 +2,7 @@
#include "Global.h"
#include "classes/IoTItem.h"
String URL = "https://script.google.com/macros/s/";
String URL = F("https://script.google.com/macros/s/");
class GoogleSheet : public IoTItem
{
@@ -12,9 +11,11 @@ private:
String logid;
String scid = "";
String shname = "";
bool init = false;
// bool init = false;
int interval = 1;
// long interval;
// long interval;
String urlFinal;
public:
GoogleSheet(String parameters) : IoTItem(parameters)
{
@@ -24,6 +25,7 @@ public:
jsonRead(parameters, F("shname"), shname);
jsonRead(parameters, F("int"), interval);
interval = interval * 1000 * 60; // так как у нас в минутах
urlFinal = URL + scid + F("/exec?") + F("sheet=") + shname;
}
void doByInterval()
@@ -31,34 +33,8 @@ public:
if (WiFi.status() == WL_CONNECTED)
{
String value = getItemValue(logid);
String urlFinal = URL + scid + "/exec?"+"sheet=" + shname + "&id=" + logid + "&value=" + value;
if (!init){ init=true; urlFinal = urlFinal + "&init=1";}
HTTPClient http;
#if defined ESP8266
WiFiClientSecure client;
client.setInsecure();
if (!http.begin(client, urlFinal))
{
#elif defined ESP32
WiFiClient client;
if (!http.begin(urlFinal))
{
#endif
SerialPrint("I", F("GoogleSheet"), "connection failed ");
}
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); // HTTPC_STRICT_FOLLOW_REDIRECTS HTTPC_FORCE_FOLLOW_REDIRECTS
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
int httpCode = http.GET();
// String payload = http.getString();
SerialPrint("<-", F("GoogleSheet"), "URL: " + urlFinal);
SerialPrint("->", F("GoogleSheet"), "server: " + (String)httpCode); /*"URL: " + urlFinal + */
/* if (httpCode > 0)
{
SerialPrint("->", F("GoogleSheet"), "msg from server: " + (String)payload.c_str());
}
*/
http.end();
if (value != "")
send2Google(logid, value, true);
}
}
@@ -75,6 +51,108 @@ public:
}
}
}
IoTValue execute(String command, std::vector<IoTValue> &param)
{
if (WiFi.status() == WL_CONNECTED)
{
if (command == F("logGoogle"))
{ // Логирование определенного элемента по его идентификатору в GoogleSheet
/* if (param.size() == 1)
{
String id = param[0].valS;
String value = getItemValue(id);
send2Google(id, value, true);
return {};
}
*/
if (param.size() >= 1)
{
int sizeOfParam = param.size();
for (unsigned int i = 0; i < sizeOfParam; i++)
{
IoTItem *itm = findIoTItemOnValue(param[i].valS);
if (itm != nullptr)
{
if (i == sizeOfParam - 1)
send2Google(itm->getID(), param[i].valS, true);
else
send2Google(itm->getID(), param[i].valS, false);
}
}
}
}
else if (command == F("logGoogleAny"))
{ // Запись произвольных данных в GoogleSheet
if (param.size() == 2)
{
send2Google(param[0].valS, param[1].valS, true);
return {};
}
}
}
return {};
}
void send2Google(String logid, String value, bool send)
{
urlFinal = urlFinal + ("&id=") + logid + ("&value=") + value;
if (!send)
return; // Не отправляем просто накапливаем данные
/* if (!init)
{
init = true;
urlFinal = urlFinal + "&init=1";
}
*/
HTTPClient http;
#if defined ESP8266
WiFiClientSecure client;
client.setInsecure();
if (!http.begin(client, urlFinal))
{
#elif defined ESP32
WiFiClient client;
if (!http.begin(urlFinal))
{
#endif
SerialPrint("I", F("GoogleSheet"), F("connection failed"));
}
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); // HTTPC_STRICT_FOLLOW_REDIRECTS HTTPC_FORCE_FOLLOW_REDIRECTS
http.addHeader(F("Content-Type"), F("application/x-www-form-urlencoded"));
int httpCode = http.GET();
// String payload = http.getString();
SerialPrint("<-", F("GoogleSheet"), "URL: " + urlFinal);
SerialPrint("->", F("GoogleSheet"), "server: " + (String)httpCode); /*"URL: " + urlFinal + */
/* if (httpCode > 0)
{
SerialPrint("->", F("GoogleSheet"), "msg from server: " + (String)payload.c_str());
}
*/
http.end();
// Обнуляем данные в запросе, так как все отправили
urlFinal = URL + scid + F("/exec?") + F("sheet=") + shname;
};
// поиск элемента модуля в существующей конфигурации по его значению
// По хорошему ЭТО наверное надо в ЯДРО пернести
IoTItem *findIoTItemOnValue(const String &value)
{
if (value == "")
return nullptr;
for (std::list<IoTItem *>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it)
{
if ((*it)->getValue() == value)
return *it;
}
return nullptr;
};
~GoogleSheet(){};
};

View File

@@ -0,0 +1,52 @@
var SS = SpreadsheetApp.openById('GOOGLE_SHEET_ID');
function doGet(e){
var value = e.parameters.value;
var id = e.parameters.id;
var sheet = e.parameter.sheet;
var init = e.parameter.init;
if (sheet == undefined) {
sheet = SS.getActiveSheet();
} else{
sheet = SS.getSheetByName(sheet);
}
if (sheet == null) {
return ContentService.createTextOutput("Error sheet name");
}
// if (init !== undefined){
sheet.getRange('A1').setValue("ID");
sheet.getRange('B1').setValue("VALUE");
sheet.getRange('C1').setValue("DATE");
// }
var nextFreeRow = sheet.getLastRow() + 1;
if (id == undefined) id = "nan";
if (value !== undefined){
try {
var now = Utilities.formatDate(new Date(), "GMT+03:00", "dd.MM.yyyy HH:mm:ss");
for (let i = 0; i < id.length; i++) {
sheet.getRange("A"+nextFreeRow).setValue(id[i]);
value[i] = value[i].replace(/\./, ",");
sheet.getRange("B"+nextFreeRow).setValue(value[i]);
sheet.getRange("C"+nextFreeRow).setValue(now);
nextFreeRow++;
}
return ContentService.createTextOutput("Successfully wrote: " +
e.parameter.value + "\ninto spreadsheet.");
//Logger.log(str);
}
catch(f){
return ContentService.createTextOutput("Error in parsing appendRow");
}
} else {
return ContentService.createTextOutput("Error wrote: value = " +
e.parameter.value + " , id = "+e.parameter.id);
}
}

View File

@@ -11,7 +11,7 @@
"page": "",
"descr": "",
"int": 5,
"logid": "id",
"logid": "",
"scid": "Script_ID",
"shname": "Logger"
}
@@ -35,7 +35,26 @@
"logid": "ID величины которую будем логировать",
"scid": "Идентификатор развертывания Google Apps (script id)",
"shname": "Наименование листа в таблице (sheet name)"
}
},
"retInfo": "",
"funcInfo": [
{
"name": "logGoogle",
"descr": "Использовать не чаще раз в минуту! Логирование элементов по их идентификатору в GoogleSheet, указывать через запятую, от одного до N (проверено на 16шт)",
"params": [
"id Идентификатор 1-го элеменета",
"id Идентификатор N-го элеменета"
]
},
{
"name": "logGoogleAny",
"descr": "Использовать не чаще раз в минуту! Запись произвольных данных в GoogleSheet",
"params": [
"Наименование данных",
"Значение для записи"
]
}
]
},
"defActive": false,
"usedLibs": {