LED_shit/main/mqtt_comandos.c
2025-11-30 12:29:16 +00:00

330 lines
10 KiB
C

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "esp_log.h"
#include "esp_system.h"
#include "esp_random.h"
#include "mqtt_client.h"
#include "cJSON.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "led_driver.h"
#include "led_effects.h"
#include "eeprom_virtual.h"
#include "eeprom_animacao.h" // animacao + animacao_save()
static const char *TAG = "MQTT_CMD";
// Estes vêm de mqtt_handler.c
extern esp_mqtt_client_handle_t mqtt_client;
extern char topic_resp[64];
// Variável global declarada noutro ficheiro
extern bool modo_bloqueado;
// Modo atual
bool demo_mode = false;
char current_mode[16] = "IDLE";
// Relógio
uint8_t hora_r = 10, hora_g = 40, hora_b = 10;
uint8_t min_r = 10, min_g = 10, min_b = 60;
uint8_t sec_r = 5, sec_g = 5, sec_b = 5;
int clock_speed_ms = 150;
// ======================================================
// FUNÇÃO PRINCIPAL
// ======================================================
void mqtt_comandos_handle(cJSON *root)
{
cJSON *cmd = cJSON_GetObjectItem(root, "cmd");
if (!cJSON_IsString(cmd)) {
ESP_LOGW(TAG, "⚠️ Comando inválido (sem cmd)");
return;
}
const char *c = cmd->valuestring;
ESP_LOGI(TAG, "📩 CMD: %s", c);
// --------------------------------------------------
// LED_ON
// --------------------------------------------------
if (strcmp(c, "LED_ON") == 0) {
led_all_on(50, 50, 50);
}
// --------------------------------------------------
else if (strcmp(c, "LED_OFF") == 0) {
led_all_off();
}
else if (strcmp(c, "CLEAR") == 0) {
led_all_off();
}
// --------------------------------------------------
else if (strcmp(c, "SPIN") == 0) {
int n = led_get_count();
if (n > 0) {
uint16_t p = esp_random() % n;
led_spin_to(p, 2, 12, 80);
}
}
// --------------------------------------------------
else if (strcmp(c, "JACKPOT") == 0) {
led_jackpot_animation();
}
// --------------------------------------------------
else if (strcmp(c, "REBOOT") == 0) {
ESP_LOGW(TAG, "🔁 REBOOT pedido via MQTT");
vTaskDelay(pdMS_TO_TICKS(200));
esp_restart();
}
// --------------------------------------------------
else if (strcmp(c, "STATUS") == 0) {
char resp[160];
snprintf(resp, sizeof(resp),
"{\"uptime\":%lu,\"heap\":%lu}",
(unsigned long)(esp_log_timestamp()/1000),
(unsigned long)esp_get_free_heap_size());
esp_mqtt_client_publish(mqtt_client, topic_resp,
resp, 0, 1, false);
ESP_LOGI(TAG, "📤 STATUS enviado");
}
// ======================================================
// BLOQUEIO
// ======================================================
else if (strcmp(c, "BLOCK") == 0) {
cJSON *v = cJSON_GetObjectItem(root, "value");
if (!cJSON_IsNumber(v)) {
ESP_LOGW(TAG, "BLOCK sem valor numérico");
return;
}
uint8_t novo = (uint8_t)v->valueint;
uint8_t val = novo;
eeprom_virtual_write_bin("blocked", &val, 1);
extern bool modo_bloqueado;
modo_bloqueado = novo;
ESP_LOGW(TAG, "%s", novo ? "BLOQUEADO" : "DESBLOQUEADO");
char resp[64];
snprintf(resp, sizeof(resp), "{\"blocked\":%u}", novo);
esp_mqtt_client_publish(mqtt_client, topic_resp,
resp, 0, 1, false);
}
// ======================================================
// SET_ANIM
// ======================================================
else if (strcmp(c, "SET_ANIM") == 0) {
cJSON *v = cJSON_GetObjectItem(root, "value");
if (!cJSON_IsNumber(v)) {
ESP_LOGW(TAG, "❌ SET_ANIM sem value");
return;
}
uint8_t novo = v->valueint;
animacao_save(novo);
animacao = novo;
ESP_LOGI(TAG, "🎨 Animação alterada para %u", novo);
char resp[64];
snprintf(resp, sizeof(resp), "{\"anim\":%u}", novo);
esp_mqtt_client_publish(mqtt_client, topic_resp, resp, 0, 1, false);
}
// ======================================================
// SET_COLOR
// ======================================================
else if (strcmp(c, "SET_COLOR") == 0) {
cJSON *r = cJSON_GetObjectItem(root, "r");
cJSON *g = cJSON_GetObjectItem(root, "g");
cJSON *b = cJSON_GetObjectItem(root, "b");
if (!cJSON_IsNumber(r) || !cJSON_IsNumber(g) || !cJSON_IsNumber(b)) {
ESP_LOGW(TAG, "❌ SET_COLOR sem r/g/b");
return;
}
int n = led_get_count();
for (int i = 0; i < n; i++) {
led_set_pixel(i, r->valueint, g->valueint, b->valueint);
}
led_show();
}
// ======================================================
// SET_BRIGHT
// ======================================================
else if (strcmp(c, "SET_BRIGHT") == 0) {
cJSON *v = cJSON_GetObjectItem(root, "value");
if (!cJSON_IsNumber(v)) {
ESP_LOGW(TAG, "❌ SET_BRIGHT sem value");
return;
}
led_set_global_brightness(v->valueint);
ESP_LOGI(TAG, "💡 Brightness = %u", v->valueint);
}
// ======================================================
// LED_PIXEL
// ======================================================
else if (strcmp(c, "LED_PIXEL") == 0) {
cJSON *n = cJSON_GetObjectItem(root, "n");
cJSON *r = cJSON_GetObjectItem(root, "r");
cJSON *g = cJSON_GetObjectItem(root, "g");
cJSON *b = cJSON_GetObjectItem(root, "b");
if (!cJSON_IsNumber(n) || !cJSON_IsNumber(r) ||
!cJSON_IsNumber(g) || !cJSON_IsNumber(b)) {
ESP_LOGW(TAG, "❌ LED_PIXEL sem dados");
return;
}
led_set_pixel(n->valueint, r->valueint, g->valueint, b->valueint);
led_show();
}
// ======================================================
// DEMO
// ======================================================
else if (strcmp(c, "DEMO_ON") == 0) {
demo_mode = true;
strncpy(current_mode, "DEMO", sizeof(current_mode));
ESP_LOGI(TAG, "▶ Demo ON");
}
else if (strcmp(c, "DEMO_OFF") == 0) {
demo_mode = false;
strncpy(current_mode, "NORMAL", sizeof(current_mode));
ESP_LOGI(TAG, "⏹ Demo OFF");
}
// ======================================================
// SET_MODE
// ======================================================
else if (strcmp(c, "SET_MODE") == 0) {
cJSON *v = cJSON_GetObjectItem(root, "value");
if (!cJSON_IsString(v)) {
ESP_LOGW(TAG, "❌ SET_MODE sem string");
return;
}
strncpy(current_mode, v->valuestring, sizeof(current_mode));
current_mode[sizeof(current_mode)-1] = '\0';
ESP_LOGI(TAG, "🎛 Modo = %s", current_mode);
}
// ======================================================
// GET_INFO
// ======================================================
else if (strcmp(c, "GET_INFO") == 0) {
char resp[256];
snprintf(resp, sizeof(resp),
"{\"uptime\":%lu,\"heap\":%lu,\"anim\":%u,\"mode\":\"%s\"}",
(unsigned long)(esp_log_timestamp()/1000),
(unsigned long)esp_get_free_heap_size(),
animacao,
current_mode
);
esp_mqtt_client_publish(mqtt_client, topic_resp, resp, 0, 1, false);
ESP_LOGI(TAG, "📤 INFO enviado");
}
// ======================================================
// CORES DO RELÓGIO
// ======================================================
else if (strcmp(c, "SET_HOUR_COLOR") == 0 ||
strcmp(c, "SET_MIN_COLOR") == 0 ||
strcmp(c, "SET_SEC_COLOR") == 0) {
cJSON *r = cJSON_GetObjectItem(root, "r");
cJSON *g = cJSON_GetObjectItem(root, "g");
cJSON *b = cJSON_GetObjectItem(root, "b");
if (!cJSON_IsNumber(r) || !cJSON_IsNumber(g) || !cJSON_IsNumber(b)) {
ESP_LOGW(TAG, "❌ SET_*_COLOR inválido");
return;
}
if (strcmp(c, "SET_HOUR_COLOR") == 0) {
hora_r = r->valueint; hora_g = g->valueint; hora_b = b->valueint;
}
else if (strcmp(c, "SET_MIN_COLOR") == 0) {
min_r = r->valueint; min_g = g->valueint; min_b = b->valueint;
}
else {
sec_r = r->valueint; sec_g = g->valueint; sec_b = b->valueint;
}
}
// ======================================================
// SET_CLOCK_SPEED
// ======================================================
else if (strcmp(c, "SET_CLOCK_SPEED") == 0) {
cJSON *v = cJSON_GetObjectItem(root, "ms");
if (!cJSON_IsNumber(v)) {
ESP_LOGW(TAG, "❌ SET_CLOCK_SPEED sem ms");
return;
}
clock_speed_ms = v->valueint;
ESP_LOGI(TAG, "⏰ Clock speed = %d ms", clock_speed_ms);
}
// ======================================================
// TEST_RING
// ======================================================
else if (strcmp(c, "TEST_RING") == 0) {
int n = led_get_count();
for (int i = 0; i < n; i++) {
led_clear();
led_set_pixel(i, 0, 50, 0);
led_show();
vTaskDelay(pdMS_TO_TICKS(80));
}
led_all_off();
}
// ======================================================
// COMANDO DESCONHECIDO
// ======================================================
else {
ESP_LOGW(TAG, "⚠️ Comando desconhecido: %s", c);
char resp[128];
snprintf(resp, sizeof(resp),
"{\"error\":\"unknown_cmd\",\"cmd\":\"%s\"}", c);
esp_mqtt_client_publish(mqtt_client, topic_resp, resp, 0, 1, false);
}
}