// 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 #include #include #include #include #include #include #include #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 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 DdsMsgData::ScaleInfo_queue_; std::queue DdsMsgData::WeightInfoOk_queue_; std::queue DdsMsgData::WeightInfoError_queue_; std::queue DdsMsgData::LicenseSnapUpdate_queue_; std::queue DdsMsgData::QueueSuccess_queue_; std::mutex DdsMsgData::queue_cv_mtx_; std::atomic running(true); int main(int argc, char** argv) { auto ret = EXIT_SUCCESS; std::shared_ptr 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(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(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 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; }