| | |
| | | #include "power_save_timer.h" |
| | | #include "adc_battery_monitor.h" |
| | | #include "wifi_manager.h" |
| | | #include "app_task.h" |
| | | |
| | | #include <esp_log.h> |
| | | #include <esp_efuse_table.h> |
| | |
| | | static float last_mp3_play_speed = 1.0f; |
| | | static int64_t last_mp3_play_time = 0; |
| | | mcp_server.AddTool("self.mp3.play", |
| | | "Play one MP3 file from the SD card. The name argument must exactly match a files[].name from self.mp3.get_list. Optional speed supports only 0.5, 0.75, 1.0, 1.25, 1.5, or 2.0; non-1.0 speeds change pitch and affect only SD card MP3 playback. For play, random play, switch song, or named-song requests, call this tool before telling the user playback has started. Do not call this tool repeatedly for the same user request after it has returned accepted=true.", |
| | | "Play one MP3 file from the SD card. The name argument must exactly match a files[].name from self.mp3.get_list. Optional speed supports only 0.5, 0.75, 1.0, 1.25, 1.5, or 2.0; non-1.0 speeds change pitch and affect only SD card MP3 playback. Optional repeat is the number of full-file loops (default 1). Optional power_off_after requests existing power-off standby after a natural finish, not after stop. For play, random play, switch song, or named-song requests, call this tool before telling the user playback has started. Do not call this tool repeatedly for the same user request after it has returned accepted=true.", |
| | | PropertyList({ |
| | | Property("name", kPropertyTypeString), |
| | | Property("speed", kPropertyTypeNumber, 1.0) |
| | | Property("speed", kPropertyTypeNumber, 1.0), |
| | | Property("repeat", kPropertyTypeInteger, 1, 1, 99), |
| | | Property("power_off_after", kPropertyTypeBoolean, false) |
| | | }), |
| | | [](const PropertyList& properties) -> ReturnValue { |
| | | std::string name = properties["name"].value<std::string>(); |
| | | float speed = static_cast<float>(properties["speed"].value<double>()); |
| | | int repeat = properties["repeat"].value<int>(); |
| | | bool power_off_after = properties["power_off_after"].value<bool>(); |
| | | if (repeat < 1) { |
| | | repeat = 1; |
| | | } |
| | | int64_t now = esp_timer_get_time(); |
| | | if (name == last_mp3_play_name && std::fabs(speed - last_mp3_play_speed) < 0.001f && now - last_mp3_play_time < 15000000) { |
| | | return std::string("{\"accepted\":true,\"duplicate_ignored\":true}"); |
| | | } |
| | | |
| | | esp_err_t err = SDCard_Play_MP3_With_Speed(name.data(), speed); |
| | | esp_err_t err = SDCard_Play_MP3_With_Speed_Repeat(name.data(), speed, repeat, power_off_after); |
| | | if (err != ESP_OK) { |
| | | return std::string("{\"accepted\":false,\"error\":\"") + esp_err_to_name(err) + |
| | | "\",\"retry\":\"use exact files[].name from self.mp3.get_list\"}"; |
| | |
| | | last_mp3_play_name = name; |
| | | last_mp3_play_speed = speed; |
| | | last_mp3_play_time = now; |
| | | return std::string("{\"accepted\":true}"); |
| | | return std::string("{\"accepted\":true,\"repeat\":") + std::to_string(repeat) + |
| | | ",\"power_off_after\":" + (power_off_after ? "true" : "false") + "}"; |
| | | }); |
| | | |
| | | mcp_server.AddTool("self.mp3.get_status", |
| | |
| | | PropertyList(), |
| | | [](const PropertyList& properties) -> ReturnValue { |
| | | return std::string("{\"playing\":") + (SDCard_Is_Playing() ? "true" : "false") + |
| | | ",\"tts_paused\":" + (SDCard_Is_Paused() ? "true" : "false") + "}"; |
| | | ",\"tts_paused\":" + (SDCard_Is_Paused() ? "true" : "false") + |
| | | ",\"repeat_left\":" + std::to_string(SDCard_Get_Repeat_Left()) + "}"; |
| | | }); |
| | | |
| | | mcp_server.AddTool("self.mp3.stop", |
| | |
| | | InitializeTools(); |
| | | } |
| | | |
| | | void OnDeviceReady() override { |
| | | xTaskCreate([](void *arg) { |
| | | (void)arg; |
| | | vTaskDelay(pdMS_TO_TICKS(1500)); |
| | | Board_ResolveBootOrRestore(false); |
| | | vTaskDelete(nullptr); |
| | | }, "boot_app_task", 4096, nullptr, 3, nullptr); |
| | | } |
| | | |
| | | bool OnRestoredFromPowerOff(bool network_ready) override { |
| | | (void)network_ready; |
| | | Board_ResolveBootOrRestore(true); |
| | | return true; |
| | | } |
| | | |
| | | virtual void SetNetworkEventCallback(NetworkEventCallback callback) override { |
| | | WifiBoard::SetNetworkEventCallback([this, callback](NetworkEvent event, const std::string& data) { |
| | | if (event == NetworkEvent::Connected) { |