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;}
|
.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 {
|
footer {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 0.7rem;
|
font-size: 0.7rem;
|
||||||
@ -275,6 +311,8 @@
|
|||||||
<div class="value-wrapper">
|
<div class="value-wrapper">
|
||||||
<div class="pressure-value" id="currentPressureDisplay">0.0 атм</div>
|
<div class="pressure-value" id="currentPressureDisplay">0.0 атм</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="pump-state" id="currentPumpState"></div>
|
||||||
|
|
||||||
|
|
||||||
<div class="sliders-panel">
|
<div class="sliders-panel">
|
||||||
<div class="slider-group">
|
<div class="slider-group">
|
||||||
@ -295,7 +333,7 @@
|
|||||||
|
|
||||||
<button class="save-btn" id="saveButton">💾 СОХРАНИТЬ УСТАНОВКИ</button>
|
<button class="save-btn" id="saveButton">💾 СОХРАНИТЬ УСТАНОВКИ</button>
|
||||||
</div>
|
</div>
|
||||||
<footer>⚡ IoT контроллер давления | © Vladislav Kan <thek4n@yandex.ru></footer>
|
<footer>⚡IoT контроллер давления | © Vladislav Kan <thek4n@yandex.ru></footer>
|
||||||
</div>
|
</div>
|
||||||
<div id="toastMsg" class="toast-msg">✓ Пороги успешно сохранены</div>
|
<div id="toastMsg" class="toast-msg">✓ Пороги успешно сохранены</div>
|
||||||
|
|
||||||
@ -315,6 +353,7 @@
|
|||||||
const minSpan = document.getElementById('minThresholdVal');
|
const minSpan = document.getElementById('minThresholdVal');
|
||||||
const maxSpan = document.getElementById('maxThresholdVal');
|
const maxSpan = document.getElementById('maxThresholdVal');
|
||||||
const pressureDisplay = document.getElementById('currentPressureDisplay');
|
const pressureDisplay = document.getElementById('currentPressureDisplay');
|
||||||
|
const currentState = document.getElementById('currentPumpState');
|
||||||
const saveBtn = document.getElementById('saveButton');
|
const saveBtn = document.getElementById('saveButton');
|
||||||
const toast = document.getElementById('toastMsg');
|
const toast = document.getElementById('toastMsg');
|
||||||
|
|
||||||
@ -510,6 +549,22 @@
|
|||||||
ctx.stroke();
|
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() {
|
async function fetchPressure() {
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/pressure');
|
const response = await fetch('/pressure');
|
||||||
@ -735,6 +790,7 @@
|
|||||||
function startPolling() {
|
function startPolling() {
|
||||||
// Запускаем опрос давления каждые 500 мс
|
// Запускаем опрос давления каждые 500 мс
|
||||||
pollingInterval = setInterval(fetchPressure, 500);
|
pollingInterval = setInterval(fetchPressure, 500);
|
||||||
|
pollingInterval = setInterval(fetchState, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopPolling() {
|
function stopPolling() {
|
||||||
|
|||||||
@ -9,13 +9,24 @@ dependencies:
|
|||||||
registry_url: https://components.espressif.com/
|
registry_url: https://components.espressif.com/
|
||||||
type: service
|
type: service
|
||||||
version: 1.7.19~2
|
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:
|
idf:
|
||||||
source:
|
source:
|
||||||
type: idf
|
type: idf
|
||||||
version: 6.1.0
|
version: 6.1.0
|
||||||
direct_dependencies:
|
direct_dependencies:
|
||||||
- espressif/cjson
|
- espressif/cjson
|
||||||
|
- espressif/mdns
|
||||||
- idf
|
- idf
|
||||||
manifest_hash: 626fd43651c3fd7f446de49c6321e4d29d1ea2ce423ef88701f30386e340d0f8
|
manifest_hash: aacec634967d1d3809618f54875956325d8c0200c299b5c0a55b6f3128ef2854
|
||||||
target: esp32
|
target: esp32
|
||||||
version: 3.0.0
|
version: 3.0.0
|
||||||
|
|||||||
@ -14,4 +14,5 @@ dependencies:
|
|||||||
# # `public` flag doesn't have an effect dependencies of the `main` component.
|
# # `public` flag doesn't have an effect dependencies of the `main` component.
|
||||||
# # All dependencies of `main` are public by default.
|
# # All dependencies of `main` are public by default.
|
||||||
# public: true
|
# 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.h"
|
||||||
#include "esp_adc/adc_cali_scheme.h"
|
#include "esp_adc/adc_cali_scheme.h"
|
||||||
#include "esp_task_wdt.h"
|
#include "esp_task_wdt.h"
|
||||||
|
#include "mdns.h"
|
||||||
|
|
||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
@ -57,6 +58,8 @@
|
|||||||
#define PRIORITY_CONTROL 2
|
#define PRIORITY_CONTROL 2
|
||||||
#define PRIORITY_SENSOR 3
|
#define PRIORITY_SENSOR 3
|
||||||
|
|
||||||
|
#define MDNS_DOMAIN "pumpctl"
|
||||||
|
|
||||||
static adc_oneshot_unit_handle_t adc_handle;
|
static adc_oneshot_unit_handle_t adc_handle;
|
||||||
static adc_cali_handle_t cali_handle;
|
static adc_cali_handle_t cali_handle;
|
||||||
static bool is_calibrated = false;
|
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;
|
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) {
|
esp_err_t adc_init(void) {
|
||||||
adc_oneshot_unit_init_cfg_t init_config = {
|
adc_oneshot_unit_init_cfg_t init_config = {
|
||||||
.unit_id = ADC_UNIT_1,
|
.unit_id = ADC_UNIT_1,
|
||||||
@ -163,7 +180,7 @@ esp_err_t adc_init(void) {
|
|||||||
static esp_err_t pump_init(void) {
|
static esp_err_t pump_init(void) {
|
||||||
gpio_config_t io_conf = {
|
gpio_config_t io_conf = {
|
||||||
.pin_bit_mask = (1ULL << CONFIG_PUMP_PIN),
|
.pin_bit_mask = (1ULL << CONFIG_PUMP_PIN),
|
||||||
.mode = GPIO_MODE_OUTPUT,
|
.mode = GPIO_MODE_INPUT_OUTPUT,
|
||||||
.intr_type = GPIO_INTR_DISABLE,
|
.intr_type = GPIO_INTR_DISABLE,
|
||||||
.pull_down_en = 1,
|
.pull_down_en = 1,
|
||||||
.pull_up_en = 0,
|
.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);
|
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) {
|
static esp_err_t save_thresholds_handler(httpd_req_t *req) {
|
||||||
char *content = NULL;
|
char *content = NULL;
|
||||||
if (receive_http_content(req, &content) != ESP_OK) {
|
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");
|
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 = {
|
httpd_uri_t get_thresholds = {
|
||||||
.uri = "/thresholds",
|
.uri = "/thresholds",
|
||||||
.method = HTTP_GET,
|
.method = HTTP_GET,
|
||||||
@ -532,11 +565,14 @@ void app_main(void) {
|
|||||||
}
|
}
|
||||||
ESP_ERROR_CHECK(ret);
|
ESP_ERROR_CHECK(ret);
|
||||||
|
|
||||||
|
|
||||||
load_thresholds_from_nvs();
|
load_thresholds_from_nvs();
|
||||||
ESP_ERROR_CHECK(adc_init());
|
ESP_ERROR_CHECK(adc_init());
|
||||||
ESP_ERROR_CHECK(pump_init());
|
ESP_ERROR_CHECK(pump_init());
|
||||||
wifi_init_softap();
|
wifi_init_softap();
|
||||||
|
|
||||||
|
// ESP_ERROR_CHECK(start_mdns_service());
|
||||||
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
|
||||||
xTaskCreate(vReadSensorTask, "read_sensor", 2048, NULL, PRIORITY_SENSOR, NULL);
|
xTaskCreate(vReadSensorTask, "read_sensor", 2048, NULL, PRIORITY_SENSOR, NULL);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user