feat: pump state
This commit is contained in:
parent
c13b47a276
commit
ef4cdc53a2
@ -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 @@
|
||||
<div class="value-wrapper">
|
||||
<div class="pressure-value" id="currentPressureDisplay">0.0 атм</div>
|
||||
</div>
|
||||
<div class="pump-state" id="currentPumpState"></div>
|
||||
|
||||
|
||||
<div class="sliders-panel">
|
||||
<div class="slider-group">
|
||||
@ -295,7 +333,7 @@
|
||||
|
||||
<button class="save-btn" id="saveButton">💾 СОХРАНИТЬ УСТАНОВКИ</button>
|
||||
</div>
|
||||
<footer>⚡ IoT контроллер давления | © Vladislav Kan <thek4n@yandex.ru></footer>
|
||||
<footer>⚡IoT контроллер давления | © Vladislav Kan <thek4n@yandex.ru></footer>
|
||||
</div>
|
||||
<div id="toastMsg" class="toast-msg">✓ Пороги успешно сохранены</div>
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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'
|
||||
|
||||
38
main/main.c
38
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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user