/*
*********************************************************************************************************
*                                       IAR Development Kits
*                                              on the
*
*                                    Nano100
*
* Filename      : ext_data.h
* Version       : V1.00
* Programmer(s) : Qian Xianghong
*********************************************************************************************************
*/

#ifndef  USER_EXT_DATA_PRESENT
#define  USER_EXT_DATA_PRESENT

#include "type.h"

extern loopbuff_t RF_DataM, RF_TranM;
extern SemaphoreHandle_t RF_TranLock;

// 初始化
void Data_Open();

// 允许匿名结构
#pragma anon_unions
#pragma pack(push, 1)

// 历史数据和上传队列
typedef struct	// size = 64
{
	uint16_t check; 			// 标志位，必须为0x55AA
	uint8_t oriPSN[6];
	uint8_t payload_len;
	uint8_t payload[RF_MAX_PAYLOAD_LEN];
	int32_t prevData;			// 同一个PSN的上一条记录	(-1表示无上一条记录)
	unsigned warn : 1;			// 是否报警记录
	unsigned fault : 1;			// 是否故障记录
	unsigned : 14;	
	uint16_t volumePct;			// 计算液位百分比
	uint32_t volume;			// 计算重量
	uint32_t recvTime;			// 射频收到的绝对时间戳
	uint16_t crc;				// 校验位
} ext_data_t;

// 储罐总数
typedef struct
{
	uint16_t check; 			// 标志位，必须为0x55AA
	int16_t count;				// 储罐总数，为0表示无档案
	uint16_t crc;				// 校验位
} ext_count_t;

// 储罐档案
typedef struct	// size = 16
{
	uint8_t PSN[6];
	int32_t lastData;			// 最后一条数据记录的序号	(-1表示无记录)
	uint8_t pn;
	unsigned warn : 1;			// 是否报警状态
	unsigned fault : 1;			// 是否故障状态
	unsigned : 6;	
	uint32_t recvTime;			// 射频收到的绝对时间戳
} ext_bottle_t;

// 储罐扩展档案
typedef struct	// size = 24
{
	uint8_t PSN[6];
	char	TGGU[12];			// 箱主序号
	uint8_t FF[6];
} ext_box_t;

// 储罐档案按PSN索引
typedef struct
{
	uint8_t PSN[6];
	int16_t recNo;
} ext_bottle_idx_t;

// 储罐档案按箱主序号索引
typedef struct
{
	char TGGU[12];
	uint8_t PSN[6];
	int16_t recNo;
} ext_box_idx_t;

// GPS定位信息
typedef struct	// size = 22
{
	uint16_t check; 			// 标志位，必须为0x55AA
	date_time_t		sysTime;	// 系统时间, size = 6
	int32_t			longitude;	// 经度
	int32_t			latitude;	// 维度
	uint16_t		speed;		// 速度
	uint8_t			sateCount;	// GPS卫星数量
	uint8_t			posState;	// GPS定位状态
	uint16_t crc;				// 校验位
} ext_gps_t;

extern ext_gps_t  Ext_GPS;

extern ext_data_t Ext_Data_Rec, Ext_Data_Rec1;

extern ext_count_t bottleCnt, boxCnt;
extern ext_bottle_idx_t bottlePSN[];
extern ext_box_idx_t boxTGGU[];
extern ext_box_idx_t boxPSN[];

#pragma pack(pop)

// 关联铁电和SFlash的一致性（用相对时间和绝对时间作为标记）
void CheckFramSFlashValid(uint32_t relative_time);

// TODO: 将精简数据转换成上传数据
void cacl_gprs_tran_data(ext_data_t *pGprs, data_sample_t *sample);

// 将一个数据加入队列
// RF_DataM和RF_TranM用一个存储区，写指针始终相同，读指针可能不同
void Data_PutToQueue(ext_data_t *pGprs);

// 快速排序法
void Ext_Sort_Bottle_PSN(ext_bottle_idx_t a[], int16_t lo, int16_t hi);
void Ext_Sort_Box_TGGU(ext_box_idx_t a[], int16_t lo, int16_t hi);
void Ext_Sort_Box_PSN(ext_box_idx_t a[], int16_t lo, int16_t hi);

// 根据PSN查找储罐档案序号，没有则返回-1
int16_t Ext_Lookup_Bottle_PSN(uint8_t PSN[], int16_t cnt);
// 根据箱主序号查找PSN，没有则返回-1
int16_t Ext_Lookup_Box_TGGU(char TGGU[], int16_t cnt);
// 根据PSN查找箱主序号，没有则返回-1
int16_t Ext_Lookup_Box_PSN(uint8_t PSN[], int16_t cnt);

// 更新从服务器下载的罐箱档案
void Ext_Update_Boxes(char *buff);

#endif
