Changelog

# Changelog / 更新日志

## 1.2.0
- **BREAKING — on-air format (空口格式破坏性变更)**: the beacon is now 27 bytes, the NFC
  provisioning payload 46 bytes and the REG_ACK 18 bytes. `sys_state` is gone, replaced by
  `slot_step_us`, `tx_suspended` and the opaque `user_state`; the firmware-version and
  slot-offset fields are gone entirely. A 1.2.0 master can talk to nothing but 1.2.0 slaves:
  the whole fleet must be updated together. *(信标 27 字节、NFC 配网包 46 字节、REG_ACK 18 字节;
  `sys_state` 被 `slot_step_us`、`tx_suspended` 与不透明的 `user_state` 取代;固件版本与时隙偏移
  字段被彻底删除。1.2.0 网关只能与 1.2.0 节点通信,必须全网同版本升级。)*
- **BREAKING — API (接口破坏性变更)**:
  - `esp_tdma_slave_set_config_ex()` and the legacy 4-argument `esp_tdma_slave_set_config()`
    are merged into one `esp_tdma_slave_set_config(node_id, gateway_mac, node_unicast_lmk,
    beacon_cmac_key)`. The slot offset is no longer a parameter.
  - `on_node_registered(node_id)` replaces `on_node_registered(node_id, fw_ver, upgrade_required)`.
  - `on_sys_state_changed` is replaced by `on_user_state_changed`, fed by the beacon's opaque
    `user_state` byte.
  - `TDMA_STATE_OTA` is removed from `esp_tdma_state_t`.
  *(接口合并与回调重命名;时隙偏移不再是参数;OTA 状态从状态机移除。)*
- **The OTA coupling is gone (移除 OTA 耦合)**: the component no longer knows what OTA is. The
  firmware-version handshake was provably inert — both sides always reported `20260622` and
  `upgrade_required = false` — and the beacon's `sys_state` field, which drove slave transitions,
  was the application's business state leaking into the link layer. Firmware versioning and OTA
  belong entirely to the application payload now.
  *(组件不再知道 OTA 是什么。固件版本握手经查证是死代码——两端恒为 `20260622` 与
  `upgrade_required = false`;而驱动从节点状态跳转的信标 `sys_state` 字段,本质是业务状态
  渗入链路层。固件版本与 OTA 现在完全归应用载荷所有。)*
- **Generic network-wide TX suspension (通用全网发送暂停)**: new
  `esp_tdma_master_set_tx_suspended()` / `is_tx_suspended()` and `esp_tdma_slave_is_suspended()`.
  Suspension gates the *entire* slave TX path — user payloads and the REG_ACK alike — so the
  application can hand the radio to another stack and take it back deterministically. The master
  keeps beaconing while suspended, so the fleet stays synchronised and resumes on the next beacon.
  A caller must wait at least three beacon periods after setting the flag, because nodes already
  mid-transmission can only observe the change at their next beacon.
  To make that safe, the slave's packet sequence counter **keeps advancing while suspended** and
  the master **suspends its own PER evaluation**, resetting the window on resume: otherwise the
  silent window would be scored as a burst of losses and trip a spurious AFH hop on the very first
  packet back.
  *(暂停闸门覆盖从节点**全部**发送路径(含 REG_ACK);暂停期间网关仍广播信标,全网保持同步。
  置位后调用方须等待至少三个信标周期。为此从节点序号在暂停期间**继续递增**、网关**暂停 PER 评估**
  并在恢复时重置窗口,否则静默期会被判为一串丢包、恢复瞬间误触发跳频。)*
- **Slot geometry moved into the beacon (时隙几何改由信标下发)**: the beacon carries
  `slot_step_us` and each node derives its own offset as `node_id * slot_step_us`. Nothing about
  the frame geometry is provisioned any more, so resizing the frame or rebooting a node after an
  OTA needs no re-provisioning. The step's divisor is the **highest node ID in use**, not a node
  count: offsets are positional, so a sparse ID range would otherwise push the top node past the
  end of the frame. The node validates the advertised step against its own offset before arming
  its slot timer. *(信标携带 `slot_step_us`,节点自行推导偏移。除数取**当前占用的最高节点号**而非
  节点数量——偏移是位置量,稀疏 ID 会把最大号节点顶出帧外。节点会先校验再装定时器。)*
- **`active_nodes_bitmask` is now read (该字段现在真的被读取)**: it was written but never
  consumed. Bit `node_id - 1` now decides whether a node is admitted to the schedule, replacing the
  global `sys_state` transition. A consequence is that a gateway reboot recovers by itself: the
  master's registry starts empty, every node sees its bit clear, returns to REGISTERING and
  re-announces. *(该字段过去只写不读。现在由 `node_id - 1` 位决定节点是否纳入调度,取代全局
  `sys_state` 跳转。附带效果:网关重启可自愈——登记册为空→节点发现自己的位被清零→回到
  REGISTERING 重新宣告。)*
- **Beacon-loss detection (信标丢失检测)**: a node that receives no valid beacon for
  `CONFIG_TDMA_BEACON_LOSS_TIMEOUT_MS` (default 500 ms) reports `TDMA_STATE_SILENT_ERROR` and
  `ESP_TDMA_LINK_OFFLINE` instead of staying in RUNNING on an undisciplined clock, and
  re-registers by itself when beacons return. Beacons that fail CMAC or replay checks do not count
  as received. *(超时未收到有效信标即进入 `TDMA_STATE_SILENT_ERROR`;验签或重放校验失败的信标
  不计入"收到";信标恢复后自动重新注册。)*
- **PER window no longer freezes after a node restarts (节点重启不再冻结 PER)**: a node's
  sequence counter rolling backwards was not handled, so after a reboot the window could not
  advance until the node caught up — minutes of frozen or bogus PER, and an AFH decision based on
  it. The window is now reset when the sequence rolls back, when TX resumes, and when AFH hops.
  *(节点序号回绕此前未处理,重启后窗口长时间无法推进,PER 冻结甚至失真并影响跳频决策。现在在
  序号回退、暂停恢复与跳频时都会重置窗口。)*
- **`TDMA_PKT_CMD_OTA` and the 54-byte legacy provisioning layout are gone (删除 OTA 命令码与旧配网布局)**.
  The NFC payload is 46 bytes with its CRC over the preceding 42 bytes.
  *(NFC 配网包改为 46 字节,CRC 覆盖前 42 字节。)*
- **Kconfig**: new `TDMA_BEACON_LOSS_TIMEOUT_MS`; `TDMA_SLOT_STEP_US` renamed in the menu to
  `Fallback time slot step per node` and re-documented, since the master derives the real step.
  *(新增信标丢失超时;`TDMA_SLOT_STEP_US` 菜单名与说明改为"兜底值"。)*

## 1.1.3
- **24 Mbps rate lock migrated to the per-peer API (24 Mbps 速率锁定迁移到逐 peer 接口)**: the
  component now calls `esp_now_set_peer_rate_config()` for every peer it installs — node peers,
  the gateway peer and the broadcast beacon peer — instead of the interface-wide
  `esp_wifi_config_espnow_rate()`, which is deprecated since IDF 5.2 and **removed in IDF 6.0**.
  A peer whose rate cannot be locked is not registered and does not start, because at the 1 Mbps
  default its packets would overrun the slot frame. The beacon peer only warns, since a 22-byte
  beacon at 1 Mbps still fits inside the frame.
  The `(phymode, rate)` pairing is `WIFI_PHY_MODE_11G` + `WIFI_PHY_RATE_24M` (24 Mbps is a legacy
  OFDM rate). This pairing is **not documented anywhere in the ESP-IDF documentation** — it was
  reported upstream as [espressif/esp-idf#18766](https://github.com/espressif/esp-idf/issues/18766),
  which is still open — so it was **verified on ESP32-S3 hardware** instead: the driver accepts it
  and `esp_now_set_peer_rate_config()` returns `ESP_OK`.
  *(无法锁定速率的 peer 不予注册、不予启动,因为 1 Mbps 默认值下其数据包会贯穿时隙帧;信标 peer
  仅告警,因为 22 字节信标在 1 Mbps 下仍装得进帧。配对为 `WIFI_PHY_MODE_11G` + `WIFI_PHY_RATE_24M`
  (24 Mbps 是 11g legacy OFDM 速率)。该配对在 ESP-IDF 文档中**无任何记载**——已作为
  espressif/esp-idf#18766 上报上游且仍未关闭——因此改为**在 ESP32-S3 实机上验证**:驱动接受该配对,
  `esp_now_set_peer_rate_config()` 返回 `ESP_OK`。)*
- **Manifest (清单)**: minimum IDF raised to `>= 5.2.0` (the version that introduced the per-peer
  API) and the `< 6.0.0` upper bound dropped, since the component is now forward-compatible with
  IDF 6.0. *(最低版本提到 `>= 5.2.0`(逐 peer 接口的引入版本),并移除 `< 6.0.0` 上限——组件已向前
  兼容 IDF 6.0。)*
- **Radio configuration ownership (射频配置归属)**: the component now pins the protocol bitmap,
  bandwidth and power-save mode **only when it performed the Wi-Fi initialization itself**. If the
  application brought Wi-Fi up, those settings belong to the application: the component verifies
  them instead of overriding them, logging an error for every premise that does not hold (HT20,
  11G/11N enabled, LR disabled, power save off).
  *(组件现在**仅在自己完成 Wi-Fi 初始化时**固定协议位图、带宽与省电模式。若 Wi-Fi 由应用启动,这些
  设置归应用所有:组件改为校验而非覆盖,并对每条不成立的前提报错。)*
- **Documentation correction (文档更正)**: the 1.0.7 entry claimed the OTA state had been removed
  from the core state machine. It had not been; the field and the state were still there and still
  drove transitions. That removal is now planned for 1.2.0, and the 1.0.7 wording has been corrected
  to say what actually happened.
  *(修正 1.0.7 的条目:它声称已把 OTA 状态从核心状态机中移除,实际并未移除——字段与状态都还在,
  且仍在驱动状态跳转。该移除改为在 1.2.0 完成,1.0.7 的措辞已改为与事实一致。)*
- No on-air format change and no public API removal: 1.1.3 is drop-in compatible with 1.1.2.
  *(无空口格式变更、无公开接口删除:1.1.3 可直接替换 1.1.2。)*

## 1.1.2
- **Slave-side robustness: the same "fail loudly" treatment the master got in 1.1.0
  (从节点侧健壮性:与 1.1.0 主节点侧同等的"失败即显式报错")**:
  - `esp_tdma_slave_set_config_ex()` now checks `esp_now_add_peer()` for the gateway peer.
    Unicast ESP-NOW requires a peer entry, so a failure there means the node can never
    transmit; previously the error was discarded and the node ran as a silent dead node.
    *(从节点配置现在检查网关 peer 的安装结果。单播 ESP-NOW 必须有 peer 条目,安装失败意味着
    该节点永远发不出数据;此前该错误被直接丢弃,节点会以"静默死节点"的形态运行。)*
  - **Behaviour change:** `esp_tdma_slave_start()` returns `ESP_ERR_INVALID_STATE` when no
    gateway peer is installed, instead of always returning `ESP_OK`.
    *(**行为变更**:未成功安装网关 peer 时 `esp_tdma_slave_start()` 返回 `ESP_ERR_INVALID_STATE`,
    不再无条件返回 `ESP_OK`。)*
  - Checked the remaining unchecked calls: `esp_now_register_recv_cb()` (master and slave init),
    `xTaskCreatePinnedToCore()` (slave init now fails with `ESP_ERR_NO_MEM`),
    `esp_timer_start_once()` (slot arming) and the beacon `esp_now_send()` — a failed beacon
    send used to cost every node a frame with no trace in the log.
    *(补齐其余未检查的调用:`esp_now_register_recv_cb()`(主/从初始化)、`xTaskCreatePinnedToCore()`
    (从节点初始化失败时返回 `ESP_ERR_NO_MEM`)、`esp_timer_start_once()`(时隙定时器装载)以及信标
    的 `esp_now_send()`——此前信标发送失败会让全网丢一帧且日志里毫无痕迹。)*
  - Added NULL guards to the public entry points that memcpy from caller pointers:
    `esp_tdma_master_register_node()`, `esp_tdma_master_get_node_mac()` and
    `esp_tdma_slave_set_config_ex()`.
    *(为会从调用方指针 memcpy 的公开接口补上 NULL 防护。)*
- **README trimmed (README 精简)**: the radio-parameter notes and the 11-row transmit-power
  quantisation table were **removed from the README entirely**. They documented ESP-IDF API
  semantics and internal pinning rather than what a user of this component needs to decide, and a
  duplicated IDF table would silently rot. What the component actually does is unchanged and is
  described in the source comments and in this changelog. The two constraints users actually hit —
  the encrypted-peer node-count cap and the unassociated-station requirement for AFH — stay at the
  top of the page in compressed form.
  *(README 删除了射频参数说明与 11 行发射功率量化表:它们讲的是 ESP-IDF 的 API 语义与组件内部固定项,
  而非使用者需要做的决策,且复制 IDF 的表格只会悄悄过时。组件实际行为未变,改由源码注释与本更新日志
  描述。用户真正会踩的两条约束(加密配对节点数上限、AFH 需未关联 AP)压缩后保留在页面顶部。)*
- **Manifest**: added an `issues` link for the registry page. *(清单补充 `issues` 链接。)*
- No API removal and no on-air format change: 1.1.2 is drop-in compatible with 1.1.1 apart from the
  stricter `esp_tdma_slave_start()` failure signalling described above.
  *(无接口删除、无空口格式变更:除上述 `esp_tdma_slave_start()` 更严格的失败信号外,1.1.2 可直接替换 1.1.1。)*

## 1.1.1
- **Pinned RF parameters the TDMA schedule depends on (固定时序所依赖的射频参数)**: when the
  component owns the Wi-Fi initialization it now also sets the protocol bitmap to
  `11B | 11G | 11N` and the bandwidth to `HT20`, and logs a single confirmation line. The
  bitmap deliberately excludes `WIFI_PROTOCOL_LR`: the proprietary long-range mode is mutually
  exclusive with OFDM and therefore cannot coexist with the 24 Mbps data rate. The bandwidth
  matters because the AFH channels 1/6/11 are only non-overlapping at HT20 — at HT40 a channel
  spans its neighbours and the hopping premise collapses.
  *(组件负责 Wi-Fi 初始化时,现会显式固定协议位图 `11B|11G|11N` 与带宽 `HT20`,并打印一行确认日志。
  位图刻意排除 `WIFI_PROTOCOL_LR`——该长距离模式与 OFDM 互斥,无法与 24 Mbps 速率共存;带宽则因为
  AFH 的 1/6/11 只在 HT20 下互不重叠,40 MHz 会横跨邻道、使跳频前提失效。)*
- **AFH re-checks its own premise at hop time (跳频时复检前提)**: the master now re-reads the
  bandwidth immediately before switching channel and logs an error if it is no longer HT20, so a
  runtime change cannot silently turn a hop into a move onto an equally interfered channel.
  *(主节点在换信道前会重新读取带宽,若非 HT20 则报错,避免运行时改动悄悄让跳频落到同样受干扰的信道。)*
- **Transmit power documented (发射功率文档化)**: the READMEs now state that transmit power is an
  application decision and document the full quantisation table of
  `esp_wifi_set_max_tx_power()`. In particular set value 32 yields **7.0 dBm, not 8 dBm** —
  8 dBm is not reachable at all; the nearest steps are 7.0 dBm and 8.5 dBm.
  *(README 说明发射功率属应用决策,并给出完整量化映射表:设定值 32 实得 7.0 dBm 而非 8 dBm,
  8 dBm 不在可取值集合内。)*
- No API or on-air format change: 1.1.1 is drop-in compatible with 1.1.0.
  *(无 API 与空口格式变更:1.1.1 与 1.1.0 可直接替换。)*

## 1.1.0
- **Robustness: fail loudly instead of silently (健壮性:失败即显式报错)**:
  - The 24 Mbps PHY-rate lock is now checked and **fatal on failure**. ESP-NOW defaults to
    1 Mbps, where a 235-byte packet occupies ~1.88 ms of airtime and overruns the slot frame;
    a silent fallback used to corrupt the whole TDMA schedule with no visible error.
    *(24 Mbps 速率锁定改为检查返回值并在失败时中止初始化:ESP-NOW 默认 1 Mbps,235 字节单包空口
    约 1.88 ms,会贯穿整个时隙帧;旧实现静默回退会导致全网时序崩坏且无任何报错。)*
  - `esp_tdma_master_register_node()` now installs the ESP-NOW peer **before** committing the
    registry entry, and escalates the failure to `ESP_LOGE`. Previously a node was marked
    registered even when `esp_now_add_peer()` failed, leaving a phantom "online" node whose
    traffic could never be delivered. *(节点登记改为「peer 安装成功后才写入登记册」,失败升级为
    ESP_LOGE;此前 peer 安装失败仍会标记为已注册,形成永远收不到数据的假在线节点。)*
  - `esp_tdma_master_init()` rejects a `target_node_count` larger than the ESP-NOW
    **encrypted-peer capacity** (`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM`, default 7, max 17;
    ESP32-C2 max 4). Each node is an encrypted peer, so the previous "up to 15" claim was
    silently capped at 7 by the IDF default. *(主节点初始化会校验目标节点数不超过 ESP-NOW 加密
    配对容量(默认 7、最大 17);此前「最多 15 节点」的说法在默认配置下实际只能到 7。)*
  - Both AFH channel switches (master and slave) now check `esp_wifi_set_channel()` and act on
    failure: the master aborts and re-arms the hop instead of desynchronising the network, and
    the slave keeps its target and retries on the next beacon instead of silently staying put.
    `esp_wifi_set_channel()` cannot change the channel while the station is associated with an
    AP, and `esp_tdma_master_init()` now probes that capability at startup.
    *(主/从节点跳频均检查换信道返回值:主节点失败则中止并重新计时而非让全网失步;从节点保留目标
    并在下一个信标重试。`esp_tdma_master_init()` 新增启动时换信道能力探测。)*
  - The AFH trigger now requires a successful `esp_wifi_get_channel()` read, so the network can
    no longer be hopped blind from an unknown channel. *(AFH 触发前必须成功读到当前信道,避免从
    未知信道盲目跳频。)*
- **Power-save mode pinned (省电模式显式化)**: `WIFI_PS_NONE` is set explicitly when the
  component owns the Wi-Fi initialization, so the radio is never parked in modem sleep while the
  slot timer depends on beacon reception. *(组件负责初始化 Wi-Fi 时显式设置 `WIFI_PS_NONE`。)*
- **RSSI reported with the PER window (PER 窗口附带 RSSI)**: the per-node report now includes the
  last and mean RSSI taken from `esp_now_recv_info_t::rx_ctrl`, giving the channel-quality input
  that a PER-only AFH decision lacks. *(每节点 PER 上报新增末次与平均 RSSI,取自收包回调的
  `rx_ctrl`,为纯 PER 的跳频决策补上信道质量输入。)*
- **Documentation corrections (文档修正)**: the package length comment in `tdma_protocol.h`
  is corrected (54, not 38 bytes); the README now defines what the reported "jitter" actually
  measures (end-to-end slot arrival deviation, not slot-timer accuracy); the AFH countdown
  wording no longer claims that a node missing the entire warning window is still recalled; the
  `tdma_data_pkt_t` payload ceiling is documented as a deliberate design choice rather than a
  protocol limit (ESP-NOW v2.0 raises it to 1470 bytes); and the node example's slot offset is
  made consistent with the gateway example. *(修正 NFC 包长注释、补充 jitter 指标口径定义、修正
  跳频预警窗措辞、澄清 242 字节上限为设计选择而非协议上限、对齐示例时隙偏移。)*
- **IDF version bound (IDF 版本上限)**: the manifest now declares `idf: ">=5.0.0,<6.0.0"` because
  `esp_wifi_config_espnow_rate()` (still used for the rate lock) is removed in ESP-IDF v6.0.
  *(因 `esp_wifi_config_espnow_rate()` 在 v6.0 被移除,清单加上 `<6.0.0` 上限。)*
- **Adaptive Slot Step & Runtime Node Count (自适应时隙步长与运行时节点数)**:
  Ported the master's runtime slot-step algorithm. The slot step is now
  `(CONFIG_TDMA_BEACON_INTERVAL_MS * 1000 - CONFIG_TDMA_BEACON_TAIL_MARGIN_US) / target_node_count`,
  clamped to `CONFIG_TDMA_SLOT_STEP_MIN_US`. Adds `esp_tdma_master_set_target_node_count()`,
  `esp_tdma_master_get_target_node_count()` and `esp_tdma_master_get_slot_step_us()`.
  *(引入自适应时隙步长:时隙步长 = (信标周期 - 尾部余量) / 目标节点数,并按最小保护带钳位;
  新增目标节点数运行时读写与时隙步长查询接口。)*
- **Beacon Authentication (信标 CMAC 验签)**: Beacons now carry a 4-byte AES-128-CMAC tag
  (`tdma_beacon_t::cmac_tag`, beacon grows to 22 bytes). The master signs beacons after
  `esp_tdma_master_set_beacon_key()`; slaves provisioned with a `beacon_cmac_key` silently
  drop beacons that fail verification. *(信标携带 CMAC 标签,网关签名、节点验签,抵御伪造信标。)*
- **Replay Protection (重放保护)**: Slaves reject beacons whose `global_time_us` does not
  advance, and automatically resynchronise when the master reboots or restarts its clock.
  *(节点拒绝时间戳不前进的信标,并在网关重启后自动重新对齐基线。)*
- **Dual-Key NFC Provisioning (双密钥配网)**: `tdma_nfc_payload_t` is now 54 bytes, carrying
  both `node_unicast_lmk` and `beacon_cmac_key` in place of the 1.0.x single 16-byte key.
  *(配网包由 38 字节单密钥升级为 54 字节双密钥:单播加密密钥 + 信标验签密钥。)*
- **Node Registry Query APIs (节点登记册查询接口)**: `esp_tdma_master_get_node_mac()`,
  `esp_tdma_master_get_node_lmk()` (for re-provisioning without rotating keys) and
  `esp_tdma_master_is_node_online()` (6 s heartbeat timeout).
- **24 Mbps PHY Rate Lock (物理速率锁定)**: ESP-NOW is pinned to `WIFI_PHY_RATE_24M`.
  *(1 Mbps 下 235 字节单包空口时长高达 1.88 ms,远超 700 µs 时隙并会贯穿后续节点时隙;
  锁定 24 Mbps 后压缩至约 78 µs,是 TDMA 时序能够闭环的物理前提。)*
- **Registration Handshake Fix (注册握手修复)**: REG_ACK is now transmitted whenever it is
  pending instead of being gated on the slave still being in `TDMA_STATE_REGISTERING`.
  *(旧逻辑下若信标已把节点状态推到 RUNNING,REG_ACK 将永不发出,节点永远无法完成注册。)*
- **RX Robustness (接收健壮性)**: the master drops data packets whose `payload_len` exceeds
  the actually received byte count; `safe_err_to_name()` guards against NULL error strings;
  the SPSC ring buffer now asserts a power-of-two capacity, which its bitmask wrap-around
  addressing silently depends on.
- **OTA Callback Restore (OTA 后回调恢复)**: `esp_tdma_restore_recv_cb()` re-installs the TDMA
  packet dispatcher after the managed `espressif/esp-now` component overwrote the raw receive
  callback. *(OTA 完成后用于恢复 TDMA 收包分发。)*
- **Configurable TX Task Placement (发送任务放置可配置)**: new Kconfig options
  `TDMA_TX_TASK_CORE` / `TDMA_TX_TASK_PRIORITY` / `TDMA_TX_TASK_STACK`,
  `TDMA_PER_REPORT_PACKETS`, `TDMA_BEACON_TAIL_MARGIN_US`, `TDMA_SLOT_STEP_MIN_US`.
  These expose the variables needed for slot-timing experiments (core, priority,
  evaluation cadence, frame geometry) without recompiling the component.
- **API compatibility (API 兼容)**: `esp_tdma_slave_set_config()` keeps its 1.0.x 4-argument
  signature (beacon authentication disabled) and delegates to the new
  `esp_tdma_slave_set_config_ex()`. Existing applications keep compiling unchanged.
- **Air-format break (空口格式变更)**: beacon 18 -> 22 bytes, NFC payload 38 -> 54 bytes.
  A 1.1.0 master is **not** interoperable with 1.0.x slaves, and vice versa — update the whole
  fleet together. *(空口不兼容,必须全网同版本升级。)*

## 1.0.7
- **Architecture Decoupling (架构解耦与重构)**:
  - Decoupled Wi-Fi & ESP-NOW auto-initialization. Added `.skip_wifi_init` configurations and `ESP_TDMA_AUTO_INIT_WIFI` Kconfig option. *(解耦 Wi-Fi 与 ESP-NOW 自动初始化,增加 `.skip_wifi_init` 配置以及相应的 Kconfig 选项。)*
  - Decoupled data queue policies. Added selectable FIFO or DISCARD_STALE policies to allow custom application queueing logic. *(解耦数据排队策略,支持在入队时传入 FIFO 或零延迟覆盖(DISCARD_STALE)模式。)*
  - Decoupled application business states: introduced a generic system-state notification callback plus decoupled link-state updates. Correction: contrary to what this entry originally claimed, the OTA state was NOT removed from the core state machine in 1.0.7 — `TDMA_STATE_OTA` and the beacon `sys_state` field were still present and still drove slave transitions. Their removal is completed in 1.2.0. *(解耦业务状态机:引入通用系统状态通知回调与解耦的链路状态更新。更正:与本条最初的说法相反,1.0.7 并未把 OTA 状态从核心状态机中移除——TDMA_STATE_OTA 与信标 sys_state 字段都还在,且仍在驱动从节点状态跳转。其移除在 1.2.0 完成。)* *(解耦业务状态机,将 OTA 从链路同步状态机中剥离,仅通过回调回调通知高级系统状态更新。)*
- **Bilingual Documentation (中英双语自述)**: Synchronized examples and changelog in both English and Chinese. *(全面同步了示例说明和更新日志的双语支持。)*
- **Backward Compatibility (向后兼容层)**: Fully preserved legacy structures, callbacks, and the original 2-argument enqueue function signature to guarantee zero disruption to existing projects. *(完全保留原状态回调和双参数入队函数,保障主项目编译零报错、稳定运行。)*

## 1.0.6
- **Multilingual Support (多语言支持)**: Added `readme_zh.md` to support English/Chinese toggle on the registry page. *(新增 `readme_zh.md` 支持组件库网页端的英/中双语切换。)*
- **Bilingual Updates (双语日志与代码注释)**: Added Chinese comments to example codes and translated changelog. *(为示例项目代码添加了中文注释,并翻译了更新日志。)*

## 1.0.5
- **Changelog Separation (独立更新日志)**: Refactored version history into a dedicated `CHANGELOG.md` file to enable the Changelog tab in the registry. *(将版本历史整理至独立的 `CHANGELOG.md` 文件中,启用组件库独立的 Changelog 选项卡。)*

## 1.0.4
- **Registry Version Sync (组件库版本同步)**: Synchronized component version with ESP Component Registry release. *(同步代码版本号与组件库发布版。)*

## 1.0.3
- **Example Projects Added (添加示例程序)**: Added `gateway_example` and `node_example` under the `examples/` directory to show how to use the TDMA component. *(在 `examples/` 目录下新增了网关和从节点示例,展示组件的使用方法。)*
- **Example Documentation (示例说明文档)**: Added example `README.md` documentation for both Gateway and Node roles. *(为网关和从节点示例分别编写了 `README.md` 说明文件。)*

## 1.0.2
- **Homepage Migration (迁移主页及仓库)**: Migrated component homepage and repository URL to `https://github.com/yangcong-bit/esp-now-tdma`. *(迁移组件主页及开源仓库地址。)*

## 1.0.1
- **Zero-Latency Stale Frame Discarding (零延迟数据丢弃策略)**: Added backlog cleanup in the Slave's TX loop. Discards older frames and keeps only the newest frame, guaranteeing zero accumulation latency (ideal for high-rate sensors like IMUs). *(在从节点的发送循环中加入过载清理机制,自动丢弃旧帧保留最新单帧,消除高频传感器如 IMU 带来的累积延迟。)*
- **Automatic Wi-Fi & ESP-NOW Initialization (免样板无线初始化)**: Encapsulated Wi-Fi (STA mode) and ESP-NOW startup boilerplate inside `init_wifi_and_espnow()`. *(将 STA 模式 Wi-Fi 及 ESP-NOW 初始化封装进组件内部,免去应用层手动编写样板代码。)*
- **Dynamic Key Exchange & Registration (动态密钥交换与注册)**: Encapsulated `aes_lmk` in `tdma_reg_ack_t`, allowing the Master to dynamically register and modify peers with encryption upon joining. *(在注册响应包中携带 AES 局部主密钥,允许网关在节点加入时动态配置加密 Peer。)*
- **Dynamic State Synchronization (状态自动跳变)**: Slave nodes now autonomously transition to `RUNNING`, `REGISTERING`, or `OTA` based on the Master's broadcasted Beacon status (`sys_state`). *(节点根据接收到的 Beacon 系统状态标志,自动跳变至 `RUNNING`、`REGISTERING` 或 `OTA` 状态。)*
- **Console Log Flooding Prevention (控制台日志防刷限流)**: Added log throttling for `esp_now_send` failures in the Slave's TX task (logs only the first 5 errors and then throttles to once every 100 failures). *(限制发包失败日志打印频率,前 5 次错误正常输出,之后每 100 次失败才打印一次。)*
- **Enhanced Telemetry & Diagnostics (增强型遥测与链路诊断)**: Upgraded `TX Task SLOT REACHED` to output ring buffer and transmission counters (`rb_empty`, `send_ok`, `send_fail`, `reg_ack_ok/fail`), and added Master RX diagnostics logs. *(诊断日志输出新增发送计数和环形队列状态,网关端新增注册回调日志。)*
- **UTF-8 Transcoding (编码转换)**: Transcoded source files to clean UTF-8. *(将所有源文件转码为 UTF-8 编码。)*

## 1.0.0
- Initial release. *(初始版本发布。)*