Browse Source

system: finish up cleaning broker code

dev
Maxim Prokhorov 3 years ago
parent
commit
4d8dc5d2a6
20 changed files with 93 additions and 185 deletions
  1. +0
    -3
      code/espurna/board.cpp
  2. +0
    -89
      code/espurna/broker.h
  3. +0
    -1
      code/espurna/config/arduino.h
  4. +0
    -25
      code/espurna/config/dependencies.h
  5. +0
    -8
      code/espurna/config/general.h
  6. +0
    -2
      code/espurna/config/hardware.h
  7. +3
    -3
      code/espurna/influxdb.cpp
  8. +2
    -3
      code/espurna/light.h
  9. +0
    -1
      code/espurna/main.h
  10. +16
    -12
      code/espurna/rfbridge.cpp
  11. +2
    -3
      code/espurna/rfbridge.h
  12. +36
    -15
      code/espurna/rpnrules.cpp
  13. +0
    -1
      code/espurna/scheduler.cpp
  14. +23
    -11
      code/espurna/sensor.cpp
  15. +3
    -4
      code/espurna/sensor.h
  16. +1
    -1
      code/espurna/terminal.cpp
  17. +0
    -1
      code/espurna/tuya.cpp
  18. +5
    -1
      code/espurna/wifi.cpp
  19. +2
    -0
      code/espurna/wifi.h
  20. +0
    -1
      code/test/build/core.h

+ 0
- 3
code/espurna/board.cpp View File

@ -17,9 +17,6 @@ PROGMEM const char espurna_modules[] =
#if API_SUPPORT
"API "
#endif
#if BROKER_SUPPORT
"BROKER "
#endif
#if BUTTON_SUPPORT
"BUTTON "
#endif


+ 0
- 89
code/espurna/broker.h View File

@ -1,89 +0,0 @@
/*
BROKER MODULE
Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
*/
#pragma once
#include <functional>
#include <utility>
#include <vector>
#include <tuple>
// Example usage:
//
// module.h
// BrokerDeclare(CustomBroker, void(int));
//
// module.cpp
// BrokerBind(CustomBroker);
//
// other.cpp
// #include "module.h"
// void func() {
// CustomBroker::Register([](int arg) { Serial.println(arg); }
// CustomBroker::Publish(12345);
// }
template <typename Func>
struct TBroker {};
template <typename R, typename ...Args>
struct TBroker<R(Args...)> {
using TArgs = typename std::tuple<Args...>;
using TCallback = std::function<R(Args...)>;
using TCallbacks = std::vector<TCallback>;
TBroker(const TBroker&) = delete;
TBroker& operator=(const TBroker&) = delete;
TBroker() = default;
// TODO: https://source.chromium.org/chromium/chromium/src/+/master:base/callback_list.h
// Consider giving out 'subscription' / 'token', so that the caller can remove callback later
void Register(TCallback callback) {
callbacks.push_back(callback);
}
void Publish(Args... args) {
for (auto& callback : callbacks) {
callback(args...);
}
}
protected:
TCallbacks callbacks;
};
// TODO: since 1.14.0 we intoduced static syntax for Brokers, ::Register & ::Publish.
// Preserve it (up to a point) when creating module-level objects.
// Provide a helper namespace with Register & Publish, instance and
// To help out VS Code with argument discovery, put TArgs as the first template parameter.
#define BrokerDeclare(Name, Signature) \
namespace Name { \
using type = TBroker<Signature>; \
extern type Instance; \
template<typename S = type::TArgs, typename ...Args> \
inline void Register(Args&&... args) { \
Instance.Register(std::forward<Args>(args)...); \
}\
\
template<typename S = type::TArgs, typename ...Args> \
inline void Publish(Args&&... args) { \
Instance.Publish(std::forward<Args>(args)...); \
}\
}
#define BrokerBind(Name) \
namespace Name { \
Name::type Instance; \
}

+ 0
- 1
code/espurna/config/arduino.h View File

@ -191,7 +191,6 @@
//#define ALEXA_SUPPORT 0
//#define API_SUPPORT 0
//#define BROKER_SUPPORT 0
//#define BUTTON_SUPPORT 0
//#define DEBUG_SERIAL_SUPPORT 0
//#define DEBUG_TELNET_SUPPORT 0


+ 0
- 25
code/espurna/config/dependencies.h View File

@ -36,32 +36,16 @@
#endif
#if ALEXA_SUPPORT
#undef BROKER_SUPPORT
#define BROKER_SUPPORT 1 // If Alexa enabled enable BROKER
#undef RELAY_SUPPORT
#define RELAY_SUPPORT 1 // and switches
#endif
#if RPN_RULES_SUPPORT
#undef BROKER_SUPPORT
#define BROKER_SUPPORT 1 // If RPN Rules enabled enable BROKER
#undef MQTT_SUPPORT
#define MQTT_SUPPORT 1
#endif
#if LED_SUPPORT
#undef BROKER_SUPPORT
#define BROKER_SUPPORT 1 // If LED is enabled enable BROKER to supply status changes
#endif
#if INFLUXDB_SUPPORT
#undef BROKER_SUPPORT
#define BROKER_SUPPORT 1 // If InfluxDB enabled enable BROKER
#endif
#if DOMOTICZ_SUPPORT
#undef BROKER_SUPPORT
#define BROKER_SUPPORT 1 // If Domoticz enabled enable BROKER
#undef MQTT_SUPPORT
#define MQTT_SUPPORT 1 // If Domoticz enabled enable MQTT
#endif
@ -71,11 +55,6 @@
#define MQTT_SUPPORT 1 // If Home Assistant enabled enable MQTT
#endif
#if THINGSPEAK_SUPPORT
#undef BROKER_SUPPORT
#define BROKER_SUPPORT 1 // If Thingspeak enabled enable BROKER
#endif
#if THERMOSTAT_SUPPORT
#undef MQTT_USE_JSON
#define MQTT_USE_JSON 1 // Thermostat depends on group messages in a JSON body
@ -86,8 +65,6 @@
#if SCHEDULER_SUPPORT
#undef NTP_SUPPORT
#define NTP_SUPPORT 1 // Scheduler needs NTP to work
#undef BROKER_SUPPORT
#define BROKER_SUPPORT 1 // Scheduler needs Broker to trigger every minute
#undef RELAY_SUPPORT
#define RELAY_SUPPORT 1 // Scheduler needs relays
#endif
@ -102,8 +79,6 @@
#endif
#if TUYA_SUPPORT
#undef BROKER_SUPPORT
#define BROKER_SUPPORT 1 // Broker is required to process relay & lights events
#undef RELAY_SUPPORT
#define RELAY_SUPPORT 1 // Most of the time we require it
#endif


+ 0
- 8
code/espurna/config/general.h View File

@ -1234,14 +1234,6 @@
#define MQTT_SETTER "/set"
#endif
// -----------------------------------------------------------------------------
// BROKER
// -----------------------------------------------------------------------------
#ifndef BROKER_SUPPORT
#define BROKER_SUPPORT 1 // The broker is a poor-man's pubsub manager
#endif
// -----------------------------------------------------------------------------
// SETTINGS
// -----------------------------------------------------------------------------


+ 0
- 2
code/espurna/config/hardware.h View File

@ -60,7 +60,6 @@
// Disable non-core modules
#define ALEXA_SUPPORT 0
#define API_SUPPORT 0
#define BROKER_SUPPORT 0
#define DEBUG_SERIAL_SUPPORT 0
#define DEBUG_TELNET_SUPPORT 0
#define DEBUG_WEB_SUPPORT 0
@ -99,7 +98,6 @@
// Disable non-core modules
#define ALEXA_SUPPORT 0
#define API_SUPPORT 0
#define BROKER_SUPPORT 0
#define DOMOTICZ_SUPPORT 0
#define DEBUG_SERIAL_SUPPORT 0
//#define DEBUG_TELNET_SUPPORT 0


+ 3
- 3
code/espurna/influxdb.cpp View File

@ -13,9 +13,9 @@ Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
#include <map>
#include <memory>
#include "broker.h"
#include "mqtt.h"
#include "rpc.h"
#include "relay.h"
#include "sensor.h"
#include "terminal.h"
#include "ws.h"
@ -157,7 +157,7 @@ void _idbConfigure() {
if (_idb_enabled && !_idb_client) _idbInitClient();
}
void _idbBrokerSensor(const String& topic, unsigned char id, double, const char* value) {
void _idbSendSensor(const String& topic, unsigned char id, double, const char* value) {
idbSend(topic.c_str(), id, value);
}
@ -297,7 +297,7 @@ void idbSetup() {
#endif
#if SENSOR_SUPPORT
SensorReportBroker::Register(_idbBrokerSensor);
sensorSetMagnitudeReport(_idbSendSensor);
#endif
espurnaRegisterReload(_idbConfigure);


+ 2
- 3
code/espurna/light.h View File

@ -41,8 +41,7 @@ enum class Report {
None = 0,
Web = 1 << 0,
Mqtt = 1 << 1,
MqttGroup = 1 << 2,
Broker = 1 << 3
MqttGroup = 1 << 2
};
constexpr int operator|(Report lhs, int rhs) {
@ -66,7 +65,7 @@ constexpr int operator&(Report lhs, int rhs) {
}
constexpr int DefaultReport {
Report::Web | Report::Mqtt | Report::MqttGroup | Report::Broker
Report::Web | Report::Mqtt | Report::MqttGroup
};
struct Hsv {


+ 0
- 1
code/espurna/main.h View File

@ -22,7 +22,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "alexa.h"
#include "api.h"
#include "broker.h"
#include "button.h"
#include "crash.h"
#include "curtain_kingart.h"


+ 16
- 12
code/espurna/rfbridge.cpp View File

@ -17,8 +17,6 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#include "ws.h"
#include "utils.h"
BrokerBind(RfbridgeBroker);
#include <algorithm>
#include <bitset>
#include <cstring>
@ -45,6 +43,12 @@ constexpr bool _rfb_transmit { true };
#endif
std::forward_list<RfbCodeHandler> _rfb_code_handlers;
void rfbSetCodeHandler(RfbCodeHandler handler) {
_rfb_code_handlers.push_front(handler);
}
// -----------------------------------------------------------------------------
// MATCH RECEIVED CODE WITH THE SPECIFIC RELAY ID
// -----------------------------------------------------------------------------
@ -531,7 +535,7 @@ void _rfbLearnStartFromPayload(const char* payload) {
std::copy(payload, sep, relay);
size_t id;
if (!tryParseId(relay, relayCount(), id)) {
if (!tryParseId(relay, relayCount, id)) {
DEBUG_MSG_P(PSTR("[RF] Invalid relay ID (%u)\n"), id);
return;
}
@ -645,9 +649,9 @@ void _rfbParse(uint8_t code, const std::vector<uint8_t>& payload) {
mqttSend(MQTT_TOPIC_RFIN, buffer, false, false);
#endif
#if BROKER_SUPPORT
RfbridgeBroker::Publish(RfbDefaultProtocol, buffer + 12);
#endif
for (auto& handler : _rfb_code_handlers) {
handler(RfbDefaultProtocol, buffer + 12);
}
}
break;
}
@ -665,10 +669,10 @@ void _rfbParse(uint8_t code, const std::vector<uint8_t>& payload) {
mqttSend(MQTT_TOPIC_RFIN, buffer, false, false);
#endif
#if BROKER_SUPPORT
// ref. https://github.com/Portisch/RF-Bridge-EFM8BB1/wiki/0xA6#example-of-a-received-decoded-protocol
RfbridgeBroker::Publish(payload[0], buffer + 2);
#endif
for (auto& handler : _rfb_code_handlers) {
handler(payload[0], buffer + 2);
}
} else {
DEBUG_MSG_P(PSTR("[RF] Received 0x%02X (%u bytes)\n"), code, payload.size());
}
@ -882,9 +886,9 @@ void _rfbReceiveImpl() {
mqttSend(MQTT_TOPIC_RFIN, buffer, false, false);
#endif
#if BROKER_SUPPORT
RfbridgeBroker::Publish(message[1], buffer + 10);
#endif
for (auto& handler : _rfb_code_handlers) {
handler(message[1], buffer + 10);
}
}
_rfb_modem->resetAvailable();


+ 2
- 3
code/espurna/rfbridge.h View File

@ -12,9 +12,8 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#if RFB_SUPPORT
#include "broker.h"
BrokerDeclare(RfbridgeBroker, void(unsigned char protocol, const char* code));
using RfbCodeHandler = void(*)(unsigned char protocol, const char* code);
void rfbSetCodeHandler(RfbCodeHandler);
void rfbSend(const char* code);
void rfbSend(const String& code);


+ 36
- 15
code/espurna/rpnrules.cpp View File

@ -158,7 +158,7 @@ void _rpnRelayStatus(size_t id, bool status) {
char name[32] = {0};
snprintf(name, sizeof(name), "relay%u", id);
rpn_variable_set(_rpn_ctxt, name, rpn_value(std::forward<T>(value)));
rpn_variable_set(_rpn_ctxt, name, rpn_value(status));
_rpn_run = true;
}
@ -167,13 +167,30 @@ void _rpnLightStatus() {
char name[32] = {0};
for (decltype(channels) channel = 0; channel < channels; ++channel) {
auto value = rpn_value(static_cast<rpn_int>(lightChannel(channel)));
snprintf(name, sizeof(name), "channel%u", channel);
rpn_variable_set(_rpn_ctxt, name, rpn_value(lightChannel(channel)));
rpn_variable_set(_rpn_ctxt, name, std::move(value));
}
_rpn_run = true;
}
#if SENSOR_SUPPORT
void _rpnSensorMagnitudeRead(const String& topic, unsigned char index, double reading, const char*) {
static_assert(sizeof(double) == sizeof(rpn_float), "");
String name;
name.reserve(topic.length() + 3);
name += topic;
name += index;
rpn_variable_set(_rpn_ctxt, name, rpn_value(static_cast<rpn_float>(reading)));
}
#endif
#if NTP_SUPPORT
namespace {
@ -494,7 +511,7 @@ rpn_error _rpnRfbMatcher(rpn_context& ctxt) {
return rpn_operator_error::CannotContinue;
}
void _rpnBrokerRfbridgeCallback(unsigned char protocol, const char* raw_code) {
void _rpnRfbridgeCodeHandler(unsigned char protocol, const char* raw_code) {
// remove really old codes that we have not seen in a while to avoid memory exhaustion
auto ts = millis();
@ -525,7 +542,7 @@ void _rpnRfbSetup() {
// - Repeat window is an arbitrary time, just about 3-4 more times it takes for
// a code to be sent again when holding a generic remote button
// Code counter is reset to 0 when outside of the window.
// - Stale delay allows broker callback to remove really old codes.
// - Stale delay allows the handler to remove really old codes.
// (TODO: can this happen in loop() cb instead?)
_rfb_code_repeat_window = getSetting("rfbRepeatWindow", 2000ul);
_rfb_code_match_window = getSetting("rfbMatchWindow", 2000ul);
@ -548,23 +565,27 @@ void _rpnRfbSetup() {
#endif
// Main bulk of the processing goes on in here
RfbridgeBroker::Register(_rpnBrokerRfbridgeCallback);
rfbSetCodeHandler(_rpnRfbridgeCodeHandler);
}
#endif // RFB_SUPPORT
void _rpnDeepSleep(uint64_t duration, RFMode mode);
void _rpnDeepSleepSchedule(uint64_t duration, RFMode mode) {
schedule_function([duration, mode]() {
_rpnDeepSleep(duration, mode);
});
}
void _rpnDeepSleep(uint64_t duration, RFMode mode) {
if (WiFi.getMode() != WIFI_OFF) {
wifiTurnOff();
schedule_function([duration, mode]() {
_rpnDeepSleep(duration, mode);
});
_rpnDeepSleepSchedule(duration, mode);
return;
}
deepSleep(duration, mode);
ESP.deepSleep(duration, mode);
}
void _rpnShowStack(Print& print) {
@ -1015,13 +1036,13 @@ void rpnSetup() {
lightSetReportListener(_rpnLightStatus);
#endif
#if RFB_SUPPORT
_rpnRfbSetup();
#endif
#if RFB_SUPPORT
_rpnRfbSetup();
#endif
#if SENSOR_SUPPORT
SensorReadBroker::Register(_rpnBrokerCallback);
#endif
#if SENSOR_SUPPORT
sensorSetMagnitudeRead(_rpnSensorMagnitudeRead);
#endif
espurnaRegisterReload(_rpnConfigure);
espurnaRegisterLoop(_rpnLoop);


+ 0
- 1
code/espurna/scheduler.cpp View File

@ -11,7 +11,6 @@ Adapted by Xose Pérez <xose dot perez at gmail dot com>
#if SCHEDULER_SUPPORT
#include "broker.h"
#include "light.h"
#include "ntp.h"
#include "ntp_timelib.h"


+ 23
- 11
code/espurna/sensor.cpp View File

@ -11,7 +11,6 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#if SENSOR_SUPPORT
#include "api.h"
#include "broker.h"
#include "domoticz.h"
#include "i2c.h"
#include "mqtt.h"
@ -528,9 +527,6 @@ void _magnitudeSaveEnergyTotal(sensor_magnitude_t& magnitude, bool persistent) {
// ---------------------------------------------------------------------------
BrokerBind(SensorReadBroker);
BrokerBind(SensorReportBroker);
std::vector<BaseSensor *> _sensors;
std::vector<sensor_magnitude_t> _magnitudes;
bool _sensors_ready = false;
@ -539,6 +535,22 @@ bool _sensor_realtime = API_REAL_TIME_VALUES;
unsigned long _sensor_read_interval = 1000 * SENSOR_READ_INTERVAL;
unsigned char _sensor_report_every = SENSOR_REPORT_EVERY;
// ---------------------------------------------------------------------------
using MagnitudeReadHandlers = std::forward_list<MagnitudeReadHandler>;
MagnitudeReadHandlers _magnitude_read_handlers;
void sensorSetMagnitudeRead(MagnitudeReadHandler handler) {
_magnitude_read_handlers.push_front(handler);
}
MagnitudeReadHandlers _magnitude_report_handlers;
void sensorSetMagnitudeReport(MagnitudeReadHandler handler) {
_magnitude_report_handlers.push_front(handler);
}
// -----------------------------------------------------------------------------
// Private
// -----------------------------------------------------------------------------
@ -2258,9 +2270,9 @@ void _sensorReport(unsigned char index, const sensor_magnitude_t& magnitude) {
char buffer[64];
dtostrf(magnitude.reported, 1, magnitude.decimals, buffer);
#if BROKER_SUPPORT
SensorReportBroker::Publish(magnitudeTopic(magnitude.type), magnitude.index_global, magnitude.reported, buffer);
#endif
for (auto& handler : _magnitude_report_handlers) {
handler(magnitudeTopic(magnitude.type), magnitude.index_global, magnitude.reported, buffer);
}
#if MQTT_SUPPORT
{
@ -2364,7 +2376,7 @@ namespace settings {
namespace internal {
template <>
sensor::Unit convert(const String& string) {
sensor::Unit convert(const String& value) {
auto len = value.length();
if (len && isNumber(value)) {
constexpr int Min { static_cast<int>(sensor::Unit::Min_) };
@ -2811,13 +2823,13 @@ void sensorLoop() {
// -------------------------------------------------------------
value_show = _magnitudeProcess(magnitude, value_raw);
#if BROKER_SUPPORT
{
char buffer[64];
dtostrf(value_show, 1, magnitude.decimals, buffer);
SensorReadBroker::Publish(magnitudeTopic(magnitude.type), magnitude.index_global, value_show, buffer);
for (auto& handler : _magnitude_read_handlers) {
handler(magnitudeTopic(magnitude.type), magnitude.index_global, value_show, buffer);
}
}
#endif
// -------------------------------------------------------------
// Debug


+ 3
- 4
code/espurna/sensor.h View File

@ -11,8 +11,6 @@ Copyright (C) 2020 by Maxim Prokhorov <prokhorov dot max at outlook dot com>
#include "espurna.h"
#include "broker.h"
//--------------------------------------------------------------------------------
namespace sensor {
@ -137,8 +135,9 @@ struct Value {
}
BrokerDeclare(SensorReadBroker, void(const String&, unsigned char, double, const char*));
BrokerDeclare(SensorReportBroker, void(const String&, unsigned char, double, const char*));
using MagnitudeReadHandler = void(*)(const String&, unsigned char, double, const char*);
void sensorSetMagnitudeRead(MagnitudeReadHandler handler);
void sensorSetMagnitudeReport(MagnitudeReadHandler handler);
String magnitudeUnits(unsigned char index);
String magnitudeDescription(unsigned char index);


+ 1
- 1
code/espurna/terminal.cpp View File

@ -351,7 +351,7 @@ void _terminalInitCommands() {
auto count = 1;
if (ctx.argc == 2) {
count = ctx.argv[1].toInt();
if (arg < SYSTEM_CHECK_MAX) {
if (count < SYSTEM_CHECK_MAX) {
systemStabilityCounter(count);
}
}


+ 0
- 1
code/espurna/tuya.cpp View File

@ -12,7 +12,6 @@ Copyright (C) 2019-2021 by Maxim Prokhorov <prokhorov dot max at outlook dot com
#if TUYA_SUPPORT
#include "broker.h"
#include "light.h"
#include "relay.h"
#include "rpc.h"


+ 5
- 1
code/espurna/wifi.cpp View File

@ -1340,7 +1340,7 @@ bool scanning() {
// esp32 only has a generic onEvent, but event names are not compatible with the esp8266 version.
void init() {
static auto status = WiFi.onStationModeDisconnected([](const auto& src) {
static auto status = WiFi.onStationModeDisconnected([](const WiFiEventStationModeDisconnected& src) { // aka const auto&
connection::internal::connected = false;
});
disconnect();
@ -2387,6 +2387,10 @@ void wifiToggleSta() {
wifi::sta::toggle();
}
void wifiStartAp() {
wifi::action(wifi::Action::AccessPointStart);
}
void wifiTurnOff() {
wifi::action(wifi::Action::TurnOff);
}


+ 2
- 0
code/espurna/wifi.h View File

@ -86,7 +86,9 @@ IPAddress wifiStaIp();
// Request to change the current STA / AP status
// Current state persists until reset or configuration reload
void wifiStartAp();
void wifiToggleAp();
void wifiToggleSta();
// Disconnects STA intefrace


+ 0
- 1
code/test/build/core.h View File

@ -1,6 +1,5 @@
#define ALEXA_SUPPORT 0
#define API_SUPPORT 0
#define BROKER_SUPPORT 0
#define DEBUG_SERIAL_SUPPORT 0
#define DEBUG_TELNET_SUPPORT 0
#define DEBUG_WEB_SUPPORT 0


Loading…
Cancel
Save