windows系统下监控串口设备的插入和拔出(C++)

项目github地址:https://github.com/BaoZR/serial_monitor

思路

特别感谢 Hardware Change Detection
要想获得设备的插入和拔出情况,就要借助windows自带的消息循环,通过注册串口类变动的通知,来实现这一目标。
设计思路如下图
在这里插入图片描述

最后我写了一个演示效果的ui-demo和一个方便使用的lib导出库。

演示效果

请添加图片描述

代码(c++)

lib导出库的头文件
/**
 * @file serial_monitor_lib.h
 * @brief 用于监控串口物理插入和物理拔出的库,只能在win32下使用
 * @details 监控窗口为固定名字的窗口,所以请勿重复调用。
 * @author cuicui
 * @date 2023-09-04
 * @version 0.1
 * @copyright MIT
 * @web https://github.com/BaoZR/serial_monitor
 */



#ifndef _SERIAL_MONITOR_LIB_H_
#define _SERIAL_MONITOR_LIB_H_

#include <string>

#ifdef SERIAL_MONITOR_LIB_EXPORTS
#ifdef _WIN32
#define SERIAL_MONITOR_API __declspec(dllexport) __stdcall
#else
#define SERIAL_MONITOR_API __attribute__((visibility("default")))
#endif // _WIN32
#else
#ifdef _WIN32
#define SERIAL_MONITOR_API __declspec(dllimport) __stdcall
#else
#define SERIAL_MONITOR_API
#endif // _WIN32
#endif // SERIAL_MONITOR_LIB_EXPORTS

#define IN
#define OUT
#define INOUT


#define DEVICE_NEW                              (1)     /* 新的设备 */
#define DEVICE_DELETE                           (2)     /* 被删除的设备 */

typedef std::string DeviceId;

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

/**
 * @brief 监控的状态回调函数,用于初始化,串口设备插入,串口设备拔出时,返回状态,需传入monitor_init函数中
 * @param id 串口设备的ID
 * @param status 发现新的设备或者该设备已删除
 *               DEVICE_NEW 
 *               DEVICE_DELETE
 * @param friendly_name 发现新的设备时返回友好的串口名字,删除设备时返回之前友好的串口名字
 */
typedef void (*device_change_progress)(
    IN const std::string& id,
    IN int status,
    IN const std::string& friendly_name);

/**
 * @brief 用于初始化监听线程,监听是单窗口,请勿重复调用
 * @param device_change_progress 传入的回调函数
 *  
 */
void SERIAL_MONITOR_API monitor_init(
    IN device_change_progress progress_cb
);

/** @brief 用于关闭监听
 * 
 */
void SERIAL_MONITOR_API monitor_terminate();


#ifdef __cplusplus
}
#endif // __cplusplus

#endif
lib导出库的源文件
#define SERIAL_MONITOR_LIB_EXPORTS
#include "serial_monitor_lib.h"
#include "simple_notify_window.h"
#include "enum_device.h"
#include "device_info.h"
#include <iostream>
#include <mutex>

class DeviceChange : public IDeviceChanged
{
public:
    explicit DeviceChange(device_change_progress progress_cb);
    void InterfaceArrival(const GUID &guid);
    void InterfaceRemoved(const std::string &lower_dbcc);

private:
    device_change_progress progress_cb_;
};

static std::unique_ptr<SimpleNotifyWindow> window_ = nullptr;
static std::unique_ptr<DeviceChange> device_change_ = nullptr;
static HDEVNOTIFY h_dev_notify_ = nullptr;
static std::map<DeviceId, DeviceInfo> actual_devices_;
static bool init_flag_ = false;
static std::mutex section_;

DeviceChange::DeviceChange(device_change_progress progress_cb)
{
    this->progress_cb_ = progress_cb;
};
void DeviceChange::InterfaceRemoved(const std::string &lower_dbcc)
{
    section_.lock();
    if(actual_devices_.count(lower_dbcc) != 0)
    {
        std::string name = actual_devices_[lower_dbcc].GetFriendlyName();
        actual_devices_.erase(lower_dbcc);
        this->progress_cb_(lower_dbcc, DEVICE_DELETE, name);
    }
    section_.unlock();
}
void DeviceChange::InterfaceArrival(const GUID &guid)
{
    std::vector<DeviceInfo> temp_devices = detect_device::GetDevicesByGuid(&const_cast<GUID&>(guid));
    for(std::vector<DeviceInfo>::const_iterator iter = temp_devices.begin();iter != temp_devices.end();iter++)
    {
        section_.lock();
        if(actual_devices_.count((*iter).GetDbcc()) == 0)
        {
            actual_devices_[(*iter).GetDbcc()] = *iter;
            this->progress_cb_((*iter).GetDbcc(), DEVICE_NEW, (*iter).GetFriendlyName());
        }
        section_.unlock();
    }
}

void SERIAL_MONITOR_API monitor_init(
    IN device_change_progress progress_cb)
{
    if (init_flag_ == true)
    {
        monitor_terminate();
    }
    device_change_.reset(new DeviceChange(progress_cb));
    window_.reset(new SimpleNotifyWindow(*device_change_));
    h_dev_notify_ = detect_device::RegisterNotify(GUID_DEVINTERFACE_COMPORT, (*window_).GetHandle());
    init_flag_ = true;
    (*device_change_).InterfaceArrival(GUID_DEVINTERFACE_COMPORT);//初始化扫描

};

void SERIAL_MONITOR_API monitor_terminate()
{
    if (init_flag_ == true)
    {
        detect_device::UnRegisterNotify(h_dev_notify_);
        window_.reset(nullptr);
        device_change_ = nullptr;
        actual_devices_.clear();
        init_flag_ = false;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值