#include "relay_ctrl.h" #include #include "esp_check.h" #include "esp_log.h" static const char *TAG = "relay_ctrl"; typedef struct { bool inited; relay_config_t config[RELAY_CTRL_ID_MAX]; bool states[RELAY_CTRL_ID_MAX]; } relay_ctx_t; static relay_ctx_t s_ctx; static inline int relay_level_from_state(int id, bool on) { return (on == s_ctx.config[id].active_high) ? 1 : 0; } static esp_err_t relay_validate_id(relay_ctrl_id_t relay_id) { ESP_RETURN_ON_FALSE(relay_id >= RELAY_CTRL_ID_1 && relay_id < RELAY_CTRL_ID_MAX, ESP_ERR_INVALID_ARG, TAG, "invalid relay id"); return ESP_OK; } esp_err_t relay_ctrl_init(const relay_config_t config[RELAY_CTRL_ID_MAX]) { uint64_t pin_bit_mask = 0; for (int i = 0; i < RELAY_CTRL_ID_MAX; ++i) { ESP_RETURN_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(config[i].pin), ESP_ERR_INVALID_ARG, TAG, "relay gpio invalid"); s_ctx.config[i] = config[i]; pin_bit_mask |= (1ULL << config[i].pin); } const gpio_config_t io_cfg = { .pin_bit_mask = pin_bit_mask, .mode = GPIO_MODE_OUTPUT, .pull_down_en = GPIO_PULLDOWN_DISABLE, .pull_up_en = GPIO_PULLUP_DISABLE, .intr_type = GPIO_INTR_DISABLE, }; ESP_RETURN_ON_ERROR(gpio_config(&io_cfg), TAG, "relay gpio config failed"); // 根据每个继电器的配置设置初始电平(默认关闭) for (int i = 0; i < RELAY_CTRL_ID_MAX; ++i) { s_ctx.states[i] = false; ESP_RETURN_ON_ERROR(gpio_set_level(s_ctx.config[i].pin, relay_level_from_state(i, false)), TAG, "relay set init level failed"); } s_ctx.inited = true; ESP_LOGI(TAG, "继电器初始化完成(独立电平配置已应用)"); return ESP_OK; } esp_err_t relay_ctrl_set(relay_ctrl_id_t relay_id, bool on) { ESP_RETURN_ON_FALSE(s_ctx.inited, ESP_ERR_INVALID_STATE, TAG, "relay not initialized"); ESP_RETURN_ON_ERROR(relay_validate_id(relay_id), TAG, "invalid relay id"); ESP_RETURN_ON_ERROR(gpio_set_level(s_ctx.config[relay_id].pin, relay_level_from_state(relay_id, on)), TAG, "relay set level failed"); s_ctx.states[relay_id] = on; ESP_LOGI(TAG, "继电器%d -> %s (GPIO%d level=%d)", relay_id + 1, on ? "ON" : "OFF", s_ctx.config[relay_id].pin, relay_level_from_state(relay_id, on)); return ESP_OK; } esp_err_t relay_ctrl_toggle(relay_ctrl_id_t relay_id) { ESP_RETURN_ON_FALSE(s_ctx.inited, ESP_ERR_INVALID_STATE, TAG, "relay not initialized"); ESP_RETURN_ON_ERROR(relay_validate_id(relay_id), TAG, "invalid relay id"); return relay_ctrl_set(relay_id, !s_ctx.states[relay_id]); } esp_err_t relay_ctrl_get(relay_ctrl_id_t relay_id, bool *on_out) { ESP_RETURN_ON_FALSE(s_ctx.inited, ESP_ERR_INVALID_STATE, TAG, "relay not initialized"); ESP_RETURN_ON_FALSE(on_out != NULL, ESP_ERR_INVALID_ARG, TAG, "on_out is null"); ESP_RETURN_ON_ERROR(relay_validate_id(relay_id), TAG, "invalid relay id"); *on_out = s_ctx.states[relay_id]; return ESP_OK; } esp_err_t relay_ctrl_set_all(bool relay1_on, bool relay2_on, bool relay3_on, bool relay4_on) { ESP_RETURN_ON_ERROR(relay_ctrl_set(RELAY_CTRL_ID_1, relay1_on), TAG, "set relay1 failed"); ESP_RETURN_ON_ERROR(relay_ctrl_set(RELAY_CTRL_ID_2, relay2_on), TAG, "set relay2 failed"); ESP_RETURN_ON_ERROR(relay_ctrl_set(RELAY_CTRL_ID_3, relay3_on), TAG, "set relay3 failed"); ESP_RETURN_ON_ERROR(relay_ctrl_set(RELAY_CTRL_ID_4, relay4_on), TAG, "set relay4 failed"); return ESP_OK; }