#include "barrier_vidicon.h" #include "application.h" #include "nlohmann/json.hpp" #include "common/sys_util.h" #include "common/snowflake.h" namespace zsy { bool BarrierVidicon::saveImageToFile(const std::string &decodedImageData, const std::string &filePath) { try { // 以二进制写入模式打开文件 std::ofstream file(filePath, std::ios::binary | std::ios::trunc); // 检查文件是否成功打开 if (!file.is_open()) { throw std::system_error(errno, std::generic_category(), "无法打开文件"); } // 写入解码后的图像数据 file.write(decodedImageData.data(), decodedImageData.size()); // 检查写入是否成功 if (!file.good()) { throw std::system_error(errno, std::generic_category(), "写入文件失败"); } return true; } catch (const std::exception &e) { LOGGER_ERROR("图片保存失败"); return false; } } BarrierVidicon::~BarrierVidicon() { } BarrierVidicon::BarrierVidicon(const VidiconProperties &config) : config(config) , hasNewContent(false) { SysUtil::createDirs(SysUtil::HOME_DIR + "\\temp"); auto cli = Application::mqttCliHolder->localCli(); Application::eventManager->subscribe(MqttCli::TYPE_LOCAL + "/device/" + config.ip + "/message/up/snapshot", [this](const EventManager::Event &event) { if (!event.data.has_value()) { LOGGER_ERROR("错误的消息格式"); return; } auto jsonData = event.data.value(); LOGGER_INFO("收到道闸拍照结果:{}", jsonData.dump()); const auto res = jsonData.get(); imageContent = res.payload.image_content; hasNewContent.store(true); }); Application::eventManager->subscribe(MqttCli::TYPE_LOCAL + "/device/" + config.ip + "/message/down/snapshot/reply", [this](const EventManager::Event &event) { if (!event.data.has_value()) { LOGGER_ERROR("错误的消息格式"); return; } auto jsonData = event.data.value(); LOGGER_INFO("收到道闸拍照消息回执:{}", jsonData.dump()); }); } static long long getTime() { const auto now = std::chrono::system_clock::now(); const auto now_ms = std::chrono::time_point_cast(now); const auto epoch = now_ms.time_since_epoch(); return std::chrono::duration_cast(epoch).count(); } std::string BarrierVidicon::photograph() { try { LOGGER_INFO("摄像机正在拍照,设备名称:{}", config.name); const long timestamp = static_cast(getTime()); nlohmann::json j{ {"id", "photograph" + std::to_string(timestamp)}, {"sn", config.ip}, {"name", "snapshot"}, {"version", "1.0"}, {"timestamp", timestamp}, { "payload", { {"type", "snapshot"}, {"body", {}}, } } }; auto topic = "device/" + config.ip + "/message/down/snapshot"; auto data = j.dump(); LOGGER_INFO("拍照:{} {}", topic, data); try { auto cli = Application::mqttCliHolder->localCli(); if (cli) { hasNewContent.store(false); imageContent = ""; cli->publish(topic, data, 0); uint8_t i = 0; do { i++; LOGGER_INFO("等待:{}", i); std::this_thread::sleep_for(std::chrono::milliseconds(1000)); } while (i <= 10 && !hasNewContent.load()); const auto filename = "car_body_" + Snowflake::genIdStr() + ".jpg"; std::string path = SysUtil::HOME_DIR + "\\temp\\" + filename; auto content = SysUtil::base64_decode(imageContent); bool res = saveImageToFile(content, path); return path; } else { LOGGER_ERROR("未找到 MQTT 本地客户端"); } } catch (const std::exception &e) { LOGGER_INFO("拍照失败:{}", e.what()); } catch (...) { LOGGER_ERROR("未知异常,拍照失败"); } return ""; } catch (std::exception &e) { LOGGER_ERROR("摄像机拍照失败:{}", e.what()); return {}; } catch (...) { LOGGER_ERROR("未知异常,摄像机拍照失败"); return {}; } } }