#include <Arduino.h>
// Кол-во каналов (и для ядра, и для device-layer)
#define BUTTON_CHANNEL_NUM 4
const char* DEVICE_TYPE = "button";
const char* FW_VERSION = "1.0.3 alpha";
const uint8_t CHANNEL_NUM = BUTTON_CHANNEL_NUM;
#include <sh_core_esp8266.h>
#include "ButtonLogic.h"
// Используем GPIO номера напрямую:
// D1 mini: D2=GPIO4, D5=GPIO14, D6=GPIO12, D7=GPIO13
const uint8_t SIGNAL_LED = 4; // GPIO4
const uint8_t BUTTON_PINS[BUTTON_CHANNEL_NUM] = { 14, 12, 13, 15 }; // GPIO14, GPIO12, GPIO13
static String extract_json_string_value_local(const String &body, const String &key) {
String pattern = "\"" + key + "\"";
int keyIndex = body.indexOf(pattern);
if (keyIndex < 0) return "";
int colonIndex = body.indexOf(':', keyIndex);
if (colonIndex < 0) return "";
int firstQuote = body.indexOf('"', colonIndex + 1);
if (firstQuote < 0) return "";
int secondQuote = body.indexOf('"', firstQuote + 1);
if (secondQuote < 0) return "";
return body.substring(firstQuote + 1, secondQuote);
}
static int extract_json_int_value_local(const String &body, const String &key) {
String pattern = "\"" + key + "\"";
int keyIndex = body.indexOf(pattern);
if (keyIndex < 0) return -1;
int colonIndex = body.indexOf(':', keyIndex);
if (colonIndex < 0) return -1;
int i = colonIndex + 1;
while (i < (int)body.length() && body[i] == ' ') i++;
long v = 0;
bool any = false;
while (i < (int)body.length()) {
char c = body[i];
if (c < '0' || c > '9') break;
any = true;
v = v * 10 + (c - '0');
i++;
}
if (!any) return -1;
return (int)v;
}
void appendStatusJsonFields(String &json) {
json += ",\"indicators\":\"";
if (deviceMode == DEVICE_MODE_SETUP) {
json += "setup";
} else if (WiFi.status() != WL_CONNECTED) {
json += "nowifi";
} else {
json += "none";
}
json += "\"";
json += ",\"channels\":[";
for (uint8_t ch = 0; ch < BUTTON_CHANNEL_NUM; ch++) {
if (ch) json += ",";
json += "{\"id\":" + String(ch) + ",\"indicator\":\"";
IndicatorState st = get_channel_indicator(ch);
switch (st) {
case IND_ENABLED: json += "enabled"; break;
case IND_DISABLED: json += "disabled"; break;
case IND_MUTE: json += "mute"; break;
case IND_WAITING: json += "waiting"; break;
case IND_WARNING: json += "warning"; break;
case IND_ERROR: json += "error"; break;
}
json += "\"}";
}
json += "]";
}
void appendAboutJsonFields(String &json) {
json += ",\"channels\":" + String(CHANNEL_NUM);
json += ",\"has_indicators\":true";
}
bool deviceHandleAction(const String &action,
const String ¶msJson,
String &errorCode,
String &errorMessage)
{
if (action == "set_channel_state") {
int ch = extract_json_int_value_local(paramsJson, "channel");
if (ch < 0 || ch >= BUTTON_CHANNEL_NUM) {
errorCode = "IllegalActionOrParams";
errorMessage = "Invalid channel";
return false;
}
String st = extract_json_string_value_local(paramsJson, "state");
st.toLowerCase();
if (st == "enabled") set_channel_indicator((uint8_t)ch, IND_ENABLED);
else if (st == "disabled") set_channel_indicator((uint8_t)ch, IND_DISABLED);
else if (st == "mute") set_channel_indicator((uint8_t)ch, IND_MUTE);
else if (st == "warning") set_channel_indicator((uint8_t)ch, IND_WARNING);
else if (st == "error") set_channel_indicator((uint8_t)ch, IND_ERROR);
else {
errorCode = "IllegalActionOrParams";
errorMessage = "Invalid state";
return false;
}
return true;
}
errorCode = "IllegalActionOrParams";
errorMessage = "Unknown action";
return false;
}
void deviceHandleReset() {
for (uint8_t ch = 0; ch < BUTTON_CHANNEL_NUM; ch++) {
set_channel_indicator(ch, IND_DISABLED);
clear_channel_temp(ch);
}
}
void setup() {
coreSetup();
button_logic_setup();
}
void loop() {
coreLoop();
delay(0);
button_logic_loop();
}