added time drift check command
This commit is contained in:
@@ -51,11 +51,13 @@ namespace commands
|
||||
|
||||
// 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;
|
||||
response["cmd"] = "loadCronjob";
|
||||
auto& cron = Cron::getInstance(dev);
|
||||
if(!cron.loadEvents()){
|
||||
response["cmd"] = "loadCronJob";
|
||||
auto &cron = Cron::getInstance(dev);
|
||||
if (!cron.loadEvents())
|
||||
{
|
||||
LOG_ERROR("loadCronJob failed to load events from flash");
|
||||
response["values"]["status"] = "invalid";
|
||||
return response;
|
||||
@@ -64,10 +66,10 @@ namespace commands
|
||||
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;
|
||||
response["cmd"] = "setCronjob";
|
||||
response["cmd"] = "setCronJob";
|
||||
|
||||
const auto &jobName = params["name"].as<std::string>();
|
||||
const auto &timeStr = params["cronExpr"].as<std::string>();
|
||||
@@ -92,16 +94,16 @@ namespace commands
|
||||
response["value"]["status"] = "valid";
|
||||
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;
|
||||
response["cmd"] = "getCronjob";
|
||||
response["cmd"] = "getCronJob";
|
||||
auto &cron = Cron::getInstance(dev);
|
||||
auto eventName = params["name"].as<std::string>();
|
||||
Cron::CronEvent 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";
|
||||
return response;
|
||||
}
|
||||
@@ -117,18 +119,18 @@ namespace commands
|
||||
response["values"]["cronExpr"] = cron::to_cronstr(cronExpr);
|
||||
response["values"]["action"] = action;
|
||||
|
||||
LOG_INFO("getCronjob get job [", eventName.c_str(), "]");
|
||||
LOG_INFO("getCronJob get job [", eventName.c_str(), "]");
|
||||
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;
|
||||
response["cmd"] = "delCronjob";
|
||||
response["cmd"] = "delCronJob";
|
||||
auto &cron = Cron::getInstance(dev);
|
||||
auto eventName = params["name"].as<std::string>();
|
||||
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";
|
||||
return response;
|
||||
}
|
||||
@@ -136,12 +138,13 @@ namespace commands
|
||||
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;
|
||||
response["cmd"] = "storeCronjob";
|
||||
auto& cron = Cron::getInstance(dev);
|
||||
if(!cron.storeEvents()){
|
||||
response["cmd"] = "storeCronJob";
|
||||
auto &cron = Cron::getInstance(dev);
|
||||
if (!cron.storeEvents())
|
||||
{
|
||||
LOG_ERROR("storeCronJob failed to store events in flash");
|
||||
response["values"]["status"] = "invalid";
|
||||
return response;
|
||||
@@ -406,6 +409,37 @@ namespace commands
|
||||
LOG_WARN("Comand not yet implemented");
|
||||
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 //
|
||||
|
||||
|
||||
@@ -69,11 +69,11 @@ namespace commands
|
||||
static const ArduinoJson::JsonDocument getConfig(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
||||
|
||||
// CRONJOBS //
|
||||
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 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 storeCronjob(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 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 storeCronJob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
||||
|
||||
// SETTERS //
|
||||
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 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 getTimeDrift(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms);
|
||||
};
|
||||
|
||||
static const std::map<const std::string, Command> commandMap = {
|
||||
{"setConfig", Commands::setConfig},
|
||||
{"getConfig", Commands::getConfig},
|
||||
|
||||
{"loadCronjob", Commands::loadCronjob},
|
||||
{"setCronjob", Commands::setCronjob},
|
||||
{"getCronjob", Commands::getCronjob},
|
||||
{"delCronjob", Commands::delCronjob},
|
||||
{"storeCronjob", Commands::storeCronjob},
|
||||
{"loadCronJob", Commands::loadCronJob},
|
||||
{"setCronJob", Commands::setCronJob},
|
||||
{"getCronJob", Commands::getCronJob},
|
||||
{"delCronJob", Commands::delCronJob},
|
||||
{"storeCronJob", Commands::storeCronJob},
|
||||
|
||||
{"setHPlimit", Commands::setHPlimit},
|
||||
{"setHeating", Commands::setHeating},
|
||||
@@ -107,6 +108,7 @@ namespace commands
|
||||
|
||||
{"getHPpower", Commands::getHPpower},
|
||||
{"setHeating", Commands::setHeating},
|
||||
{"getTimeDrift", Commands::getTimeDrift},
|
||||
};
|
||||
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
typedef struct
|
||||
{
|
||||
drivers::Ethernet ð
|
||||
drivers::PCF85063 &rtc;
|
||||
drivers::R4DCB08 &tmp;
|
||||
drivers::S50140 &seneca;
|
||||
|
||||
20
src/main.cpp
20
src/main.cpp
@@ -48,7 +48,7 @@ void loop()
|
||||
LOG_INFO("Temperature sensors connected ->", sensors);
|
||||
|
||||
// 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 ////////////////
|
||||
|
||||
//////////////// MQTT ////////////////
|
||||
@@ -72,11 +72,11 @@ void loop()
|
||||
return;
|
||||
}
|
||||
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))
|
||||
{ // call command from command map in this same thread (the MQTT thread)
|
||||
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())
|
||||
return;
|
||||
mqtt.publish(conf.m_mqttPublish["answers"], answer);
|
||||
@@ -104,12 +104,13 @@ void loop()
|
||||
uint8_t mqttRetries(0);
|
||||
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);
|
||||
led.setColor(led.COLOR_ORANGE);
|
||||
// rtc.setDatetime(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;
|
||||
}
|
||||
delay(100);
|
||||
@@ -118,6 +119,7 @@ void loop()
|
||||
{
|
||||
if (mqtt.connect())
|
||||
{
|
||||
buzzer.beep(250, NOTE_B);
|
||||
led.setColor(led.COLOR_GREEN);
|
||||
mqtt.subscribe(conf.m_mqttSubscribe["commands"], commandsCallback);
|
||||
break;
|
||||
@@ -133,8 +135,10 @@ void loop()
|
||||
while (true)
|
||||
{
|
||||
const uint32_t start(millis());
|
||||
const std::string timeStr(rtc.getTimeStr());
|
||||
LOG_INFO("[", k++, "] Loop - Current Datetime", timeStr.c_str());
|
||||
drivers::PCF85063::datetime_t datetime;
|
||||
rtc.readDatetime(datetime);
|
||||
const std::string timeStr(drivers::PCF85063::datetime2str(datetime));
|
||||
LOG_INFO("[", k++, "] Loop - Current Datetime UTC", timeStr.c_str());
|
||||
|
||||
{
|
||||
ArduinoJson::JsonDocument poll;
|
||||
|
||||
@@ -44,7 +44,7 @@ const bool MQTTwrapper::disconnect()
|
||||
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))
|
||||
{
|
||||
@@ -61,7 +61,7 @@ const bool MQTTwrapper::subscribe(topic_t topic, action_t action)
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool MQTTwrapper::unsubscribe(topic_t topic)
|
||||
const bool MQTTwrapper::unsubscribe(const topic_t &topic)
|
||||
{
|
||||
if (!m_actionMap.contains(topic))
|
||||
{
|
||||
@@ -83,7 +83,7 @@ const bool MQTTwrapper::connected()
|
||||
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;
|
||||
if (!m_client.connected())
|
||||
|
||||
@@ -54,10 +54,10 @@ public:
|
||||
const bool disconnect();
|
||||
const bool connected();
|
||||
|
||||
const bool subscribe(topic_t topic, action_t action);
|
||||
const bool unsubscribe(topic_t topic);
|
||||
const bool subscribe(const topic_t &topic, const action_t action);
|
||||
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:
|
||||
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