mirror of
https://github.com/esphome/esphome.git
synced 2026-06-24 12:17:23 +00:00
189 lines
6.3 KiB
YAML
189 lines
6.3 KiB
YAML
esphome:
|
|
name: uart-mock-ld2420-test
|
|
|
|
host:
|
|
api:
|
|
batch_delay: 0ms # Disable batching to receive all state updates
|
|
logger:
|
|
level: VERBOSE
|
|
|
|
external_components:
|
|
- source:
|
|
type: local
|
|
path: EXTERNAL_COMPONENT_PATH
|
|
|
|
# Dummy uart entry to satisfy ld2420's DEPENDENCIES = ["uart"]
|
|
# The actual UART bus used is the uart_mock component below
|
|
uart:
|
|
baud_rate: 115200
|
|
port: /dev/null
|
|
|
|
uart_mock:
|
|
id: mock_uart
|
|
baud_rate: 115200
|
|
auto_start: false
|
|
responses:
|
|
# Version-specific response: match the complete firmware version command TX.
|
|
# CMD_READ_VERSION (0x0000) TX = FD FC FB FA 02 00 00 00 04 03 02 01
|
|
# Returns "v2.0.0" → get_firmware_int = 200 >= 154 → energy mode
|
|
#
|
|
# Response layout:
|
|
# [0-3] FD FC FB FA = header
|
|
# [4-5] 0C 00 = length 12
|
|
# [6] 00 = cmd (CMD_READ_VERSION)
|
|
# [7] 01 = status (ACK)
|
|
# [8-9] 00 00 = error = 0
|
|
# [10] 06 = ver_len = 6
|
|
# [11] 00 = padding
|
|
# [12-17] "v2.0.0" = version string
|
|
# [18-21] 04 03 02 01 = footer
|
|
- expect_tx:
|
|
[0xFD, 0xFC, 0xFB, 0xFA, 0x02, 0x00, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01]
|
|
inject_rx:
|
|
[
|
|
0xFD, 0xFC, 0xFB, 0xFA,
|
|
0x0C, 0x00,
|
|
0x00, 0x01,
|
|
0x00, 0x00,
|
|
0x06, 0x00,
|
|
0x76, 0x32, 0x2E, 0x30, 0x2E, 0x30,
|
|
0x04, 0x03, 0x02, 0x01,
|
|
]
|
|
|
|
# Catch-all response: match any command footer (04 03 02 01).
|
|
# Returns a generic ACK with cmd=0xFF (CMD_ENABLE_CONF case in switch).
|
|
# All commands get unblocked via cmd_reply_.ack = true.
|
|
# Data fields stay zeroed (min_gate=0, max_gate=0, timeout=0, thresholds=0).
|
|
#
|
|
# Response layout:
|
|
# [0-3] FD FC FB FA = header
|
|
# [4-5] 04 00 = length 4
|
|
# [6] FF = cmd (handled as CMD_ENABLE_CONF)
|
|
# [7] 01 = status (ACK)
|
|
# [8-9] 00 00 = error = 0
|
|
# [10-13] 04 03 02 01 = footer
|
|
- expect_tx: [0x04, 0x03, 0x02, 0x01]
|
|
inject_rx:
|
|
[
|
|
0xFD, 0xFC, 0xFB, 0xFA,
|
|
0x04, 0x00,
|
|
0xFF, 0x01,
|
|
0x00, 0x00,
|
|
0x04, 0x03, 0x02, 0x01,
|
|
]
|
|
|
|
injections:
|
|
# Phase 1 (t=100ms): Valid LD2420 energy mode data frame - happy path
|
|
# Buffer is clean (buffer_pos_=0). This frame should parse correctly.
|
|
# Presence: 1 (target detected), Distance: 100cm, Gate energies: all 0
|
|
#
|
|
# Energy frame layout (45 bytes):
|
|
# [0-3] F4 F3 F2 F1 = energy frame header
|
|
# [4-5] 23 00 = length 35 (1+2+32)
|
|
# [6] 01 = presence (1 = target)
|
|
# [7-8] 64 00 = distance 100 (uint16_t LE)
|
|
# [9-40] 00 00 x16 = 16 gate energies (uint16_t LE each)
|
|
# [41-44] F8 F7 F6 F5 = energy frame footer
|
|
- delay: 100ms
|
|
inject_rx:
|
|
[
|
|
0xF4, 0xF3, 0xF2, 0xF1,
|
|
0x23, 0x00,
|
|
0x01,
|
|
0x64, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0xF8, 0xF7, 0xF6, 0xF5,
|
|
]
|
|
|
|
# Phase 2 (t=300ms): Garbage bytes
|
|
# LD2420's readline_ does NOT check frame headers at position 0 (unlike LD2412),
|
|
# so these bytes accumulate in the buffer. buffer_pos_ goes from 0 to 7.
|
|
- delay: 200ms
|
|
inject_rx: [0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x11, 0x22]
|
|
|
|
# Phase 3 (t=400ms): Truncated energy frame WITH footer (13 bytes)
|
|
# This tests PR #14458 bug #3: missing length validation in handle_energy_mode_.
|
|
# The 7 garbage bytes from Phase 2 are still in the buffer (buffer_pos_=7).
|
|
# These 13 bytes are appended at positions 7-19 (buffer_pos_=20).
|
|
# Energy footer at positions 16-19 triggers handle_energy_mode_(buffer, 20).
|
|
#
|
|
# Pre-fix: handle_energy_mode_ reads 32 bytes of gate energy from buffer[9:40],
|
|
# which is past the 20 actual bytes. Reads uninitialized data.
|
|
# No "Energy frame too short" warning exists.
|
|
# Post-fix: len=20 < 41 → logs "Energy frame too short: 20 bytes", returns early.
|
|
#
|
|
# Frame: header + length + presence + distance + footer (no gate data)
|
|
- delay: 100ms
|
|
inject_rx:
|
|
[
|
|
0xF4, 0xF3, 0xF2, 0xF1,
|
|
0x23, 0x00,
|
|
0x01,
|
|
0x64, 0x00,
|
|
0xF8, 0xF7, 0xF6, 0xF5,
|
|
]
|
|
|
|
# Phase 4 (t=600ms): Overflow - inject 50 bytes of 0xFF (MAX_LINE_LENGTH=50)
|
|
# After Phase 3, buffer_pos_=0 (reset after energy footer detection).
|
|
# 49 bytes fill positions 0-48 (buffer_pos_=49), 50th byte triggers overflow.
|
|
# Logs "Max command length exceeded; ignoring", buffer_pos_=0.
|
|
- delay: 200ms
|
|
inject_rx:
|
|
[
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
]
|
|
|
|
# Phase 5 (t=1500ms): Valid frame after overflow - recovery test
|
|
# Buffer was reset by overflow. This valid frame should parse correctly.
|
|
# Presence: 1 (target), Distance: 50cm
|
|
# Delay=900ms ensures >1000ms gap from Phase 1 for REFRESH_RATE_MS throttle.
|
|
- delay: 900ms
|
|
inject_rx:
|
|
[
|
|
0xF4, 0xF3, 0xF2, 0xF1,
|
|
0x23, 0x00,
|
|
0x01,
|
|
0x32, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0xF8, 0xF7, 0xF6, 0xF5,
|
|
]
|
|
|
|
button:
|
|
- platform: template
|
|
name: "Start Scenario"
|
|
on_press:
|
|
- lambda: 'id(mock_uart).start_scenario();'
|
|
|
|
ld2420:
|
|
id: ld2420_dev
|
|
uart_id: mock_uart
|
|
|
|
sensor:
|
|
- platform: ld2420
|
|
ld2420_id: ld2420_dev
|
|
moving_distance:
|
|
name: "Moving Distance"
|
|
filters:
|
|
- timeout:
|
|
timeout: 50ms
|
|
value: last
|
|
- throttle_with_priority: 50ms
|
|
|
|
binary_sensor:
|
|
- platform: ld2420
|
|
ld2420_id: ld2420_dev
|
|
has_target:
|
|
name: "Has Target"
|
|
filters:
|
|
- settle: 50ms
|