#include <Arduino.h>
const char* DEVICE_TYPE = "relay";
const char* FW_VERSION = "1.0.1 beta";
const uint8_t CHANNEL_NUM = 1;
#include <sh_core_8266.h>
#include "RelayLogic.h" // вот тут находятся каналы и функции управления
// --------------------- УСТРОЙСТВЕННЫЙ КОНФИГ ---------------------
const uint16_t RELAY_EEPROM_BASE = getDeviceEepromStart();
// если когда-нибудь понадобится хранить состояние каналов:
const uint16_t RELAY_STATE_ADDR = RELAY_EEPROM_BASE; // например
// const uint16_t RELAY_OTHER_ADDR = RELAY_EEPROM_BASE + 16;
// Количество каналов уже задано в Config.h через CHANNEL_NUM.
// Здесь просто указываем, какие пины у каждого канала.
// Для одноканального ESP-01S, где реле сидит на GPIO0:
const uint8_t RELAY_PINS[CHANNEL_NUM] = { 0 };
// Состояние каналов (по умолчанию все выключены)
bool channelState[CHANNEL_NUM] = { false };
// Флаг инверта для каналов
const bool RELAY_INVERT[CHANNEL_NUM] = {
true // если нужно инвертировать канал
// false ← если модуль обычный, без инверта
};
// ---------------------------------------------------------------
void relayLoadStates() {
EEPROM.begin(EEPROM_SIZE);
for (uint8_t ch = 0; ch < CHANNEL_NUM; ch++) {
uint8_t v = EEPROM.read(RELAY_STATE_ADDR + ch);
// 0xFF считаем "ничего не записано" → по умолчанию выкл
if (v == 0xFF) {
channelState[ch] = false;
} else {
channelState[ch] = (v != 0);
}
}
EEPROM.end();
// применяем к железу
for (uint8_t ch = 0; ch < CHANNEL_NUM; ch++) {
applyChannelState(ch, channelState[ch]);
}
}
void relaySaveStates() {
EEPROM.begin(EEPROM_SIZE);
for (uint8_t ch = 0; ch < CHANNEL_NUM; ch++) {
EEPROM.write(RELAY_STATE_ADDR + ch, channelState[ch] ? 1 : 0);
}
EEPROM.commit();
EEPROM.end();
}
void appendStatusJsonFields(String &json) {
// Базовое поле "status":"ok" уже добавлено в REST_API.h,
// мы лишь дополняем JSON полем channels.
json += ",\"channels\":[";
for (uint8_t ch = 0; ch < CHANNEL_NUM; ch++) {
if (ch > 0) json += ",";
json += "{";
json += "\"id\":" + String(ch) + ",";
json += "\"state\":\"";
json += getChannelState(ch) ? "on" : "off";
json += "\",\"inverted\":";
json += RELAY_INVERT[ch] ? "true" : "false";
json += "}";
}
json += "]";
}
void appendAboutJsonFields(String &json) {
json += ",\"channels\":" + String(CHANNEL_NUM);
}
bool deviceHandleAction(const String &action,
const String ¶msJson,
String &errorCode,
String &errorMessage)
{
if (action == "set_state") {
String state = extractJsonStringValue(paramsJson, "state");
if (state != "on" && state != "off") {
errorCode = "IllegalActionOrParams";
errorMessage = "Invalid state";
return false;
}
setOn(state == "on");
relaySaveStates();
return true;
}
if (action == "set_channel_state") {
// Канал
int ch = extractJsonIntValue(paramsJson, "channel");
if (ch < 0 || ch >= CHANNEL_NUM) {
errorCode = "IllegalActionOrParams";
errorMessage = "Invalid channel index";
return false;
}
// State
String state = extractJsonStringValue(paramsJson, "state");
state.toLowerCase();
if (state != "on" && state != "off") {
errorCode = "IllegalActionOrParams";
errorMessage = "Invalid state";
return false;
}
bool newState = (state == "on");
setChannelState(ch, newState);
relaySaveStates();
return true;
}
if (action == "toggle_channel") {
int ch = extractJsonIntValue(paramsJson, "channel");
if (ch < 0 || ch >= CHANNEL_NUM) {
errorCode = "IllegalActionOrParams";
errorMessage = "Invalid channel index";
return false;
}
bool newState = !getChannelState(ch);
setChannelState(ch, newState);
relaySaveStates();
return true;
}
errorCode = "IllegalActionOrParams";
errorMessage = "Unknown action";
return false;
}
void deviceHandleReset() {
for (uint8_t ch = 0; ch < CHANNEL_NUM; ch++) {
channelState[ch] = false;
applyChannelState(ch, false);
}
EEPROM.begin(EEPROM_SIZE);
for (uint16_t addr = DEVICE_EEPROM_START; addr < EEPROM_SIZE; addr++) {
EEPROM.write(addr, 0xFF);
}
EEPROM.commit();
EEPROM.end();
}
void setup() {
for (int i = 0; i < CHANNEL_NUM; i++) {
pinMode(RELAY_PINS[i], OUTPUT);
}
relayLoadStates();
coreSetup();
}
void loop() {
coreLoop();
}