mirror of
https://github.com/xoseperez/espurna.git
synced 2026-03-03 23:14:15 +01:00
dcz: flash strings and our own namespace
This commit is contained in:
@@ -22,32 +22,31 @@ Copyright (C) 2019-2021 by Maxim Prokhorov <prokhorov dot max at outlook dot com
|
||||
#include <ArduinoJson.h>
|
||||
#include <bitset>
|
||||
|
||||
namespace espurna {
|
||||
namespace domoticz {
|
||||
namespace {
|
||||
|
||||
struct Idx {
|
||||
constexpr static size_t Default { 0 };
|
||||
|
||||
Idx() = default;
|
||||
Idx(const Idx&) = default;
|
||||
Idx(Idx&&) = default;
|
||||
|
||||
explicit Idx(size_t value) :
|
||||
constexpr Idx() = default;
|
||||
constexpr explicit Idx(size_t value) :
|
||||
_value(value)
|
||||
{}
|
||||
|
||||
explicit operator bool() const {
|
||||
constexpr explicit operator bool() const {
|
||||
return _value != Default;
|
||||
}
|
||||
|
||||
bool operator==(size_t other) const {
|
||||
constexpr bool operator==(size_t other) const {
|
||||
return _value == other;
|
||||
}
|
||||
|
||||
bool operator==(const Idx& other) {
|
||||
constexpr bool operator==(const Idx& other) {
|
||||
return _value == other._value;
|
||||
}
|
||||
|
||||
size_t value() const {
|
||||
constexpr size_t value() const {
|
||||
return _value;
|
||||
}
|
||||
|
||||
@@ -55,27 +54,33 @@ private:
|
||||
size_t _value { Default };
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace domoticz
|
||||
} // namespace espurna
|
||||
|
||||
namespace settings {
|
||||
namespace internal {
|
||||
|
||||
template <>
|
||||
domoticz::Idx convert(const String& value) {
|
||||
return domoticz::Idx(convert<size_t>(value));
|
||||
espurna::domoticz::Idx convert(const String& value) {
|
||||
return espurna::domoticz::Idx(convert<size_t>(value));
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace settings
|
||||
|
||||
namespace espurna {
|
||||
namespace domoticz {
|
||||
namespace {
|
||||
namespace internal {
|
||||
namespace {
|
||||
|
||||
bool enabled { false };
|
||||
|
||||
} // namespace
|
||||
} // namespace internal
|
||||
|
||||
namespace {
|
||||
|
||||
bool enabled() {
|
||||
return internal::enabled;
|
||||
}
|
||||
@@ -88,9 +93,12 @@ void disable() {
|
||||
internal::enabled = false;
|
||||
}
|
||||
|
||||
namespace build {
|
||||
} // namespace
|
||||
|
||||
constexpr Idx DefaultIdx{};
|
||||
namespace build {
|
||||
namespace {
|
||||
|
||||
static constexpr ::espurna::domoticz::Idx DefaultIdx;
|
||||
|
||||
const __FlashStringHelper* topicOut() {
|
||||
return F(DOMOTICZ_OUT_TOPIC);
|
||||
@@ -104,50 +112,77 @@ constexpr bool enabled() {
|
||||
return 1 == DOMOTICZ_ENABLED;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace build
|
||||
|
||||
namespace settings {
|
||||
namespace keys {
|
||||
|
||||
alignas(4) static constexpr char Enabled[] PROGMEM = "dczEnabled";
|
||||
alignas(4) static constexpr char TopicOut[] PROGMEM = "dczTopicOut";
|
||||
alignas(4) static constexpr char TopicIn[] PROGMEM = "dczTopicIn";
|
||||
|
||||
#if RELAY_SUPPORT
|
||||
alignas(4) static constexpr char RelayIdx[] PROGMEM = "dczTopicIn";
|
||||
#endif
|
||||
|
||||
#if SENSOR_SUPPORT
|
||||
alignas(4) static constexpr char MagnitudeIdx[] PROGMEM = "dczTopicIn";
|
||||
#endif
|
||||
|
||||
#if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE
|
||||
alignas(4) static constexpr char LightIdx[] PROGMEM = "dczLightIdx";
|
||||
#endif
|
||||
|
||||
} // namespace keys
|
||||
|
||||
namespace {
|
||||
|
||||
bool enabled() {
|
||||
return getSetting("dczEnabled", build::enabled());
|
||||
return getSetting(FPSTR(keys::Enabled), build::enabled());
|
||||
}
|
||||
|
||||
String topicOut() {
|
||||
return getSetting("dczTopicOut", build::topicOut());
|
||||
return getSetting(FPSTR(keys::TopicOut), build::topicOut());
|
||||
}
|
||||
|
||||
String topicIn() {
|
||||
return getSetting("dczTopicIn", build::topicIn());
|
||||
return getSetting(FPSTR(keys::TopicIn), build::topicIn());
|
||||
}
|
||||
|
||||
#if RELAY_SUPPORT
|
||||
Idx relayIdx(size_t id) {
|
||||
return getSetting({"dczRelayIdx", id}, build::DefaultIdx);
|
||||
return getSetting({FPSTR(keys::RelayIdx), id}, build::DefaultIdx);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SENSOR_SUPPORT
|
||||
Idx magnitudeIdx(size_t id) {
|
||||
return getSetting({"dczMagnitude", id}, build::DefaultIdx);
|
||||
return getSetting({FPSTR(keys::MagnitudeIdx), id}, build::DefaultIdx);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE
|
||||
Idx lightIdx() {
|
||||
return getSetting("dczLightIdx", build::DefaultIdx);
|
||||
return getSetting(FPSTR(keys::LightIdx), build::DefaultIdx);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
} // namespace settings
|
||||
|
||||
#if RELAY_SUPPORT
|
||||
namespace relay {
|
||||
namespace internal {
|
||||
namespace {
|
||||
|
||||
std::bitset<RelaysMax> status;
|
||||
|
||||
} // namespace
|
||||
} // namespace internal
|
||||
|
||||
namespace {
|
||||
|
||||
void send(Idx, bool);
|
||||
void send();
|
||||
|
||||
@@ -177,14 +212,20 @@ void callback(size_t id, bool value) {
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
::relayOnStatusChange(callback);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace relay
|
||||
#endif
|
||||
|
||||
#if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE
|
||||
namespace light {
|
||||
namespace {
|
||||
|
||||
void status(const JsonObject& root, unsigned char nvalue) {
|
||||
JsonObject& color = root["Color"];
|
||||
JsonObject& color = root[F("Color")];
|
||||
if (color.success()) {
|
||||
|
||||
// for ColorMode... see:
|
||||
@@ -199,7 +240,7 @@ void status(const JsonObject& root, unsigned char nvalue) {
|
||||
auto ww = color["ww"].as<long>();
|
||||
|
||||
DEBUG_MSG_P(PSTR("[DOMOTICZ] Dimmer nvalue:%hhu rgb:%ld,%ld,%ld ww:%ld,cw:%ld t:%ld brightness:%ld\n"),
|
||||
nvalue, r, g, b, ww, cw, color["t"].as<long>(), color["Level"].as<long>());
|
||||
nvalue, r, g, b, ww, cw, color["t"].as<long>(), color[F("Level")].as<long>());
|
||||
|
||||
// m field contains information about color mode (enum ColorMode from domoticz ColorSwitch.h):
|
||||
switch (color["m"].as<int>()) {
|
||||
@@ -223,15 +264,17 @@ void status(const JsonObject& root, unsigned char nvalue) {
|
||||
}
|
||||
|
||||
// domoticz uses 100 as maximum value while we're using a custom scale
|
||||
lightBrightnessPercent(root["Level"].as<long>());
|
||||
lightBrightnessPercent(root[F("Level")].as<long>());
|
||||
lightState(nvalue > 0);
|
||||
lightUpdate();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace light
|
||||
#endif
|
||||
|
||||
namespace mqtt {
|
||||
namespace {
|
||||
|
||||
void subscribe() {
|
||||
mqttSubscribeRaw(settings::topicOut().c_str());
|
||||
@@ -264,19 +307,19 @@ void callback(unsigned int type, const char* topic, char* payload) {
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned char nvalue = root["nvalue"];
|
||||
Idx idx(root["idx"].as<size_t>());
|
||||
unsigned char nvalue = root[F("nvalue")];
|
||||
Idx idx(root[F("idx")].as<size_t>());
|
||||
|
||||
#if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE
|
||||
String stype = root["stype"];
|
||||
String switchType = root["switchType"];
|
||||
if ((idx == settings::lightIdx()) && (stype.startsWith("RGB") || (switchType.equals("Dimmer")))) {
|
||||
domoticz::light::status(root, nvalue);
|
||||
String stype = root[F("stype")];
|
||||
String switchType = root[F("switchType")];
|
||||
if ((idx == settings::lightIdx()) && (stype.startsWith(F("RGB")) || (switchType.equals(F("Dimmer"))))) {
|
||||
espurna::domoticz::light::status(root, nvalue);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
domoticz::relay::status(idx, nvalue > 0);
|
||||
espurna::domoticz::relay::status(idx, nvalue > 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -293,9 +336,9 @@ void send(Idx idx, int nvalue, const char* svalue) {
|
||||
|
||||
StaticJsonBuffer<JSON_OBJECT_SIZE(3)> json;
|
||||
JsonObject& root = json.createObject();
|
||||
root["idx"] = idx.value();
|
||||
root["nvalue"] = nvalue;
|
||||
root["svalue"] = svalue;
|
||||
root[F("idx")] = idx.value();
|
||||
root[F("nvalue")] = nvalue;
|
||||
root[F("svalue")] = svalue;
|
||||
|
||||
char payload[128] = {0};
|
||||
root.printTo(payload);
|
||||
@@ -307,10 +350,16 @@ void send(Idx idx, int nvalue) {
|
||||
send(idx, nvalue, "");
|
||||
}
|
||||
|
||||
void setup() {
|
||||
::mqttRegister(callback);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace mqtt
|
||||
|
||||
#if RELAY_SUPPORT
|
||||
namespace relay {
|
||||
namespace {
|
||||
|
||||
void send(Idx idx, bool value) {
|
||||
mqtt::send(idx, value ? 1 : 0);
|
||||
@@ -323,11 +372,13 @@ void send() {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace relay
|
||||
#endif
|
||||
|
||||
#if SENSOR_SUPPORT
|
||||
namespace sensor {
|
||||
namespace {
|
||||
|
||||
void send(unsigned char index, const ::sensor::Value& value) {
|
||||
if (!enabled()) {
|
||||
@@ -373,50 +424,64 @@ void send(unsigned char index, const ::sensor::Value& value) {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace sensor
|
||||
#endif // SENSOR_SUPPORT
|
||||
|
||||
#if WEB_SUPPORT
|
||||
namespace web {
|
||||
namespace {
|
||||
|
||||
alignas(4) static constexpr char Prefix[] PROGMEM = "dcz";
|
||||
|
||||
bool onKeyCheck(const char* key, JsonVariant& value) {
|
||||
return (strncmp(key, "dcz", 3) == 0);
|
||||
return (strncmp_P(key, Prefix, 3) == 0);
|
||||
}
|
||||
|
||||
void onVisible(JsonObject& root) {
|
||||
if (haveRelaysOrSensors()) {
|
||||
wsPayloadModule(root, "dcz");
|
||||
wsPayloadModule(root, Prefix);
|
||||
}
|
||||
}
|
||||
|
||||
void onConnected(JsonObject& root) {
|
||||
root["dczEnabled"] = settings::enabled();
|
||||
root["dczTopicIn"] = settings::topicIn();
|
||||
root["dczTopicOut"] = settings::topicOut();
|
||||
root[FPSTR(settings::keys::Enabled)] = settings::enabled();
|
||||
root[FPSTR(settings::keys::TopicIn)] = settings::topicIn();
|
||||
root[FPSTR(settings::keys::TopicOut)] = settings::topicOut();
|
||||
|
||||
#if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE
|
||||
root["dczLightIdx"] = settings::lightIdx().value();
|
||||
root[FPSTR(settings::keys::LightIdx)] = settings::lightIdx().value();
|
||||
#endif
|
||||
|
||||
const size_t Relays { relayCount() };
|
||||
|
||||
JsonArray& relays = root.createNestedArray("dczRelays");
|
||||
JsonArray& relays = root.createNestedArray(F("dczRelays"));
|
||||
for (size_t id = 0; id < Relays; ++id) {
|
||||
relays.add(settings::relayIdx(id).value());
|
||||
}
|
||||
|
||||
#if SENSOR_SUPPORT
|
||||
sensorWebSocketMagnitudes(root, PSTR("dcz"), [](JsonArray& out, size_t index) {
|
||||
out.add(getSetting({"dczMagnitude", index}, "0"));
|
||||
out.add(settings::magnitudeIdx(index).value());
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void setup() {
|
||||
wsRegister()
|
||||
.onVisible(onVisible)
|
||||
.onConnected(onConnected)
|
||||
.onKeyCheck(onKeyCheck);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace web
|
||||
#endif // WEB_SUPPORT
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
|
||||
void configure() {
|
||||
auto enabled_in_cfg = settings::enabled();
|
||||
if (enabled_in_cfg != enabled()) {
|
||||
@@ -447,46 +512,46 @@ void migrate(int version) {
|
||||
return;
|
||||
}
|
||||
|
||||
moveSetting("dczRelayIdx0", "dczLightIdx");
|
||||
moveSetting(F("dczRelayIdx0"), FPSTR(settings::keys::LightIdx));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
} // namespace domoticz
|
||||
|
||||
#if SENSOR_SUPPORT
|
||||
|
||||
void domoticzSendMagnitude(unsigned char index, const sensor::Value& value) {
|
||||
domoticz::sensor::send(index, value);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void domoticzSetup() {
|
||||
void setup() {
|
||||
#if RELAY_SUPPORT && (LIGHT_PROVIDER != LIGHT_PROVIDER_NONE)
|
||||
migrateVersion(domoticz::migrate);
|
||||
migrateVersion(migrate);
|
||||
#endif
|
||||
|
||||
#if WEB_SUPPORT
|
||||
wsRegister()
|
||||
.onVisible(domoticz::web::onVisible)
|
||||
.onConnected(domoticz::web::onConnected)
|
||||
.onKeyCheck(domoticz::web::onKeyCheck);
|
||||
web::setup();
|
||||
#endif
|
||||
|
||||
#if RELAY_SUPPORT
|
||||
relayOnStatusChange(domoticz::relay::callback);
|
||||
relay::setup();
|
||||
#endif
|
||||
|
||||
mqttRegister(domoticz::mqtt::callback);
|
||||
espurnaRegisterReload(domoticz::configure);
|
||||
mqtt::setup();
|
||||
|
||||
domoticz::configure();
|
||||
::espurnaRegisterReload(configure);
|
||||
configure();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace domoticz
|
||||
} // namespace espurna
|
||||
|
||||
#if SENSOR_SUPPORT
|
||||
void domoticzSendMagnitude(unsigned char index, const sensor::Value& value) {
|
||||
espurna::domoticz::sensor::send(index, value);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool domoticzEnabled() {
|
||||
return domoticz::enabled();
|
||||
return espurna::domoticz::enabled();
|
||||
}
|
||||
|
||||
void domoticzSetup() {
|
||||
espurna::domoticz::setup();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user