board.cc 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. #include "board.h"
  2. #include "system_info.h"
  3. #include "settings.h"
  4. #include "display/display.h"
  5. #include "assets/lang_config.h"
  6. #include <esp_log.h>
  7. #include <esp_ota_ops.h>
  8. #include <esp_chip_info.h>
  9. #include <esp_random.h>
  10. #include "application.h"
  11. #define TAG "Board"
  12. Board::Board() {
  13. Settings settings("board", true);
  14. uuid_ = settings.GetString("uuid");
  15. if (uuid_.empty()) {
  16. uuid_ = GenerateUuid();
  17. settings.SetString("uuid", uuid_);
  18. }
  19. ESP_LOGI(TAG, "UUID=%s SKU=%s", uuid_.c_str(), BOARD_NAME);
  20. }
  21. std::string Board::GenerateUuid() {
  22. // UUID v4 需要 16 字节的随机数据
  23. uint8_t uuid[16];
  24. // 使用 ESP32 的硬件随机数生成器
  25. esp_fill_random(uuid, sizeof(uuid));
  26. // 设置版本 (版本 4) 和变体位
  27. uuid[6] = (uuid[6] & 0x0F) | 0x40; // 版本 4
  28. uuid[8] = (uuid[8] & 0x3F) | 0x80; // 变体 1
  29. // 将字节转换为标准的 UUID 字符串格式
  30. char uuid_str[37];
  31. snprintf(uuid_str, sizeof(uuid_str),
  32. "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
  33. uuid[0], uuid[1], uuid[2], uuid[3],
  34. uuid[4], uuid[5], uuid[6], uuid[7],
  35. uuid[8], uuid[9], uuid[10], uuid[11],
  36. uuid[12], uuid[13], uuid[14], uuid[15]);
  37. return std::string(uuid_str);
  38. }
  39. bool Board::GetBatteryLevel(int &level, bool& charging, bool& discharging) {
  40. return false;
  41. }
  42. bool Board::GetTemperature(float& esp32temp){
  43. return false;
  44. }
  45. Display* Board::GetDisplay() {
  46. static NoDisplay display;
  47. return &display;
  48. }
  49. Camera* Board::GetCamera() {
  50. return nullptr;
  51. }
  52. Led* Board::GetLed() {
  53. static NoLed led;
  54. return &led;
  55. }
  56. std::string Board::GetJson() {
  57. /*
  58. {
  59. "version": 2,
  60. "flash_size": 4194304,
  61. "psram_size": 0,
  62. "minimum_free_heap_size": 123456,
  63. "mac_address": "00:00:00:00:00:00",
  64. "uuid": "00000000-0000-0000-0000-000000000000",
  65. "chip_model_name": "esp32s3",
  66. "chip_info": {
  67. "model": 1,
  68. "cores": 2,
  69. "revision": 0,
  70. "features": 0
  71. },
  72. "application": {
  73. "name": "my-app",
  74. "version": "1.0.0",
  75. "compile_time": "2021-01-01T00:00:00Z"
  76. "idf_version": "4.2-dev"
  77. "elf_sha256": ""
  78. },
  79. "partition_table": [
  80. "app": {
  81. "label": "app",
  82. "type": 1,
  83. "subtype": 2,
  84. "address": 0x10000,
  85. "size": 0x100000
  86. }
  87. ],
  88. "ota": {
  89. "label": "ota_0"
  90. },
  91. "board": {
  92. ...
  93. }
  94. }
  95. */
  96. std::string json = R"({"version":2,"language":")" + std::string(Lang::CODE) + R"(",)";
  97. json += R"("flash_size":)" + std::to_string(SystemInfo::GetFlashSize()) + R"(,)";
  98. json += R"("minimum_free_heap_size":")" + std::to_string(SystemInfo::GetMinimumFreeHeapSize()) + R"(",)";
  99. json += R"("mac_address":")" + SystemInfo::GetMacAddress() + R"(",)";
  100. json += R"("uuid":")" + uuid_ + R"(",)";
  101. json += R"("chip_model_name":")" + SystemInfo::GetChipModelName() + R"(",)";
  102. esp_chip_info_t chip_info;
  103. esp_chip_info(&chip_info);
  104. json += R"("chip_info":{)";
  105. json += R"("model":)" + std::to_string(chip_info.model) + R"(,)";
  106. json += R"("cores":)" + std::to_string(chip_info.cores) + R"(,)";
  107. json += R"("revision":)" + std::to_string(chip_info.revision) + R"(,)";
  108. json += R"("features":)" + std::to_string(chip_info.features) + R"(},)";
  109. auto app_desc = esp_app_get_description();
  110. json += R"("application":{)";
  111. json += R"("name":")" + std::string(app_desc->project_name) + R"(",)";
  112. json += R"("version":")" + std::string(app_desc->version) + R"(",)";
  113. json += R"("compile_time":")" + std::string(app_desc->date) + R"(T)" + std::string(app_desc->time) + R"(Z",)";
  114. json += R"("idf_version":")" + std::string(app_desc->idf_ver) + R"(",)";
  115. char sha256_str[65];
  116. for (int i = 0; i < 32; i++) {
  117. snprintf(sha256_str + i * 2, sizeof(sha256_str) - i * 2, "%02x", app_desc->app_elf_sha256[i]);
  118. }
  119. json += R"("elf_sha256":")" + std::string(sha256_str) + R"(")";
  120. json += R"(},)";
  121. json += R"("partition_table": [)";
  122. esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL);
  123. while (it) {
  124. const esp_partition_t *partition = esp_partition_get(it);
  125. json += R"({)";
  126. json += R"("label":")" + std::string(partition->label) + R"(",)";
  127. json += R"("type":)" + std::to_string(partition->type) + R"(,)";
  128. json += R"("subtype":)" + std::to_string(partition->subtype) + R"(,)";
  129. json += R"("address":)" + std::to_string(partition->address) + R"(,)";
  130. json += R"("size":)" + std::to_string(partition->size) + R"(},)";;
  131. it = esp_partition_next(it);
  132. }
  133. json.pop_back(); // Remove the last comma
  134. json += R"(],)";
  135. json += R"("ota":{)";
  136. auto ota_partition = esp_ota_get_running_partition();
  137. json += R"("label":")" + std::string(ota_partition->label) + R"(")";
  138. json += R"(},)";
  139. json += R"("board":)" + GetBoardJson();
  140. // Close the JSON object
  141. json += R"(})";
  142. return json;
  143. }
  144. void Board::postAlive() {
  145. // 创建HTTP客户端
  146. auto network = Board::GetInstance().GetNetwork();
  147. auto& app = Application::GetInstance();
  148. // 排除其他状态
  149. if (app.GetDeviceState() == kDeviceStateSpeaking ||
  150. app.GetDeviceState() == kDeviceStateListening
  151. )
  152. {
  153. ESP_LOGI(TAG, "cancel post ");
  154. return ;
  155. }
  156. if (!network) {
  157. ESP_LOGE(TAG, "Failed to get network instance");
  158. return;
  159. }
  160. // 创建 HTTP 客户端
  161. auto http = network->CreateHttp(2); // 使用正确的创建方式
  162. if (!http) {
  163. ESP_LOGE(TAG, "Failed to create HTTP client");
  164. return;
  165. }
  166. // 获取电池状态
  167. int level;
  168. bool charging, discharging;
  169. GetBatteryLevel(level, charging, discharging);
  170. // 根据充电状态设置esoc值
  171. std::string esoc_value;
  172. if (charging) {
  173. esoc_value = "-1";
  174. } else {
  175. esoc_value = std::to_string(level);
  176. }
  177. // 打印esoc值
  178. ESP_LOGI(TAG, "ESOC value: %s", esoc_value.c_str());
  179. std::string json = "{}";
  180. // 获取MAC地址并构建JSON
  181. std::string mac = SystemInfo::GetMacAddress();
  182. ESP_LOGI(TAG, "Device MAC: %s", mac.c_str());
  183. // 设置HTTP头
  184. http->SetHeader("macAddress", mac.c_str());
  185. http->SetHeader("Content-Type", "application/json");
  186. http->SetHeader("esoc", esoc_value.c_str()); // 添加esoc头
  187. http->SetContent(std::move(json));
  188. std::string url = "http://36.134.23.41:8004/xiaozhi-app/app/device/getDeviceEnable";
  189. // 发送POST请求
  190. if (!http->Open("POST", url.c_str())) {
  191. ESP_LOGE(TAG, "HTTP POST failed to open connection");
  192. return;
  193. }
  194. // 获取响应状态码
  195. int status = http->GetStatusCode();
  196. ESP_LOGI(TAG, "HTTP response status: %d", status);
  197. if (status == 200) {
  198. ESP_LOGI(TAG, "POST success");
  199. } else {
  200. ESP_LOGW(TAG, "POST received non-200 status: %d", status);
  201. }
  202. http->Close();
  203. ESP_LOGD(TAG, "postAlive completed");
  204. }