Merge pull request #8 from Mit4el/ver4dev

esp32s2 и новые модули
This commit is contained in:
2023-06-17 18:54:04 +03:00
committed by GitHub
27 changed files with 1021 additions and 8 deletions

View File

@@ -34,6 +34,10 @@
"path": "src/modules/virtual/Cron",
"active": true
},
{
"path": "src/modules/virtual/GoogleSheet",
"active": false
},
{
"path": "src/modules/virtual/Loging",
"active": true

View File

@@ -27,7 +27,11 @@
#define FIRMWARE_NAME "esp32_4mb"
#endif
// Размер буфера json
#ifdef esp32s2_4mb
#define FIRMWARE_NAME "esp32s2_4mb"
#endif
//Размер буфера json
#define JSON_BUFFER_SIZE 2048 // держим 2 кб не меняем
#define WEB_SOCKETS_FRAME_SIZE 2048

View File

@@ -34,6 +34,10 @@
"path": "src/modules/virtual/Cron",
"active": true
},
{
"path": "src/modules/virtual/GoogleSheet",
"active": false
},
{
"path": "src/modules/virtual/Loging",
"active": true

View File

@@ -79,7 +79,7 @@ build_flags = -Desp8266_2mb="esp8266_2mb"
framework = arduino
board = d1_wroom_02
board_build.ldscript = eagle.flash.2m1m.ld
platform = espressif8266
platform = espressif8266 @4.2.0
monitor_filters = esp8266_exception_decoder
upload_speed = 921600
monitor_speed = 115200
@@ -100,7 +100,7 @@ build_flags = -Desp8266_2mb_ota="esp8266_2mb_ota"
framework = arduino
board = d1_wroom_02
board_build.ldscript = eagle.flash.2m256.ld
platform = espressif8266
platform = espressif8266 @4.2.0
monitor_filters = esp8266_exception_decoder
upload_speed = 921600
monitor_speed = 115200
@@ -174,6 +174,29 @@ build_src_filter =
+<modules/*.cpp>
${env:esp32_4mb_fromitems.build_src_filter}
[env:esp32s2_4mb]
lib_deps =
${common_env_data.lib_deps_external}
${env:esp32s2_4mb_fromitems.lib_deps}
build_flags =
-Desp32s2_4mb="esp32s2_4mb"
-DARDUINO_USB_CDC_ON_BOOT=1
-DARDUINO_USB_MODE=0
framework = arduino
board = lolin_s2_mini
platform = espressif32 @6.3.1
monitor_filters = esp32_exception_decoder
upload_speed = 921600
monitor_speed = 115200
debug_tool = esp-prog
board_build.filesystem = littlefs
build_src_filter =
+<*.cpp>
+<classes/*.cpp>
+<utils/*.cpp>
+<modules/*.cpp>
${env:esp32s2_4mb_fromitems.build_src_filter}
[env:esp8266_1mb_ota_fromitems]
lib_deps =
adafruit/Adafruit BME280 Library
@@ -474,3 +497,6 @@ build_src_filter =
+<modules/exec/TelegramLT>
+<modules/display/Lcd2004>
[env:esp32s2_4mb_fromitems]
lib_deps =
build_src_filter =

View File

@@ -77,6 +77,7 @@ uint32_t ESP_getChipId(void) {
}
// устарела используем новую функцию ниже
#ifndef esp32s2_4mb
uint32_t ESP_getFlashChipId(void) {
#ifdef ESP32
// Нет аналогичной (без доп.кода) функций в 32
@@ -86,6 +87,7 @@ uint32_t ESP_getFlashChipId(void) {
return ESP.getFlashChipId();
#endif
}
#endif
// https://github.com/espressif/arduino-esp32/issues/6945#issuecomment-1199900892
// получение flash ch id из проекта esp easy

View File

@@ -3,6 +3,9 @@
#include "classes/IoTDB.h"
#include "utils/Statistic.h"
#include <Wire.h>
#ifdef esp32s2_4mb
#include <USB.h>
#endif
IoTScenario iotScen; // объект управления сценарием
@@ -77,6 +80,9 @@ void stopErrorMarker(int id) {
}
void setup() {
#ifdef esp32s2_4mb
USB.begin();
#endif
#ifdef esp32_4mb
My_timer = timerBegin(0, 80, true);
timerAttachInterrupt(My_timer, &onTimer, true);
@@ -120,7 +126,7 @@ void setup() {
jsonRead(settingsFlashJson, "i2cFreq", i2cFreq, false);
jsonRead(settingsFlashJson, "i2c", i2c, false);
if (i2c != 0) {
#ifdef esp32_4mb
#ifdef ESP32
Wire.end();
Wire.begin(pinSDA, pinSCL, (uint32_t)i2cFreq);
#else

View File

@@ -58,7 +58,50 @@ void printGlobalVarSize() {
String ESP_getResetReason(void) {
return ESP.getResetReason();
}
#else
#endif
#ifdef esp32s2_4mb
String ESP_getResetReason(void) {
return ESP32GetResetReason(0); // CPU 0
}
String ESP32GetResetReason(uint32_t cpu_no) {
// tools\sdk\include\esp32\rom\rtc.h
switch (rtc_get_reset_reason((RESET_REASON)cpu_no)) {
case POWERON_RESET:
return F("Vbat power on reset"); // 1
case RTC_SW_SYS_RESET:
return F("Software reset digital core"); // 3
// case OWDT_RESET:
// return F("Legacy Watchdog reset digital core"); // 4
case DEEPSLEEP_RESET:
return F("Deep Sleep reset digital core"); // 5
// case SDIO_RESET:
// return F("Reset by SLC module, reset digital core"); // 6
case TG0WDT_SYS_RESET:
return F("Timer Group0 Watchdog reset digital core"); // 7
case TG1WDT_SYS_RESET:
return F("Timer Group1 Watchdog reset digital core"); // 8
case RTCWDT_SYS_RESET:
return F("RTC Watchdog Reset digital core"); // 9
case INTRUSION_RESET:
return F("Instrusion tested to reset CPU"); // 10
case TG0WDT_CPU_RESET:
return F("Time Group reset CPU"); // 11
case RTC_SW_CPU_RESET:
return F("Software reset CPU"); // 12
case RTCWDT_CPU_RESET:
return F("RTC Watchdog Reset CPU"); // 13
// case EXT_CPU_RESET:
// return F("or APP CPU, reseted by PRO CPU"); // 14
case RTCWDT_BROWN_OUT_RESET:
return F("Reset when the vdd voltage is not stable"); // 15
case RTCWDT_RTC_RESET:
return F("RTC Watchdog reset digital core and rtc module"); // 16
default:
return F("NO_MEAN"); // 0
}
}
#endif
#ifdef esp32_4mb
String ESP_getResetReason(void) {
return ESP32GetResetReason(0); // CPU 0
}

View File

@@ -76,7 +76,7 @@ bool upgradeBuild() {
ESPhttpUpdate.rebootOnUpdate(false);
t_httpUpdate_return retBuild = ESPhttpUpdate.update(wifiClient, getBinPath("firmware.bin"));
#endif
#ifdef esp32_4mb
#ifdef ESP32
httpUpdate.rebootOnUpdate(false);
HTTPUpdateResult retBuild = httpUpdate.update(wifiClient, getBinPath("firmware.bin"));
#endif

View File

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

View File

@@ -15,7 +15,7 @@
],
"about": {
"authorName": "Bubnov Mikhail",
"authorContact": "https://t.me/Mitchel",
"authorContact": "https://t.me/Mit4bmw",
"authorGit": "https://github.com/Mit4el",
"exampleURL": "https://iotmanager.org/wiki",
"specialThanks": "",

View File

@@ -21,7 +21,7 @@
],
"about": {
"authorName": "Bubnov Mikhail",
"authorContact": "https://t.me/Mitchel",
"authorContact": "https://t.me/Mit4bmw",
"authorGit": "https://github.com/Mit4el",
"exampleURL": "https://iotmanager.org/wiki",
"specialThanks": "",
@@ -41,6 +41,7 @@
"defActive": true,
"usedLibs": {
"esp32_4mb": [],
"esp32s2_4mb": [],
"esp8266_4mb": [],
"esp8266_1mb": [],
"esp8266_1mb_ota": [],

View File

@@ -0,0 +1,178 @@
#include "Global.h"
#include "classes/IoTItem.h"
#include <DS2423.h>
#include <OneWire.h>
#include <map>
typedef uint8_t DeviceAddressDS2423[8];
// глобальные списки необходимы для хранения объектов об активных линиях 1-wire используемых разными датчиками из модуля. Ключ - номер пина
std::map<int, OneWire *> oneWireDS2423Array;
// Функция инициализации библиотечного класса, возвращает Единстрвенный указать на библиотеку
OneWire *instanceOneWire_DS2423(uint8_t ONE_WIRE_PIN)
{
// учитываем, что библиотека может работать с несколькими линиями на разных пинах, поэтому инициируем библиотеку, если линия ранее не использовалась
if (oneWireDS2423Array.find(ONE_WIRE_PIN) == oneWireDS2423Array.end())
oneWireDS2423Array[ONE_WIRE_PIN] = new OneWire((uint8_t)ONE_WIRE_PIN);
return oneWireDS2423Array[ONE_WIRE_PIN];
}
// Определяем адрес.
bool getDeviceAddressDS2423(uint8_t pin, uint8_t *deviceAddress, int index)
{
OneWire *_wire = instanceOneWire_DS2423(pin);
uint8_t depth = 0;
_wire->reset_search();
while (depth <= index && _wire->search(deviceAddress))
{
if (depth == index && _wire->crc8((uint8_t *)deviceAddress, 7) == deviceAddress[7])
return true;
depth++;
}
return false;
}
class Ds2423a : public IoTItem
{
private:
// описание параметров передаваемых из настроек датчика из веба
String _addr;
int _pin;
int _index;
DS2423 *ds2423;
DeviceAddressDS2423 _deviceAddress;
public:
Ds2423a(String parameters) : IoTItem(parameters)
{
jsonRead(parameters, "pin", _pin);
jsonRead(parameters, "index", _index, false);
jsonRead(parameters, "addr", _addr, false);
// Определяем адрес. Если параметр addr не установлен, то узнаем адрес по индексу
if (_addr == "")
{
if (getDeviceAddressDS2423(_pin, _deviceAddress, _index))
{
char addrStr[20] = "";
hex2string(_deviceAddress, 8, addrStr);
SerialPrint("I", "Sensor " + (String)_id, "index: " + (String)_index + " addr: " + String(addrStr));
}
else
{
SerialPrint("E", "Sensor " + (String)_id, "index: " + (String)_index + " addres not search");
}
}
else
{
string2hex(_addr.c_str(), _deviceAddress);
}
ds2423 = new DS2423(instanceOneWire_DS2423(_pin), _deviceAddress);
ds2423->begin(DS2423_COUNTER_A | DS2423_COUNTER_B);
}
void doByInterval()
{
ds2423->update();
if (ds2423->isError())
{
Serial.println("Error reading counter");
}
else
{
value.valD = ds2423->getCount(DS2423_COUNTER_A);
// if (value.valD != -127)
regEvent(value.valD, "Ds2423a"); // обязательный вызов для отправки результата работы
// else
// SerialPrint("E", "Sensor Ds2423a", "Error");
}
}
//=======================================================================================================
~Ds2423a(){};
};
class Ds2423b : public IoTItem
{
private:
// описание параметров передаваемых из настроек датчика из веба
String _addr;
int _pin;
int _index;
DS2423 *ds2423;
DeviceAddressDS2423 _deviceAddress;
public:
Ds2423b(String parameters) : IoTItem(parameters)
{
jsonRead(parameters, "pin", _pin);
jsonRead(parameters, "index", _index, false);
jsonRead(parameters, "addr", _addr, false);
// Определяем адрес. Если параметр addr не установлен, то узнаем адрес по индексу
if (_addr == "")
{
if (getDeviceAddressDS2423(_pin, _deviceAddress, _index))
{
char addrStr[20] = "";
hex2string(_deviceAddress, 8, addrStr);
SerialPrint("I", "Sensor " + (String)_id, "index: " + (String)_index + " addr: " + String(addrStr));
}
else
{
SerialPrint("E", "Sensor " + (String)_id, "index: " + (String)_index + " addres not search");
}
}
else
{
string2hex(_addr.c_str(), _deviceAddress);
}
ds2423 = new DS2423(instanceOneWire_DS2423(_pin), _deviceAddress);
ds2423->begin(DS2423_COUNTER_A | DS2423_COUNTER_B);
}
void doByInterval()
{
ds2423->update();
if (ds2423->isError())
{
Serial.println("Error reading counter");
}
else
{
// запускаем опрос измерений у всех датчиков на линии
value.valD = ds2423->getCount(DS2423_COUNTER_B);
// if (value.valD != -127)
regEvent(value.valD, "Ds2423b"); // обязательный вызов для отправки результата работы
// else
// SerialPrint("E", "Sensor Ds2423b", "Error");
}
}
//=======================================================================================================
~Ds2423b(){};
};
void *getAPI_Ds2423(String subtype, String param)
{
if (subtype == F("Ds2423a"))
{
return new Ds2423a(param);
}
else if (subtype == F("Ds2423b"))
{
return new Ds2423b(param);
}
else
{
return nullptr;
}
}

View File

@@ -0,0 +1,72 @@
{
"menuSection": "Сенсоры",
"configItem": [
{
"global": 0,
"name": "DS2423 счетчик 1",
"type": "Reading",
"subtype": "Ds2423a",
"id": "dscounta",
"widget": "anydataDef",
"page": "Счетчики",
"descr": "DS1 V",
"plus": 0,
"multiply": 1,
"pin": 4,
"index": 0,
"addr": "",
"int": 10,
"round": 0,
"needSave": 0
},
{
"global": 0,
"name": "DS2423 счетчик 2",
"type": "Reading",
"subtype": "Ds2423b",
"id": "dscountb",
"widget": "anydataDef",
"page": "Счетчики",
"descr": "DS2 V",
"plus": 0,
"multiply": 1,
"pin": 4,
"index": 0,
"addr": "",
"int": 10,
"round": 0,
"needSave": 0
}
],
"about": {
"authorName": "Serghei Crasnicov",
"authorContact": "https://t.me/Serghei63",
"authorGit": "https://github.com/Serghei63",
"specialThanks": "Bubnov Mikhail @Mit4bmw",
"moduleName": "Ds2423",
"moduleVersion": "1.0",
"usedRam": {
"esp32_4mb": 15,
"esp8266_4mb": 15
},
"title": "Cчетчик ds2423",
"moduleDesc": "Позволяет получить значения с Ds2423.",
"propInfo": {
"pin": "GPIO номер, к которому подключена шина данных датчиков.",
"index": "Порядковый номер датчика на шине.",
"addr": "Адрес датчика на шине для точной идентификации. Если оставить пустым, то попробует найти по индексу и пину и Можно скопировать из консоли.",
"int": "Количество секунд между опросами датчика."
}
},
"defActive": true,
"usedLibs": {
"esp32_4mb": [
"https://github.com/jbechter/arduino-onewire-DS2423",
"paulstoffregen/OneWire @ ^2.3.7"
],
"esp8266_4mb": [
"https://github.com/jbechter/arduino-onewire-DS2423",
"paulstoffregen/OneWire @ ^2.3.7"
]
}
}

View File

@@ -88,6 +88,9 @@
"esp32_4mb": [
"https://github.com/adafruit/Adafruit_INA219.git"
],
"esp32s2_4mb": [
"https://github.com/adafruit/Adafruit_INA219.git"
],
"esp8266_4mb": [
"https://github.com/adafruit/Adafruit_INA219.git"

View File

@@ -78,6 +78,7 @@
"defActive": false,
"usedLibs": {
"esp32_4mb": [],
"esp32s2_4mb": ["plerup/EspSoftwareSerial"],
"esp8266_4mb": []
}
}

View File

@@ -0,0 +1,432 @@
#include "Global.h"
#include "classes/IoTItem.h"
#include <SensirionI2CScd4x.h>
#include <SensirionCore.h>
#include <Wire.h>
// SensirionI2CScd4x scd4x;
SensirionI2CScd4x *scd4x = nullptr; // create an object of the CSD40 class
char errorMessageScd4x[256];
uint16_t errorCodeScd4x;
void printUint16Hex(uint16_t value)
{
Serial.print(value < 4096 ? "0" : "");
Serial.print(value < 256 ? "0" : "");
Serial.print(value < 16 ? "0" : "");
Serial.print(value, HEX);
}
void printSerialNumber(uint16_t serial0, uint16_t serial1, uint16_t serial2)
{
Serial.print("Serial: 0x");
printUint16Hex(serial0);
printUint16Hex(serial1);
printUint16Hex(serial2);
Serial.println();
}
// Функция инициализации библиотечного класса, возвращает Единстрвенный указать на библиотеку
SensirionI2CScd4x *instance()
{
if (!scd4x)
{ // Если библиотека ранее инициализировалась, т о просто вернем указатель
// Инициализируем библиотеку
scd4x = new SensirionI2CScd4x();
Wire.begin();
scd4x->begin(Wire);
//Останавливаем периодический опрос датчика вбиблиотеке для запроса Сер.номера (на всякий случай)
// stop potentially previously started measurement
errorCodeScd4x = instance()->stopPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute stopPeriodicMeasurement(): ");
Serial.println(errorMessageScd4x);
}
//Запрашиваем и выводим серийный номер датчика
uint16_t serial0;
uint16_t serial1;
uint16_t serial2;
errorCodeScd4x = instance()->getSerialNumber(serial0, serial1, serial2);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute getSerialNumber(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
else
{
printSerialNumber(serial0, serial1, serial2);
}
//Обратно стартуем периодический опрос датчика библиотекой (по описанию библиотеки каждые 5сек)
// Start Measurement
errorCodeScd4x = instance()->startPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute startPeriodicMeasurement(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
Serial.println("Waiting for first measurement... ");
}
return scd4x;
}
class Scd40co2 : public IoTItem
{
private:
bool lowPeriodic = true;
bool autoCalibration = true;
//int targetCo2 = 0;
public:
Scd40co2(String parameters) : IoTItem(parameters)
{
jsonRead(parameters, F("lowPeriodic"), lowPeriodic);
jsonRead(parameters, F("autoCalibration"), autoCalibration);
// jsonRead(parameters, F("targetCo2"), targetCo2);
settingParameters();
}
void doByInterval()
{
// Read Measurement
uint16_t co2 = 0;
float temperature = 0.0f;
float humidity = 0.0f;
bool isDataReady = false;
//Запрашиваем библиотеку о готовности отправить запрос
errorCodeScd4x = instance()->getDataReadyFlag(isDataReady);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute getDataReadyFlag(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
return;
}
if (!isDataReady)
{
return;
}
//Если все нормально забираем у библиотеки данные
errorCodeScd4x = instance()->readMeasurement(co2, temperature, humidity);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute readMeasurement(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
else if (co2 == 0)
{
Serial.println("Invalid sample detected, skipping.");
}
else
{
Serial.print("Co2:");
Serial.print(co2);
Serial.print("\t");
// Serial.print("Temperature:");
// Serial.print(temperature);
// Serial.print("\t");
// Serial.print("Humidity:");
// Serial.println(humidity);
}
// value.valD = scd4x.readMeasurement(temperature);
value.valD = co2;
if (value.valD < 5000)
regEvent(value.valD, "Scd40co2");
else
SerialPrint("E", "Sensor Scd40co2", "Error", _id);
}
//Хук для обработки кнопки
void onModuleOrder(String &key, String &value)
{
if (key == "Recalibration")//название кнопки btn-Recalibration
{
SerialPrint("i", F("Sensor Scd40co2"), "User run calibration, targetCo2: " + value);
Recalibration(value.toInt());
}
}
void Recalibration(int targetCo2)
{
//Останавливаем периодический опрос датчика вбиблиотеке для запроса Сер.номера (на всякий случай)
// stop potentially previously started measurement
errorCodeScd4x = instance()->stopPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute stopPeriodicMeasurement(): ");
Serial.println(errorMessageScd4x);
}
delay(500); // Из описания performForcedRecalibration 2. Stop periodic measurement. Wait 500 ms.
uint16_t frcCorrection;
errorCodeScd4x = instance()->performForcedRecalibration(targetCo2, frcCorrection);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute performForcedRecalibration(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
else
{
Serial.println("performForcedRecalibration(): OK!");
SerialPrint("i", F("Sensor Scd40co2"), "Calibration is OK, frcCorrection: " + String(frcCorrection));
}
//Обратно стартуем периодический опрос датчика библиотекой (по описанию библиотеки каждые 5сек)
// Start Measurement
errorCodeScd4x = instance()->startPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute startPeriodicMeasurement(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
Serial.println("Waiting for first measurement... ");
}
void settingParameters()
{
//Останавливаем периодический опрос датчика вбиблиотеке для запроса Сер.номера (на всякий случай)
// stop potentially previously started measurement
errorCodeScd4x = instance()->stopPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute stopPeriodicMeasurement(): ");
Serial.println(errorMessageScd4x);
}
errorCodeScd4x = instance()->startLowPowerPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute startLowPowerPeriodicMeasurement(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
else
{
Serial.println("startLowPowerPeriodicMeasurement(): OK!");
}
errorCodeScd4x = instance()->setAutomaticSelfCalibration((uint16_t)autoCalibration);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute setAutomaticSelfCalibration(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
else
{
Serial.println("setAutomaticSelfCalibration(): OK!");
}
//Обратно стартуем периодический опрос датчика библиотекой (по описанию библиотеки каждые 5сек)
// Start Measurement
errorCodeScd4x = instance()->startPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute startPeriodicMeasurement(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
Serial.println("Waiting for first measurement... ");
}
~Scd40co2(){};
};
class Scd40t : public IoTItem
{
private:
int offsetT;
public:
Scd40t(String parameters) : IoTItem(parameters)
{
jsonRead(parameters, F("offset"), offsetT);
setTemperatureOffset();
}
void doByInterval()
{
// Read Measurement
uint16_t co2 = 0;
float temperature = 0.0f;
float humidity = 0.0f;
bool isDataReady = false;
errorCodeScd4x = instance()->getDataReadyFlag(isDataReady);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute getDataReadyFlag(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
return;
}
if (!isDataReady)
{
return;
}
errorCodeScd4x = instance()->readMeasurement(co2, temperature, humidity);
if (errorCodeScd4x)
{
Serial.print("errorCodeScd4x trying to execute readMeasurement(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
else if (co2 == 0)
{
Serial.println("Invalid sample detected, skipping.");
}
else
{
// Serial.print("Co2:");
// Serial.print(co2);
// Serial.print("\t");
Serial.print("Temperature:");
Serial.print(temperature);
Serial.print("\t");
// Serial.print("Humidity:");
// Serial.println(humidity);
}
// value.valD = scd4x.readMeasurement(temperature);
value.valD = temperature;
if (value.valD < 124)
regEvent(value.valD, "Scd40t");
else
SerialPrint("E", "Sensor Scd40t", "Error", _id);
}
void setTemperatureOffset()
{
//Останавливаем периодический опрос датчика вбиблиотеке для запроса Сер.номера (на всякий случай)
// stop potentially previously started measurement
errorCodeScd4x = instance()->stopPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute stopPeriodicMeasurement(): ");
Serial.println(errorMessageScd4x);
}
errorCodeScd4x = instance()->setTemperatureOffset((uint16_t)offsetT);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute setTemperatureOffset(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
else
{
Serial.println("setTemperatureOffset(): OK!");
}
//Обратно стартуем периодический опрос датчика библиотекой (по описанию библиотеки каждые 5сек)
// Start Measurement
errorCodeScd4x = instance()->startPeriodicMeasurement();
if (errorCodeScd4x)
{
Serial.print("Error trying to execute startPeriodicMeasurement(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
Serial.println("Waiting for first measurement... ");
}
~Scd40t(){};
};
class Scd40h : public IoTItem
{
public:
Scd40h(String parameters) : IoTItem(parameters)
{
}
void doByInterval()
{
// Read Measurement
uint16_t co2 = 0;
float temperature = 0.0f;
float humidity = 0.0f;
bool isDataReady = false;
errorCodeScd4x = instance()->getDataReadyFlag(isDataReady);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute getDataReadyFlag(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
return;
}
if (!isDataReady)
{
return;
}
errorCodeScd4x = instance()->readMeasurement(co2, temperature, humidity);
if (errorCodeScd4x)
{
Serial.print("Error trying to execute readMeasurement(): ");
errorToString(errorCodeScd4x, errorMessageScd4x, 256);
Serial.println(errorMessageScd4x);
}
else if (co2 == 0)
{
Serial.println("Invalid sample detected, skipping.");
}
else
{
// Serial.print("Co2:");
// Serial.print(co2);
// Serial.print("\t");
// Serial.print("Temperature:");
// Serial.print(temperature);
// Serial.print("\t");
Serial.print("Humidity:");
Serial.println(humidity);
Serial.print("\t");
}
// value.valD = scd4x.readMeasurement(temperature);
value.valD = humidity;
if (value.valD < 100)
regEvent(value.valD, "Scd40h");
else
SerialPrint("E", "Sensor Scd40h", "Error", _id);
}
~Scd40h(){};
};
void *getAPI_Scd40(String subtype, String param)
{
if (subtype == F("Scd40co2"))
{
// hdc1080.begin(0x40);
// scd4x->begin(Wire);
// scd4x.begin(Wire);
return new Scd40co2(param);
}
else if (subtype == F("Scd40t"))
{
// hdc1080.begin(0x40);
// scd4x->begin(Wire);
return new Scd40t(param);
}
else if (subtype == F("Scd40h"))
{
// hdc1080.begin(0x40);
// scd4x->begin(Wire);
return new Scd40h(param);
// } else {
// return nullptr;
}
return nullptr;
}

View File

@@ -0,0 +1,84 @@
{
"menuSection": "Сенсоры",
"configItem": [
{
"global": 0,
"name": "SCD40 Углекислый газ",
"type": "Reading",
"subtype": "Scd40co2",
"id": "Scd40co2",
"widget": "anydataPpm",
"page": "Сенсоры",
"descr": "SCD40 Углекислый газ",
"int": 15,
"round": 0,
"lowPeriodic": 1,
"autoCalibration": 1,
"btn-Recalibration": 0
},
{
"global": 0,
"name": "SCD40 Влажность",
"type": "Reading",
"subtype": "Scd40h",
"id": "Scd40h",
"widget": "anydataHum",
"page": "Сенсоры",
"descr": "SCD40 Влажность",
"int": 15,
"round": 1
},
{
"global": 0,
"name": "SCD40 Температура",
"type": "Reading",
"subtype": "Scd40t",
"id": "Scd40t",
"widget": "anydataTmp",
"page": "Сенсоры",
"descr": "SCD40 Температура",
"int": 15,
"round": 1,
"offset": 4
}
],
"about": {
"authorName": "Serghei Crasnicov",
"authorContact": "https://t.me/Serghei63",
"authorGit": "https://github.com/Serghei63",
"specialThanks": "Bubnov Mikhail @Mit4bmw",
"moduleName": "Scd40",
"moduleVersion": "0.0",
"usedRam": {
"esp32_4mb": 15,
"esp8266_4mb": 15
},
"subTypes": [
"Scd40co2",
"Scd40t",
"Scd40h"
],
"title": "Датчик температуры и влажности Scd40",
"moduleDesc": "Позволяет получить значения температуры и влажности с Scd40.",
"propInfo": {
"int": "Количество секунд между опросами библиотеки (датчик опрашивается библиотекой по своему таймеру, см. lowPeriodic).",
"offset": "Смещение температуры представляет собой разницу между температурой, измеренной SCD4x, и фактической температурой окружающей среды температура. По умолчанию смещение температуры в библиотеке/датчике установлено на 4°C.",
"lowPeriodic": "Медленные режим опроса датчика библиотекой. 0-каждые 5сек, 1-каждые 30сек",
"autoCalibration": "Автоматическая калибровка, по умолчанию включена AutomaticSelfCalibration, 0 - выключена",
"btn-Recalibration": "Кнопка принудительной калибровки. В поле указать Целевая концентрация CO₂ в миллионных долях. Перед калибровкой необходимо находтся в течение > 3 минут в среде с однородной и постоянной концентрацией CO₂. Выдает в лог Значение коррекции FRC в co₂ ppm"
}
},
"defActive": true,
"usedLibs": {
"esp32_4mb": [
"Sensirion I2C SCD4x @0.4.0",
"Sensirion Core @0.6.0"
],
"esp8266_4mb": [
"Sensirion I2C SCD4x @0.4.0",
"Sensirion Core @0.6.0"
]
}
}

View File

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

View File

@@ -0,0 +1,92 @@
#include "Global.h"
#include "classes/IoTItem.h"
String URL = "https://script.google.com/macros/s/";
class GoogleSheet : public IoTItem
{
private:
String id;
String logid;
String scid = "";
String shname = "";
bool init = false;
int interval = 1;
// long interval;
public:
GoogleSheet(String parameters) : IoTItem(parameters)
{
jsonRead(parameters, F("id"), id);
jsonRead(parameters, F("logid"), logid);
jsonRead(parameters, F("scid"), scid);
jsonRead(parameters, F("shname"), shname);
jsonRead(parameters, F("int"), interval);
interval = interval * 1000 * 60; // так как у нас в минутах
}
void doByInterval()
{
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();
}
}
void loop()
{
if (enableDoByInt)
{
currentMillis = millis();
difference = currentMillis - prevMillis;
if (difference >= interval)
{
prevMillis = millis();
this->doByInterval();
}
}
}
~GoogleSheet(){};
};
void *getAPI_GoogleSheet(String subtype, String param)
{
if (subtype == F("GoogleSheet"))
{
return new GoogleSheet(param);
}
else
{
return nullptr;
}
}

View File

@@ -0,0 +1,52 @@
{
"menuSection": "Виртуальные элементы",
"configItem": [
{
"global": 0,
"name": "GoogleSheet",
"type": "Reading",
"subtype": "GoogleSheet",
"id": "sheet",
"widget": "nil",
"page": "",
"descr": "",
"int": 5,
"logid": "id",
"scid": "AKfycbzAsuM-4Keb-DxZ6yqwmqSeiXRJJAqndijayZQfmx9pfh6wGAejjT6u7gTAIxrbxPBxyw",
"shname": "Logger"
}
],
"about": {
"authorName": "Bubnov Mikhail",
"authorContact": "https://t.me/Mit4bmw",
"authorGit": "https://github.com/Mit4el",
"exampleURL": "https://iotmanager.org/wiki",
"specialThanks": "",
"moduleName": "GoogleSheet",
"moduleVersion": "1.0",
"usedRam": {
"esp32_4mb": 10,
"esp8266_4mb": 10
},
"title": "Логирование в Google таблицы",
"moduleDesc": "Расширение позволяющее логировать любую величину в Google таблицы. Инструкция https://drive.google.com/file/d/1VuI06arObNfH3rsOSHKww1tyhfgqXd9F/view?usp=sharing",
"propInfo": {
"int": "Интервал логирования в минутах",
"logid": "ID величины которую будем логировать",
"scid": "Идентификатор развертывания Google Apps (script id)",
"shname": "Наименование листа в таблице (sheet name)"
}
},
"defActive": false,
"usedLibs": {
"esp32_4mb": [],
"esp32s2_4mb": [],
"esp8266_4mb": [],
"esp8266_1mb": [],
"esp8266_1mb_ota": [],
"esp8285_1mb": [],
"esp8285_1mb_ota": [],
"esp8266_2mb": [],
"esp8266_2mb_ota": []
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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