main.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. #include <string>
  2. #include "freertos/FreeRTOS.h"
  3. #include "freertos/task.h"
  4. #include "freertos/event_groups.h"
  5. #include "driver/gpio.h"
  6. #include "sdkconfig.h"
  7. // SD-Card ////////////////////
  8. #include "nvs_flash.h"
  9. #include "esp_vfs_fat.h"
  10. #include "sdmmc_cmd.h"
  11. #include "driver/sdmmc_host.h"
  12. #include "driver/sdmmc_defs.h"
  13. ///////////////////////////////
  14. #include "ClassLogFile.h"
  15. #include "connect_wlan.h"
  16. #include "read_wlanini.h"
  17. #include "server_main.h"
  18. #include "server_tflite.h"
  19. #include "server_file.h"
  20. #include "server_ota.h"
  21. #include "time_sntp.h"
  22. #include "ClassControllCamera.h"
  23. #include "server_main.h"
  24. #include "server_camera.h"
  25. #ifdef ENABLE_MQTT
  26. #include "server_mqtt.h"
  27. #endif //ENABLE_MQTT
  28. #include "Helper.h"
  29. extern const char* GIT_TAG;
  30. extern const char* GIT_REV;
  31. extern const char* GIT_BRANCH;
  32. extern const char* BUILD_TIME;
  33. extern std::string getHTMLversion(void);
  34. extern std::string getHTMLcommit(void);
  35. #define __HIDE_PASSWORD
  36. // #include "jomjol_WS2812Slow.h"
  37. #include "SmartLeds.h"
  38. #define __SD_USE_ONE_LINE_MODE__
  39. #include "server_GPIO.h"
  40. #define BLINK_GPIO GPIO_NUM_33
  41. static const char *TAG = "MAIN";
  42. //#define FLASH_GPIO GPIO_NUM_4
  43. bool Init_NVS_SDCard()
  44. {
  45. esp_err_t ret = nvs_flash_init();
  46. if (ret == ESP_ERR_NVS_NO_FREE_PAGES) {
  47. ESP_ERROR_CHECK(nvs_flash_erase());
  48. ret = nvs_flash_init();
  49. }
  50. ////////////////////////////////////////////////
  51. ESP_LOGI(TAG, "Using SDMMC peripheral");
  52. sdmmc_host_t host = SDMMC_HOST_DEFAULT();
  53. // This initializes the slot without card detect (CD) and write protect (WP) signals.
  54. // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
  55. sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
  56. // To use 1-line SD mode, uncomment the following line:
  57. #ifdef __SD_USE_ONE_LINE_MODE__
  58. slot_config.width = 1;
  59. #endif
  60. // GPIOs 15, 2, 4, 12, 13 should have external 10k pull-ups.
  61. // Internal pull-ups are not sufficient. However, enabling internal pull-ups
  62. // does make a difference some boards, so we do that here.
  63. gpio_set_pull_mode(GPIO_NUM_15, GPIO_PULLUP_ONLY); // CMD, needed in 4- and 1- line modes
  64. gpio_set_pull_mode(GPIO_NUM_2, GPIO_PULLUP_ONLY); // D0, needed in 4- and 1-line modes
  65. #ifndef __SD_USE_ONE_LINE_MODE__
  66. gpio_set_pull_mode(GPIO_NUM_4, GPIO_PULLUP_ONLY); // D1, needed in 4-line mode only
  67. gpio_set_pull_mode(GPIO_NUM_12, GPIO_PULLUP_ONLY); // D2, needed in 4-line mode only
  68. #endif
  69. gpio_set_pull_mode(GPIO_NUM_13, GPIO_PULLUP_ONLY); // D3, needed in 4- and 1-line modes
  70. // Options for mounting the filesystem.
  71. // If format_if_mount_failed is set to true, SD card will be partitioned and
  72. // formatted in case when mounting fails.
  73. esp_vfs_fat_sdmmc_mount_config_t mount_config = {
  74. .format_if_mount_failed = false,
  75. .max_files = 7, // anstatt 5 (2022-09-21)
  76. .allocation_unit_size = 16 * 1024
  77. };
  78. // Use settings defined above to initialize SD card and mount FAT filesystem.
  79. // Note: esp_vfs_fat_sdmmc_mount is an all-in-one convenience function.
  80. // Please check its source code and implement error recovery when developing
  81. // production applications.
  82. sdmmc_card_t* card;
  83. ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card);
  84. if (ret != ESP_OK) {
  85. if (ret == ESP_FAIL) {
  86. ESP_LOGE(TAG, "Failed to mount filesystem. "
  87. "If you want the card to be formatted, set format_if_mount_failed = true.");
  88. } else {
  89. ESP_LOGE(TAG, "Failed to initialize the card (%s). "
  90. "Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));
  91. }
  92. return false;
  93. }
  94. sdmmc_card_print_info(stdout, card);
  95. SaveSDCardInfo(card);
  96. return true;
  97. }
  98. void task_NoSDBlink(void *pvParameter)
  99. {
  100. gpio_pad_select_gpio(BLINK_GPIO);
  101. gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
  102. TickType_t xDelay;
  103. xDelay = 100 / portTICK_PERIOD_MS;
  104. ESP_LOGD(TAG, "SD-Card could not be inialized - STOP THE PROGRAMM HERE");
  105. while (1)
  106. {
  107. gpio_set_level(BLINK_GPIO, 1);
  108. vTaskDelay( xDelay );
  109. gpio_set_level(BLINK_GPIO, 0);
  110. vTaskDelay( xDelay );
  111. }
  112. vTaskDelete(NULL); //Delete this task if it exits from the loop above
  113. }
  114. extern "C" void app_main(void)
  115. {
  116. TickType_t xDelay;
  117. bool initSucessful = true;
  118. ESP_LOGI(TAG, "\n\n\n\n\n"); // Add mark on log to see when it restarted
  119. PowerResetCamera();
  120. esp_err_t camStatus = Camera.InitCam();
  121. Camera.LightOnOff(false);
  122. xDelay = 2000 / portTICK_PERIOD_MS;
  123. ESP_LOGD(TAG, "After camera initialization: sleep for: %ldms", (long) xDelay);
  124. vTaskDelay( xDelay );
  125. if (!Init_NVS_SDCard())
  126. {
  127. xTaskCreate(&task_NoSDBlink, "task_NoSDBlink", configMINIMAL_STACK_SIZE * 64, NULL, tskIDLE_PRIORITY+1, NULL);
  128. return;
  129. };
  130. string versionFormated = "Branch: '" + std::string(GIT_BRANCH) + \
  131. "', Revision: " + std::string(GIT_REV) +", Date/Time: " + std::string(BUILD_TIME) + \
  132. ", Web UI: " + getHTMLversion();
  133. if (std::string(GIT_TAG) != "") { // We are on a tag, add it as prefix
  134. string versionFormated = "Tag: '" + std::string(GIT_TAG) + "', " + versionFormated;
  135. }
  136. LogFile.CreateLogDirectories();
  137. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
  138. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "==================== Startup ====================");
  139. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
  140. LogFile.WriteToFile(ESP_LOG_INFO, TAG, versionFormated);
  141. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Reset reason: " + getResetReason());
  142. CheckOTAUpdate();
  143. CheckUpdate();
  144. char *ssid = NULL, *passwd = NULL, *hostname = NULL, *ip = NULL, *gateway = NULL, *netmask = NULL, *dns = NULL;
  145. LoadWlanFromFile("/sdcard/wlan.ini", ssid, passwd, hostname, ip, gateway, netmask, dns);
  146. if (ssid != NULL && passwd != NULL)
  147. #ifdef __HIDE_PASSWORD
  148. ESP_LOGD(TAG, "WLan: %s, XXXXXX", ssid);
  149. #else
  150. ESP_LOGD(TAG, "WLan: %s, %s", ssid, passwd);
  151. #endif
  152. else
  153. ESP_LOGD(TAG, "No SSID and PASSWORD set!!!");
  154. if (hostname != NULL)
  155. ESP_LOGD(TAG, "Hostname: %s", hostname);
  156. else
  157. ESP_LOGD(TAG, "Hostname not set");
  158. if (ip != NULL && gateway != NULL && netmask != NULL)
  159. ESP_LOGD(TAG, "Fixed IP: %s, Gateway %s, Netmask %s", ip, gateway, netmask);
  160. if (dns != NULL)
  161. ESP_LOGD(TAG, "DNS IP: %s", dns);
  162. wifi_init_sta(ssid, passwd, hostname, ip, gateway, netmask, dns);
  163. xDelay = 2000 / portTICK_PERIOD_MS;
  164. ESP_LOGD(TAG, "main: sleep for: %ldms", (long) xDelay);
  165. vTaskDelay( xDelay );
  166. if (!setup_time()) {
  167. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "NTP Initialization failed!");
  168. }
  169. setBootTime();
  170. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
  171. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "================== Main Started =================");
  172. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
  173. if (getHTMLcommit().substr(0, 7) != std::string(GIT_REV).substr(0, 7)) { // Compare the first 7 characters of both hashes
  174. LogFile.WriteToFile(ESP_LOG_WARN, TAG, std::string("Web UI version (") + getHTMLcommit() + ") does not match firmware version (" + std::string(GIT_REV) + ") !");
  175. }
  176. std::string zw = gettimestring("%Y%m%d-%H%M%S");
  177. ESP_LOGD(TAG, "time %s", zw.c_str());
  178. size_t _hsize = getESPHeapSize();
  179. if (_hsize < 4000000) // Check for a bit less than 4 MB (but clearly over 2 MB)
  180. {
  181. std::string _zws = "Not enough PSRAM available. Expected around 4 MBytes - available: " + std::to_string((float)_hsize/1024/1024) + " MBytes!";
  182. _zws = _zws + "\nEither not initialized, too small (2 MByte only) or not present at all. Firmware cannot start!!";
  183. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, _zws);
  184. } else { // Bad Camera Status, retry init
  185. if (camStatus != ESP_OK) {
  186. LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Failed to initialize camera module, retrying...");
  187. PowerResetCamera();
  188. esp_err_t camStatus = Camera.InitCam();
  189. Camera.LightOnOff(false);
  190. xDelay = 2000 / portTICK_PERIOD_MS;
  191. ESP_LOGD(TAG, "After camera initialization: sleep for: %ldms", (long) xDelay);
  192. vTaskDelay( xDelay );
  193. if (camStatus != ESP_OK) {
  194. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to initialize camera module!");
  195. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Check that your camera module is working and connected properly!");
  196. initSucessful = false;
  197. }
  198. } else { // Test Camera
  199. camera_fb_t * fb = esp_camera_fb_get();
  200. if (!fb) {
  201. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera Framebuffer cannot be initialized!");
  202. /* Easiest would be to simply restart here and try again,
  203. how ever there seem to be systems where it fails at startup but still work corectly later.
  204. Therefore we treat it still as successed!
  205. //initSucessful = false; */
  206. }
  207. else {
  208. esp_camera_fb_return(fb);
  209. Camera.LightOnOff(false);
  210. }
  211. }
  212. }
  213. xDelay = 2000 / portTICK_PERIOD_MS;
  214. ESP_LOGD(TAG, "main: sleep for: %ldms", (long) xDelay*10);
  215. vTaskDelay( xDelay );
  216. ESP_LOGD(TAG, "starting servers");
  217. server = start_webserver();
  218. register_server_camera_uri(server);
  219. register_server_tflite_uri(server);
  220. register_server_file_uri(server, "/sdcard");
  221. register_server_ota_sdcard_uri(server);
  222. #ifdef ENABLE_MQTT
  223. register_server_mqtt_uri(server);
  224. #endif //ENABLE_MQTT
  225. gpio_handler_create(server);
  226. ESP_LOGD(TAG, "vor reg server main");
  227. register_server_main_uri(server, "/sdcard");
  228. if (initSucessful) {
  229. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Initialization completed successfully!");
  230. ESP_LOGD(TAG, "vor do autostart");
  231. TFliteDoAutoStart();
  232. }
  233. else { // Initialization failed
  234. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Initialization failed. Will restart in 5 minutes!");
  235. vTaskDelay(60*4000 / portTICK_RATE_MS); // Wait 4 minutes to give time to do an OTA or fetch the log
  236. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Initialization failed. Will restart in 1 minute!");
  237. vTaskDelay(60*1000 / portTICK_RATE_MS); // Wait 1 minute to give time to do an OTA or fetch the log
  238. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Initialization failed. Will restart now!");
  239. doReboot();
  240. }
  241. }