mirror of
https://github.com/esphome/esphome.git
synced 2026-09-27 15:00:24 +00:00
Merge branch 'dev' into remove_posix_tz_parser
This commit is contained in:
@@ -7,10 +7,23 @@
|
||||
testing binaries that combine many components. By convention, this unique namespace is `esphome::component::testing`
|
||||
(where "component" is the component under test), for example: `esphome::uart::testing`.
|
||||
|
||||
### Platform components
|
||||
|
||||
For components that expose to a platform component, create a folder under your component test folder with the platform component name, e.g. `binary_sensor` and
|
||||
include the relevant `.cpp` and `.h` test files there.
|
||||
|
||||
### Override component code generation for testing
|
||||
|
||||
When generating code for testing, ESPHome won't invoke the component's `to_code` function, since most components do not
|
||||
need to generate configuration code for testing.
|
||||
|
||||
If you do need to generate code to for example configure compilation flags or add libraries,
|
||||
add the component name to the `CPP_TESTING_CODEGEN_COMPONENTS` allowlist in `script/cpp_unit_test.py`.
|
||||
|
||||
## Running component unit tests
|
||||
|
||||
(from the repository root)
|
||||
|
||||
```bash
|
||||
./script/cpp_unit_test.py component1 component2 ...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<<: !include common.yaml
|
||||
|
||||
wifi:
|
||||
ssid: MySSID
|
||||
password: password1
|
||||
@@ -0,0 +1,9 @@
|
||||
audio_file:
|
||||
- id: test_audio
|
||||
file:
|
||||
type: local
|
||||
path: $component_dir/test.wav
|
||||
|
||||
media_source:
|
||||
- platform: audio_file
|
||||
id: audio_file_source
|
||||
@@ -0,0 +1 @@
|
||||
<<: !include common.yaml
|
||||
Binary file not shown.
@@ -0,0 +1,4 @@
|
||||
ble_nus:
|
||||
type: uart
|
||||
tx_buffer_size: 160
|
||||
rx_buffer_size: 160
|
||||
@@ -0,0 +1 @@
|
||||
<<: !include common.yaml
|
||||
@@ -0,0 +1,19 @@
|
||||
sensor:
|
||||
- platform: dew_point
|
||||
name: Dew Point
|
||||
temperature: template_temperature
|
||||
humidity: template_humidity
|
||||
- platform: template
|
||||
id: template_humidity
|
||||
lambda: |-
|
||||
if (millis() > 10000) {
|
||||
return 0.6;
|
||||
}
|
||||
return 0.0;
|
||||
- platform: template
|
||||
id: template_temperature
|
||||
lambda: |-
|
||||
if (millis() > 10000) {
|
||||
return 42.0;
|
||||
}
|
||||
return 0.0;
|
||||
@@ -0,0 +1 @@
|
||||
<<: !include common.yaml
|
||||
@@ -0,0 +1 @@
|
||||
<<: !include common.yaml
|
||||
@@ -0,0 +1 @@
|
||||
<<: !include common.yaml
|
||||
@@ -1,3 +1,6 @@
|
||||
esp8266:
|
||||
enable_full_printf: false
|
||||
|
||||
logger:
|
||||
level: VERBOSE
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
external_components:
|
||||
- source: github://esphome/esphome@dev
|
||||
- id: my_ext
|
||||
source: github://esphome/esphome@dev
|
||||
refresh: 1d
|
||||
components: [bh1750]
|
||||
- source: ../../../esphome/components
|
||||
- id: my_local
|
||||
source: ../../../esphome/components
|
||||
components: [sntp]
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
# WARNING: Using !extend or !remove prevents automatic component grouping in CI, making builds slower.
|
||||
<<: !include common.yaml
|
||||
|
||||
external_components:
|
||||
- id: !remove my_local
|
||||
|
||||
@@ -27,3 +27,14 @@ globals:
|
||||
type: bool
|
||||
restore_value: false
|
||||
initial_value: "false"
|
||||
# Test restore_value with string "false" - should be converted to bool false
|
||||
- id: glob_no_restore_string_false
|
||||
type: int
|
||||
restore_value: "false"
|
||||
initial_value: "42"
|
||||
# Test restore_value with string "true" - should be converted to bool true
|
||||
- id: glob_restore_string_true
|
||||
type: int
|
||||
restore_value: "true"
|
||||
initial_value: "99"
|
||||
update_interval: 5s
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
substitutions:
|
||||
verify_ssl: "false"
|
||||
|
||||
<<: !include common.yaml
|
||||
|
||||
http_request:
|
||||
verify_ssl: false
|
||||
tls_buffer_size_rx: 16384
|
||||
tls_buffer_size_tx: 512
|
||||
|
||||
@@ -1,9 +1,19 @@
|
||||
esphome:
|
||||
on_boot:
|
||||
then:
|
||||
- sensor.integration.reset:
|
||||
id: integration_sensor
|
||||
- sensor.integration.set_value:
|
||||
id: integration_sensor
|
||||
value: 100.0
|
||||
|
||||
sensor:
|
||||
- platform: adc
|
||||
id: my_sensor
|
||||
pin: ${pin}
|
||||
attenuation: 12db
|
||||
- platform: integration
|
||||
id: integration_sensor
|
||||
sensor: my_sensor
|
||||
name: Integration Sensor
|
||||
time_unit: s
|
||||
|
||||
@@ -16,7 +16,7 @@ class MockUARTComponent : public uart::UARTComponent {
|
||||
MOCK_METHOD(bool, read_array, (uint8_t * data, size_t len), (override));
|
||||
MOCK_METHOD(bool, peek_byte, (uint8_t * data), (override));
|
||||
MOCK_METHOD(size_t, available, (), (override));
|
||||
MOCK_METHOD(void, flush, (), (override));
|
||||
MOCK_METHOD(uart::FlushResult, flush, (), (override));
|
||||
MOCK_METHOD(void, check_logger_conflict, (), (override));
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "esphome/components/logger/logger.h"
|
||||
|
||||
/*
|
||||
This special main.cpp replaces the default one.
|
||||
It will run all the Google Tests found in all compiled cpp files and then exit with the result
|
||||
@@ -18,6 +20,12 @@ void original_setup() {
|
||||
}
|
||||
|
||||
void setup() {
|
||||
// Log functions call global_logger->log_vprintf_() without a null check,
|
||||
// so we must set up a Logger before any test that triggers logging.
|
||||
static esphome::logger::Logger test_logger(0);
|
||||
test_logger.set_log_level(ESPHOME_LOG_LEVEL);
|
||||
test_logger.pre_setup();
|
||||
|
||||
::testing::InitGoogleTest();
|
||||
int exit_code = RUN_ALL_TESTS();
|
||||
exit(exit_code);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
modbus:
|
||||
id: mod_bus1
|
||||
flow_control_pin: ${flow_control_pin}
|
||||
send_wait_time: 500ms
|
||||
turnaround_time: 100ms
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
display:
|
||||
- id: !extend main_lcd
|
||||
tft_url: http://esphome.io/default35.tft
|
||||
tft_upload_http_timeout: 20s
|
||||
tft_upload_http_retries: 10
|
||||
@@ -0,0 +1,3 @@
|
||||
display:
|
||||
- id: !extend main_lcd
|
||||
tft_upload_watchdog_timeout: 30s
|
||||
@@ -1,7 +1,5 @@
|
||||
packages:
|
||||
uart: !include ../../test_build_components/common/uart/esp32-ard.yaml
|
||||
base: !include common.yaml
|
||||
|
||||
display:
|
||||
- id: !extend main_lcd
|
||||
tft_url: http://esphome.io/default35.tft
|
||||
tft_upload: !include common_tft_upload.yaml
|
||||
tft_upload_watchdog: !include common_tft_upload_watchdog.yaml
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
packages:
|
||||
uart: !include ../../test_build_components/common/uart/esp32-idf.yaml
|
||||
base: !include common.yaml
|
||||
|
||||
display:
|
||||
- id: !extend main_lcd
|
||||
tft_url: http://esphome.io/default35.tft
|
||||
tft_upload: !include common_tft_upload.yaml
|
||||
tft_upload_watchdog: !include common_tft_upload_watchdog.yaml
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
packages:
|
||||
uart: !include ../../test_build_components/common/uart/esp8266-ard.yaml
|
||||
base: !include common.yaml
|
||||
|
||||
display:
|
||||
- id: !extend main_lcd
|
||||
tft_url: http://esphome.io/default35.tft
|
||||
tft_upload: !include common_tft_upload.yaml
|
||||
|
||||
@@ -40,6 +40,10 @@ online_image:
|
||||
url: https://samples-files.com/samples/images/bmp/480-360-sample.bmp
|
||||
format: BMP
|
||||
type: BINARY
|
||||
- id: online_rgb_bmp_8bit
|
||||
url: https://samples-files.com/samples/images/bmp/480-360-sample.bmp
|
||||
format: BMP
|
||||
type: RGB
|
||||
- id: online_jpeg_image
|
||||
url: http://www.faqs.org/images/library.jpg
|
||||
format: JPEG
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
esp32:
|
||||
board: esp32-c6-devkitc-1
|
||||
framework:
|
||||
type: esp-idf
|
||||
log_level: DEBUG
|
||||
|
||||
network:
|
||||
enable_ipv6: true
|
||||
|
||||
@@ -13,3 +19,4 @@ openthread:
|
||||
force_dataset: true
|
||||
use_address: open-thread-test.local
|
||||
poll_period: 20sec
|
||||
output_power: 1dBm
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
zephyr_ble_server:
|
||||
|
||||
ota:
|
||||
- platform: zephyr_mcumgr
|
||||
transport:
|
||||
ble: true
|
||||
hardware_uart: CDC
|
||||
on_begin:
|
||||
then:
|
||||
- logger.log: "OTA start"
|
||||
on_progress:
|
||||
then:
|
||||
- logger.log:
|
||||
format: "OTA progress %0.1f%%"
|
||||
args: ["x"]
|
||||
on_end:
|
||||
then:
|
||||
- logger.log: "OTA end"
|
||||
on_error:
|
||||
then:
|
||||
- logger.log:
|
||||
format: "OTA update error %d"
|
||||
args: ["x"]
|
||||
on_state_change:
|
||||
then:
|
||||
lambda: >-
|
||||
ESP_LOGD("ota", "State %d", state);
|
||||
@@ -0,0 +1,77 @@
|
||||
#include "../common.h"
|
||||
|
||||
namespace esphome::packet_transport::testing {
|
||||
|
||||
TEST(PacketTransportBinarySensorTest, AddBinarySensor) {
|
||||
TestablePacketTransport transport;
|
||||
binary_sensor::BinarySensor bs;
|
||||
transport.add_binary_sensor("motion", &bs);
|
||||
ASSERT_EQ(transport.binary_sensors_.size(), 1u);
|
||||
EXPECT_STREQ(transport.binary_sensors_[0].id, "motion");
|
||||
EXPECT_EQ(transport.binary_sensors_[0].sensor, &bs);
|
||||
}
|
||||
|
||||
TEST(PacketTransportBinarySensorTest, AddRemoteBinarySensor) {
|
||||
TestablePacketTransport transport;
|
||||
binary_sensor::BinarySensor bs;
|
||||
transport.add_remote_binary_sensor("host1", "remote_motion", &bs);
|
||||
EXPECT_TRUE(transport.providers_.contains("host1"));
|
||||
EXPECT_EQ(transport.remote_binary_sensors_["host1"]["remote_motion"], &bs);
|
||||
}
|
||||
|
||||
TEST(PacketTransportBinarySensorTest, UnencryptedBinarySensorRoundTrip) {
|
||||
TestablePacketTransport encoder;
|
||||
encoder.init_for_test("sender");
|
||||
binary_sensor::BinarySensor local_bs;
|
||||
local_bs.state = true;
|
||||
encoder.add_binary_sensor("motion", &local_bs);
|
||||
|
||||
encoder.send_data_(true);
|
||||
ASSERT_EQ(encoder.sent_packets.size(), 1u);
|
||||
|
||||
TestablePacketTransport decoder;
|
||||
decoder.init_for_test("receiver");
|
||||
binary_sensor::BinarySensor remote_bs;
|
||||
decoder.add_remote_binary_sensor("sender", "motion", &remote_bs);
|
||||
|
||||
auto &packet = encoder.sent_packets[0];
|
||||
decoder.process_({packet.data(), packet.size()});
|
||||
EXPECT_TRUE(remote_bs.state);
|
||||
}
|
||||
|
||||
TEST(PacketTransportBinarySensorTest, MultipleSensorsRoundTrip) {
|
||||
TestablePacketTransport encoder;
|
||||
encoder.init_for_test("sender");
|
||||
|
||||
sensor::Sensor s1, s2;
|
||||
s1.state = 10.0f;
|
||||
s2.state = 20.0f;
|
||||
encoder.add_sensor("s1", &s1);
|
||||
encoder.add_sensor("s2", &s2);
|
||||
|
||||
binary_sensor::BinarySensor bs1;
|
||||
bs1.state = true;
|
||||
encoder.add_binary_sensor("bs1", &bs1);
|
||||
|
||||
encoder.send_data_(true);
|
||||
ASSERT_EQ(encoder.sent_packets.size(), 1u);
|
||||
|
||||
TestablePacketTransport decoder;
|
||||
decoder.init_for_test("receiver");
|
||||
sensor::Sensor rs1, rs2;
|
||||
binary_sensor::BinarySensor rbs1;
|
||||
rs1.state = -999.0f;
|
||||
rs2.state = -999.0f;
|
||||
decoder.add_remote_sensor("sender", "s1", &rs1);
|
||||
decoder.add_remote_sensor("sender", "s2", &rs2);
|
||||
decoder.add_remote_binary_sensor("sender", "bs1", &rbs1);
|
||||
|
||||
auto &packet = encoder.sent_packets[0];
|
||||
decoder.process_({packet.data(), packet.size()});
|
||||
|
||||
EXPECT_FLOAT_EQ(rs1.state, 10.0f);
|
||||
EXPECT_FLOAT_EQ(rs2.state, 20.0f);
|
||||
EXPECT_TRUE(rbs1.state);
|
||||
}
|
||||
|
||||
} // namespace esphome::packet_transport::testing
|
||||
@@ -0,0 +1,98 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
#include <gtest/gtest.h>
|
||||
#include "esphome/components/packet_transport/packet_transport.h"
|
||||
|
||||
namespace esphome::packet_transport::testing {
|
||||
|
||||
// Protocol constants mirrored from packet_transport.cpp for test packet construction.
|
||||
static constexpr uint16_t MAGIC_NUMBER = 0x4553;
|
||||
static constexpr uint16_t MAGIC_PING = 0x5048;
|
||||
|
||||
// Concrete testable implementation of PacketTransport.
|
||||
// Captures sent packets and exposes protected members for verification.
|
||||
//
|
||||
// Sensor round-trip tests require USE_SENSOR / USE_BINARY_SENSOR to be defined,
|
||||
// which happens when 'sensor' and 'binary_sensor' components are in the build.
|
||||
// Run with --all or include those components to enable the full test suite.
|
||||
class TestablePacketTransport : public PacketTransport {
|
||||
public:
|
||||
using PacketTransport::add_key_;
|
||||
using PacketTransport::data_;
|
||||
using PacketTransport::encryption_key_;
|
||||
using PacketTransport::flush_;
|
||||
using PacketTransport::header_;
|
||||
using PacketTransport::increment_code_;
|
||||
using PacketTransport::init_data_;
|
||||
using PacketTransport::is_encrypted_;
|
||||
using PacketTransport::is_provider_;
|
||||
using PacketTransport::name_;
|
||||
using PacketTransport::ping_key_;
|
||||
using PacketTransport::ping_keys_;
|
||||
using PacketTransport::ping_pong_enable_;
|
||||
using PacketTransport::ping_pong_recyle_time_;
|
||||
using PacketTransport::process_;
|
||||
using PacketTransport::providers_;
|
||||
using PacketTransport::rolling_code_;
|
||||
using PacketTransport::rolling_code_enable_;
|
||||
using PacketTransport::send_data_;
|
||||
using PacketTransport::updated_;
|
||||
#ifdef USE_SENSOR
|
||||
using PacketTransport::add_data_;
|
||||
using PacketTransport::remote_sensors_;
|
||||
using PacketTransport::sensors_;
|
||||
#endif
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
using PacketTransport::add_binary_data_;
|
||||
using PacketTransport::binary_sensors_;
|
||||
using PacketTransport::remote_binary_sensors_;
|
||||
#endif
|
||||
|
||||
// NOTE: std::vector is used here for test convenience. For production code,
|
||||
// consider using StaticVector or FixedVector from esphome/core/helpers.h instead.
|
||||
mutable std::vector<std::vector<uint8_t>> sent_packets;
|
||||
size_t max_packet_size{512};
|
||||
bool send_enabled{true};
|
||||
|
||||
void send_packet(const std::vector<uint8_t> &buf) const override { this->sent_packets.push_back(buf); }
|
||||
size_t get_max_packet_size() override { return this->max_packet_size; }
|
||||
bool should_send() override { return this->send_enabled; }
|
||||
|
||||
/// Build the packet header for testing without requiring App or global_preferences.
|
||||
void init_for_test(const char *name) {
|
||||
this->name_ = name;
|
||||
this->header_.clear();
|
||||
// MAGIC_NUMBER as uint16_t little-endian
|
||||
this->header_.push_back(MAGIC_NUMBER & 0xFF);
|
||||
this->header_.push_back((MAGIC_NUMBER >> 8) & 0xFF);
|
||||
// Length-prefixed hostname
|
||||
auto len = strlen(name);
|
||||
this->header_.push_back(static_cast<uint8_t>(len));
|
||||
for (size_t i = 0; i < len; i++)
|
||||
this->header_.push_back(name[i]);
|
||||
// Pad to 4-byte boundary
|
||||
while (this->header_.size() & 0x3)
|
||||
this->header_.push_back(0);
|
||||
}
|
||||
};
|
||||
|
||||
/// Build a MAGIC_PING packet for testing add_key_ / ping-pong flows.
|
||||
inline std::vector<uint8_t> build_ping_packet(const char *hostname, uint32_t key) {
|
||||
std::vector<uint8_t> packet;
|
||||
packet.push_back(MAGIC_PING & 0xFF);
|
||||
packet.push_back((MAGIC_PING >> 8) & 0xFF);
|
||||
auto len = strlen(hostname);
|
||||
packet.push_back(static_cast<uint8_t>(len));
|
||||
for (size_t i = 0; i < len; i++)
|
||||
packet.push_back(hostname[i]);
|
||||
packet.push_back(key & 0xFF);
|
||||
packet.push_back((key >> 8) & 0xFF);
|
||||
packet.push_back((key >> 16) & 0xFF);
|
||||
packet.push_back((key >> 24) & 0xFF);
|
||||
return packet;
|
||||
}
|
||||
|
||||
} // namespace esphome::packet_transport::testing
|
||||
@@ -0,0 +1,186 @@
|
||||
#include "common.h"
|
||||
|
||||
namespace esphome::packet_transport::testing {
|
||||
|
||||
// --- Configuration setter tests ---
|
||||
|
||||
TEST(PacketTransportTest, SetIsProvider) {
|
||||
TestablePacketTransport transport;
|
||||
transport.set_is_provider(true);
|
||||
EXPECT_TRUE(transport.is_provider_);
|
||||
}
|
||||
|
||||
TEST(PacketTransportTest, SetEncryptionKey) {
|
||||
TestablePacketTransport transport;
|
||||
std::vector<uint8_t> key(32, 0xAB);
|
||||
transport.set_encryption_key(key);
|
||||
EXPECT_EQ(transport.encryption_key_, key);
|
||||
EXPECT_TRUE(transport.is_encrypted_());
|
||||
}
|
||||
|
||||
TEST(PacketTransportTest, NoEncryptionByDefault) {
|
||||
TestablePacketTransport transport;
|
||||
EXPECT_FALSE(transport.is_encrypted_());
|
||||
}
|
||||
|
||||
TEST(PacketTransportTest, SetRollingCodeEnable) {
|
||||
TestablePacketTransport transport;
|
||||
transport.set_rolling_code_enable(true);
|
||||
EXPECT_TRUE(transport.rolling_code_enable_);
|
||||
}
|
||||
|
||||
TEST(PacketTransportTest, SetPingPongEnable) {
|
||||
TestablePacketTransport transport;
|
||||
transport.set_ping_pong_enable(true);
|
||||
EXPECT_TRUE(transport.ping_pong_enable_);
|
||||
}
|
||||
|
||||
TEST(PacketTransportTest, SetPingPongRecycleTime) {
|
||||
TestablePacketTransport transport;
|
||||
transport.set_ping_pong_recycle_time(600);
|
||||
EXPECT_EQ(transport.ping_pong_recyle_time_, 600u);
|
||||
}
|
||||
|
||||
// --- Provider management ---
|
||||
|
||||
TEST(PacketTransportTest, AddProvider) {
|
||||
TestablePacketTransport transport;
|
||||
transport.add_provider("host1");
|
||||
EXPECT_TRUE(transport.providers_.contains("host1"));
|
||||
EXPECT_EQ(transport.providers_.size(), 1u);
|
||||
}
|
||||
|
||||
TEST(PacketTransportTest, AddProviderDuplicate) {
|
||||
TestablePacketTransport transport;
|
||||
transport.add_provider("host1");
|
||||
transport.add_provider("host1");
|
||||
EXPECT_EQ(transport.providers_.size(), 1u);
|
||||
}
|
||||
|
||||
TEST(PacketTransportTest, SetProviderEncryption) {
|
||||
TestablePacketTransport transport;
|
||||
transport.add_provider("host1");
|
||||
std::vector<uint8_t> key(32, 0xCD);
|
||||
transport.set_provider_encryption("host1", key);
|
||||
EXPECT_EQ(transport.providers_["host1"].encryption_key, key);
|
||||
}
|
||||
|
||||
// --- Ping key tests ---
|
||||
|
||||
TEST(PacketTransportTest, PingKeyStoredWhenEncrypted) {
|
||||
TestablePacketTransport transport;
|
||||
transport.init_for_test("receiver");
|
||||
transport.set_encryption_key(std::vector<uint8_t>(32, 0xAA));
|
||||
|
||||
auto ping = build_ping_packet("requester", 0xDEADBEEF);
|
||||
transport.process_({ping.data(), ping.size()});
|
||||
|
||||
ASSERT_EQ(transport.ping_keys_.size(), 1u);
|
||||
EXPECT_EQ(transport.ping_keys_["requester"], 0xDEADBEEFu);
|
||||
}
|
||||
|
||||
TEST(PacketTransportTest, PingKeyIgnoredWhenNotEncrypted) {
|
||||
TestablePacketTransport transport;
|
||||
transport.init_for_test("receiver");
|
||||
// No encryption key — add_key_ should be a no-op
|
||||
|
||||
auto ping = build_ping_packet("requester", 0xDEADBEEF);
|
||||
transport.process_({ping.data(), ping.size()});
|
||||
|
||||
EXPECT_TRUE(transport.ping_keys_.empty());
|
||||
}
|
||||
|
||||
TEST(PacketTransportTest, PingKeyUpdatedOnRepeat) {
|
||||
TestablePacketTransport transport;
|
||||
transport.init_for_test("receiver");
|
||||
transport.set_encryption_key(std::vector<uint8_t>(32, 0xAA));
|
||||
|
||||
auto ping1 = build_ping_packet("host1", 0x1111);
|
||||
transport.process_({ping1.data(), ping1.size()});
|
||||
EXPECT_EQ(transport.ping_keys_["host1"], 0x1111u);
|
||||
|
||||
// Same host, new key value — should update in place
|
||||
auto ping2 = build_ping_packet("host1", 0x2222);
|
||||
transport.process_({ping2.data(), ping2.size()});
|
||||
EXPECT_EQ(transport.ping_keys_.size(), 1u);
|
||||
EXPECT_EQ(transport.ping_keys_["host1"], 0x2222u);
|
||||
}
|
||||
|
||||
TEST(PacketTransportTest, PingKeyMaxLimit) {
|
||||
TestablePacketTransport transport;
|
||||
transport.init_for_test("receiver");
|
||||
transport.set_encryption_key(std::vector<uint8_t>(32, 0xAA));
|
||||
|
||||
// Fill to MAX_PING_KEYS (4)
|
||||
for (int i = 0; i < 4; i++) {
|
||||
char name[16];
|
||||
snprintf(name, sizeof(name), "host%d", i);
|
||||
auto ping = build_ping_packet(name, 0x1000 + i);
|
||||
transport.process_({ping.data(), ping.size()});
|
||||
}
|
||||
EXPECT_EQ(transport.ping_keys_.size(), 4u);
|
||||
|
||||
// 5th key should be discarded
|
||||
auto ping = build_ping_packet("host4", 0x9999);
|
||||
transport.process_({ping.data(), ping.size()});
|
||||
EXPECT_EQ(transport.ping_keys_.size(), 4u);
|
||||
EXPECT_FALSE(transport.ping_keys_.contains("host4"));
|
||||
}
|
||||
|
||||
// --- Process error handling ---
|
||||
|
||||
TEST(PacketTransportTest, ProcessShortBuffer) {
|
||||
TestablePacketTransport transport;
|
||||
transport.init_for_test("receiver");
|
||||
uint8_t buf[] = {0x53};
|
||||
// Too short for a magic number - should return safely
|
||||
transport.process_({buf, 1});
|
||||
}
|
||||
|
||||
TEST(PacketTransportTest, ProcessBadMagic) {
|
||||
TestablePacketTransport transport;
|
||||
transport.init_for_test("receiver");
|
||||
uint8_t buf[] = {0xFF, 0xFF, 0x00, 0x00};
|
||||
// Wrong magic - should return safely
|
||||
transport.process_({buf, sizeof(buf)});
|
||||
}
|
||||
|
||||
TEST(PacketTransportTest, ProcessOwnHostname) {
|
||||
TestablePacketTransport transport;
|
||||
transport.init_for_test("myself");
|
||||
// Build a packet from "myself" using a separate encoder
|
||||
TestablePacketTransport fake_sender;
|
||||
fake_sender.init_for_test("myself");
|
||||
fake_sender.send_data_(true);
|
||||
ASSERT_EQ(fake_sender.sent_packets.size(), 1u);
|
||||
|
||||
auto &packet = fake_sender.sent_packets[0];
|
||||
// Should be silently ignored because hostname matches our own
|
||||
transport.process_({packet.data(), packet.size()});
|
||||
}
|
||||
|
||||
TEST(PacketTransportTest, ProcessUnknownHostname) {
|
||||
TestablePacketTransport transport;
|
||||
transport.init_for_test("receiver");
|
||||
// No providers registered - "unknown" will not be found
|
||||
TestablePacketTransport sender;
|
||||
sender.init_for_test("unknown");
|
||||
sender.send_data_(true);
|
||||
ASSERT_EQ(sender.sent_packets.size(), 1u);
|
||||
|
||||
auto &packet = sender.sent_packets[0];
|
||||
// Should return safely without crash
|
||||
transport.process_({packet.data(), packet.size()});
|
||||
}
|
||||
|
||||
// --- Send disabled ---
|
||||
|
||||
TEST(PacketTransportTest, NoSendWhenDisabled) {
|
||||
TestablePacketTransport transport;
|
||||
transport.init_for_test("sender");
|
||||
transport.send_enabled = false;
|
||||
transport.send_data_(true);
|
||||
EXPECT_TRUE(transport.sent_packets.empty());
|
||||
}
|
||||
|
||||
} // namespace esphome::packet_transport::testing
|
||||
@@ -0,0 +1,170 @@
|
||||
#include "../common.h"
|
||||
|
||||
namespace esphome::packet_transport::testing {
|
||||
|
||||
TEST(PacketTransportSensorTest, AddSensor) {
|
||||
TestablePacketTransport transport;
|
||||
sensor::Sensor s;
|
||||
transport.add_sensor("temp", &s);
|
||||
ASSERT_EQ(transport.sensors_.size(), 1u);
|
||||
EXPECT_STREQ(transport.sensors_[0].id, "temp");
|
||||
EXPECT_EQ(transport.sensors_[0].sensor, &s);
|
||||
EXPECT_TRUE(transport.sensors_[0].updated);
|
||||
}
|
||||
|
||||
TEST(PacketTransportSensorTest, AddRemoteSensor) {
|
||||
TestablePacketTransport transport;
|
||||
sensor::Sensor s;
|
||||
transport.add_remote_sensor("host1", "remote_temp", &s);
|
||||
EXPECT_TRUE(transport.providers_.contains("host1"));
|
||||
EXPECT_EQ(transport.remote_sensors_["host1"]["remote_temp"], &s);
|
||||
}
|
||||
|
||||
TEST(PacketTransportSensorTest, UnencryptedSensorRoundTrip) {
|
||||
// Encoder
|
||||
TestablePacketTransport encoder;
|
||||
encoder.init_for_test("sender");
|
||||
sensor::Sensor local_sensor;
|
||||
local_sensor.state = 42.5f;
|
||||
encoder.add_sensor("temp", &local_sensor);
|
||||
|
||||
encoder.send_data_(true);
|
||||
ASSERT_EQ(encoder.sent_packets.size(), 1u);
|
||||
|
||||
// Decoder
|
||||
TestablePacketTransport decoder;
|
||||
decoder.init_for_test("receiver");
|
||||
sensor::Sensor remote_sensor;
|
||||
remote_sensor.state = -999.0f; // sentinel
|
||||
decoder.add_remote_sensor("sender", "temp", &remote_sensor);
|
||||
|
||||
auto &packet = encoder.sent_packets[0];
|
||||
decoder.process_({packet.data(), packet.size()});
|
||||
EXPECT_FLOAT_EQ(remote_sensor.state, 42.5f);
|
||||
}
|
||||
|
||||
TEST(PacketTransportSensorTest, EncryptedSensorRoundTrip) {
|
||||
std::vector<uint8_t> key(32);
|
||||
for (int i = 0; i < 32; i++)
|
||||
key[i] = i;
|
||||
|
||||
TestablePacketTransport encoder;
|
||||
encoder.init_for_test("sender");
|
||||
encoder.set_encryption_key(key);
|
||||
sensor::Sensor local_sensor;
|
||||
local_sensor.state = 99.9f;
|
||||
encoder.add_sensor("temp", &local_sensor);
|
||||
|
||||
encoder.send_data_(true);
|
||||
ASSERT_EQ(encoder.sent_packets.size(), 1u);
|
||||
|
||||
TestablePacketTransport decoder;
|
||||
decoder.init_for_test("receiver");
|
||||
sensor::Sensor remote_sensor;
|
||||
remote_sensor.state = -999.0f;
|
||||
decoder.add_remote_sensor("sender", "temp", &remote_sensor);
|
||||
decoder.set_provider_encryption("sender", key);
|
||||
|
||||
auto &packet = encoder.sent_packets[0];
|
||||
decoder.process_({packet.data(), packet.size()});
|
||||
EXPECT_FLOAT_EQ(remote_sensor.state, 99.9f);
|
||||
}
|
||||
|
||||
TEST(PacketTransportSensorTest, SendDataOnlyUpdated) {
|
||||
TestablePacketTransport encoder;
|
||||
encoder.init_for_test("sender");
|
||||
|
||||
sensor::Sensor s1, s2;
|
||||
s1.state = 1.0f;
|
||||
s2.state = 2.0f;
|
||||
encoder.add_sensor("s1", &s1);
|
||||
encoder.add_sensor("s2", &s2);
|
||||
|
||||
// Mark s1 as not updated, only s2 as updated
|
||||
encoder.sensors_[0].updated = false;
|
||||
encoder.sensors_[1].updated = true;
|
||||
|
||||
encoder.send_data_(false);
|
||||
ASSERT_EQ(encoder.sent_packets.size(), 1u);
|
||||
|
||||
TestablePacketTransport decoder;
|
||||
decoder.init_for_test("receiver");
|
||||
sensor::Sensor rs1, rs2;
|
||||
rs1.state = -999.0f;
|
||||
rs2.state = -999.0f;
|
||||
decoder.add_remote_sensor("sender", "s1", &rs1);
|
||||
decoder.add_remote_sensor("sender", "s2", &rs2);
|
||||
|
||||
auto &packet = encoder.sent_packets[0];
|
||||
decoder.process_({packet.data(), packet.size()});
|
||||
|
||||
EXPECT_FLOAT_EQ(rs1.state, -999.0f); // not updated, not sent
|
||||
EXPECT_FLOAT_EQ(rs2.state, 2.0f); // updated, sent
|
||||
}
|
||||
|
||||
TEST(PacketTransportSensorTest, PingKeyIncludedInTransmittedPacket) {
|
||||
std::vector<uint8_t> key(32, 0xBB);
|
||||
|
||||
// Responder: encrypted, owns a sensor
|
||||
TestablePacketTransport responder;
|
||||
responder.init_for_test("responder");
|
||||
responder.set_encryption_key(key);
|
||||
sensor::Sensor local_sensor;
|
||||
local_sensor.state = 77.7f;
|
||||
responder.add_sensor("temp", &local_sensor);
|
||||
|
||||
// Requester sends a MAGIC_PING that the responder processes
|
||||
auto ping = build_ping_packet("requester", 0xDEADBEEF);
|
||||
responder.process_({ping.data(), ping.size()});
|
||||
ASSERT_EQ(responder.ping_keys_.size(), 1u);
|
||||
|
||||
// Responder sends sensor data — ping key should be embedded
|
||||
responder.send_data_(true);
|
||||
ASSERT_EQ(responder.sent_packets.size(), 1u);
|
||||
|
||||
// Requester: encrypted provider, ping-pong enabled, expects key 0xDEADBEEF
|
||||
TestablePacketTransport requester;
|
||||
requester.init_for_test("requester");
|
||||
requester.set_ping_pong_enable(true);
|
||||
requester.ping_key_ = 0xDEADBEEF;
|
||||
sensor::Sensor remote_sensor;
|
||||
remote_sensor.state = -999.0f;
|
||||
requester.add_remote_sensor("responder", "temp", &remote_sensor);
|
||||
requester.set_provider_encryption("responder", key);
|
||||
|
||||
// The requester decrypts the packet and finds its ping key echoed back,
|
||||
// which gates the sensor data — if the key is missing, data is blocked.
|
||||
auto &packet = responder.sent_packets[0];
|
||||
requester.process_({packet.data(), packet.size()});
|
||||
EXPECT_FLOAT_EQ(remote_sensor.state, 77.7f);
|
||||
}
|
||||
|
||||
TEST(PacketTransportSensorTest, MissingPingKeyBlocksSensorData) {
|
||||
std::vector<uint8_t> key(32, 0xBB);
|
||||
|
||||
// Responder sends data WITHOUT receiving any MAGIC_PING first — no ping keys
|
||||
TestablePacketTransport responder;
|
||||
responder.init_for_test("responder");
|
||||
responder.set_encryption_key(key);
|
||||
sensor::Sensor local_sensor;
|
||||
local_sensor.state = 77.7f;
|
||||
responder.add_sensor("temp", &local_sensor);
|
||||
responder.send_data_(true);
|
||||
ASSERT_EQ(responder.sent_packets.size(), 1u);
|
||||
|
||||
// Requester with ping-pong enabled expects a key that isn't in the packet
|
||||
TestablePacketTransport requester;
|
||||
requester.init_for_test("requester");
|
||||
requester.set_ping_pong_enable(true);
|
||||
requester.ping_key_ = 0xDEADBEEF;
|
||||
sensor::Sensor remote_sensor;
|
||||
remote_sensor.state = -999.0f;
|
||||
requester.add_remote_sensor("responder", "temp", &remote_sensor);
|
||||
requester.set_provider_encryption("responder", key);
|
||||
|
||||
auto &packet = responder.sent_packets[0];
|
||||
requester.process_({packet.data(), packet.size()});
|
||||
EXPECT_FLOAT_EQ(remote_sensor.state, -999.0f); // blocked — ping key not found
|
||||
}
|
||||
|
||||
} // namespace esphome::packet_transport::testing
|
||||
@@ -1,3 +1,6 @@
|
||||
rp2040:
|
||||
enable_full_printf: false
|
||||
|
||||
logger:
|
||||
level: VERBOSE
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
rp2040_ble:
|
||||
@@ -0,0 +1,2 @@
|
||||
rp2040_ble:
|
||||
enable_on_boot: false
|
||||
@@ -0,0 +1 @@
|
||||
<<: !include common.yaml
|
||||
@@ -0,0 +1,10 @@
|
||||
wifi:
|
||||
ssid: MySSID
|
||||
password: password1
|
||||
|
||||
api:
|
||||
|
||||
serial_proxy:
|
||||
- id: serial_proxy_1
|
||||
name: Test Serial Port
|
||||
port_type: RS232
|
||||
@@ -0,0 +1,8 @@
|
||||
substitutions:
|
||||
tx_pin: GPIO4
|
||||
rx_pin: GPIO5
|
||||
|
||||
packages:
|
||||
uart: !include ../../test_build_components/common/uart/esp32-idf.yaml
|
||||
|
||||
<<: !include common.yaml
|
||||
@@ -0,0 +1,8 @@
|
||||
substitutions:
|
||||
tx_pin: GPIO0
|
||||
rx_pin: GPIO2
|
||||
|
||||
packages:
|
||||
uart: !include ../../test_build_components/common/uart/esp8266-ard.yaml
|
||||
|
||||
<<: !include common.yaml
|
||||
@@ -0,0 +1,8 @@
|
||||
substitutions:
|
||||
tx_pin: GPIO4
|
||||
rx_pin: GPIO5
|
||||
|
||||
packages:
|
||||
uart: !include ../../test_build_components/common/uart/rp2040-ard.yaml
|
||||
|
||||
<<: !include common.yaml
|
||||
@@ -0,0 +1,18 @@
|
||||
<<: !include common.yaml
|
||||
|
||||
media_player:
|
||||
- platform: speaker
|
||||
id: speaker_media_player_id
|
||||
announcement_pipeline:
|
||||
speaker: speaker_id
|
||||
buffer_size: 1000000
|
||||
volume_increment: 0.02
|
||||
volume_max: 0.95
|
||||
volume_min: 0.0
|
||||
task_stack_in_psram: true
|
||||
on_turn_on:
|
||||
then:
|
||||
- logger.log: "Turn On Media Player"
|
||||
on_turn_off:
|
||||
then:
|
||||
- logger.log: "Turn Off Media Player"
|
||||
@@ -0,0 +1,9 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO16
|
||||
sda_pin: GPIO17
|
||||
i2s_bclk_pin: GPIO27
|
||||
i2s_lrclk_pin: GPIO26
|
||||
i2s_mclk_pin: GPIO25
|
||||
i2s_dout_pin: GPIO23
|
||||
|
||||
<<: !include common-media_player_off_on.yaml
|
||||
@@ -0,0 +1,43 @@
|
||||
i2s_audio:
|
||||
i2s_lrclk_pin: ${i2s_bclk_pin}
|
||||
i2s_bclk_pin: ${i2s_lrclk_pin}
|
||||
i2s_mclk_pin: ${i2s_mclk_pin}
|
||||
|
||||
speaker:
|
||||
- platform: i2s_audio
|
||||
id: speaker_id
|
||||
dac_type: external
|
||||
i2s_dout_pin: ${i2s_dout_pin}
|
||||
sample_rate: 48000
|
||||
num_channels: 2
|
||||
|
||||
audio_file:
|
||||
- id: test_audio
|
||||
file:
|
||||
type: local
|
||||
path: $component_dir/test.wav
|
||||
|
||||
media_source:
|
||||
- platform: audio_file
|
||||
id: audio_file_source
|
||||
|
||||
media_player:
|
||||
- platform: speaker_source
|
||||
id: media_player_id
|
||||
name: Media Player
|
||||
volume_increment: 0.02
|
||||
volume_initial: 0.75
|
||||
volume_max: 0.95
|
||||
volume_min: 0.0
|
||||
media_pipeline:
|
||||
speaker: speaker_id
|
||||
format: FLAC
|
||||
num_channels: 1
|
||||
sources:
|
||||
- audio_file_source
|
||||
on_mute:
|
||||
- media_player.pause:
|
||||
id: media_player_id
|
||||
on_unmute:
|
||||
- media_player.play:
|
||||
id: media_player_id
|
||||
@@ -0,0 +1,9 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO16
|
||||
sda_pin: GPIO17
|
||||
i2s_bclk_pin: GPIO27
|
||||
i2s_lrclk_pin: GPIO26
|
||||
i2s_mclk_pin: GPIO25
|
||||
i2s_dout_pin: GPIO23
|
||||
|
||||
<<: !include common.yaml
|
||||
Binary file not shown.
@@ -28,9 +28,14 @@ esphome:
|
||||
# Test C++ API: set_template() with stateless lambda (no captures)
|
||||
# NOTE: set_template() is not intended to be a public API, but we test it to ensure it doesn't break.
|
||||
- lambda: |-
|
||||
id(template_sens).set_template([]() -> esphome::optional<float> {
|
||||
id(template_sens).set_template([]() -> std::optional<float> {
|
||||
return 123.0f;
|
||||
});
|
||||
# Test that esphome::optional alias still works for backward compatibility
|
||||
- lambda: |-
|
||||
id(template_sens).set_template([]() -> esphome::optional<float> {
|
||||
return 42.0f;
|
||||
});
|
||||
|
||||
- datetime.date.set:
|
||||
id: test_date
|
||||
|
||||
@@ -30,7 +30,7 @@ class MockUARTComponent : public UARTComponent {
|
||||
MOCK_METHOD(bool, read_array, (uint8_t * data, size_t len), (override));
|
||||
MOCK_METHOD(bool, peek_byte, (uint8_t * data), (override));
|
||||
MOCK_METHOD(size_t, available, (), (override));
|
||||
MOCK_METHOD(void, flush, (), (override));
|
||||
MOCK_METHOD(FlushResult, flush, (), (override));
|
||||
MOCK_METHOD(void, check_logger_conflict, (), (override));
|
||||
};
|
||||
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
esphome:
|
||||
on_boot:
|
||||
then:
|
||||
- uart.write: 'Hello World'
|
||||
- uart.write: [0x00, 0x20, 0x42]
|
||||
- uart.write:
|
||||
id: uart_id
|
||||
data: 'Hello World'
|
||||
- uart.write:
|
||||
id: uart_id
|
||||
data: [0x00, 0x20, 0x42]
|
||||
|
||||
uart:
|
||||
- id: uart_uart
|
||||
- id: uart_id
|
||||
tx_pin: 4
|
||||
rx_pin: 5
|
||||
flow_control_pin: 6
|
||||
@@ -16,3 +20,9 @@ uart:
|
||||
rx_timeout: 1
|
||||
parity: EVEN
|
||||
stop_bits: 2
|
||||
- id: uart_debug
|
||||
tx_pin: 18
|
||||
rx_pin: 19
|
||||
baud_rate: 115200
|
||||
debug:
|
||||
debug_prefix: "[UART1] "
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
esphome:
|
||||
on_boot:
|
||||
then:
|
||||
- uart.write: 'Hello World'
|
||||
- uart.write: [0x00, 0x20, 0x42]
|
||||
- uart.write: !lambda |-
|
||||
return {0xAA, 0xBB, 0xCC};
|
||||
- uart.write:
|
||||
id: uart_id
|
||||
data: 'Hello World'
|
||||
- uart.write:
|
||||
id: uart_id
|
||||
data: [0x00, 0x20, 0x42]
|
||||
- uart.write:
|
||||
id: uart_id
|
||||
data: !lambda |-
|
||||
return {0xAA, 0xBB, 0xCC};
|
||||
|
||||
uart:
|
||||
- id: uart_uart
|
||||
- id: uart_id
|
||||
tx_pin: 17
|
||||
rx_pin: 16
|
||||
flow_control_pin: 4
|
||||
@@ -18,32 +24,54 @@ uart:
|
||||
rx_timeout: 1
|
||||
parity: EVEN
|
||||
stop_bits: 2
|
||||
- id: uart_debug
|
||||
tx_pin: 21
|
||||
rx_pin: 22
|
||||
baud_rate: 115200
|
||||
debug:
|
||||
debug_prefix: "[UART1] "
|
||||
- id: uart_debug_custom
|
||||
tx_pin: 25
|
||||
rx_pin: 26
|
||||
baud_rate: 9600
|
||||
debug:
|
||||
debug_prefix: "[UART2] "
|
||||
after:
|
||||
delimiter: "\n"
|
||||
sequence:
|
||||
- lambda: UARTDebug::log_string(direction, bytes, debug_prefix);
|
||||
- id: uart_debug_no_prefix
|
||||
tx_pin: 32
|
||||
rx_pin: 33
|
||||
baud_rate: 9600
|
||||
debug:
|
||||
|
||||
packet_transport:
|
||||
- platform: uart
|
||||
uart_id: uart_id
|
||||
|
||||
switch:
|
||||
# Test uart switch with single state (array)
|
||||
- platform: uart
|
||||
name: "UART Switch Single Array"
|
||||
uart_id: uart_uart
|
||||
uart_id: uart_id
|
||||
data: [0x01, 0x02, 0x03]
|
||||
# Test uart switch with single state (string)
|
||||
- platform: uart
|
||||
name: "UART Switch Single String"
|
||||
uart_id: uart_uart
|
||||
uart_id: uart_id
|
||||
data: "ON"
|
||||
# Test uart switch with turn_on/turn_off (arrays)
|
||||
- platform: uart
|
||||
name: "UART Switch Dual Array"
|
||||
uart_id: uart_uart
|
||||
uart_id: uart_id
|
||||
data:
|
||||
turn_on: [0xA0, 0xA1, 0xA2]
|
||||
turn_off: [0xB0, 0xB1, 0xB2]
|
||||
# Test uart switch with turn_on/turn_off (strings)
|
||||
- platform: uart
|
||||
name: "UART Switch Dual String"
|
||||
uart_id: uart_uart
|
||||
uart_id: uart_id
|
||||
data:
|
||||
turn_on: "TURN_ON"
|
||||
turn_off: "TURN_OFF"
|
||||
@@ -61,24 +89,26 @@ button:
|
||||
# Test uart button with array data
|
||||
- platform: uart
|
||||
name: "UART Button Array"
|
||||
uart_id: uart_uart
|
||||
uart_id: uart_id
|
||||
data: [0xFF, 0xEE, 0xDD]
|
||||
# Test uart button with string data
|
||||
- platform: uart
|
||||
name: "UART Button String"
|
||||
uart_id: uart_uart
|
||||
uart_id: uart_id
|
||||
data: "BUTTON_PRESS"
|
||||
# Test uart button with lambda (function pointer)
|
||||
- platform: template
|
||||
name: "UART Lambda Test"
|
||||
on_press:
|
||||
- uart.write: !lambda |-
|
||||
std::string cmd = "VALUE=" + str_sprintf("%.0f", id(test_number).state) + "\r\n";
|
||||
return std::vector<uint8_t>(cmd.begin(), cmd.end());
|
||||
- uart.write:
|
||||
id: uart_id
|
||||
data: !lambda |-
|
||||
std::string cmd = "VALUE=" + str_sprintf("%.0f", id(test_number).state) + "\r\n";
|
||||
return std::vector<uint8_t>(cmd.begin(), cmd.end());
|
||||
|
||||
event:
|
||||
- platform: uart
|
||||
uart_id: uart_uart
|
||||
uart_id: uart_id
|
||||
name: "UART Event"
|
||||
event_types:
|
||||
- "string_event_A": "*A#"
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
esphome:
|
||||
on_boot:
|
||||
then:
|
||||
- uart.write: 'Hello World'
|
||||
- uart.write: [0x00, 0x20, 0x42]
|
||||
- uart.write:
|
||||
id: uart_id
|
||||
data: 'Hello World'
|
||||
- uart.write:
|
||||
id: uart_id
|
||||
data: [0x00, 0x20, 0x42]
|
||||
|
||||
uart:
|
||||
- id: uart_uart
|
||||
- id: uart_id
|
||||
tx_pin: 4
|
||||
rx_pin: 5
|
||||
baud_rate: 9600
|
||||
@@ -13,15 +17,21 @@ uart:
|
||||
rx_buffer_size: 512
|
||||
parity: EVEN
|
||||
stop_bits: 2
|
||||
- id: uart_debug
|
||||
tx_pin: 14
|
||||
rx_pin: 12
|
||||
baud_rate: 115200
|
||||
debug:
|
||||
debug_prefix: "[UART1] "
|
||||
|
||||
switch:
|
||||
- platform: uart
|
||||
name: "UART Switch Array"
|
||||
uart_id: uart_uart
|
||||
uart_id: uart_id
|
||||
data: [0x01, 0x02, 0x03]
|
||||
- platform: uart
|
||||
name: "UART Switch Dual"
|
||||
uart_id: uart_uart
|
||||
uart_id: uart_id
|
||||
data:
|
||||
turn_on: [0xA0, 0xA1]
|
||||
turn_off: [0xB0, 0xB1]
|
||||
@@ -29,12 +39,12 @@ switch:
|
||||
button:
|
||||
- platform: uart
|
||||
name: "UART Button"
|
||||
uart_id: uart_uart
|
||||
uart_id: uart_id
|
||||
data: [0xFF, 0xEE]
|
||||
|
||||
event:
|
||||
- platform: uart
|
||||
uart_id: uart_uart
|
||||
uart_id: uart_id
|
||||
name: "UART Event"
|
||||
event_types:
|
||||
- "string_event_A": "*A#"
|
||||
|
||||
@@ -5,7 +5,7 @@ esphome:
|
||||
- uart.write: [0x00, 0x20, 0x42]
|
||||
|
||||
uart:
|
||||
- id: uart_uart
|
||||
- id: uart_id
|
||||
port: "/dev/ttyS0"
|
||||
baud_rate: 9600
|
||||
data_bits: 8
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
esphome:
|
||||
on_boot:
|
||||
then:
|
||||
- uart.write: 'Hello World'
|
||||
- uart.write: [0x00, 0x20, 0x42]
|
||||
- uart.write:
|
||||
id: uart_id
|
||||
data: 'Hello World'
|
||||
- uart.write:
|
||||
id: uart_id
|
||||
data: [0x00, 0x20, 0x42]
|
||||
|
||||
uart:
|
||||
- id: uart_uart
|
||||
- id: uart_id
|
||||
tx_pin: 4
|
||||
rx_pin: 5
|
||||
baud_rate: 9600
|
||||
@@ -13,3 +17,9 @@ uart:
|
||||
rx_buffer_size: 512
|
||||
parity: EVEN
|
||||
stop_bits: 2
|
||||
- id: uart_debug
|
||||
tx_pin: 8
|
||||
rx_pin: 9
|
||||
baud_rate: 115200
|
||||
debug:
|
||||
debug_prefix: "[UART1] "
|
||||
|
||||
@@ -34,3 +34,11 @@ usb_uart:
|
||||
- id: channel_4_1
|
||||
debug: true
|
||||
dummy_receiver: true
|
||||
debug_prefix: "[ESP_JTAG] "
|
||||
- id: uart_5
|
||||
type: cp210x
|
||||
channels:
|
||||
- id: channel_5_1
|
||||
baud_rate: 9600
|
||||
debug: true
|
||||
debug_prefix: "[CP210X] "
|
||||
|
||||
Reference in New Issue
Block a user