8 Commits

Author SHA1 Message Date
Yurii
842b443723 refactor: final changes 2025-03-06 04:38:39 +03:00
Yurii
3bf65aeaad chore: cleaning 2025-03-05 02:15:01 +03:00
Yurii
1b004b25c7 refactor: added idf and `h2zero/esp-nimble-cpp` for esp32 c6 2025-03-04 21:27:30 +03:00
Yurii
95b18385ba chore: gitignore update 2025-03-04 17:50:59 +03:00
Yurii
4457e16a8f refactor: increased opentherm disconnect timeout 2025-02-27 12:48:27 +03:00
Yurii
1965ca671e chore: bump pioarduino/platform-espressif32 from 3.1.2 to 3.1.3 2025-02-20 16:50:06 +03:00
Yurii
0d1873ec77 fix: set SSID on click in table of available networks fixed 2025-02-17 19:37:51 +03:00
Yurii
38ec56fb33 fix: working with `Sensors::Type::MANUAL` sensors fixed 2025-02-17 18:58:01 +03:00
8 changed files with 133 additions and 54 deletions

9
.gitignore vendored
View File

@@ -1,8 +1,13 @@
.pio .pio
.vscode .vscode
build/*.bin build/*
data/* data/*
managed_components/*
node_modules/*
secrets.ini secrets.ini
node_modules
package-lock.json package-lock.json
*.lock
sdkconfig.*
CMakeLists.txt
!sdkconfig.defaults
!.gitkeep !.gitkeep

View File

@@ -84,7 +84,7 @@ board_build.ldscript = eagle.flash.4m1m.ld
;platform_packages = ;platform_packages =
; framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.5 ; framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.5
; framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.1/esp32-arduino-libs-idf-release_v5.1-33fbade6.zip ; framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.1/esp32-arduino-libs-idf-release_v5.1-33fbade6.zip
platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.12/platform-espressif32.zip platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.13/platform-espressif32.zip
platform_packages = platform_packages =
board_build.partitions = esp32_partitions.csv board_build.partitions = esp32_partitions.csv
lib_deps = lib_deps =
@@ -287,21 +287,26 @@ build_flags =
[env:esp32_c6] [env:esp32_c6]
platform = ${esp32_defaults.platform} platform = ${esp32_defaults.platform}
framework = arduino, espidf
platform_packages = ${esp32_defaults.platform_packages} platform_packages = ${esp32_defaults.platform_packages}
board = esp32-c6-devkitm-1 board = esp32-c6-devkitm-1
board_build.partitions = ${esp32_defaults.board_build.partitions} board_build.partitions = ${esp32_defaults.board_build.partitions}
lib_deps = lib_deps = ${esp32_defaults.lib_deps}
${esp32_defaults.lib_deps} lib_ignore =
;${esp32_defaults.nimble_lib} ${esp32_defaults.lib_ignore}
lib_ignore = ${esp32_defaults.lib_ignore}
extra_scripts = ${esp32_defaults.extra_scripts} extra_scripts = ${esp32_defaults.extra_scripts}
build_unflags = build_unflags =
-mtext-section-literals -mtext-section-literals
build_type = ${esp32_defaults.build_type} build_type = ${esp32_defaults.build_type}
build_flags = build_flags =
${esp32_defaults.build_flags} ${esp32_defaults.build_flags}
; Currently the NimBLE library is incompatible with ESP32 C6 -D USE_BLE=1
;-D USE_BLE=1 -D DEFAULT_OT_IN_GPIO=15
-D DEFAULT_OT_OUT_GPIO=23
-D DEFAULT_SENSOR_OUTDOOR_GPIO=0
-D DEFAULT_SENSOR_INDOOR_GPIO=0
-D DEFAULT_STATUS_LED_GPIO=11
-D DEFAULT_OT_RX_LED_GPIO=10
[env:otthing] [env:otthing]
platform = ${esp32_defaults.platform} platform = ${esp32_defaults.platform}

33
sdkconfig.defaults Normal file
View File

@@ -0,0 +1,33 @@
# Source:
# https://github.com/pioarduino/platform-espressif32/tree/main/examples/espidf-arduino-h2zero-BLE_scan
CONFIG_FREERTOS_HZ=1000
CONFIG_MBEDTLS_PSK_MODES=y
CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y
#
# BT config
CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y
#
# Arduino Configuration
CONFIG_AUTOSTART_ARDUINO=y
CONFIG_ARDUINO_SELECTIVE_COMPILATION=y
CONFIG_ARDUINO_SELECTIVE_Zigbee=n
CONFIG_ARDUINO_SELECTIVE_Matter=n
CONFIG_ARDUINO_SELECTIVE_WiFiProv=n
CONFIG_ARDUINO_SELECTIVE_BLE=n
CONFIG_ARDUINO_SELECTIVE_BluetoothSerial=n
CONFIG_ARDUINO_SELECTIVE_SimpleBLE=n
CONFIG_ARDUINO_SELECTIVE_RainMaker=n
CONFIG_ARDUINO_SELECTIVE_OpenThread=n
CONFIG_ARDUINO_SELECTIVE_Insights=n

View File

@@ -70,8 +70,8 @@ public:
this->prevPubVarsTime = 0; this->prevPubVarsTime = 0;
} }
inline void rebuildHaEntity(uint8_t sensorId, Sensors::Settings& prevSettings) { inline void reconfigureSensor(uint8_t sensorId, Sensors::Settings& prevSettings) {
this->queueRebuildingHaEntities[sensorId] = prevSettings; this->queueReconfigureSensors[sensorId] = prevSettings;
} }
protected: protected:
@@ -81,7 +81,7 @@ protected:
MqttWriter* writer = nullptr; MqttWriter* writer = nullptr;
UnitSystem currentUnitSystem = UnitSystem::METRIC; UnitSystem currentUnitSystem = UnitSystem::METRIC;
bool currentHomeAssistantDiscovery = false; bool currentHomeAssistantDiscovery = false;
std::unordered_map<uint8_t, Sensors::Settings> queueRebuildingHaEntities; std::unordered_map<uint8_t, Sensors::Settings> queueReconfigureSensors;
unsigned short readyForSendTime = 30000; unsigned short readyForSendTime = 30000;
unsigned long lastReconnectTime = 0; unsigned long lastReconnectTime = 0;
unsigned long connectedTime = 0; unsigned long connectedTime = 0;
@@ -276,8 +276,8 @@ protected:
this->publishNonStaticHaEntities(); this->publishNonStaticHaEntities();
} }
// rebuilding ha configs
for (auto& [sensorId, prevSettings] : this->queueRebuildingHaEntities) { for (auto& [sensorId, prevSettings] : this->queueReconfigureSensors) {
Log.sinfoln(FPSTR(L_MQTT_HA), F("Rebuilding config for sensor #%hhu '%s'"), sensorId, prevSettings.name); Log.sinfoln(FPSTR(L_MQTT_HA), F("Rebuilding config for sensor #%hhu '%s'"), sensorId, prevSettings.name);
// delete old config // delete old config
@@ -297,15 +297,6 @@ protected:
this->haHelper->deleteSignalQualityDynamicSensor(prevSettings); this->haHelper->deleteSignalQualityDynamicSensor(prevSettings);
this->haHelper->deleteDynamicSensor(prevSettings, Sensors::ValueType::TEMPERATURE); this->haHelper->deleteDynamicSensor(prevSettings, Sensors::ValueType::TEMPERATURE);
break; break;
case Sensors::Type::MANUAL:
this->client->unsubscribe(
this->haHelper->getDeviceTopic(
F("sensors"),
Sensors::makeObjectId(prevSettings.name).c_str(),
F("set")
).c_str()
);
default: default:
this->haHelper->deleteDynamicSensor(prevSettings, Sensors::ValueType::PRIMARY); this->haHelper->deleteDynamicSensor(prevSettings, Sensors::ValueType::PRIMARY);
@@ -333,26 +324,51 @@ protected:
this->haHelper->publishSignalQualityDynamicSensor(sSettings, false); this->haHelper->publishSignalQualityDynamicSensor(sSettings, false);
this->haHelper->publishDynamicSensor(sSettings, Sensors::ValueType::TEMPERATURE, settings.system.unitSystem); this->haHelper->publishDynamicSensor(sSettings, Sensors::ValueType::TEMPERATURE, settings.system.unitSystem);
break; break;
case Sensors::Type::MANUAL:
this->client->subscribe(
this->haHelper->getDeviceTopic(
F("sensors"),
Sensors::makeObjectId(prevSettings.name).c_str(),
F("set")
).c_str()
);
default: default:
this->haHelper->publishDynamicSensor(sSettings, Sensors::ValueType::PRIMARY, settings.system.unitSystem); this->haHelper->publishDynamicSensor(sSettings, Sensors::ValueType::PRIMARY, settings.system.unitSystem);
} }
} }
this->queueRebuildingHaEntities.clear();
} else if (this->currentHomeAssistantDiscovery) { } else if (this->currentHomeAssistantDiscovery) {
this->currentHomeAssistantDiscovery = false; this->currentHomeAssistantDiscovery = false;
} }
// reconfigure manual sensors
for (auto& [sensorId, prevSettings] : this->queueReconfigureSensors) {
// unsubscribe from old topic
if (strlen(prevSettings.name) && prevSettings.enabled) {
if (prevSettings.type == Sensors::Type::MANUAL) {
this->client->unsubscribe(
this->haHelper->getDeviceTopic(
F("sensors"),
Sensors::makeObjectId(prevSettings.name).c_str(),
F("set")
).c_str()
);
}
}
if (!Sensors::hasEnabledAndValid(sensorId)) {
continue;
}
// subscribe to new topic
auto& sSettings = Sensors::settings[sensorId];
if (sSettings.type == Sensors::Type::MANUAL) {
this->client->subscribe(
this->haHelper->getDeviceTopic(
F("sensors"),
Sensors::makeObjectId(sSettings.name).c_str(),
F("set")
).c_str()
);
}
}
// clear queue
this->queueReconfigureSensors.clear();
if (this->newConnection) { if (this->newConnection) {
this->newConnection = false; this->newConnection = false;
} }
@@ -366,6 +382,26 @@ protected:
this->client->subscribe(this->haHelper->getDeviceTopic(F("settings/set")).c_str()); this->client->subscribe(this->haHelper->getDeviceTopic(F("settings/set")).c_str());
this->client->subscribe(this->haHelper->getDeviceTopic(F("state/set")).c_str()); this->client->subscribe(this->haHelper->getDeviceTopic(F("state/set")).c_str());
// subscribe to manual sensors
for (uint8_t sensorId = 0; sensorId <= Sensors::getMaxSensorId(); sensorId++) {
if (!Sensors::hasEnabledAndValid(sensorId)) {
continue;
}
auto& sSettings = Sensors::settings[sensorId];
if (sSettings.type != Sensors::Type::MANUAL) {
continue;
}
this->client->subscribe(
this->haHelper->getDeviceTopic(
F("sensors"),
Sensors::makeObjectId(sSettings.name).c_str(),
F("set")
).c_str()
);
}
} }
void onDisconnect() { void onDisconnect() {
@@ -513,15 +549,6 @@ protected:
this->haHelper->publishSignalQualityDynamicSensor(sSettings, false); this->haHelper->publishSignalQualityDynamicSensor(sSettings, false);
this->haHelper->publishDynamicSensor(sSettings, Sensors::ValueType::TEMPERATURE, settings.system.unitSystem); this->haHelper->publishDynamicSensor(sSettings, Sensors::ValueType::TEMPERATURE, settings.system.unitSystem);
break; break;
case Sensors::Type::MANUAL:
this->client->subscribe(
this->haHelper->getDeviceTopic(
F("sensors"),
Sensors::makeObjectId(sSettings.name).c_str(),
F("set")
).c_str()
);
default: default:
this->haHelper->publishDynamicSensor(sSettings, Sensors::ValueType::PRIMARY, settings.system.unitSystem); this->haHelper->publishDynamicSensor(sSettings, Sensors::ValueType::PRIMARY, settings.system.unitSystem);

View File

@@ -214,7 +214,12 @@ protected:
); );
} }
if (!vars.slave.connected && millis() - this->lastSuccessResponse < 1325) { // 5 request retries
// 1000ms maximum response waiting time
// 100ms delay between requests
// +15%
// 5 * (1000 + 100) * 1.15 = 6325 ms
if (!vars.slave.connected && millis() - this->lastSuccessResponse < 6325) {
Log.sinfoln( Log.sinfoln(
FPSTR(L_OT), FPSTR(L_OT),
F("Connected, downtime: %lu s."), F("Connected, downtime: %lu s."),
@@ -224,7 +229,7 @@ protected:
this->connectedTime = millis(); this->connectedTime = millis();
vars.slave.connected = true; vars.slave.connected = true;
} else if (vars.slave.connected && millis() - this->lastSuccessResponse > 1325) { } else if (vars.slave.connected && millis() - this->lastSuccessResponse > 6325) {
Log.swarningln( Log.swarningln(
FPSTR(L_OT), FPSTR(L_OT),
F("Disconnected, uptime: %lu s."), F("Disconnected, uptime: %lu s."),

View File

@@ -618,7 +618,7 @@ protected:
} }
if (changed) { if (changed) {
tMqtt->rebuildHaEntity(sensorId, prevSettings); tMqtt->reconfigureSensor(sensorId, prevSettings);
fsSensorsSettings.update(); fsSensorsSettings.update();
} }
}); });

3
src/idf_component.yml Normal file
View File

@@ -0,0 +1,3 @@
dependencies:
idf: ">=5.3.2"
h2zero/esp-nimble-cpp: ">=2.2.1"

View File

@@ -132,10 +132,14 @@ const setupNetworkScanForm = (formSelector, tableSelector) => {
for (let i = 0; i < result.length; i++) { for (let i = 0; i < result.length; i++) {
let row = tbody.insertRow(-1); let row = tbody.insertRow(-1);
row.classList.add("network"); row.classList.add("network");
row.setAttribute('data-ssid', result[i].hidden ? '' : result[i].ssid); row.dataset.ssid = result[i].hidden ? '' : result[i].ssid;
row.onclick = () => { row.insertCell().textContent = `#${i + 1}`;
const input = document.querySelector('input#sta-ssid');
const ssid = this.getAttribute('data-ssid'); const nameCell = row.insertCell();
nameCell.innerHTML = result[i].hidden ? `<i>${result[i].bssid}</i>` : result[i].ssid;
nameCell.onclick = (event) => {
const input = document.querySelector("[name='sta[ssid]']");
const ssid = event.target.parentNode.dataset.ssid;
if (!input || !ssid) { if (!input || !ssid) {
return; return;
} }
@@ -144,9 +148,6 @@ const setupNetworkScanForm = (formSelector, tableSelector) => {
input.focus(); input.focus();
}; };
row.insertCell().textContent = `#${i + 1}`;
row.insertCell().innerHTML = result[i].hidden ? `<i>${result[i].bssid}</i>` : result[i].ssid;
// info cell // info cell
let infoCell = row.insertCell(); let infoCell = row.insertCell();
@@ -165,7 +166,7 @@ const setupNetworkScanForm = (formSelector, tableSelector) => {
} }
let signalQualityContainer = document.createElement("span"); let signalQualityContainer = document.createElement("span");
signalQualityContainer.setAttribute('data-tooltip', `${result[i].signalQuality}%`); signalQualityContainer.dataset.tooltip = `${result[i].signalQuality}%`;
signalQualityContainer.appendChild(signalQualityIcon); signalQualityContainer.appendChild(signalQualityIcon);
infoCell.appendChild(signalQualityContainer); infoCell.appendChild(signalQualityContainer);
@@ -192,7 +193,7 @@ const setupNetworkScanForm = (formSelector, tableSelector) => {
} }
let authContainer = document.createElement("span"); let authContainer = document.createElement("span");
authContainer.setAttribute('data-tooltip', (result[i].auth in authList) ? authList[result[i].auth] : "unknown"); authContainer.dataset.tooltip = (result[i].auth in authList) ? authList[result[i].auth] : "unknown";
authContainer.appendChild(authIcon); authContainer.appendChild(authIcon);
infoCell.appendChild(authContainer); infoCell.appendChild(authContainer);
} }