// Copyright (c) 2020 Lukasz Chodyla // Distributed under the MIT License. // See accompanying file LICENSE.txt for the full license. #include "nx/firmware/Restarter.h" #include "esp_log.h" #include "esp_system.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include #include #define TAG "RESTARTER" #define RESTARTER_CHECK_INTERVAL_SEC 10 #define RESTART_SCHEDULE_SIZE 12 #define RESTART_SCHEDULE_MIN_LEN 7 // 'x x x x' const char* schedule = ""; const char* tz = ""; // day - days from sunday (0 is sunday), schedule - binary schedule from sunday (1 is sunday, 64 is saturday) int isDayInSchedule(int day, int schedule) { int dayMatch = 1 << day; int match = (dayMatch & schedule); return match != 0; } void restarterTask(void* param) { //UNUSED(param); ESP_LOGI(TAG, "Starting restarter task"); if (strlen(schedule) < RESTART_SCHEDULE_MIN_LEN) { ESP_LOGW(TAG, "Closing restarter task due to the incomplete schedule: [%s]", schedule); vTaskDelete( NULL ); return; } long int intervalMs = 1000 * RESTARTER_CHECK_INTERVAL_SEC; char scheduleLine[RESTART_SCHEDULE_SIZE]; strcpy(scheduleLine, schedule); int daySchedule = atoi( strtok(scheduleLine, " ") ); int hour = atoi( strtok(NULL, " ") ); int minute = atoi( strtok(NULL, " ") ); int maxUptime = atoi( strtok(NULL, " ") ); ESP_LOGI(TAG, "Restart schedule: %i %i %i %i", daySchedule, hour, minute, maxUptime); if (daySchedule == 0) { ESP_LOGI(TAG, "Closing restarter task due to zero days in schedule"); vTaskDelete( NULL ); return; } while (1) { vTaskDelay(intervalMs / portTICK_PERIOD_MS); int uptimeMin = portTICK_PERIOD_MS * xTaskGetTickCount() / 1000 / 60; time_t now; struct tm timeinfo; time(&now); // Set timezone to Eastern Standard Time and print local time setenv("TZ", tz, 1); tzset(); localtime_r(&now, &timeinfo); if (uptimeMin < maxUptime) { continue; } if (!isDayInSchedule(timeinfo.tm_wday, daySchedule)) { continue; } if (hour != timeinfo.tm_hour || hour == -1) { continue; } if (minute != timeinfo.tm_min) { continue; } ESP_LOGI(TAG, "all conditions met, restarting..."); esp_restart(); } } void nxStartRestarter(const char* scheduleString, const char* timezone) { schedule = scheduleString; tz = timezone; xTaskCreate(restarterTask, "restarter_task", 2048, (void*)1, tskIDLE_PRIORITY, NULL); }