diff --git a/sscma/callback/invoke.hpp b/sscma/callback/invoke.hpp index e36fb798..0380ccea 100644 --- a/sscma/callback/invoke.hpp +++ b/sscma/callback/invoke.hpp @@ -145,7 +145,7 @@ class Invoke final : public std::enable_shared_from_this { return true; } - inline void direct_reply(std::string algorithm_config) { + void direct_reply(std::string algorithm_config) { auto ss{concat_strings("\r{\"type\": 0, \"name\": \"", _cmd, "\", \"code\": ", @@ -160,16 +160,46 @@ class Invoke final : public std::enable_shared_from_this { static_cast(_caller)->send_bytes(ss.c_str(), ss.size()); } - inline void event_reply(std::string data) { + void event_reply(std::string data, std::string some_hack = "") { auto ss{concat_strings("\r{\"type\": 1, \"name\": \"", _cmd, "\", \"code\": ", std::to_string(_ret), ", \"data\": {\"count\": ", std::to_string(_times), - data, - "}}\n")}; + data)}; static_cast(_caller)->send_bytes(ss.c_str(), ss.size()); + + if (!some_hack.empty()) { + const std::size_t len_unsafe_hdr = std::strlen("\"image\": \""); + static_cast(_caller)->send_bytes("\"image\": \"", len_unsafe_hdr); + + void* buffer = nullptr; + std::size_t size = 0; + std::size_t index = len_unsafe_hdr; + + // Have no idea why the firmware maker can not generate the firmware with the success build + // and I need to make this dirty hack to make it work + const auto ptr_str = some_hack.substr(index, sizeof(void*) << 1); + index += (sizeof(void*) << 1); + const auto len_str = some_hack.substr(index, sizeof(std::size_t) << 1); + index += (sizeof(std::size_t) << 1); + + static_assert(sizeof(void*) == sizeof(std::size_t)); + buffer = reinterpret_cast(from_hex_string(ptr_str)); + size = from_hex_string(len_str); + + if (buffer && size) [[likely]] { + static_cast(_caller)->send_bytes(reinterpret_cast(buffer), size); + } + + const auto remain_str = some_hack.substr(index); + if (!remain_str.empty()) [[likely]] { + static_cast(_caller)->send_bytes(remain_str.c_str(), remain_str.size()); + } + } + + static_cast(_caller)->send_bytes("}}\n", sizeof("}}\n")); } inline void event_loop() { @@ -444,12 +474,9 @@ class Invoke final : public std::enable_shared_from_this { event_reply( concat_strings(", ", algorithm_results_2_json_str(algorithm), ", ", img_res_2_json_str(&frame))); else { - event_reply(concat_strings(", ", - algorithm_results_2_json_str(algorithm), - ", ", - img_res_2_json_str(&frame), - ", ", - std::move(encoded_frame_str))); + event_reply( + concat_strings(", ", algorithm_results_2_json_str(algorithm), ", ", img_res_2_json_str(&frame), ", "), + std::move(encoded_frame_str)); } } diff --git a/sscma/callback/sample.hpp b/sscma/callback/sample.hpp index b285db8d..006aca28 100644 --- a/sscma/callback/sample.hpp +++ b/sscma/callback/sample.hpp @@ -76,16 +76,46 @@ class Sample final : public std::enable_shared_from_this { static_cast(_caller)->send_bytes(ss.c_str(), ss.size()); } - inline void event_reply(std::string data) { + inline void event_reply(std::string data, std::string some_hack = "") { auto ss{concat_strings("\r{\"type\": 1, \"name\": \"", _cmd, "\", \"code\": ", std::to_string(_ret), ", \"data\": {\"count\": ", std::to_string(_times), - data, - "}}\n")}; + data)}; static_cast(_caller)->send_bytes(ss.c_str(), ss.size()); + + if (!some_hack.empty()) { + const std::size_t len_unsafe_hdr = std::strlen("\"image\": \""); + static_cast(_caller)->send_bytes("\"image\": \"", len_unsafe_hdr); + + void* buffer = nullptr; + std::size_t size = 0; + std::size_t index = len_unsafe_hdr; + + // Have no idea why the firmware maker can not generate the firmware with the success build + // and I need to make this dirty hack to make it work + const auto ptr_str = some_hack.substr(index, sizeof(void*) << 1); + index += (sizeof(void*) << 1); + const auto len_str = some_hack.substr(index, sizeof(std::size_t) << 1); + index += (sizeof(std::size_t) << 1); + + static_assert(sizeof(void*) == sizeof(std::size_t)); + buffer = reinterpret_cast(from_hex_string(ptr_str)); + size = from_hex_string(len_str); + + if (buffer && size) [[likely]] { + static_cast(_caller)->send_bytes(reinterpret_cast(buffer), size); + } + + const auto remain_str = some_hack.substr(index); + if (!remain_str.empty()) [[likely]] { + static_cast(_caller)->send_bytes(remain_str.c_str(), remain_str.size()); + } + } + + static_cast(_caller)->send_bytes("}}\n", sizeof("}}\n")); } inline void event_loop() { @@ -131,7 +161,7 @@ class Sample final : public std::enable_shared_from_this { if (!is_everything_ok()) [[unlikely]] goto Err; - event_reply(concat_strings(", ", img_res_2_json_str(&frame), ", ", std::move(encoded_frame_str))); + event_reply(concat_strings(", ", img_res_2_json_str(&frame), ", "), std::move(encoded_frame_str)); static_resource->executor->add_task( [_this = std::move(getptr())](const std::atomic&) { _this->event_loop_cam(); }); diff --git a/sscma/static_resource.hpp b/sscma/static_resource.hpp index 1c2a91a1..362fdedb 100644 --- a/sscma/static_resource.hpp +++ b/sscma/static_resource.hpp @@ -133,7 +133,7 @@ class StaticResource final { boot_count = 0; current_model_id = 1; current_sensor_id = 1; - current_sensor_opt = 0; + current_sensor_opt = 1; current_algorithm_type = EL_ALGO_TYPE_UNDEFINED; current_task_id = 0; diff --git a/sscma/utility.hpp b/sscma/utility.hpp index bda0c492..d8714a69 100644 --- a/sscma/utility.hpp +++ b/sscma/utility.hpp @@ -103,6 +103,21 @@ template decltype(auto) to_hex_string(T dec) { return hex; } +template decltype(auto) from_hex_string(const std::string& hex) { + static_assert(std::is_unsigned::value); + T dec = 0; + for (char c : hex) { + dec <<= 4; + if ((c >= '0') & (c <= '9')) + dec |= c - '0'; + else if ((c >= 'a') & (c <= 'f')) + dec |= c - 'a' + 10; + else if ((c >= 'A') & (c <= 'F')) + dec |= c - 'A' + 10; + } + return dec; +} + decltype(auto) model_info_2_json_str(const el_model_info_t& model_info) { return concat_strings("{\"id\": ", std::to_string(model_info.id), @@ -266,8 +281,12 @@ inline decltype(auto) img_res_2_json_str(const el_img_t* img) { } inline decltype(auto) img_2_json_str(const el_img_t* img) { - if (!img || !img->data || !img->size) [[unlikely]] - return std::string("\"image\": \"\""); + int rotate = 0; + std::string no_copy_hack((sizeof(void*) + sizeof(std::size_t)) << 1, '0'); + + if (!img || !img->data || !img->size) [[unlikely]] { + return concat_strings("\"image\": \"", no_copy_hack, "\"", ", \"rotate\": ", std::to_string(rotate)); + } #if SSCMA_SHARED_BASE64_BUFFER static char* buffer = reinterpret_cast(SSCMA_SHARED_BASE64_BUFFER_BASE); @@ -275,7 +294,7 @@ inline decltype(auto) img_2_json_str(const el_img_t* img) { if ((((img->size + 2u) / 3u) << 2u) + 1u > buffer_size) { EL_LOGW("Error: shared base64 buffer exhausted"); - return std::string{"\"image\": \"\""}; + return concat_strings("\"image\": \"", no_copy_hack, "\"", ", \"rotate\": ", std::to_string(rotate)); } #else static char* buffer = nullptr; @@ -296,8 +315,21 @@ inline decltype(auto) img_2_json_str(const el_img_t* img) { std::memset(buffer, 0, buffer_size); el_base64_encode(img->data, img->size, buffer); - int rotate = (360 - (static_cast(img->rotate) * 90)) % 360; - return concat_strings("\"image\": \"", buffer, "\"", ", \"rotate\": ", std::to_string(rotate)); + void const* addr = buffer; + std::size_t const len = std::strlen(buffer); + + { + static_assert(sizeof(void*) == sizeof(std::size_t)); + auto addr_str = to_hex_string(reinterpret_cast(addr)); + no_copy_hack = std::move(addr_str); + } + { + auto len_str = to_hex_string(len); + no_copy_hack += std::move(len_str); + } + + rotate = (360 - (static_cast(img->rotate) * 90)) % 360; + return concat_strings("\"image\": \"", no_copy_hack, "\"", ", \"rotate\": ", std::to_string(rotate)); } // TODO: avoid repeatly allocate/release memory in for loop