esp_app_main.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. * Squeezelite for esp32
  3. *
  4. * (c) Sebastien 2019
  5. * Philippe G. 2019, philippe_44@outlook.com
  6. *
  7. * This software is released under the MIT License.
  8. * https://opensource.org/licenses/MIT
  9. *
  10. */
  11. #include "Config.h"
  12. #include "accessors.h"
  13. #include "audio_controls.h"
  14. #include "cmd_system.h"
  15. #include "display.h"
  16. #include "esp_log.h"
  17. #include "freertos/FreeRTOS.h"
  18. #include "gds_draw.h"
  19. #include "gds_font.h"
  20. #include "gds_text.h"
  21. #include "led.h"
  22. #include "led_vu.h"
  23. #include "mdns.h"
  24. #include "messaging.h"
  25. #include "network_manager.h"
  26. #include "platform_esp32.h"
  27. #include "squeezelite-ota.h"
  28. #include "telnet.h"
  29. #include "tools.h"
  30. #include "trace.h"
  31. #include <math.h>
  32. #include <stdio.h>
  33. #include <string.h>
  34. #include "bootstate.h"
  35. #include "platform_console.h"
  36. #include "system_time.h"
  37. #if defined(CONFIG_WITH_METRICS)
  38. #include "Metrics.h"
  39. #endif
  40. #ifdef CONFIG_HEAP_TRACING
  41. #include "esp_heap_trace.h"
  42. #endif
  43. #define JOIN_TIMEOUT_MS (10000)
  44. #define LOCAL_MAC_SIZE 20
  45. static const char TAG[] = "esp_app_main";
  46. #define DEFAULT_HOST_NAME "squeezelite"
  47. #ifdef CONFIG_IDF_TARGET_ESP32S3
  48. extern const char _ctype_[];
  49. const char* __ctype_ptr__ = _ctype_;
  50. #endif
  51. // as an exception _init function don't need include
  52. extern void services_init(void);
  53. extern void services_ports_init(void);
  54. extern void services_gpio_init(void);
  55. extern void services_sleep_init(void);
  56. extern void display_init(char* welcome);
  57. extern void led_vu_init(void);
  58. extern void target_init(char* target);
  59. extern void start_squeezelite();
  60. void cb_connection_got_ip(nm_state_t new_state, int sub_state) {
  61. const char* hostname;
  62. static ip4_addr_t ip;
  63. tcpip_adapter_ip_info_t ipInfo;
  64. network_get_ip_info(&ipInfo);
  65. if (ip.addr && ipInfo.ip.addr != ip.addr) {
  66. config_raise_changed(false);
  67. ESP_LOGW(TAG, "IP change, need to reboot");
  68. simple_restart();
  69. }
  70. system_time_init();
  71. // initializing mDNS
  72. network_get_hostname(&hostname);
  73. mdns_init();
  74. mdns_hostname_set(hostname);
  75. ESP_LOGI(TAG, "Network connected and mDNS initialized with %s", hostname);
  76. messaging_post_message(MESSAGING_INFO, MESSAGING_CLASS_SYSTEM, "Network connected");
  77. led_unpush(LED_GREEN);
  78. if (is_recovery_running) {
  79. // when running in recovery, send a LMS discovery message
  80. // to find a running instance. This is to enable using
  81. // the plugin's proxy mode for FW download and avoid
  82. // expired certificate issues.
  83. discover_ota_server(5);
  84. }
  85. }
  86. void cb_connection_sta_disconnected(nm_state_t new_state, int sub_state) {
  87. led_blink_pushed(LED_GREEN, 250, 250);
  88. messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Wifi disconnected");
  89. }
  90. void handle_ap_connect(nm_state_t new_state, int sub_state) { start_telnet(NULL); }
  91. void handle_network_up(nm_state_t new_state, int sub_state) { bootstate_uptate_counter(0); }
  92. void initialize_network() {
  93. ESP_LOGI(TAG, "Starting Network Manager");
  94. TRACE_START
  95. network_initialize_task();
  96. // register main
  97. network_register_state_callback(NETWORK_WIFI_ACTIVE_STATE, WIFI_CONNECTED_STATE, "cb_connection_got_ip", &cb_connection_got_ip);
  98. network_register_state_callback(NETWORK_ETH_ACTIVE_STATE, ETH_ACTIVE_CONNECTED_STATE, "cb_connection_got_ip", &cb_connection_got_ip);
  99. // OTA Processing should happen when a network IP address is received
  100. network_register_state_callback(NETWORK_WIFI_ACTIVE_STATE, WIFI_CONNECTED_STATE, "cb_handle_ota", &cb_handle_ota);
  101. network_register_state_callback(NETWORK_ETH_ACTIVE_STATE, ETH_ACTIVE_CONNECTED_STATE, "cb_handle_ota", &cb_handle_ota);
  102. network_register_state_callback(
  103. NETWORK_WIFI_ACTIVE_STATE, WIFI_LOST_CONNECTION_STATE, "cb_connection_sta_disconnected", &cb_connection_sta_disconnected);
  104. /* Start the telnet service after we are certain that the network stack has been properly
  105. * initialized. This can be either after we're started the AP mode, or after we've started
  106. * the STA mode */
  107. network_register_state_callback(NETWORK_INITIALIZING_STATE, -1, "handle_ap_connect", &handle_ap_connect);
  108. network_register_state_callback(NETWORK_ETH_ACTIVE_STATE, ETH_ACTIVE_LINKDOWN_STATE, "handle_network_up", &handle_network_up);
  109. network_register_state_callback(NETWORK_WIFI_ACTIVE_STATE, WIFI_INITIALIZING_STATE, "handle_network_up", &handle_network_up);
  110. TRACE_STOP;
  111. }
  112. void app_main() {
  113. /* initialize console here, as it will capture logs earlier */
  114. initialize_console();
  115. ESP_LOGI(TAG, "Setting log level to max. System compiled with max level %s", get_log_level_desc(CONFIG_LOG_MAXIMUM_LEVEL));
  116. // calling this will set the log level to verbose,
  117. // but in reality, the actual log level used is limited
  118. // by CONFIG_LOG_MAXIMUM_LEVEL in sdkconfig as well as
  119. // LOG_LOCAL_LEVEL of each component
  120. esp_log_level_set("*", ESP_LOG_VERBOSE);
  121. messaging_service_init();
  122. bootstate_handle_boot();
  123. TRACE_INIT;
  124. ESP_LOGI(TAG, "Starting app_main");
  125. init_spiffs();
  126. if (esp_log_level_get(TAG) >= ESP_LOG_DEBUG) {
  127. listFiles("/spiffs");
  128. }
  129. // now that the spiffs is initialized, we can load the
  130. // core configuration system, which is needed by
  131. // most of the other system components
  132. config_load();
  133. if (!platform) {
  134. ESP_LOGE(TAG, "Invalid configuration object. Cannot continue");
  135. config_erase_config();
  136. }
  137. // initialize SPI/I2C and gpios/gpio expansion modules
  138. // now as they may be required for hardware access by
  139. // ethernet, etc. later
  140. services_ports_init();
  141. services_gpio_init();
  142. // Start the network task at this point; this is critical
  143. // as various subsequent init steps will post events to the queue
  144. initialize_network();
  145. #if defined(CONFIG_WITH_METRICS)
  146. ESP_LOGI(TAG, "Setting up metrics.");
  147. metrics_init();
  148. #endif
  149. init_telnet(); // align on 32 bits boundaries
  150. services_init();
  151. display_init("SqueezeESP32");
  152. if (platform->target && strlen(platform->target) > 0) {
  153. target_init(platform->target);
  154. }
  155. led_vu_init();
  156. if (is_recovery_running) {
  157. if (display) {
  158. ESP_LOGD(TAG, "Writing to display");
  159. GDS_ClearExt(display, true);
  160. GDS_SetFont(display, Font_line_2);
  161. GDS_TextPos(display, GDS_FONT_DEFAULT, GDS_TEXT_CENTERED, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "RECOVERY");
  162. }
  163. if (led_display) {
  164. led_vu_color_yellow(LED_VU_BRIGHT);
  165. }
  166. }
  167. #if defined(CONFIG_WITH_METRICS)
  168. metrics_event_boot(is_recovery_running ? "recovery" : "ota");
  169. #endif
  170. if (!is_recovery_running) {
  171. ESP_LOGD(TAG, "Getting audio control mapping ");
  172. if (platform && platform->has_dev && platform->dev.root_button_profile && strlen(platform->dev.root_button_profile) > 0) {
  173. ESP_LOGD(TAG, "Initializing audio control buttons type %s", platform->dev.root_button_profile);
  174. if (actrls_init(platform->dev.root_button_profile) == ESP_OK) {
  175. ESP_LOGD(TAG, "Done Initializing audio control buttons type %s", platform->dev.root_button_profile);
  176. } else {
  177. ESP_LOGD(TAG, "No audio control buttons");
  178. }
  179. }
  180. }
  181. led_blink_pushed(LED_GREEN, 250, 250);
  182. if (!is_recovery_running) {
  183. start_squeezelite();
  184. }
  185. console_start();
  186. services_sleep_init();
  187. messaging_post_message(MESSAGING_INFO, MESSAGING_CLASS_SYSTEM, "System started");
  188. #ifdef CONFIG_HEAP_TRACING
  189. #endif
  190. }