560 lines
22 KiB
C++
560 lines
22 KiB
C++
#include <commands.h>
|
|
#include <cronjobs.h>
|
|
|
|
namespace commands
|
|
{
|
|
|
|
void restart(TimerHandle_t t)
|
|
{
|
|
esp_restart();
|
|
}
|
|
const ArduinoJson::JsonDocument Commands::setBuzz(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
|
{
|
|
ArduinoJson::JsonDocument response;
|
|
dev.buzzer.beep(500, NOTE_Bb);
|
|
return response;
|
|
}
|
|
|
|
// CONFIG //
|
|
// CONFIG //
|
|
const ArduinoJson::JsonDocument Commands::setConfig(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
|
{
|
|
ArduinoJson::JsonDocument response;
|
|
auto &conf = Config::getInstance();
|
|
std::string buf;
|
|
response["cmd"] = "setConfig";
|
|
auto values = response["values"].to<JsonObject>();
|
|
if (params.isNull())
|
|
{
|
|
values["status"] = "Invalid";
|
|
return response;
|
|
}
|
|
conf.setConfig(params);
|
|
values["status"] = "Valid";
|
|
serializeJson(params, buf);
|
|
LOG_INFO("setConfig ->", buf.c_str());
|
|
TimerHandle_t resetTimer(xTimerCreate("restartTimer", pdMS_TO_TICKS(5000), false, NULL, restart));
|
|
LOG_WARN("setConfig will cause restart!");
|
|
if (resetTimer)
|
|
{
|
|
xTimerStart(resetTimer, 0);
|
|
}
|
|
return response;
|
|
}
|
|
const ArduinoJson::JsonDocument Commands::getConfig(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
|
{
|
|
ArduinoJson::JsonDocument response;
|
|
auto &conf = Config::getInstance();
|
|
std::string buf;
|
|
response["cmd"] = "getConfig";
|
|
response["values"] = conf.getConfig();
|
|
serializeJson(response["values"], buf);
|
|
LOG_INFO("getConfig ->", buf.c_str());
|
|
return response;
|
|
}
|
|
// CONFIG //
|
|
// CONFIG //
|
|
|
|
// CRONJOBS //
|
|
// CRONJOBS //
|
|
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())
|
|
{
|
|
LOG_ERROR("loadCronJob failed to load events from flash");
|
|
response["values"]["status"] = "invalid";
|
|
return response;
|
|
}
|
|
response["values"]["status"] = "valid";
|
|
return response;
|
|
}
|
|
const ArduinoJson::JsonDocument Commands::addCronJob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
|
{
|
|
ArduinoJson::JsonDocument response;
|
|
response["cmd"] = "addCronJob";
|
|
|
|
const auto &eventName = params["name"].as<std::string>();
|
|
const auto &timeStr = params["cronExpr"].as<std::string>();
|
|
const auto &actionStr = params["action"].as<std::string>();
|
|
response["values"]["name"] = eventName;
|
|
|
|
ArduinoJson::JsonDocument action;
|
|
if (ArduinoJson::deserializeJson(action, actionStr) != ArduinoJson::DeserializationError::Ok)
|
|
{
|
|
LOG_ERROR("addCronJob unable to deserialize cron job [", actionStr.c_str(), "]");
|
|
response["values"]["status"] = "invalid";
|
|
return response;
|
|
}
|
|
|
|
auto &cron = Cron::getInstance(dev);
|
|
if (!cron.addEvent(eventName, timeStr, action))
|
|
{
|
|
LOG_ERROR("addCronJob unable to add job [", actionStr.c_str(), "]");
|
|
response["values"]["status"] = "invalid";
|
|
return response;
|
|
}
|
|
LOG_INFO("addCronJob added job [", actionStr.c_str(), "]");
|
|
response["values"]["status"] = "valid";
|
|
return response;
|
|
}
|
|
const ArduinoJson::JsonDocument Commands::setCronJob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
|
{
|
|
ArduinoJson::JsonDocument response;
|
|
response["cmd"] = "setCronJob";
|
|
const auto &eventName = params["name"].as<std::string>();
|
|
const auto &statusStr = params["status"].as<std::string>();
|
|
response["values"]["name"] = eventName;
|
|
|
|
auto &cron = Cron::getInstance(dev);
|
|
if (!cron.c_statusStr2Enum.contains(statusStr))
|
|
{
|
|
LOG_ERROR("setCronJob invalid status [", statusStr.c_str(), "]");
|
|
response["values"]["status"] = "invalid";
|
|
return response;
|
|
}
|
|
cron.setEvent(eventName, cron.c_statusStr2Enum.at(statusStr));
|
|
LOG_INFO("setCronJob set job [", eventName.c_str(), "] to [", statusStr.c_str(), "]");
|
|
response["values"]["status"] = "valid";
|
|
return response;
|
|
}
|
|
const ArduinoJson::JsonDocument Commands::getCronJob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
|
{
|
|
ArduinoJson::JsonDocument response;
|
|
response["cmd"] = "getCronJob";
|
|
auto &cron = Cron::getInstance(dev);
|
|
auto eventName = params["name"].as<std::string>();
|
|
|
|
if (eventName.empty())
|
|
{
|
|
LOG_ERROR("getCronJob empty job name");
|
|
response["values"]["status"] = "invalid";
|
|
return response;
|
|
}
|
|
|
|
if (eventName == "all")
|
|
{
|
|
const auto &eventMap = cron.getAllEvents();
|
|
uint8_t eventNum(0);
|
|
for (const auto &[name, event] : eventMap)
|
|
{
|
|
response["values"][name] = event.cmd;
|
|
eventNum++;
|
|
}
|
|
LOG_INFO("getCronJob got [", eventNum, "] events");
|
|
return response;
|
|
}
|
|
|
|
Cron::CronEvent event;
|
|
response["values"]["name"] = eventName;
|
|
if (!cron.getEvent(eventName, event))
|
|
{
|
|
LOG_ERROR("getCronJob failed to get job [", eventName.c_str(), "]");
|
|
response["values"]["status"] = "invalid";
|
|
return response;
|
|
}
|
|
|
|
ArduinoJson::JsonDocument action;
|
|
action["cmd"] = event.cmd;
|
|
action["params"] = event.cmdParams;
|
|
response["values"]["cronExpr"] = cron::to_cronstr(event.cronExpr);
|
|
response["values"]["action"] = action;
|
|
LOG_INFO("getCronJob get job [", eventName.c_str(), "]");
|
|
return response;
|
|
}
|
|
const ArduinoJson::JsonDocument Commands::delCronJob(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
|
{
|
|
ArduinoJson::JsonDocument response;
|
|
response["cmd"] = "delCronJob";
|
|
auto &cron = Cron::getInstance(dev);
|
|
auto eventName = params["name"].as<std::string>();
|
|
response["values"]["name"] = eventName;
|
|
if (eventName.empty() || !cron.delEvent(eventName))
|
|
{
|
|
LOG_ERROR("delCronJob failed to delete job [", eventName.c_str(), "]");
|
|
response["values"]["status"] = "invalid";
|
|
return response;
|
|
}
|
|
response["values"]["status"] = "valid";
|
|
return response;
|
|
}
|
|
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())
|
|
{
|
|
LOG_ERROR("storeCronJob failed to store events in flash");
|
|
response["values"]["status"] = "invalid";
|
|
return response;
|
|
}
|
|
response["values"]["status"] = "valid";
|
|
return response;
|
|
}
|
|
// CRONJOBS //
|
|
// CRONJOBS //
|
|
|
|
// SETTERS //
|
|
// SETTERS //
|
|
const ArduinoJson::JsonDocument Commands::setHPlimit(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
|
{
|
|
ArduinoJson::JsonDocument response;
|
|
response["cmd"] = "setHPlimit";
|
|
if (!params["level"].is<std::string>())
|
|
{
|
|
LOG_ERROR("setHPlimit incorrect parameters");
|
|
return response;
|
|
}
|
|
const auto level = params["level"].as<std::string>();
|
|
response["values"]["level"] = level;
|
|
if (!c_hpLimitsMap.contains(level))
|
|
{
|
|
LOG_ERROR("setHPlimit invalid level", level.c_str());
|
|
response["values"]["status"] = "invalid";
|
|
return response;
|
|
}
|
|
for (const auto [lvl, ro] : c_hpLimitsMap)
|
|
{
|
|
if (ro == RO::RO_MAX)
|
|
continue; // avoid overshooting relay range
|
|
if (level == lvl && level != "UNLIMITED")
|
|
dev.io.digitalOutWrite(ro, true);
|
|
else
|
|
dev.io.digitalOutWrite(ro, false);
|
|
}
|
|
LOG_INFO("setHPlimit -> level", level.c_str());
|
|
response["values"]["status"] = "valid";
|
|
return response;
|
|
}
|
|
const ArduinoJson::JsonDocument Commands::setHeating(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
|
{
|
|
ArduinoJson::JsonDocument response;
|
|
response["cmd"] = "setHeating";
|
|
if (params.isNull())
|
|
{
|
|
LOG_ERROR("setHeating incorrect paramaters");
|
|
return response;
|
|
}
|
|
for (const auto [lvl, ro] : c_heatingValveMap)
|
|
{
|
|
if (params[lvl].isNull())
|
|
continue;
|
|
if (params[lvl] == "ON")
|
|
{
|
|
dev.io.digitalOutWrite(ro, true);
|
|
response["values"][lvl] = "ON";
|
|
LOG_INFO("setHeating -> ", lvl.c_str(), "ON");
|
|
}
|
|
else if (params[lvl] == "OFF")
|
|
{
|
|
dev.io.digitalOutWrite(ro, false);
|
|
response["values"][lvl] = "OFF";
|
|
LOG_INFO("setHeating -> ", lvl.c_str(), "OFF");
|
|
}
|
|
else
|
|
{
|
|
response["values"][lvl] = "invalid";
|
|
LOG_ERROR("setHeating invalid valve state");
|
|
}
|
|
}
|
|
return response;
|
|
}
|
|
void resetZone(TimerHandle_t th)
|
|
{
|
|
devices_t *dev = (devices_t *)pvTimerGetTimerID(th);
|
|
const char *timerName = pcTimerGetName(th);
|
|
LOG_INFO("setIrrigation shutdown zone [", timerName, "]");
|
|
if (!c_irrigationValveMap.contains(timerName))
|
|
{
|
|
LOG_ERROR("Irrigation timer name invalid");
|
|
return;
|
|
}
|
|
dev->io.digitalOutWrite(c_irrigationValveMap.at(timerName), false);
|
|
c_irrigationTimerMap.at(timerName).second = NULL; // reset timer handle for this timer
|
|
xTimerDelete(th, 0); // delete the timer on expiry
|
|
}
|
|
void resetWaterPump(TimerHandle_t th)
|
|
{
|
|
devices_t *dev = (devices_t *)pvTimerGetTimerID(th);
|
|
LOG_INFO("setIrrigation shutdown pump");
|
|
dev->io.digitalOutWrite(RO::PUMP_IRR, false);
|
|
s_irrigationPumpTimer = NULL;
|
|
xTimerDelete(th, 0); // delete the timer on expiry
|
|
}
|
|
const ArduinoJson::JsonDocument Commands::setIrrigation(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
|
{
|
|
ArduinoJson::JsonDocument response;
|
|
auto &conf = Config::getInstance();
|
|
response["cmd"] = "setIrrigation";
|
|
if (params.isNull())
|
|
{
|
|
LOG_ERROR("setIrrigation incorrect paramaters");
|
|
return response;
|
|
}
|
|
const std::string zone(params["zone"].as<std::string>());
|
|
const uint16_t tOn(params["timeOn"].as<uint16_t>());
|
|
const uint16_t tPause(params["timePause"].as<uint16_t>());
|
|
response["values"]["zone"] = zone;
|
|
|
|
if (zone == "stop")
|
|
{ // stop all zones and reset timers
|
|
LOG_INFO("setIrrigation stop all zones");
|
|
for (auto &h : c_irrigationTimerMap)
|
|
{
|
|
const auto zoneName = h.first;
|
|
auto &timerHandle = h.second.second; // get the timer handle
|
|
if (timerHandle) // if handle is not null (not from a deleted timer)
|
|
{
|
|
if (xTimerIsTimerActive(timerHandle)) // stop the timer if active
|
|
{
|
|
LOG_INFO("setIrrigation stopping timer", zoneName.c_str());
|
|
xTimerStop(timerHandle, 0);
|
|
xTimerDelete(timerHandle, pdMS_TO_TICKS(10)); // delete it
|
|
timerHandle = NULL;
|
|
}
|
|
}
|
|
LOG_INFO("setIrrigation closing", zoneName.c_str());
|
|
dev.io.digitalOutWrite(c_irrigationValveMap.at(zoneName), false); // shutdown the valve
|
|
}
|
|
if (s_irrigationPumpTimer)
|
|
{
|
|
xTimerChangePeriod(s_irrigationPumpTimer, pdMS_TO_TICKS(30 * 1000), 0); // shutdown the pump in 30s after the stop
|
|
xTimerReset(s_irrigationPumpTimer, 0);
|
|
}
|
|
response["values"]["status"] = "stop";
|
|
return response;
|
|
}
|
|
|
|
if (!s_rainOverride && !dev.io.digitalInRead(DI::RAIN)) // verify rain sensor and override value (rain sensor input is inverted)
|
|
{
|
|
LOG_WARN("setIrrigation skipping zone [", zone.c_str(), "] because its raining");
|
|
response["values"]["status"] = "rain";
|
|
return response;
|
|
}
|
|
|
|
response["values"]["timeOn"] = tOn;
|
|
response["values"]["timePause"] = tPause;
|
|
if (!c_irrigationValveMap.contains(zone) || tOn <= 0 || tPause <= 0) // verify if zone is a valid map key
|
|
{
|
|
LOG_ERROR("setIrrigation incorrect zone[", zone.c_str(), "] or time values tOn[", tOn, "] tPause[", tPause, "]");
|
|
response["values"]["status"] = "invalid";
|
|
return response;
|
|
}
|
|
|
|
// verify if timer was already started, zone is already on
|
|
const auto timerName = c_irrigationTimerMap.at(zone).first;
|
|
const auto zoneIoNumber = c_irrigationValveMap.at(zone);
|
|
auto &timerHandle = c_irrigationTimerMap.at(zone).second;
|
|
|
|
if (timerHandle)
|
|
{ // this timer was alteady started, ignore command
|
|
LOG_WARN("setIrrigation zone [", timerName, "] already started");
|
|
response["values"]["status"] = "conflict";
|
|
return response;
|
|
}
|
|
|
|
const uint32_t pumpTime((tOn + 30) * 1000);
|
|
const uint32_t zoneTime(tOn * 1000);
|
|
|
|
if (!s_irrigationPumpTimer) // Pump has not yet started
|
|
{
|
|
s_irrigationPumpTimer = xTimerCreate("pumpTimer", pdMS_TO_TICKS(pumpTime), false, (void *)&dev, resetWaterPump);
|
|
dev.io.digitalOutWrite(RO::PUMP_IRR, true);
|
|
xTimerStart(s_irrigationPumpTimer, 0); // immediate start pump timer
|
|
LOG_INFO("setIrrigation pump time", pumpTime);
|
|
}
|
|
else
|
|
{
|
|
const auto currentRemaining(xTimerGetExpiryTime(s_irrigationPumpTimer) - xTaskGetTickCount());
|
|
const auto newRemaining(pumpTime);
|
|
const auto newPeriod(std::max(newRemaining, currentRemaining));
|
|
xTimerChangePeriod(s_irrigationPumpTimer, newPeriod, 0); // set new period based on timing of new zone
|
|
xTimerReset(s_irrigationPumpTimer, 0); // if timer was already started, restart
|
|
LOG_INFO("setIrrigation pump time reset", newRemaining);
|
|
}
|
|
|
|
TimerHandle_t shTimer(xTimerCreate(timerName, pdMS_TO_TICKS(zoneTime), false, (void *)&dev, resetZone));
|
|
if (shTimer)
|
|
{
|
|
dev.io.digitalOutWrite(zoneIoNumber, true);
|
|
// controllare riempimento serbatoio con controllo del pressostato, magari in un timer
|
|
xTimerStart(shTimer, 0);
|
|
timerHandle = shTimer;
|
|
response["values"]["status"] = "valid";
|
|
LOG_INFO("setIrrigation zone [", timerName, "] tOn[", tOn, "] tPause[", tPause, "]");
|
|
}
|
|
return response;
|
|
}
|
|
const ArduinoJson::JsonDocument Commands::setRainOverride(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
|
{
|
|
ArduinoJson::JsonDocument response;
|
|
response["cmd"] = "setRainOverride";
|
|
if (params.isNull())
|
|
{
|
|
LOG_ERROR("setRainOverride incorrect paramaters");
|
|
return response;
|
|
}
|
|
s_rainOverride = params["status"].as<std::string>() == "True" ? true : false;
|
|
response["values"]["status"] = "valid";
|
|
LOG_INFO("setRainOverride [", s_rainOverride ? "True]" : "False]");
|
|
return response;
|
|
}
|
|
const ArduinoJson::JsonDocument Commands::setTimeNTP(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
|
{
|
|
ArduinoJson::JsonDocument response;
|
|
response["cmd"] = "setTimeNTP";
|
|
auto ð = dev.eth;
|
|
auto &rtc = dev.rtc;
|
|
|
|
time_t ntpTime;
|
|
auto ntpOk = eth.getNtpTime(ntpTime);
|
|
|
|
drivers::PCF85063::datetime_t rtcTime(drivers::PCF85063::fromEpoch(ntpTime));
|
|
auto rtcOk = rtc.setDatetime(rtcTime);
|
|
|
|
if (!rtcOk || !ntpOk)
|
|
{
|
|
response["values"]["status"] = "invalid";
|
|
return response;
|
|
}
|
|
|
|
response["values"]["status"] = "valid";
|
|
response["values"]["time"] = rtc.getTimeStr();
|
|
LOG_INFO("setTimeNTP -> RTC is [", response["status"]["time"].as<std::string>().c_str(), "]");
|
|
return response;
|
|
}
|
|
// SETTERS //
|
|
// SETTERS //
|
|
|
|
// GETTERS //
|
|
// GETTERS //
|
|
const ArduinoJson::JsonDocument Commands::getHPpower(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
|
{
|
|
ArduinoJson::JsonDocument response;
|
|
response["cmd"] = "getHPpower";
|
|
const auto pinfo = dev.seneca.getAll();
|
|
auto values = response["values"].to<JsonObject>();
|
|
values["power"] = pinfo.pAct;
|
|
values["current"] = pinfo.a;
|
|
values["voltage"] = pinfo.v;
|
|
values["energy"] = pinfo.whPar;
|
|
LOG_INFO("getHPpower -> power", pinfo.pAct, "current", pinfo.a, "voltage", pinfo.v, "energy", pinfo.whPar);
|
|
return response;
|
|
}
|
|
const ArduinoJson::JsonDocument Commands::getInputStatus(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
|
{
|
|
ArduinoJson::JsonDocument response;
|
|
response["cmd"] = "getInputStatus";
|
|
const std::vector<bool> inStatus(dev.io.digitalInReadPort());
|
|
if (inStatus.empty() || inStatus.size() != dev.io.getInNum())
|
|
{
|
|
response["values"] = "invalid";
|
|
return response;
|
|
}
|
|
uint8_t i(0);
|
|
for (auto s : inStatus)
|
|
{
|
|
response["values"][DI_2str.at(i++)] = s;
|
|
}
|
|
LOG_INFO("getInputStatus ->", printBoolVec(inStatus).c_str());
|
|
return response;
|
|
}
|
|
const ArduinoJson::JsonDocument Commands::getOutputStatus(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
|
{
|
|
ArduinoJson::JsonDocument response;
|
|
response["cmd"] = "getOutputStatus";
|
|
const std::vector<bool> inStatus(dev.io.digitalOutReadPort());
|
|
if (inStatus.empty() || inStatus.size() != dev.io.getOutNum())
|
|
{
|
|
response["values"] = "invalid";
|
|
return response;
|
|
}
|
|
uint8_t i(0);
|
|
for (auto s : inStatus)
|
|
{
|
|
response["values"][RO_2str.at(i++)] = s;
|
|
}
|
|
LOG_INFO("getOutputStatus ->", printBoolVec(inStatus).c_str());
|
|
return response;
|
|
}
|
|
const ArduinoJson::JsonDocument Commands::getTemperatures(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
|
{
|
|
ArduinoJson::JsonDocument response;
|
|
LOG_WARN("Comand not yet implemented");
|
|
return response;
|
|
}
|
|
const ArduinoJson::JsonDocument Commands::getWaterInfo(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
|
{
|
|
ArduinoJson::JsonDocument response;
|
|
LOG_WARN("Comand not yet implemented");
|
|
return response;
|
|
}
|
|
const ArduinoJson::JsonDocument Commands::getTankInfo(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
|
{
|
|
ArduinoJson::JsonDocument response;
|
|
LOG_WARN("Comand not yet implemented");
|
|
return response;
|
|
}
|
|
const ArduinoJson::JsonDocument Commands::getRainInfo(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
|
{
|
|
ArduinoJson::JsonDocument response;
|
|
const auto rain = !dev.io.digitalInRead(DI::RAIN) ? "True" : "False";
|
|
response["cmd"] = "getRainInfo";
|
|
response["values"]["status"] = rain;
|
|
LOG_INFO("getRainInfo -> ", rain);
|
|
return response;
|
|
}
|
|
const ArduinoJson::JsonDocument Commands::getIrrigation(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
|
{
|
|
ArduinoJson::JsonDocument response;
|
|
LOG_WARN("Comand not yet implemented");
|
|
return response;
|
|
}
|
|
const ArduinoJson::JsonDocument Commands::getRainOverride(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
|
{
|
|
ArduinoJson::JsonDocument response;
|
|
const auto ovr = s_rainOverride ? "True" : "False";
|
|
response["cmd"] = "getRainOverride";
|
|
response["values"]["rainOverride"] = ovr;
|
|
LOG_INFO("getRainOverride -> ", ovr);
|
|
return response;
|
|
}
|
|
const ArduinoJson::JsonDocument Commands::getTimeDrift(const devices_t &dev, const ArduinoJson::JsonDocument ¶ms)
|
|
{
|
|
ArduinoJson::JsonDocument response;
|
|
response["cmd"] = "getTimeDrift";
|
|
auto ð = 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["values"]["status"] = "invalid";
|
|
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"]["status"] = "valid";
|
|
response["values"]["drift"] = (uint32_t)timeDiff.count();
|
|
response["values"]["direction"] = "RTC is [" + std::string(direction) + "] NTP time";
|
|
LOG_INFO("getTimeDrift -> RTC is [", (int32_t)timeDiff.count(), "] sec, [", std::string(direction).c_str(), "] NTP time");
|
|
return response;
|
|
}
|
|
// GETTERS //
|
|
// GETTERS //
|
|
|
|
} |