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-06-29 14:08:45 +08:00
|
|
|
std::map<std::string, int8_t> device_map;
|
2025-05-27 15:37:11 +08:00
|
|
|
|
|
|
|
|
ScanBlueteeth::ScanBlueteeth() : device_id(-1), sock(-1) {
|
|
|
|
|
retry_count = 0;
|
|
|
|
|
max_retries = 5;
|
|
|
|
|
// 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) {
|
|
|
|
|
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 字节
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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");
|
|
|
|
|
|
|
|
|
|
//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));
|
|
|
|
|
sprintf(whereCon, "mac='%s' order by timeStamp desc limit 1", mac);
|
|
|
|
|
std::string timestamp_last = sqlite_db_ctrl::instance().GetData(" blueteeth_info ", " timeStamp ", whereCon);
|
2025-05-27 15:37:11 +08:00
|
|
|
GetTimeNet(localtimestamp, 1);
|
2025-05-30 18:31:15 +08:00
|
|
|
if (atol(localtimestamp) - atol(timestamp_last.c_str()) < 10) {
|
|
|
|
|
zlog_info(zct, "blueteeth_info already exist, mac = %s, timeStamp = %s", mac, timestamp_last.c_str());
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
sprintf(insertSql,"'%s','%s','%d',%d,'%.1f','%.1f','%.1f','%.1f','%s'",device_id,mac,rssi,count,volt_,blueteeth_temp,chip_temp,env_temp,localtimestamp);
|
|
|
|
|
sqlite_db_ctrl::instance().InsertData(" blueteeth_info ", insertSql);
|
|
|
|
|
}
|
2025-06-29 14:08:45 +08:00
|
|
|
Json::Value root;
|
|
|
|
|
Json::Value valdatastatic;
|
|
|
|
|
valdatastatic["TemperatureTop"] = env_temp;
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
int iRet = data_publish(strstatisticData.c_str(), GlobalConfig::Topic_G.mPubData.c_str());
|
|
|
|
|
device_map.insert(std::make_pair(std::string(mac), rssi));
|
2025-05-27 15:37:11 +08:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|