Aktualny kod:
Code: Select all
#include <SuplaDevice.h>
#include <supla/network/esp_wifi.h>
#include <supla/control/relay.h>
#include <supla/control/button.h>
#include <supla/control/hvac_base.h>
#include <supla/clock/clock.h>
#include <supla/network/html/time_parameters.h>
#include <supla/network/html/hvac_parameters.h>
#include <supla/control/internal_pin_output.h>
#include <supla/device/status_led.h>
// ======================================================
// STORAGE
// ======================================================
#include <supla/storage/storage.h>
#include <supla/storage/config.h>
#include <supla/storage/littlefs_config.h>
// ======================================================
// WWW
// ======================================================
#include <supla/network/esp_web_server.h>
#include <supla/network/html/device_info.h>
#include <supla/network/html/protocol_parameters.h>
#include <supla/network/html/status_led_parameters.h>
#include <supla/network/html/wifi_parameters.h>
#include <supla/device/supla_ca_cert.h>
// ======================================================
// OTA
// ======================================================
#ifdef ARDUINO_ARCH_ESP32
#include <HTTPUpdateServer.h>
#else
#include <ESP8266HTTPUpdateServer.h>
#endif
// ======================================================
// DS18B20
// ======================================================
#include <OneWire.h>
#include <DallasTemperature.h>
#include <supla/sensor/thermometer.h>
// ======================================================
// GPIO
// ======================================================
#define STATUS_LED_GPIO 2
#define BUTTON_CFG_GPIO 0
#define RELAY_1_GPIO 2
#define RELAY_2_GPIO 12
#define BUTTON_2_GPIO 9
#define RELAY_3_GPIO 5
#define RELAY_4_GPIO 4
#define BUTTON_4_GPIO 10
#define RELAY_5_GPIO 15
#define RELAY_6_GPIO 3
#define BUTTON_6_GPIO 0
#define BUTTON_THERMOSTAT_GPIO 14
#define ONE_WIRE_BUS 1
// ======================================================
// SUPLA
// ======================================================
Supla::ESPWifi wifi;
Supla::LittleFsConfig configSupla;
Supla::Device::StatusLed statusLed(
STATUS_LED_GPIO,
false);
Supla::EspWebServer suplaServer;
#ifdef ARDUINO_ARCH_ESP32
HTTPUpdateServer httpUpdater;
#else
ESP8266HTTPUpdateServer httpUpdater;
#endif
// ======================================================
// DS18B20
// ======================================================
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress discoveredAddresses[10];
int discoveredCount = 0;
// ======================================================
// DS18B20 CLASS
// ======================================================
class ConfigurableDS18B20
: public Supla::Sensor::Thermometer {
public:
ConfigurableDS18B20(int sensorNumber)
: sensorNum(sensorNumber) {
memset(deviceAddress, 0,
sizeof(deviceAddress));
}
void onInit() override {
loadAddress();
channel.setNewValue(getValue());
}
double getValue() override {
if (deviceAddress[0] == 0 &&
deviceAddress[7] == 0) {
return -275.0;
}
sensors.requestTemperaturesByAddress(
deviceAddress);
double temp =
sensors.getTempC(deviceAddress);
if (temp == DEVICE_DISCONNECTED_C) {
return -275.0;
}
return temp;
}
void loadAddress() {
auto cfg =
Supla::Storage::ConfigInstance();
if (!cfg) return;
char key[20];
for (int i = 0; i < 8; i++) {
snprintf(key,
sizeof(key),
"ds_%d_byte_%d",
sensorNum,
i);
uint8_t b = 0;
cfg->getUInt8(key, &b);
deviceAddress[i] = b;
}
}
protected:
int sensorNum;
DeviceAddress deviceAddress;
};
ConfigurableDS18B20* dsSensors[4];
// ======================================================
// WEB PANEL
// ======================================================
class DS18B20AssignmentParameter
: public Supla::HtmlElement {
public:
DS18B20AssignmentParameter()
: HtmlElement(Supla::HTML_SECTION_FORM) {}
void send(Supla::WebSender* sender) override {
sender->send("</div><div class=\"box\">");
sender->send(
"<h3>DS18B20 Thermometer Assignment</h3>");
auto cfg =
Supla::Storage::ConfigInstance();
for (int t = 0; t < 4; t++) {
char label[32];
snprintf(label,
sizeof(label),
"Thermometer %d",
t + 1);
sender->send(
"<div class=\"form-field\"><label>");
sender->send(label);
sender->send("</label>");
sender->send("<select name=\"");
char selectName[32];
snprintf(selectName,
sizeof(selectName),
"ds_assign_%d",
t);
sender->send(selectName);
sender->send("\">");
uint8_t selectedIdx = 255;
char key[20];
snprintf(key,
sizeof(key),
"ds_idx_%d",
t);
if (cfg) {
cfg->getUInt8(key,
&selectedIdx);
}
sender->send(
"<option value=\"255\"");
if (selectedIdx == 255) {
sender->send(" selected");
}
sender->send(
">Not Assigned</option>");
for (int i = 0;
i < discoveredCount;
i++) {
char optValue[4];
char optLabel[64];
snprintf(optValue,
sizeof(optValue),
"%d",
i);
snprintf(optLabel,
sizeof(optLabel),
"ID: %02X%02X%02X%02X...",
discoveredAddresses[i][0],
discoveredAddresses[i][1],
discoveredAddresses[i][2],
discoveredAddresses[i][3]);
sender->send("<option value=\"");
sender->send(optValue);
sender->send("\"");
if (selectedIdx == i) {
sender->send(" selected");
}
sender->send(">");
sender->send(optLabel);
sender->send("</option>");
}
sender->send("</select></div>");
}
sender->send("</div><div>");
sender->send(
"<button type=\"button\" "
"onclick=\"window.location.href='/update'\">");
sender->send("FIRMWARE UPDATE");
sender->send("</button>");
}
bool handleResponse(
const char* key,
const char* value) override {
if (strncmp(key,
"ds_assign_",
10) != 0) {
return false;
}
int t = atoi(key + 10);
int selectedIdx = atoi(value);
auto cfg =
Supla::Storage::ConfigInstance();
if (!cfg) return false;
char idxKey[20];
snprintf(idxKey,
sizeof(idxKey),
"ds_idx_%d",
t);
cfg->setUInt8(idxKey,
selectedIdx);
char byteKey[20];
if (selectedIdx >= 0 &&
selectedIdx < discoveredCount) {
for (int i = 0; i < 8; i++) {
snprintf(byteKey,
sizeof(byteKey),
"ds_%d_byte_%d",
t,
i);
cfg->setUInt8(
byteKey,
discoveredAddresses[selectedIdx][i]);
}
} else {
for (int i = 0; i < 8; i++) {
snprintf(byteKey,
sizeof(byteKey),
"ds_%d_byte_%d",
t,
i);
cfg->setUInt8(byteKey, 0);
}
}
return true;
}
};
// ======================================================
// SCAN DS18B20
// ======================================================
void scanDS18B20() {
sensors.begin();
discoveredCount = 0;
DeviceAddress tempAddr;
oneWire.reset_search();
while (oneWire.search(tempAddr) &&
discoveredCount < 10) {
if (sensors.validAddress(tempAddr) &&
tempAddr[0] == 0x28) {
memcpy(discoveredAddresses[
discoveredCount],
tempAddr,
sizeof(DeviceAddress));
discoveredCount++;
}
}
}
// ======================================================
// SETUP
// ======================================================
void setup() {
Serial.begin(115200);
new Supla::Clock;
scanDS18B20();
SuplaDevice.allowWorkInOfflineMode(0);
SuplaDevice.setName(
"SUPLA-SmartPool");
SuplaDevice.setSwVersion(
"SmartPool v1.0");
httpUpdater.setup(
suplaServer.getServerPtr(),
"/update");
// ====================================================
// WWW
// ====================================================
new Supla::Html::DeviceInfo(
&SuplaDevice);
new Supla::Html::WifiParameters;
new Supla::Html::ProtocolParameters(
false,
false);
new Supla::Html::StatusLedParameters;
new Supla::Html::TimeParameters(
&SuplaDevice);
new DS18B20AssignmentParameter();
// ====================================================
// RELAY 1
// ====================================================
auto r1 =
new Supla::Control::Relay(
RELAY_1_GPIO);
r1->getChannel()
->setChannelNumber(0);
r1->setDefaultFunction(
SUPLA_CHANNELFNC_POWERSWITCH);
r1->setInitialCaption(
"Zabezpieczenie");
// ====================================================
// RELAY 2
// ====================================================
auto r2 =
new Supla::Control::Relay(
RELAY_2_GPIO);
r2->getChannel()
->setChannelNumber(1);
r2->setDefaultFunction(
SUPLA_CHANNELFNC_POWERSWITCH);
r2->setInitialCaption(
"Pompa filtracyjna");
auto b2 =
new Supla::Control::Button(
BUTTON_2_GPIO,
true,
true);
b2->addAction(
Supla::TOGGLE,
r2,
Supla::ON_PRESS);
// ====================================================
// RELAY 3
// ====================================================
auto r3 =
new Supla::Control::Relay(
RELAY_3_GPIO);
r3->getChannel()
->setChannelNumber(2);
r3->setDefaultFunction(
SUPLA_CHANNELFNC_POWERSWITCH);
r3->setInitialCaption(
"Generator chloru i ozonu");
// ====================================================
// RELAY 4
// ====================================================
auto r4 =
new Supla::Control::Relay(
RELAY_4_GPIO);
r4->getChannel()
->setChannelNumber(3);
r4->setDefaultFunction(
SUPLA_CHANNELFNC_POWERSWITCH);
r4->setInitialCaption(
"Pompa ogrzewania");
auto b4 =
new Supla::Control::Button(
BUTTON_4_GPIO,
true,
true);
b4->addAction(
Supla::TOGGLE,
r4,
Supla::ON_PRESS);
// ====================================================
// RELAY 5
// ====================================================
auto r5 =
new Supla::Control::Relay(
RELAY_5_GPIO);
r5->getChannel()
->setChannelNumber(4);
r5->setDefaultFunction(
SUPLA_CHANNELFNC_LIGHTSWITCH);
r5->setInitialCaption(
"Lampa UV-C");
// ====================================================
// RELAY 6
// ====================================================
auto r6 =
new Supla::Control::Relay(
RELAY_6_GPIO);
r6->getChannel()
->setChannelNumber(5);
r6->setDefaultFunction(
SUPLA_CHANNELFNC_LIGHTSWITCH);
r6->setInitialCaption(
"Oświetlenie basenu");
auto b6 =
new Supla::Control::Button(
BUTTON_6_GPIO,
true,
true);
b6->addAction(
Supla::TOGGLE,
r6,
Supla::ON_PRESS);
// ====================================================
// DS18B20
// ====================================================
dsSensors[0] = new ConfigurableDS18B20(0);
dsSensors[0]->getChannel()->setChannelNumber(7);
dsSensors[0]->setInitialCaption("Woda w basenie");
dsSensors[1] = new ConfigurableDS18B20(1);
dsSensors[1]->getChannel()->setChannelNumber(8);
dsSensors[1]->setInitialCaption("Woda w solarach");
dsSensors[2] = new ConfigurableDS18B20(2);
dsSensors[2]->getChannel()->setChannelNumber(9);
dsSensors[2]->setInitialCaption("Woda powrotna z solarów");
dsSensors[3] = new ConfigurableDS18B20(3);
dsSensors[3]->getChannel()->setChannelNumber(10);
dsSensors[3]->setInitialCaption("Powietrze");
// ====================================================
// HVAC
// ====================================================
auto hvac = new Supla::Control::HvacBase();
new Supla::Html::HvacParameters(hvac);
hvac->getChannel()
->setChannelNumber(6);
hvac->setInitialCaption("Termostat Basenu");
// główny termometr
hvac->setMainThermometerChannelNo(7);
// histereza
hvac->setTemperatureHisteresis(40);
// zakres histerezy
hvac->setTemperatureHisteresisMin(20);
hvac->setTemperatureHisteresisMax(1000);
// zakres temperatur
hvac->setTemperatureRoomMin(2000);
hvac->setTemperatureRoomMax(4000);
// ====================================================
// HVAC BUTTON
// ====================================================
auto bThermostat =
new Supla::Control::Button(
BUTTON_THERMOSTAT_GPIO,
true,
true);
bThermostat->addAction(
Supla::TOGGLE,
hvac,
Supla::ON_PRESS);
// ====================================================
// CONFIG BUTTON
// ====================================================
auto buttonCfg =
new Supla::Control::Button(
BUTTON_CFG_GPIO,
true,
true);
buttonCfg->configureAsConfigButton(
&SuplaDevice);
// ====================================================
// CERT
// ====================================================
SuplaDevice.setSuplaCACert(
suplaCACert);
SuplaDevice.setSupla3rdPartyCACert(
supla3rdCACert);
// ====================================================
// START
// ====================================================
SuplaDevice.begin(21);
}
// ======================================================
// LOOP
// ======================================================
void loop() {
SuplaDevice.iterate();
static bool LOCAL_WEB_SERVER = false;
if (!LOCAL_WEB_SERVER &&
Supla::Network::IsReady()) {
LOCAL_WEB_SERVER = true;
SuplaDevice.handleAction(
0,
Supla::START_LOCAL_WEB_SERVER);
}
}Prosze o porady łopatologiczne, mile widziane poprawki w kodzie.
