Newer
Older
smart-home-server / devices / button / button_esp8266 / button_esp8266.ino
#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 &paramsJson,
                        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();
}