
#include "device_uhd_c.h"
#include "CtrlSpecialDecode.h"
#include "_AlgmDemodulate.h"
#include "cJSON.h"
#include "device_uhd_cpp.h"
#include "device_uhd_struct.h"
#include "error_callback.h"
#include "hulc/DataOutputFormats.h"
#include <atomic>
#include <cstdio>
#include <deque>
#include <fstream>
#include <functional>
#include <iostream>
#include <mutex>
#include <queue>
#include <sstream>
#include <thread>
#include <unistd.h>
#include <vector>
using namespace std;

rx_data_cbk_t s_cbk;

#include <iostream>
#include <sstream>
#include <string>

#include <atomic>
using namespace std;

// stringstream error_ss;
// mutex error_ss_mutex;
// device_uhd_c_error_out_cbk_t error_out_cbk;

typedef struct config_struct_t
{
    char cwd[PATH_MAX];
    char dirpath[PATH_MAX];
    double rx_gain_val = 0;
    char rx_clock_ref[50] = {0};

    char config_name[255]; // = "lib9002config.json";
    char config_path[PATH_MAX];
    char is_save_adsb;
    char is_save_yuanshi_iq;
    int new_file_zhouqi_s;
    int max_save_file_count;

    uint64_t save_yuanshi_size_MByte;
    bool need_new_file;

    uint64_t cache_over_byte;
    char is_save_gps;

    char is_trans_gps;

    int end_flag = 3;

} config_struct_t;
ofstream ofs_adsb;
ofstream ofs_yuanshi_iq;
ofstream ofs_gps;
config_struct_t cfg;
std::mutex cfg_mutex;
std::thread *pread_cfg_thread;
bool b_read_cfg_running = false;
deque<string> yuanshi_iq_file_path_dq;

#include <cstdlib>
#include <libgen.h>
#include <string>
#include <unistd.h>

void read_cfg_func()
{
    time_t read_cfg_t0 = time(0);
    bool b_once = false;
    while (b_read_cfg_running)
    {

        time_t read_cfg_t1 = time(0);

        if (difftime(read_cfg_t1, read_cfg_t0) > cfg.new_file_zhouqi_s || b_once == false)
        {
            b_once = true;
            {
                ifstream ifs(cfg.config_path);
                string str;

                if (ifs.is_open())
                {
                    std::stringstream ss;
                    ss << ifs.rdbuf();
                    str = ss.str();
                    ifs.close();
                }
                else
                {
                    ofstream ofs(cfg.config_path);
                    string tmp_str = "{\"gain\":\"30.0\",\"clock_ref\":\"external\",\"is_save_adsb\":\"0\",\"new_file_zhouqi_s\":\"60\",\"max_save_file_count\":\"3\",\"is_save_yuanshi_iq\":\"0\",\"save_yuanshi_size_MByte\":\"0\",\"is_trans_gps\":\"0\",\"is_save_gps\":\"0\"}";

                    ofs.write(tmp_str.c_str(), tmp_str.size());
                    str = tmp_str;
                    ofs.close();
                }

                cJSON *root = nullptr;
                if (str.size() > 2)
                {
                    root = cJSON_Parse(str.data());
                }
                else
                {
                    sleep(5);
                    continue;
                }

                cJSON *obj_gain = nullptr;
                obj_gain = cJSON_GetObjectItem(root, "gain");
                if (obj_gain != nullptr)
                {
                    lock_guard<std::mutex> lg(cfg_mutex);
                    char *value = obj_gain->valuestring;

                    cfg.rx_gain_val = std::stof(value);
                }
                else
                {
                    cJSON_AddItemToObject(root, "gain", cJSON_CreateString("30.0"));
                }

                cJSON *obj_clock_ref = nullptr;
                obj_clock_ref = cJSON_GetObjectItem(root, "clock_ref");
                if (obj_clock_ref != nullptr)
                {
                    lock_guard<std::mutex> lg(cfg_mutex);
                    char *value = obj_clock_ref->valuestring;

                    strcpy(cfg.rx_clock_ref, value);
                }
                else
                {
                    cJSON_AddItemToObject(root, "clock_ref", cJSON_CreateString("external"));
                }

                cJSON *obj_is_save_adsb = nullptr;
                obj_is_save_adsb = cJSON_GetObjectItem(root, "is_save_adsb");
                if (obj_is_save_adsb != nullptr)
                {
                    lock_guard<std::mutex> lg(cfg_mutex);
                    char *value = obj_is_save_adsb->valuestring;

                    cfg.is_save_adsb = std::stod(value);
                }
                else
                {
                    cJSON_AddItemToObject(root, "is_save_adsb", cJSON_CreateString("0"));
                }

                cJSON *obj_is_save_yuanshi_iq = nullptr;
                obj_is_save_yuanshi_iq = cJSON_GetObjectItem(root, "is_save_yuanshi_iq");
                if (obj_is_save_adsb != nullptr)
                {
                    lock_guard<std::mutex> lg(cfg_mutex);
                    char *value = obj_is_save_yuanshi_iq->valuestring;

                    cfg.is_save_yuanshi_iq = std::stod(value);
                }
                else
                {
                    cJSON_AddItemToObject(root, "is_save_yuanshi_iq", cJSON_CreateString("0"));
                }

                {
                    cJSON *obj_new_file_zhouqi_s = nullptr;
                    obj_new_file_zhouqi_s = cJSON_GetObjectItem(root, "new_file_zhouqi_s");
                    if (obj_new_file_zhouqi_s != nullptr)
                    {
                        lock_guard<std::mutex> lg(cfg_mutex);
                        char *value = obj_new_file_zhouqi_s->valuestring;

                        cfg.new_file_zhouqi_s = std::stod(value);
                    }
                    else
                    {
                        cJSON_AddItemToObject(root, "new_file_zhouqi_s", cJSON_CreateString("60"));
                    }
                }

                {
                    cJSON *obj_max_save_file_count = nullptr;
                    obj_max_save_file_count = cJSON_GetObjectItem(root, "max_save_file_count");
                    if (obj_max_save_file_count != nullptr)
                    {
                        lock_guard<std::mutex> lg(cfg_mutex);
                        char *value = obj_max_save_file_count->valuestring;

                        cfg.max_save_file_count = std::stod(value);
                    }
                    else
                    {
                        cJSON_AddItemToObject(root, "max_save_file_count", cJSON_CreateString("3"));
                    }
                }

                cJSON *obj_save_yuanshi_size_MByte = nullptr;
                obj_save_yuanshi_size_MByte = cJSON_GetObjectItem(root, "save_yuanshi_size_MByte");
                if (obj_save_yuanshi_size_MByte != nullptr)
                {
                    lock_guard<std::mutex> lg(cfg_mutex);
                    char *value = obj_save_yuanshi_size_MByte->valuestring;

                    cfg.save_yuanshi_size_MByte = std::stod(value);
                }
                else
                {
                    cJSON_AddItemToObject(root, "save_yuanshi_size_MByte", cJSON_CreateString("0"));
                }
                // is_save_gps

                cJSON *obj_is_save_gps = nullptr;
                obj_is_save_gps = cJSON_GetObjectItem(root, "is_save_gps");
                if (obj_is_save_gps != nullptr)
                {
                    lock_guard<std::mutex> lg(cfg_mutex);
                    char *value = obj_is_save_gps->valuestring;

                    cfg.is_save_gps = std::stod(value);
                }
                else
                {
                    cJSON_AddItemToObject(root, "is_save_gps", cJSON_CreateString("0"));
                }

                // is_trans_gps
                cJSON *obj_is_trans_gps = nullptr;
                obj_is_trans_gps = cJSON_GetObjectItem(root, "is_trans_gps");
                if (obj_is_trans_gps != nullptr)
                {
                    lock_guard<std::mutex> lg(cfg_mutex);
                    char *value = obj_is_trans_gps->valuestring;

                    cfg.is_trans_gps = std::stod(value);
                }
                else
                {
                    cJSON_AddItemToObject(root, "is_trans_gps", cJSON_CreateString("0"));
                }
                char *rootstr = cJSON_Print(root);

                ofstream ofs(cfg.config_path);
                if (ofs.is_open())
                {
                    ofs.write(rootstr, strlen(rootstr));
                    ofs.close();
                }
                free(rootstr);

                cJSON_Delete(root);

                if (cfg.is_save_adsb & !ofs_adsb.is_open())
                {
                    lock_guard<std::mutex> lg(cfg_mutex);
                    string adsb_path;

                    time_t t = time(0);
                    char t_str[30];
                    memset(t_str, 0, 30);
                    strftime(t_str, sizeof(t_str), "%Y_%m_%d_%H_%M_%S", localtime(&t));

                    adsb_path.append(cfg.dirpath);
                    adsb_path.append("/adsb").append(t_str).append(".txt");
                    ofs_adsb.open(adsb_path);
                }
                else if (!cfg.is_save_adsb && ofs_adsb.is_open())
                {

                    ofs_adsb.close();
                }
                if (cfg.is_save_gps && !ofs_gps.is_open())
                {
                    lock_guard<std::mutex> lg(cfg_mutex);
                    string gps_path;

                    time_t t = time(0);
                    char t_str[30];
                    memset(t_str, 0, 30);
                    strftime(t_str, sizeof(t_str), "%Y_%m_%d_%H_%M_%S", localtime(&t));

                    gps_path.append(cfg.dirpath);
                    gps_path.append("/gps").append(t_str).append(".txt");
                }
                else if (!cfg.is_save_gps && ofs_gps.is_open())
                {

                    ofs_gps.close();
                }

                if (cfg.is_save_yuanshi_iq && cfg.save_yuanshi_size_MByte > 0)
                {

                    lock_guard<std::mutex> lg(cfg_mutex);

                    if (cfg.need_new_file == true)
                    {
                        string yuanshi_path;
                        if (ofs_yuanshi_iq.is_open())
                        {
                            ofs_yuanshi_iq.close();
                        }

                        time_t t = time(0);
                        char t_str[30];
                        memset(t_str, 0, 30);
                        strftime(t_str, sizeof(t_str), "%Y_%m_%d_%H_%M_%S", localtime(&t));

                        yuanshi_path.append(cfg.dirpath);
                        yuanshi_path.append("/yuanshi").append(t_str).append(".dat");

                        yuanshi_iq_file_path_dq.push_back(yuanshi_path);
                        if (yuanshi_iq_file_path_dq.size() > cfg.max_save_file_count)
                        {

                            string first = yuanshi_iq_file_path_dq.front();
                            yuanshi_iq_file_path_dq.pop_front();

                            std::remove(first.c_str());
                        }

                        ofs_yuanshi_iq.open(yuanshi_path, ios::binary);

                        cfg.need_new_file = false;
                    }
                }
            }
            read_cfg_t0 = read_cfg_t1;
        }

        sleep(5);
    }
}
int32_t init9002(void **phandle)
{

    //
    {
        memset(cfg.cwd, 0, sizeof(cfg.cwd));
        strcpy(cfg.rx_clock_ref, "external");
        memset(cfg.config_name, 0, sizeof(cfg.config_name));
        memset(cfg.config_path, 0, sizeof(cfg.config_path));
        cfg.rx_gain_val = 30.0;
        cfg.is_save_adsb = 0;
        cfg.is_save_gps = 0;
        cfg.is_save_yuanshi_iq = 0;
        cfg.save_yuanshi_size_MByte = 0;
        cfg.cache_over_byte = 0;
        cfg.need_new_file = true;
        cfg.end_flag = 3;
    }
    Device_UHD *pthis = new Device_UHD();
    // getcwd(cwd, sizeof(cwd) - 1);

    strcpy(cfg.config_name, "lib9002config.json");
    int len = readlink("/proc/self/exe", cfg.cwd, sizeof(cfg.cwd) - 1);
    cfg.cwd[len] = '\0';
    char *dir = dirname(cfg.cwd);

    strcpy(cfg.dirpath, dir);
    sprintf(cfg.config_path, "%s/%s", dir, cfg.config_name);
    // printf("config_path = %s\n", cfg.config_path);

    b_read_cfg_running = true;

    ifstream ifs(cfg.config_path);
    string str;

    if (ifs.is_open())
    {
        std::stringstream ss;
        ss << ifs.rdbuf();
        str = ss.str();
        ifs.close();
    }
    else
    {
        ofstream ofs(cfg.config_path);
        string tmp_str = "{\"gain\":\"30.0\",\"clock_ref\":\"external\",\"is_save_adsb\":\"0\",\"new_file_zhouqi_s\":\"60\",\"max_save_file_count\":\"20\",\"is_save_yuanshi_iq\":\"0\",\"save_yuanshi_size_MByte\":\"0\",\"is_trans_gps\":\"0\",\"is_save_gps\":\"0\"}";

        ofs.write(tmp_str.c_str(), tmp_str.size());
        str = tmp_str;
        ofs.close();
    }

    stringstream ss;

    ss << "json_str = " << str << endl;
    MACROS_ERROR_CBK_CALL(ss.str().c_str());

    pread_cfg_thread = new thread(read_cfg_func);

    *phandle = pthis;
    return 0;
}
int32_t free9002(void **phandle)
{
    if (phandle != nullptr)
    {
        b_read_cfg_running = false;
        if (pread_cfg_thread && pread_cfg_thread->joinable())
        {
            pread_cfg_thread->join();
            delete pread_cfg_thread;
        }
        Device_UHD *pthis = (Device_UHD *)*phandle;
        delete pthis;
        pthis = nullptr;
        phandle = nullptr;

        return 0;
    }
    return 0;
}
int32_t isDevOpened(void *phandle, int32_t *result)
{
    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        *result = (int32_t)pthis->isDevOpened();
        return 0;
    }
    return -1;
}
int32_t findDevices(void *phandle, uhd::device_addrs_t *addrs)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        *addrs = pthis->findDevices();
        return 0;
    }
    return -1;
}
int32_t openDevice(void *phandle, uhd::device_addr_t addr)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        pthis->openDevice(addr);
        return 0;
    }
    return -1;
}
int32_t closeDevice(void *phandle)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        pthis->closeDevice();
        return 0;
    }
    return -1;
}
int32_t findDevInfos(void *phandle, char infos[1000])
{
    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        string str = pthis->findDevInfos();
        strcpy(infos, str.c_str());
        return 0;
    }
    return -1;
}
int32_t findDevInfos2(void *phandle, char infos[1000])
{
    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        string str = pthis->findDevInfos2();
        strcpy(infos, str.c_str());
        return 0;
    }
    return -1;
}
int32_t getDevTree(void *phandle, char tree_infos[1000])
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        string str = pthis->getDevTree();
        strcpy(tree_infos, str.c_str());
        return 0;
    }
    return -1;
}
int32_t setDevClockSource(void *phandle, char sourceStr[1000])
{
    stringstream ss;
    ss << "sourceStr v:[" << sourceStr << "]" << endl;
    MACROS_ERROR_CBK_CALL(ss.str().c_str());
    if (phandle)
    {

        Device_UHD *pthis = (Device_UHD *)phandle;
        pthis->setDevClockSource(sourceStr);
        return 0;
    }
    return -1;
}
int32_t getDevClockSource(void *phandle, char sourceStr[1000])
{
    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        string str = pthis->getDevClockSource();
        strcpy(sourceStr, str.c_str());
        return 0;
    }
    return -1;
}
int32_t setDevInClock(void *phandle, double clockFreq)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        pthis->setDevInClock(clockFreq);
        return 0;
    }
    return -1;
}
int32_t getDevInClockRange(void *phandle, double *min, double *max)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        pthis->getDevInClockRange();
        *min = pthis->getDevParamMin();
        *max = pthis->getDevParamMax();
        return 0;
    }
    return -1;
}
int32_t getDevInClock(void *phandle, double *val)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        *val = pthis->getDevInClock();
        return 0;
    }
    return -1;
}
int32_t getDevRXChCount(void *phandle, size_t *val)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        *val = pthis->getDevRXChCount();
        return 0;
    }
    return -1;
}
int32_t getDevTXChCount(void *phandle, size_t *val)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        *val = pthis->getDevTXChCount();
        return 0;
    }
    return -1;
}
int32_t setDevParam(void *phandle, char chStr[50], UHD_ParamType paramType, double paramValue)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        pthis->setDevParam(chStr, paramType, paramValue);
        return 0;
    }
    return -1;
}
int32_t getDevParam(void *phandle, char chStr[50], UHD_ParamType paramType, double *paramValue)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        *paramValue = pthis->getDevParam(chStr, paramType);
        return 0;
    }
    return -1;
}
int32_t getDevParamMin(void *phandle, double *val)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        *val = pthis->getDevParamMin();
        return 0;
    }
    return -1;
}
int32_t getDevParamMax(void *phandle, double *val)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        *val = pthis->getDevParamMax();
        return 0;
    }
    return -1;
}
int32_t setAllAntenna(void *phandle, int32_t *result)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        *result = pthis->setAllAntenna();
        return 0;
    }
    return -1;
}
int32_t setDevDDCParam_Any(void *phandle, char chStr[50], unsigned int jcqOffset, unsigned int jcqData)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        pthis->setDevDDCParam_Any(chStr, jcqOffset, jcqData);
        return 0;
    }
    return -1;
}
int32_t getDevDDCParam_Any(void *phandle, char chStr[50], unsigned int jcqOffset, unsigned int *jcqData)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        unsigned int t = 0;
        pthis->getDevDDCParam_Any(chStr, jcqOffset, t);
        *jcqData = t;
        return 0;
    }
    return -1;
}
int32_t setDevDataSwitch(void *phandle, char chStr[50], UHD_ParamType dataType, unsigned char ZDCh, int bSwitch)
{
    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        pthis->setDevDataSwitch(chStr, dataType, ZDCh, bSwitch);
        return 0;
    }
    return -1;
}
int32_t getDevDataSwitch(void *phandle, char chStr[50], UHD_ParamType dataType, unsigned char ZDCh, int *bSwitch)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        bool b = false;
        pthis->getDevDataSwitch(chStr, dataType, ZDCh, b);
        *bSwitch = b;
        return 0;
    }
    return -1;
}
int32_t setDevZDParam(void *phandle, char chStr[50], unsigned char ZDCh, long long centerfreq, int bw, int sample)
{

    if (phandle)
    {

        Device_UHD *pthis = (Device_UHD *)phandle;
        pthis->setDevZDParam(chStr, ZDCh, centerfreq, bw, sample);

        return 0;
    }
    return -1;
}
int32_t getDevZDParam(void *phandle, char chStr[50], unsigned char ZDCh, long long *centerfreq, int *bw, int *sample)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        long long c = 0;
        int b = 0;
        int s = 0;
        pthis->getDevZDParam(chStr, ZDCh, c, b, s);

        *centerfreq = c;
        *bw = b;
        *sample = s;
        return 0;
    }
    return -1;
}
int32_t getDevZDCenterRange(void *phandle, char chStr[50], long long &min, long long &max)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        pthis->getDevZDCenterRange(chStr, min, max);
        return 0;
    }
    return -1;
}
int32_t getDevZDBandWidthRange(void *phandle, char chStr[50], int &min, int &max)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        pthis->getDevZDBandWidthRange(chStr, min, max);
        return 0;
    }
    return -1;
}
int32_t getDevZDSampleFreqRange(void *phandle, char chStr[50], int arr[13], int *valid_len)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        vector<int> v = pthis->getDevZDSampleFreqRange(chStr);
        *valid_len = v.size();
        for (int i = 0; i < v.size(); ++i)
        {
            arr[i] = v[i];
        }
        return 0;
    }
    return -1;
}
int32_t setDevFFTParam(void *phandle, UHD_FFTWin fftWin, UHD_FFTLen fftLen, int fftPeriod_ms)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        pthis->setDevFFTParam(fftWin, fftLen, fftPeriod_ms);
        return 0;
    }
    return -1;
}
int32_t getDevFFTParam(void *phandle, UHD_FFTWin *fftWin, UHD_FFTLen *fftLen, int *fftPeriod_ms)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        UHD_FFTWin _fftWin;
        UHD_FFTLen _fftLen;
        int _fftPeriod_ms;
        pthis->getDevFFTParam(_fftWin, _fftLen, _fftPeriod_ms);
        *fftWin = _fftWin;
        *fftLen = _fftLen;
        *fftPeriod_ms = _fftPeriod_ms;
        return 0;
    }
    return -1;
}
int32_t getDevRecvSpeed(void *phandle, int channel, double *val)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        *val = pthis->getDevSendSpeed(channel);
        return 0;
    }
    return -1;
}
int32_t isDevRecving(void *phandle, int channel, int *result)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        *result = pthis->isDevRecving(channel);
        return 0;
    }
    return -1;
}

class A
{
  public:
    void callBackData_Func(int channel, void *pData, int iLength) { s_cbk(channel, pData, iLength); }
};
A a;
int32_t startDevRecv(void *phandle, int channel, rx_data_cbk_t rx_cbk)
{
    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;

        s_cbk = rx_cbk;

        pthis->callBackData = std::bind(&A::callBackData_Func, &a, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
        pthis->startDevRecv(channel);
        return 0;
    }
    return -1;
}
int32_t stopDevRecv(void *phandle, int channel)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        pthis->stopDevRecv(channel);
        return 0;
    }
    return -1;
}
int32_t getDevSendSpeed(void *phandle, int channel, double *val)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        *val = pthis->getDevSendSpeed(channel);
        return 0;
    }
    return -1;
}
int32_t isDevSending(void *phandle, int channel, int32_t *result)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        *result = (int32_t)pthis->isDevSending(channel);

        return 0;
    }
    return -1;
}
int32_t startDevSend(void *phandle, int channel, unsigned long long send_cf, unsigned long long data_sf, char *filename, int bwhile)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        pthis->startDevSend(channel, send_cf, data_sf, filename, bwhile);
        return 0;
    }
    return -1;
}
int32_t stopDevSend(void *phandle, int channel)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        pthis->stopDevSend(channel);
        return 0;
    }
    return -1;
}
int32_t getGPSInfo(void *phandle, char gps_info[50])
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        string str = pthis->getGPSInfo();

        strcpy(gps_info, str.c_str());
        return 0;
    }
    return -1;
}
int32_t setLedEnable(void *phandle, int led_num, int bEnable)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        pthis->setLedEnable(led_num, bEnable);
        return 0;
    }
    return -1;
}
int32_t getLedEnable(void *phandle, int led_num, int *bEnable)
{

    if (phandle)
    {
        Device_UHD *pthis = (Device_UHD *)phandle;
        bool b = false;
        pthis->getLedEnable(led_num, b);
        *bEnable = b;
        return 0;
    }
    return -1;
}

#include <mutex>
#include <thread>
typedef struct context_t
{
  public:
    void *pdev;
    adsb_msg_cbk_t adsb_cbk;
    thread *t_getgps;

    bool b_pool_over;
    void *adsb_pusr;
} context_t;
unsigned long long msgNo = 0;
void *phandle_math_3a_decode = nullptr;
int lastframindex_ch0_zdddc = 0;
int lastframindex_ch0_fft = 0;
int lastframindex_ch1_zdddc = 0;
int lastframindex_ch1_fft = 0;
iq_cbk_t iq_cbk;
void *iq_pusr;
extern volatile bool iio_context_find_err[2];

#include <math.h>
int BCDToDec(int bcd, int byt)
{
    if (1 == byt)
    {
        return bcd - (bcd >> 4) * 6;
    }
    else
    {
        int nDec = 0;
        for (int i = 0; i < byt; i++)
        {
            uint8_t ucBcd = (uint8_t)(bcd >> (8 * i));
            nDec += ((ucBcd - (ucBcd >> 4) * 6) * (int)std::pow(100, i));
        }
        return nDec;
    }
}

time_t get_2000_1_1_000_time_t()
{
    struct tm tt;
    tt.tm_year = 2000 - 1900;
    tt.tm_mon = 0;
    tt.tm_mday = 1;
    tt.tm_hour = 0;
    tt.tm_min = 0;
    tt.tm_sec = 0;
    return mktime(&tt);
}

int flag1 = 0;
int is_leap_year(int year)
{
    return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
void day_of_year_to_month_day(int year, int day_of_year, int *month, int *day)
{
    int days_per_month[] = {
        31, // 1 月 大
        28, // 2 月 平
        31, // 3 月 大
        30, // 4 月 小
        31, // 5 月 大
        30, // 6 月 小
        31, // 7 月 大
        31, // 8 月 大
        30, // 9 月 小
        31, // 10月 大
        30, // 11月 小
        31  // 12月 大
    };
    if (is_leap_year(year))
    {
        days_per_month[1] = 29;
    }
    *month = 1;
    *day = day_of_year;
    for (int i = 0; i < 12 && *day > days_per_month[i]; ++i)
    {
        *day -= days_per_month[i];
        (*month)++;
    }
}

// uint64_t rev_cbk_lenght_per_s = 0;
// time_t recv_time_t0 = time(0);

int last_type = 0;

time_t print_t1;
time_t print_t2;

string get_UHD_Enum_DataType(UHD_Enum_DataType v)
{
    string ttttttt;
    switch (v)
    {

    case zd_ddc: {
        ttttttt = "zd_ddc";
    }
    break;
    case kd_ddc: {
        ttttttt = "kd_ddc";
    }
    break;
    case kd_fft: {
        ttttttt = "kd_fft";
    }
    break;
    case GPS_Info: {
        ttttttt = "GPS_Info";
    }
    break;
    default:
        break;
    }
    return ttttttt;
}
void _rx_data_cbk_t(int channel, void *pdata, int length)
{

    if (iq_cbk != NULL && channel != 0)
    {
        iq_cbk(iq_pusr, pdata, length);
    }
    // if (phandle_math_3a_decode)
    // {
    //
    //     int nErr = SpecDecdInput(phandle_math_3a_decode, ((char *)pdata + 64), 2048, 0);
    //     int a = 0;
    // }

    UHD_Struct_KDDC *p = (UHD_Struct_KDDC *)pdata;
    if (last_type != (int)p->DataType)
    {
        last_type = (int)p->DataType;
    }

    // 丢帧打印t
    {

        int data_channel = p->Channel;

        if (data_channel == 0 && p->DataType == UHD_Enum_DataType::zd_ddc)
        {
            int cha = p->FrameIndex - lastframindex_ch0_zdddc;
            time_t tmp_t = time(0);
            if (p->FrameIndex != 0 && lastframindex_ch0_zdddc != 0 && cha != 1 && cha != -65535 && difftime(tmp_t, print_t1) > 5)
            {
                stringstream ss;
                ss << "loseframe!!!=> channel:[" << channel << "]\tcurrent_index:[" << p->FrameIndex << "]\tlast_index:[" << lastframindex_ch0_zdddc << "]" << endl;
                MACROS_ERROR_CBK_CALL(ss.str().c_str());
                print_t1 = tmp_t;
            }
            lastframindex_ch0_zdddc = p->FrameIndex;
        }
        // TODO:test else if (channel == 1 && p->DataType == UHD_Enum_DataType::zd_ddc)
        else if (data_channel == 1 && p->DataType == UHD_Enum_DataType::zd_ddc)
        {
            int cha = p->FrameIndex - lastframindex_ch1_zdddc;
            time_t tmp_t = time(0);
            if (p->FrameIndex != 0 && lastframindex_ch1_zdddc != 0 && cha != 1 && cha != -65535 && difftime(tmp_t, print_t2) > 5)
            {
                stringstream ss;
                ss << "loseframe!!!=> channel:[" << channel << "]\tcurrent_index:[" << p->FrameIndex << "]\tlast_index:[" << lastframindex_ch1_zdddc << "]" << endl;
                MACROS_ERROR_CBK_CALL(ss.str().c_str());
                print_t2 = tmp_t;
            }
            lastframindex_ch1_zdddc = p->FrameIndex;
        }
    }

    // 原始文件存储

    if (p->DataType == zd_ddc && channel == 0)
    {
        {
            lock_guard<std::mutex> lg(cfg_mutex);
            cfg.cache_over_byte += length;
            int mbyte = cfg.cache_over_byte / (1024 * 1024);

            if (cfg.is_save_yuanshi_iq && cfg.save_yuanshi_size_MByte > 0 && ofs_yuanshi_iq.is_open() && (mbyte < (cfg.save_yuanshi_size_MByte)))
            {
                ofs_yuanshi_iq.write((char *)pdata, length);
                return;
            }
            else if (cfg.save_yuanshi_size_MByte >= mbyte)
            {

                cfg.cache_over_byte = 0;
                cfg.is_save_yuanshi_iq = 0;
                cfg.need_new_file = true;
            }
        }

        struct_DataTime *dt = &p->DateTm;
        struct tm tt2;
        memset(&tt2, 0, sizeof(struct tm));
        uint64_t result_nsec = 0;

        switch (dt->TimeType)
        {
        case Enum_TimeType_Invlid: {
            result_nsec = 0;
        }
        break;
        case Enum_TimeType_IRIG_B: {
            int B_Year = BCDToDec(dt->TimeInfo.IRIGB_Head.Year, 1) + 2000;
            int B_Day = BCDToDec(dt->TimeInfo.IRIGB_Head.Day, 2);
            int B_Hour = BCDToDec(dt->TimeInfo.IRIGB_Head.Hour, 1);
            int B_Minute = BCDToDec(dt->TimeInfo.IRIGB_Head.Minute, 1);
            int B_Second = BCDToDec(dt->TimeInfo.IRIGB_Head.Second, 1);
            uint32_t B_NSec = dt->TimeInfo.IRIGB_Head.NanoSec;

            tm my_tm;
            int month;
            int day;
            day_of_year_to_month_day(B_Year, B_Day, &month, &day);

            tt2.tm_year = B_Year - 1900;
            tt2.tm_mon = month - 1;
            tt2.tm_mday = day;
            tt2.tm_hour = B_Hour;
            tt2.tm_min = B_Minute;
            tt2.tm_sec = B_Second;

            // stringstream ss;
            // ss << " y1=" << tt2.tm_year << "\n"
            //    << " M1=" << tt2.tm_mon << "\n"
            //    << " D1=" << tt2.tm_mday << "\n"
            //    << " H1=" << tt2.tm_hour << "\n"
            //    << " m1=" << tt2.tm_min << "\n"
            //    << " s1=" << tt2.tm_sec << "\n"
            //    << " nsec" << B_NSec << endl;
            // error_callback_call(ss.str().c_str());

            time_t t2 = mktime(&tt2);
            // t2+= dt->TimeInfo.RMC_Head.NanoSec;
            result_nsec = t2 * 1000000000 + B_NSec;
        }
        break;
        case Enum_TimeType_RMC: {

            // time_t t1 = get_2000_1_1_000_time_t();

            tt2.tm_year = dt->TimeInfo.RMC_Head.Year + 2000 - 1900;
            tt2.tm_mon = dt->TimeInfo.RMC_Head.Month - 1;
            tt2.tm_mday = dt->TimeInfo.RMC_Head.Day;
            tt2.tm_hour = dt->TimeInfo.RMC_Head.Hour;
            tt2.tm_min = dt->TimeInfo.RMC_Head.Minute;
            tt2.tm_sec = dt->TimeInfo.RMC_Head.Second;

            time_t t2 = mktime(&tt2);
            // t2+= dt->TimeInfo.RMC_Head.NanoSec;
            result_nsec = t2 * 1000000000 + dt->TimeInfo.RMC_Head.NanoSec + (8ull * 3600 * 1000000000ull);

            if (flag1 == 0)
            {
                // stringstream ss;
                // ss << "\n dt_type" << (int)dt->TimeType << "\n"
                // << " y1=" << tt2.tm_year<< "\n"
                // << " M1=" << tt2.tm_mon<< "\n"
                // << " D1=" << tt2.tm_mday<< "\n"
                // << " H1=" << tt2.tm_hour<< "\n"
                // << " m1=" << tt2.tm_min<< "\n"
                // << " s1=" << tt2.tm_sec << "\n"
                // << " nsec" << tt2.tm_sec << "\n"
                // << "result_nsec" << result_nsec << "\n"
                // << "this is for input" << endl;
                // error_callback_call(ss.str().c_str());
                flag1 = 1;
            }
        }
        break;
        case Enum_TimeType_ABSCNTTM: {
            uint64_t sec_n = ((uint64_t)dt->TimeInfo.ABSCNTTM_Head.Second) * 1000000000;
            result_nsec = dt->TimeInfo.ABSCNTTM_Head.NanoSec + sec_n;
        }
        break;
        case Enum_TimeType_REFCNTTM: {
            uint64_t sec_n = ((uint64_t)dt->TimeInfo.REFCNTTM_Head.Second) * 1000000000;
            result_nsec = dt->TimeInfo.REFCNTTM_Head.NanoSec + sec_n;
        }
        break;
        default:
            break;
        }

        if (result_nsec > 0 && phandle_math_3a_decode)
        {

            int nErr = SpecDecdInput(phandle_math_3a_decode, ((char *)pdata + 64), 2048, result_nsec);
            if (nErr != 0)
            {
                stringstream ss;
                ss << "t数据溢出" << endl;
                MACROS_ERROR_CBK_CALL(ss.str().c_str());
            }
        }
    }
}

int flag2 = 0;

// // // TODO:以下三行测试用，没有关闭操作，记得及时删除
// #include <fstream>
// fstream g_fsTst2("test_time.txt",ios::app);
// fstream g_fsTst1("test_for_server.txt",ios::app);
time_t mesc_to_time_t(int64_t mesc)
{
    auto sec = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::milliseconds(mesc));
    auto time_point = std::chrono::system_clock::time_point(sec);
    return std::chrono::system_clock::to_time_t(time_point);
}
void SpecDecdRetClbkFun(void *hdl, int taskId, MSpecDecdSigType sigType, char *data, int length)
{
    context_t *pthis = (context_t *)hdl;
    USpecDecdRet *pRet = (USpecDecdRet *)data;
    char cRet[1024] = {0};
    char cRet2[1024] = {0};
    switch (sigType)
    {
    case MSpecDecdSigType::ADSB: {
        time_t u64Time = pRet->ADSBRet.Time / 1000000000;
        // time_t l_tm_t = u64Time + 8 * 3600;
        time_t l_tm_t = u64Time; // 改为UTC时间基准

        tm TmTime = *(gmtime(&l_tm_t));
        TmTime.tm_year += 1900;
        TmTime.tm_mon += 1;
        TmTime.tm_hour;

        // // TODO:测试用
        // {
        //     unsigned long long ullSec = ((TmTime.tm_hour * 60) + TmTime.tm_min) * 60 + TmTime.tm_sec;
        //     unsigned long long ullNSec = pRet->ADSBRet.Time % 1000000000;
        //     unsigned long long ullTime = ((ullSec & 0x3FFFF)) << 30 | (ullNSec & 0x3FFFFFFF);
        //     char cTime[6] = {0};
        //     memcpy(cTime, &ullTime, 6);
        //     for (int i = 0, j = 5; i < j; i++, j--) //小端转大端
        //     {
        //         char cTemp = cTime[i];
        //         cTime[i] = cTime[j];
        //         cTime[j] = cTemp;
        //     }
        //     std::string strMsg = "";
        //     for (int i = 0; i < 6; i++)
        //     {
        //         char cByte[16] = {0};
        //         sprintf(cByte, " %02X", cTime[i] & 0xFF);
        //         strMsg += cByte;
        //     }
        //     //测试用
        //     char cMsg[256] = {0};
        //     sprintf(cMsg, "%s\n", strMsg.c_str());
        //     // g_fsTst2.write(cMsg, strlen(cMsg));
        //     // g_fsTst2.flush();
        // }

        if (flag2 == 0)
        {
            // stringstream ss;
            // ss << " y2=" << TmTime.tm_year << "\n"
            //    << " M2=" << TmTime.tm_mon << "\n"
            //    << " D2=" << TmTime.tm_mday << "\n"
            //    << " H2=" << TmTime.tm_hour << "\n"
            //    << " m2=" << TmTime.tm_min << "\n"
            //    << " s2=" << TmTime.tm_sec << "\n"
            //    << " SpecDecdRetClbkFun " << "\n"
            //    << " TmTime.tm_hour" << TmTime.tm_hour << " pRet->ADSBRet.Time" << pRet->ADSBRet.Time << " u64Time" << u64Time << std::endl;
            // error_callback_call(ss.str().c_str());
            flag2 = 1;
        }
        int nMsgLen = 0;
        for (int i = sizeof(pRet->ADSBRet.Msg) - 1; i >= 0; i--)
        {
            if (0 != pRet->ADSBRet.Msg[i])
            {
                nMsgLen = i + 1;
                break;
            }
        }
        if (nMsgLen >= 28)
        {
            nMsgLen = 28;
        }
        else if (nMsgLen >= 14)
        {
            nMsgLen = 14;
        }
        else
        {
            nMsgLen = 4;
        }
        // char cMsg[1024] = {0};
        // for (int i = 0; i < nMsgLen; i++)
        // {
        //     sprintf(&cMsg[i*2], "%02x", pRet->ADSBRet.Msg[i]);
        // }
        // sprintf(cRet, "#%03d 0x%06x %08s %02d Lon:%f Lat:%f Alt:%f %s, %04d-%02d-%02d %02d:%02d:%02d\r",
        //         ++msgNo, pRet->ADSBRet.ICAO, pRet->ADSBRet.FltNo, pRet->ADSBRet.Label, pRet->ADSBRet.Longitude, pRet->ADSBRet.Latitude, pRet->ADSBRet.Altitude, cMsg,
        //         TmTime.tm_year, TmTime.tm_mon, TmTime.tm_mday, TmTime.tm_hour, TmTime.tm_min, TmTime.tm_sec);
        // 按规定格式输出报文
        std::string strMsg = "1A";
        switch (nMsgLen / 2)
        {
        case 2:
            strMsg += " 31";
            break;
        case 7:
            strMsg += " 32";
            break;
        case 14:
            strMsg += " 33";
            break;
        default:
            break;
        }
        unsigned long long ullSec = ((TmTime.tm_hour * 60) + TmTime.tm_min) * 60 + TmTime.tm_sec;
        // if (ullSec > 86400) //86400 = 24*60*60
        // {
        //     return;
        // }
        unsigned long long ullNSec = pRet->ADSBRet.Time % 1000000000;
        unsigned long long ullTime = ((ullSec & 0x3FFFF) << 30) | (ullNSec & 0x3FFFFFFF);
        char cTime[6] = {0};
        memcpy(cTime, &ullTime, 6);
        for (int i = 0, j = 5; i < j; i++, j--) // 小端转大端
        {
            char cTemp = cTime[i];
            cTime[i] = cTime[j];
            cTime[j] = cTemp;
        }
        for (int i = 0; i < 6; i++)
        {
            if (26 == cTime[i])
            {
                strMsg += " 1A";
            }
            char cByte[16] = {0};
            sprintf(cByte, " %02X", cTime[i] & 0xFF);
            strMsg += cByte;
        }
        int nRSSI = (int)(pRet->ADSBRet.RSSI + 0.5);
        if (26 == (nRSSI & 0xFF))
        {
            strMsg += " 1A";
        }
        char cRSSI[16] = {0};
        sprintf(cRSSI, " %02X", nRSSI & 0xFF);
        strMsg += cRSSI;
        for (int i = 0; i < nMsgLen / 2; i++)
        {
            if ('1' == pRet->ADSBRet.Msg[2 * i] && ('a' == pRet->ADSBRet.Msg[2 * i + 1] || 'A' == pRet->ADSBRet.Msg[2 * i + 1]))
            {
                strMsg += " 1A";
            }
            char cByte[8] = {0};
            sprintf(cByte, " %C%C", toupper(pRet->ADSBRet.Msg[2 * i]), toupper(pRet->ADSBRet.Msg[2 * i + 1]));
            strMsg += cByte;
        }
        sprintf(cRet, "%s", strMsg.c_str());
    }
    break;
    default:
        break;
    }
    // if (strlen(cRet) > 0)
    // {
    //     // printf(cRet);
    //     // printf("\n");
    // }

    // //TODO:测试用
    // {
    //     char cMsg[256] = {0};
    //     sprintf(cMsg, "%s\r", cRet);
    //     g_fsTst1.write(cMsg, strlen(cMsg));
    //     g_fsTst1.flush();
    // }

    if (cfg.is_save_adsb && ofs_adsb.is_open())
    {
        ofs_adsb << cRet;
    }
    pthis->adsb_cbk(pthis->adsb_pusr, cRet, strlen(cRet));
}

int32_t ex_declare init_adsb9002(void **phandle, adsb_msg_cbk_t cbk, void *pusr)
{
    context_t *pthis = new context_t();
    pthis->adsb_cbk = cbk;
    pthis->adsb_pusr = pusr;
    phandle_math_3a_decode = 0;
    pthis->pdev = nullptr;
    init9002(&pthis->pdev);
    if (!pthis->pdev)
    {

        stringstream ss;
        ss << "pdev init error" << endl;
        MACROS_ERROR_CBK_CALL(ss.str().c_str());
        return -1;
    }
    uhd::device_addrs_t s;

    if (findDevices(pthis->pdev, &s) != 0)
    {

        stringstream ss;
        ss << "findDevices error!" << endl;
        MACROS_ERROR_CBK_CALL(ss.str().c_str());
        return -1;
    }
    else
    {
    }
    if (openDevice(pthis->pdev, s[0]) != 0)
    {

        stringstream ss;
        ss << "openDevice error!" << endl;
        MACROS_ERROR_CBK_CALL(ss.str().c_str());

        return -1;
    }
    else
    {
    }
    // 关闭开关
    setDevDataSwitch(pthis->pdev, "RX0", UHD_ParamType::ZDDCSwitch, 0, false);
    setDevDataSwitch(pthis->pdev, "RX0", UHD_ParamType::KFFTSwitch, 0, false);
    setDevDataSwitch(pthis->pdev, "RX0", UHD_ParamType::KDDCSwitch, 0, false);

    setDevDataSwitch(pthis->pdev, "RX1", UHD_ParamType::ZDDCSwitch, 8, false);
    setDevDataSwitch(pthis->pdev, "RX1", UHD_ParamType::KFFTSwitch, 8, false);
    setDevDataSwitch(pthis->pdev, "RX1", UHD_ParamType::KDDCSwitch, 8, false);
    // 启动接收线程
    if (startDevRecv(pthis->pdev, 0, _rx_data_cbk_t) != 0)
    {
        stringstream ss;
        ss << "startDevRecv 0 error!" << endl;
        MACROS_ERROR_CBK_CALL(ss.str().c_str());
        return -1;
    }
    else
    {
    }
    if (startDevRecv(pthis->pdev, 1, _rx_data_cbk_t) != 0)
    {
        stringstream ss;
        ss << "startDevRecv 1 error!" << endl;
        MACROS_ERROR_CBK_CALL(ss.str().c_str());
        return -1;
    }
    else
    {
    }
    // 设置默认参数
    setDevParam(pthis->pdev, "RX0", UHD_ParamType::CenterFreq, 1089000000);
    setDevParam(pthis->pdev, "RX0", UHD_ParamType::BandWidth, 6000000);
    setDevParam(pthis->pdev, "RX0", UHD_ParamType::SampleFreq, 24000000);
    setDevParam(pthis->pdev, "RX0", UHD_ParamType::Gain, cfg.rx_gain_val);

    setDevParam(pthis->pdev, "RX1", UHD_ParamType::CenterFreq, 15000000);
    setDevParam(pthis->pdev, "RX1", UHD_ParamType::BandWidth, 30000000);
    setDevParam(pthis->pdev, "RX1", UHD_ParamType::SampleFreq, 61440000);
    setDevParam(pthis->pdev, "RX1", UHD_ParamType::Gain, cfg.rx_gain_val);

    setDevZDParam(pthis->pdev, "RX0", 0, 1090000000, 3000000, 12000000);
    setDevClockSource(pthis->pdev, cfg.rx_clock_ref);
    setDevDataSwitch(pthis->pdev, "RX0", UHD_ParamType::ZDDCSwitch, 0, true);

    int nFs = 12000000;
    SpecDecdInit(&phandle_math_3a_decode, 0, MSpecDecdSigType::ADSB, MSpecDecdDaType::ShortC, nFs, 1, SpecDecdRetClbkFun, pthis);

    pthis->b_pool_over = false;
    pthis->t_getgps = new thread(
        [=](context_t *ppthis) {
            time_t t1 = time(0);
            int print_times = 0;
            while (ppthis->b_pool_over == false)
            {
                time_t t2 = time(0);
                if (difftime(t2, t1) > 2)
                {
                    t1 = t2;
                    char gpsinfo[50];
                    memset(gpsinfo, 0, 50);

                    getGPSInfo(ppthis->pdev, gpsinfo);
                    string gpsinfostr = gpsinfo;
                    if (gpsinfostr.size() <= 0)
                    {
                        continue;
                    }

                    int mposi = gpsinfostr.find('M');

                    if (mposi != std::string::npos || mposi < 10)
                    {

                        string sub;
                        double h = stod(gpsinfostr.substr(0, mposi));
                        char zl = gpsinfostr.substr(mposi + 1, 1).at(0);
                        if (zl != '1')
                        {
                            continue;
                        }
                        char ew = gpsinfostr.substr(mposi + 2, 1).at(0);
                        int lon_du = stoi(gpsinfostr.substr(mposi + 3, 3));
                        int lon_fen_zhengshu = stoi(gpsinfostr.substr(mposi + 6, 2));
                        int lon_fen_xiaoshu = stoi(gpsinfostr.substr(mposi + 8, 4));

                        char ns = gpsinfostr.substr(mposi + 12, 1).at(0);
                        int lat_du = stoi(gpsinfostr.substr(mposi + 13, 2));
                        int lat_fen_zhengshu = stoi(gpsinfostr.substr(mposi + 15, 2));
                        int lat_fen_xiaoshu = stoi(gpsinfostr.substr(mposi + 17, 4));

                        double lon_fen = lon_fen_zhengshu + lon_fen_xiaoshu / 10000.0;
                        double longitude = lon_du + lon_fen / 60.0;

                        // 根据东西经度调整符号
                        if (ew == 'W')
                        {
                            longitude = -longitude;
                        }

                        // 计算纬度
                        // 将分数的小数部分转换为小数形式（假设小数部分是4位数字）
                        double lat_fen = lat_fen_zhengshu + lat_fen_xiaoshu / 10000.0;
                        double latitude = lat_du + lat_fen / 60.0;

                        // 根据南北纬度调整符号
                        if (ns == 'S')
                        {
                            latitude = -latitude;
                        }

                        if (print_times < 3)
                        {
                            print_times++;
                            stringstream ss;
                            ss << "经度:[" << longitude << "°]\t纬度:[" << latitude << "°]\t\t海拔:[" << h << "m]" << endl;
                            MACROS_ERROR_CBK_CALL(ss.str().c_str());
                        }

                        HULC_Status_Message message;

                        message.set_latitude(latitude);
                        message.set_longitude(longitude);
                        message.Alt = (int16_t)h;

                        auto lat = message.get_latitude();
                        auto lon = message.get_longitude();
                        auto alt = message.Alt;

                        auto bin = mem2hex(packet_to_escape_format(message.toBinary()));

                        char *c = (char *)bin.c_str();
                        int len = bin.size();

                        if (cfg.is_trans_gps == 1)
                        {
                            pthis->adsb_cbk(pthis->adsb_pusr, c, len);
                        }
                        if (cfg.is_save_gps && ofs_gps.is_open())
                        {
                            ofs_gps << "经度:" << longitude << "°" << "\t纬度: " << latitude << "°" << "\t海拔: " << h << "m" << "\tbin_str:" << bin.c_str() << endl;
                        }
                    }
                }
                usleep(500000);
            }
        },
        pthis);
    int a = 1;
    *phandle = pthis;
    if (iio_context_find_err[0] || iio_context_find_err[1])
    {

        stringstream ss;
        ss << "9002 init failed!" << endl;
        MACROS_ERROR_CBK_CALL(ss.str().c_str());
        return -1;
    }
    return 0;
}

int32_t ex_declare free_adsb9002(void **phandle)
{
    context_t *pthis = (context_t *)*phandle;
    if (pthis->pdev)
    {
        int32_t result = 0;
        isDevOpened(pthis->pdev, &result);
        if (result > 0)
        {
            setDevDataSwitch(pthis->pdev, "RX0", UHD_ParamType::ZDDCSwitch, 0, 0);
            setDevDataSwitch(pthis->pdev, "RX0", UHD_ParamType::KFFTSwitch, 0, 0);
            setDevDataSwitch(pthis->pdev, "RX0", UHD_ParamType::KDDCSwitch, 0, 0);
            setDevDataSwitch(pthis->pdev, "RX1", UHD_ParamType::ZDDCSwitch, 8, 0);
            setDevDataSwitch(pthis->pdev, "RX1", UHD_ParamType::KFFTSwitch, 8, 0);
            setDevDataSwitch(pthis->pdev, "RX1", UHD_ParamType::KDDCSwitch, 8, 0);
            if (stopDevRecv(pthis->pdev, 0) != 0)
            {

                stringstream ss;
                ss << "stopDevRecv 0 error!" << endl;
                MACROS_ERROR_CBK_CALL(ss.str().c_str());
            }
            else
            {
            }
            if (stopDevRecv(pthis->pdev, 1) != 0)
            {

                stringstream ss;
                ss << "stopDevRecv 1 error!" << endl;
                MACROS_ERROR_CBK_CALL(ss.str().c_str());
            }
            else
            {
            }
            closeDevice(pthis->pdev);
            if (pthis->t_getgps->joinable())
            {
                pthis->b_pool_over = true;
                pthis->t_getgps->join();
            }
            pthis->t_getgps = nullptr;
        }
        free9002(&pthis->pdev);
    }
    pthis->pdev = nullptr;
    SpecDecdFree(&phandle_math_3a_decode);
    if (ofs_adsb.is_open())
    {
        ofs_adsb.close();
    }
    if (ofs_gps.is_open())
    {
        ofs_gps.close();
    }
    if (ofs_yuanshi_iq.is_open())
    {
        ofs_yuanshi_iq.close();
    }
    return 0;
}

int ex_declare set_iq_cbk(void *phandle, iq_cbk_t recv_cbk, void *pusr)
{
    if (phandle)
    {
        context_t *pthis = (context_t *)phandle;
        iq_cbk = recv_cbk;
        iq_pusr = pusr;
        return 0;
    }
    return -1;
}

int ex_declare set_less_30Mhz_ddc_param(void *phandle, uint64_t cf_hz, uint64_t sf_hz, uint64_t bw_hz, int8_t sw)
{
    if (phandle)
    {
        context_t *pthis = (context_t *)phandle;
        // setDevDataSwitch(pthis->pdev, "RX1", UHD_ParamType::ZDDCSwitch, 0, false);
        setDevDataSwitch(pthis->pdev, "RX1", UHD_ParamType::ZDDCSwitch, 8, false);
        setDevZDParam(pthis->pdev, "RX1", 8, cf_hz, bw_hz, sf_hz);
        setDevDataSwitch(pthis->pdev, "RX1", UHD_ParamType::ZDDCSwitch, 8, true);
        return 0;
    }
    return -1;
}

int ex_declare set_less_30Mhz_fft_param(void *phandle, int fftWin, int fftLen, int fftPeriod_ms, int8_t sw)
{
    if (phandle)
    {
        context_t *pthis = (context_t *)phandle;
        setDevDataSwitch(pthis->pdev, "RX1", UHD_ParamType::KFFTSwitch, 8, false);
        setDevFFTParam(pthis->pdev, (UHD_FFTWin)fftWin, (UHD_FFTLen)fftLen, fftPeriod_ms);
        setDevDataSwitch(pthis->pdev, "RX1", UHD_ParamType::KFFTSwitch, 8, true);

        return 0;
    }
    return -1;
}

#pragma region 王永琛代码
struct Global_Read_Buffer
{
    Global_Read_Buffer();
    ~Global_Read_Buffer();
    std::string read()
    {
        std::lock_guard g(mtx);
        std::string ret;
        std::swap(ret, buffer);
        return ret;
    }
    void append(std::string buf)
    {
        std::lock_guard g(mtx);
        buffer.append(buf);
    }

    void *phandle{};
    std::mutex mtx;
    std::string buffer;
};

#include "error_callback.h"
void my_error_cbk_t(const char *err_msg)
{
    cout << err_msg << endl;
}

Global_Read_Buffer t;

void adsb2(void *pusr, char *pmsg, int msglen)
{
    t.append(std::string(pmsg, msglen));
}
void _iq_cbk_t(void *phandle, void *pdata, uint64_t length)
{
    //   cout << "FUNC:[dev_uhd_c::" << __func__ << "]\tcbk called!!!!!!!" << endl;
}
Global_Read_Buffer::Global_Read_Buffer()
{
    init_adsb9002(&phandle, adsb2, nullptr);
    set_iq_cbk(phandle, _iq_cbk_t, nullptr);
}

Global_Read_Buffer::~Global_Read_Buffer()
{
    free_adsb9002(&phandle);
}

std::string adsb_read()
{
    // return t.read();
    return t.read();
}

#include <cstring>
void adsb_read(char *buf, std::uint16_t *len)
{
    auto s = t.read();
    *len = s.size();
    std::memcpy(buf, s.c_str(), *len);
}

int adsb_set_iq_cbk(iq_cbk_t recv_cbk, void *pusr)
{
    stringstream ss;
    ss << "adsb_set_iq_cbk " << pusr << "  " << recv_cbk << " " << std::endl;
    MACROS_ERROR_CBK_CALL(ss.str().c_str());
    return set_iq_cbk(t.phandle, recv_cbk, pusr);
}

int adsb_set_less_30Mhz_ddc_param(uint64_t cf_hz, uint64_t sf_hz, uint64_t bw_hz, int8_t sw)
{

    stringstream ss;
    ss << "adsb_set_less_30Mhz_ddc_param " << cf_hz << "  " << sf_hz << " " << bw_hz << " " << sw << " " << std::endl;
    MACROS_ERROR_CBK_CALL(ss.str().c_str());
    return set_less_30Mhz_ddc_param(t.phandle, cf_hz, sf_hz, bw_hz, sw);
}

int adsb_set_less_30Mhz_fft_param(uint64_t fftWin, uint64_t fftLen, int fftPeriod_ms, int8_t sw)
{
    stringstream ss;
    ss << "adsb_set_less_30Mhz_fft_param " << fftWin << "  " << fftLen << " " << fftPeriod_ms << " " << sw << std::endl;
    MACROS_ERROR_CBK_CALL(ss.str().c_str());
    return set_less_30Mhz_fft_param(t.phandle, fftWin, fftLen, fftPeriod_ms, sw);
}

#pragma endregion