ml307_board.cc 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #include "ml307_board.h"
  2. #include "application.h"
  3. #include "display.h"
  4. #include "font_awesome_symbols.h"
  5. #include "assets/lang_config.h"
  6. #include <esp_log.h>
  7. #include <esp_timer.h>
  8. #include <opus_encoder.h>
  9. static const char *TAG = "Ml307Board";
  10. Ml307Board::Ml307Board(gpio_num_t tx_pin, gpio_num_t rx_pin, gpio_num_t dtr_pin) : tx_pin_(tx_pin), rx_pin_(rx_pin), dtr_pin_(dtr_pin) {
  11. }
  12. std::string Ml307Board::GetBoardType() {
  13. return "ml307";
  14. }
  15. void Ml307Board::StartNetwork() {
  16. auto& application = Application::GetInstance();
  17. auto display = Board::GetInstance().GetDisplay();
  18. display->SetStatus(Lang::Strings::DETECTING_MODULE);
  19. while (true) {
  20. modem_ = AtModem::Detect(tx_pin_, rx_pin_, dtr_pin_, 921600);
  21. if (modem_ != nullptr) {
  22. break;
  23. }
  24. vTaskDelay(pdMS_TO_TICKS(1000));
  25. }
  26. modem_->OnNetworkStateChanged([this, &application](bool network_ready) {
  27. if (network_ready) {
  28. ESP_LOGI(TAG, "Network is ready");
  29. } else {
  30. ESP_LOGE(TAG, "Network is down");
  31. auto device_state = application.GetDeviceState();
  32. if (device_state == kDeviceStateListening || device_state == kDeviceStateSpeaking) {
  33. application.Schedule([this, &application]() {
  34. application.SetDeviceState(kDeviceStateIdle);
  35. });
  36. }
  37. }
  38. });
  39. // Wait for network ready
  40. display->SetStatus(Lang::Strings::REGISTERING_NETWORK);
  41. while (true) {
  42. auto result = modem_->WaitForNetworkReady();
  43. if (result == NetworkStatus::ErrorInsertPin) {
  44. application.Alert(Lang::Strings::ERROR, Lang::Strings::PIN_ERROR, "sad", Lang::Sounds::P3_ERR_PIN);
  45. } else if (result == NetworkStatus::ErrorRegistrationDenied) {
  46. application.Alert(Lang::Strings::ERROR, Lang::Strings::REG_ERROR, "sad", Lang::Sounds::P3_ERR_REG);
  47. } else {
  48. break;
  49. }
  50. vTaskDelay(pdMS_TO_TICKS(10000));
  51. }
  52. // Print the ML307 modem information
  53. std::string module_revision = modem_->GetModuleRevision();
  54. std::string imei = modem_->GetImei();
  55. std::string iccid = modem_->GetIccid();
  56. ESP_LOGI(TAG, "ML307 Revision: %s", module_revision.c_str());
  57. ESP_LOGI(TAG, "ML307 IMEI: %s", imei.c_str());
  58. ESP_LOGI(TAG, "ML307 ICCID: %s", iccid.c_str());
  59. }
  60. NetworkInterface* Ml307Board::GetNetwork() {
  61. return modem_.get();
  62. }
  63. const char* Ml307Board::GetNetworkStateIcon() {
  64. if (modem_ == nullptr || !modem_->network_ready()) {
  65. return FONT_AWESOME_SIGNAL_OFF;
  66. }
  67. int csq = modem_->GetCsq();
  68. if (csq == -1) {
  69. return FONT_AWESOME_SIGNAL_OFF;
  70. } else if (csq >= 0 && csq <= 14) {
  71. return FONT_AWESOME_SIGNAL_1;
  72. } else if (csq >= 15 && csq <= 19) {
  73. return FONT_AWESOME_SIGNAL_2;
  74. } else if (csq >= 20 && csq <= 24) {
  75. return FONT_AWESOME_SIGNAL_3;
  76. } else if (csq >= 25 && csq <= 31) {
  77. return FONT_AWESOME_SIGNAL_4;
  78. }
  79. ESP_LOGW(TAG, "Invalid CSQ: %d", csq);
  80. return FONT_AWESOME_SIGNAL_OFF;
  81. }
  82. std::string Ml307Board::GetBoardJson() {
  83. // Set the board type for OTA
  84. std::string board_json = std::string("{\"type\":\"" BOARD_TYPE "\",");
  85. board_json += "\"name\":\"" BOARD_NAME "\",";
  86. board_json += "\"revision\":\"" + modem_->GetModuleRevision() + "\",";
  87. board_json += "\"carrier\":\"" + modem_->GetCarrierName() + "\",";
  88. board_json += "\"csq\":\"" + std::to_string(modem_->GetCsq()) + "\",";
  89. board_json += "\"imei\":\"" + modem_->GetImei() + "\",";
  90. board_json += "\"iccid\":\"" + modem_->GetIccid() + "\",";
  91. board_json += "\"cereg\":" + modem_->GetRegistrationState().ToString() + "}";
  92. return board_json;
  93. }
  94. void Ml307Board::SetPowerSaveMode(bool enabled) {
  95. // TODO: Implement power save mode for ML307
  96. }
  97. std::string Ml307Board::GetDeviceStatusJson() {
  98. /*
  99. * 返回设备状态JSON
  100. *
  101. * 返回的JSON结构如下:
  102. * {
  103. * "audio_speaker": {
  104. * "volume": 70
  105. * },
  106. * "screen": {
  107. * "brightness": 100,
  108. * "theme": "light"
  109. * },
  110. * "battery": {
  111. * "level": 50,
  112. * "charging": true
  113. * },
  114. * "network": {
  115. * "type": "cellular",
  116. * "carrier": "CHINA MOBILE",
  117. * "csq": 10
  118. * }
  119. * }
  120. */
  121. auto& board = Board::GetInstance();
  122. auto root = cJSON_CreateObject();
  123. // Audio speaker
  124. auto audio_speaker = cJSON_CreateObject();
  125. auto audio_codec = board.GetAudioCodec();
  126. if (audio_codec) {
  127. cJSON_AddNumberToObject(audio_speaker, "volume", audio_codec->output_volume());
  128. }
  129. cJSON_AddItemToObject(root, "audio_speaker", audio_speaker);
  130. // Screen brightness
  131. auto backlight = board.GetBacklight();
  132. auto screen = cJSON_CreateObject();
  133. if (backlight) {
  134. cJSON_AddNumberToObject(screen, "brightness", backlight->brightness());
  135. }
  136. auto display = board.GetDisplay();
  137. if (display && display->height() > 64) { // For LCD display only
  138. cJSON_AddStringToObject(screen, "theme", display->GetTheme().c_str());
  139. }
  140. cJSON_AddItemToObject(root, "screen", screen);
  141. // Battery
  142. int battery_level = 0;
  143. bool charging = false;
  144. bool discharging = false;
  145. if (board.GetBatteryLevel(battery_level, charging, discharging)) {
  146. cJSON* battery = cJSON_CreateObject();
  147. cJSON_AddNumberToObject(battery, "level", battery_level);
  148. cJSON_AddBoolToObject(battery, "charging", charging);
  149. cJSON_AddItemToObject(root, "battery", battery);
  150. }
  151. // Network
  152. auto network = cJSON_CreateObject();
  153. cJSON_AddStringToObject(network, "type", "cellular");
  154. cJSON_AddStringToObject(network, "carrier", modem_->GetCarrierName().c_str());
  155. int csq = modem_->GetCsq();
  156. if (csq == -1) {
  157. cJSON_AddStringToObject(network, "signal", "unknown");
  158. } else if (csq >= 0 && csq <= 14) {
  159. cJSON_AddStringToObject(network, "signal", "very weak");
  160. } else if (csq >= 15 && csq <= 19) {
  161. cJSON_AddStringToObject(network, "signal", "weak");
  162. } else if (csq >= 20 && csq <= 24) {
  163. cJSON_AddStringToObject(network, "signal", "medium");
  164. } else if (csq >= 25 && csq <= 31) {
  165. cJSON_AddStringToObject(network, "signal", "strong");
  166. }
  167. cJSON_AddItemToObject(root, "network", network);
  168. auto json_str = cJSON_PrintUnformatted(root);
  169. std::string json(json_str);
  170. cJSON_free(json_str);
  171. cJSON_Delete(root);
  172. return json;
  173. }