WLG/wifi_5g/scan_blueteeth.cpp

269 lines
9.7 KiB
C++
Raw Permalink Normal View History

2025-05-27 15:37:11 +08:00
#include "scan_blueteeth.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <stdint.h>
#include <fcntl.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <zlog.h>
#include "common/common_func.hpp"
2025-06-29 14:08:45 +08:00
#include "common/global.hpp"
2025-05-27 15:37:11 +08:00
#include "dbaccess/sql_db.hpp"
2025-06-29 14:08:45 +08:00
#include "mqttclient/mqtt_client.h"
2025-05-27 15:37:11 +08:00
extern zlog_category_t *zct;
2025-07-23 22:00:44 +08:00
std::unordered_map<std::string, DeviceInfo> device_map;
std::mutex map_mutex;
2025-05-27 15:37:11 +08:00
2025-07-23 22:00:44 +08:00
double min = -102;
double max = -60;
// 将信号值 x 映射为百分比 [0, 100]
double signalToPercent(double x, double min, double max) {
if (x < min) x = min;
if (x > max) x = max;
return (x - min) / (max - min) * 100.0;
}
// 将百分比 [0, 100] 还原为信号值
double percentToSignal(double percent, double min, double max) {
if (percent < 0) percent = 0;
if (percent > 100) percent = 100;
return min + (percent / 100.0) * (max - min);
}
// 添加或更新设备信息
void updateDevice(const std::string& mac, int rssi) {
std::lock_guard<std::mutex> lock(map_mutex);
device_map[mac] = {
rssi,
steady_clock::now()
};
}
// 清除超过 timeout_ms 毫秒未更新的设备
void removeStaleDevices(int timeout_ms = 1000) {
std::lock_guard<std::mutex> lock(map_mutex);
auto now = steady_clock::now();
for (auto it = device_map.begin(); it != device_map.end(); ) {
auto elapsed = duration_cast<milliseconds>(now - it->second.last_seen).count();
if (elapsed > timeout_ms) {
std::cout << "[Remove] " << it->first << " (stale: " << elapsed << "ms)\n";
it = device_map.erase(it);
} else {
++it;
}
}
}
2025-05-27 15:37:11 +08:00
ScanBlueteeth::ScanBlueteeth() : device_id(-1), sock(-1) {
retry_count = 0;
max_retries = 5;
2025-07-14 20:24:40 +08:00
current_dev = ""; // Initialize current_dev to an empty string
ccurrent_time = "";
2025-05-27 15:37:11 +08:00
// Constructor initializes device_id and sock to invalid values
}
ScanBlueteeth::~ScanBlueteeth() {
// Destructor ensures resources are released
if (sock >= 0) {
hci_le_set_scan_enable(sock, 0x00, 0x00, 1000); // Disable scanning
close(sock); // Close the socket
}
}
// 初始化 socket 成为非阻塞模式
int set_nonblocking(int fd) {
int flags = fcntl(fd, F_GETFL, 0);
if (flags == -1) return -1;
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
int ScanBlueteeth::InitDevice(){
zlog_info(zct,"Initializing HCI device...");
system("hciconfig hci0 reset");
device_id = hci_get_route(NULL);
sock = hci_open_dev(device_id);
if (device_id < 0 || sock < 0) {
zlog_error(zct,"Failed to open HCI device.");
return -1;
}
// 设置扫描参数 扫描间隔450ms
if (hci_le_set_scan_parameters(sock, 0x01, 0x02D0, 0x02D0, 0x00, 0x00, 1000) < 0) {
zlog_error(zct,"Set scan parameters failed");
close(sock);
return -2;
}
// 启动扫描
if (hci_le_set_scan_enable(sock, 0x01, 0x00, 1000) < 0) {
zlog_error(zct,"Enable scan failed");
close(sock);
return -3;
}
// 设置事件过滤器
struct hci_filter nf;
hci_filter_clear(&nf);
hci_filter_set_ptype(HCI_EVENT_PKT, &nf);
hci_filter_set_event(EVT_LE_META_EVENT, &nf);
setsockopt(sock, SOL_HCI, HCI_FILTER, &nf, sizeof(nf));
retry_count = 0;
if (sock >= 0) {
set_nonblocking(sock); // 设置非阻塞
}
return 0;
}
void ScanBlueteeth::StartScan(){
while (1) {
2025-07-14 20:24:40 +08:00
mssleep(100); // 每次扫描间隔100毫秒
2025-05-27 15:37:11 +08:00
if (sock < 0 || retry_count > max_retries) {
zlog_error(zct,"Reinitializing HCI device...");
if (sock >= 0) close(sock);
if (InitDevice() != 0) {
zlog_error(zct,"Failed to initialize HCI device.");
sleep(3);
retry_count++;
continue;
}
retry_count = 0;
}
unsigned char buf[HCI_MAX_EVENT_SIZE];
int len = read(sock, buf, sizeof(buf));
if (len < 0) {
if (errno == EAGAIN || errno == EINTR) {
continue; // Ignore temporary errors
} else {
zlog_error(zct,"Read error: %s", strerror(errno));
retry_count++;
sleep(1);
continue;
}
continue;
}
evt_le_meta_event *meta = (evt_le_meta_event *)(buf + (1 + HCI_EVENT_HDR_SIZE));
if (meta->subevent != EVT_LE_ADVERTISING_REPORT) continue;
uint8_t *ptr = meta->data;
uint8_t reports = *ptr++;
for (int i = 0; i < reports; i++) {
le_advertising_info *info = (le_advertising_info *)ptr;
char addr[18];
ba2str(&info->bdaddr, addr);
int info_len = info->length;
int rssi_offset = (uint8_t *)info->data - buf + info_len;
int8_t rssi = (int8_t)buf[rssi_offset];
ParseData(info->data, info->length,rssi);
ptr += sizeof(le_advertising_info) + info->length + 1; // 最后的 +1 是 RSSI 字节
}
2025-07-23 22:00:44 +08:00
2025-05-27 15:37:11 +08:00
}
hci_le_set_scan_enable(sock, 0x00, 0x00, 1000);
close(sock);
}
void ScanBlueteeth::ParseData(unsigned char *data, int len,int8_t rssi){
if (len < 25) return;
// 找到 Manufacturer Specific 区块开头
for (int i = 0; i < len - 4; i++) {
if (data[i] == 0x06 && data[i+1] == 0x09 && data[i+2] == 0x43 && data[i+3] == 0x68 && data[i+4] == 0x61) {
char device_id[15]={0},mac[15] = {0},temp_bl[5]={0};
int count = 0;
sprintf(device_id,"%02x%02x%02x%02x%02x%02x",data[2],data[3],data[4],data[5],data[6],data[7]);
sprintf(mac,"%02x%02x%02x%02x%02x%02x",data[13],data[14],data[15],data[16],data[17],data[18]);
sprintf(temp_bl,"%02x%02x",data[i + 24],data[i + 25]);
int temp_ch = (data[i + 26] << 8) | data[i + 27];
int volt = data[i + 23];
short temp1001 = ((data[i + 28] << 8) | data[i + 29]) >> 4;
count = (data[i + 19] << 24) | (data[i + 20] << 16) | (data[i + 21] << 8) | data[i + 22];
long num = strtol(temp_bl, NULL, 16);
short signed_num = (short)num;
float blueteeth_temp = (float)signed_num*0.01;
float chip_temp = 0.0;
if (temp_ch == 0)
{
chip_temp = 1000;
}else{
chip_temp = ((float)temp_ch*0.0625) - 50.0625;
}
float env_temp = 0.0;
if (temp1001 < 0x800)
{
env_temp = (float)temp1001 * 0.0625;
}else{
env_temp = float((~temp1001) & 0xfff) * (-1) * 0.0625;
}
float volt_ = (double)volt * 0.03125;
// 打印原始广播数据十六进制
printf(" Raw Adv Data: ");
for (int k = 0; k < len; k++) {
printf("%02x ", data[k]);
}
printf("\n");
2025-07-23 22:00:44 +08:00
double rssi_percent = signalToPercent((double)rssi, min, max);
updateDevice(std::string(mac), (int)rssi_percent);
removeStaleDevices(1000*300); // 清除超过5分钟未更新的设备
2025-05-27 15:37:11 +08:00
//printf("time %s Bluetooth temp :%f ℃ , NST 1001 temp: %f ℃\n",GetCurrentTime().c_str(),(float)temp*0.01, ((float)temp1*0.0625) - 50.0625);
//printf(" volt : %f v\n", (double)volt * 0.03125 );
2025-05-30 18:31:15 +08:00
char insertSql[512] = {0},whereCon[128] = {0};
2025-05-27 15:37:11 +08:00
char localtimestamp[32] = {0};
2025-05-30 18:31:15 +08:00
memset(whereCon,0,sizeof(whereCon));
2025-05-27 15:37:11 +08:00
GetTimeNet(localtimestamp, 1);
2025-07-14 20:24:40 +08:00
if (current_dev == mac && atol(localtimestamp) - atol(ccurrent_time.c_str()) < 10) {
zlog_info(zct, "blueteeth_info already exist, mac = %s", mac);
return; // 如果当前设备已经存在,则不再插入
} else{
current_dev = mac; // 更新当前设备
}
ccurrent_time = std::string(localtimestamp);
sprintf(whereCon, "mac='%s'", mac);
int count_ = sqlite_db_ctrl::instance().GetTableRows(T_SENSOR_BT_INFO(TNAME), whereCon);
if (count_ < 1) {
zlog_info(zct, "device not exist, mac = %s", mac);
return;
2025-05-30 18:31:15 +08:00
} else {
2025-07-14 20:24:40 +08:00
zlog_info(zct, "device already exist, mac = %s", mac);
2025-05-30 18:31:15 +08:00
}
2025-07-14 20:24:40 +08:00
2025-07-23 22:00:44 +08:00
sprintf(insertSql,"'%s','%s','%d','%d',%d,'%.1f','%.1f','%.1f','%.1f','%s'",device_id,mac,rssi,(int)rssi_percent,count,volt_,blueteeth_temp,chip_temp,env_temp,localtimestamp);
2025-07-14 20:24:40 +08:00
int ret = sqlite_db_ctrl::instance().InsertData(" blueteeth_info ", insertSql);
2025-06-29 14:08:45 +08:00
Json::Value root;
Json::Value valdatastatic;
2025-07-14 20:24:40 +08:00
valdatastatic["TemperatureTop"] = blueteeth_temp;
2025-06-29 14:08:45 +08:00
valdatastatic["TemperatureBot"] = chip_temp;
valdatastatic["Voltage"] = volt_;
valdatastatic["ChannelId"] = mac;
valdatastatic["TimeStamp"] = localtimestamp;
valdatastatic["dataNodeNo"] = mac;
root["data"] = valdatastatic;
root["dataNodeGatewayNo"] = GlobalConfig::MacAddr_G;
Json::FastWriter featureValue;
std::string strstatisticData = featureValue.write(root);
2025-07-14 20:24:40 +08:00
int iRet = data_publish(strstatisticData.c_str(), GlobalConfig::Topic_G.mPubBTData.c_str());
2025-07-23 22:00:44 +08:00
2025-05-27 15:37:11 +08:00
return;
}
}
}