fix esp32c6 & add ble, Fix Date Log, add BL0942, upd Descovery

This commit is contained in:
Mit4el
2025-01-06 20:35:19 +03:00
parent a844d08ebf
commit 68fea2ae37
18 changed files with 719 additions and 85 deletions

View File

@@ -396,8 +396,8 @@ framework = arduino
board = esp32-c6-devkitm-1
platform = espressif32 @6.9.0
platform_packages =
platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git
platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1
framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.1
framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.1/esp32-arduino-libs-3.0.1.zip
monitor_filters = esp32_exception_decoder
upload_speed = 921600
monitor_speed = 115200
@@ -423,15 +423,16 @@ build_flags =
-DARDUINO_USB_MODE=0
-Wl,--wrap=esp_panic_handler
framework = arduino
board = esp32-c6-devkitc-1
board = esp32-c6-devkitm-1
platform = espressif32 @6.9.0
platform_packages =
platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git
platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1
framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.1
framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.1/esp32-arduino-libs-3.0.1.zip
monitor_filters = esp32_exception_decoder
upload_speed = 921600
monitor_speed = 115200
debug_tool = esp-prog
board_build.partitions = tools/partitions_custom_8mb.csv
board_build.filesystem = littlefs
build_src_filter =
+<*.cpp>

View File

@@ -1,5 +1,6 @@
#include "ESPConfiguration.h"
#include "classes/IoTGpio.h"
//#include "classes/IoTDiscovery.h"
extern IoTGpio IoTgpio;
@@ -52,6 +53,26 @@ void configure(String path) {
}
file.close();
SerialPrint("i", "Config", "Configured");
/*
#ifdef ESP32
if(HOMEdDiscovery)
HOMEdDiscovery->mqttSubscribeDiscovery();
if(HADiscovery)
HADiscovery->mqttSubscribeDiscovery();
// оттправляем все статусы
if(HOMEdDiscovery || HADiscovery)
{
for (std::list<IoTItem *>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it)
{
if ((*it)->iAmLocal)
{
publishStatusMqtt((*it)->getID(), (*it)->getValue());
(*it)->onMqttWsAppConnectEvent();
}
}
}
#endif
*/
}
void clearConfigure() {

View File

@@ -120,7 +120,9 @@ void getMqttData() {
mqttUser = jsonReadStr(settingsFlashJson, F("mqttUser"));
mqttPass = jsonReadStr(settingsFlashJson, F("mqttPass"));
mqttPrefix = jsonReadStr(settingsFlashJson, F("mqttPrefix"));
nameId = jsonReadStr(settingsFlashJson, F("name"));
if (jsonReadInt(settingsFlashJson, F("HOMEd_names"))){
nameId = jsonReadStr(settingsFlashJson, F("name"));}
else{nameId = getChipId();}
mqttRootDevice = mqttPrefix + "/" + chipId;
}

View File

@@ -180,33 +180,30 @@ const String getTodayDateDotFormated() {
// format 22.02.2022
unsigned long strDateToUnix(String date) {
int day = selectToMarker(date, ".").toInt();
date = deleteBeforeDelimiter(date, ".");
int month = selectToMarker(date, ".").toInt();
date = deleteBeforeDelimiter(date, ".");
int year = selectToMarker(date, ".").toInt();
int secsInOneDay = 86400;
int daysInOneYear = 365;
int daysInLeepYear = 366;
int numberOfLeepYears = 12;
int totalNormalYears = year - 1970 - numberOfLeepYears;
int day, month, year;
unsigned int daysInMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (year % 4 == 0) {
if (year % 100 != 0 || year % 400 == 0) {
daysInMonth[1] = 29;
} else {
daysInMonth[1] = 28;
}
} else {
daysInMonth[1] = 28;
}
int numberOfDaysInPastMonths = 0;
for (int i = 0; i <= 11; i++) {
if (i <= month - 2) {
numberOfDaysInPastMonths = numberOfDaysInPastMonths + daysInMonth[i];
}
day = date.substring(0, date.indexOf(".")).toInt();
date = date.substring(date.indexOf(".") + 1);
month = date.substring(0, date.indexOf(".")).toInt();
date = date.substring(date.indexOf(".") + 1);
year = date.toInt();
unsigned long unixTime = (year - 1970) * 365 * 86400;
int numberOfLeepYears = (year - 1968) / 4 - (year - 1900) / 100 + (year - 1600) / 400;
unixTime += numberOfLeepYears * 86400;
if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) {
daysInMonth[1] = 29;
}
return (day * secsInOneDay) + (numberOfDaysInPastMonths * secsInOneDay) + (totalNormalYears * daysInOneYear * secsInOneDay) + (numberOfLeepYears * daysInLeepYear * secsInOneDay);
for (int i = 0; i < month - 1; i++) {
unixTime += daysInMonth[i] * 86400;
}
unixTime += (day - 1) * 86400;
return unixTime;
}
const String getDateTimeDotFormatedFromUnix(unsigned long unixTime) {

View File

@@ -49,6 +49,12 @@
},
"defActive": false,
"usedLibs": {
"esp32c6_4mb": [
"exclude"
],
"esp32c6_8mb": [
"exclude"
],
"esp32*": []
}
}

View File

@@ -0,0 +1,289 @@
#include "Global.h"
#include "classes/IoTUart.h"
#include "datatypes.h"
//namespace bl0942
//{
class BL0942cmd;
BL0942cmd *BL0942 = nullptr;
DataPacket buffer;
uint8_t inpos = 0xFF;
uint8_t checksum;
uint8_t pubPhase = 0xFF;
bool needUpdate = false;
static const float BL0942_PREF = 596; // taken from tasmota
static const float BL0942_UREF = 15873.35944299; // should be 73989/1.218
static const float BL0942_IREF = 251213.46469622; // 305978/1.218
static const float BL0942_EREF = 3304.61127328; // Measured
static const char *const TAG = "bl0942";
static const uint8_t BL0942_READ_COMMAND = 0x58;
static const uint8_t BL0942_FULL_PACKET = 0xAA;
static const uint8_t BL0942_PACKET_HEADER = 0x55;
static const uint8_t BL0942_WRITE_COMMAND = 0xA8;
static const uint8_t BL0942_REG_I_FAST_RMS_CTRL = 0x10;
static const uint8_t BL0942_REG_MODE = 0x18;
static const uint8_t BL0942_REG_SOFT_RESET = 0x19;
static const uint8_t BL0942_REG_USR_WRPROT = 0x1A;
static const uint8_t BL0942_REG_TPS_CTRL = 0x1B;
// TODO: Confirm insialisation works as intended
const uint8_t BL0942_INIT[5][6] = {
// Reset to default
{BL0942_WRITE_COMMAND, BL0942_REG_SOFT_RESET, 0x5A, 0x5A, 0x5A, 0x38},
// Enable User Operation Write
{BL0942_WRITE_COMMAND, BL0942_REG_USR_WRPROT, 0x55, 0x00, 0x00, 0xF0},
// 0x0100 = CF_UNABLE energy pulse, AC_FREQ_SEL 50Hz, RMS_UPDATE_SEL 800mS
{BL0942_WRITE_COMMAND, BL0942_REG_MODE, 0x00, 0x10, 0x00, 0x37},
// 0x47FF = Over-current and leakage alarm on, Automatic temperature measurement, Interval 100mS
{BL0942_WRITE_COMMAND, BL0942_REG_TPS_CTRL, 0xFF, 0x47, 0x00, 0xFE},
// 0x181C = Half cycle, Fast RMS threshold 6172
{BL0942_WRITE_COMMAND, BL0942_REG_I_FAST_RMS_CTRL, 0x1C, 0x18, 0x00, 0x1B}};
class BL0942cmd : public IoTUart
{
private:
float i_rms, watt, v_rms, frequency, total_energy_consumption = 0;
// Divide by this to turn into Watt
float power_reference_ = BL0942_PREF;
// Divide by this to turn into Volt
float voltage_reference_ = BL0942_UREF;
// Divide by this to turn into Ampere
float current_reference_ = BL0942_IREF;
// Divide by this to turn into kWh
float energy_reference_ = BL0942_EREF;
public:
BL0942cmd(String parameters) : IoTUart(parameters)
{
/*
jsonRead(parameters, "R_current", CURRENT_RESISTOR);
jsonRead(parameters, "R_upstream", VOLTAGE_RESISTOR_UPSTREAM);
jsonRead(parameters, "R_downstream", VOLTAGE_RESISTOR_DOWNSTREAM);
jsonRead(parameters, "CF_GPIO", BL0942_CF_GPIO);
jsonRead(parameters, "CF1_GPIO", BL0942_CF1_GPIO);
jsonRead(parameters, "SEL_GPIO", BL0942_SEL_GPIO_INV);
jsonRead(parameters, "kfV", _kfV);
jsonRead(parameters, "kfA", _kfA);
jsonRead(parameters, "kfW", _kfW);
*/
for (auto *i : BL0942_INIT)
{
_myUART->write(i, 6);
delay(1);
}
_myUART->flush();
BL0942 = this;
}
void loop()
{
if (_myUART->available())
{
while (_myUART->available())
{
uint8_t in;
_myUART->readBytes(&in, 1);
if (inpos < sizeof(buffer) - 1)
{ // читаем тело пакета
((uint8_t *)(&buffer))[inpos] = in;
inpos++;
checksum += in;
}
else if (inpos < sizeof(buffer))
{ // получили контрольную сумму
inpos++;
checksum ^= 0xFF;
if (in != checksum)
{
ESP_LOGE(TAG, "BL0942 invalid checksum! 0x%02X != 0x%02X", checksum, in);
}
else
{
pubPhase = 0;
}
}
else
{
if (in == BL0942_PACKET_HEADER)
{ // стартовый хидер
((uint8_t *)(&buffer))[0] = BL0942_PACKET_HEADER;
inpos = 1; // начало сохранения буфера
checksum = BL0942_READ_COMMAND + BL0942_PACKET_HEADER; // начальные данные рассчета кс
pubPhase = 3;
}
else
{
ESP_LOGE(TAG, "Invalid data. Header mismatch: %d", in);
}
}
}
}
else if (pubPhase < 3)
{
if (pubPhase == 0)
{
i_rms = (uint24_t)buffer.i_rms / current_reference_;
watt = (int24_t)buffer.watt / power_reference_;
pubPhase = 1;
}
else if (pubPhase == 1)
{
v_rms = (uint24_t)buffer.v_rms / voltage_reference_;
frequency = 1000000.0f / buffer.frequency;
pubPhase = 2;
}
else if (pubPhase == 2)
{
uint32_t cf_cnt = (uint24_t)buffer.cf_cnt;
total_energy_consumption = cf_cnt / energy_reference_;
pubPhase = 3;
}
}
IoTItem::loop();
}
void doByInterval()
{
_myUART->write(BL0942_READ_COMMAND);
_myUART->write(BL0942_FULL_PACKET);
}
float getEnergy() { return total_energy_consumption; }
float getPower() { return watt; }
float getCurrent() { return i_rms; }
float getVoltage() { return v_rms; }
~BL0942cmd(){
};
};
class BL0942v : public IoTItem
{
private:
public:
BL0942v(String parameters) : IoTItem(parameters)
{
}
void doByInterval()
{
if (BL0942)
regEvent(BL0942->getVoltage(), "BL0942 V");
else
{
regEvent(NAN, "BL0942v");
SerialPrint("E", "BL0942cmd", "initialization error", _id);
}
}
~BL0942v(){};
};
class BL0942a : public IoTItem
{
private:
public:
BL0942a(String parameters) : IoTItem(parameters)
{
}
void doByInterval()
{
if (BL0942)
regEvent(BL0942->getCurrent(), "BL0942 A");
else
{
regEvent(NAN, "BL0942a");
SerialPrint("E", "BL0942cmd", "initialization error", _id);
}
}
~BL0942a(){};
};
class BL0942w : public IoTItem
{
private:
public:
BL0942w(String parameters) : IoTItem(parameters)
{
}
void doByInterval()
{
if (BL0942)
regEvent(BL0942->getPower(), "BL0942 W");
else
{
regEvent(NAN, "BL0942w");
SerialPrint("E", "BL0942cmd", "initialization error", _id);
}
}
~BL0942w(){};
};
class BL0942wh : public IoTItem
{
private:
public:
BL0942wh(String parameters) : IoTItem(parameters)
{
}
void doByInterval()
{
if (BL0942)
regEvent(BL0942->getEnergy() / 3600.0 / 1000.0, "BL0942 Wh");
else
{
regEvent(NAN, "BL0942wh");
SerialPrint("E", "BL0942cmd", "initialization error", _id);
}
}
~BL0942wh(){};
};
//} // namespace bl0942
void *getAPI_BL0942(String subtype, String param)
{
if (subtype == F("BL0942v"))
{
return new BL0942v(param);
}
else if (subtype == F("BL0942a"))
{
return new BL0942a(param);
}
else if (subtype == F("BL0942w"))
{
return new BL0942w(param);
}
else if (subtype == F("BL0942wh"))
{
return new BL0942wh(param);
}
else if (subtype == F("BL0942cmd"))
{
return new BL0942cmd(param);
}
else
{
return nullptr;
}
}

View File

@@ -0,0 +1,116 @@
#pragma once
#include <cstdint>
//#include "helpers.h"
namespace internal {
// Various functions can be constexpr in C++14, but not in C++11 (because their body isn't just a return statement).
// Define a substitute constexpr keyword for those functions, until we can drop C++11 support.
#if __cplusplus >= 201402L
#define constexpr14 constexpr
#else
#define constexpr14 inline // constexpr implies inline
#endif
// std::byteswap from C++23
template<typename T> constexpr14 T byteswap(T n) {
T m;
for (size_t i = 0; i < sizeof(T); i++)
reinterpret_cast<uint8_t *>(&m)[i] = reinterpret_cast<uint8_t *>(&n)[sizeof(T) - 1 - i];
return m;
}
template<> constexpr14 uint8_t byteswap(uint8_t n) { return n; }
template<> constexpr14 uint16_t byteswap(uint16_t n) { return __builtin_bswap16(n); }
template<> constexpr14 uint32_t byteswap(uint32_t n) { return __builtin_bswap32(n); }
template<> constexpr14 uint64_t byteswap(uint64_t n) { return __builtin_bswap64(n); }
template<> constexpr14 int8_t byteswap(int8_t n) { return n; }
template<> constexpr14 int16_t byteswap(int16_t n) { return __builtin_bswap16(n); }
template<> constexpr14 int32_t byteswap(int32_t n) { return __builtin_bswap32(n); }
template<> constexpr14 int64_t byteswap(int64_t n) { return __builtin_bswap64(n); }
/// Convert a value between host byte order and big endian (most significant byte first) order.
template<typename T> constexpr14 T convert_big_endian(T val) {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
return byteswap(val);
#else
return val;
#endif
}
/// Convert a value between host byte order and little endian (least significant byte first) order.
template<typename T> constexpr14 T convert_little_endian(T val) {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
return val;
#else
return byteswap(val);
#endif
}
/// Wrapper class for memory using big endian data layout, transparently converting it to native order.
template<typename T> class BigEndianLayout {
public:
constexpr14 operator T() { return convert_big_endian(val_); }
private:
T val_;
} __attribute__((packed));
/// Wrapper class for memory using big endian data layout, transparently converting it to native order.
template<typename T> class LittleEndianLayout {
public:
constexpr14 operator T() { return convert_little_endian(val_); }
private:
T val_;
} __attribute__((packed));
} // namespace internal
/// 24-bit unsigned integer type, transparently converting to 32-bit.
struct uint24_t { // NOLINT(readability-identifier-naming)
operator uint32_t() { return val; }
uint32_t val : 24;
} __attribute__((packed));
/// 24-bit signed integer type, transparently converting to 32-bit.
struct int24_t { // NOLINT(readability-identifier-naming)
operator int32_t() { return val; }
int32_t val : 24;
} __attribute__((packed));
// Integer types in big or little endian data layout.
using uint64_be_t = internal::BigEndianLayout<uint64_t>;
using uint32_be_t = internal::BigEndianLayout<uint32_t>;
using uint24_be_t = internal::BigEndianLayout<uint24_t>;
using uint16_be_t = internal::BigEndianLayout<uint16_t>;
using int64_be_t = internal::BigEndianLayout<int64_t>;
using int32_be_t = internal::BigEndianLayout<int32_t>;
using int24_be_t = internal::BigEndianLayout<int24_t>;
using int16_be_t = internal::BigEndianLayout<int16_t>;
using uint64_le_t = internal::LittleEndianLayout<uint64_t>;
using uint32_le_t = internal::LittleEndianLayout<uint32_t>;
using uint24_le_t = internal::LittleEndianLayout<uint24_t>;
using uint16_le_t = internal::LittleEndianLayout<uint16_t>;
using int64_le_t = internal::LittleEndianLayout<int64_t>;
using int32_le_t = internal::LittleEndianLayout<int32_t>;
using int24_le_t = internal::LittleEndianLayout<int24_t>;
using int16_le_t = internal::LittleEndianLayout<int16_t>;
struct DataPacket {
uint8_t frame_header;
uint24_le_t i_rms;
uint24_le_t v_rms;
uint24_le_t i_fast_rms;
int24_le_t watt;
uint24_le_t cf_cnt;
uint16_le_t frequency;
uint8_t reserved1;
uint8_t status;
uint8_t reserved2;
uint8_t reserved3;
uint8_t checksum;
} __attribute__((packed));

View File

@@ -0,0 +1,108 @@
{
"menuSection": "sensors",
"configItem": [
{
"global": 0,
"name": "BL0942 Напряжение",
"type": "Reading",
"subtype": "BL0942v",
"id": "bl_v",
"widget": "anydataVlt",
"page": "BL0942",
"descr": "Напряжение",
"int": 15,
"round": 1
},
{
"global": 0,
"name": "BL0942 Сила тока",
"type": "Reading",
"subtype": "BL0942a",
"id": "bl_a",
"widget": "anydataAmp",
"page": "BL0942",
"descr": "Сила тока",
"int": 15,
"round": 1
},
{
"global": 0,
"name": "BL0942 Мощность",
"type": "Reading",
"subtype": "BL0942w",
"id": "bl_w",
"widget": "anydataWt",
"page": "BL0942",
"descr": "Мощность",
"int": 15,
"round": 1
},
{
"global": 0,
"name": "BL0942 Энергия",
"type": "Reading",
"subtype": "BL0942wh",
"id": "bl_wh",
"widget": "anydataWth",
"page": "BL0942",
"descr": "Энергия",
"int": 15,
"round": 1
},
{
"global": 0,
"name": "BL0942 настройка",
"type": "Reading",
"subtype": "BL0942cmd",
"id": "bl_set",
"widget": "nil",
"page": "",
"descr": "",
"int": "5",
"tx": 17,
"rx": 16,
"line": 2,
"speed": 9600
}
],
"about": {
"authorName": "Bubnov Mikhail",
"authorContact": "https://t.me/Mit4bmw",
"authorGit": "https://github.com/Mit4el",
"specialThanks": "",
"moduleName": "BL0942",
"moduleVersion": "1.0",
"usedRam": {
"esp32_4mb": 15,
"esp8266_4mb": 15
},
"title": "Счетчик электроэнергии BL0942",
"moduleDesc": "Считает потраченную электроэнергию, измеряет напряжение, силу тока и прочие параметры.",
"propInfo": {
"int": "Количество секунд между опросами датчика. В bl_set интервал между попытками калибровки (т.к. нужны сначала данные от датчика)",
"btn-reset": "Энергия BL0942 будет сброшена к нулю.",
"R_current": "Резистор подключенный последовательно к основной линии",
"R_upstream": "это 5 резисторов по 470 Ком в делителе напряжения, который питает вывод V2P",
"R_downstream": "это резистор емкостью 1 Ком в делителе напряжения, который питает вывод V2P",
"CF_GPIO": "пин CF",
"CF1_GPIO": "пин CF1",
"SEL_GPIO": "пин SEL",
"kfV": "Коэффициент корректировки напряжение, указать после калибровки",
"kfA": "Коэффициент корректировки тока, указать после калибровки",
"kfW": "Коэффициент корректировки мощности, указать после калибровки"
},
"funcInfo": [
{
"name": "calibration",
"descr": "Расчет коэффициентов калибровки. Вызывать от имени BL0942 настройка. bl_set.calibration(220, 16, 3.5). Полученный коэффициенты искать в логе и ввести в конфигурацию kfV, kfA и kfW",
"params": ["Напряжение, Ток, Мощность"]
}
]
},
"defActive": true,
"usedLibs": {
"esp32*": [],
"esp82*": [],
"bk72*": []
}
}

View File

@@ -178,7 +178,11 @@ void scanEndedCB(NimBLEScanResults results)
// pBLEScan->clearResults();
}
//#if defined (esp32c6_4mb) || defined (esp32c6_8mb)
//class BleScan : public IoTItem, NimBLEScanCallbacks
//#else
class BleScan : public IoTItem, BLEAdvertisedDeviceCallbacks
//#endif
{
private:
// описание параметров передаваемых из настроек датчика из веба
@@ -218,7 +222,9 @@ public:
BLEdata["manufacturerdata"] = manufacturerdata;
free(manufacturerdata);
}
#if !defined (esp32c6_4mb) && !defined (esp32c6_8mb)
if (advertisedDevice->haveRSSI())
#endif
BLEdata["rssi"] = (int)advertisedDevice->getRSSI();
if (advertisedDevice->haveTXPower())
BLEdata["txpower"] = (int8_t)advertisedDevice->getTXPower();
@@ -243,7 +249,6 @@ public:
mac_address = BLEdata["id"].as<const char *>();
}
mac_address.replace(":", "");
if (_debug < 2)
{
BLEdata.remove("manufacturerdata");
@@ -297,7 +302,11 @@ public:
BLEDevice::init("");
pBLEScan = BLEDevice::getScan(); // create new scan
#if defined (esp32c6_4mb) || defined (esp32c6_8mb)
pBLEScan->setScanCallbacks(this);
#else
pBLEScan->setAdvertisedDeviceCallbacks(this);
#endif
pBLEScan->setActiveScan(false); // active scan uses more power, but get results faster
pBLEScan->setInterval(100);
pBLEScan->setWindow(99); // less or equal setInterval value
@@ -312,7 +321,11 @@ public:
if (_scanDuration > 0)
{
SerialPrint("i", F("BLE"), "Start Scanning...");
#if defined (esp32c6_4mb) || defined (esp32c6_8mb)
pBLEScan->start(_scanDuration, false);
#else
pBLEScan->start(_scanDuration, scanEndedCB, false);
#endif
}
}
}

View File

@@ -64,10 +64,10 @@
},
"defActive": false,
"usedLibs": {
"esp32c62_4mb": [
"esp32c6_4mb": [
"https://github.com/h2zero/NimBLE-Arduino#c6-build"
],
"esp32c62_8mb": [
"esp32c6_8mb": [
"https://github.com/h2zero/NimBLE-Arduino#c6-build"
],
"esp32_4mb3f": [

View File

@@ -178,7 +178,11 @@ void scanEndedCB(NimBLEScanResults results)
// pBLEScan->clearResults();
}
//#if defined (esp32c6_4mb) || defined (esp32c6_8mb)
//class BleScan : public IoTItem, NimBLEScanCallbacks
//#else
class BleScan : public IoTItem, BLEAdvertisedDeviceCallbacks
//#endif
{
private:
// описание параметров передаваемых из настроек датчика из веба
@@ -218,7 +222,9 @@ public:
BLEdata["manufacturerdata"] = manufacturerdata;
free(manufacturerdata);
}
#if !defined (esp32c6_4mb) && !defined (esp32c6_8mb)
if (advertisedDevice->haveRSSI())
#endif
BLEdata["rssi"] = (int)advertisedDevice->getRSSI();
if (advertisedDevice->haveTXPower())
BLEdata["txpower"] = (int8_t)advertisedDevice->getTXPower();
@@ -296,7 +302,11 @@ public:
BLEDevice::init("");
pBLEScan = BLEDevice::getScan(); // create new scan
#if defined (esp32c6_4mb) || defined (esp32c6_8mb)
pBLEScan->setScanCallbacks(this);
#else
pBLEScan->setAdvertisedDeviceCallbacks(this);
#endif
pBLEScan->setActiveScan(false); // active scan uses more power, but get results faster
pBLEScan->setInterval(100);
pBLEScan->setWindow(99); // less or equal setInterval value
@@ -311,7 +321,11 @@ public:
if (_scanDuration > 0)
{
SerialPrint("i", F("BLE"), "Start Scanning...");
#if defined (esp32c6_4mb) || defined (esp32c6_8mb)
pBLEScan->start(_scanDuration, false);
#else
pBLEScan->start(_scanDuration, scanEndedCB, false);
#endif
}
}
}

View File

@@ -64,6 +64,12 @@
},
"defActive": false,
"usedLibs": {
"esp32c6_4mb": [
"https://github.com/h2zero/NimBLE-Arduino#c6-build"
],
"esp32c6_8mb": [
"https://github.com/h2zero/NimBLE-Arduino#c6-build"
],
"esp32*": [
"https://github.com/Mit4el/NimBLE-Arduino.git"
],

View File

@@ -178,7 +178,11 @@ void scanEndedCB(NimBLEScanResults results)
// pBLEScan->clearResults();
}
//#if defined (esp32c6_4mb) || defined (esp32c6_8mb)
//class BleScan : public IoTItem, NimBLEScanCallbacks
//#else
class BleScan : public IoTItem, BLEAdvertisedDeviceCallbacks
//#endif
{
private:
// описание параметров передаваемых из настроек датчика из веба
@@ -218,7 +222,9 @@ public:
BLEdata["manufacturerdata"] = manufacturerdata;
free(manufacturerdata);
}
#if !defined (esp32c6_4mb) && !defined (esp32c6_8mb)
if (advertisedDevice->haveRSSI())
#endif
BLEdata["rssi"] = (int)advertisedDevice->getRSSI();
if (advertisedDevice->haveTXPower())
BLEdata["txpower"] = (int8_t)advertisedDevice->getTXPower();
@@ -254,7 +260,6 @@ public:
BLEdata.remove("track");
BLEdata.remove("id");
}
// дописываем время прихода пакета данных
BLEdata["last"] = millis();
if (_debug)
@@ -297,7 +302,11 @@ public:
BLEDevice::init("");
pBLEScan = BLEDevice::getScan(); // create new scan
#if defined (esp32c6_4mb) || defined (esp32c6_8mb)
pBLEScan->setScanCallbacks(this);
#else
pBLEScan->setAdvertisedDeviceCallbacks(this);
#endif
pBLEScan->setActiveScan(false); // active scan uses more power, but get results faster
pBLEScan->setInterval(100);
pBLEScan->setWindow(99); // less or equal setInterval value
@@ -312,7 +321,11 @@ public:
if (_scanDuration > 0)
{
SerialPrint("i", F("BLE"), "Start Scanning...");
#if defined (esp32c6_4mb) || defined (esp32c6_8mb)
pBLEScan->start(_scanDuration, false);
#else
pBLEScan->start(_scanDuration, scanEndedCB, false);
#endif
}
}
}

View File

@@ -64,6 +64,12 @@
},
"defActive": false,
"usedLibs": {
"esp32c6_4mb": [
"https://github.com/h2zero/NimBLE-Arduino#c6-build"
],
"esp32c6_8mb": [
"https://github.com/h2zero/NimBLE-Arduino#c6-build"
],
"esp32*": [
"https://github.com/Mit4el/NimBLE-Arduino.git"
],

View File

@@ -28,25 +28,25 @@ public:
// mqttSubscribeExternal(_topic);
}
}
/*
void onMqttRecive(String &topic, String &msg)
{
if (!HA)
return;
if (msg.indexOf("HELLO") == -1)
/*
void onMqttRecive(String &topic, String &msg)
{
String dev = selectToMarkerLast(topic, "/");
dev.toUpperCase();
dev.replace(":", "");
if (_topic != topic)
{
// SerialPrint("i", "ExternalMQTT", _id + " not equal: " + topic + " msg: " + msg);
if (!HA)
return;
if (msg.indexOf("HELLO") == -1)
{
String dev = selectToMarkerLast(topic, "/");
dev.toUpperCase();
dev.replace(":", "");
if (_topic != topic)
{
// SerialPrint("i", "ExternalMQTT", _id + " not equal: " + topic + " msg: " + msg);
return;
}
// обработка топика, на который подписались
}
// обработка топика, на который подписались
}
} */
} */
void doByInterval()
{
@@ -96,7 +96,7 @@ public:
jsonWriteInt(errorsHeapJson, F("jse3"), 1); // Ошибка чтения json файла с виджетами при отправки в mqtt
}
int i = 0;
// String path = jsonReadStr(settingsFlashJson, F("HomeAssistant"));
// String HATopic = jsonReadStr(settingsFlashJson, F("HomeAssistant"));
JsonArray arr = doc.as<JsonArray>();
for (JsonVariant value : arr)
{
@@ -104,7 +104,7 @@ public:
dev.replace(":", "");
String HAjson = "";
HAjson = "{\"availability\":[{\"topic\": \"" + mqttRootDevice + "/state\",\"value_template\": \"{{ value_json.status }}\"}],\"availability_mode\": \"any\",";
HAjson = HAjson + " \"device\": {\"identifiers\": [\"" + value["page"].as<String>() + "\"],";
HAjson = HAjson + " \"device\": {\"identifiers\": [\"" + mqttRootDevice + value["page"].as<String>() + "\"],";
HAjson = HAjson + " \"name\": \" " + value["page"].as<String>() + "\"},";
HAjson = HAjson + " \"name\": \"" + value["descr"].as<String>() + "\",";
HAjson = HAjson + " \"state_topic\": \"" + value["topic"].as<String>() + "/status\",";
@@ -114,22 +114,39 @@ public:
if (value["name"].as<String>() == "anydataTmp")
{
HAjson = HAjson + " \"value_template\": \"{{ float( value_json.status, default = 0) | default }}\",";
HAjson = HAjson + " \"unique_id\": \"" + dev + "\",";
HAjson = HAjson + " \"state_class\": \"measurement\",";
HAjson = HAjson + " \"unique_id\": \"" + mqttRootDevice + dev + "\",";
HAjson = HAjson + " \"unit_of_measurement\": \"°C\"";
}
else if (value["name"].as<String>() == "anydataHum")
{
HAjson = HAjson + " \"value_template\": \"{{ float( value_json.status, default = 0) | default }}\",";
HAjson = HAjson + " \"unique_id\": \"" + dev + "\",";
HAjson = HAjson + " \"state_class\": \"measurement\",";
HAjson = HAjson + " \"unique_id\": \"" + mqttRootDevice + dev + "\",";
HAjson = HAjson + " \"unit_of_measurement\": \"%\"";
}
// ввод числа
else if (value["name"].as<String>() == "anydataMm")
{
HAjson = HAjson + " \"value_template\": \"{{ float( value_json.status, default = 0) | default }}\",";
HAjson = HAjson + " \"unique_id\": \"" + mqttRootDevice + dev + "\",";
HAjson = HAjson + " \"unit_of_measurement\": \"mm\"";
}
else if (value["name"].as<String>() == "anydataBar")
{
HAjson = HAjson + " \"value_template\": \"{{ float( value_json.status, default = 0) | default }}\",";
HAjson = HAjson + " \"unique_id\": \"" + mqttRootDevice + dev + "\",";
HAjson = HAjson + " \"unit_of_measurement\": \"Bar\"";
}
else if (value["name"].as<String>() == "anydataPpm")
{
HAjson = HAjson + " \"value_template\": \"{{ float( value_json.status, default = 0) | default }}\",";
HAjson = HAjson + " \"unique_id\": \"" + mqttRootDevice + dev + "\",";
HAjson = HAjson + " \"unit_of_measurement\": \"ppm\"";
}
// ввод числаФВ
else if (value["name"].as<String>() == "inputDgt")
{
HAjson = HAjson + " \"value_template\": \"{{ float( value_json.status, default = 0) | default }}\",";
HAjson = HAjson + " \"unique_id\": \"" + dev + "\",";
HAjson = HAjson + " \"unique_id\": \"" + mqttRootDevice + dev + "\",";
HAjson = HAjson + " \"command_topic\": \"" + value["topic"].as<String>() + "/control\",";
HAjson = HAjson + " \"mode\": \"box\",";
HAjson = HAjson + " \"min\": " + -1000000 + ",";
@@ -139,14 +156,14 @@ public:
else if (value["name"].as<String>() == "inputTxt")
{
HAjson = HAjson + " \"value_template\": \"{{ value_json.status | default }}\",";
HAjson = HAjson + " \"unique_id\": \"" + dev + "\",";
HAjson = HAjson + " \"unique_id\": \"" + mqttRootDevice + dev + "\",";
HAjson = HAjson + " \"command_topic\": \"" + value["topic"].as<String>() + "/control\"";
}
// переключатель
else if (value["name"].as<String>() == "toggle")
{
HAjson = HAjson + " \"value_template\": \"{{ value_json.status | default }}\",";
HAjson = HAjson + " \"unique_id\": \"" + dev + "\",";
HAjson = HAjson + " \"unique_id\": \"" + mqttRootDevice + dev + "\",";
HAjson = HAjson + " \"command_topic\": \"" + value["topic"].as<String>() + "/control\",";
HAjson = HAjson + " \"device_class\": \"switch\",";
HAjson = HAjson + " \"payload_off\": " + 0 + ",";
@@ -157,7 +174,7 @@ public:
else
{
HAjson = HAjson + " \"value_template\": \"{{ value_json.status | default }}\",";
HAjson = HAjson + " \"unique_id\": \"" + dev + "\"";
HAjson = HAjson + " \"unique_id\": \"" + mqttRootDevice + dev + "\"";
}
HAjson = HAjson + " }";

View File

@@ -8,16 +8,29 @@ private:
bool sendOk = false;
// bool topicOk = false;
bool HOMEd = false;
int _names = 0;
String esp_id = chipId;
public:
DiscoveryHomeD(String parameters) : IoTDiscovery(parameters)
{
_topic = jsonReadStr(parameters, "topic");
_names = jsonReadInt(parameters, "names");
if (_topic && _topic != "" && _topic != "null")
{
HOMEd = true;
HOMEdTopic = _topic;
}
if (_names)
{
esp_id = jsonReadStr(settingsFlashJson, F("name"));
jsonWriteInt(settingsFlashJson, F("HOMEd_names"), 1);
}
else
{
jsonWriteInt(settingsFlashJson, F("HOMEd_names"), 0);
}
if (mqttIsConnect() && HOMEd)
{
mqttReconnect();
@@ -33,14 +46,14 @@ public:
if (payloadStr.indexOf("HELLO") == -1)
{
/* String dev = selectToMarkerLast(topic, "/");
dev.toUpperCase();
dev.replace(":", "");
if (_topic != topic)
{
// SerialPrint("i", "ExternalMQTT", _id + " not equal: " + topic + " msg: " + msg);
return;
} */
/* String dev = selectToMarkerLast(topic, "/");
dev.toUpperCase();
dev.replace(":", "");
if (_topic != topic)
{
// SerialPrint("i", "ExternalMQTT", _id + " not equal: " + topic + " msg: " + msg);
return;
} */
// обработка топика, на который подписались
if (topic.indexOf(F("/td/custom")) != -1)
{
@@ -52,7 +65,6 @@ public:
{
String key = kvp.key().c_str();
SerialPrint("i", F("=>MQTT"), "Msg from HOMEd: " + key);
String value = kvp.value().as<const char *>();
if (key.indexOf(F("status_")) != -1)
{
@@ -71,11 +83,17 @@ public:
generateOrder(key, val);
}
}
if (!value)
else
{
float val = kvp.value();
generateOrder(key, (String)(val));
if (!value)
{
float val = kvp.value();
generateOrder(key, (String)(val));
}
else
{
generateOrder(key, value);
}
}
}
@@ -90,8 +108,8 @@ public:
if (mqttIsConnect() && !sendOk && topicOk)
{
sendOk = true;
publishRetain(_topic + "/device/custom/" + nameId, "{\"status\":\"online\"}");
String HOMEdsubscribeTopic = _topic + "/td/custom/" + nameId;
publishRetain(_topic + "/device/custom/" + esp_id, "{\"status\":\"online\"}");
String HOMEdsubscribeTopic = _topic + "/td/custom/" + esp_id;
// mqtt.subscribe(HOMEdsubscribeTopic.c_str());
mqttSubscribeExternal(HOMEdsubscribeTopic);
}
@@ -103,7 +121,7 @@ public:
void publishStatusHOMEd(const String &topic, const String &data)
{
String path_h = HOMEdTopic + "/fd/custom/" + nameId;
String path_h = HOMEdTopic + "/fd/custom/" + esp_id;
String json_h = "{}";
if (topic != "onStart")
{
@@ -133,8 +151,8 @@ public:
{
deleteFromHOMEd();
getlayoutHOMEd();
publishRetain(HOMEdTopic + "/device/custom/" + nameId, "{\"status\":\"online\"}");
String HOMEdsubscribeTopic = HOMEdTopic + "/td/custom/" + nameId;
publishRetain(HOMEdTopic + "/device/custom/" + esp_id, "{\"status\":\"online\"}");
String HOMEdsubscribeTopic = HOMEdTopic + "/td/custom/" + esp_id;
mqtt.subscribe(HOMEdsubscribeTopic.c_str());
}
}
@@ -164,7 +182,7 @@ public:
JsonArray arr = doc.as<JsonArray>();
String HOMEdJSON = "";
HOMEdJSON = "{\"action\":\"updateDevice\",";
HOMEdJSON = HOMEdJSON + "\"device\":\"" + nameId + "\",";
HOMEdJSON = HOMEdJSON + "\"device\":\"" + chipId + "\",";
HOMEdJSON = HOMEdJSON + "\"data\":{";
HOMEdJSON = HOMEdJSON + "\"active\": true,";
HOMEdJSON = HOMEdJSON + "\"cloud\": false,";
@@ -178,7 +196,7 @@ public:
{
String name = value["descr"];
String device = selectToMarkerLast(value["topic"].as<String>(), "/");
//String id = chipId + "-" + device;
// String id = ChipId + "-" + device;
String expose = value["name"];
if (value["name"].as<String>() == "toggle")
{
@@ -219,7 +237,7 @@ public:
file.close();
publishRetain(HOMEdTopic + "/device/custom/" + nameId, "{\"status\":\"online\"}");
publishRetain(HOMEdTopic + "/device/custom/" + esp_id, "{\"status\":\"online\"}");
for (std::list<IoTItem *>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it)
{
@@ -243,7 +261,7 @@ public:
String HOMEdjson = "";
HOMEdjson = "{\"action\":\"removeDevice\",";
HOMEdjson = HOMEdjson + "\"device\":\"";
HOMEdjson = HOMEdjson + nameId;
HOMEdjson = HOMEdjson + chipId;
HOMEdjson = HOMEdjson + "\"}";
String topic = (HOMEdTopic + "/command/custom").c_str();
if (!publish(topic, HOMEdjson))

View File

@@ -10,7 +10,8 @@
"widget": "",
"page": "",
"descr": "",
"topic": "homed"
"topic": "homed",
"names":1
}
],
"about": {

View File

@@ -0,0 +1,6 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, , 3000K,
app1, app, ota_1, , 3000K,
spiffs, data, spiffs, , 1500K,
1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x9000 0x5000
3 otadata data ota 0xe000 0x2000
4 app0 app ota_0 3000K
5 app1 app ota_1 3000K
6 spiffs data spiffs 1500K