Files
zh_nrf24_gateway/README.md
T
2026-10-31 09:18:55 +03:00

4.8 KiB
Executable File

esp_component_template

esp_component_template

#include <stdio.h>
#include <string.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_event.h"

#include "zh_nrf24_gateway.h"
// #include "zh_nrf24_config.h"

static const char *TAG = "MAIN";

#define GW_CHANNEL 120
#define GW_ADDRESS 0xDDEEFF

static const zh_nrf_gateway_config_t s_gw_config = {
    .spi_host     = SPI2_HOST,
    .pin_sck      = 18,
    .pin_miso     = 19,
    .pin_mosi     = 23,
    .pin_csn      = 17,
    .pin_ce       = 16,
    .pin_irq      = 4,
    .channel      = GW_CHANNEL,
    .address      = GW_ADDRESS,
    .spi_clock_hz = 0,
};

static void dump_bindings(const char *reason)
{
    zh_nrf_gateway_binding_t tmp[ZH_NRF_GATEWAY_MAX_BINDINGS];
    size_t got = zh_nrf_gateway_bindings_get(tmp, ZH_NRF_GATEWAY_MAX_BINDINGS);

    ESP_LOGI(TAG, "=== Bindings (%s): %u total ===", reason, (unsigned)got);
    for (size_t i = 0; i < got; i++) {
        ESP_LOGI(TAG, "  [%u] id=%u type=%u (%s)",
                 (unsigned)i,
                 tmp[i].id, tmp[i].type,
                 zh_get_nrf24_sensor_type_name((zh_nrf24_sensor_type_t)tmp[i].type));
    }
}

static void gateway_event_handler(void *arg,
                                  esp_event_base_t base,
                                  int32_t id,
                                  void *event_data)
{
    if (base != ZH_NRF_GATEWAY_EVENTS) return;

    switch (id)
    {
    case ZH_NRF_GATEWAY_EVENT_SENSOR_DATA: {
        const zh_nrf24_sensor_transmitted_data_t *d = event_data;
        const char *name = zh_get_nrf24_sensor_type_name((zh_nrf24_sensor_type_t)d->type);

        ESP_LOGI(TAG, "<<< sensor id=%d type=%s battery=%.2fV",
                 d->id, name, d->battery / 100.0);

        switch (d->type)
        {
        case ZH_NRF24_SENSOR_TOUCH_SWITCH:
            ESP_LOGI(TAG, "    button event");
            break;
        case ZH_NRF24_SENSOR_WATER_LEAKAGE:
            ESP_LOGI(TAG, "    status=%s",
                     d->value_1 == ZH_NRF24_SENSOR_STATUS_ALARM ? "ALARM" : "DRY");
            break;
        case ZH_NRF24_SENSOR_OPEN_CLOSE:
            ESP_LOGI(TAG, "    state=%s",
                     d->value_1 == ZH_NRF24_SENSOR_STATUS_OPEN ? "OPEN" : "CLOSE");
            break;
        case ZH_NRF24_SENSOR_PLANT_HUMIDITY:
            ESP_LOGI(TAG, "    humidity=%d%%", d->value_1);
            break;
        case ZH_NRF24_SENSOR_BMP280:
            ESP_LOGI(TAG, "    T=%d C, P=%d", d->value_1, d->value_2);
            break;
        case ZH_NRF24_SENSOR_BME280:
            ESP_LOGI(TAG, "    H=%d%% T=%d C P=%d mmHg",
                     d->value_1, d->value_2, d->value_3);
            break;
        case ZH_NRF24_SENSOR_BME680:
            ESP_LOGI(TAG, "    H=%d%% T=%d C P=%d Q=%d",
                     d->value_1, d->value_2, d->value_3, d->value_4);
            break;
        default:
            break;
        }
        break;
    }
    default:
        break;
    }
}

/* Пример: удаление одной привязки (из MQTT, кнопки, HTTP и т.п.) */
static void demo_manual_delete(void)
{
    uint8_t id   = 5;
    uint8_t type = ZH_NRF24_SENSOR_BME280;

    if (zh_nrf_gateway_binding_exists(id, type)) {
        ESP_LOGI(TAG, "Binding {id=%u, type=%u} exists, deleting", id, type);
        esp_err_t err = zh_nrf_gateway_binding_delete(id, type);
        ESP_LOGI(TAG, "delete → %s", esp_err_to_name(err));
    } else {
        ESP_LOGW(TAG, "Binding {id=%u, type=%u} not found, nothing to do", id, type);
    }
}

void app_main(void)
{
    ESP_LOGI(TAG, "Starting nRF24L01+ gateway");

    ESP_ERROR_CHECK(esp_event_loop_create_default());
    ESP_ERROR_CHECK(esp_event_handler_instance_register(
        ZH_NRF_GATEWAY_EVENTS,
        ESP_EVENT_ANY_ID,
        &gateway_event_handler,
        NULL, NULL));

    ESP_ERROR_CHECK(zh_nrf_gateway_init(&s_gw_config));
    dump_bindings("after init");

    ESP_ERROR_CHECK(zh_nrf_gateway_start());

    ESP_LOGI(TAG, "Gateway running: channel=%d, address=0x%06X",
             GW_CHANNEL, GW_ADDRESS);

    /* Здесь можно, например, ждать команд по MQTT/HTTP и вызывать:
     *
     *   zh_nrf_gateway_binding_delete(id, type)          — точное удаление
     *   zh_nrf_gateway_bindings_delete_by_id(id)         — всё с этим id
     *   zh_nrf_gateway_bindings_delete_by_type(type)     — всё этого типа
     *   zh_nrf_gateway_binding_clear_all()               — полный сброс
     *   zh_nrf_gateway_binding_exists(id, type)          — проверка
     *   zh_nrf_gateway_bindings_get(...) / _count()      — чтение
     *
     * После удаления id сразу доступен для следующего pairing-запроса
     * того же типа.
     */
}