mirror of
https://github.com/IoTManagerProject/IoTManager.git
synced 2026-03-27 06:32:19 +03:00
97
src/modules/exec/Ftp/Ftp.cpp
Normal file
97
src/modules/exec/Ftp/Ftp.cpp
Normal 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;
|
||||
}
|
||||
46
src/modules/exec/Ftp/modinfo.json
Normal file
46
src/modules/exec/Ftp/modinfo.json
Normal 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": []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
"defActive": false,
|
||||
"usedLibs": {
|
||||
"esp32_4mb": [],
|
||||
"esp32s2_4mb": [],
|
||||
"esp8266_4mb": [],
|
||||
"esp8266_1mb": [],
|
||||
"esp8266_1mb_ota": [],
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
"int": "Количество секунд между опросами датчика."
|
||||
}
|
||||
},
|
||||
"defActive": true,
|
||||
"defActive": false,
|
||||
"usedLibs": {
|
||||
"esp32_4mb": [
|
||||
"https://github.com/jbechter/arduino-onewire-DS2423",
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
"Beta":"Beta термистора"
|
||||
}
|
||||
},
|
||||
"defActive": true,
|
||||
"defActive": false,
|
||||
"usedLibs": {
|
||||
"esp32_4mb": [],
|
||||
"esp8266_4mb": [],
|
||||
|
||||
@@ -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(): ");
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
|
||||
}
|
||||
},
|
||||
"defActive": true,
|
||||
"defActive": false,
|
||||
"usedLibs": {
|
||||
"esp32_4mb": [
|
||||
"Sensirion I2C SCD4x @0.4.0",
|
||||
|
||||
@@ -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> ¶m)
|
||||
{
|
||||
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(){};
|
||||
};
|
||||
|
||||
|
||||
52
src/modules/virtual/GoogleSheet/goggleapp.gs
Normal file
52
src/modules/virtual/GoogleSheet/goggleapp.gs
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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": {
|
||||
|
||||
Reference in New Issue
Block a user