mirror of
https://github.com/esphome/esphome.git
synced 2025-01-05 18:57:43 +01:00
Merge branch 'dev' into optolink
This commit is contained in:
commit
99e01efdec
60
.github/workflows/sync-device-classes.yml
vendored
Normal file
60
.github/workflows/sync-device-classes.yml
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
---
|
||||
name: Synchronise Device Classes from Home Assistant
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '45 6 * * *'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
name: Sync Device Classes
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Checkout Home Assistant
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: home-assistant/core
|
||||
path: lib/home-assistant
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.11
|
||||
|
||||
- name: Install Home Assistant
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -e lib/home-assistant
|
||||
|
||||
- name: Sync
|
||||
run: |
|
||||
python ./script/sync-device_class.py
|
||||
|
||||
- name: Get PR template
|
||||
id: pr-template-body
|
||||
run: |
|
||||
body=$(cat .github/PULL_REQUEST_TEMPLATE.md)
|
||||
delimiter="$(openssl rand -hex 8)"
|
||||
echo "body<<$delimiter" >> $GITHUB_OUTPUT
|
||||
echo "$body" >> $GITHUB_OUTPUT
|
||||
echo "$delimiter" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Commit changes
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
with:
|
||||
commit-message: "Synchronise Device Classes from Home Assistant"
|
||||
committer: esphomebot <esphome@nabucasa.com>
|
||||
author: esphomebot <esphome@nabucasa.com>
|
||||
branch: sync/device-classes/
|
||||
branch-suffix: timestamp
|
||||
delete-branch: true
|
||||
title: "Synchronise Device Classes from Home Assistant"
|
||||
body: ${{ steps.pr-template-body.outputs.body }}
|
@ -53,6 +53,8 @@ service APIConnection {
|
||||
rpc bluetooth_gatt_write_descriptor(BluetoothGATTWriteDescriptorRequest) returns (void) {}
|
||||
rpc bluetooth_gatt_notify(BluetoothGATTNotifyRequest) returns (void) {}
|
||||
rpc subscribe_bluetooth_connections_free(SubscribeBluetoothConnectionsFreeRequest) returns (BluetoothConnectionsFreeResponse) {}
|
||||
rpc unsubscribe_bluetooth_le_advertisements(UnsubscribeBluetoothLEAdvertisementsRequest) returns (void) {}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1125,6 +1127,7 @@ message MediaPlayerCommandRequest {
|
||||
message SubscribeBluetoothLEAdvertisementsRequest {
|
||||
option (id) = 66;
|
||||
option (source) = SOURCE_CLIENT;
|
||||
option (ifdef) = "USE_BLUETOOTH_PROXY";
|
||||
}
|
||||
|
||||
message BluetoothServiceData {
|
||||
@ -1361,6 +1364,12 @@ message BluetoothDeviceUnpairingResponse {
|
||||
int32 error = 3;
|
||||
}
|
||||
|
||||
message UnsubscribeBluetoothLEAdvertisementsRequest {
|
||||
option (id) = 87;
|
||||
option (source) = SOURCE_CLIENT;
|
||||
option (ifdef) = "USE_BLUETOOTH_PROXY";
|
||||
}
|
||||
|
||||
message BluetoothDeviceClearCacheResponse {
|
||||
option (id) = 88;
|
||||
option (source) = SOURCE_SERVER;
|
||||
|
@ -97,6 +97,12 @@ class APIConnection : public APIServerConnection {
|
||||
this->send_homeassistant_service_response(call);
|
||||
}
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
void subscribe_bluetooth_le_advertisements(const SubscribeBluetoothLEAdvertisementsRequest &msg) override {
|
||||
this->bluetooth_le_advertisement_subscription_ = true;
|
||||
}
|
||||
void unsubscribe_bluetooth_le_advertisements(const UnsubscribeBluetoothLEAdvertisementsRequest &msg) override {
|
||||
this->bluetooth_le_advertisement_subscription_ = false;
|
||||
}
|
||||
bool send_bluetooth_le_advertisement(const BluetoothLEAdvertisementResponse &msg);
|
||||
|
||||
void bluetooth_device_request(const BluetoothDeviceRequest &msg) override;
|
||||
@ -150,9 +156,7 @@ class APIConnection : public APIServerConnection {
|
||||
return {};
|
||||
}
|
||||
void execute_service(const ExecuteServiceRequest &msg) override;
|
||||
void subscribe_bluetooth_le_advertisements(const SubscribeBluetoothLEAdvertisementsRequest &msg) override {
|
||||
this->bluetooth_le_advertisement_subscription_ = true;
|
||||
}
|
||||
|
||||
bool is_authenticated() override { return this->connection_state_ == ConnectionState::AUTHENTICATED; }
|
||||
bool is_connection_setup() override {
|
||||
return this->connection_state_ == ConnectionState ::CONNECTED || this->is_authenticated();
|
||||
@ -197,7 +201,9 @@ class APIConnection : public APIServerConnection {
|
||||
uint32_t last_traffic_;
|
||||
bool sent_ping_{false};
|
||||
bool service_call_subscription_{false};
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool bluetooth_le_advertisement_subscription_{false};
|
||||
#endif
|
||||
bool next_close_ = false;
|
||||
APIServer *parent_;
|
||||
InitialStateIterator initial_state_iterator_;
|
||||
|
@ -6062,6 +6062,12 @@ void BluetoothDeviceUnpairingResponse::dump_to(std::string &out) const {
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
void UnsubscribeBluetoothLEAdvertisementsRequest::encode(ProtoWriteBuffer buffer) const {}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void UnsubscribeBluetoothLEAdvertisementsRequest::dump_to(std::string &out) const {
|
||||
out.append("UnsubscribeBluetoothLEAdvertisementsRequest {}");
|
||||
}
|
||||
#endif
|
||||
bool BluetoothDeviceClearCacheResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
case 1: {
|
||||
|
@ -1555,6 +1555,15 @@ class BluetoothDeviceUnpairingResponse : public ProtoMessage {
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
};
|
||||
class UnsubscribeBluetoothLEAdvertisementsRequest : public ProtoMessage {
|
||||
public:
|
||||
void encode(ProtoWriteBuffer buffer) const override;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void dump_to(std::string &out) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
};
|
||||
class BluetoothDeviceClearCacheResponse : public ProtoMessage {
|
||||
public:
|
||||
uint64_t address{0};
|
||||
|
@ -329,6 +329,8 @@ bool APIServerConnectionBase::send_media_player_state_response(const MediaPlayer
|
||||
#ifdef USE_MEDIA_PLAYER
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool APIServerConnectionBase::send_bluetooth_le_advertisement_response(const BluetoothLEAdvertisementResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_bluetooth_le_advertisement_response: %s", msg.dump().c_str());
|
||||
@ -442,6 +444,8 @@ bool APIServerConnectionBase::send_bluetooth_device_unpairing_response(const Blu
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool APIServerConnectionBase::send_bluetooth_device_clear_cache_response(const BluetoothDeviceClearCacheResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_bluetooth_device_clear_cache_response: %s", msg.dump().c_str());
|
||||
@ -717,12 +721,14 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
|
||||
break;
|
||||
}
|
||||
case 66: {
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
SubscribeBluetoothLEAdvertisementsRequest msg;
|
||||
msg.decode(msg_data, msg_size);
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "on_subscribe_bluetooth_le_advertisements_request: %s", msg.dump().c_str());
|
||||
#endif
|
||||
this->on_subscribe_bluetooth_le_advertisements_request(msg);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case 68: {
|
||||
@ -810,6 +816,17 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
|
||||
ESP_LOGVV(TAG, "on_subscribe_bluetooth_connections_free_request: %s", msg.dump().c_str());
|
||||
#endif
|
||||
this->on_subscribe_bluetooth_connections_free_request(msg);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case 87: {
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
UnsubscribeBluetoothLEAdvertisementsRequest msg;
|
||||
msg.decode(msg_data, msg_size);
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "on_unsubscribe_bluetooth_le_advertisements_request: %s", msg.dump().c_str());
|
||||
#endif
|
||||
this->on_unsubscribe_bluetooth_le_advertisements_request(msg);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
@ -1073,6 +1090,7 @@ void APIServerConnection::on_media_player_command_request(const MediaPlayerComma
|
||||
this->media_player_command(msg);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
void APIServerConnection::on_subscribe_bluetooth_le_advertisements_request(
|
||||
const SubscribeBluetoothLEAdvertisementsRequest &msg) {
|
||||
if (!this->is_connection_setup()) {
|
||||
@ -1085,6 +1103,7 @@ void APIServerConnection::on_subscribe_bluetooth_le_advertisements_request(
|
||||
}
|
||||
this->subscribe_bluetooth_le_advertisements(msg);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
void APIServerConnection::on_bluetooth_device_request(const BluetoothDeviceRequest &msg) {
|
||||
if (!this->is_connection_setup()) {
|
||||
@ -1193,6 +1212,20 @@ void APIServerConnection::on_subscribe_bluetooth_connections_free_request(
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
void APIServerConnection::on_unsubscribe_bluetooth_le_advertisements_request(
|
||||
const UnsubscribeBluetoothLEAdvertisementsRequest &msg) {
|
||||
if (!this->is_connection_setup()) {
|
||||
this->on_no_setup_connection();
|
||||
return;
|
||||
}
|
||||
if (!this->is_authenticated()) {
|
||||
this->on_unauthenticated_access();
|
||||
return;
|
||||
}
|
||||
this->unsubscribe_bluetooth_le_advertisements(msg);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace api
|
||||
} // namespace esphome
|
||||
|
@ -154,8 +154,10 @@ class APIServerConnectionBase : public ProtoService {
|
||||
#ifdef USE_MEDIA_PLAYER
|
||||
virtual void on_media_player_command_request(const MediaPlayerCommandRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
virtual void on_subscribe_bluetooth_le_advertisements_request(
|
||||
const SubscribeBluetoothLEAdvertisementsRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool send_bluetooth_le_advertisement_response(const BluetoothLEAdvertisementResponse &msg);
|
||||
#endif
|
||||
@ -216,6 +218,10 @@ class APIServerConnectionBase : public ProtoService {
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool send_bluetooth_device_unpairing_response(const BluetoothDeviceUnpairingResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
virtual void on_unsubscribe_bluetooth_le_advertisements_request(
|
||||
const UnsubscribeBluetoothLEAdvertisementsRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool send_bluetooth_device_clear_cache_response(const BluetoothDeviceClearCacheResponse &msg);
|
||||
#endif
|
||||
@ -270,7 +276,9 @@ class APIServerConnection : public APIServerConnectionBase {
|
||||
#ifdef USE_MEDIA_PLAYER
|
||||
virtual void media_player_command(const MediaPlayerCommandRequest &msg) = 0;
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
virtual void subscribe_bluetooth_le_advertisements(const SubscribeBluetoothLEAdvertisementsRequest &msg) = 0;
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
virtual void bluetooth_device_request(const BluetoothDeviceRequest &msg) = 0;
|
||||
#endif
|
||||
@ -295,6 +303,9 @@ class APIServerConnection : public APIServerConnectionBase {
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
virtual BluetoothConnectionsFreeResponse subscribe_bluetooth_connections_free(
|
||||
const SubscribeBluetoothConnectionsFreeRequest &msg) = 0;
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
virtual void unsubscribe_bluetooth_le_advertisements(const UnsubscribeBluetoothLEAdvertisementsRequest &msg) = 0;
|
||||
#endif
|
||||
protected:
|
||||
void on_hello_request(const HelloRequest &msg) override;
|
||||
@ -342,7 +353,9 @@ class APIServerConnection : public APIServerConnectionBase {
|
||||
#ifdef USE_MEDIA_PLAYER
|
||||
void on_media_player_command_request(const MediaPlayerCommandRequest &msg) override;
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
void on_subscribe_bluetooth_le_advertisements_request(const SubscribeBluetoothLEAdvertisementsRequest &msg) override;
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
void on_bluetooth_device_request(const BluetoothDeviceRequest &msg) override;
|
||||
#endif
|
||||
@ -367,6 +380,10 @@ class APIServerConnection : public APIServerConnectionBase {
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
void on_subscribe_bluetooth_connections_free_request(const SubscribeBluetoothConnectionsFreeRequest &msg) override;
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
void on_unsubscribe_bluetooth_le_advertisements_request(
|
||||
const UnsubscribeBluetoothLEAdvertisementsRequest &msg) override;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
@ -12,7 +12,6 @@ from esphome.const import (
|
||||
CONF_CAPACITANCE,
|
||||
)
|
||||
|
||||
AUTO_LOAD = ["sensor", "binary_sensor"]
|
||||
MULTI_CONF = True
|
||||
|
||||
CONF_AS3935_ID = "as3935_id"
|
||||
|
@ -26,9 +26,13 @@ void AS3935Component::setup() {
|
||||
void AS3935Component::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "AS3935:");
|
||||
LOG_PIN(" Interrupt Pin: ", this->irq_pin_);
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
LOG_BINARY_SENSOR(" ", "Thunder alert", this->thunder_alert_binary_sensor_);
|
||||
#endif
|
||||
#ifdef USE_SENSOR
|
||||
LOG_SENSOR(" ", "Distance", this->distance_sensor_);
|
||||
LOG_SENSOR(" ", "Lightning energy", this->energy_sensor_);
|
||||
#endif
|
||||
}
|
||||
|
||||
float AS3935Component::get_setup_priority() const { return setup_priority::DATA; }
|
||||
@ -44,16 +48,22 @@ void AS3935Component::loop() {
|
||||
ESP_LOGI(TAG, "Disturber was detected - try increasing the spike rejection value!");
|
||||
} else if (int_value == LIGHTNING_INT) {
|
||||
ESP_LOGI(TAG, "Lightning has been detected!");
|
||||
if (this->thunder_alert_binary_sensor_ != nullptr)
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
if (this->thunder_alert_binary_sensor_ != nullptr) {
|
||||
this->thunder_alert_binary_sensor_->publish_state(true);
|
||||
this->set_timeout(10, [this]() { this->thunder_alert_binary_sensor_->publish_state(false); });
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SENSOR
|
||||
uint8_t distance = this->get_distance_to_storm_();
|
||||
if (this->distance_sensor_ != nullptr)
|
||||
this->distance_sensor_->publish_state(distance);
|
||||
|
||||
uint32_t energy = this->get_lightning_energy_();
|
||||
if (this->energy_sensor_ != nullptr)
|
||||
this->energy_sensor_->publish_state(energy);
|
||||
#endif
|
||||
}
|
||||
this->thunder_alert_binary_sensor_->publish_state(false);
|
||||
}
|
||||
|
||||
void AS3935Component::write_indoor(bool indoor) {
|
||||
|
@ -1,9 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/defines.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#ifdef USE_SENSOR
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#endif
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
#include "esphome/components/binary_sensor/binary_sensor.h"
|
||||
#endif
|
||||
|
||||
namespace esphome {
|
||||
namespace as3935 {
|
||||
@ -52,6 +57,15 @@ enum AS3935Values {
|
||||
};
|
||||
|
||||
class AS3935Component : public Component {
|
||||
#ifdef USE_SENSOR
|
||||
SUB_SENSOR(distance)
|
||||
SUB_SENSOR(energy)
|
||||
#endif
|
||||
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
SUB_BINARY_SENSOR(thunder_alert)
|
||||
#endif
|
||||
|
||||
public:
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
@ -59,11 +73,7 @@ class AS3935Component : public Component {
|
||||
void loop() override;
|
||||
|
||||
void set_irq_pin(GPIOPin *irq_pin) { irq_pin_ = irq_pin; }
|
||||
void set_distance_sensor(sensor::Sensor *distance_sensor) { distance_sensor_ = distance_sensor; }
|
||||
void set_energy_sensor(sensor::Sensor *energy_sensor) { energy_sensor_ = energy_sensor; }
|
||||
void set_thunder_alert_binary_sensor(binary_sensor::BinarySensor *thunder_alert_binary_sensor) {
|
||||
thunder_alert_binary_sensor_ = thunder_alert_binary_sensor;
|
||||
}
|
||||
|
||||
void set_indoor(bool indoor) { indoor_ = indoor; }
|
||||
void write_indoor(bool indoor);
|
||||
void set_noise_level(uint8_t noise_level) { noise_level_ = noise_level; }
|
||||
@ -92,9 +102,6 @@ class AS3935Component : public Component {
|
||||
|
||||
virtual void write_register(uint8_t reg, uint8_t mask, uint8_t bits, uint8_t start_position) = 0;
|
||||
|
||||
sensor::Sensor *distance_sensor_{nullptr};
|
||||
sensor::Sensor *energy_sensor_{nullptr};
|
||||
binary_sensor::BinarySensor *thunder_alert_binary_sensor_{nullptr};
|
||||
GPIOPin *irq_pin_;
|
||||
|
||||
bool indoor_;
|
||||
|
@ -30,7 +30,7 @@ void BinarySensorMap::process_group_() {
|
||||
if (bs.binary_sensor->state) {
|
||||
num_active_sensors++;
|
||||
total_current_value += bs.sensor_value;
|
||||
mask |= 1 << i;
|
||||
mask |= 1ULL << i;
|
||||
}
|
||||
}
|
||||
// check if the sensor map was touched
|
||||
@ -38,12 +38,11 @@ void BinarySensorMap::process_group_() {
|
||||
// did the bit_mask change or is it a new sensor touch
|
||||
if (this->last_mask_ != mask) {
|
||||
float publish_value = total_current_value / num_active_sensors;
|
||||
ESP_LOGD(TAG, "'%s' - Publishing %.2f", this->name_.c_str(), publish_value);
|
||||
this->publish_state(publish_value);
|
||||
}
|
||||
} else if (this->last_mask_ != 0ULL) {
|
||||
// is this a new sensor release
|
||||
ESP_LOGD(TAG, "'%s' - No binary sensor active, publishing NAN", this->name_.c_str());
|
||||
ESP_LOGV(TAG, "'%s' - No binary sensor active, publishing NAN", this->name_.c_str());
|
||||
this->publish_state(NAN);
|
||||
}
|
||||
this->last_mask_ = mask;
|
||||
@ -52,28 +51,22 @@ void BinarySensorMap::process_group_() {
|
||||
void BinarySensorMap::process_sum_() {
|
||||
float total_current_value = 0.0;
|
||||
uint64_t mask = 0x00;
|
||||
// check all binary_sensors for its state. when active add its value to total_current_value.
|
||||
// create a bitmask for the binary_sensor status on all channels
|
||||
// - check all binary_sensor states
|
||||
// - if active, add its value to total_current_value
|
||||
// - creates a bitmask for the binary_sensor status on all channels
|
||||
for (size_t i = 0; i < this->channels_.size(); i++) {
|
||||
auto bs = this->channels_[i];
|
||||
if (bs.binary_sensor->state) {
|
||||
total_current_value += bs.sensor_value;
|
||||
mask |= 1 << i;
|
||||
mask |= 1ULL << i;
|
||||
}
|
||||
}
|
||||
// check if the sensor map was touched
|
||||
if (mask != 0ULL) {
|
||||
// did the bit_mask change or is it a new sensor touch
|
||||
if (this->last_mask_ != mask) {
|
||||
float publish_value = total_current_value;
|
||||
ESP_LOGD(TAG, "'%s' - Publishing %.2f", this->name_.c_str(), publish_value);
|
||||
this->publish_state(publish_value);
|
||||
}
|
||||
} else if (this->last_mask_ != 0ULL) {
|
||||
// is this a new sensor release
|
||||
ESP_LOGD(TAG, "'%s' - No binary sensor active, publishing 0", this->name_.c_str());
|
||||
this->publish_state(0.0);
|
||||
|
||||
// update state only if the binary sensor states have changed or if no state has ever been sent on boot
|
||||
if ((this->last_mask_ != mask) || (!this->has_state())) {
|
||||
this->publish_state(total_current_value);
|
||||
}
|
||||
|
||||
this->last_mask_ = mask;
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ CONFIG_SCHEMA = cv.typed_schema(
|
||||
).extend(
|
||||
{
|
||||
cv.Required(CONF_CHANNELS): cv.All(
|
||||
cv.ensure_list(entry), cv.Length(min=1)
|
||||
cv.ensure_list(entry), cv.Length(min=1, max=64)
|
||||
),
|
||||
}
|
||||
),
|
||||
@ -50,7 +50,7 @@ CONFIG_SCHEMA = cv.typed_schema(
|
||||
).extend(
|
||||
{
|
||||
cv.Required(CONF_CHANNELS): cv.All(
|
||||
cv.ensure_list(entry), cv.Length(min=1)
|
||||
cv.ensure_list(entry), cv.Length(min=1, max=64)
|
||||
),
|
||||
}
|
||||
),
|
||||
|
@ -6,9 +6,6 @@ namespace button {
|
||||
|
||||
static const char *const TAG = "button";
|
||||
|
||||
Button::Button(const std::string &name) : EntityBase(name) {}
|
||||
Button::Button() : Button("") {}
|
||||
|
||||
void Button::press() {
|
||||
ESP_LOGD(TAG, "'%s' Pressed.", this->get_name().c_str());
|
||||
this->press_action();
|
||||
|
@ -28,9 +28,6 @@ namespace button {
|
||||
*/
|
||||
class Button : public EntityBase {
|
||||
public:
|
||||
explicit Button();
|
||||
explicit Button(const std::string &name);
|
||||
|
||||
/** Press this button. This is called by the front-end.
|
||||
*
|
||||
* For implementing buttons, please override press_action.
|
||||
|
@ -453,12 +453,7 @@ void Climate::set_visual_temperature_step_override(float target, float current)
|
||||
this->visual_target_temperature_step_override_ = target;
|
||||
this->visual_current_temperature_step_override_ = current;
|
||||
}
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
Climate::Climate(const std::string &name) : EntityBase(name) {}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
Climate::Climate() : Climate("") {}
|
||||
ClimateCall Climate::make_call() { return ClimateCall(this); }
|
||||
|
||||
ClimateCall ClimateDeviceRestoreState::to_call(Climate *climate) {
|
||||
|
@ -166,11 +166,6 @@ struct ClimateDeviceRestoreState {
|
||||
*/
|
||||
class Climate : public EntityBase {
|
||||
public:
|
||||
/// Construct a climate device with empty name (will be set later).
|
||||
Climate();
|
||||
/// Construct a climate device with a name.
|
||||
Climate(const std::string &name);
|
||||
|
||||
/// The active mode of the climate device.
|
||||
ClimateMode mode{CLIMATE_MODE_OFF};
|
||||
/// The active state of the climate device.
|
||||
|
@ -31,7 +31,7 @@ const char *cover_operation_to_str(CoverOperation op) {
|
||||
}
|
||||
}
|
||||
|
||||
Cover::Cover(const std::string &name) : EntityBase(name), position{COVER_OPEN} {}
|
||||
Cover::Cover() : position{COVER_OPEN} {}
|
||||
|
||||
CoverCall::CoverCall(Cover *parent) : parent_(parent) {}
|
||||
CoverCall &CoverCall::set_command(const char *command) {
|
||||
@ -204,7 +204,6 @@ optional<CoverRestoreState> Cover::restore_state_() {
|
||||
return {};
|
||||
return recovered;
|
||||
}
|
||||
Cover::Cover() : Cover("") {}
|
||||
std::string Cover::get_device_class() {
|
||||
if (this->device_class_override_.has_value())
|
||||
return *this->device_class_override_;
|
||||
|
@ -111,7 +111,6 @@ const char *cover_operation_to_str(CoverOperation op);
|
||||
class Cover : public EntityBase {
|
||||
public:
|
||||
explicit Cover();
|
||||
explicit Cover(const std::string &name);
|
||||
|
||||
/// The current operation of the cover (idle, opening, closing).
|
||||
CoverOperation current_operation{COVER_OPERATION_IDLE};
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <esp_bt.h>
|
||||
#include <esp_bt_main.h>
|
||||
#include <esp_bt_device.h>
|
||||
#include <esp_gap_ble_api.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/FreeRTOSConfig.h>
|
||||
@ -211,7 +212,16 @@ void ESP32BLE::real_gattc_event_handler_(esp_gattc_cb_event_t event, esp_gatt_if
|
||||
|
||||
float ESP32BLE::get_setup_priority() const { return setup_priority::BLUETOOTH; }
|
||||
|
||||
void ESP32BLE::dump_config() { ESP_LOGCONFIG(TAG, "ESP32 BLE:"); }
|
||||
void ESP32BLE::dump_config() {
|
||||
const uint8_t *mac_address = esp_bt_dev_get_address();
|
||||
if (mac_address) {
|
||||
ESP_LOGCONFIG(TAG, "ESP32 BLE:");
|
||||
ESP_LOGCONFIG(TAG, " MAC address: %02X:%02X:%02X:%02X:%02X:%02X", mac_address[0], mac_address[1], mac_address[2],
|
||||
mac_address[3], mac_address[4], mac_address[5]);
|
||||
} else {
|
||||
ESP_LOGCONFIG(TAG, "ESP32 BLE: bluetooth stack is not enabled");
|
||||
}
|
||||
}
|
||||
|
||||
ESP32BLE *global_ble = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
|
@ -202,7 +202,7 @@ void ESP32Camera::loop() {
|
||||
float ESP32Camera::get_setup_priority() const { return setup_priority::DATA; }
|
||||
|
||||
/* ---------------- constructors ---------------- */
|
||||
ESP32Camera::ESP32Camera(const std::string &name) : EntityBase(name) {
|
||||
ESP32Camera::ESP32Camera() {
|
||||
this->config_.pin_pwdn = -1;
|
||||
this->config_.pin_reset = -1;
|
||||
this->config_.pin_xclk = -1;
|
||||
@ -215,7 +215,6 @@ ESP32Camera::ESP32Camera(const std::string &name) : EntityBase(name) {
|
||||
|
||||
global_esp32_camera = this;
|
||||
}
|
||||
ESP32Camera::ESP32Camera() : ESP32Camera("") {}
|
||||
|
||||
/* ---------------- setters ---------------- */
|
||||
/* set pin assignment */
|
||||
|
@ -103,7 +103,6 @@ class CameraImageReader {
|
||||
/* ---------------- ESP32Camera class ---------------- */
|
||||
class ESP32Camera : public Component, public EntityBase {
|
||||
public:
|
||||
ESP32Camera(const std::string &name);
|
||||
ESP32Camera();
|
||||
|
||||
/* setters */
|
||||
|
@ -12,14 +12,14 @@ static const char *const TAG = "ezo.sensor";
|
||||
|
||||
enum EzoCommandType : uint8_t {
|
||||
EZO_READ = 0,
|
||||
EZO_LED = 1,
|
||||
EZO_DEVICE_INFORMATION = 2,
|
||||
EZO_SLOPE = 3,
|
||||
EZO_LED,
|
||||
EZO_DEVICE_INFORMATION,
|
||||
EZO_SLOPE,
|
||||
EZO_CALIBRATION,
|
||||
EZO_SLEEP = 4,
|
||||
EZO_I2C = 5,
|
||||
EZO_T = 6,
|
||||
EZO_CUSTOM = 7
|
||||
EZO_SLEEP,
|
||||
EZO_I2C,
|
||||
EZO_T,
|
||||
EZO_CUSTOM
|
||||
};
|
||||
|
||||
enum EzoCalibrationType : uint8_t { EZO_CAL_LOW = 0, EZO_CAL_MID = 1, EZO_CAL_HIGH = 2 };
|
||||
|
@ -80,9 +80,6 @@ void FanRestoreState::apply(Fan &fan) {
|
||||
fan.publish_state();
|
||||
}
|
||||
|
||||
Fan::Fan() : EntityBase("") {}
|
||||
Fan::Fan(const std::string &name) : EntityBase(name) {}
|
||||
|
||||
FanCall Fan::turn_on() { return this->make_call().set_state(true); }
|
||||
FanCall Fan::turn_off() { return this->make_call().set_state(false); }
|
||||
FanCall Fan::toggle() { return this->make_call().set_state(!this->state); }
|
||||
|
@ -99,10 +99,6 @@ struct FanRestoreState {
|
||||
|
||||
class Fan : public EntityBase {
|
||||
public:
|
||||
Fan();
|
||||
/// Construct the fan with name.
|
||||
explicit Fan(const std::string &name);
|
||||
|
||||
/// The current on/off state of the fan.
|
||||
bool state{false};
|
||||
/// The current oscillation state of the fan.
|
||||
|
@ -15,7 +15,6 @@ enum ESPDEPRECATED("LegacyFanDirection members are deprecated, use FanDirection
|
||||
class ESPDEPRECATED("FanState is deprecated, use Fan instead.", "2022.2") FanState : public Fan, public Component {
|
||||
public:
|
||||
FanState() = default;
|
||||
explicit FanState(const std::string &name) : Fan(name) {}
|
||||
|
||||
/// Get the traits of this fan.
|
||||
FanTraits get_traits() override { return this->traits_; }
|
||||
|
@ -8,7 +8,6 @@ namespace light {
|
||||
|
||||
static const char *const TAG = "light";
|
||||
|
||||
LightState::LightState(const std::string &name, LightOutput *output) : EntityBase(name), output_(output) {}
|
||||
LightState::LightState(LightOutput *output) : output_(output) {}
|
||||
|
||||
LightTraits LightState::get_traits() { return this->output_->get_traits(); }
|
||||
|
@ -33,9 +33,6 @@ enum LightRestoreMode {
|
||||
*/
|
||||
class LightState : public EntityBase, public Component {
|
||||
public:
|
||||
/// Construct this LightState using the provided traits and name.
|
||||
LightState(const std::string &name, LightOutput *output);
|
||||
|
||||
LightState(LightOutput *output);
|
||||
|
||||
LightTraits get_traits();
|
||||
|
@ -24,8 +24,7 @@ const char *lock_state_to_string(LockState state) {
|
||||
}
|
||||
}
|
||||
|
||||
Lock::Lock(const std::string &name) : EntityBase(name), state(LOCK_STATE_NONE) {}
|
||||
Lock::Lock() : Lock("") {}
|
||||
Lock::Lock() : state(LOCK_STATE_NONE) {}
|
||||
LockCall Lock::make_call() { return LockCall(this); }
|
||||
|
||||
void Lock::lock() {
|
||||
|
@ -103,7 +103,6 @@ class LockCall {
|
||||
class Lock : public EntityBase {
|
||||
public:
|
||||
explicit Lock();
|
||||
explicit Lock(const std::string &name);
|
||||
|
||||
/** Make a lock device control call, this is used to control the lock device, see the LockCall description
|
||||
* for more info.
|
||||
|
@ -31,6 +31,7 @@ from esphome.const import (
|
||||
DEVICE_CLASS_DISTANCE,
|
||||
DEVICE_CLASS_EMPTY,
|
||||
DEVICE_CLASS_ENERGY,
|
||||
DEVICE_CLASS_ENERGY_STORAGE,
|
||||
DEVICE_CLASS_FREQUENCY,
|
||||
DEVICE_CLASS_GAS,
|
||||
DEVICE_CLASS_HUMIDITY,
|
||||
@ -59,6 +60,7 @@ from esphome.const import (
|
||||
DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS,
|
||||
DEVICE_CLASS_VOLTAGE,
|
||||
DEVICE_CLASS_VOLUME,
|
||||
DEVICE_CLASS_VOLUME_STORAGE,
|
||||
DEVICE_CLASS_WATER,
|
||||
DEVICE_CLASS_WEIGHT,
|
||||
DEVICE_CLASS_WIND_SPEED,
|
||||
@ -81,6 +83,7 @@ DEVICE_CLASSES = [
|
||||
DEVICE_CLASS_DISTANCE,
|
||||
DEVICE_CLASS_EMPTY,
|
||||
DEVICE_CLASS_ENERGY,
|
||||
DEVICE_CLASS_ENERGY_STORAGE,
|
||||
DEVICE_CLASS_FREQUENCY,
|
||||
DEVICE_CLASS_GAS,
|
||||
DEVICE_CLASS_HUMIDITY,
|
||||
@ -109,6 +112,7 @@ DEVICE_CLASSES = [
|
||||
DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS,
|
||||
DEVICE_CLASS_VOLTAGE,
|
||||
DEVICE_CLASS_VOLUME,
|
||||
DEVICE_CLASS_VOLUME_STORAGE,
|
||||
DEVICE_CLASS_WATER,
|
||||
DEVICE_CLASS_WEIGHT,
|
||||
DEVICE_CLASS_WIND_SPEED,
|
||||
|
@ -102,7 +102,7 @@ async def to_code(config):
|
||||
conf[CONF_ADDRESSABLE_LIGHT_ID],
|
||||
await cg.get_variable(conf[CONF_SINGLE_LIGHT_ID]),
|
||||
)
|
||||
light_state = cg.new_Pvariable(conf[CONF_LIGHT_ID], "", wrapper)
|
||||
light_state = cg.new_Pvariable(conf[CONF_LIGHT_ID], wrapper)
|
||||
await cg.register_component(light_state, conf)
|
||||
segments.append(AddressableSegment(light_state, 0, 1, False))
|
||||
|
||||
|
@ -43,6 +43,7 @@ from esphome.const import (
|
||||
DEVICE_CLASS_DURATION,
|
||||
DEVICE_CLASS_EMPTY,
|
||||
DEVICE_CLASS_ENERGY,
|
||||
DEVICE_CLASS_ENERGY_STORAGE,
|
||||
DEVICE_CLASS_FREQUENCY,
|
||||
DEVICE_CLASS_GAS,
|
||||
DEVICE_CLASS_HUMIDITY,
|
||||
@ -72,6 +73,7 @@ from esphome.const import (
|
||||
DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS,
|
||||
DEVICE_CLASS_VOLTAGE,
|
||||
DEVICE_CLASS_VOLUME,
|
||||
DEVICE_CLASS_VOLUME_STORAGE,
|
||||
DEVICE_CLASS_WATER,
|
||||
DEVICE_CLASS_WEIGHT,
|
||||
DEVICE_CLASS_WIND_SPEED,
|
||||
@ -97,6 +99,7 @@ DEVICE_CLASSES = [
|
||||
DEVICE_CLASS_DURATION,
|
||||
DEVICE_CLASS_EMPTY,
|
||||
DEVICE_CLASS_ENERGY,
|
||||
DEVICE_CLASS_ENERGY_STORAGE,
|
||||
DEVICE_CLASS_FREQUENCY,
|
||||
DEVICE_CLASS_GAS,
|
||||
DEVICE_CLASS_HUMIDITY,
|
||||
@ -126,6 +129,7 @@ DEVICE_CLASSES = [
|
||||
DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS,
|
||||
DEVICE_CLASS_VOLTAGE,
|
||||
DEVICE_CLASS_VOLUME,
|
||||
DEVICE_CLASS_VOLUME_STORAGE,
|
||||
DEVICE_CLASS_WATER,
|
||||
DEVICE_CLASS_WEIGHT,
|
||||
DEVICE_CLASS_WIND_SPEED,
|
||||
|
@ -20,8 +20,7 @@ std::string state_class_to_string(StateClass state_class) {
|
||||
}
|
||||
}
|
||||
|
||||
Sensor::Sensor(const std::string &name) : EntityBase(name), state(NAN), raw_state(NAN) {}
|
||||
Sensor::Sensor() : Sensor("") {}
|
||||
Sensor::Sensor() : state(NAN), raw_state(NAN) {}
|
||||
|
||||
std::string Sensor::get_unit_of_measurement() {
|
||||
if (this->unit_of_measurement_.has_value())
|
||||
|
@ -57,7 +57,6 @@ std::string state_class_to_string(StateClass state_class);
|
||||
class Sensor : public EntityBase {
|
||||
public:
|
||||
explicit Sensor();
|
||||
explicit Sensor(const std::string &name);
|
||||
|
||||
/// Get the unit of measurement, using the manual override if set.
|
||||
std::string get_unit_of_measurement();
|
||||
@ -162,7 +161,6 @@ class Sensor : public EntityBase {
|
||||
CallbackManager<void(float)> raw_callback_; ///< Storage for raw state callbacks.
|
||||
CallbackManager<void(float)> callback_; ///< Storage for filtered state callbacks.
|
||||
|
||||
bool has_state_{false};
|
||||
Filter *filter_list_{nullptr}; ///< Store all active filters.
|
||||
|
||||
optional<std::string> unit_of_measurement_; ///< Unit of measurement override
|
||||
@ -170,6 +168,7 @@ class Sensor : public EntityBase {
|
||||
optional<std::string> device_class_; ///< Device class override
|
||||
optional<StateClass> state_class_{STATE_CLASS_NONE}; ///< State class override
|
||||
bool force_update_{false}; ///< Force update mode
|
||||
bool has_state_{false};
|
||||
};
|
||||
|
||||
} // namespace sensor
|
||||
|
@ -6,8 +6,7 @@ namespace switch_ {
|
||||
|
||||
static const char *const TAG = "switch";
|
||||
|
||||
Switch::Switch(const std::string &name) : EntityBase(name), state(false) {}
|
||||
Switch::Switch() : Switch("") {}
|
||||
Switch::Switch() : state(false) {}
|
||||
|
||||
void Switch::turn_on() {
|
||||
ESP_LOGD(TAG, "'%s' Turning ON.", this->get_name().c_str());
|
||||
|
@ -32,7 +32,6 @@ enum SwitchRestoreMode {
|
||||
class Switch : public EntityBase {
|
||||
public:
|
||||
explicit Switch();
|
||||
explicit Switch(const std::string &name);
|
||||
|
||||
/** Publish a state to the front-end from the back-end.
|
||||
*
|
||||
|
@ -6,9 +6,6 @@ namespace text_sensor {
|
||||
|
||||
static const char *const TAG = "text_sensor";
|
||||
|
||||
TextSensor::TextSensor() : TextSensor("") {}
|
||||
TextSensor::TextSensor(const std::string &name) : EntityBase(name) {}
|
||||
|
||||
void TextSensor::publish_state(const std::string &state) {
|
||||
this->raw_state = state;
|
||||
this->raw_callback_.call(state);
|
||||
|
@ -30,9 +30,6 @@ namespace text_sensor {
|
||||
|
||||
class TextSensor : public EntityBase {
|
||||
public:
|
||||
explicit TextSensor();
|
||||
explicit TextSensor(const std::string &name);
|
||||
|
||||
/// Getter-syntax for .state.
|
||||
std::string get_state() const;
|
||||
/// Getter-syntax for .raw_state
|
||||
|
@ -100,8 +100,8 @@ void ESP32ArduinoUARTComponent::setup() {
|
||||
invert = true;
|
||||
if (rx_pin_ != nullptr && rx_pin_->is_inverted())
|
||||
invert = true;
|
||||
this->hw_serial_->begin(this->baud_rate_, get_config(), rx, tx, invert);
|
||||
this->hw_serial_->setRxBufferSize(this->rx_buffer_size_);
|
||||
this->hw_serial_->begin(this->baud_rate_, get_config(), rx, tx, invert);
|
||||
}
|
||||
|
||||
void ESP32ArduinoUARTComponent::dump_config() {
|
||||
|
@ -28,6 +28,9 @@ class ESP32ArduinoUARTComponent : public UARTComponent, public Component {
|
||||
|
||||
uint32_t get_config();
|
||||
|
||||
HardwareSerial *get_hw_serial() { return this->hw_serial_; }
|
||||
uint8_t get_hw_serial_number() { return this->number_; }
|
||||
|
||||
protected:
|
||||
void check_logger_conflict() override;
|
||||
|
||||
|
@ -79,7 +79,12 @@ void IDFUARTComponent::setup() {
|
||||
return;
|
||||
}
|
||||
|
||||
err = uart_driver_install(this->uart_num_, this->rx_buffer_size_, 0, 0, nullptr, 0);
|
||||
err = uart_driver_install(this->uart_num_, /* UART RX ring buffer size. */ this->rx_buffer_size_,
|
||||
/* UART TX ring buffer size. If set to zero, driver will not use TX buffer, TX function will
|
||||
block task until all data have been sent out.*/
|
||||
0,
|
||||
/* UART event queue size/depth. */ 20, &(this->uart_event_queue_),
|
||||
/* Flags used to allocate the interrupt. */ 0);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "uart_driver_install failed: %s", esp_err_to_name(err));
|
||||
this->mark_failed();
|
||||
|
@ -23,9 +23,13 @@ class IDFUARTComponent : public UARTComponent, public Component {
|
||||
int available() override;
|
||||
void flush() override;
|
||||
|
||||
uint8_t get_hw_serial_number() { return this->uart_num_; }
|
||||
QueueHandle_t *get_uart_event_queue() { return &this->uart_event_queue_; }
|
||||
|
||||
protected:
|
||||
void check_logger_conflict() override;
|
||||
uart_port_t uart_num_;
|
||||
QueueHandle_t uart_event_queue_;
|
||||
uart_config_t get_config_();
|
||||
SemaphoreHandle_t lock_;
|
||||
|
||||
|
@ -30,6 +30,9 @@ class RP2040UartComponent : public UARTComponent, public Component {
|
||||
|
||||
uint16_t get_config();
|
||||
|
||||
bool is_hw_serial() { return this->hw_serial_; }
|
||||
HardwareSerial *get_hw_serial() { return this->serial_; }
|
||||
|
||||
protected:
|
||||
void check_logger_conflict() override {}
|
||||
bool hw_serial_{false};
|
||||
|
@ -946,6 +946,7 @@ DEVICE_CLASS_DOOR = "door"
|
||||
DEVICE_CLASS_DURATION = "duration"
|
||||
DEVICE_CLASS_EMPTY = ""
|
||||
DEVICE_CLASS_ENERGY = "energy"
|
||||
DEVICE_CLASS_ENERGY_STORAGE = "energy_storage"
|
||||
DEVICE_CLASS_FREQUENCY = "frequency"
|
||||
DEVICE_CLASS_GARAGE = "garage"
|
||||
DEVICE_CLASS_GARAGE_DOOR = "garage_door"
|
||||
@ -1000,6 +1001,7 @@ DEVICE_CLASS_VIBRATION = "vibration"
|
||||
DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS = "volatile_organic_compounds"
|
||||
DEVICE_CLASS_VOLTAGE = "voltage"
|
||||
DEVICE_CLASS_VOLUME = "volume"
|
||||
DEVICE_CLASS_VOLUME_STORAGE = "volume_storage"
|
||||
DEVICE_CLASS_WATER = "water"
|
||||
DEVICE_CLASS_WEIGHT = "weight"
|
||||
DEVICE_CLASS_WINDOW = "window"
|
||||
|
@ -6,19 +6,16 @@ namespace esphome {
|
||||
|
||||
static const char *const TAG = "entity_base";
|
||||
|
||||
EntityBase::EntityBase(std::string name) : name_(std::move(name)) { this->calc_object_id_(); }
|
||||
|
||||
// Entity Name
|
||||
const std::string &EntityBase::get_name() const { return this->name_; }
|
||||
void EntityBase::set_name(const std::string &name) {
|
||||
if (name.empty()) {
|
||||
this->name_ = App.get_friendly_name();
|
||||
const StringRef &EntityBase::get_name() const { return this->name_; }
|
||||
void EntityBase::set_name(const char *name) {
|
||||
this->name_ = StringRef(name);
|
||||
if (this->name_.empty()) {
|
||||
this->name_ = StringRef(App.get_friendly_name());
|
||||
this->has_own_name_ = false;
|
||||
} else {
|
||||
this->name_ = name;
|
||||
this->has_own_name_ = true;
|
||||
}
|
||||
this->calc_object_id_();
|
||||
}
|
||||
|
||||
// Entity Internal
|
||||
@ -43,13 +40,37 @@ EntityCategory EntityBase::get_entity_category() const { return this->entity_cat
|
||||
void EntityBase::set_entity_category(EntityCategory entity_category) { this->entity_category_ = entity_category; }
|
||||
|
||||
// Entity Object ID
|
||||
const std::string &EntityBase::get_object_id() { return this->object_id_; }
|
||||
std::string EntityBase::get_object_id() const {
|
||||
// Check if `App.get_friendly_name()` is constant or dynamic.
|
||||
if (!this->has_own_name_ && App.is_name_add_mac_suffix_enabled()) {
|
||||
// `App.get_friendly_name()` is dynamic.
|
||||
return str_sanitize(str_snake_case(App.get_friendly_name()));
|
||||
} else {
|
||||
// `App.get_friendly_name()` is constant.
|
||||
if (this->object_id_c_str_ == nullptr) {
|
||||
return "";
|
||||
}
|
||||
return this->object_id_c_str_;
|
||||
}
|
||||
}
|
||||
void EntityBase::set_object_id(const char *object_id) {
|
||||
this->object_id_c_str_ = object_id;
|
||||
this->calc_object_id_();
|
||||
}
|
||||
|
||||
// Calculate Object ID Hash from Entity Name
|
||||
void EntityBase::calc_object_id_() {
|
||||
this->object_id_ = str_sanitize(str_snake_case(this->name_));
|
||||
// FNV-1 hash
|
||||
this->object_id_hash_ = fnv1_hash(this->object_id_);
|
||||
// Check if `App.get_friendly_name()` is constant or dynamic.
|
||||
if (!this->has_own_name_ && App.is_name_add_mac_suffix_enabled()) {
|
||||
// `App.get_friendly_name()` is dynamic.
|
||||
const auto object_id = str_sanitize(str_snake_case(App.get_friendly_name()));
|
||||
// FNV-1 hash
|
||||
this->object_id_hash_ = fnv1_hash(object_id);
|
||||
} else {
|
||||
// `App.get_friendly_name()` is constant.
|
||||
// FNV-1 hash
|
||||
this->object_id_hash_ = fnv1_hash(this->object_id_c_str_);
|
||||
}
|
||||
}
|
||||
uint32_t EntityBase::get_object_id_hash() { return this->object_id_hash_; }
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include "string_ref.h"
|
||||
|
||||
namespace esphome {
|
||||
|
||||
@ -14,18 +15,16 @@ enum EntityCategory : uint8_t {
|
||||
// The generic Entity base class that provides an interface common to all Entities.
|
||||
class EntityBase {
|
||||
public:
|
||||
EntityBase() : EntityBase("") {}
|
||||
explicit EntityBase(std::string name);
|
||||
|
||||
// Get/set the name of this Entity
|
||||
const std::string &get_name() const;
|
||||
void set_name(const std::string &name);
|
||||
const StringRef &get_name() const;
|
||||
void set_name(const char *name);
|
||||
|
||||
// Get whether this Entity has its own name or it should use the device friendly_name.
|
||||
bool has_own_name() const { return this->has_own_name_; }
|
||||
|
||||
// Get the sanitized name of this Entity as an ID. Caching it internally.
|
||||
const std::string &get_object_id();
|
||||
// Get the sanitized name of this Entity as an ID.
|
||||
std::string get_object_id() const;
|
||||
void set_object_id(const char *object_id);
|
||||
|
||||
// Get the unique Object ID of this Entity
|
||||
uint32_t get_object_id_hash();
|
||||
@ -54,11 +53,11 @@ class EntityBase {
|
||||
virtual uint32_t hash_base() { return 0L; }
|
||||
void calc_object_id_();
|
||||
|
||||
std::string name_;
|
||||
bool has_own_name_{false};
|
||||
std::string object_id_;
|
||||
StringRef name_;
|
||||
const char *object_id_c_str_{nullptr};
|
||||
const char *icon_c_str_{nullptr};
|
||||
uint32_t object_id_hash_;
|
||||
bool has_own_name_{false};
|
||||
bool internal_{false};
|
||||
bool disabled_by_default_{false};
|
||||
EntityCategory entity_category_{ENTITY_CATEGORY_NONE};
|
||||
|
12
esphome/core/string_ref.cpp
Normal file
12
esphome/core/string_ref.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
#include "string_ref.h"
|
||||
|
||||
namespace esphome {
|
||||
|
||||
#ifdef USE_JSON
|
||||
|
||||
// NOLINTNEXTLINE(readability-identifier-naming)
|
||||
void convertToJson(const StringRef &src, JsonVariant dst) { dst.set(src.c_str()); }
|
||||
|
||||
#endif // USE_JSON
|
||||
|
||||
} // namespace esphome
|
134
esphome/core/string_ref.h
Normal file
134
esphome/core/string_ref.h
Normal file
@ -0,0 +1,134 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <iterator>
|
||||
#include <cstring>
|
||||
#include "esphome/core/defines.h"
|
||||
|
||||
#ifdef USE_JSON
|
||||
#include "esphome/components/json/json_util.h"
|
||||
#endif // USE_JSON
|
||||
|
||||
namespace esphome {
|
||||
|
||||
/**
|
||||
* StringRef is a reference to a string owned by something else. So it behaves like simple string, but it does not own
|
||||
* pointer. When it is default constructed, it has empty string. You can freely copy or move around this struct, but
|
||||
* never free its pointer. str() function can be used to export the content as std::string. StringRef is adopted from
|
||||
* <https://github.com/nghttp2/nghttp2/blob/29cbf8b83ff78faf405d1086b16adc09a8772eca/src/template.h#L376>
|
||||
*/
|
||||
class StringRef {
|
||||
public:
|
||||
using traits_type = std::char_traits<char>;
|
||||
using value_type = traits_type::char_type;
|
||||
using allocator_type = std::allocator<char>;
|
||||
using size_type = std::allocator_traits<allocator_type>::size_type;
|
||||
using difference_type = std::allocator_traits<allocator_type>::difference_type;
|
||||
using const_reference = const value_type &;
|
||||
using const_pointer = const value_type *;
|
||||
using const_iterator = const_pointer;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
constexpr StringRef() : base_(""), len_(0) {}
|
||||
explicit StringRef(const std::string &s) : base_(s.c_str()), len_(s.size()) {}
|
||||
explicit StringRef(const char *s) : base_(s), len_(strlen(s)) {}
|
||||
constexpr StringRef(const char *s, size_t n) : base_(s), len_(n) {}
|
||||
template<typename CharT>
|
||||
constexpr StringRef(const CharT *s, size_t n) : base_(reinterpret_cast<const char *>(s)), len_(n) {}
|
||||
template<typename InputIt>
|
||||
StringRef(InputIt first, InputIt last)
|
||||
: base_(reinterpret_cast<const char *>(&*first)), len_(std::distance(first, last)) {}
|
||||
template<typename InputIt>
|
||||
StringRef(InputIt *first, InputIt *last)
|
||||
: base_(reinterpret_cast<const char *>(first)), len_(std::distance(first, last)) {}
|
||||
template<typename CharT, size_t N> constexpr static StringRef from_lit(const CharT (&s)[N]) {
|
||||
return StringRef{s, N - 1};
|
||||
}
|
||||
static StringRef from_maybe_nullptr(const char *s) {
|
||||
if (s == nullptr) {
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
return StringRef(s);
|
||||
}
|
||||
|
||||
constexpr const_iterator begin() const { return base_; };
|
||||
constexpr const_iterator cbegin() const { return base_; };
|
||||
|
||||
constexpr const_iterator end() const { return base_ + len_; };
|
||||
constexpr const_iterator cend() const { return base_ + len_; };
|
||||
|
||||
const_reverse_iterator rbegin() const { return const_reverse_iterator{base_ + len_}; }
|
||||
const_reverse_iterator crbegin() const { return const_reverse_iterator{base_ + len_}; }
|
||||
|
||||
const_reverse_iterator rend() const { return const_reverse_iterator{base_}; }
|
||||
const_reverse_iterator crend() const { return const_reverse_iterator{base_}; }
|
||||
|
||||
constexpr const char *c_str() const { return base_; }
|
||||
constexpr size_type size() const { return len_; }
|
||||
constexpr bool empty() const { return len_ == 0; }
|
||||
constexpr const_reference operator[](size_type pos) const { return *(base_ + pos); }
|
||||
|
||||
std::string str() const { return std::string(base_, len_); }
|
||||
const uint8_t *byte() const { return reinterpret_cast<const uint8_t *>(base_); }
|
||||
|
||||
operator std::string() const { return str(); }
|
||||
|
||||
private:
|
||||
const char *base_;
|
||||
size_type len_;
|
||||
};
|
||||
|
||||
inline bool operator==(const StringRef &lhs, const StringRef &rhs) {
|
||||
return lhs.size() == rhs.size() && std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs));
|
||||
}
|
||||
|
||||
inline bool operator==(const StringRef &lhs, const std::string &rhs) {
|
||||
return lhs.size() == rhs.size() && std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs));
|
||||
}
|
||||
|
||||
inline bool operator==(const std::string &lhs, const StringRef &rhs) { return rhs == lhs; }
|
||||
|
||||
inline bool operator==(const StringRef &lhs, const char *rhs) {
|
||||
return lhs.size() == strlen(rhs) && std::equal(std::begin(lhs), std::end(lhs), rhs);
|
||||
}
|
||||
|
||||
inline bool operator==(const char *lhs, const StringRef &rhs) { return rhs == lhs; }
|
||||
|
||||
inline bool operator!=(const StringRef &lhs, const StringRef &rhs) { return !(lhs == rhs); }
|
||||
|
||||
inline bool operator!=(const StringRef &lhs, const std::string &rhs) { return !(lhs == rhs); }
|
||||
|
||||
inline bool operator!=(const std::string &lhs, const StringRef &rhs) { return !(rhs == lhs); }
|
||||
|
||||
inline bool operator!=(const StringRef &lhs, const char *rhs) { return !(lhs == rhs); }
|
||||
|
||||
inline bool operator!=(const char *lhs, const StringRef &rhs) { return !(rhs == lhs); }
|
||||
|
||||
inline bool operator<(const StringRef &lhs, const StringRef &rhs) {
|
||||
return std::lexicographical_compare(std::begin(lhs), std::end(lhs), std::begin(rhs), std::end(rhs));
|
||||
}
|
||||
|
||||
inline std::string &operator+=(std::string &lhs, const StringRef &rhs) {
|
||||
lhs.append(rhs.c_str(), rhs.size());
|
||||
return lhs;
|
||||
}
|
||||
|
||||
inline std::string operator+(const char *lhs, const StringRef &rhs) {
|
||||
auto str = std::string(lhs);
|
||||
str.append(rhs.c_str(), rhs.size());
|
||||
return str;
|
||||
}
|
||||
|
||||
inline std::string operator+(const StringRef &lhs, const char *rhs) {
|
||||
auto str = lhs.str();
|
||||
str.append(rhs);
|
||||
return str;
|
||||
}
|
||||
|
||||
#ifdef USE_JSON
|
||||
// NOLINTNEXTLINE(readability-identifier-naming)
|
||||
void convertToJson(const StringRef &src, JsonVariant dst);
|
||||
#endif // USE_JSON
|
||||
|
||||
} // namespace esphome
|
@ -20,6 +20,7 @@ from esphome.types import ConfigType, ConfigFragmentType
|
||||
from esphome.cpp_generator import add, get_variable
|
||||
from esphome.cpp_types import App
|
||||
from esphome.util import Registry, RegistryEntry
|
||||
from esphome.helpers import snake_case, sanitize
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@ -101,6 +102,10 @@ async def register_parented(var, value):
|
||||
async def setup_entity(var, config):
|
||||
"""Set up generic properties of an Entity"""
|
||||
add(var.set_name(config[CONF_NAME]))
|
||||
if not config[CONF_NAME]:
|
||||
add(var.set_object_id(sanitize(snake_case(CORE.friendly_name))))
|
||||
else:
|
||||
add(var.set_object_id(sanitize(snake_case(config[CONF_NAME]))))
|
||||
add(var.set_disabled_by_default(config[CONF_DISABLED_BY_DEFAULT]))
|
||||
if CONF_INTERNAL in config:
|
||||
add(var.set_internal(config[CONF_INTERNAL]))
|
||||
|
@ -7,6 +7,7 @@ from pathlib import Path
|
||||
from typing import Union
|
||||
import tempfile
|
||||
from urllib.parse import urlparse
|
||||
import re
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@ -334,3 +335,13 @@ def add_class_to_obj(value, cls):
|
||||
if type(value) is type_: # pylint: disable=unidiomatic-typecheck
|
||||
return add_class_to_obj(func(value), cls)
|
||||
raise
|
||||
|
||||
|
||||
def snake_case(value):
|
||||
"""Same behaviour as `helpers.cpp` method `str_snake_case`."""
|
||||
return value.replace(" ", "_").lower()
|
||||
|
||||
|
||||
def sanitize(value):
|
||||
"""Same behaviour as `helpers.cpp` method `str_sanitize`."""
|
||||
return re.sub("[^-_0-9a-zA-Z]", r"", value)
|
||||
|
@ -25,9 +25,9 @@ DOMAINS = {
|
||||
|
||||
|
||||
def sub(path, pattern, repl):
|
||||
with open(path, "r") as handle:
|
||||
with open(path) as handle:
|
||||
content = handle.read()
|
||||
content = re.sub(pattern, repl, content, flags=re.MULTILINE, count=1)
|
||||
content = re.sub(pattern, repl, content, flags=re.MULTILINE)
|
||||
with open(path, "w") as handle:
|
||||
handle.write(content)
|
||||
|
||||
@ -48,7 +48,7 @@ def main():
|
||||
out = ""
|
||||
for cls in sorted(classes):
|
||||
out += f'DEVICE_CLASS_{cls.upper()} = "{classes[cls]}"\n'
|
||||
sub("esphome/const.py", '(DEVICE_CLASS_\w+ = "\w*"\r?\n)+', out)
|
||||
sub("esphome/const.py", '(DEVICE_CLASS_\\w+ = "\\w*"\r?\n)+', out)
|
||||
|
||||
for domain in sorted(allowed):
|
||||
# replace imports
|
||||
@ -58,7 +58,7 @@ def main():
|
||||
|
||||
sub(
|
||||
f"esphome/components/{domain}/__init__.py",
|
||||
"( DEVICE_CLASS_\w+,\r?\n)+",
|
||||
"( DEVICE_CLASS_\\w+,\r?\n)+",
|
||||
out,
|
||||
)
|
||||
|
||||
|
@ -229,3 +229,37 @@ def test_file_compare(fixture_path, file1, file2, expected):
|
||||
actual = helpers.file_compare(path1, path2)
|
||||
|
||||
assert actual == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"text, expected",
|
||||
(
|
||||
("foo", "foo"),
|
||||
("foo bar", "foo_bar"),
|
||||
("foo Bar", "foo_bar"),
|
||||
("foo BAR", "foo_bar"),
|
||||
("foo.bar", "foo.bar"),
|
||||
("fooBAR", "foobar"),
|
||||
("Foo-bar_EEK", "foo-bar_eek"),
|
||||
(" foo", "__foo"),
|
||||
),
|
||||
)
|
||||
def test_snake_case(text, expected):
|
||||
actual = helpers.snake_case(text)
|
||||
|
||||
assert actual == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"text, expected",
|
||||
(
|
||||
("foo_bar", "foo_bar"),
|
||||
('!"§$%&/()=?foo_bar', "foo_bar"),
|
||||
('foo_!"§$%&/()=?bar', "foo_bar"),
|
||||
('foo_bar!"§$%&/()=?', "foo_bar"),
|
||||
),
|
||||
)
|
||||
def test_sanitize(text, expected):
|
||||
actual = helpers.sanitize(text)
|
||||
|
||||
assert actual == expected
|
||||
|
Loading…
Reference in New Issue
Block a user