|
|
// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
|
|
|
//
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
// You may obtain a copy of the License at
|
|
|
//
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
//
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
// See the License for the specific language governing permissions and
|
|
|
// limitations under the License.
|
|
|
|
|
|
/*!
|
|
|
* @file main.cxx
|
|
|
* This file acts as a main entry point to the application.
|
|
|
*
|
|
|
* This file was generated by the tool fastddsgen.
|
|
|
*/
|
|
|
|
|
|
#include <csignal>
|
|
|
#include <cstring>
|
|
|
#include <functional>
|
|
|
#include <iostream>
|
|
|
#include <stdexcept>
|
|
|
#include <thread>
|
|
|
#include <queue>
|
|
|
|
|
|
#include <fastdds/dds/log/Log.hpp>
|
|
|
|
|
|
#include "Subscriber.hpp"
|
|
|
#include "msg.hpp"
|
|
|
#include "DEBUG.hpp"
|
|
|
#include "utils.hpp"
|
|
|
#include "BX6K1YYProtocol.hpp"
|
|
|
#include "Bx6k1YyLedClient.hpp"
|
|
|
|
|
|
using eprosima::fastdds::dds::Log;
|
|
|
|
|
|
|
|
|
std::function<void(int)> stop_handler;
|
|
|
void signal_handler(
|
|
|
int signum)
|
|
|
{
|
|
|
stop_handler(signum);
|
|
|
}
|
|
|
|
|
|
std::string parse_signal(
|
|
|
const int& signum)
|
|
|
{
|
|
|
switch (signum)
|
|
|
{
|
|
|
case SIGINT:
|
|
|
return "SIGINT";
|
|
|
case SIGTERM:
|
|
|
return "SIGTERM";
|
|
|
#ifndef _WIN32
|
|
|
case SIGQUIT:
|
|
|
return "SIGQUIT";
|
|
|
case SIGHUP:
|
|
|
return "SIGHUP";
|
|
|
#endif // _WIN32
|
|
|
default:
|
|
|
return "UNKNOWN SIGNAL";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// ========== LED 运行参数(参照 PuAnLED/Onbon/BX6K1YY 协议:BX-6K1-YY,0x64 / 0x02)==========
|
|
|
// 屏幕宽高是「查询失败时」的回退值;正常情况下启动后通过 A2 0A 查控制卡真实分辨率。
|
|
|
constexpr int LED_SCREEN_WIDTH = 64;
|
|
|
constexpr int LED_SCREEN_HEIGHT = 32;
|
|
|
// 控制卡 IP / 端口(与 config.json.led 对应)
|
|
|
constexpr const char* LED_IP = "192.168.6.147";
|
|
|
constexpr int LED_PORT = 5005;
|
|
|
|
|
|
// 全局 LED 客户端(BX-6K1-YY 协议),main 中构造,send_text 内部调用
|
|
|
static led::Bx6k1YyLedClient* g_led_client = nullptr;
|
|
|
|
|
|
|
|
|
std::string readfile(std::string name)
|
|
|
{
|
|
|
auto exeDir = getExeDir();
|
|
|
auto configPath = exeDir / name;
|
|
|
|
|
|
// 检查文件是否存在
|
|
|
if (!std::filesystem::exists(configPath))
|
|
|
{
|
|
|
std::cerr << "文件不存在: " << configPath << std::endl;
|
|
|
return "";
|
|
|
}
|
|
|
|
|
|
std::ifstream file(configPath);
|
|
|
if (!file.is_open())
|
|
|
{
|
|
|
std::cerr << "无法打开文件: " << configPath << std::endl;
|
|
|
return "";
|
|
|
}
|
|
|
|
|
|
// 方法1:使用 stringstream 读取整个文件
|
|
|
std::stringstream buffer;
|
|
|
buffer << file.rdbuf(); // 读取所有内容
|
|
|
std::string config = buffer.str();
|
|
|
|
|
|
file.close();
|
|
|
return config;
|
|
|
}
|
|
|
|
|
|
// 默认内容(led.txt):长驻到 area 0,控制卡不会自动删除。
|
|
|
static void send_default_text(const std::string& text)
|
|
|
{
|
|
|
if (!g_led_client) return;
|
|
|
std::string err;
|
|
|
if (!g_led_client->displayText(text, led::Bx6k1YyLedClient::kAreaDefault, err))
|
|
|
{
|
|
|
std::cerr << "LED default display failed: " << err << std::endl;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// DDS QueueSuccess 消息:下发到 area 1,60 秒后由控制卡自动删除,露出 area 0 的默认内容。
|
|
|
static void send_queue_text(const std::string& text)
|
|
|
{
|
|
|
if (!g_led_client) return;
|
|
|
std::string err;
|
|
|
if (!g_led_client->displayText(text, led::Bx6k1YyLedClient::kAreaTemporary, err))
|
|
|
{
|
|
|
std::cerr << "LED queue display failed: " << err << std::endl;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
std::queue<WeighingSystem::ScaleInfo> DdsMsgData::ScaleInfo_queue_;
|
|
|
std::queue<WeighingSystem::WeightInfoOk> DdsMsgData::WeightInfoOk_queue_;
|
|
|
std::queue<WeighingSystem::WeightInfoError> DdsMsgData::WeightInfoError_queue_;
|
|
|
std::queue<WeighingSystem::LicenseSnapUpdate> DdsMsgData::LicenseSnapUpdate_queue_;
|
|
|
std::queue<Queue::QueueSuccess> DdsMsgData::QueueSuccess_queue_;
|
|
|
std::mutex DdsMsgData::queue_cv_mtx_;
|
|
|
|
|
|
std::atomic<bool> running(true);
|
|
|
|
|
|
int main(int argc, char** argv)
|
|
|
{
|
|
|
auto ret = EXIT_SUCCESS;
|
|
|
std::shared_ptr<SubscriberApp> sub;
|
|
|
|
|
|
int domain_id = 0;
|
|
|
|
|
|
// —— IP / 端口:命令行可覆盖顶部常量 ——
|
|
|
std::string addr = LED_IP;
|
|
|
int port = LED_PORT;
|
|
|
|
|
|
// ====== 命令行解析 ======
|
|
|
for (int i = 1; i < argc; i++)
|
|
|
{
|
|
|
if (strcmp(argv[i], "--domain") == 0 && i + 1 < argc)
|
|
|
{
|
|
|
domain_id = atoi(argv[++i]);
|
|
|
}
|
|
|
else if (strcmp(argv[i], "--addr") == 0 && i + 1 < argc)
|
|
|
{
|
|
|
addr = argv[++i];
|
|
|
DEBUG("use addr from cmd: " << addr);
|
|
|
}
|
|
|
else if (strcmp(argv[i], "--port") == 0 && i + 1 < argc)
|
|
|
{
|
|
|
port = atoi(argv[++i]);
|
|
|
DEBUG("use port from cmd: " << port);
|
|
|
}
|
|
|
else if (strcmp(argv[i], "--version") == 0)
|
|
|
{
|
|
|
std::cout << "Version: " << PROGRAM_VERSION << "\n";
|
|
|
return EXIT_SUCCESS;
|
|
|
}
|
|
|
else if (strcmp(argv[i], "--help") == 0)
|
|
|
{
|
|
|
std::cout << "Usage: led [options]\n"
|
|
|
<< "Options:\n"
|
|
|
<< " --domain Set DDS domain ID\n"
|
|
|
<< " --addr LED TCP ip\n"
|
|
|
<< " --port LED TCP port (default " << LED_PORT << ")\n"
|
|
|
<< " --version Show software Version\n"
|
|
|
<< " --help Show this help message\n"
|
|
|
<< "\nLED config (edit source):\n"
|
|
|
<< " ip = " << LED_IP << "\n"
|
|
|
<< " port = " << port << "\n"
|
|
|
<< " screen = " << LED_SCREEN_WIDTH << "x" << LED_SCREEN_HEIGHT
|
|
|
<< " (fallback; real size queried at runtime via A2 0A)\n"
|
|
|
<< " protocol = BX-6K1-YY (0x64 / 0x02), A3 06 dynamic area\n";
|
|
|
return EXIT_SUCCESS;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
std::cout << "Usage: led [options]\n"
|
|
|
<< " --domain Set DDS domain ID\n"
|
|
|
<< " --version Show software Version\n"
|
|
|
<< " --help Show this help message\n";
|
|
|
return EXIT_FAILURE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// ====== 0. 构造 BX-6K1-YY LED 客户端(裸 TCP 协议,不依赖 vendor SDK)======
|
|
|
{
|
|
|
led::Bx6k1YyLedClient::Config cfg;
|
|
|
cfg.ip = addr;
|
|
|
cfg.port = static_cast<uint16_t>(port);
|
|
|
cfg.connectTimeoutMs = 1000;
|
|
|
cfg.responseTimeoutMs = 1000;
|
|
|
cfg.fallbackScreenWidth = LED_SCREEN_WIDTH;
|
|
|
cfg.fallbackScreenHeight = LED_SCREEN_HEIGHT;
|
|
|
// cfg.textEncoding = "GBK"; // BX-6K1-YY 默认按 GBK
|
|
|
cfg.textEncoding = "UTF-8"; // 临时:跳过 iconv,先验证连通和协议
|
|
|
g_led_client = new led::Bx6k1YyLedClient(cfg);
|
|
|
}
|
|
|
|
|
|
// ====== 1. DDS 订阅 ======
|
|
|
sub = std::make_shared<SubscriberApp>(domain_id);
|
|
|
DEBUG("Program is running. Please press Ctrl+C to stop at any time.");
|
|
|
|
|
|
// ====== 2. 启动直接显示默认内容(长驻 area 0)======
|
|
|
const std::string default_text = "#3排队"; // UTF-8 → iconv 转 GBK = 23 33 C5 C5 B6 D3
|
|
|
send_default_text(default_text);
|
|
|
|
|
|
// ====== 3. 主循环:仅 QueueSuccess 触发刷新,下发到 area 1(60 秒自删)======
|
|
|
std::string last_text;
|
|
|
bool last_inited = false;
|
|
|
|
|
|
while (running.load())
|
|
|
{
|
|
|
std::unique_lock<std::mutex> lock(DdsMsgData::queue_cv_mtx_, std::try_to_lock);
|
|
|
if (lock.owns_lock())
|
|
|
{
|
|
|
if (!DdsMsgData::QueueSuccess_queue_.empty())
|
|
|
{
|
|
|
Queue::QueueSuccess info = std::move(DdsMsgData::QueueSuccess_queue_.front());
|
|
|
DdsMsgData::QueueSuccess_queue_.pop();
|
|
|
lock.unlock();
|
|
|
|
|
|
std::string cur = info.display_text();
|
|
|
if (!last_inited || cur != last_text)
|
|
|
{
|
|
|
last_text = cur;
|
|
|
last_inited = true;
|
|
|
DEBUG("QueueSuccess.display_text=" << cur);
|
|
|
send_queue_text(cur);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
lock.unlock();
|
|
|
}
|
|
|
}
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
|
}
|
|
|
|
|
|
// ====== 4. 退出:释放 LED 客户端 ======
|
|
|
if (g_led_client)
|
|
|
{
|
|
|
delete g_led_client;
|
|
|
g_led_client = nullptr;
|
|
|
}
|
|
|
|
|
|
stop_handler = [&](int signum) {
|
|
|
std::cout << "\n" << parse_signal(signum) << " received, stopping "
|
|
|
<< (argc > 0 ? argv[0] : "") << " execution." << std::endl;
|
|
|
running.store(false);
|
|
|
};
|
|
|
signal(SIGINT, signal_handler);
|
|
|
signal(SIGTERM, signal_handler);
|
|
|
#ifndef _WIN32
|
|
|
signal(SIGQUIT, signal_handler);
|
|
|
signal(SIGHUP, signal_handler);
|
|
|
#endif
|
|
|
|
|
|
Log::Reset();
|
|
|
return ret;
|
|
|
}
|