#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <vector>
#include "htra_api.h"
#include <fstream>
#include"msgpack.h"
#include <time.h>
#include <iostream>
#include <filesystem>
using namespace std;

#define IS_USB 1 // By default, a USB device is used; if using a network port device, define IS_USB as 0.

// uint_16 little-endian to big-endian conversion
uint16_t littleToBigEndian16(uint16_t value) {
	return (value >> 8) | (value << 8);
}
// uint_32 little-endian to big-endian conversion
uint32_t littleToBigEndian32(uint32_t value) {
	uint32_t result = ((value >> 24) & 0xFF) | ((value >> 8) & 0xFF00) | ((value << 8) & 0xFF0000) | ((value << 24) & 0xFF000000);
	return result;
}
// uint_64 little-endian to big-endian conversion
uint64_t littleToBigEndian64(uint64_t val)
{
	return ((val) & ((uint64_t)0x00000000000000ffULL << 56) |

		(((uint64_t)(val) & (uint64_t)0x000000000000ff00ULL) << 40) |

		(((uint64_t)(val) & (uint64_t)0x0000000000ff0000ULL) << 24) |

		(((uint64_t)(val) & (uint64_t)0x00000000ff000000ULL) << 8) |

		(((uint64_t)(val) & (uint64_t)0x000000ff00000000ULL) >> 8) |

		(((uint64_t)(val) & (uint64_t)0x0000ff0000000000ULL) >> 24) |

		(((uint64_t)(val) & (uint64_t)0x00ff000000000000ULL) >> 40) |

		(((uint64_t)(val) & (uint64_t)0xff00000000000000ULL) >> 56));
}
// float little-endian to big-endian conversion
float littleToBigEndianFloat(float value) {
	union {
		float floatValue;
		uint32_t intValue;
	} u;

	u.floatValue = value;
	u.intValue = littleToBigEndian32(u.intValue);
	return u.floatValue;
}
// double little-endian to big-endian conversion
double littleToBigEndianDouble(double value) {
	union {
		double doubleValue;
		uint64_t longValue;
	} u;

	u.doubleValue = value;
	u.longValue = ((uint64_t)littleToBigEndian32((uint32_t)(u.longValue & 0xFFFFFFFF)) << 32) | littleToBigEndian32((uint32_t)(u.longValue >> 32));
	return u.doubleValue;
}

// Compress SWP_Profile_TypeDef and SWP_TraceInfo_TypeDef using msgpack
msgpack_sbuffer pack(const SWP_Profile_TypeDef* SWP_ProfileOut, const SWP_Profile_TypeDef* SWP_ProfileIn, const SWP_TraceInfo_TypeDef* TraceInfo)
{
	msgpack_sbuffer sbuf; // msgpack_sbuffer is a structure in the MessagePack library used to dynamically store serialization results.

	msgpack_sbuffer_init(&sbuf); // Initialize the msgpack_sbuffer buffer so that it can store serialized data.

	msgpack_packer pck; // msgpack_packer is a packer provided by the MessagePack library, used to convert C++ data structures into MessagePack formatted byte streams.

	msgpack_packer_init(&pck, &sbuf, msgpack_sbuffer_write); // Initialize the msgpack_packer object, associating pck with sbuf to ensure serialized data is written into sbuf.

	// Pack the SWP_Profile_TypeDef and SWP_TraceInfo_TypeDef structures.
	msgpack_pack_double(&pck, SWP_ProfileOut->StartFreq_Hz);
	msgpack_pack_double(&pck, SWP_ProfileOut->StopFreq_Hz);
	msgpack_pack_double(&pck, SWP_ProfileOut->CenterFreq_Hz);
	msgpack_pack_double(&pck, SWP_ProfileOut->Span_Hz);
	msgpack_pack_double(&pck, SWP_ProfileOut->RefLevel_dBm);
	msgpack_pack_double(&pck, SWP_ProfileOut->RBW_Hz);
	msgpack_pack_double(&pck, SWP_ProfileOut->VBW_Hz);
	msgpack_pack_double(&pck, SWP_ProfileOut->SweepTime);
	msgpack_pack_double(&pck, SWP_ProfileOut->TraceBinSize_Hz);

	msgpack_pack_int(&pck, SWP_ProfileOut->FreqAssignment);
	msgpack_pack_int(&pck, SWP_ProfileOut->Window);
	msgpack_pack_int(&pck, SWP_ProfileOut->RBWMode);
	msgpack_pack_int(&pck, SWP_ProfileOut->VBWMode);
	msgpack_pack_int(&pck, SWP_ProfileOut->SweepTimeMode);
	msgpack_pack_int(&pck, SWP_ProfileOut->Detector);
	msgpack_pack_int(&pck, SWP_ProfileOut->TraceFormat);
	msgpack_pack_int(&pck, SWP_ProfileOut->TraceDetectMode);
	msgpack_pack_int(&pck, SWP_ProfileOut->TraceDetector);

	msgpack_pack_uint32(&pck, SWP_ProfileOut->TracePoints);
	msgpack_pack_int(&pck, SWP_ProfileOut->TracePointsStrategy);
	msgpack_pack_int(&pck, SWP_ProfileOut->TraceAlign);
	msgpack_pack_int(&pck, SWP_ProfileOut->FFTExecutionStrategy);
	msgpack_pack_int(&pck, SWP_ProfileOut->RxPort);
	msgpack_pack_int(&pck, SWP_ProfileOut->SpurRejection);
	msgpack_pack_int(&pck, SWP_ProfileOut->ReferenceClockSource);
	msgpack_pack_double(&pck, SWP_ProfileOut->ReferenceClockFrequency);

	msgpack_pack_uint8(&pck, SWP_ProfileOut->EnableReferenceClockOut);
	msgpack_pack_int(&pck, SWP_ProfileOut->SystemClockSource);
	msgpack_pack_double(&pck, SWP_ProfileOut->ExternalSystemClockFrequency);
	msgpack_pack_int(&pck, SWP_ProfileOut->TriggerSource);
	msgpack_pack_int(&pck, SWP_ProfileOut->TriggerEdge);
	msgpack_pack_int(&pck, SWP_ProfileOut->TriggerOutMode);
	msgpack_pack_int(&pck, SWP_ProfileOut->TriggerOutPulsePolarity);
	msgpack_pack_uint32(&pck, SWP_ProfileOut->PowerBalance);
	msgpack_pack_int(&pck, SWP_ProfileOut->GainStrategy);
	msgpack_pack_int(&pck, SWP_ProfileOut->Preamplifier);

	msgpack_pack_uint8(&pck, SWP_ProfileOut->AnalogIFBWGrade);
	msgpack_pack_uint8(&pck, SWP_ProfileOut->IFGainGrade);
	msgpack_pack_uint8(&pck, SWP_ProfileOut->EnableDebugMode);
	msgpack_pack_uint8(&pck, SWP_ProfileOut->CalibrationSettings);

	msgpack_pack_int8(&pck, SWP_ProfileOut->Atten);
	msgpack_pack_int(&pck, SWP_ProfileOut->TraceType);
	msgpack_pack_int(&pck, SWP_ProfileOut->LOOptimization);

	// Pack the SWP_ProfileIn structure data.
	msgpack_pack_double(&pck, SWP_ProfileIn->StartFreq_Hz);
	msgpack_pack_double(&pck, SWP_ProfileIn->StopFreq_Hz);
	msgpack_pack_double(&pck, SWP_ProfileIn->CenterFreq_Hz);
	msgpack_pack_double(&pck, SWP_ProfileIn->Span_Hz);
	msgpack_pack_double(&pck, SWP_ProfileIn->RefLevel_dBm);
	msgpack_pack_double(&pck, SWP_ProfileIn->RBW_Hz);
	msgpack_pack_double(&pck, SWP_ProfileIn->VBW_Hz);
	msgpack_pack_double(&pck, SWP_ProfileIn->SweepTime);
	msgpack_pack_double(&pck, SWP_ProfileIn->TraceBinSize_Hz);

	msgpack_pack_int(&pck, SWP_ProfileIn->FreqAssignment);
	msgpack_pack_int(&pck, SWP_ProfileIn->Window);
	msgpack_pack_int(&pck, SWP_ProfileIn->RBWMode);
	msgpack_pack_int(&pck, SWP_ProfileIn->VBWMode);
	msgpack_pack_int(&pck, SWP_ProfileIn->SweepTimeMode);
	msgpack_pack_int(&pck, SWP_ProfileIn->Detector);
	msgpack_pack_int(&pck, SWP_ProfileIn->TraceFormat);
	msgpack_pack_int(&pck, SWP_ProfileIn->TraceDetectMode);
	msgpack_pack_int(&pck, SWP_ProfileIn->TraceDetector);

	msgpack_pack_uint32(&pck, SWP_ProfileIn->TracePoints);
	msgpack_pack_int(&pck, SWP_ProfileIn->TracePointsStrategy);
	msgpack_pack_int(&pck, SWP_ProfileIn->TraceAlign);
	msgpack_pack_int(&pck, SWP_ProfileIn->FFTExecutionStrategy);
	msgpack_pack_int(&pck, SWP_ProfileIn->RxPort);
	msgpack_pack_int(&pck, SWP_ProfileIn->SpurRejection);
	msgpack_pack_int(&pck, SWP_ProfileIn->ReferenceClockSource);

	msgpack_pack_double(&pck, SWP_ProfileIn->ReferenceClockFrequency);

	msgpack_pack_uint8(&pck, SWP_ProfileIn->EnableReferenceClockOut);
	msgpack_pack_int(&pck, SWP_ProfileIn->SystemClockSource);
	msgpack_pack_double(&pck, SWP_ProfileIn->ExternalSystemClockFrequency);
	msgpack_pack_int(&pck, SWP_ProfileIn->TriggerSource);
	msgpack_pack_int(&pck, SWP_ProfileIn->TriggerEdge);
	msgpack_pack_int(&pck, SWP_ProfileIn->TriggerOutMode);
	msgpack_pack_int(&pck, SWP_ProfileIn->TriggerOutPulsePolarity);
	msgpack_pack_uint32(&pck, SWP_ProfileIn->PowerBalance);
	msgpack_pack_int(&pck, SWP_ProfileIn->GainStrategy);
	msgpack_pack_int(&pck, SWP_ProfileIn->Preamplifier);

	msgpack_pack_uint8(&pck, SWP_ProfileIn->AnalogIFBWGrade);
	msgpack_pack_uint8(&pck, SWP_ProfileIn->IFGainGrade);
	msgpack_pack_uint8(&pck, SWP_ProfileIn->EnableDebugMode);
	msgpack_pack_uint8(&pck, SWP_ProfileIn->CalibrationSettings);

	msgpack_pack_int8(&pck, SWP_ProfileIn->Atten);
	msgpack_pack_int(&pck, SWP_ProfileIn->TraceType);
	msgpack_pack_int(&pck, SWP_ProfileIn->LOOptimization);

	//Pack the TraceInfo structure data.
	msgpack_pack_int(&pck, TraceInfo->FullsweepTracePoints);
	msgpack_pack_int(&pck, TraceInfo->PartialsweepTracePoints);
	msgpack_pack_int(&pck, TraceInfo->TotalHops);
	msgpack_pack_uint32(&pck, TraceInfo->UserStartIndex);
	msgpack_pack_uint32(&pck, TraceInfo->UserStopIndex);

	msgpack_pack_double(&pck, TraceInfo->TraceBinBW_Hz);
	msgpack_pack_double(&pck, TraceInfo->StartFreq_Hz);
	msgpack_pack_double(&pck, TraceInfo->AnalysisBW_Hz);
	msgpack_pack_int(&pck, TraceInfo->TraceDetectRatio);
	msgpack_pack_int(&pck, TraceInfo->DecimateFactor);
	msgpack_pack_float(&pck, TraceInfo->FrameTimeMultiple);

	msgpack_pack_double(&pck, TraceInfo->FrameTime);
	msgpack_pack_double(&pck, TraceInfo->EstimateMinSweepTime);

	msgpack_pack_int(&pck, TraceInfo->DataFormat);
	msgpack_pack_uint64(&pck, TraceInfo->SamplePoints);
	msgpack_pack_uint32(&pck, TraceInfo->GainParameter);
	msgpack_pack_int(&pck, TraceInfo->DSPPlatform);

	return sbuf;
}

// Record SWP mode data.
int Write_SWPData_Info(const BootInfo_TypeDef* BootInfo, const SWP_Profile_TypeDef* SWP_ProfileIn, const SWP_Profile_TypeDef* SWP_ProfileOut, const SWP_TraceInfo_TypeDef* TraceInfo,
	const double Frequency[], const float PowerSpec_dBm[], const int HopIndex, const int FrameIndex, const MeasAuxInfo_TypeDef* MeasAuxInfo)
{
	static vector<uint32_t> document_count(1, 0); // Record the number of files, create a new file when the size exceeds 4GB.
	static vector<uint32_t> bagcount(1, 0);       // Record the number of data packets.

	bagcount[0]++; // Increase the current number of data packets.

	uint16_t InfoSize_2 = 0; // Temporarily store two bytes of data.
	uint32_t InfoSize_4 = 0; // Temporarily store four bytes of data.
	uint64_t InfoSize_8 = 0; // Temporarily store eight bytes of data.

	SWP_TraceInfo_TypeDef TraceInfo_temp = *TraceInfo;   // Store the data of the SWP_TraceInfo_TypeDef structure.
	MeasAuxInfo_TypeDef MeasAuxInfo_temp = *MeasAuxInfo; // Store the data of the MeasAuxInfo_TypeDef structure.

	static uint32_t Data_length = 0;  // File length, record the current file size.
	static char FileName[39] = { 0 }; // Used to store the file name, size is 39 characters.
	string s = "./data/";             // Assume the file save path is ./data/.

	// Check if the directory exists, create it if it does not exist.
	if (!(filesystem::exists(s))) {
		// Create the directory and its parent directories.
		filesystem::create_directories(s);
		cout << "dataFolder address :Htra_RecordingandPlayBack\\data" << endl;
		if (filesystem::create_directories(s)) {
			cout << "Failed to create a directory: \"" << s << "\" " << endl;
			return 0;
		}
	}

	char FilePath_1[50];                                             // Used to store the file path, size is 50 characters.
	static uint16_t Length_1 = 0;                                    // The length of the structure after compression.
	auto msgBuffer = pack(SWP_ProfileOut, SWP_ProfileIn, TraceInfo); // Call the pack function to pack the data.
	Length_1 = msgBuffer.size;                                       // Get the size of the compressed data.

	uint64_t BagCount = 0; // Used to calculate whether the file size exceeds 4GB.

	BagCount = 4294967296 - 10485834 - Length_1 / (56 + 12 * TraceInfo_temp.PartialsweepTracePoints); // Calculate approximately how many data packets the current file can contain.

	// Determine whether the file size is close to 4GB, if so, split into another file.
	if (bagcount[0] % BagCount == 1) // When the file header plus data is about 4GB, split the file.
	{
		document_count[0]++; // Increase the file count.

		// Get the current system time.
		time_t timep;
		struct tm* p;
		time(&timep);       // Get the current time.
		p = gmtime(&timep); // Convert the time to Greenwich Mean Time.


		char hex[4] = { 0 }; // Used to store the last four digits of UID in hexadecimal.

		// Calculate and extract the last four digits of the UID in hexadecimal.
		hex[0] = BootInfo->DeviceInfo.DeviceUID % 16;                  // Take the lowest 4 bits of UID.
		hex[1] = (BootInfo->DeviceInfo.DeviceUID / 16) % 16;           // Take bits 5-8 of UID.
		hex[2] = (BootInfo->DeviceInfo.DeviceUID / 16 / 16) % 16;      // Take bits 9-12 of UID.
		hex[3] = (BootInfo->DeviceInfo.DeviceUID / 16 / 16 / 16) % 16; // Take bits 13-16 of UID.

		sprintf(FileName, "%X%X%X%X_%d%02d%d_%02d%02d%02d.part%d.spectrum", hex[3], hex[2], hex[1], hex[0], 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, 8 + p->tm_hour, p->tm_min, p->tm_sec, document_count[0]); // Format the file name using the last four digits of the device UID, current date and time, and file segment number.

		s += FileName;                   // Add the generated file name to the path.
		strcpy_s(FilePath_1, s.c_str()); // Copy the file path to FilePath_1.

		// Open the record file.
		fstream File;
		File.open(FilePath_1, ios::out | ios::binary);

		// Check if the file is opened successfully.
		if (!File.is_open()) {
			std::cerr << "Unable to open file: " << FilePath_1 << std::endl;
		}
		else {
			std::cout << "The file opened successfully: " << FilePath_1 << std::endl;
		}

		// Start writing the record file.
		InfoSize_2 = littleToBigEndian16(document_count[0]);
		File.write((char*)&InfoSize_2, 2); // File number.

		uint8_t digit_1 = 0x8c;
		File.write((char*)&digit_1, 1); // 0x8c.

		uint8_t digit_2 = 0x22;
		File.write((char*)&digit_2, 1); // 0x22.

		uint8_t digit_3 = 0x52;
		File.write((char*)&digit_3, 1); // 0x52.

		uint8_t digit_4 = 0x9b;
		File.write((char*)&digit_4, 1); // 0x9b.

		uint8_t digit_5 = 0x00;
		File.write((char*)&digit_5, 1); // 0x00 protocol version.

		uint8_t digit_6 = 0x01;
		File.write((char*)&digit_6, 1); // 0x01 protocol version.

		uint32_t digit_7 = littleToBigEndian32(BootInfo->APIVersion);
		File.write((char*)&digit_7, 4); // API version information.

		char c = 'X'; // Fill the reserved file space, 52 bytes.
		for (int i = 0; i < 52; i++)
		{
			File.write(&c, 1);
		}

		InfoSize_8 = bagcount[0];                     // Store the number of data packets in the current file into InfoSize_8.
		InfoSize_8 = littleToBigEndian64(InfoSize_8); // Convert InfoSize_8 from little-endian to big-endian.
		File.write((char*)&InfoSize_8, 8);            // Write the converted (number of data packets, 8 bytes) into the file.

		for (int j = 0; j < 10 * 1024 * 1024; j++) // Packet index, just padding, not accurate value.
		{
			File.write(&c, 1);
		}
		
		uint16_t Profile_Stream = littleToBigEndian16(msgBuffer.size); // Convert msgBuffer.size from little-endian to big-endian and store in Profile_Stream.
		File.write((char*)&Profile_Stream, 2);                         // Write the length of configuration + default configuration + trace information into the file.
		
		for (int i = 0; i < msgBuffer.size; i++) // Write the compressed data byte by byte into the file.
		{
			File.write(&msgBuffer.data[i], 1);
		}

		Data_length = (8 + 4) * TraceInfo_temp.PartialsweepTracePoints + 52; // Data_length includes the number of bytes of the data packet.
		uint32_t Datalength1 = littleToBigEndian32(Data_length);             // Convert Datalength1 from little-endian to big-endian and store in Datalength1.
		File.write((char*)&Datalength1, 4);                                  // Write the converted data packet length (4 bytes) into the file.

		// Write frequency data
		for (int i = 0; i < TraceInfo_temp.PartialsweepTracePoints; i++) {
			File.write((char*)&Frequency[i], 8);
		}

		// Write power data
		for (int i = 0; i < TraceInfo_temp.PartialsweepTracePoints; i++) {
			File.write((char*)&PowerSpec_dBm[i], 4);
		}
		
		InfoSize_4 = littleToBigEndian32(HopIndex); // Convert HopIndex from little-endian to big-endian and write into the file.
		File.write((char*)&InfoSize_4, 4);          // Write 4 bytes of data.


		InfoSize_4 = littleToBigEndian32(FrameIndex); // Convert FrameIndex from little-endian to big-endian and write into the file.
		File.write((char*)&InfoSize_4, 4);            // Write 4 bytes of data.


		MeasAuxInfo_temp.MaxIndex = littleToBigEndian32(MeasAuxInfo_temp.MaxIndex); // Convert MeasAuxInfo_temp.MaxIndex from little-endian to big-endian format and write to file.
		File.write((char*)&MeasAuxInfo_temp.MaxIndex, 4);                           // Write 4 bytes of data.

		MeasAuxInfo_temp.MaxPower_dBm = littleToBigEndianFloat(MeasAuxInfo_temp.MaxPower_dBm);
		File.write((char*)&MeasAuxInfo_temp.MaxPower_dBm, 4);

		MeasAuxInfo_temp.Temperature = littleToBigEndian16(MeasAuxInfo_temp.Temperature);
		File.write((char*)&MeasAuxInfo_temp.Temperature, 2);

		MeasAuxInfo_temp.RFState = littleToBigEndian16(MeasAuxInfo_temp.RFState);
		File.write((char*)&MeasAuxInfo_temp.RFState, 2);

		MeasAuxInfo_temp.BBState = littleToBigEndian16(MeasAuxInfo_temp.BBState);
		File.write((char*)&MeasAuxInfo_temp.BBState, 2);

		MeasAuxInfo_temp.GainPattern = littleToBigEndian16(MeasAuxInfo_temp.GainPattern);
		File.write((char*)&MeasAuxInfo_temp.GainPattern, 2);

		MeasAuxInfo_temp.ConvertPattern = littleToBigEndian32(MeasAuxInfo_temp.ConvertPattern);
		File.write((char*)&MeasAuxInfo_temp.ConvertPattern, 4);

		MeasAuxInfo_temp.SysTimeStamp = littleToBigEndianDouble(MeasAuxInfo_temp.SysTimeStamp);
		File.write((char*)&MeasAuxInfo_temp.SysTimeStamp, 8);

		MeasAuxInfo_temp.AbsoluteTimeStamp = littleToBigEndianDouble(MeasAuxInfo_temp.AbsoluteTimeStamp);
		File.write((char*)&MeasAuxInfo_temp.AbsoluteTimeStamp, 8);

		MeasAuxInfo_temp.Latitude = littleToBigEndianFloat(MeasAuxInfo_temp.Latitude);
		File.write((char*)&MeasAuxInfo_temp.Latitude, 4);

		MeasAuxInfo_temp.Longitude = littleToBigEndianFloat(MeasAuxInfo_temp.Longitude);
		File.write((char*)&MeasAuxInfo_temp.Longitude, 4);

		File.close();
	}

	// When the data is not the first packet in each file, the structure that does not change with the number of packets does not need to be written again.
	else
	{
		s += FileName; // Add the generated file name to the path.
		fstream File;  // Create an fstream object for reading and writing files.

		strcpy_s(FilePath_1, s.c_str());                         // Store the file path in FilePath_1.
		File.open(FilePath_1, ios::in | ios::binary | ios::out); // Open the file in read/write and binary mode to avoid clearing the contents by opening in write-only mode.
		File.seekp(64, ios::beg);                                // Set the file pointer position to the 64th byte.
		InfoSize_8 = bagcount[0];                                // Get the number of data packets for the current file (stored in bagcount[0]) and assign it to InfoSize_8.
		InfoSize_8 = littleToBigEndian64(InfoSize_8);            // Convert InfoSize_8 from little-endian to big-endian format.
		File.write((char*)&InfoSize_8, 8);                       // Write the converted InfoSize_8 into the file, writing 8 bytes of data.

		/* Write packet content */
		File.seekp(74 + 10 * 1024 * 1024 + Length_1 + ((bagcount[0] % 615000) - 1) * (4 + Data_length), ios::beg); // Set the file pointer to the starting position of the next packet (74 bytes + 10MB data + length including the current packet).

		uint32_t Datalength2 = littleToBigEndian32(Data_length); // Convert Data_length to big-endian format and write 4 bytes of data.
		File.write((char*)&Datalength2, 4);                      // Update packet length.

		// Write frequency data.
		for (int i = 0; i < TraceInfo_temp.PartialsweepTracePoints; i++) {
			File.write((char*)&Frequency[i], 8);
		}

		// Write power data.
		for (int i = 0; i < TraceInfo_temp.PartialsweepTracePoints; i++) {
			File.write((char*)&PowerSpec_dBm[i], 4);
		}

		InfoSize_4 = littleToBigEndian32(HopIndex); // Convert HopIndex to big-endian format (4 bytes) and write to file.
		File.write((char*)&InfoSize_4, 4);

		InfoSize_4 = littleToBigEndian32(FrameIndex); // Convert FrameIndex to big-endian format (4 bytes) and write to file.
		File.write((char*)&InfoSize_4, 4);

		MeasAuxInfo_temp.MaxIndex = littleToBigEndian32(MeasAuxInfo_temp.MaxIndex); // Convert MeasAuxInfo_temp.MaxIndex to big-endian format (4 bytes) and write to file.
		File.write((char*)&MeasAuxInfo_temp.MaxIndex, 4);

		MeasAuxInfo_temp.MaxPower_dBm = littleToBigEndianFloat(MeasAuxInfo_temp.MaxPower_dBm); // Convert MeasAuxInfo_temp.MaxPower_dBm to big-endian format (4-byte float) and write to file.
		File.write((char*)&MeasAuxInfo_temp.MaxPower_dBm, 4);

		MeasAuxInfo_temp.Temperature = littleToBigEndian16(MeasAuxInfo_temp.Temperature);
		File.write((char*)&MeasAuxInfo_temp.Temperature, 2);

		MeasAuxInfo_temp.RFState = littleToBigEndian16(MeasAuxInfo_temp.RFState);
		File.write((char*)&MeasAuxInfo_temp.RFState, 2);

		MeasAuxInfo_temp.BBState = littleToBigEndian16(MeasAuxInfo_temp.BBState);
		File.write((char*)&MeasAuxInfo_temp.BBState, 2);

		MeasAuxInfo_temp.GainPattern = littleToBigEndian16(MeasAuxInfo_temp.GainPattern);
		File.write((char*)&MeasAuxInfo_temp.GainPattern, 2);

		MeasAuxInfo_temp.ConvertPattern = littleToBigEndian32(MeasAuxInfo_temp.ConvertPattern);
		File.write((char*)&MeasAuxInfo_temp.ConvertPattern, 4);

		MeasAuxInfo_temp.SysTimeStamp = littleToBigEndianDouble(MeasAuxInfo_temp.SysTimeStamp);
		File.write((char*)&MeasAuxInfo_temp.SysTimeStamp, 8);

		MeasAuxInfo_temp.AbsoluteTimeStamp = littleToBigEndianDouble(MeasAuxInfo_temp.AbsoluteTimeStamp);
		File.write((char*)&MeasAuxInfo_temp.AbsoluteTimeStamp, 8);

		MeasAuxInfo_temp.Latitude = littleToBigEndianFloat(MeasAuxInfo_temp.Latitude);
		File.write((char*)&MeasAuxInfo_temp.Latitude, 4);

		MeasAuxInfo_temp.Longitude = littleToBigEndianFloat(MeasAuxInfo_temp.Longitude);
		File.write((char*)&MeasAuxInfo_temp.Longitude, 4);
		File.close();
	}
	return 0;
}

int SWPMode_Recording()
{
	int Status = 0;      // Return value of the function.
	void* Device = NULL; // Memory address of the current device.
	int DevNum = 0;      // Specify the device number.

	BootProfile_TypeDef BootProfile; // Boot configuration structure, including physical interface, power supply method, etc.
	BootInfo_TypeDef BootInfo;       // Boot information structure, including device information, USB rate, etc.

	BootProfile.DevicePowerSupply = USBPortAndPowerPort; // Use both USB data port and independent power supply port.

#if IS_USB==1
	// Configure USB interface.
	BootProfile.PhysicalInterface = USB;
#else 
	// Configure ETH interface.
	BootProfile.PhysicalInterface = ETH;
	BootProfile.ETH_IPVersion = IPv4;
	BootProfile.ETH_RemotePort = 5000;
	BootProfile.ETH_ReadTimeOut = 5000;
	BootProfile.ETH_IPAddress[0] = 192;
	BootProfile.ETH_IPAddress[1] = 168;
	BootProfile.ETH_IPAddress[2] = 1;
	BootProfile.ETH_IPAddress[3] = 100;
#endif

	Status = Device_Open(&Device, DevNum, &BootProfile, &BootInfo); // Open the device.

	if (Status == APIRETVAL_NoError)
	{
		cout << "The device is turned on successfully" << endl;
	}

	// If the device fails to open, return an error message. In the following errors, the device cannot operate normally. It is recommended to follow the prompts and reopen the device.
	else
	{
		switch (Status)
		{

		case -1:cout << "Error - Check the power supply of the device, the connection of the data cable, and check if the driver is installed correctly" << endl; break;
		case -3:cout << "Error - RF calibration file is missing, please copy the RF calibration file to the CalFile folder" << endl; break;
		case -4:cout << "Error - IF calibration file is missing, please copy the IF calibration file to the CalFile folder" << endl; break;
		case -5:cout << "Error - Config file is missing, please copy the config file into the CalFile folder" << endl; break;
		case -6:cout << "Error - Device spec file is missing, please copy the device spec file to the CalFile folder" << endl; break;
		default:cout << "Returns other errors Status = "<< Status << endl; break;
		}

		return Status;
	}

	SWP_Profile_TypeDef SWP_ProfileIn;  // SWP input configuration, including start frequency, stop frequency, RBW, reference level, etc.
	SWP_Profile_TypeDef SWP_ProfileOut; // SWP output configuration.
	SWP_TraceInfo_TypeDef TraceInfo;    // Trace information under the current configuration, including trace points, hopping points, etc.

	SWP_ProfileDeInit(&Device, &SWP_ProfileIn); // Initialize parameters related to SWP mode configuration.

	SWP_ProfileIn.StartFreq_Hz = 9e3;   // Configure start frequency.
	SWP_ProfileIn.StopFreq_Hz = 6.35e9; // Configure stop frequency.
	SWP_ProfileIn.RBW_Hz = 300e3;       // Configure RBW.

	Status = SWP_Configuration(&Device, &SWP_ProfileIn, &SWP_ProfileOut, &TraceInfo); // Send SWP mode related configuration.

	vector<double> Frequency(TraceInfo.PartialsweepTracePoints);    // Dynamically create an array to store the complete frequency data.
	vector<float> PowerSpec_dBm(TraceInfo.PartialsweepTracePoints); // Dynamically create an array to store the complete amplitude data.
	int HopIndex = 0;                                               // The complete spectrum of the device is obtained by assembling frames. This parameter is used to return the current frame number.
	int FrameIndex = 0;                                             // Indicates the index of the current frame among all frames.
	MeasAuxInfo_TypeDef MeasAuxInfo;                                // This structure is used to store auxiliary information of measurement data.

	while (1)
	{
		for (int i = 0; i < TraceInfo.TotalHops; i++) // TraceInfo.TotalHops represents the number of frames under the current configuration. Therefore, call SWP_GetPartialSweep TraceInfo.TotalHops times to obtain the complete trace.
		{
			Status = SWP_GetPartialSweep(&Device, Frequency.data(), PowerSpec_dBm.data(), &HopIndex, &FrameIndex, &MeasAuxInfo); // Acquire spectrum data.

			if (Status == APIRETVAL_NoError)
			{
				// Call Write_SWPData_Info() function to start writing the record file.
				Write_SWPData_Info(&BootInfo, &SWP_ProfileIn, &SWP_ProfileOut, &TraceInfo, &Frequency[0], &PowerSpec_dBm[0], HopIndex, FrameIndex, &MeasAuxInfo);
			}

			// If data acquisition fails, return an error message. In the following errors, it is recommended to follow the prompts.
			else
			{
				switch (Status)
				{
				case -10:cout << "WARNING - IF saturation is recommended to be reconfigured, reference level <= signal power" << endl; break; // If SWP_GetPartialSweep returns -10, it is recommended to reconfigure parameters.
				case -14:cout << "Warning - The temperature of the current device varies greatly. It is recommended to reconfigure the temperature"<<endl; break; // If SWP_GetPartialSweep returns -14, it is recommended to reconfigure parameters.
				default:cout << "Returns other errors Status = " << Status << endl; Device_Close(&Device); break;
				}
			}
		}
	}

	Device_Close(&Device); // Close the device.

	return 0;
}