【新增】设备信息获取接口

This commit is contained in:
wdp
2025-01-20 22:30:11 +08:00
parent 18d649a636
commit df1f4b6a69
3 changed files with 306 additions and 0 deletions

257
src/util/DeviceInfo.cpp Normal file
View File

@@ -0,0 +1,257 @@
#include "DeviceInfo.h"
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <algorithm>
#ifdef _WIN32
#include <windows.h>
#include <comdef.h>
#include <Wbemidl.h>
#include <iphlpapi.h>
#include <iomanip>
// #include <winsock2.h>
// #include <ws2tcpip.h>
#pragma comment(lib, "wbemuuid.lib")
#pragma comment(lib, "iphlpapi.lib")
// #pragma comment(lib, "ws2_32.lib")
#elif defined(__linux__)
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/cpu.h>
#include <sys/utsname.h>
#elif defined(__ANDROID__)
#include <sys/system_properties.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <cutils/properties.h>
#endif
/// @brief 格式化mac地址删除:或者- 和空格 并且转成大写
static std::string& FormatMac(std::string& mac) {
for (auto &c : mac) {
if (c == ':' || c == '-') {
c = ' ';
}
}
std::transform(mac.begin(), mac.end(), mac.begin(), [ ](unsigned char c) { return std::toupper(c); });
// 删除空格
mac.erase(std::remove(mac.begin(), mac.end(), ' '), mac.end());
return mac;
}
std::vector<std::string> DeviceInfo::GetMacAddress() {
m_macs.clear();
#ifdef _WIN32
IP_ADAPTER_INFO adapterInfo[16];
DWORD bufLen = sizeof(adapterInfo);
DWORD status = GetAdaptersInfo(adapterInfo, &bufLen);
if (status == ERROR_SUCCESS) {
PIP_ADAPTER_INFO pAdapterInfo = adapterInfo;
while (pAdapterInfo) {
std::ostringstream os;
os << std::hex << std::setfill('0');
for (UINT i = 0; i < pAdapterInfo->AddressLength; i++) {
os << std::setw(2) << static_cast<int>(pAdapterInfo->Address[i]);
if (i < pAdapterInfo->AddressLength - 1) {
os << ":";
}
}
m_macs.push_back(os.str());
pAdapterInfo = pAdapterInfo->Next;
}
}
#endif
#ifdef __linux__
DIR *dir;
struct dirent *entry;
dir = opendir("/sys/class/net/");
if (dir == nullptr) {
goto end;
}
while ((entry = readdir(dir)) != nullptr) {
std::string path = "/sys/class/net/" + std::string(entry->d_name) + "/address";
struct stat statbuf;
if (stat(path.c_str(), &statbuf) == 0 && S_ISREG(statbuf.st_mode)) {
int fd = open(path.c_str(), O_RDONLY);
if (fd != -1) {
char buffer[18];
if (read(fd, buffer, sizeof(buffer) - 1) > 0) {
buffer[17] = '\0';
m_macs.push_back(buffer);
}
close(fd);
}
}
}
closedir(dir);
#endif
end:
/// 地址统一转成大写 并且去掉:或者-
for (auto &mac : m_macs) {
FormatMac(mac);
}
return m_macs;
}
std::string DeviceInfo::GetBoardInfo() {
m_board = "";
#ifdef _WIN32
HRESULT hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres)) {
return m_board;
}
// Initialize Security.
hres = CoInitializeSecurity(
NULL,
-1,
NULL,
NULL,
RPC_C_AUTHN_LEVEL_DEFAULT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE,
NULL
);
if (FAILED(hres)) {
CoUninitialize();
return m_board;
}
// Obtain the initial locator to WMI.
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *)&pLoc);
if (FAILED(hres)) {
CoUninitialize();
return m_board;
}
IWbemServices *pSvc = NULL;
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"),
NULL,
NULL,
0,
NULL,
0,
0,
&pSvc
);
if (FAILED(hres)) {
pLoc->Release();
CoUninitialize();
return m_board;
}
// Set security levels on the proxy.
hres = CoSetProxyBlanket(
pSvc,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE
);
if (FAILED(hres)) {
pSvc->Release();
pLoc->Release();
CoUninitialize();
return m_board;
}
// Use the IWbemServices pointer to make requests of WMI.
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_BaseBoard"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres)) {
std::cerr << "WMI query for Win32_BaseBoard failed. Error code = 0x" << std::hex << hres << std::endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return m_board;
}
// Get the data from the query.
IWbemClassObject *pclsObj;
ULONG uReturn = 0;
while (pEnumerator) {
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if (0 == uReturn) {
break;
}
VARIANT vtProp;
// Get the value of the m_board property.
hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0);
if (SUCCEEDED(hr)) {
m_board = std::string(_bstr_t(vtProp.bstrVal));
VariantClear(&vtProp);
}
pclsObj->Release();
}
// Cleanup
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
CoUninitialize();
#endif
#ifdef __linux__
std::ifstream file("/sys/class/dmi/id/product_serial");
if (file.is_open()) {
std::getline(file, serialNumber);
file.close();
}
#endif
#ifdef __ANDROID__
m_board = "andirod_0000";
#endif
return m_board;
}
bool DeviceInfo::VerifyMac(std::string mac) {
FormatMac(mac);
for (auto& m : m_macs) {
if(m.compare(mac) == 0) {
return true;
}
}
return false;
}
bool DeviceInfo::VerifyBoard(std::string board) {
return board.compare(m_board) == 0;
}

30
src/util/DeviceInfo.h Normal file
View File

@@ -0,0 +1,30 @@
#ifndef DEVICE_INFO_H
#define DEVICE_INFO_H
#include <string>
#include <vector>
#include "util/Singleton.h"
/// @file 这个文件定义了一些跨平台的接口用于获取设备的mac、cpu、主板等信息
class DeviceInfo : public Singleton<DeviceInfo> {
public:
std::vector<std::string> m_macs;
std::string m_board;
/// @brief 获取设备的mac地址
/// @return 设备的mac地址
std::vector<std::string> GetMacAddress();
/// @brief 获取设备的主板信息
/// @return 设备的主板信息
std::string GetBoardInfo();
/// @brief mac地址验证
bool VerifyMac(std::string mac);
/// @brief 主板序列号验证
bool VerifyBoard(std::string board);
};
#endif

19
src/util/Singleton.h Normal file
View File

@@ -0,0 +1,19 @@
#ifndef SINGLETON_H
#define SINGLETON_H
template <typename T>
class Singleton {
public:
static T& GetInstance() {
static T instance;
return instance;
}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
protected:
Singleton() {}
~Singleton() {}
};
#endif