从 Wt 小部件信号事件发出 运行 popen()

Issues running popen() from Wt widget signal event

我正在尝试将固件升级功能集成到 Witty 应用程序中。

应用程序通过/dev/ttyUSB0与外部设备通信,固件升级使用同一个端口,此时应用程序释放端口并通过[=14=调用外部命令行应用程序].

主要问题是它在 main 中执行时完美运行,但在从事件示例中执行时却不是:

m_pUploadButton->clicked().connect(std::bind([=] () {
                pComputer->firmwareUpgrade();
            }));

相关函数的定义如下:

bool ComputerV2::upgradeFirmware()
{
    m_oMutex.lock();

    std::string sFile = "/home/alextown/MPLABXProjects/ordinateur_V2/dist/default/production/ordinateur_V2.production.hex";

    std::string sResult = "";
    std::string sCommand = "/home/alextown/QtProjects/build-pic32ubl-qt-qt5-Release/pic32ubl-qt --headless --port=/dev/" + m_sPort + " --file=" + sFile + " --erase --program --verify --jump-application";

    std::cout << sCommand << std::endl;

    int nResult = exec(sCommand,sResult);

    std::cout << sResult << std::endl;

    m_oMutex.unlock();

    return nResult == 0;
}

int exec(std::string p_sCommand, std::string &p_sResult)
{
    FILE *pipe = popen(p_sCommand.c_str(),"r");

    p_sResult = "";

    if(!pipe) return -1;

    char buffer[128];

    while(!feof(pipe))
    {
        if(fgets(buffer,128,pipe) != NULL)
        {
            p_sResult += buffer;
        }
    }

    return pclose(pipe);
}

据我观察,当 运行 从 main 升级时,一切正常(在升级模式下跳转设备,在正常模式下升级并跳回)。当运行来自widget时,通过端口/dev/ttyUSB0发送的数据不相同,从而导致通信问题和升级失败。

根据我的理解,Witty 小部件的线程 运行 与主应用程序的线程 运行 有所不同。

我强烈建议在外部线程或 std::launch::async'edstd::future` 中执行此更新,因为 Wt 线程确实 特殊.

特殊方式,它们可能是 运行 在某种线程池中,也可能是 运行 在上下文中,即网络服务器的进程(尽管我猜你目前通过内置的部署它在 http-server 中,但假设您想重用您的代码)。

那么你的 USB 驱动程序是否有特定的进程(全局、状态等?)那么最好的办法是在一个新创建的进程中进行升级,除了你的网络应用程序(有人称之为微服务方法,使这种旧技术看起来更花哨)。

如果需要,Wt 提供与外部事件同步的方法。 参见 Wt::WApplication::bindWt::Server::post

将这项工作分开还有一个好处,即您的 Web 应用程序在升级时仍会响应,这可能需要一些时间。此外,如果升级导致一些重大问题,您的网络应用程序可以更轻松地传递诊断消息或接管更好的问题。