This commit is contained in:
aZholtikov committed 2026-11-01 07:59:36 +03:00
1 parent 0daf4de19f
commit 036b856a93
2 files changed
+153 -44

No files matched your search

+83 -21
View File
@@ -202,7 +202,7 @@ static esp_err_t nrf_irq_init(void)
}
/* ============================================================
* NVS BINDING TABLE
* NVS BINDING TABLE (internal)
* ============================================================ */
static esp_err_t bindings_load(void)
{
@@ -251,22 +251,30 @@ static esp_err_t bindings_save(void)
return err;
}
/* Caller must hold bindings_mutex. */
static bool bindings_exists_locked(uint8_t id, uint8_t type)
{
for (uint16_t i = 0; i < s_ctx.bindings.count; i++) {
if (s_ctx.bindings.items[i].id == id &&
s_ctx.bindings.items[i].type == type) {
return true;
}
}
return false;
}
/* Caller must hold bindings_mutex. */
static uint8_t bindings_alloc_id(uint8_t type)
{
for (uint16_t id = BINDING_ID_MIN; id <= BINDING_ID_MAX; id++) {
bool used = false;
for (uint16_t i = 0; i < s_ctx.bindings.count; i++) {
if (s_ctx.bindings.items[i].id == id &&
s_ctx.bindings.items[i].type == type) {
used = true;
break;
}
if (!bindings_exists_locked((uint8_t)id, type)) {
return (uint8_t)id;
}
if (!used) return (uint8_t)id;
}
return 0;
}
/* Caller must hold bindings_mutex. */
static esp_err_t bindings_add(uint8_t id, uint8_t type)
{
if (s_ctx.bindings.count >= ZH_NRF_GATEWAY_MAX_BINDINGS) {
@@ -278,6 +286,7 @@ static esp_err_t bindings_add(uint8_t id, uint8_t type)
return bindings_save();
}
/* Caller must hold bindings_mutex. */
static esp_err_t bindings_delete(uint8_t id, uint8_t type)
{
for (uint16_t i = 0; i < s_ctx.bindings.count; i++) {
@@ -319,18 +328,38 @@ bool zh_nrf_gateway_binding_exists(uint8_t id, uint8_t type)
{
if (!s_ctx.initialized || !s_ctx.bindings_mutex) return false;
xSemaphoreTake(s_ctx.bindings_mutex, portMAX_DELAY);
bool found = false;
for (uint16_t i = 0; i < s_ctx.bindings.count; i++) {
if (s_ctx.bindings.items[i].id == id &&
s_ctx.bindings.items[i].type == type) {
found = true;
break;
}
}
bool found = bindings_exists_locked(id, type);
xSemaphoreGive(s_ctx.bindings_mutex);
return found;
}
int zh_nrf_gateway_binding_auto_register(uint8_t id, uint8_t type)
{
if (!s_ctx.initialized || !s_ctx.bindings_mutex) return -ESP_ERR_INVALID_STATE;
if (id < BINDING_ID_MIN || id > BINDING_ID_MAX) return -ESP_ERR_INVALID_ARG;
if (zh_get_nrf24_sensor_payload_size(type) == 0) return -ESP_ERR_INVALID_ARG;
xSemaphoreTake(s_ctx.bindings_mutex, portMAX_DELAY);
int result = 0;
if (!bindings_exists_locked(id, type)) {
esp_err_t err = bindings_add(id, type);
if (err == ESP_OK) {
result = 1;
} else {
if (s_ctx.bindings.count > 0 &&
s_ctx.bindings.items[s_ctx.bindings.count - 1].id == id &&
s_ctx.bindings.items[s_ctx.bindings.count - 1].type == type) {
s_ctx.bindings.count--;
}
result = -(int)err;
}
}
xSemaphoreGive(s_ctx.bindings_mutex);
return result;
}
esp_err_t zh_nrf_gateway_binding_delete(uint8_t id, uint8_t type)
{
if (!s_ctx.initialized) return ESP_ERR_INVALID_STATE;
@@ -526,7 +555,6 @@ static void handle_pairing_request(const uint8_t *data)
return;
}
/* --- ACK delivered → binding is final. Notify the application. --- */
ESP_LOGI(TAG, "Pairing complete: id=%u type=%u", new_id, req_type);
zh_nrf_gateway_binding_t paired = {
@@ -564,6 +592,37 @@ static void handle_sensor_data(const uint8_t *buf, uint8_t len)
len, expected, d.type);
}
/* ----- Auto-register unknown {id, type} ----- */
if (d.id >= BINDING_ID_MIN && d.id <= BINDING_ID_MAX) {
int r = zh_nrf_gateway_binding_auto_register((uint8_t)d.id,
(uint8_t)d.type);
if (r == 1) {
ESP_LOGI(TAG, "Auto-registered sensor: id=%d type=%d (%s)",
d.id, d.type,
zh_get_nrf24_sensor_type_name((zh_nrf24_sensor_type_t)d.type));
zh_nrf_gateway_binding_t b = {
.id = (uint8_t)d.id,
.type = (uint8_t)d.type,
};
esp_err_t perr = esp_event_post(ZH_NRF_GATEWAY_EVENTS,
ZH_NRF_GATEWAY_EVENT_SENSOR_REGISTERED,
&b, sizeof(b),
pdMS_TO_TICKS(100));
if (perr != ESP_OK) {
ESP_LOGW(TAG, "esp_event_post(registered) failed: %s",
esp_err_to_name(perr));
}
} else if (r < 0) {
ESP_LOGW(TAG, "Auto-register failed for id=%d type=%d: %s",
d.id, d.type, esp_err_to_name((esp_err_t)(-r)));
}
} else {
ESP_LOGW(TAG, "Sensor id %d out of range [%d..%d], skipping auto-register",
d.id, BINDING_ID_MIN, BINDING_ID_MAX);
}
/* ----- Parse type-specific fields ----- */
switch (d.type) {
case ZH_NRF24_SENSOR_TOUCH_SWITCH:
break;
@@ -598,11 +657,12 @@ static void handle_sensor_data(const uint8_t *buf, uint8_t len)
break;
}
/* ----- Post SENSOR_DATA ----- */
esp_err_t err = esp_event_post(ZH_NRF_GATEWAY_EVENTS,
ZH_NRF_GATEWAY_EVENT_SENSOR_DATA,
&d, sizeof(d), pdMS_TO_TICKS(100));
if (err != ESP_OK) {
ESP_LOGW(TAG, "esp_event_post failed: %s", esp_err_to_name(err));
ESP_LOGW(TAG, "esp_event_post(data) failed: %s", esp_err_to_name(err));
}
}
@@ -712,10 +772,10 @@ esp_err_t zh_nrf_gateway_init(const zh_nrf_gateway_config_t *config)
nrf_write_register(NRF_REG_CONFIG, 0x00);
nrf_write_register(NRF_REG_EN_AA, 0x01);
nrf_write_register(NRF_REG_EN_RXADDR, 0x01);
nrf_write_register(NRF_REG_SETUP_AW, 0x01);
nrf_write_register(NRF_REG_SETUP_AW, 0x01); /* 3-byte address */
nrf_write_register(NRF_REG_SETUP_RETR, 0xFF);
nrf_write_register(NRF_REG_RF_CH, s_ctx.cfg.channel);
nrf_write_register(NRF_REG_RF_SETUP, 0x26); /* 250 kbps, 0 dBm */
nrf_write_register(NRF_REG_RF_SETUP, 0x26); /* 250 kbps, 0 dBm */
uint8_t addr_bytes[3] = {
(uint8_t)(s_ctx.cfg.address >> 0),
@@ -728,10 +788,12 @@ esp_err_t zh_nrf_gateway_init(const zh_nrf_gateway_config_t *config)
nrf_write_register(NRF_REG_STATUS,
NRF_STATUS_RX_DR | NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT);
/* Enable Dynamic Payload Length */
nrf_activate();
nrf_write_register(NRF_REG_FEATURE, NRF_FEATURE_EN_DPL);
nrf_write_register(NRF_REG_DYNPD, NRF_DYNPD_DPL_P0);
/* Enter RX */
nrf_write_register(NRF_REG_CONFIG, NRF_CONFIG_RX_UNMASKED);
vTaskDelay(pdMS_TO_TICKS(5));
nrf_ce_high();