修复问题
parent
e7cb901478
commit
a0caa24dea
|
@ -19,6 +19,7 @@ find_package(HCNet CONFIG REQUIRED)
|
|||
find_package(ICU REQUIRED COMPONENTS uc)
|
||||
find_path(CPP_HTTPLIB_INCLUDE_DIRS "httplib.h") # 使用时要先于 windows.h 包含
|
||||
find_path(CPPCODEC_INCLUDE_DIRS "cppcodec/base32_crockford.hpp")
|
||||
#find_library(WS2_32_LIB NAMES ws2_32)
|
||||
set(SOURCE_DIRS
|
||||
src/common
|
||||
src/vidicon
|
||||
|
@ -43,6 +44,7 @@ set(LINK_DIRS
|
|||
src
|
||||
)
|
||||
set(LIBRARIES
|
||||
# ${WS2_32_LIB}
|
||||
openssl::libssl
|
||||
openssl::libcrypto
|
||||
mqtt_cpp_iface::mqtt_cpp_iface
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
{
|
||||
"sn": "remote",
|
||||
"name": "远程",
|
||||
"server": "127.0.0.1",
|
||||
"server": "47.117.76.168",
|
||||
"port": 1883,
|
||||
"clientId": "yztq",
|
||||
"username": "dcs",
|
||||
|
@ -45,7 +45,7 @@
|
|||
}
|
||||
],
|
||||
"reportSvr": {
|
||||
"server": "http://127.0.0.1:8080",
|
||||
"server": "https://biz-api.jstqhj.cn:443",
|
||||
"passUrl": "/api/site/report-car-pass?debug=1",
|
||||
"reportUrl": "/api/site/report-v2?debug=1"
|
||||
},
|
||||
|
@ -53,6 +53,7 @@
|
|||
{
|
||||
"name": "进前置",
|
||||
"sn": "b11ceeb5-af42d80f",
|
||||
"ip": "192.168.120.240",
|
||||
"io": 0,
|
||||
"platformScale": "1",
|
||||
"soundColumn": "1",
|
||||
|
@ -61,32 +62,36 @@
|
|||
{
|
||||
"name": "进",
|
||||
"sn": "25ec7559-74125e77",
|
||||
"ip": "192.168.120.235",
|
||||
"io": 0,
|
||||
"platformScale": "1",
|
||||
"soundColumn": "1",
|
||||
"soundColumn": "2",
|
||||
"vidicon": "1"
|
||||
},
|
||||
{
|
||||
"name": "出前置",
|
||||
"sn": "351b2406-6fae5ab5",
|
||||
"ip": "192.168.120.243",
|
||||
"io": 0,
|
||||
"platformScale": "1",
|
||||
"soundColumn": "1",
|
||||
"vidicon": "1"
|
||||
"soundColumn": "2",
|
||||
"vidicon": "2"
|
||||
},
|
||||
{
|
||||
"name": "出",
|
||||
"sn": "34fc9ce5-8b091060",
|
||||
"ip": "192.168.120.238",
|
||||
"io": 0,
|
||||
"platformScale": "1",
|
||||
"soundColumn": "1",
|
||||
"vidicon": "1"
|
||||
"vidicon": "2"
|
||||
}
|
||||
],
|
||||
"platformScales": [
|
||||
{
|
||||
"sn": "1",
|
||||
"name": "地磅",
|
||||
"sample": 20,
|
||||
"port": "COM2",
|
||||
"baudRate": 1200,
|
||||
"byteSize": 8,
|
||||
|
@ -97,19 +102,33 @@
|
|||
"soundColumns": [
|
||||
{
|
||||
"sn": "1",
|
||||
"name": "音柱",
|
||||
"server": "http://localhost:8080",
|
||||
"name": "音柱1",
|
||||
"server": "http://192.168.120.246:80",
|
||||
"path": "/v1/speech"
|
||||
},
|
||||
{
|
||||
"sn": "2",
|
||||
"name": "音柱2",
|
||||
"server": "http://192.168.120.237:80",
|
||||
"path": "/v1/speech"
|
||||
}
|
||||
],
|
||||
"vidicons": [
|
||||
{
|
||||
"sn": "1",
|
||||
"name": "摄像头",
|
||||
"ip": "192.168.2.64",
|
||||
"name": "摄像头1",
|
||||
"ip": "192.168.120.245",
|
||||
"port": 8000,
|
||||
"username": "admin",
|
||||
"passwd": "Zsy8899."
|
||||
"passwd": "gk147258"
|
||||
},
|
||||
{
|
||||
"sn": "2",
|
||||
"name": "摄像头2",
|
||||
"ip": "192.168.120.244",
|
||||
"port": 8000,
|
||||
"username": "admin",
|
||||
"passwd": "gk147258"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -42,8 +42,35 @@ namespace zsy
|
|||
}
|
||||
}
|
||||
|
||||
void Application::removePid()
|
||||
{
|
||||
std::regex pattern(R"(deviceAccessLayer_\d+\.txt)");
|
||||
|
||||
std::filesystem::path path = std::filesystem::path(pidFilePath);
|
||||
|
||||
try
|
||||
{
|
||||
for (const auto &entry: std::filesystem::directory_iterator(path))
|
||||
{
|
||||
std::string filename = entry.path().filename().string();
|
||||
if (std::regex_match(filename, pattern))
|
||||
{
|
||||
std::filesystem::remove(entry.path());
|
||||
LOGGER_INFO("PID 文件删除成功:{}", entry.path().string());
|
||||
}
|
||||
}
|
||||
} catch (const std::exception &e)
|
||||
{
|
||||
LOGGER_ERROR("PID 文件删除失败:{}", e.what());
|
||||
}catch (...)
|
||||
{
|
||||
LOGGER_ERROR("未知异常,PID 文件删除失败");
|
||||
}
|
||||
}
|
||||
|
||||
void Application::writePid()
|
||||
{
|
||||
removePid();
|
||||
try
|
||||
{
|
||||
pid = std::to_string(GetCurrentProcessId());
|
||||
|
@ -54,7 +81,6 @@ namespace zsy
|
|||
{
|
||||
LOGGER_ERROR("无法打开文件:{}", pidFile);
|
||||
}
|
||||
|
||||
outFile << pid;
|
||||
outFile.close();
|
||||
} catch (const std::exception &e)
|
||||
|
|
|
@ -20,6 +20,8 @@ namespace zsy
|
|||
|
||||
void loadConfig();
|
||||
|
||||
void removePid();
|
||||
|
||||
void writePid();
|
||||
|
||||
public:
|
||||
|
|
|
@ -46,10 +46,32 @@ namespace zsy
|
|||
LOGGER_ERROR("未找到 MQTT 远程客户端");
|
||||
}
|
||||
|
||||
Application::httpSvr->getEndpoint("/data", [](const httplib::Request &req, httplib::Response &res)
|
||||
{
|
||||
nlohmann::json j;
|
||||
try
|
||||
{
|
||||
// double weight = Application::deviceHolder->getPlatformScale("b11ceeb5-af42d80f")->reading();
|
||||
// j["地磅读数"] = weight;
|
||||
// Application::deviceHolder->getSoundColumn( "b11ceeb5-af42d80f")->play("欢迎光临");
|
||||
// auto reportPassResult = Application::reportSvr->reportPass("苏K85076", "b11ceeb5-af42d80f", "");
|
||||
} catch (std::exception &e)
|
||||
{
|
||||
LOGGER_ERROR("错误", e.what());
|
||||
j["错误"] = "";
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOGGER_ERROR("错误");
|
||||
j["错误"] = "";
|
||||
}
|
||||
res.set_content(j.dump(), "application/json");
|
||||
});
|
||||
|
||||
Application::httpSvr->postEndpoint("/plateRecognize", [](const httplib::Request &req, httplib::Response &res)
|
||||
{
|
||||
static std::unordered_map<std::string, long long> cache;
|
||||
static std::mutex cacheMutex;
|
||||
// static std::unordered_map<std::string, long long> cache;
|
||||
// static std::mutex cacheMutex;
|
||||
try
|
||||
{
|
||||
auto body = req.body;
|
||||
|
@ -73,11 +95,11 @@ namespace zsy
|
|||
}
|
||||
if (license.find("无") != std::string::npos)
|
||||
{
|
||||
LOGGER_ERROR("车牌识别失败");
|
||||
LOGGER_WARN("车牌识别失败");
|
||||
res.set_content(R"({})", "application/json");
|
||||
return;
|
||||
}
|
||||
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
/*auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
auto key = serialno + license;
|
||||
long long time = ms + 60000 * 5;
|
||||
{
|
||||
|
@ -96,7 +118,7 @@ namespace zsy
|
|||
}
|
||||
}
|
||||
cache[key] = ms;
|
||||
}
|
||||
}*/
|
||||
|
||||
Application::threadPool->submit([imageFile,license, barrier = Application::deviceHolder->getBarrier(serialno)]
|
||||
{
|
||||
|
@ -182,11 +204,14 @@ namespace zsy
|
|||
{
|
||||
LOGGER_INFO("车牌识别结果处理中,设备名称:{}", config.name);
|
||||
// 播放语音 1
|
||||
Application::threadPool->submit([sn = config.sn]
|
||||
/*Application::threadPool->submit([sn = config.sn]
|
||||
{
|
||||
Application::deviceHolder->getSoundColumn(sn)->play("欢迎光临");
|
||||
});*/
|
||||
std::thread t1([sn = config.sn]
|
||||
{
|
||||
Application::deviceHolder->getSoundColumn(sn)->play("欢迎光临");
|
||||
});
|
||||
|
||||
// 上传车头照
|
||||
auto imageFileDecode = SysUtil::base64_decode(imageFile);
|
||||
const std::shared_ptr<std::istream> imageFileStream = std::make_shared<std::istringstream>(imageFileDecode, std::ios_base::in | std::ios_base::binary);
|
||||
|
@ -205,10 +230,16 @@ namespace zsy
|
|||
auto reportPassResult = Application::reportSvr->reportPass(license, config.sn, carFrontUrl);
|
||||
if (!(reportPassResult.code == 0 && (reportPassResult.data.type == 1 || reportPassResult.data.type == 2)))
|
||||
{
|
||||
LOGGER_INFO("不处理:{}", config.name);
|
||||
t1.join();
|
||||
return;
|
||||
}
|
||||
// 上报结果不为 0,播放语音 2 并读地磅,拍车斗并上传
|
||||
Application::threadPool->submit([sn =config.sn]
|
||||
/*Application::threadPool->submit([sn =config.sn]
|
||||
{
|
||||
Application::deviceHolder->getSoundColumn(sn)->play("正在称重,请稍后");
|
||||
});*/
|
||||
std::thread t2([sn = config.sn]
|
||||
{
|
||||
Application::deviceHolder->getSoundColumn(sn)->play("正在称重,请稍后");
|
||||
});
|
||||
|
@ -230,6 +261,8 @@ namespace zsy
|
|||
|
||||
// 上报 2
|
||||
Application::reportSvr->report(license, config.sn, weight, carFrontUrl, carBodyUrl, reportPassResult.data.orderNo);
|
||||
t1.join();
|
||||
t2.join();
|
||||
} catch (std::exception &e)
|
||||
{
|
||||
LOGGER_ERROR("车牌识别结果处理失败: {}", e.what());
|
||||
|
|
|
@ -41,6 +41,18 @@ namespace zsy
|
|||
svr->Post(std::move(path), std::forward<Func>(handler));
|
||||
}
|
||||
|
||||
template<typename Func>
|
||||
void getEndpoint(std::string path, Func &&handler)
|
||||
{
|
||||
std::shared_lock lock(status_mtx);
|
||||
if (status == 0)
|
||||
{
|
||||
LOGGER_ERROR("HTTP 服务不可用");
|
||||
return;
|
||||
}
|
||||
svr->Get(path, std::forward<Func>(handler));
|
||||
}
|
||||
|
||||
~HttpSvr();
|
||||
};
|
||||
} // zsy
|
||||
|
|
|
@ -9,13 +9,11 @@ namespace zsy
|
|||
const std::string MqttCli::TYPE_REMOTE = "remote";
|
||||
const std::string MqttCli::TYPE_LOCAL = "local";
|
||||
|
||||
MqttCli::MqttCli(MqttProperties &config, std::shared_ptr<EventManager> eventManager)
|
||||
: status(0),
|
||||
config(config),
|
||||
eventManager(eventManager)
|
||||
void MqttCli::connect()
|
||||
{
|
||||
try
|
||||
{
|
||||
LOGGER_ERROR("MQTT:{} 正在连接...", config.clientId);
|
||||
ioc = std::make_shared<boost::asio::io_context>();
|
||||
cli = MQTT_NS::make_sync_client(*ioc, config.server, config.port);
|
||||
cli->set_client_id(config.clientId);
|
||||
|
@ -49,11 +47,34 @@ namespace zsy
|
|||
}
|
||||
}
|
||||
|
||||
MqttCli::MqttCli(MqttProperties &config, std::shared_ptr<EventManager> eventManager)
|
||||
: status(0),
|
||||
config(config),
|
||||
eventManager(eventManager)
|
||||
{
|
||||
connect();
|
||||
}
|
||||
|
||||
void MqttCli::reconnect()
|
||||
{
|
||||
do
|
||||
{
|
||||
std::unique_lock lock(status_mtx);
|
||||
if (status == 2) break;
|
||||
mqtt::error_code ec;
|
||||
cli->connect(ec);
|
||||
if (!ec) break;
|
||||
|
||||
LOGGER_INFO("MQTT 10 秒后重新连接:{},{}", config.clientId, SysUtil::str_w_a(SysUtil::str_a_w( ec.message(),"GBK" )));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
} while (true);
|
||||
}
|
||||
|
||||
void MqttCli::run()
|
||||
{
|
||||
try
|
||||
{
|
||||
cli->connect();
|
||||
reconnect();
|
||||
ioc->run();
|
||||
} catch (std::exception &e)
|
||||
{
|
||||
|
@ -102,6 +123,7 @@ namespace zsy
|
|||
std::unique_lock lock(status_mtx);
|
||||
status = 0;
|
||||
LOGGER_INFO("MQTT 连接已关闭:{}", config.clientId);
|
||||
reconnect();
|
||||
}
|
||||
|
||||
void MqttCli::onError(mqtt::error_code ec)
|
||||
|
@ -109,6 +131,7 @@ namespace zsy
|
|||
std::unique_lock lock(status_mtx);
|
||||
status = 0;
|
||||
LOGGER_INFO("MQTT 错误:{} {}", config.clientId, ec.message());
|
||||
reconnect();
|
||||
}
|
||||
|
||||
bool MqttCli::onMessage(mqtt::optional<packet_id_t> packet_id, mqtt::publish_options pubopts, mqtt::buffer topic_, mqtt::buffer payload_)
|
||||
|
@ -138,6 +161,8 @@ namespace zsy
|
|||
|
||||
MqttCli::~MqttCli()
|
||||
{
|
||||
std::unique_lock lock(status_mtx);
|
||||
status = 2;
|
||||
cli->disconnect();
|
||||
ioc->stop();
|
||||
}
|
||||
|
|
|
@ -22,13 +22,15 @@ namespace zsy
|
|||
using CLI_PTR = std::shared_ptr<CLI>;
|
||||
using packet_id_t = CLI::packet_id_t;
|
||||
MqttProperties config;
|
||||
// 0-->不可用、1-->可用
|
||||
// 0-->不可用、1-->可用、2-->已停止
|
||||
uint8_t status;
|
||||
std::shared_mutex status_mtx;
|
||||
std::shared_ptr<EventManager> eventManager;
|
||||
std::unique_ptr<std::jthread> eventLoop;
|
||||
CLI_PTR cli;
|
||||
std::shared_ptr<boost::asio::io_context> ioc;
|
||||
CLI_PTR cli;
|
||||
|
||||
void connect();
|
||||
|
||||
void run();
|
||||
|
||||
|
@ -40,6 +42,8 @@ namespace zsy
|
|||
|
||||
bool onMessage(MQTT_NS::optional<packet_id_t> packet_id, MQTT_NS::publish_options pubopts, MQTT_NS::buffer topic_,MQTT_NS::buffer payload_);
|
||||
|
||||
void reconnect();
|
||||
|
||||
public:
|
||||
static const std::string TYPE_REMOTE;
|
||||
static const std::string TYPE_LOCAL;
|
||||
|
|
|
@ -34,7 +34,9 @@ namespace zsy
|
|||
|
||||
// 构建请求
|
||||
httplib::Client cli(config.bucketName + "." + config.endpoint);
|
||||
|
||||
cli.set_connection_timeout(5);
|
||||
cli.set_read_timeout(10);
|
||||
cli.set_write_timeout(10);
|
||||
// 设置请求头
|
||||
httplib::Headers headers = {
|
||||
{"Date", date},
|
||||
|
|
|
@ -103,7 +103,7 @@ namespace zsy
|
|||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
auto processor = static_cast<GenericPlatformScaleProcessor *>(serialPort->processor);
|
||||
int count = 0;
|
||||
while (processor->steady.load() < 20)
|
||||
while (processor->steady.load() < config.sample)
|
||||
{
|
||||
count++;
|
||||
if (count >= 10)
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace zsy
|
|||
{
|
||||
public:
|
||||
std::atomic<uint64_t> steady;
|
||||
|
||||
std::atomic<double> weight;
|
||||
|
||||
GenericPlatformScaleProcessor();
|
||||
|
|
|
@ -8,6 +8,7 @@ namespace zsy
|
|||
{
|
||||
std::string sn;
|
||||
std::string name;
|
||||
uint8_t sample;
|
||||
std::string port;
|
||||
uint32_t baudRate{9600};
|
||||
uint8_t byteSize{8};
|
||||
|
@ -19,6 +20,7 @@ namespace zsy
|
|||
{
|
||||
PARSE_JSON(sn, o.sn);
|
||||
PARSE_JSON(name, o.name);
|
||||
PARSE_JSON(sample, o.sample);
|
||||
PARSE_JSON(port, o.port);
|
||||
PARSE_JSON(baudRate, o.baudRate);
|
||||
PARSE_JSON(byteSize, o.byteSize);
|
||||
|
|
|
@ -31,6 +31,9 @@ namespace zsy
|
|||
LOGGER_INFO("上报数据:{}{} {}", config.server, config.passUrl, body);
|
||||
|
||||
httplib::Client cli(config.server);
|
||||
cli.set_connection_timeout(5);
|
||||
cli.set_read_timeout(10);
|
||||
cli.set_write_timeout(10);
|
||||
auto response = cli.Post(config.passUrl.c_str(), headers, body, "application/json");
|
||||
if (response)
|
||||
{
|
||||
|
@ -87,10 +90,13 @@ namespace zsy
|
|||
|
||||
auto body = data.dump();
|
||||
|
||||
LOGGER_INFO("上报数据:{}{} {}", config.server, config.passUrl, body);
|
||||
LOGGER_INFO("上报数据:{}{} {}", config.server, config.reportUrl, body);
|
||||
|
||||
httplib::Client cli(config.server);
|
||||
auto response = cli.Post(config.passUrl.c_str(), headers, body, "application/json");
|
||||
cli.set_connection_timeout(5);
|
||||
cli.set_read_timeout(10);
|
||||
cli.set_write_timeout(10);
|
||||
auto response = cli.Post(config.reportUrl.c_str(), headers, body, "application/json");
|
||||
if (response)
|
||||
{
|
||||
LOGGER_INFO("上报结果:{}", response->body);
|
||||
|
|
|
@ -63,9 +63,9 @@ namespace zsy
|
|||
};
|
||||
|
||||
nlohmann::json data{
|
||||
{"loop", {{"times", 1}}},
|
||||
{"loop", {{"times", 2}, {"gap", 2}}},
|
||||
{"prompt", true},
|
||||
{"queue", false},
|
||||
{"queue", true},
|
||||
{"rcn", "0"},
|
||||
{"rdn", "0"},
|
||||
{"reg", 0},
|
||||
|
@ -79,6 +79,10 @@ namespace zsy
|
|||
LOGGER_INFO("播放语音:{}{} {}", config.server, config.path, body);
|
||||
|
||||
httplib::Client cli(config.server);
|
||||
cli.set_connection_timeout(5);
|
||||
cli.set_read_timeout(10);
|
||||
cli.set_write_timeout(10);
|
||||
|
||||
auto response = cli.Post(config.path.c_str(), headers, body, "application/json");
|
||||
|
||||
if (response)
|
||||
|
@ -89,8 +93,16 @@ namespace zsy
|
|||
{
|
||||
LOGGER_ERROR("语音播放失败,HTTP状态码:{}", status);
|
||||
} else
|
||||
{
|
||||
auto json = nlohmann::json::parse(response->body);
|
||||
auto result = json.get<PlaySoundColumnResult>();
|
||||
if (result.code == 200)
|
||||
{
|
||||
LOGGER_INFO("语音播放成功");
|
||||
} else
|
||||
{
|
||||
LOGGER_ERROR("语音播放失败,错误:{}", result.message);
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
|
|
|
@ -5,6 +5,18 @@
|
|||
|
||||
namespace zsy
|
||||
{
|
||||
struct PlaySoundColumnResult
|
||||
{
|
||||
int code;
|
||||
std::string message;
|
||||
};
|
||||
|
||||
inline void from_json(const nlohmann::json &j, PlaySoundColumnResult &o)
|
||||
{
|
||||
PARSE_JSON(code, o.code);
|
||||
PARSE_JSON(message, o.message);
|
||||
}
|
||||
|
||||
class GenericSoundColumn final : public SoundColumn
|
||||
{
|
||||
SoundColumnProperties config;
|
||||
|
|
|
@ -34,22 +34,21 @@ namespace zsy
|
|||
|
||||
static std::string convert(const std::string &numberStr)
|
||||
{
|
||||
static const std::vector<std::string> digits = {"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"};
|
||||
std::string chineseStr;
|
||||
for (char c: numberStr)
|
||||
{
|
||||
if ('0' <= c && c <= '9')
|
||||
{
|
||||
chineseStr += digits[c - '0'];
|
||||
} else if (c == '.')
|
||||
{
|
||||
chineseStr += '点';
|
||||
} else
|
||||
{
|
||||
chineseStr += c;
|
||||
static const std::unordered_map<char, std::string> digitMap = {
|
||||
{'0', "零"}, {'1', "一"}, {'2', "二"}, {'3', "三"}, {'4', "四"},
|
||||
{'5', "五"}, {'6', "六"}, {'7', "七"}, {'8', "八"}, {'9', "九"},
|
||||
{'.', "点"}
|
||||
};
|
||||
|
||||
std::string result;
|
||||
for (char c : numberStr) {
|
||||
if (digitMap.contains(c)) {
|
||||
result += digitMap.at(c);
|
||||
} else {
|
||||
result += c;
|
||||
}
|
||||
}
|
||||
return chineseStr;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
} // zsy
|
||||
|
|
Loading…
Reference in New Issue