mirror of
https://github.com/esphome/esphome.git
synced 2025-03-15 15:18:16 +00:00
Merge branch 'dev' into feature_dallas_pio
This commit is contained in:
commit
d1a2850aa7
4
.github/actions/build-image/action.yaml
vendored
4
.github/actions/build-image/action.yaml
vendored
@ -46,7 +46,7 @@ runs:
|
|||||||
|
|
||||||
- name: Build and push to ghcr by digest
|
- name: Build and push to ghcr by digest
|
||||||
id: build-ghcr
|
id: build-ghcr
|
||||||
uses: docker/build-push-action@v6.11.0
|
uses: docker/build-push-action@v6.12.0
|
||||||
env:
|
env:
|
||||||
DOCKER_BUILD_SUMMARY: false
|
DOCKER_BUILD_SUMMARY: false
|
||||||
DOCKER_BUILD_RECORD_UPLOAD: false
|
DOCKER_BUILD_RECORD_UPLOAD: false
|
||||||
@ -72,7 +72,7 @@ runs:
|
|||||||
|
|
||||||
- name: Build and push to dockerhub by digest
|
- name: Build and push to dockerhub by digest
|
||||||
id: build-dockerhub
|
id: build-dockerhub
|
||||||
uses: docker/build-push-action@v6.11.0
|
uses: docker/build-push-action@v6.12.0
|
||||||
env:
|
env:
|
||||||
DOCKER_BUILD_SUMMARY: false
|
DOCKER_BUILD_SUMMARY: false
|
||||||
DOCKER_BUILD_RECORD_UPLOAD: false
|
DOCKER_BUILD_RECORD_UPLOAD: false
|
||||||
|
@ -11,14 +11,6 @@ repos:
|
|||||||
args: [--fix]
|
args: [--fix]
|
||||||
# Run the formatter.
|
# Run the formatter.
|
||||||
- id: ruff-format
|
- id: ruff-format
|
||||||
- repo: https://github.com/psf/black-pre-commit-mirror
|
|
||||||
rev: 24.4.2
|
|
||||||
hooks:
|
|
||||||
- id: black
|
|
||||||
args:
|
|
||||||
- --safe
|
|
||||||
- --quiet
|
|
||||||
files: ^((esphome|script|tests)/.+)?[^/]+\.py$
|
|
||||||
- repo: https://github.com/PyCQA/flake8
|
- repo: https://github.com/PyCQA/flake8
|
||||||
rev: 6.1.0
|
rev: 6.1.0
|
||||||
hooks:
|
hooks:
|
||||||
@ -53,6 +45,6 @@ repos:
|
|||||||
hooks:
|
hooks:
|
||||||
- id: pylint
|
- id: pylint
|
||||||
name: pylint
|
name: pylint
|
||||||
entry: script/run-in-env.sh pylint
|
entry: python script/run-in-env pylint
|
||||||
language: script
|
language: system
|
||||||
types: [python]
|
types: [python]
|
||||||
|
@ -340,7 +340,6 @@ esphome/components/radon_eye_rd200/* @jeffeb3
|
|||||||
esphome/components/rc522/* @glmnet
|
esphome/components/rc522/* @glmnet
|
||||||
esphome/components/rc522_i2c/* @glmnet
|
esphome/components/rc522_i2c/* @glmnet
|
||||||
esphome/components/rc522_spi/* @glmnet
|
esphome/components/rc522_spi/* @glmnet
|
||||||
esphome/components/resistance_sampler/* @jesserockz
|
|
||||||
esphome/components/restart/* @esphome/core
|
esphome/components/restart/* @esphome/core
|
||||||
esphome/components/rf_bridge/* @jesserockz
|
esphome/components/rf_bridge/* @jesserockz
|
||||||
esphome/components/rgbct/* @jesserockz
|
esphome/components/rgbct/* @jesserockz
|
||||||
|
@ -298,6 +298,12 @@ void DalyBmsComponent::decode_data_(std::vector<uint8_t> data) {
|
|||||||
if (this->cell_16_voltage_sensor_) {
|
if (this->cell_16_voltage_sensor_) {
|
||||||
this->cell_16_voltage_sensor_->publish_state((float) encode_uint16(it[5], it[6]) / 1000);
|
this->cell_16_voltage_sensor_->publish_state((float) encode_uint16(it[5], it[6]) / 1000);
|
||||||
}
|
}
|
||||||
|
if (this->cell_17_voltage_sensor_) {
|
||||||
|
this->cell_17_voltage_sensor_->publish_state((float) encode_uint16(it[7], it[8]) / 1000);
|
||||||
|
}
|
||||||
|
if (this->cell_18_voltage_sensor_) {
|
||||||
|
this->cell_18_voltage_sensor_->publish_state((float) encode_uint16(it[9], it[10]) / 1000);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -54,6 +54,8 @@ class DalyBmsComponent : public PollingComponent, public uart::UARTDevice {
|
|||||||
SUB_SENSOR(cell_14_voltage)
|
SUB_SENSOR(cell_14_voltage)
|
||||||
SUB_SENSOR(cell_15_voltage)
|
SUB_SENSOR(cell_15_voltage)
|
||||||
SUB_SENSOR(cell_16_voltage)
|
SUB_SENSOR(cell_16_voltage)
|
||||||
|
SUB_SENSOR(cell_17_voltage)
|
||||||
|
SUB_SENSOR(cell_18_voltage)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_TEXT_SENSOR
|
#ifdef USE_TEXT_SENSOR
|
||||||
|
@ -52,6 +52,8 @@ CONF_CELL_13_VOLTAGE = "cell_13_voltage"
|
|||||||
CONF_CELL_14_VOLTAGE = "cell_14_voltage"
|
CONF_CELL_14_VOLTAGE = "cell_14_voltage"
|
||||||
CONF_CELL_15_VOLTAGE = "cell_15_voltage"
|
CONF_CELL_15_VOLTAGE = "cell_15_voltage"
|
||||||
CONF_CELL_16_VOLTAGE = "cell_16_voltage"
|
CONF_CELL_16_VOLTAGE = "cell_16_voltage"
|
||||||
|
CONF_CELL_17_VOLTAGE = "cell_17_voltage"
|
||||||
|
CONF_CELL_18_VOLTAGE = "cell_18_voltage"
|
||||||
ICON_CURRENT_DC = "mdi:current-dc"
|
ICON_CURRENT_DC = "mdi:current-dc"
|
||||||
ICON_BATTERY_OUTLINE = "mdi:battery-outline"
|
ICON_BATTERY_OUTLINE = "mdi:battery-outline"
|
||||||
ICON_THERMOMETER_CHEVRON_UP = "mdi:thermometer-chevron-up"
|
ICON_THERMOMETER_CHEVRON_UP = "mdi:thermometer-chevron-up"
|
||||||
@ -92,6 +94,8 @@ TYPES = [
|
|||||||
CONF_CELL_14_VOLTAGE,
|
CONF_CELL_14_VOLTAGE,
|
||||||
CONF_CELL_15_VOLTAGE,
|
CONF_CELL_15_VOLTAGE,
|
||||||
CONF_CELL_16_VOLTAGE,
|
CONF_CELL_16_VOLTAGE,
|
||||||
|
CONF_CELL_17_VOLTAGE,
|
||||||
|
CONF_CELL_18_VOLTAGE,
|
||||||
]
|
]
|
||||||
|
|
||||||
CELL_VOLTAGE_SCHEMA = sensor.sensor_schema(
|
CELL_VOLTAGE_SCHEMA = sensor.sensor_schema(
|
||||||
@ -212,6 +216,8 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
cv.Optional(CONF_CELL_14_VOLTAGE): CELL_VOLTAGE_SCHEMA,
|
cv.Optional(CONF_CELL_14_VOLTAGE): CELL_VOLTAGE_SCHEMA,
|
||||||
cv.Optional(CONF_CELL_15_VOLTAGE): CELL_VOLTAGE_SCHEMA,
|
cv.Optional(CONF_CELL_15_VOLTAGE): CELL_VOLTAGE_SCHEMA,
|
||||||
cv.Optional(CONF_CELL_16_VOLTAGE): CELL_VOLTAGE_SCHEMA,
|
cv.Optional(CONF_CELL_16_VOLTAGE): CELL_VOLTAGE_SCHEMA,
|
||||||
|
cv.Optional(CONF_CELL_17_VOLTAGE): CELL_VOLTAGE_SCHEMA,
|
||||||
|
cv.Optional(CONF_CELL_18_VOLTAGE): CELL_VOLTAGE_SCHEMA,
|
||||||
}
|
}
|
||||||
).extend(cv.COMPONENT_SCHEMA)
|
).extend(cv.COMPONENT_SCHEMA)
|
||||||
)
|
)
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
#include "esp_crt_bundle.h"
|
#include "esp_crt_bundle.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "esp_task_wdt.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace http_request {
|
namespace http_request {
|
||||||
|
|
||||||
@ -117,11 +119,11 @@ std::shared_ptr<HttpContainer> HttpRequestIDF::start(std::string url, std::strin
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
App.feed_wdt();
|
container->feed_wdt();
|
||||||
container->content_length = esp_http_client_fetch_headers(client);
|
container->content_length = esp_http_client_fetch_headers(client);
|
||||||
App.feed_wdt();
|
container->feed_wdt();
|
||||||
container->status_code = esp_http_client_get_status_code(client);
|
container->status_code = esp_http_client_get_status_code(client);
|
||||||
App.feed_wdt();
|
container->feed_wdt();
|
||||||
if (is_success(container->status_code)) {
|
if (is_success(container->status_code)) {
|
||||||
container->duration_ms = millis() - start;
|
container->duration_ms = millis() - start;
|
||||||
return container;
|
return container;
|
||||||
@ -151,11 +153,11 @@ std::shared_ptr<HttpContainer> HttpRequestIDF::start(std::string url, std::strin
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
App.feed_wdt();
|
container->feed_wdt();
|
||||||
container->content_length = esp_http_client_fetch_headers(client);
|
container->content_length = esp_http_client_fetch_headers(client);
|
||||||
App.feed_wdt();
|
container->feed_wdt();
|
||||||
container->status_code = esp_http_client_get_status_code(client);
|
container->status_code = esp_http_client_get_status_code(client);
|
||||||
App.feed_wdt();
|
container->feed_wdt();
|
||||||
if (is_success(container->status_code)) {
|
if (is_success(container->status_code)) {
|
||||||
container->duration_ms = millis() - start;
|
container->duration_ms = millis() - start;
|
||||||
return container;
|
return container;
|
||||||
@ -185,8 +187,9 @@ int HttpContainerIDF::read(uint8_t *buf, size_t max_len) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
App.feed_wdt();
|
this->feed_wdt();
|
||||||
int read_len = esp_http_client_read(this->client_, (char *) buf, bufsize);
|
int read_len = esp_http_client_read(this->client_, (char *) buf, bufsize);
|
||||||
|
this->feed_wdt();
|
||||||
this->bytes_read_ += read_len;
|
this->bytes_read_ += read_len;
|
||||||
|
|
||||||
this->duration_ms += (millis() - start);
|
this->duration_ms += (millis() - start);
|
||||||
@ -201,6 +204,13 @@ void HttpContainerIDF::end() {
|
|||||||
esp_http_client_cleanup(this->client_);
|
esp_http_client_cleanup(this->client_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HttpContainerIDF::feed_wdt() {
|
||||||
|
// Tests to see if the executing task has a watchdog timer attached
|
||||||
|
if (esp_task_wdt_status(nullptr) == ESP_OK) {
|
||||||
|
App.feed_wdt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace http_request
|
} // namespace http_request
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
||||||
|
@ -18,6 +18,9 @@ class HttpContainerIDF : public HttpContainer {
|
|||||||
int read(uint8_t *buf, size_t max_len) override;
|
int read(uint8_t *buf, size_t max_len) override;
|
||||||
void end() override;
|
void end() override;
|
||||||
|
|
||||||
|
/// @brief Feeds the watchdog timer if the executing task has one attached
|
||||||
|
void feed_wdt();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
esp_http_client_handle_t client_;
|
esp_http_client_handle_t client_;
|
||||||
};
|
};
|
||||||
|
@ -9,6 +9,13 @@
|
|||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace http_request {
|
namespace http_request {
|
||||||
|
|
||||||
|
// The update function runs in a task only on ESP32s.
|
||||||
|
#ifdef USE_ESP32
|
||||||
|
#define UPDATE_RETURN vTaskDelete(nullptr) // Delete the current update task
|
||||||
|
#else
|
||||||
|
#define UPDATE_RETURN return
|
||||||
|
#endif
|
||||||
|
|
||||||
static const char *const TAG = "http_request.update";
|
static const char *const TAG = "http_request.update";
|
||||||
|
|
||||||
static const size_t MAX_READ_SIZE = 256;
|
static const size_t MAX_READ_SIZE = 256;
|
||||||
@ -29,45 +36,57 @@ void HttpRequestUpdate::setup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HttpRequestUpdate::update() {
|
void HttpRequestUpdate::update() {
|
||||||
auto container = this->request_parent_->get(this->source_url_);
|
#ifdef USE_ESP32
|
||||||
|
xTaskCreate(HttpRequestUpdate::update_task, "update_task", 8192, (void *) this, 1, &this->update_task_handle_);
|
||||||
|
#else
|
||||||
|
this->update_task(this);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpRequestUpdate::update_task(void *params) {
|
||||||
|
HttpRequestUpdate *this_update = (HttpRequestUpdate *) params;
|
||||||
|
|
||||||
|
auto container = this_update->request_parent_->get(this_update->source_url_);
|
||||||
|
|
||||||
if (container == nullptr || container->status_code != HTTP_STATUS_OK) {
|
if (container == nullptr || container->status_code != HTTP_STATUS_OK) {
|
||||||
std::string msg = str_sprintf("Failed to fetch manifest from %s", this->source_url_.c_str());
|
std::string msg = str_sprintf("Failed to fetch manifest from %s", this_update->source_url_.c_str());
|
||||||
this->status_set_error(msg.c_str());
|
this_update->status_set_error(msg.c_str());
|
||||||
return;
|
UPDATE_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||||
uint8_t *data = allocator.allocate(container->content_length);
|
uint8_t *data = allocator.allocate(container->content_length);
|
||||||
if (data == nullptr) {
|
if (data == nullptr) {
|
||||||
std::string msg = str_sprintf("Failed to allocate %d bytes for manifest", container->content_length);
|
std::string msg = str_sprintf("Failed to allocate %d bytes for manifest", container->content_length);
|
||||||
this->status_set_error(msg.c_str());
|
this_update->status_set_error(msg.c_str());
|
||||||
container->end();
|
container->end();
|
||||||
return;
|
UPDATE_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t read_index = 0;
|
size_t read_index = 0;
|
||||||
while (container->get_bytes_read() < container->content_length) {
|
while (container->get_bytes_read() < container->content_length) {
|
||||||
int read_bytes = container->read(data + read_index, MAX_READ_SIZE);
|
int read_bytes = container->read(data + read_index, MAX_READ_SIZE);
|
||||||
|
|
||||||
App.feed_wdt();
|
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
read_index += read_bytes;
|
read_index += read_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool valid = false;
|
||||||
|
{ // Ensures the response string falls out of scope and deallocates before the task ends
|
||||||
std::string response((char *) data, read_index);
|
std::string response((char *) data, read_index);
|
||||||
allocator.deallocate(data, container->content_length);
|
allocator.deallocate(data, container->content_length);
|
||||||
|
|
||||||
container->end();
|
container->end();
|
||||||
|
container.reset(); // Release ownership of the container's shared_ptr
|
||||||
|
|
||||||
bool valid = json::parse_json(response, [this](JsonObject root) -> bool {
|
valid = json::parse_json(response, [this_update](JsonObject root) -> bool {
|
||||||
if (!root.containsKey("name") || !root.containsKey("version") || !root.containsKey("builds")) {
|
if (!root.containsKey("name") || !root.containsKey("version") || !root.containsKey("builds")) {
|
||||||
ESP_LOGE(TAG, "Manifest does not contain required fields");
|
ESP_LOGE(TAG, "Manifest does not contain required fields");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this->update_info_.title = root["name"].as<std::string>();
|
this_update->update_info_.title = root["name"].as<std::string>();
|
||||||
this->update_info_.latest_version = root["version"].as<std::string>();
|
this_update->update_info_.latest_version = root["version"].as<std::string>();
|
||||||
|
|
||||||
for (auto build : root["builds"].as<JsonArray>()) {
|
for (auto build : root["builds"].as<JsonArray>()) {
|
||||||
if (!build.containsKey("chipFamily")) {
|
if (!build.containsKey("chipFamily")) {
|
||||||
@ -84,38 +103,40 @@ void HttpRequestUpdate::update() {
|
|||||||
ESP_LOGE(TAG, "Manifest does not contain required fields");
|
ESP_LOGE(TAG, "Manifest does not contain required fields");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this->update_info_.firmware_url = ota["path"].as<std::string>();
|
this_update->update_info_.firmware_url = ota["path"].as<std::string>();
|
||||||
this->update_info_.md5 = ota["md5"].as<std::string>();
|
this_update->update_info_.md5 = ota["md5"].as<std::string>();
|
||||||
|
|
||||||
if (ota.containsKey("summary"))
|
if (ota.containsKey("summary"))
|
||||||
this->update_info_.summary = ota["summary"].as<std::string>();
|
this_update->update_info_.summary = ota["summary"].as<std::string>();
|
||||||
if (ota.containsKey("release_url"))
|
if (ota.containsKey("release_url"))
|
||||||
this->update_info_.release_url = ota["release_url"].as<std::string>();
|
this_update->update_info_.release_url = ota["release_url"].as<std::string>();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
std::string msg = str_sprintf("Failed to parse JSON from %s", this->source_url_.c_str());
|
std::string msg = str_sprintf("Failed to parse JSON from %s", this_update->source_url_.c_str());
|
||||||
this->status_set_error(msg.c_str());
|
this_update->status_set_error(msg.c_str());
|
||||||
return;
|
UPDATE_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge source_url_ and this->update_info_.firmware_url
|
// Merge source_url_ and this_update->update_info_.firmware_url
|
||||||
if (this->update_info_.firmware_url.find("http") == std::string::npos) {
|
if (this_update->update_info_.firmware_url.find("http") == std::string::npos) {
|
||||||
std::string path = this->update_info_.firmware_url;
|
std::string path = this_update->update_info_.firmware_url;
|
||||||
if (path[0] == '/') {
|
if (path[0] == '/') {
|
||||||
std::string domain = this->source_url_.substr(0, this->source_url_.find('/', 8));
|
std::string domain = this_update->source_url_.substr(0, this_update->source_url_.find('/', 8));
|
||||||
this->update_info_.firmware_url = domain + path;
|
this_update->update_info_.firmware_url = domain + path;
|
||||||
} else {
|
} else {
|
||||||
std::string domain = this->source_url_.substr(0, this->source_url_.rfind('/') + 1);
|
std::string domain = this_update->source_url_.substr(0, this_update->source_url_.rfind('/') + 1);
|
||||||
this->update_info_.firmware_url = domain + path;
|
this_update->update_info_.firmware_url = domain + path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{ // Ensures the current version string falls out of scope and deallocates before the task ends
|
||||||
std::string current_version;
|
std::string current_version;
|
||||||
#ifdef ESPHOME_PROJECT_VERSION
|
#ifdef ESPHOME_PROJECT_VERSION
|
||||||
current_version = ESPHOME_PROJECT_VERSION;
|
current_version = ESPHOME_PROJECT_VERSION;
|
||||||
@ -123,19 +144,23 @@ void HttpRequestUpdate::update() {
|
|||||||
current_version = ESPHOME_VERSION;
|
current_version = ESPHOME_VERSION;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
this->update_info_.current_version = current_version;
|
this_update->update_info_.current_version = current_version;
|
||||||
|
|
||||||
if (this->update_info_.latest_version.empty() || this->update_info_.latest_version == update_info_.current_version) {
|
|
||||||
this->state_ = update::UPDATE_STATE_NO_UPDATE;
|
|
||||||
} else {
|
|
||||||
this->state_ = update::UPDATE_STATE_AVAILABLE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this->update_info_.has_progress = false;
|
if (this_update->update_info_.latest_version.empty() ||
|
||||||
this->update_info_.progress = 0.0f;
|
this_update->update_info_.latest_version == this_update->update_info_.current_version) {
|
||||||
|
this_update->state_ = update::UPDATE_STATE_NO_UPDATE;
|
||||||
|
} else {
|
||||||
|
this_update->state_ = update::UPDATE_STATE_AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
this->status_clear_error();
|
this_update->update_info_.has_progress = false;
|
||||||
this->publish_state();
|
this_update->update_info_.progress = 0.0f;
|
||||||
|
|
||||||
|
this_update->status_clear_error();
|
||||||
|
this_update->publish_state();
|
||||||
|
|
||||||
|
UPDATE_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpRequestUpdate::perform(bool force) {
|
void HttpRequestUpdate::perform(bool force) {
|
||||||
|
@ -7,6 +7,10 @@
|
|||||||
#include "esphome/components/http_request/ota/ota_http_request.h"
|
#include "esphome/components/http_request/ota/ota_http_request.h"
|
||||||
#include "esphome/components/update/update_entity.h"
|
#include "esphome/components/update/update_entity.h"
|
||||||
|
|
||||||
|
#ifdef USE_ESP32
|
||||||
|
#include <freertos/FreeRTOS.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace http_request {
|
namespace http_request {
|
||||||
|
|
||||||
@ -29,6 +33,11 @@ class HttpRequestUpdate : public update::UpdateEntity, public PollingComponent {
|
|||||||
HttpRequestComponent *request_parent_;
|
HttpRequestComponent *request_parent_;
|
||||||
OtaHttpRequestComponent *ota_parent_;
|
OtaHttpRequestComponent *ota_parent_;
|
||||||
std::string source_url_;
|
std::string source_url_;
|
||||||
|
|
||||||
|
static void update_task(void *params);
|
||||||
|
#ifdef USE_ESP32
|
||||||
|
TaskHandle_t update_task_handle_{nullptr};
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace http_request
|
} // namespace http_request
|
||||||
|
@ -2,7 +2,7 @@ from math import log
|
|||||||
|
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
from esphome.components import sensor, resistance_sampler
|
from esphome.components import sensor
|
||||||
from esphome.const import (
|
from esphome.const import (
|
||||||
CONF_CALIBRATION,
|
CONF_CALIBRATION,
|
||||||
CONF_REFERENCE_RESISTANCE,
|
CONF_REFERENCE_RESISTANCE,
|
||||||
@ -15,8 +15,6 @@ from esphome.const import (
|
|||||||
UNIT_CELSIUS,
|
UNIT_CELSIUS,
|
||||||
)
|
)
|
||||||
|
|
||||||
AUTO_LOAD = ["resistance_sampler"]
|
|
||||||
|
|
||||||
ntc_ns = cg.esphome_ns.namespace("ntc")
|
ntc_ns = cg.esphome_ns.namespace("ntc")
|
||||||
NTC = ntc_ns.class_("NTC", cg.Component, sensor.Sensor)
|
NTC = ntc_ns.class_("NTC", cg.Component, sensor.Sensor)
|
||||||
|
|
||||||
@ -126,7 +124,7 @@ CONFIG_SCHEMA = (
|
|||||||
)
|
)
|
||||||
.extend(
|
.extend(
|
||||||
{
|
{
|
||||||
cv.Required(CONF_SENSOR): cv.use_id(resistance_sampler.ResistanceSampler),
|
cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor),
|
||||||
cv.Required(CONF_CALIBRATION): process_calibration,
|
cv.Required(CONF_CALIBRATION): process_calibration,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "esphome/components/resistance_sampler/resistance_sampler.h"
|
|
||||||
#include "esphome/components/sensor/sensor.h"
|
|
||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace resistance {
|
namespace resistance {
|
||||||
@ -12,7 +11,7 @@ enum ResistanceConfiguration {
|
|||||||
DOWNSTREAM,
|
DOWNSTREAM,
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResistanceSensor : public Component, public sensor::Sensor, resistance_sampler::ResistanceSampler {
|
class ResistanceSensor : public Component, public sensor::Sensor {
|
||||||
public:
|
public:
|
||||||
void set_sensor(Sensor *sensor) { sensor_ = sensor; }
|
void set_sensor(Sensor *sensor) { sensor_ = sensor; }
|
||||||
void set_configuration(ResistanceConfiguration configuration) { configuration_ = configuration; }
|
void set_configuration(ResistanceConfiguration configuration) { configuration_ = configuration; }
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.components import sensor, resistance_sampler
|
from esphome.components import sensor
|
||||||
from esphome.const import (
|
from esphome.const import (
|
||||||
CONF_REFERENCE_VOLTAGE,
|
CONF_REFERENCE_VOLTAGE,
|
||||||
CONF_SENSOR,
|
CONF_SENSOR,
|
||||||
@ -9,15 +9,8 @@ from esphome.const import (
|
|||||||
ICON_FLASH,
|
ICON_FLASH,
|
||||||
)
|
)
|
||||||
|
|
||||||
AUTO_LOAD = ["resistance_sampler"]
|
|
||||||
|
|
||||||
resistance_ns = cg.esphome_ns.namespace("resistance")
|
resistance_ns = cg.esphome_ns.namespace("resistance")
|
||||||
ResistanceSensor = resistance_ns.class_(
|
ResistanceSensor = resistance_ns.class_("ResistanceSensor", cg.Component, sensor.Sensor)
|
||||||
"ResistanceSensor",
|
|
||||||
cg.Component,
|
|
||||||
sensor.Sensor,
|
|
||||||
resistance_sampler.ResistanceSampler,
|
|
||||||
)
|
|
||||||
|
|
||||||
CONF_CONFIGURATION = "configuration"
|
CONF_CONFIGURATION = "configuration"
|
||||||
CONF_RESISTOR = "resistor"
|
CONF_RESISTOR = "resistor"
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
import esphome.codegen as cg
|
|
||||||
|
|
||||||
resistance_sampler_ns = cg.esphome_ns.namespace("resistance_sampler")
|
|
||||||
ResistanceSampler = resistance_sampler_ns.class_("ResistanceSampler")
|
|
||||||
|
|
||||||
CODEOWNERS = ["@jesserockz"]
|
|
@ -1,10 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
namespace esphome {
|
|
||||||
namespace resistance_sampler {
|
|
||||||
|
|
||||||
/// Abstract interface to mark components that provide resistance values.
|
|
||||||
class ResistanceSampler {};
|
|
||||||
|
|
||||||
} // namespace resistance_sampler
|
|
||||||
} // namespace esphome
|
|
53
script/run-in-env
Normal file
53
script/run-in-env
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def find_and_activate_virtualenv():
|
||||||
|
try:
|
||||||
|
# Get the top-level directory of the git repository
|
||||||
|
my_path = subprocess.check_output(
|
||||||
|
["git", "rev-parse", "--show-toplevel"], text=True
|
||||||
|
).strip()
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
print(
|
||||||
|
"Error: Not a git repository or unable to determine the top-level directory.",
|
||||||
|
file=sys.stderr,
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Check for virtual environments
|
||||||
|
for venv in ["venv", ".venv", "."]:
|
||||||
|
activate_path = (
|
||||||
|
Path(my_path)
|
||||||
|
/ venv
|
||||||
|
/ ("Scripts" if os.name == "nt" else "bin")
|
||||||
|
/ "activate"
|
||||||
|
)
|
||||||
|
if activate_path.exists():
|
||||||
|
# Activate the virtual environment by updating PATH
|
||||||
|
env = os.environ.copy()
|
||||||
|
venv_bin_dir = activate_path.parent
|
||||||
|
env["PATH"] = f"{venv_bin_dir}{os.pathsep}{env['PATH']}"
|
||||||
|
env["VIRTUAL_ENV"] = str(venv_bin_dir.parent)
|
||||||
|
print(f"Activated virtual environment: {venv_bin_dir.parent}")
|
||||||
|
|
||||||
|
# Execute the remaining arguments in the new environment
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
subprocess.run(sys.argv[1:], env=env, check=False)
|
||||||
|
else:
|
||||||
|
print(
|
||||||
|
"No command provided to run in the virtual environment.",
|
||||||
|
file=sys.stderr,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
print("No virtual environment found.", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
find_and_activate_virtualenv()
|
@ -1,13 +0,0 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
my_path=$(git rev-parse --show-toplevel)
|
|
||||||
|
|
||||||
for venv in venv .venv .; do
|
|
||||||
if [ -f "${my_path}/${venv}/bin/activate" ]; then
|
|
||||||
. "${my_path}/${venv}/bin/activate"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
exec "$@"
|
|
Loading…
x
Reference in New Issue
Block a user