From ef4cdc53a2bec73718c460bafdaf6fd3e30868b7 Mon Sep 17 00:00:00 2001 From: thek4n Date: Fri, 5 Jun 2026 23:45:32 +0300 Subject: [PATCH] feat: pump state --- assets/index.html | 58 +++++++++++++++++++++++++++++++++++++++++- dependencies.lock | 13 +++++++++- main/idf_component.yml | 3 ++- main/main.c | 38 ++++++++++++++++++++++++++- 4 files changed, 108 insertions(+), 4 deletions(-) diff --git a/assets/index.html b/assets/index.html index 34e9759..6d28ed2 100644 --- a/assets/index.html +++ b/assets/index.html @@ -257,6 +257,42 @@ .toast-msg { white-space: nowrap; font-size: 0.85rem; padding: 8px 20px;} } + .pump-state { + text-align: center; + margin: 0.5rem auto 1.2rem auto; + padding: 0.4rem 0.8rem; + width: fit-content; + border-radius: 20px; + background: #33373b; + font-weight: 700; + font-size: 0.85rem; + letter-spacing: 1px; + color: #959ea6; + font-family: monospace; + text-transform: uppercase; + border: none; + transition: 0.15s linear; + } + + .pump-state.enabled { + background: #00a86b; + color: white; + text-shadow: 0 0 2px rgba(0,0,0,0.3); + animation: pump-glow 1.2s infinite ease; + } + + @keyframes pump-glow { + 0% { + box-shadow: 0 0 0 0 rgba(0, 168, 107, 0.4); + } + 70% { + box-shadow: 0 0 0 6px rgba(0, 168, 107, 0); + } + 100% { + box-shadow: 0 0 0 0 rgba(0, 168, 107, 0); + } + } + footer { text-align: center; font-size: 0.7rem; @@ -275,6 +311,8 @@
0.0 атм
+
+
@@ -295,7 +333,7 @@
-
⚡ IoT контроллер давления | © Vladislav Kan <thek4n@yandex.ru>
+
⚡IoT контроллер давления | © Vladislav Kan <thek4n@yandex.ru>
✓ Пороги успешно сохранены
@@ -315,6 +353,7 @@ const minSpan = document.getElementById('minThresholdVal'); const maxSpan = document.getElementById('maxThresholdVal'); const pressureDisplay = document.getElementById('currentPressureDisplay'); + const currentState = document.getElementById('currentPumpState'); const saveBtn = document.getElementById('saveButton'); const toast = document.getElementById('toastMsg'); @@ -510,6 +549,22 @@ ctx.stroke(); } + async function fetchState() { + try { + const response = await fetch('/state'); + if (!response.ok) { + throw new Error('Failed to fetch state'); + } + const data = await response.json(); + const state = typeof data === 'number' ? data : data.state; + if (typeof state === 'number' && !isNaN(state)) { + state === 1 ? currentState.classList.add("enabled") : currentState.classList.remove("enabled"); + } + } catch (error) { + console.error('Error fetching state:', error); + } + } + async function fetchPressure() { try { const response = await fetch('/pressure'); @@ -735,6 +790,7 @@ function startPolling() { // Запускаем опрос давления каждые 500 мс pollingInterval = setInterval(fetchPressure, 500); + pollingInterval = setInterval(fetchState, 500); } function stopPolling() { diff --git a/dependencies.lock b/dependencies.lock index 6eeb899..41988f7 100644 --- a/dependencies.lock +++ b/dependencies.lock @@ -9,13 +9,24 @@ dependencies: registry_url: https://components.espressif.com/ type: service version: 1.7.19~2 + espressif/mdns: + component_hash: 8bcf12e37c58c1d584aef32a02b92548124c7a3a9fcf548d3235c844a035e0f0 + dependencies: + - name: idf + require: private + version: '>=5.0' + source: + registry_url: https://components.espressif.com/ + type: service + version: 1.11.1 idf: source: type: idf version: 6.1.0 direct_dependencies: - espressif/cjson +- espressif/mdns - idf -manifest_hash: 626fd43651c3fd7f446de49c6321e4d29d1ea2ce423ef88701f30386e340d0f8 +manifest_hash: aacec634967d1d3809618f54875956325d8c0200c299b5c0a55b6f3128ef2854 target: esp32 version: 3.0.0 diff --git a/main/idf_component.yml b/main/idf_component.yml index 7e4db4f..53f7cb9 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -14,4 +14,5 @@ dependencies: # # `public` flag doesn't have an effect dependencies of the `main` component. # # All dependencies of `main` are public by default. # public: true - espressif/cjson: '*' + espressif/cjson: '>=1.7.0' + espressif/mdns: '>=1.11.0' diff --git a/main/main.c b/main/main.c index 39b0ea5..6735abb 100644 --- a/main/main.c +++ b/main/main.c @@ -20,6 +20,7 @@ #include "esp_adc/adc_cali.h" #include "esp_adc/adc_cali_scheme.h" #include "esp_task_wdt.h" +#include "mdns.h" #include "lwip/inet.h" #include "sdkconfig.h" @@ -57,6 +58,8 @@ #define PRIORITY_CONTROL 2 #define PRIORITY_SENSOR 3 +#define MDNS_DOMAIN "pumpctl" + static adc_oneshot_unit_handle_t adc_handle; static adc_cali_handle_t cali_handle; static bool is_calibrated = false; @@ -124,6 +127,20 @@ static esp_err_t send_json_response(httpd_req_t *req, const char *format, ...) { return ESP_OK; } +esp_err_t start_mdns_service() { + esp_err_t err = mdns_init(); + if (err) { + return err; + } + + mdns_hostname_set(MDNS_DOMAIN); + mdns_instance_name_set("Thek4n PumpController"); + + mdns_service_add(NULL, "_http", "_tcp", 80, NULL, 0); + + return ESP_OK; +} + esp_err_t adc_init(void) { adc_oneshot_unit_init_cfg_t init_config = { .unit_id = ADC_UNIT_1, @@ -163,7 +180,7 @@ esp_err_t adc_init(void) { static esp_err_t pump_init(void) { gpio_config_t io_conf = { .pin_bit_mask = (1ULL << CONFIG_PUMP_PIN), - .mode = GPIO_MODE_OUTPUT, + .mode = GPIO_MODE_INPUT_OUTPUT, .intr_type = GPIO_INTR_DISABLE, .pull_down_en = 1, .pull_up_en = 0, @@ -231,6 +248,12 @@ static esp_err_t current_pressure_handler(httpd_req_t *req) { return send_json_response(req, "{\"value\":%d}", sensor_value); } +static esp_err_t pump_state_handler(httpd_req_t *req) { + int pump_enabled = gpio_get_level(CONFIG_PUMP_PIN); + + return send_json_response(req, "{\"state\":%d}", pump_enabled); +} + static esp_err_t save_thresholds_handler(httpd_req_t *req) { char *content = NULL; if (receive_http_content(req, &content) != ESP_OK) { @@ -440,6 +463,16 @@ static void register_http_handlers(httpd_handle_t server) { ESP_LOGE(TAG, "Failed to register GET /pressure handler"); } + httpd_uri_t pump_state = { + .uri = "/state", + .method = HTTP_GET, + .handler = pump_state_handler, + .user_ctx = NULL + }; + if (httpd_register_uri_handler(server, &pump_state) != ESP_OK) { + ESP_LOGE(TAG, "Failed to register GET /state handler"); + } + httpd_uri_t get_thresholds = { .uri = "/thresholds", .method = HTTP_GET, @@ -532,11 +565,14 @@ void app_main(void) { } ESP_ERROR_CHECK(ret); + load_thresholds_from_nvs(); ESP_ERROR_CHECK(adc_init()); ESP_ERROR_CHECK(pump_init()); wifi_init_softap(); + // ESP_ERROR_CHECK(start_mdns_service()); + vTaskDelay(pdMS_TO_TICKS(1000)); xTaskCreate(vReadSensorTask, "read_sensor", 2048, NULL, PRIORITY_SENSOR, NULL);