Добавляем планировщик по типу Cron

This commit is contained in:
2022-10-31 19:33:01 +03:00
parent b8f403f1f1
commit 868c7bf4f2
7 changed files with 1653 additions and 98 deletions

View File

@@ -1,5 +1,6 @@
#include "ESPConfiguration.h"
void* getAPI_Cron(String subtype, String params);
void* getAPI_Loging(String subtype, String params);
void* getAPI_LogingDaily(String subtype, String params);
void* getAPI_Timer(String subtype, String params);
@@ -34,6 +35,7 @@ void* getAPI_Ws2812b(String subtype, String params);
void* getAPI(String subtype, String params) {
void* tmpAPI;
if ((tmpAPI = getAPI_Cron(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_Loging(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_LogingDaily(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_Timer(subtype, params)) != nullptr) return tmpAPI;

View File

@@ -0,0 +1,111 @@
#include "NTP.h"
#include "Global.h"
#include "classes/IoTItem.h"
extern "C" {
#include "ccronexpr/ccronexpr.h"
}
class Cron : public IoTItem {
private:
bool _pause = false;
String _format = "";
cron_expr _expr;
time_t _nextAlarm = 0;
public:
Cron(String parameters): IoTItem(parameters) {
jsonRead(parameters, F("formatNextAlarm"), _format);
initCron();
}
void initCron() {
const char* err = NULL;
memset(&_expr, 0, sizeof(_expr));
cron_parse_expr(value.valS.c_str(), &_expr, &err);
if (err) {
_pause = true;
_nextAlarm = 0;
memset(&_expr, 0, sizeof(_expr));
SerialPrint("E", "Cron", F("The Cron string did not apply."), _id);
} else
updateNextAlarm(true);
}
void updateNextAlarm(bool forced) {
if (!_pause && _time_isTrust) {
if (forced || (_nextAlarm <= gmtTimeToLocal(unixTime))) {
// update alarm if next trigger is not yet in the future
_nextAlarm = cron_next(&_expr, gmtTimeToLocal(unixTime));
}
}
}
String getNextAlarmF() {
if (_pause) return "Pause";
if (!_time_isTrust) return "No time";
struct tm* timeinfo;
char buffer [80];
timeinfo = localtime(&_nextAlarm);
strftime(buffer, 80, _format.c_str(), timeinfo);
return buffer;
}
String getValue() {
return getNextAlarmF();
}
void setValue(const IoTValue& Value, bool genEvent) {
value = Value;
_pause = false;
initCron();
if (_needSave) {
jsonWriteStr_(valuesFlashJson, _id, value.valS);
needSaveValues = true;
}
bool _needSaveBak = _needSave;
_needSave = false;
regEvent(getNextAlarmF(), F("Cron alarm"), false, false);
_needSave = _needSaveBak;
}
void doByInterval() {
if (!_pause && _time_isTrust && (gmtTimeToLocal(unixTime) >= _nextAlarm)) {
updateNextAlarm(true);
bool _needSaveBak = _needSave;
_needSave = false;
regEvent(getNextAlarmF(), F("Cron alarm"));
_needSave = _needSaveBak;
}
}
IoTValue execute(String command, std::vector<IoTValue> &param) {
if (command == "stop") {
_pause = true;
} else if (command == "continue") {
_pause = false;
updateNextAlarm(false);
}
bool _needSaveBak = _needSave;
_needSave = false;
regEvent(getNextAlarmF(), F("Cron alarm"), false, false);
_needSave = _needSaveBak;
return {};
}
~Cron() {};
};
void* getAPI_Cron(String subtype, String param) {
if (subtype == F("Cron")) {
return new Cron(param);
} else {
return nullptr;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,95 @@
/*
* Copyright 2015, alex at staticlibs.net
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* File: ccronexpr.h
* Author: alex
*
* Created on February 24, 2015, 9:35 AM
*/
#ifndef CCRONEXPR_H
#define CCRONEXPR_H
#define CRON_USE_LOCAL_TIME
#if defined(__cplusplus) && !defined(CRON_COMPILE_AS_CXX)
extern "C" {
#endif
#ifndef ANDROID
#include <time.h>
#else /* ANDROID */
#include <time64.h>
#endif /* ANDROID */
#include <stdint.h> /*added for use if uint*_t data types*/
/**
* Parsed cron expression
*/
typedef struct {
uint8_t seconds[8];
uint8_t minutes[8];
uint8_t hours[3];
uint8_t days_of_week[1];
uint8_t days_of_month[4];
uint8_t months[2];
} cron_expr;
/**
* Parses specified cron expression.
*
* @param expression cron expression as nul-terminated string,
* should be no longer that 256 bytes
* @param pointer to cron expression structure, it's client code responsibility
* to free/destroy it afterwards
* @param error output error message, will be set to string literal
* error message in case of error. Will be set to NULL on success.
* The error message should NOT be freed by client.
*/
void cron_parse_expr(const char* expression, cron_expr* target, const char** error);
/**
* Uses the specified expression to calculate the next 'fire' date after
* the specified date. All dates are processed as UTC (GMT) dates
* without timezones information. To use local dates (current system timezone)
* instead of GMT compile with '-DCRON_USE_LOCAL_TIME'
*
* @param expr parsed cron expression to use in next date calculation
* @param date start date to start calculation from
* @return next 'fire' date in case of success, '((time_t) -1)' in case of error.
*/
time_t cron_next(cron_expr* expr, time_t date);
/**
* Uses the specified expression to calculate the previous 'fire' date after
* the specified date. All dates are processed as UTC (GMT) dates
* without timezones information. To use local dates (current system timezone)
* instead of GMT compile with '-DCRON_USE_LOCAL_TIME'
*
* @param expr parsed cron expression to use in previous date calculation
* @param date start date to start calculation from
* @return previous 'fire' date in case of success, '((time_t) -1)' in case of error.
*/
time_t cron_prev(cron_expr* expr, time_t date);
#if defined(__cplusplus) && !defined(CRON_COMPILE_AS_CXX)
} /* extern "C"*/
#endif
#endif /* CCRONEXPR_H */

View File

@@ -0,0 +1,57 @@
{
"menuSection": "Виртуальные элементы",
"configItem": [
{
"global": 0,
"name": "Будильник (Cron)",
"type": "Writing",
"subtype": "Cron",
"id": "cron",
"widget": "anydataDef",
"page": "Таймеры",
"descr": "Будильник",
"int": 1,
"val": "*/15 * * * * *",
"formatNextAlarm": "%H:%M:%S",
"needSave": 0
}
],
"about": {
"authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe",
"authorGit": "https://github.com/biveraxe",
"specialThanks": "",
"moduleName": "Cron",
"moduleVersion": "1.0",
"usedRam": {
"esp32_4mb": 15,
"esp8266_4mb": 15
},
"title": "Будильник типа Cron",
"moduleDesc": "Планировщик времени для периодического выполнения заданий в определённое время. Генерирует событие в указанное время по формату Cron https://ru.wikipedia.org/wiki/Cron ",
"propInfo": {
"formatNextAlarm": "Формат представления даты и времени срабатывания следующего уведомления. http://cppstudio.com/post/621/",
"needSave": "Требуется сохранять(1) или нет(0) состояние в энерго независимую память."
},
"retInfo": "Содержит время следующего срабатывания.",
"funcInfo": [
{
"name": "stop",
"descr": "Поставить процесс на паузу, при этом не будет событий.",
"params": []
},
{
"name": "continue",
"descr": "Продолжить выполнение с момента остановки.",
"params": []
}
]
},
"defActive": true,
"usedLibs": {
"esp32_4mb": [],
"esp8266_4mb": [],
"esp8266_1mb": [],
"esp8266_1mb_ota": []
}
}