mirror of
https://github.com/esphome/esphome.git
synced 2026-10-11 22:04:16 +00:00
Merge remote-tracking branch 'upstream/dev' into neutral-ble-client
# Conflicts: # esphome/components/ble_client/__init__.py
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
adalight:
|
||||
|
||||
light:
|
||||
- platform: neopixelbus
|
||||
id: adalight_light
|
||||
name: Neopixelbus Light
|
||||
method: esp8266_uart
|
||||
num_leds: 5
|
||||
pin: 2
|
||||
type: GRBW
|
||||
variant: SK6812
|
||||
effects:
|
||||
- adalight:
|
||||
@@ -0,0 +1,3 @@
|
||||
packages:
|
||||
uart_115200: !include ../../test_build_components/common/uart_115200/esp8266-ard.yaml
|
||||
adalight: !include common.yaml
|
||||
@@ -1,23 +0,0 @@
|
||||
sensor:
|
||||
- platform: adc
|
||||
pin: VDDHDIV5
|
||||
name: "VDDH Voltage"
|
||||
update_interval: 5sec
|
||||
filters:
|
||||
- multiply: 5
|
||||
- platform: adc
|
||||
pin: VDD
|
||||
name: "VDD Voltage"
|
||||
update_interval: 5sec
|
||||
- platform: adc
|
||||
pin: AIN0
|
||||
name: "AIN0 Voltage"
|
||||
update_interval: 5sec
|
||||
- platform: adc
|
||||
pin: P0.03
|
||||
name: "AIN1 Voltage"
|
||||
update_interval: 5sec
|
||||
- platform: adc
|
||||
name: "AIN2 Voltage"
|
||||
update_interval: 5sec
|
||||
pin: 4
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
# Config only: every LibreTiny chip compiles the same ADC code, covered by the
|
||||
# ln882x-ard build; this checks the BK72xx analog pin names.
|
||||
sensor:
|
||||
- id: adc_my_sensor
|
||||
platform: adc
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
# Config only: the P4 compiles the same ADC code as the esp32-s3-idf build
|
||||
# (curve fitting calibration), only the pin table differs.
|
||||
sensor:
|
||||
- id: adc_my_sensor
|
||||
platform: adc
|
||||
+3
@@ -1,3 +1,6 @@
|
||||
# Config only: the S2 shares the C2's line fitting path (no default_vref) and
|
||||
# the original ESP32's ADC init (no clk_src); both are compiled by those
|
||||
# builds, only the S2 pin table differs.
|
||||
sensor:
|
||||
- id: adc_my_sensor
|
||||
platform: adc
|
||||
@@ -1,6 +1,7 @@
|
||||
sensor:
|
||||
- platform: ags10
|
||||
id: ags10_1
|
||||
i2c_id: i2c_bus
|
||||
tvoc:
|
||||
name: AGS10 TVOC
|
||||
update_interval: 60s
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
from pathlib import Path
|
||||
|
||||
import esphome.codegen as cg
|
||||
from esphome.const import CONF_ESPHOME, CONF_INCLUDES
|
||||
from esphome.core import CORE
|
||||
from tests.testing_helpers import ComponentManifestOverride
|
||||
|
||||
TESTS_DIR = Path(__file__).parent
|
||||
|
||||
|
||||
def override_manifest(manifest: ComponentManifestOverride) -> None:
|
||||
# USE_API compiles every api source, so emit what they need. No socket
|
||||
@@ -8,6 +14,20 @@ def override_manifest(manifest: ComponentManifestOverride) -> None:
|
||||
async def to_code_testing(config):
|
||||
cg.add_define("USE_API")
|
||||
cg.add_define("USE_API_PLAINTEXT")
|
||||
# Linked wizard inputs only exist next to homeassistant entities, which need this
|
||||
cg.add_define("USE_API_HOMEASSISTANT_STATES")
|
||||
# test_wizard.cpp supplies the tables that codegen emits for a real build;
|
||||
# it is only compiled when api's own tests are, not when api is a dependency
|
||||
if any(Path(p) == TESTS_DIR for p in CORE.config[CONF_ESPHOME][CONF_INCLUDES]):
|
||||
for define in (
|
||||
"USE_API_WIZARD",
|
||||
"USE_API_WIZARD_INPUTS",
|
||||
"USE_API_WIZARD_LINKED_INPUTS",
|
||||
"USE_API_WIZARD_STANDALONE_INPUTS",
|
||||
):
|
||||
cg.add_define(define)
|
||||
cg.add_define("API_WIZARD_DATA_SIZE", 200)
|
||||
cg.add_define("API_WIZARD_INPUT_COUNT", 2)
|
||||
cg.add_define("API_MAX_SEND_QUEUE", 8)
|
||||
cg.add_define("MAX_API_CONNECTIONS", 1)
|
||||
cg.add_define("USE_SOCKET_IMPL_BSD_SOCKETS")
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
api:
|
||||
homeassistant_services: true
|
||||
wizard:
|
||||
pages:
|
||||
- title: Features
|
||||
description: Choose which features to enable
|
||||
entities:
|
||||
- id: feature_enable_switch
|
||||
description: "[%key:component::example::feature::enable_switch%]"
|
||||
- id: guest_mode_switch
|
||||
description: Guest Mode
|
||||
- id: plain_switch
|
||||
- title: Sources
|
||||
inputs:
|
||||
- entity: outdoor_temp
|
||||
description: Outdoor temperature
|
||||
target:
|
||||
entity:
|
||||
- integration: met
|
||||
domain: sensor
|
||||
device_class: [temperature, humidity]
|
||||
supported_features: weather.WeatherEntityFeature.FORECAST_DAILY
|
||||
- domain: [sensor, number]
|
||||
- entity: default_temp
|
||||
- entity: door_open
|
||||
- entity: house_mode
|
||||
- entity: target_temp
|
||||
- entity: ha_light_switch
|
||||
target:
|
||||
entity:
|
||||
- domain: light
|
||||
- entity: ha_text
|
||||
- entity: ha_select
|
||||
target:
|
||||
entity:
|
||||
- domain: input_select
|
||||
- entity: ha_button
|
||||
- id: weather_input
|
||||
description: Weather source
|
||||
target:
|
||||
entity:
|
||||
- domain: weather
|
||||
- id: unset_input
|
||||
|
||||
switch:
|
||||
- platform: template
|
||||
id: feature_enable_switch
|
||||
name: Feature Enable
|
||||
optimistic: true
|
||||
- platform: template
|
||||
id: guest_mode_switch
|
||||
name: Guest Mode
|
||||
optimistic: true
|
||||
- platform: template
|
||||
id: plain_switch
|
||||
name: Plain Switch
|
||||
optimistic: true
|
||||
- platform: homeassistant
|
||||
id: ha_light_switch
|
||||
|
||||
sensor:
|
||||
- platform: homeassistant
|
||||
id: outdoor_temp
|
||||
- platform: homeassistant
|
||||
id: default_temp
|
||||
- platform: homeassistant
|
||||
id: fixed_temp
|
||||
entity_id: sensor.fixed_temperature
|
||||
|
||||
binary_sensor:
|
||||
- platform: homeassistant
|
||||
id: door_open
|
||||
|
||||
text_sensor:
|
||||
- platform: homeassistant
|
||||
id: house_mode
|
||||
|
||||
number:
|
||||
- platform: homeassistant
|
||||
id: target_temp
|
||||
|
||||
text:
|
||||
- platform: homeassistant
|
||||
id: ha_text
|
||||
|
||||
select:
|
||||
- platform: homeassistant
|
||||
id: ha_select
|
||||
|
||||
button:
|
||||
- platform: homeassistant
|
||||
id: ha_button
|
||||
- platform: homeassistant
|
||||
id: fixed_button
|
||||
entity_id: button.restart
|
||||
|
||||
interval:
|
||||
- interval: 1h
|
||||
then:
|
||||
- if:
|
||||
condition:
|
||||
api.wizard.input_is_set: weather_input
|
||||
then:
|
||||
- homeassistant.action:
|
||||
action: weather.get_forecasts
|
||||
data:
|
||||
type: daily
|
||||
entity_id: !lambda 'return id(weather_input).entity_id().c_str();'
|
||||
@@ -0,0 +1,6 @@
|
||||
packages:
|
||||
wizard: !include common-wizard.yaml
|
||||
|
||||
wifi:
|
||||
ssid: MySSID
|
||||
password: password1
|
||||
@@ -0,0 +1,6 @@
|
||||
packages:
|
||||
wizard: !include common-wizard.yaml
|
||||
|
||||
wifi:
|
||||
ssid: MySSID
|
||||
password: password1
|
||||
@@ -0,0 +1,4 @@
|
||||
packages:
|
||||
wizard: !include common-wizard.yaml
|
||||
|
||||
network:
|
||||
@@ -0,0 +1,88 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "esphome/components/api/api_buffer.h"
|
||||
#include "esphome/components/api/proto.h"
|
||||
|
||||
namespace esphome::api::testing {
|
||||
|
||||
// Sub-message whose body is raw bytes, so the body size is set directly by the test.
|
||||
struct BlobMessage {
|
||||
const uint8_t *data;
|
||||
uint32_t len;
|
||||
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM) {
|
||||
const auto &msg = *static_cast<const BlobMessage *>(self);
|
||||
// An empty vector's data() may be null, and memcpy needs a valid source even for zero bytes
|
||||
if (msg.len == 0)
|
||||
return pos;
|
||||
return ProtoEncode::encode_raw(pos PROTO_ENCODE_DEBUG_ARG, msg.data, msg.len);
|
||||
}
|
||||
static uint32_t calc_size_msg(const void *self) { return static_cast<const BlobMessage *>(self)->len; }
|
||||
};
|
||||
|
||||
static void append_varint(std::vector<uint8_t> &out, uint32_t value) {
|
||||
while (value > 0x7F) {
|
||||
out.push_back(static_cast<uint8_t>(value | 0x80));
|
||||
value >>= 7;
|
||||
}
|
||||
out.push_back(static_cast<uint8_t>(value));
|
||||
}
|
||||
|
||||
static std::vector<uint8_t> make_body(uint32_t len) {
|
||||
std::vector<uint8_t> body(len);
|
||||
for (uint32_t i = 0; i < len; i++)
|
||||
body[i] = static_cast<uint8_t>(i * 7 + 1);
|
||||
return body;
|
||||
}
|
||||
|
||||
static std::vector<uint8_t> expected_field(uint32_t field_id, const std::vector<uint8_t> &body) {
|
||||
std::vector<uint8_t> out;
|
||||
append_varint(out, (field_id << 3) | 2);
|
||||
append_varint(out, body.size());
|
||||
out.insert(out.end(), body.begin(), body.end());
|
||||
return out;
|
||||
}
|
||||
|
||||
// Encodes into a buffer of exactly the expected size, so any overrun trips ASan or the debug bounds check.
|
||||
template<bool OPTIONAL> static void verify(uint32_t field_id, uint32_t body_len) {
|
||||
std::vector<uint8_t> body = make_body(body_len);
|
||||
std::vector<uint8_t> expected = expected_field(field_id, body);
|
||||
if (OPTIONAL && body_len == 0)
|
||||
expected.clear();
|
||||
BlobMessage msg{body.data(), body_len};
|
||||
|
||||
APIBuffer buf;
|
||||
ASSERT_TRUE(buf.resize(expected.empty() ? 1 : expected.size()));
|
||||
uint8_t *pos = buf.data();
|
||||
#ifdef ESPHOME_DEBUG_API
|
||||
uint8_t *proto_debug_end_ = buf.data() + buf.size();
|
||||
#endif
|
||||
uint8_t *end;
|
||||
if constexpr (OPTIONAL) {
|
||||
end = ProtoEncode::encode_optional_sub_message(pos PROTO_ENCODE_DEBUG_ARG, field_id, msg);
|
||||
} else {
|
||||
end = ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, field_id, msg);
|
||||
}
|
||||
|
||||
ASSERT_EQ(static_cast<size_t>(end - buf.data()), expected.size()) << "field " << field_id << " body " << body_len;
|
||||
EXPECT_EQ(std::vector<uint8_t>(buf.data(), end), expected) << "field " << field_id << " body " << body_len;
|
||||
}
|
||||
|
||||
TEST(ProtoSubMessage, OneByteTag) { verify<false>(4, 10); }
|
||||
TEST(ProtoSubMessage, TwoByteTag) { verify<false>(20, 10); }
|
||||
TEST(ProtoSubMessage, EmptyBody) { verify<false>(20, 0); }
|
||||
TEST(ProtoSubMessage, LongestOneByteLength) { verify<false>(20, 127); }
|
||||
// The length outgrows its reserved byte, so the body is moved forward
|
||||
TEST(ProtoSubMessage, TwoByteLength) {
|
||||
verify<false>(20, 128);
|
||||
verify<false>(25, 200);
|
||||
}
|
||||
TEST(ProtoSubMessage, ThreeByteLength) { verify<false>(4, 20000); }
|
||||
|
||||
TEST(ProtoOptionalSubMessage, EmptyIsSkipped) { verify<true>(22, 0); }
|
||||
TEST(ProtoOptionalSubMessage, OneByteTag) { verify<true>(1, 10); }
|
||||
TEST(ProtoOptionalSubMessage, TwoByteTagAndLength) { verify<true>(22, 200); }
|
||||
|
||||
} // namespace esphome::api::testing
|
||||
@@ -0,0 +1,148 @@
|
||||
#ifdef USE_HOST
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "esphome/components/api/api_buffer.h"
|
||||
#include "esphome/components/api/api_pb2.h"
|
||||
#include "esphome/components/api/api_wizard.h"
|
||||
#include "esphome/components/api/proto.h"
|
||||
|
||||
namespace esphome::api {
|
||||
|
||||
// RAM buffers of the inputs, as codegen defines them
|
||||
static char *wizard_input_weather() {
|
||||
static char buffer[WIZARD_ENTITY_ID_BUFFER_SIZE] = "sensor.default";
|
||||
return buffer;
|
||||
}
|
||||
static char *wizard_input_other() {
|
||||
static char buffer[WIZARD_ENTITY_ID_BUFFER_SIZE] = "";
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static constexpr uint32_t WEATHER_KEY = 0x0a0b0c0d;
|
||||
static constexpr uint32_t OTHER_KEY = 0x11223344;
|
||||
|
||||
// The same shapes the generated code emits. The data is 200 bytes (API_WIZARD_DATA_SIZE), so its length takes two
|
||||
// bytes as a varint.
|
||||
const uint8_t API_WIZARD_DATA[API_WIZARD_DATA_SIZE] = {
|
||||
0x03, 0x0a, 0x11, 0x18, 0x1f, 0x26, 0x2d, 0x34, 0x3b, 0x42, 0x49, 0x50, 0x57, 0x5e, 0x65, 0x6c, 0x73, 0x7a, 0x81,
|
||||
0x88, 0x8f, 0x96, 0x9d, 0xa4, 0xab, 0xb2, 0xb9, 0xc0, 0xc7, 0xce, 0xd5, 0xdc, 0xe3, 0xea, 0xf1, 0xf8, 0xff, 0x06,
|
||||
0x0d, 0x14, 0x1b, 0x22, 0x29, 0x30, 0x37, 0x3e, 0x45, 0x4c, 0x53, 0x5a, 0x61, 0x68, 0x6f, 0x76, 0x7d, 0x84, 0x8b,
|
||||
0x92, 0x99, 0xa0, 0xa7, 0xae, 0xb5, 0xbc, 0xc3, 0xca, 0xd1, 0xd8, 0xdf, 0xe6, 0xed, 0xf4, 0xfb, 0x02, 0x09, 0x10,
|
||||
0x17, 0x1e, 0x25, 0x2c, 0x33, 0x3a, 0x41, 0x48, 0x4f, 0x56, 0x5d, 0x64, 0x6b, 0x72, 0x79, 0x80, 0x87, 0x8e, 0x95,
|
||||
0x9c, 0xa3, 0xaa, 0xb1, 0xb8, 0xbf, 0xc6, 0xcd, 0xd4, 0xdb, 0xe2, 0xe9, 0xf0, 0xf7, 0xfe, 0x05, 0x0c, 0x13, 0x1a,
|
||||
0x21, 0x28, 0x2f, 0x36, 0x3d, 0x44, 0x4b, 0x52, 0x59, 0x60, 0x67, 0x6e, 0x75, 0x7c, 0x83, 0x8a, 0x91, 0x98, 0x9f,
|
||||
0xa6, 0xad, 0xb4, 0xbb, 0xc2, 0xc9, 0xd0, 0xd7, 0xde, 0xe5, 0xec, 0xf3, 0xfa, 0x01, 0x08, 0x0f, 0x16, 0x1d, 0x24,
|
||||
0x2b, 0x32, 0x39, 0x40, 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x7f, 0x86, 0x8d, 0x94, 0x9b, 0xa2, 0xa9,
|
||||
0xb0, 0xb7, 0xbe, 0xc5, 0xcc, 0xd3, 0xda, 0xe1, 0xe8, 0xef, 0xf6, 0xfd, 0x04, 0x0b, 0x12, 0x19, 0x20, 0x27, 0x2e,
|
||||
0x35, 0x3c, 0x43, 0x4a, 0x51, 0x58, 0x5f, 0x66, 0x6d, 0x74};
|
||||
const WizardInputEntry API_WIZARD_INPUTS[API_WIZARD_INPUT_COUNT] = {
|
||||
{WEATHER_KEY, wizard_input_weather()},
|
||||
{OTHER_KEY, wizard_input_other()},
|
||||
};
|
||||
|
||||
using Bytes = std::vector<uint8_t>;
|
||||
|
||||
static Bytes encode(const ProtoMessage &msg, uint32_t (*calc)(const void *), ProtoEncodeFn enc) {
|
||||
APIBuffer buffer;
|
||||
uint32_t size = calc(&msg);
|
||||
EXPECT_TRUE(buffer.resize(size));
|
||||
#ifdef ESPHOME_DEBUG_API
|
||||
uint8_t *proto_debug_end_ = buffer.data() + buffer.size();
|
||||
#endif
|
||||
uint8_t *end = enc(&msg, buffer.data() PROTO_ENCODE_DEBUG_ARG);
|
||||
EXPECT_EQ(static_cast<size_t>(end - buffer.data()), size);
|
||||
return Bytes(buffer.data(), buffer.data() + size);
|
||||
}
|
||||
|
||||
TEST(DeviceWizard, ResponseSendsTheDataUnchanged) {
|
||||
DeviceWizardResponse resp;
|
||||
resp.data = API_WIZARD_DATA;
|
||||
resp.data_len = API_WIZARD_DATA_SIZE;
|
||||
|
||||
// Field 1, length delimited, then the 200 byte length as a two byte varint, then the data
|
||||
Bytes expected{0x0a, 0xc8, 0x01};
|
||||
expected.insert(expected.end(), API_WIZARD_DATA, API_WIZARD_DATA + API_WIZARD_DATA_SIZE);
|
||||
|
||||
EXPECT_EQ(encode(resp, &DeviceWizardResponse::calc_size_msg, &DeviceWizardResponse::encode_msg), expected);
|
||||
}
|
||||
|
||||
TEST(DeviceWizard, ShortDataHasAOneByteLength) {
|
||||
DeviceWizardResponse resp;
|
||||
resp.data = API_WIZARD_DATA;
|
||||
resp.data_len = 3;
|
||||
|
||||
Bytes expected{0x0a, 0x03, API_WIZARD_DATA[0], API_WIZARD_DATA[1], API_WIZARD_DATA[2]};
|
||||
EXPECT_EQ(encode(resp, &DeviceWizardResponse::calc_size_msg, &DeviceWizardResponse::encode_msg), expected);
|
||||
}
|
||||
|
||||
TEST(DeviceWizard, NoDataEncodesNothing) {
|
||||
DeviceWizardResponse resp;
|
||||
EXPECT_EQ(resp.calculate_size(), 0u);
|
||||
EXPECT_TRUE(encode(resp, &DeviceWizardResponse::calc_size_msg, &DeviceWizardResponse::encode_msg).empty());
|
||||
}
|
||||
|
||||
TEST(DeviceWizard, CapabilitiesAnnounceTheWizard) {
|
||||
DeviceCapabilitiesResponse resp;
|
||||
EXPECT_TRUE(
|
||||
encode(resp, &DeviceCapabilitiesResponse::calc_size_msg, &DeviceCapabilitiesResponse::encode_msg).empty());
|
||||
resp.wizard.configured = true;
|
||||
// Field 5 (the wizard), length delimited, holding field 1 (configured) set to 1
|
||||
EXPECT_EQ(encode(resp, &DeviceCapabilitiesResponse::calc_size_msg, &DeviceCapabilitiesResponse::encode_msg),
|
||||
(Bytes{0x2a, 0x02, 0x08, 0x01}));
|
||||
}
|
||||
|
||||
// A request for the input with the given key and entity id
|
||||
static const char *set_input(uint32_t key, const char *entity_id) {
|
||||
WizardInputSetRequest request;
|
||||
request.key = key;
|
||||
request.entity_id = StringRef(entity_id);
|
||||
return wizard_set_input(request);
|
||||
}
|
||||
|
||||
TEST(DeviceWizard, SetInputStoresTheEntityIdInTheBuffer) {
|
||||
EXPECT_EQ(set_input(OTHER_KEY, "sensor.outdoor"), wizard_input_other());
|
||||
EXPECT_STREQ(wizard_input_other(), "sensor.outdoor");
|
||||
// A shorter id replaces a longer one completely
|
||||
EXPECT_EQ(set_input(OTHER_KEY, "light.a"), wizard_input_other());
|
||||
EXPECT_STREQ(wizard_input_other(), "light.a");
|
||||
// The longest valid id fills the buffer
|
||||
std::string longest = "sensor." + std::string(WIZARD_ENTITY_ID_BUFFER_SIZE - 1 - 7, 'x');
|
||||
EXPECT_EQ(set_input(OTHER_KEY, longest.c_str()), wizard_input_other());
|
||||
EXPECT_EQ(std::string(wizard_input_other()), longest);
|
||||
}
|
||||
|
||||
TEST(DeviceWizard, SetInputFindsTheInputByItsKey) {
|
||||
EXPECT_EQ(set_input(WEATHER_KEY, "weather.home"), wizard_input_weather());
|
||||
EXPECT_STREQ(wizard_input_weather(), "weather.home");
|
||||
EXPECT_EQ(set_input(OTHER_KEY, "weather.away"), wizard_input_other());
|
||||
EXPECT_STREQ(wizard_input_weather(), "weather.home");
|
||||
}
|
||||
|
||||
TEST(DeviceWizard, SetInputIgnoresWhatIsNotAnEntityId) {
|
||||
std::string before = wizard_input_weather();
|
||||
EXPECT_EQ(set_input(WEATHER_KEY, ""), nullptr);
|
||||
EXPECT_EQ(set_input(WEATHER_KEY, "nodot"), nullptr);
|
||||
std::string too_long = "sensor." + std::string(WIZARD_ENTITY_ID_BUFFER_SIZE, 'x');
|
||||
EXPECT_EQ(set_input(WEATHER_KEY, too_long.c_str()), nullptr);
|
||||
EXPECT_EQ(set_input(0xdeadbeef, "sensor.a"), nullptr);
|
||||
EXPECT_EQ(std::string(wizard_input_weather()), before);
|
||||
}
|
||||
|
||||
TEST(DeviceWizard, StandaloneInputReadsTheBufferTheWizardWrites) {
|
||||
strcpy(wizard_input_other(), "");
|
||||
WizardInput input(wizard_input_other());
|
||||
EXPECT_FALSE(input.has_entity_id());
|
||||
EXPECT_TRUE(input.entity_id().empty());
|
||||
|
||||
ASSERT_EQ(set_input(OTHER_KEY, "weather.home"), wizard_input_other());
|
||||
EXPECT_TRUE(input.has_entity_id());
|
||||
EXPECT_EQ(input.entity_id(), "weather.home");
|
||||
}
|
||||
|
||||
} // namespace esphome::api
|
||||
#endif // USE_HOST
|
||||
@@ -0,0 +1,6 @@
|
||||
media_source:
|
||||
- platform: audio_http
|
||||
id: audio_http_ca_source
|
||||
ca_certificate_path: $component_dir/test_ca.pem
|
||||
|
||||
<<: !include common.yaml
|
||||
@@ -0,0 +1,13 @@
|
||||
# http_request requires a network component; audio_http's common.yaml declares none.
|
||||
wifi:
|
||||
ssid: MySSID
|
||||
password: password1
|
||||
|
||||
http_request:
|
||||
ca_certificate_path: $component_dir/test_ca.pem
|
||||
|
||||
media_source:
|
||||
- platform: audio_http
|
||||
id: audio_http_inherit_ca_source
|
||||
|
||||
<<: !include common.yaml
|
||||
@@ -0,0 +1,10 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIBkTCB+wIJAKHBfpegPjMCMA0GCSqGSIb3DQEBCwUAMBExDzANBgNVBAMMBnVu
|
||||
dXNlZDAeFw0yNDAxMDEwMDAwMDBaFw0yNTAxMDEwMDAwMDBaMBExDzANBgNVBAMM
|
||||
BnVudXNlZDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQC5mMUB1hOgLmlnXtsvcGMP
|
||||
XkhAqZaR0dDPW5OS8VEopWLJCX9Y0cvNCqiDI8cnP8pP8XJGU1hGLvA5PJzWnWZz
|
||||
AgMBAAGjUzBRMB0GA1UdDgQWBBR5oQ9KqFeZOdBuAJrXxEP0dqzPtTAfBgNVHSME
|
||||
GDAWgBR5oQ9KqFeZOdBuAJrXxEP0dqzPtTAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
|
||||
SIb3DQEBCwUAA0EAKqZFf6+f8FPDbKyPCpssquojgn7fEXqr/I/yz0R5CowGdMms
|
||||
H3WH3aKP4lLSHdPTBtfIoJi3gEIZjFxp3S1TWw==
|
||||
-----END CERTIFICATE-----
|
||||
@@ -61,6 +61,7 @@ sensor:
|
||||
motion:
|
||||
- platform: bmi270
|
||||
id: bmi270_motion
|
||||
i2c_id: i2c_bus
|
||||
# Accelerometer full-scale range: 2G | 4G | 8G | 16G
|
||||
accelerometer_range: 4G
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifdef USE_HOST
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "esphome/components/bytebuffer/bytebuffer.h"
|
||||
|
||||
namespace esphome::bytebuffer {
|
||||
|
||||
// The expressions esp32_ble_server emits for typed constant values, and the bytes they produce.
|
||||
// Doubles are written as float literals, so they carry float precision.
|
||||
TEST(ByteBufferWrapValues, MatchesGeneratedConstants) {
|
||||
EXPECT_EQ(ByteBuffer::wrap(uint8_t(18), LITTLE).get_data(), (std::vector<uint8_t>{0x12}));
|
||||
EXPECT_EQ(ByteBuffer::wrap(uint16_t(18), LITTLE).get_data(), (std::vector<uint8_t>{0x12, 0x00}));
|
||||
EXPECT_EQ(ByteBuffer::wrap(uint16_t(4660), BIG).get_data(), (std::vector<uint8_t>{0x12, 0x34}));
|
||||
EXPECT_EQ(ByteBuffer::wrap(uint32_t(305419896), LITTLE).get_data(), (std::vector<uint8_t>{0x78, 0x56, 0x34, 0x12}));
|
||||
EXPECT_EQ(ByteBuffer::wrap(uint64_t(1311768467294899695ULL), BIG).get_data(),
|
||||
(std::vector<uint8_t>{0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef}));
|
||||
EXPECT_EQ(ByteBuffer::wrap(int8_t(-5), LITTLE).get_data(), (std::vector<uint8_t>{0xfb}));
|
||||
EXPECT_EQ(ByteBuffer::wrap(int16_t(-2), BIG).get_data(), (std::vector<uint8_t>{0xff, 0xfe}));
|
||||
EXPECT_EQ(ByteBuffer::wrap(int32_t(-2), LITTLE).get_data(), (std::vector<uint8_t>{0xfe, 0xff, 0xff, 0xff}));
|
||||
EXPECT_EQ(ByteBuffer::wrap(int64_t(-2), LITTLE).get_data(),
|
||||
(std::vector<uint8_t>{0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}));
|
||||
EXPECT_EQ(ByteBuffer::wrap(float(123.1f), BIG).get_data(), (std::vector<uint8_t>{0x42, 0xf6, 0x33, 0x33}));
|
||||
EXPECT_EQ(ByteBuffer::wrap(float(0.1f), LITTLE).get_data(), (std::vector<uint8_t>{0xcd, 0xcc, 0xcc, 0x3d}));
|
||||
EXPECT_EQ(ByteBuffer::wrap(double(0.1f), LITTLE).get_data(),
|
||||
(std::vector<uint8_t>{0x00, 0x00, 0x00, 0xa0, 0x99, 0x99, 0xb9, 0x3f}));
|
||||
EXPECT_EQ(ByteBuffer::wrap(double(2.5f), BIG).get_data(),
|
||||
(std::vector<uint8_t>{0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}));
|
||||
}
|
||||
|
||||
} // namespace esphome::bytebuffer
|
||||
#endif
|
||||
@@ -18,6 +18,7 @@ canbus:
|
||||
lambda: "return x[0] == 0x11;"
|
||||
then:
|
||||
logger.log: Truth
|
||||
- canbus.send: !lambda return x;
|
||||
- can_id: 0b00000000000000000000001000000
|
||||
can_id_mask: 0b11111000000000011111111000000
|
||||
use_extended_id: true
|
||||
@@ -59,6 +60,9 @@ button:
|
||||
data: [0, 1, 2]
|
||||
- canbus.send: "abc"
|
||||
- canbus.send: [0, 1, 2]
|
||||
# Identical on purpose: both sends share one constant payload
|
||||
- canbus.send: [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]
|
||||
- canbus.send: [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]
|
||||
- canbus.send: !lambda return {0, 1, 2};
|
||||
# Test canbus.send with lambda that references a component (function pointer)
|
||||
- canbus.send: !lambda |-
|
||||
|
||||
@@ -30,6 +30,8 @@ cc1101:
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGD("cc1101", "packet %s freq_offset %.0f Hz rssi %.1f dBm lqi %u", format_hex(x).c_str(), freq_offset, rssi, lqi);
|
||||
- cc1101.send_packet: !lambda |-
|
||||
return x;
|
||||
|
||||
button:
|
||||
- platform: template
|
||||
@@ -42,6 +44,8 @@ button:
|
||||
- cc1101.reset: transceiver
|
||||
- cc1101.send_packet:
|
||||
data: [0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef]
|
||||
- cc1101.send_packet: [0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef]
|
||||
- cc1101.send_packet: "ABCDEFGH"
|
||||
- cc1101.send_packet: !lambda |-
|
||||
return {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
|
||||
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
sensor:
|
||||
- platform: cm1106
|
||||
id: cm1106_sensor
|
||||
co2:
|
||||
name: CM1106 CO2 Value
|
||||
on_value:
|
||||
then:
|
||||
- cm1106.abc_enable: cm1106_sensor
|
||||
- cm1106.abc_disable: cm1106_sensor
|
||||
update_interval: 15s
|
||||
automatic_baseline_calibration:
|
||||
cycle: 7
|
||||
baseline: 420
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
sensor:
|
||||
- platform: template
|
||||
id: template_temperature1
|
||||
lambda: return 0.6;
|
||||
- platform: template
|
||||
id: template_temperature2
|
||||
lambda: return 0.8;
|
||||
- platform: combination
|
||||
type: linear
|
||||
name: Linearly combined temperatures
|
||||
sources:
|
||||
- source: template_temperature1
|
||||
coeffecient: 0.5
|
||||
- source: template_temperature2
|
||||
coefficient: 1.5
|
||||
@@ -0,0 +1,43 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vector>
|
||||
#include "esphome/core/automation.h"
|
||||
|
||||
namespace esphome::testing {
|
||||
|
||||
static const uint8_t PAYLOAD[] = {1, 2, 3};
|
||||
|
||||
static std::vector<uint8_t> repeat(int count) { return std::vector<uint8_t>(count, 7); }
|
||||
|
||||
TEST(TemplatableBytesTest, VisitStaticTable) {
|
||||
TemplatableBytes<> bytes;
|
||||
bytes.set_static(PAYLOAD, sizeof(PAYLOAD));
|
||||
std::vector<uint8_t> seen;
|
||||
bytes.visit([&](const uint8_t *data, size_t len) { seen.assign(data, data + len); });
|
||||
EXPECT_EQ(seen, (std::vector<uint8_t>{1, 2, 3}));
|
||||
}
|
||||
|
||||
TEST(TemplatableBytesTest, VisitWithLargerStackBuffer) {
|
||||
TemplatableBytes<> bytes;
|
||||
bytes.set_static(PAYLOAD, sizeof(PAYLOAD));
|
||||
size_t seen = 0;
|
||||
bytes.visit<256>([&](const uint8_t *, size_t len) { seen = len; });
|
||||
EXPECT_EQ(seen, sizeof(PAYLOAD));
|
||||
}
|
||||
|
||||
TEST(TemplatableBytesTest, VisitEmptyStaticTable) {
|
||||
TemplatableBytes<> bytes;
|
||||
bytes.set_static(nullptr, 0);
|
||||
size_t seen = 1;
|
||||
bytes.visit([&](const uint8_t *, size_t len) { seen = len; });
|
||||
EXPECT_EQ(seen, 0u);
|
||||
}
|
||||
|
||||
TEST(TemplatableBytesTest, VisitLambdaWithArgument) {
|
||||
TemplatableBytes<int> bytes;
|
||||
bytes.set_template(repeat);
|
||||
std::vector<uint8_t> seen;
|
||||
bytes.visit([&](const uint8_t *data, size_t len) { seen.assign(data, data + len); }, 4);
|
||||
EXPECT_EQ(seen, (std::vector<uint8_t>(4, 7)));
|
||||
}
|
||||
|
||||
} // namespace esphome::testing
|
||||
@@ -0,0 +1,10 @@
|
||||
datetime:
|
||||
- platform: template
|
||||
name: Datetime Trigger Test
|
||||
id: datetime_trigger_test
|
||||
type: datetime
|
||||
optimistic: true
|
||||
on_value:
|
||||
- logger.log:
|
||||
format: "New value %04d-%02d-%02d"
|
||||
args: [x.year, x.month, x.day_of_month]
|
||||
@@ -0,0 +1,3 @@
|
||||
packages:
|
||||
datetime: !include common.yaml
|
||||
triggers: !include common-triggers.yaml
|
||||
@@ -1,4 +1,5 @@
|
||||
<<: !include common.yaml
|
||||
packages:
|
||||
debug: !include common.yaml
|
||||
|
||||
sensor:
|
||||
- platform: debug
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<<: !include common.yaml
|
||||
packages:
|
||||
debug: !include common.yaml
|
||||
|
||||
esp32:
|
||||
cpu_frequency: 240MHz
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<<: !include common.yaml
|
||||
packages:
|
||||
debug: !include common.yaml
|
||||
|
||||
esp32:
|
||||
cpu_frequency: 240MHz
|
||||
|
||||
sensor:
|
||||
- platform: debug
|
||||
free:
|
||||
name: "Heap Free"
|
||||
psram:
|
||||
name: "Free PSRAM"
|
||||
fragmentation:
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
<<: !include common.yaml
|
||||
|
||||
sensor:
|
||||
- platform: debug
|
||||
fragmentation:
|
||||
name: "Heap Fragmentation"
|
||||
min_free:
|
||||
name: "Heap Min Free"
|
||||
@@ -1,4 +1,5 @@
|
||||
<<: !include common.yaml
|
||||
packages:
|
||||
debug: !include common.yaml
|
||||
|
||||
sensor:
|
||||
- platform: debug
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
<<: !include common.yaml
|
||||
packages:
|
||||
debug: !include common.yaml
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
<<: !include common.yaml
|
||||
|
||||
sensor:
|
||||
- platform: debug
|
||||
min_free:
|
||||
name: "Heap Min Free"
|
||||
@@ -1,4 +1,5 @@
|
||||
<<: !include common.yaml
|
||||
packages:
|
||||
debug: !include common.yaml
|
||||
|
||||
nrf52:
|
||||
reg0:
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
<<: !include common.yaml
|
||||
packages:
|
||||
debug: !include common.yaml
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<<: !include common.yaml
|
||||
@@ -1 +1,2 @@
|
||||
<<: !include common.yaml
|
||||
packages:
|
||||
debug: !include common.yaml
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
<<: !include common.yaml
|
||||
|
||||
sensor:
|
||||
- platform: debug
|
||||
min_free:
|
||||
name: "Heap Min Free"
|
||||
@@ -0,0 +1,4 @@
|
||||
# No pin anywhere in the config: the pin class methods deep_sleep calls must still link
|
||||
deep_sleep:
|
||||
run_duration: 10s
|
||||
sleep_duration: 50s
|
||||
@@ -1,5 +1,27 @@
|
||||
substitutions:
|
||||
wakeup_pin: GPIO4
|
||||
|
||||
<<: !include common.yaml
|
||||
<<: !include common-esp32-all.yaml
|
||||
packages:
|
||||
deep_sleep: !include common.yaml
|
||||
deep_sleep_esp32: !include common-esp32-all.yaml
|
||||
|
||||
power_supply:
|
||||
- id: power_supply_ds_esp32
|
||||
pin:
|
||||
number: GPIO5
|
||||
hold_state: true
|
||||
|
||||
output:
|
||||
- platform: gpio
|
||||
pin:
|
||||
number: GPIO22
|
||||
hold_state: true
|
||||
id: gpio_output_ds_esp32
|
||||
power_supply: power_supply_ds_esp32
|
||||
|
||||
switch:
|
||||
- platform: gpio
|
||||
pin:
|
||||
number: GPIO23
|
||||
hold_state: true
|
||||
id: gpio_switch_ds_esp32
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
display:
|
||||
- platform: ssd1306_i2c
|
||||
i2c_id: i2c_bus
|
||||
model: SSD1306_128X64
|
||||
reset_pin: ${reset_pin}
|
||||
id: display_page_change_display
|
||||
pages:
|
||||
- id: display_page_change_page1
|
||||
lambda: |-
|
||||
it.rectangle(0, 0, it.get_width(), it.get_height());
|
||||
- id: display_page_change_page2
|
||||
lambda: |-
|
||||
it.rectangle(0, 0, 10, 10);
|
||||
on_page_change:
|
||||
- then:
|
||||
lambda: 'ESP_LOGD("display", "any change, %p %p", from, to);'
|
||||
- from: display_page_change_page1
|
||||
then:
|
||||
lambda: 'ESP_LOGD("display", "left page 1, %p %p", from, to);'
|
||||
- to: display_page_change_page1
|
||||
then:
|
||||
lambda: 'ESP_LOGD("display", "entered page 1, %p %p", from, to);'
|
||||
- from: display_page_change_page1
|
||||
to: display_page_change_page2
|
||||
then:
|
||||
lambda: 'ESP_LOGD("display", "1 -> 2, %p %p", from, to);'
|
||||
@@ -0,0 +1,6 @@
|
||||
substitutions:
|
||||
reset_pin: GPIO15
|
||||
|
||||
packages:
|
||||
i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml
|
||||
display: !include common-page-change.yaml
|
||||
@@ -4,63 +4,47 @@ dlms_meter:
|
||||
decryption_key: "36C66639E48A8CA4D6BC8B282A793BBB"
|
||||
auth_key: "11223344556677889900AABBCCDDEEFF"
|
||||
skip_crc: true
|
||||
provider: "netznoe"
|
||||
custom_patterns:
|
||||
- "custom_pattern_1"
|
||||
- "custom_pattern_2"
|
||||
- pattern: "L, TSTR"
|
||||
name: "MeterID"
|
||||
default_obis: "0.0.96.1.0.255"
|
||||
- pattern: "F, TDTM"
|
||||
name: "DateTime"
|
||||
default_obis: "0.0.1.0.0.255"
|
||||
|
||||
sensor:
|
||||
# Old Schema tests
|
||||
- platform: dlms_meter
|
||||
voltage_l1:
|
||||
name: "Voltage L1"
|
||||
voltage_l2:
|
||||
name: "Voltage L2"
|
||||
voltage_l3:
|
||||
name: "Voltage L3"
|
||||
current_l1:
|
||||
name: "Current L1"
|
||||
current_l2:
|
||||
name: "Current L2"
|
||||
current_l3:
|
||||
name: "Current L3"
|
||||
active_power_plus:
|
||||
name: "Active power taken from grid"
|
||||
active_power_minus:
|
||||
name: "Active power put into grid"
|
||||
active_energy_plus:
|
||||
name: "Active energy taken from grid"
|
||||
active_energy_minus:
|
||||
name: "Active energy put into grid"
|
||||
reactive_energy_plus:
|
||||
name: "Reactive energy taken from grid"
|
||||
reactive_energy_minus:
|
||||
name: "Reactive energy put into grid"
|
||||
power_factor:
|
||||
name: "Power factor"
|
||||
obis_code: "1.0.32.7.0.255"
|
||||
name: "Voltage L1"
|
||||
unit_of_measurement: V
|
||||
accuracy_decimals: 1
|
||||
device_class: voltage
|
||||
state_class: measurement
|
||||
- platform: dlms_meter
|
||||
obis_code: "1.0.1.8.0.255"
|
||||
name: "Active energy taken from grid"
|
||||
unit_of_measurement: Wh
|
||||
device_class: energy
|
||||
state_class: total_increasing
|
||||
|
||||
# Dynamic Schema tests
|
||||
- platform: dlms_meter
|
||||
dlms_meter_id: dlms_meter_hub
|
||||
obis_code: "1-0:99.99.9"
|
||||
name: "Custom Dynamic Sensor"
|
||||
|
||||
text_sensor:
|
||||
# Old Schema tests
|
||||
- platform: dlms_meter
|
||||
timestamp:
|
||||
name: "timestamp"
|
||||
meternumber:
|
||||
name: "Meter Number"
|
||||
obis_code: "0.0.1.0.0.255"
|
||||
name: "timestamp"
|
||||
|
||||
# Dynamic Schema tests
|
||||
- platform: dlms_meter
|
||||
dlms_meter_id: dlms_meter_hub
|
||||
obis_code: "0-0:99.99.9"
|
||||
name: "Custom Dynamic Text Sensor"
|
||||
|
||||
binary_sensor:
|
||||
# Dynamic Schema tests (Binary sensors only use the dynamic schema)
|
||||
- platform: dlms_meter
|
||||
dlms_meter_id: dlms_meter_hub
|
||||
obis_code: "0-1:2.3.4"
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
# - DS2484: adjustable 1-Wire timing + RWPU pullup resistor selection
|
||||
ds248x:
|
||||
- id: ds2482_100
|
||||
i2c_id: i2c_bus
|
||||
address: 0x18
|
||||
type: ds2482-100
|
||||
active_pullup: true
|
||||
- id: ds2482_101
|
||||
i2c_id: i2c_bus
|
||||
address: 0x19
|
||||
type: ds2482-101
|
||||
active_pullup: true
|
||||
@@ -18,10 +20,12 @@ ds248x:
|
||||
bus_sleep: true
|
||||
hub_sleep: true
|
||||
- id: ds2482_800
|
||||
i2c_id: i2c_bus
|
||||
address: 0x1a
|
||||
type: ds2482-800
|
||||
active_pullup: true
|
||||
- id: ds2484_hub
|
||||
i2c_id: i2c_bus
|
||||
address: 0x1b
|
||||
type: ds2484
|
||||
active_pullup: true
|
||||
|
||||
@@ -196,6 +196,21 @@ TEST(EPaperSSD1677, RequestedFullUpdateAppliesWhenTheNextUpdateStarts) {
|
||||
EXPECT_FALSE(display.run_update_state()) << "request was applied more than once";
|
||||
}
|
||||
|
||||
/// The display reports updating from the start of an update until it is back to idle.
|
||||
TEST(EPaperSSD1677, IsUpdatingUntilBackToIdle) {
|
||||
TestableSSD1677 display(16, 2);
|
||||
RecordingDelegate bus(&display.dc);
|
||||
display.install(&bus, 5);
|
||||
|
||||
EXPECT_FALSE(display.is_updating());
|
||||
display.request_full_update();
|
||||
EXPECT_TRUE(display.run_update_state());
|
||||
EXPECT_TRUE(display.is_updating());
|
||||
|
||||
EXPECT_FALSE(display.run_update_state()) << "an update with nothing drawn should not push";
|
||||
EXPECT_FALSE(display.is_updating());
|
||||
}
|
||||
|
||||
/// Nothing a partial needs lives in controller RAM any more, so a partial push skips the reset
|
||||
/// altogether; a full one still gets the hardware pulse and the software reset.
|
||||
TEST(EPaperSSD1677, PartialPushSkipsTheResetAndAFullPushKeepsIt) {
|
||||
|
||||
@@ -8,6 +8,11 @@ esphome:
|
||||
on_boot:
|
||||
then:
|
||||
- epaper_spi.full_update_next: epaper_partial
|
||||
- if:
|
||||
condition:
|
||||
epaper_spi.is_updating: epaper_partial
|
||||
then:
|
||||
- component.update: epaper_partial
|
||||
|
||||
display:
|
||||
- platform: epaper_spi
|
||||
|
||||
@@ -77,6 +77,46 @@ esp32_ble_server:
|
||||
id: test_change_descriptor
|
||||
value:
|
||||
data: [0x01, 0x02, 0x03]
|
||||
# Identical constants, strings and typed numbers
|
||||
- ble_server.characteristic.set_value:
|
||||
id: test_change_characteristic
|
||||
value:
|
||||
data: [0xfc, 0xef, 0xfe, 0x86]
|
||||
- ble_server.characteristic.set_value:
|
||||
id: test_change_characteristic
|
||||
value: "Changed"
|
||||
- ble_server.characteristic.set_value:
|
||||
id: test_change_characteristic
|
||||
value:
|
||||
data: 4660
|
||||
type: uint16_t
|
||||
endianness: BIG
|
||||
- ble_server.characteristic.set_value:
|
||||
id: test_change_characteristic
|
||||
value:
|
||||
data: -2
|
||||
type: int32_t
|
||||
- ble_server.characteristic.set_value:
|
||||
id: test_change_characteristic
|
||||
value:
|
||||
data: 0.1
|
||||
type: double
|
||||
- ble_server.descriptor.set_value:
|
||||
id: test_change_descriptor
|
||||
value:
|
||||
data: 123.1
|
||||
type: float
|
||||
endianness: BIG
|
||||
- ble_server.descriptor.set_value:
|
||||
id: test_change_descriptor
|
||||
value: "Changed"
|
||||
# Lambdas that read the trigger argument
|
||||
- ble_server.characteristic.set_value:
|
||||
id: test_change_characteristic
|
||||
value: !lambda return x;
|
||||
- ble_server.descriptor.set_value:
|
||||
id: test_change_descriptor
|
||||
value: !lambda return x;
|
||||
|
||||
# Regression test for #17142: the set_value action used from a trigger that passes
|
||||
# its argument by reference (climate on_control supplies ClimateCall&) previously
|
||||
|
||||
@@ -36,6 +36,9 @@ espnow:
|
||||
data: [0x01, 0x02, 0x03, 0x04, 0x05]
|
||||
- espnow.broadcast:
|
||||
data: !lambda 'return {0x01, 0x02, 0x03, 0x04, 0x05};'
|
||||
- espnow.send:
|
||||
address: 11:22:33:44:55:66
|
||||
data: !lambda 'return std::vector<uint8_t>(data, data + size);'
|
||||
- espnow.peer.add:
|
||||
address: 11:22:33:44:55:66
|
||||
- espnow.peer.add:
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
ethernet:
|
||||
type: W5500
|
||||
spi_id: spi_bus
|
||||
cs_pin: 5
|
||||
interrupt_pin: 36
|
||||
reset_pin: 22
|
||||
clock_speed: 10Mhz
|
||||
manual_ip:
|
||||
static_ip: 192.168.178.56
|
||||
gateway: 192.168.178.1
|
||||
subnet: 255.255.255.0
|
||||
domain: .local
|
||||
mac_address: "02:AA:BB:CC:DD:01"
|
||||
on_connect:
|
||||
- logger.log: "Ethernet connected!"
|
||||
on_disconnect:
|
||||
- logger.log: "Ethernet disconnected!"
|
||||
@@ -1 +1,6 @@
|
||||
<<: !include common-ip101.yaml
|
||||
packages:
|
||||
ethernet: !include common-ip101.yaml
|
||||
|
||||
# IPv6 on the internal EMAC: compiles the IPv6 event handler and multicast filter
|
||||
network:
|
||||
enable_ipv6: true
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
network:
|
||||
enable_ipv6: true
|
||||
|
||||
ethernet:
|
||||
type: IP101
|
||||
mdc_pin: 23
|
||||
mdio_pin: 18
|
||||
clk:
|
||||
pin: 0
|
||||
mode: CLK_EXT_IN
|
||||
phy_addr: 1
|
||||
power_pin: 5
|
||||
@@ -1,39 +0,0 @@
|
||||
ethernet:
|
||||
id: eth
|
||||
type: W5500
|
||||
clk_pin: 19
|
||||
mosi_pin: 21
|
||||
miso_pin: 23
|
||||
cs_pin: 18
|
||||
interrupt_pin: 36
|
||||
reset_pin: 22
|
||||
enable_on_boot: false
|
||||
manual_ip:
|
||||
static_ip: 192.168.178.56
|
||||
gateway: 192.168.178.1
|
||||
subnet: 255.255.255.0
|
||||
mac_address: "02:AA:BB:CC:DD:01"
|
||||
interface: spi2
|
||||
|
||||
esphome:
|
||||
on_boot:
|
||||
priority: 200
|
||||
then:
|
||||
- if:
|
||||
condition:
|
||||
not:
|
||||
ethernet.enabled:
|
||||
then:
|
||||
- ethernet.enable:
|
||||
|
||||
button:
|
||||
- platform: template
|
||||
name: "Disable Ethernet"
|
||||
on_press:
|
||||
- ethernet.disable:
|
||||
|
||||
binary_sensor:
|
||||
- platform: template
|
||||
name: "Ethernet Connected"
|
||||
lambda: |-
|
||||
return id(eth).is_connected();
|
||||
@@ -1,3 +0,0 @@
|
||||
packages:
|
||||
spi: !include ../../test_build_components/common/spi/esp32-idf.yaml
|
||||
ethernet: !include common-w5500-spi-id.yaml
|
||||
@@ -1,15 +0,0 @@
|
||||
# W5500 next to wifi with PSRAM: compiles the input path that moves received frames to PSRAM
|
||||
packages:
|
||||
ethernet: !include common-w5500.yaml
|
||||
|
||||
psram:
|
||||
mode: quad
|
||||
|
||||
wifi:
|
||||
ssid: MySSID
|
||||
password: password1
|
||||
|
||||
network:
|
||||
priority:
|
||||
- ethernet
|
||||
- wifi
|
||||
@@ -1,20 +1,47 @@
|
||||
# W5500 on a shared SPI bus, started from an automation instead of on boot.
|
||||
# Covers the spi_id attach path and the enable/disable lifecycle in one build.
|
||||
packages:
|
||||
spi: !include ../../test_build_components/common/spi/esp32-idf.yaml
|
||||
|
||||
ethernet:
|
||||
id: eth
|
||||
type: W5500
|
||||
clk_pin: 19
|
||||
mosi_pin: 21
|
||||
miso_pin: 23
|
||||
cs_pin: 18
|
||||
spi_id: spi_bus
|
||||
cs_pin: 5
|
||||
interrupt_pin: 36
|
||||
reset_pin: 22
|
||||
clock_speed: 10Mhz
|
||||
enable_on_boot: false
|
||||
manual_ip:
|
||||
static_ip: 192.168.178.56
|
||||
gateway: 192.168.178.1
|
||||
subnet: 255.255.255.0
|
||||
domain: .local
|
||||
mac_address: "02:AA:BB:CC:DD:01"
|
||||
interface: spi2
|
||||
on_connect:
|
||||
- logger.log: "Ethernet connected!"
|
||||
on_disconnect:
|
||||
- logger.log: "Ethernet disconnected!"
|
||||
|
||||
esphome:
|
||||
on_boot:
|
||||
priority: 200
|
||||
then:
|
||||
- if:
|
||||
condition:
|
||||
not:
|
||||
ethernet.enabled:
|
||||
then:
|
||||
- ethernet.enable:
|
||||
|
||||
button:
|
||||
- platform: template
|
||||
name: "Disable Ethernet"
|
||||
on_press:
|
||||
- ethernet.disable:
|
||||
|
||||
binary_sensor:
|
||||
- platform: template
|
||||
name: "Ethernet Connected"
|
||||
lambda: |-
|
||||
return id(eth).is_connected();
|
||||
|
||||
@@ -1 +1,15 @@
|
||||
<<: !include common-w5500.yaml
|
||||
# W5500 next to wifi with PSRAM: compiles the input path that moves received frames to PSRAM
|
||||
packages:
|
||||
ethernet: !include common-w5500.yaml
|
||||
|
||||
psram:
|
||||
mode: quad
|
||||
|
||||
wifi:
|
||||
ssid: MySSID
|
||||
password: password1
|
||||
|
||||
network:
|
||||
priority:
|
||||
- ethernet
|
||||
- wifi
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
# Config only: a user supplied SPI interface on dedicated pins exercises the
|
||||
# interface option in validation.
|
||||
ethernet:
|
||||
type: W5500
|
||||
interface: spi3
|
||||
clk_pin: 19
|
||||
mosi_pin: 21
|
||||
miso_pin: 17
|
||||
cs_pin: 18
|
||||
interrupt_pin: 36
|
||||
reset_pin: 12
|
||||
clock_speed: 10Mhz
|
||||
@@ -6,4 +6,19 @@ substitutions:
|
||||
switch_pin_3: GPIO6
|
||||
switch_pin_4: GPIO7
|
||||
|
||||
<<: !include common.yaml
|
||||
packages:
|
||||
gpio: !include common.yaml
|
||||
|
||||
binary_sensor:
|
||||
- platform: gpio
|
||||
pin:
|
||||
number: GPIO8
|
||||
hold_state: true
|
||||
id: gpio_binary_sensor_esp32
|
||||
|
||||
output:
|
||||
- platform: gpio
|
||||
pin:
|
||||
number: GPIO9
|
||||
hold_state: true
|
||||
id: gpio_output_esp32
|
||||
|
||||
@@ -6,4 +6,26 @@ substitutions:
|
||||
switch_pin_3: GPIO16
|
||||
switch_pin_4: GPIO17
|
||||
|
||||
<<: !include common.yaml
|
||||
packages:
|
||||
gpio: !include common.yaml
|
||||
|
||||
binary_sensor:
|
||||
- platform: gpio
|
||||
pin:
|
||||
number: GPIO18
|
||||
hold_state: true
|
||||
id: gpio_binary_sensor_esp32
|
||||
|
||||
output:
|
||||
- platform: gpio
|
||||
pin:
|
||||
number: GPIO19
|
||||
hold_state: true
|
||||
id: gpio_output_esp32
|
||||
|
||||
switch:
|
||||
- platform: gpio
|
||||
pin:
|
||||
number: GPIO21
|
||||
hold_state: true
|
||||
id: gpio_switch_esp32
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
display:
|
||||
- platform: ssd1306_i2c
|
||||
i2c_id: i2c_bus
|
||||
id: graphical_display_menu_triggers_display
|
||||
model: SSD1306_128X64
|
||||
reset_pin: ${reset_pin}
|
||||
lambda: |-
|
||||
it.rectangle(0, 0, it.get_width(), it.get_height());
|
||||
|
||||
font:
|
||||
- file: "gfonts://Roboto"
|
||||
id: graphical_display_menu_triggers_font
|
||||
size: 20
|
||||
|
||||
graphical_display_menu:
|
||||
id: graphical_display_menu_triggers_menu
|
||||
display: graphical_display_menu_triggers_display
|
||||
font: graphical_display_menu_triggers_font
|
||||
on_redraw:
|
||||
then:
|
||||
lambda: 'ESP_LOGI("graphical_display_menu", "redraw, active: %d", it->is_active());'
|
||||
items:
|
||||
- type: label
|
||||
text: "Label"
|
||||
@@ -0,0 +1,6 @@
|
||||
substitutions:
|
||||
reset_pin: GPIO15
|
||||
|
||||
packages:
|
||||
i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml
|
||||
graphical_display_menu: !include common-triggers.yaml
|
||||
@@ -71,6 +71,8 @@ esphome:
|
||||
# encode_json_ receives const copies of non-const reference args.
|
||||
- http_request.post:
|
||||
url: https://esphome.io
|
||||
request_headers:
|
||||
X-Body-Length: !lambda 'return body.empty() ? "0" : "1";'
|
||||
json:
|
||||
status: "ok"
|
||||
# Same with json: lambda variant, exercises json_func_ path
|
||||
@@ -102,3 +104,23 @@ script:
|
||||
then:
|
||||
- http_request.get:
|
||||
url: "http://google.com"
|
||||
|
||||
- id: send_with_headers
|
||||
parameters:
|
||||
token: string
|
||||
then:
|
||||
- http_request.get:
|
||||
url: https://esphome.io
|
||||
request_headers:
|
||||
Accept: application/json
|
||||
X-Device: esphome
|
||||
- http_request.get:
|
||||
url: https://esphome.io/other
|
||||
request_headers:
|
||||
Accept: application/json
|
||||
X-Device: esphome
|
||||
- http_request.get:
|
||||
url: https://esphome.io
|
||||
request_headers:
|
||||
Accept: application/json
|
||||
X-Token-Set: !lambda 'return token.empty() ? "no" : "yes";'
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
wifi:
|
||||
ssid: MySSID
|
||||
password: password1
|
||||
|
||||
binary_sensor:
|
||||
- platform: gpio
|
||||
pin: 0
|
||||
id: improv_trigger_authorizer
|
||||
|
||||
improv_ble:
|
||||
authorizer: improv_trigger_authorizer
|
||||
on_start:
|
||||
- logger.log: Improv started
|
||||
on_provisioning:
|
||||
- logger.log: Provisioning
|
||||
on_provisioned:
|
||||
- logger.log: Provisioned
|
||||
on_stop:
|
||||
- logger.log: Improv stopped
|
||||
on_state:
|
||||
- lambda: ESP_LOGD("improv", "State %d error %d", (int) state, (int) error);
|
||||
@@ -1,8 +0,0 @@
|
||||
wifi:
|
||||
ssid: MySSID
|
||||
password: password1
|
||||
|
||||
logger:
|
||||
hardware_uart: USB_SERIAL_JTAG
|
||||
|
||||
improv_serial:
|
||||
@@ -1,3 +0,0 @@
|
||||
packages:
|
||||
uart: !include ../../test_build_components/common/uart/esp8266-ard.yaml
|
||||
improv_serial: !include common-uart-bus.yaml
|
||||
@@ -1 +0,0 @@
|
||||
<<: !include common-uart0.yaml
|
||||
@@ -1 +0,0 @@
|
||||
<<: !include common-uart0.yaml
|
||||
@@ -1 +0,0 @@
|
||||
<<: !include common-uart0.yaml
|
||||
@@ -1 +0,0 @@
|
||||
<<: !include common-uart0.yaml
|
||||
@@ -1 +0,0 @@
|
||||
<<: !include common-uart0.yaml
|
||||
@@ -1 +0,0 @@
|
||||
<<: !include common-uart0.yaml
|
||||
@@ -1 +1,2 @@
|
||||
<<: !include common-usb_cdc.yaml
|
||||
packages:
|
||||
improv_serial: !include common-usb_cdc.yaml
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<<: !include common-usb_cdc.yaml
|
||||
@@ -1 +0,0 @@
|
||||
<<: !include common-usb_serial_jtag.yaml
|
||||
@@ -1 +0,0 @@
|
||||
<<: !include common-usb_serial_jtag.yaml
|
||||
@@ -0,0 +1,2 @@
|
||||
packages:
|
||||
improv_serial: !include common.yaml
|
||||
@@ -0,0 +1,2 @@
|
||||
packages:
|
||||
improv_serial: !include common.yaml
|
||||
@@ -0,0 +1,2 @@
|
||||
packages:
|
||||
improv_serial: !include common.yaml
|
||||
@@ -0,0 +1,2 @@
|
||||
packages:
|
||||
improv_serial: !include common.yaml
|
||||
@@ -1,9 +0,0 @@
|
||||
substitutions:
|
||||
cs_pin: GPIO5
|
||||
gdo0_pin: GPIO4
|
||||
gdo2_pin: GPIO16
|
||||
|
||||
packages:
|
||||
common: !include common.yaml
|
||||
spi: !include ../../test_build_components/common/spi/esp8266-ard.yaml
|
||||
cc1101: !include common-cc1101.yaml
|
||||
@@ -1,7 +0,0 @@
|
||||
substitutions:
|
||||
tx_pin: GPIO4
|
||||
rx_pin: GPIO5
|
||||
|
||||
packages:
|
||||
common: !include common.yaml
|
||||
rx: !include common-rx.yaml
|
||||
@@ -1,7 +0,0 @@
|
||||
substitutions:
|
||||
tx_pin: GPIO4
|
||||
rx_pin: GPIO5
|
||||
|
||||
packages:
|
||||
common: !include common.yaml
|
||||
rx: !include common-rx.yaml
|
||||
@@ -1,7 +0,0 @@
|
||||
substitutions:
|
||||
tx_pin: GPIO4
|
||||
rx_pin: GPIO5
|
||||
|
||||
packages:
|
||||
common: !include common.yaml
|
||||
tx: !include common-tx.yaml
|
||||
@@ -1,7 +0,0 @@
|
||||
substitutions:
|
||||
tx_pin: GPIO4
|
||||
rx_pin: GPIO5
|
||||
|
||||
packages:
|
||||
common: !include common.yaml
|
||||
tx: !include common-tx.yaml
|
||||
@@ -1,7 +0,0 @@
|
||||
substitutions:
|
||||
tx_pin: GPIO4
|
||||
rx_pin: GPIO5
|
||||
|
||||
packages:
|
||||
common: !include common.yaml
|
||||
tx: !include common-tx.yaml
|
||||
@@ -32,6 +32,7 @@ esphome:
|
||||
- lambda: |-
|
||||
const auto &effects = id(test_monochromatic_light).get_effects();
|
||||
auto &same = id(test_monochromatic_light).get_effects();
|
||||
const auto copy = id(test_monochromatic_light).get_effects(); // the view is copyable
|
||||
uint32_t total = effects.size();
|
||||
for (auto *effect : effects) {
|
||||
ESP_LOGD("test", "Effect %s", effect->get_name().c_str());
|
||||
@@ -39,7 +40,7 @@ esphome:
|
||||
if (total > 0) {
|
||||
ESP_LOGD("test", "First %s", effects.at(0)->get_name().c_str());
|
||||
// Raw pointer iterators on purpose: external code binds std::find's result to `const auto *`
|
||||
auto *it = std::find(same.begin(), same.end(), effects[0]);
|
||||
auto *it = std::find(same.begin(), same.end(), copy[0]);
|
||||
ESP_LOGD("test", "Index %d", (int) (it - same.begin()));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "esphome/components/light/light_effect.h"
|
||||
#include "esphome/components/light/light_output.h"
|
||||
#include "esphome/components/light/light_state.h"
|
||||
|
||||
@@ -18,36 +17,8 @@ class BrightnessOutput : public LightOutput {
|
||||
void write_state(LightState *state) override {}
|
||||
};
|
||||
|
||||
class NoopEffect : public LightEffect {
|
||||
public:
|
||||
using LightEffect::LightEffect;
|
||||
void apply() override {}
|
||||
};
|
||||
|
||||
// start_effect_() is where the uint32_t index is narrowed to the stored uint16_t.
|
||||
class TestableLightState : public LightState {
|
||||
public:
|
||||
using LightState::LightState;
|
||||
using LightState::start_effect_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// add_effects() is public, so an external component can exceed the codegen cap on effect count;
|
||||
// an index the uint16_t can't hold must be ignored rather than wrap onto another effect.
|
||||
TEST(LightStateEffect, IndexAboveUint16IsIgnoredAndKeepsTheActiveEffect) {
|
||||
BrightnessOutput output;
|
||||
TestableLightState state(&output);
|
||||
NoopEffect effect("Noop");
|
||||
state.add_effects({&effect});
|
||||
|
||||
state.start_effect_(1);
|
||||
ASSERT_EQ(state.get_current_effect_index(), 1u);
|
||||
|
||||
state.start_effect_(0x10000u); // unchecked narrowing wraps this to 0, which stops the effect
|
||||
EXPECT_EQ(state.get_current_effect_index(), 1u);
|
||||
}
|
||||
|
||||
// get_gamma_correct() reads the gamma codegen stores after the lookup table, rounded to two decimals.
|
||||
TEST(LightStateGamma, ReadsTheGammaStoredWithTheTable) {
|
||||
static constexpr GammaTable TABLE{{}, 280};
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "esphome/components/logger/log_buffer.h"
|
||||
#include "esphome/components/logger/logger.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome::logger::testing {
|
||||
|
||||
ESPHOME_LOG_TAG(TEST_TAG, "test.tag");
|
||||
|
||||
TEST(LogTagTest, HeaderContainsTagAndLine) {
|
||||
char data[256];
|
||||
LogBuffer buf{data, sizeof(data)};
|
||||
buf.write_header(5, TEST_TAG, 42, nullptr);
|
||||
const std::string header(data, buf.pos);
|
||||
EXPECT_NE(header.find("[D][test.tag:042]"), std::string::npos) << header;
|
||||
}
|
||||
|
||||
TEST(LogTagTest, PerTagLevelLookupMatchesByContent) {
|
||||
std::map<const char *, uint8_t, CStrCompare> levels{{"api", 1}, {"sensor", 2}, {"wifi", 3}};
|
||||
// Copies, so a match must compare content rather than pointers
|
||||
char api[] = "api", sensor[] = "sensor", wifi[] = "wifi", missing[] = "switch";
|
||||
EXPECT_EQ(levels.find(FlashTag{api})->second, 1);
|
||||
EXPECT_EQ(levels.find(FlashTag{sensor})->second, 2);
|
||||
EXPECT_EQ(levels.find(FlashTag{wifi})->second, 3);
|
||||
EXPECT_EQ(levels.find(FlashTag{missing}), levels.end());
|
||||
}
|
||||
|
||||
} // namespace esphome::logger::testing
|
||||
@@ -1,5 +0,0 @@
|
||||
<<: !include common-default_uart.yaml
|
||||
|
||||
logger:
|
||||
id: logger_id
|
||||
task_log_buffer_size: 1024B # Set a custom buffer size
|
||||
@@ -1,5 +0,0 @@
|
||||
<<: !include common-default_uart.yaml
|
||||
|
||||
logger:
|
||||
id: logger_id
|
||||
task_log_buffer_size: 0
|
||||
@@ -1,2 +0,0 @@
|
||||
logger:
|
||||
hardware_uart: UART0
|
||||
@@ -1 +0,0 @@
|
||||
<<: !include common-usb_cdc.yaml
|
||||
@@ -1 +0,0 @@
|
||||
<<: !include common-usb_cdc.yaml
|
||||
@@ -1 +0,0 @@
|
||||
<<: !include common-usb_serial_jtag.yaml
|
||||
@@ -1 +0,0 @@
|
||||
<<: !include common-usb_serial_jtag.yaml
|
||||
@@ -1 +1,5 @@
|
||||
<<: !include common-default_uart.yaml
|
||||
|
||||
logger:
|
||||
id: logger_id
|
||||
task_log_buffer_size: 0
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user