added time drift check command
This commit is contained in:
54
esp32-s3-waveshare8.json
Normal file
54
esp32-s3-waveshare8.json
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "esp32s3_out.ld",
|
||||||
|
"partitions": "app3M_fat9M_16MB.csv"
|
||||||
|
},
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": [
|
||||||
|
"-DARDUINO_ESP32S3_DEV",
|
||||||
|
"-DARDUINO_USB_MODE=1",
|
||||||
|
"-DARDUINO_RUNNING_CORE=1",
|
||||||
|
"-DARDUINO_EVENT_RUNNING_CORE=1",
|
||||||
|
"-DARDUINO_USB_CDC_ON_BOOT=1"
|
||||||
|
],
|
||||||
|
"partitions": "app3M_fat9M_16MB.csv",
|
||||||
|
"f_cpu": "240000000L",
|
||||||
|
"f_flash": "80000000L",
|
||||||
|
"flash_mode": "qio",
|
||||||
|
"hwids": [
|
||||||
|
[
|
||||||
|
"0x303A",
|
||||||
|
"0x1001"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"mcu": "esp32s3",
|
||||||
|
"variant": "esp32s3"
|
||||||
|
},
|
||||||
|
"connectivity": [
|
||||||
|
"bluetooth",
|
||||||
|
"wifi",
|
||||||
|
"ethernet"
|
||||||
|
],
|
||||||
|
"debug": {
|
||||||
|
"default_tool": "esp-builtin",
|
||||||
|
"onboard_tools": [
|
||||||
|
"esp-builtin"
|
||||||
|
],
|
||||||
|
"openocd_target": "esp32s3.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": [
|
||||||
|
"arduino",
|
||||||
|
"espidf"
|
||||||
|
],
|
||||||
|
"name": "Espressif ESP32-S3-Waveshare_8RO-8DI",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "16MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 16777216,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 921600
|
||||||
|
},
|
||||||
|
"url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/user-guide-devkitm-1.html",
|
||||||
|
"vendor": "Espressif"
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <DebugLog.h>
|
#include <DebugLog.h>
|
||||||
#include "I2C_Driver.h"
|
#include "I2C_Driver.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
// PCF85063_ADDRESS
|
// PCF85063_ADDRESS
|
||||||
#define PCF85063_ADDRESS (0x51)
|
#define PCF85063_ADDRESS (0x51)
|
||||||
|
|||||||
@@ -51,11 +51,13 @@ namespace commands
|
|||||||
|
|
||||||
// CRONJOBS //
|
// CRONJOBS //
|
||||||
// CRONJOBS //
|
// CRONJOBS //
|
||||||
const ArduinoJson::JsonDocument Commands::loadCronjob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms){
|
const ArduinoJson::JsonDocument Commands::loadCronJob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
||||||
|
{
|
||||||
ArduinoJson::JsonDocument response;
|
ArduinoJson::JsonDocument response;
|
||||||
response["cmd"] = "loadCronjob";
|
response["cmd"] = "loadCronJob";
|
||||||
auto& cron = Cron::getInstance(dev);
|
auto &cron = Cron::getInstance(dev);
|
||||||
if(!cron.loadEvents()){
|
if (!cron.loadEvents())
|
||||||
|
{
|
||||||
LOG_ERROR("loadCronJob failed to load events from flash");
|
LOG_ERROR("loadCronJob failed to load events from flash");
|
||||||
response["values"]["status"] = "invalid";
|
response["values"]["status"] = "invalid";
|
||||||
return response;
|
return response;
|
||||||
@@ -64,10 +66,10 @@ namespace commands
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ArduinoJson::JsonDocument Commands::setCronjob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
const ArduinoJson::JsonDocument Commands::setCronJob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
||||||
{
|
{
|
||||||
ArduinoJson::JsonDocument response;
|
ArduinoJson::JsonDocument response;
|
||||||
response["cmd"] = "setCronjob";
|
response["cmd"] = "setCronJob";
|
||||||
|
|
||||||
const auto &jobName = params["name"].as<std::string>();
|
const auto &jobName = params["name"].as<std::string>();
|
||||||
const auto &timeStr = params["cronExpr"].as<std::string>();
|
const auto &timeStr = params["cronExpr"].as<std::string>();
|
||||||
@@ -92,16 +94,16 @@ namespace commands
|
|||||||
response["value"]["status"] = "valid";
|
response["value"]["status"] = "valid";
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
const ArduinoJson::JsonDocument Commands::getCronjob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
const ArduinoJson::JsonDocument Commands::getCronJob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
||||||
{
|
{
|
||||||
ArduinoJson::JsonDocument response;
|
ArduinoJson::JsonDocument response;
|
||||||
response["cmd"] = "getCronjob";
|
response["cmd"] = "getCronJob";
|
||||||
auto &cron = Cron::getInstance(dev);
|
auto &cron = Cron::getInstance(dev);
|
||||||
auto eventName = params["name"].as<std::string>();
|
auto eventName = params["name"].as<std::string>();
|
||||||
Cron::CronEvent event;
|
Cron::CronEvent event;
|
||||||
if (eventName.empty() || !cron.getEvent(eventName, event))
|
if (eventName.empty() || !cron.getEvent(eventName, event))
|
||||||
{
|
{
|
||||||
LOG_ERROR("delCronjob failed to get job [", eventName.c_str(), "]");
|
LOG_ERROR("getCronJob failed to get job [", eventName.c_str(), "]");
|
||||||
response["values"]["status"] = "invalid";
|
response["values"]["status"] = "invalid";
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
@@ -117,18 +119,18 @@ namespace commands
|
|||||||
response["values"]["cronExpr"] = cron::to_cronstr(cronExpr);
|
response["values"]["cronExpr"] = cron::to_cronstr(cronExpr);
|
||||||
response["values"]["action"] = action;
|
response["values"]["action"] = action;
|
||||||
|
|
||||||
LOG_INFO("getCronjob get job [", eventName.c_str(), "]");
|
LOG_INFO("getCronJob get job [", eventName.c_str(), "]");
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
const ArduinoJson::JsonDocument Commands::delCronjob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
const ArduinoJson::JsonDocument Commands::delCronJob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
||||||
{
|
{
|
||||||
ArduinoJson::JsonDocument response;
|
ArduinoJson::JsonDocument response;
|
||||||
response["cmd"] = "delCronjob";
|
response["cmd"] = "delCronJob";
|
||||||
auto &cron = Cron::getInstance(dev);
|
auto &cron = Cron::getInstance(dev);
|
||||||
auto eventName = params["name"].as<std::string>();
|
auto eventName = params["name"].as<std::string>();
|
||||||
if (eventName.empty() || !cron.delEvent(eventName))
|
if (eventName.empty() || !cron.delEvent(eventName))
|
||||||
{
|
{
|
||||||
LOG_ERROR("delCronjob failed to delete job [", eventName.c_str(), "]");
|
LOG_ERROR("delCronJob failed to delete job [", eventName.c_str(), "]");
|
||||||
response["values"]["status"] = "invalid";
|
response["values"]["status"] = "invalid";
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
@@ -136,12 +138,13 @@ namespace commands
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ArduinoJson::JsonDocument Commands::storeCronjob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
const ArduinoJson::JsonDocument Commands::storeCronJob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
||||||
{
|
{
|
||||||
ArduinoJson::JsonDocument response;
|
ArduinoJson::JsonDocument response;
|
||||||
response["cmd"] = "storeCronjob";
|
response["cmd"] = "storeCronJob";
|
||||||
auto& cron = Cron::getInstance(dev);
|
auto &cron = Cron::getInstance(dev);
|
||||||
if(!cron.storeEvents()){
|
if (!cron.storeEvents())
|
||||||
|
{
|
||||||
LOG_ERROR("storeCronJob failed to store events in flash");
|
LOG_ERROR("storeCronJob failed to store events in flash");
|
||||||
response["values"]["status"] = "invalid";
|
response["values"]["status"] = "invalid";
|
||||||
return response;
|
return response;
|
||||||
@@ -406,6 +409,37 @@ namespace commands
|
|||||||
LOG_WARN("Comand not yet implemented");
|
LOG_WARN("Comand not yet implemented");
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ArduinoJson::JsonDocument Commands::getTimeDrift(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
||||||
|
{
|
||||||
|
ArduinoJson::JsonDocument response;
|
||||||
|
response["cmd"] = "getTimeDrift";
|
||||||
|
auto& eth= dev.eth;
|
||||||
|
auto& rtc = dev.rtc;
|
||||||
|
|
||||||
|
time_t ntpTime;
|
||||||
|
auto ntpOk = eth.getNtpTime(ntpTime);
|
||||||
|
|
||||||
|
drivers::PCF85063::datetime_t rtcTime;
|
||||||
|
auto rtcOk = rtc.readDatetime(rtcTime);
|
||||||
|
auto rtcTimeTm = drivers::PCF85063::datetime2tm(rtcTime);
|
||||||
|
|
||||||
|
if (!rtcOk || !ntpOk) {
|
||||||
|
response["value"]["status"] = "unable to get time";
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ntpTimePoint = std::chrono::system_clock::from_time_t(ntpTime);
|
||||||
|
auto rtcTimePoint = std::chrono::system_clock::from_time_t(std::mktime(&rtcTimeTm));
|
||||||
|
|
||||||
|
auto timeDiff = std::chrono::duration_cast<std::chrono::seconds>(ntpTimePoint - rtcTimePoint);
|
||||||
|
auto direction = timeDiff.count() >= 0 ? "BEYOND" : "AHEAD";
|
||||||
|
|
||||||
|
response["values"]["drift"] = timeDiff.count();
|
||||||
|
response["values"]["direction"] = "RTC is [" + std::string(direction) + "] NTP time";
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
// GETTERS //
|
// GETTERS //
|
||||||
// GETTERS //
|
// GETTERS //
|
||||||
|
|
||||||
|
|||||||
@@ -69,11 +69,11 @@ namespace commands
|
|||||||
static const ArduinoJson::JsonDocument getConfig(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
static const ArduinoJson::JsonDocument getConfig(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
||||||
|
|
||||||
// CRONJOBS //
|
// CRONJOBS //
|
||||||
static const ArduinoJson::JsonDocument loadCronjob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
static const ArduinoJson::JsonDocument loadCronJob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
||||||
static const ArduinoJson::JsonDocument setCronjob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
static const ArduinoJson::JsonDocument setCronJob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
||||||
static const ArduinoJson::JsonDocument getCronjob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
static const ArduinoJson::JsonDocument getCronJob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
||||||
static const ArduinoJson::JsonDocument delCronjob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
static const ArduinoJson::JsonDocument delCronJob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
||||||
static const ArduinoJson::JsonDocument storeCronjob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
static const ArduinoJson::JsonDocument storeCronJob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
||||||
|
|
||||||
// SETTERS //
|
// SETTERS //
|
||||||
static const ArduinoJson::JsonDocument setHPlimit(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
static const ArduinoJson::JsonDocument setHPlimit(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
||||||
@@ -89,17 +89,18 @@ namespace commands
|
|||||||
static const ArduinoJson::JsonDocument getTankInfo(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
static const ArduinoJson::JsonDocument getTankInfo(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
||||||
static const ArduinoJson::JsonDocument getRainInfo(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
static const ArduinoJson::JsonDocument getRainInfo(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
||||||
static const ArduinoJson::JsonDocument getIrrigation(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
static const ArduinoJson::JsonDocument getIrrigation(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
||||||
|
static const ArduinoJson::JsonDocument getTimeDrift(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::map<const std::string, Command> commandMap = {
|
static const std::map<const std::string, Command> commandMap = {
|
||||||
{"setConfig", Commands::setConfig},
|
{"setConfig", Commands::setConfig},
|
||||||
{"getConfig", Commands::getConfig},
|
{"getConfig", Commands::getConfig},
|
||||||
|
|
||||||
{"loadCronjob", Commands::loadCronjob},
|
{"loadCronJob", Commands::loadCronJob},
|
||||||
{"setCronjob", Commands::setCronjob},
|
{"setCronJob", Commands::setCronJob},
|
||||||
{"getCronjob", Commands::getCronjob},
|
{"getCronJob", Commands::getCronJob},
|
||||||
{"delCronjob", Commands::delCronjob},
|
{"delCronJob", Commands::delCronJob},
|
||||||
{"storeCronjob", Commands::storeCronjob},
|
{"storeCronJob", Commands::storeCronJob},
|
||||||
|
|
||||||
{"setHPlimit", Commands::setHPlimit},
|
{"setHPlimit", Commands::setHPlimit},
|
||||||
{"setHeating", Commands::setHeating},
|
{"setHeating", Commands::setHeating},
|
||||||
@@ -107,6 +108,7 @@ namespace commands
|
|||||||
|
|
||||||
{"getHPpower", Commands::getHPpower},
|
{"getHPpower", Commands::getHPpower},
|
||||||
{"setHeating", Commands::setHeating},
|
{"setHeating", Commands::setHeating},
|
||||||
|
{"getTimeDrift", Commands::getTimeDrift},
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
drivers::Ethernet ð
|
||||||
drivers::PCF85063 &rtc;
|
drivers::PCF85063 &rtc;
|
||||||
drivers::R4DCB08 &tmp;
|
drivers::R4DCB08 &tmp;
|
||||||
drivers::S50140 &seneca;
|
drivers::S50140 &seneca;
|
||||||
|
|||||||
20
src/main.cpp
20
src/main.cpp
@@ -48,7 +48,7 @@ void loop()
|
|||||||
LOG_INFO("Temperature sensors connected ->", sensors);
|
LOG_INFO("Temperature sensors connected ->", sensors);
|
||||||
|
|
||||||
// Create device structure to pass all devices in the callbacks as needed
|
// Create device structure to pass all devices in the callbacks as needed
|
||||||
devices_t devices(rtc, tmp, seneca, buzzer, led, io);
|
devices_t devices(eth, rtc, tmp, seneca, buzzer, led, io);
|
||||||
//////////////// DEVICES ////////////////
|
//////////////// DEVICES ////////////////
|
||||||
|
|
||||||
//////////////// MQTT ////////////////
|
//////////////// MQTT ////////////////
|
||||||
@@ -72,11 +72,11 @@ void loop()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const std::string cmd = doc["cmd"].as<std::string>();
|
const std::string cmd = doc["cmd"].as<std::string>();
|
||||||
ArduinoJson::JsonDocument params = doc["params"];
|
const ArduinoJson::JsonDocument params = doc["params"];
|
||||||
if (commands::commandMap.contains(cmd))
|
if (commands::commandMap.contains(cmd))
|
||||||
{ // call command from command map in this same thread (the MQTT thread)
|
{ // call command from command map in this same thread (the MQTT thread)
|
||||||
LOG_INFO("Executing command", cmd.c_str());
|
LOG_INFO("Executing command", cmd.c_str());
|
||||||
auto answer = std::move(commands::commandMap.at(cmd)(devices, params)); // here the magic happens
|
const auto answer = std::move(commands::commandMap.at(cmd)(devices, params)); // here the magic happens
|
||||||
if (answer.isNull())
|
if (answer.isNull())
|
||||||
return;
|
return;
|
||||||
mqtt.publish(conf.m_mqttPublish["answers"], answer);
|
mqtt.publish(conf.m_mqttPublish["answers"], answer);
|
||||||
@@ -104,12 +104,13 @@ void loop()
|
|||||||
uint8_t mqttRetries(0);
|
uint8_t mqttRetries(0);
|
||||||
while (timeRetries++ < conf.m_ntpRetries)
|
while (timeRetries++ < conf.m_ntpRetries)
|
||||||
{
|
{
|
||||||
if (eth.getNtpTime(ntpTime) && rtc.setDatetime(drivers::PCF85063::fromEpoch(ntpTime)))
|
if (eth.getNtpTime(ntpTime))
|
||||||
{
|
{ // skip NTP update for drift testing
|
||||||
buzzer.beep(250, NOTE_A);
|
buzzer.beep(250, NOTE_A);
|
||||||
led.setColor(led.COLOR_ORANGE);
|
led.setColor(led.COLOR_ORANGE);
|
||||||
|
// rtc.setDatetime(drivers::PCF85063::fromEpoch(ntpTime));
|
||||||
const drivers::PCF85063::datetime_t dt(drivers::PCF85063::fromEpoch(ntpTime));
|
const drivers::PCF85063::datetime_t dt(drivers::PCF85063::fromEpoch(ntpTime));
|
||||||
LOG_INFO("NTP Time Update: ", drivers::PCF85063::datetime2str(dt).c_str());
|
LOG_INFO("NTP Time: ", drivers::PCF85063::datetime2str(dt).c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
delay(100);
|
delay(100);
|
||||||
@@ -118,6 +119,7 @@ void loop()
|
|||||||
{
|
{
|
||||||
if (mqtt.connect())
|
if (mqtt.connect())
|
||||||
{
|
{
|
||||||
|
buzzer.beep(250, NOTE_B);
|
||||||
led.setColor(led.COLOR_GREEN);
|
led.setColor(led.COLOR_GREEN);
|
||||||
mqtt.subscribe(conf.m_mqttSubscribe["commands"], commandsCallback);
|
mqtt.subscribe(conf.m_mqttSubscribe["commands"], commandsCallback);
|
||||||
break;
|
break;
|
||||||
@@ -133,8 +135,10 @@ void loop()
|
|||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
const uint32_t start(millis());
|
const uint32_t start(millis());
|
||||||
const std::string timeStr(rtc.getTimeStr());
|
drivers::PCF85063::datetime_t datetime;
|
||||||
LOG_INFO("[", k++, "] Loop - Current Datetime", timeStr.c_str());
|
rtc.readDatetime(datetime);
|
||||||
|
const std::string timeStr(drivers::PCF85063::datetime2str(datetime));
|
||||||
|
LOG_INFO("[", k++, "] Loop - Current Datetime UTC", timeStr.c_str());
|
||||||
|
|
||||||
{
|
{
|
||||||
ArduinoJson::JsonDocument poll;
|
ArduinoJson::JsonDocument poll;
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ const bool MQTTwrapper::disconnect()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool MQTTwrapper::subscribe(topic_t topic, action_t action)
|
const bool MQTTwrapper::subscribe(const topic_t &topic, const action_t action)
|
||||||
{
|
{
|
||||||
if (m_actionMap.contains(topic))
|
if (m_actionMap.contains(topic))
|
||||||
{
|
{
|
||||||
@@ -61,7 +61,7 @@ const bool MQTTwrapper::subscribe(topic_t topic, action_t action)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool MQTTwrapper::unsubscribe(topic_t topic)
|
const bool MQTTwrapper::unsubscribe(const topic_t &topic)
|
||||||
{
|
{
|
||||||
if (!m_actionMap.contains(topic))
|
if (!m_actionMap.contains(topic))
|
||||||
{
|
{
|
||||||
@@ -83,7 +83,7 @@ const bool MQTTwrapper::connected()
|
|||||||
return m_loopHandle != NULL;
|
return m_loopHandle != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool MQTTwrapper::publish(topic_t topic, const ArduinoJson::JsonDocument obj)
|
const bool MQTTwrapper::publish(const topic_t &topic, const ArduinoJson::JsonDocument obj)
|
||||||
{
|
{
|
||||||
std::string message;
|
std::string message;
|
||||||
if (!m_client.connected())
|
if (!m_client.connected())
|
||||||
|
|||||||
@@ -54,10 +54,10 @@ public:
|
|||||||
const bool disconnect();
|
const bool disconnect();
|
||||||
const bool connected();
|
const bool connected();
|
||||||
|
|
||||||
const bool subscribe(topic_t topic, action_t action);
|
const bool subscribe(const topic_t &topic, const action_t action);
|
||||||
const bool unsubscribe(topic_t topic);
|
const bool unsubscribe(const topic_t &topic);
|
||||||
|
|
||||||
const bool publish(topic_t topic, const ArduinoJson::JsonDocument obj);
|
const bool publish(const topic_t &topic, const ArduinoJson::JsonDocument obj);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void callback(char *topic, uint8_t *payload, unsigned int length); // C-style callback only to invoke onMessage
|
static void callback(char *topic, uint8_t *payload, unsigned int length); // C-style callback only to invoke onMessage
|
||||||
|
|||||||
Reference in New Issue
Block a user