#ifndef UART_HPP_
#define UART_HPP_
#include <iostream>
#include <vector>
#include <boost/asio.hpp>
#include <boost/container/detail/singleton.hpp>
#include "common/common_func.hpp"
#include "common/global.hpp"
#include "dbaccess/sql_db.hpp"
#include "utility/calculation.hpp"
#include "scheduler/status_mgr.hpp"

typedef void (*pTestRecvCallBack)(int Status);

// 无关网关与传感器交互命令 1 ~ 255
enum InteractiveCommand {

    ASK_TASK = 1, // 请求任务 只从传感器发出
    DEVICE_INF = 2, // 上线发送通道配置，版本信息, 会收到REVIVE_DURATION = 8, 
    MEAS_EVAL = 3, // 特征值 校时信息带给传感器
    WAVE_CMD = 4, // 只从无线网关发出，x,y,z
    WAVE_X = 5, // 只从传感器发出
    WAVE_Y = 6, // 只从传感器发出
    WAVE_Z = 7, // 只从传感器发出
    REVIVE_DURATION = 8, // 复活时长
    CONFIG = 9, // 配置 只从无线网关发出
    CONFIG_INF2 = 10, // 配置 只从无线网关发出 测点名称，测点编号 
    DEVICE_INF2 = 11, // 测点名称，测点编号 
    UPGRADE = 12, // 升级, 升级给这条信息 
    SIGNAL_STRENGTH = 13, // 信号强度       --不再使用
    DEVICE_EXCEPTION = 14, // 异常: 外设
    WAVE_COMPRESS = 15, // 波形数据压缩
    UPGRADE_FIRMWARE = 16, //固件升级内容 
    UPGRADE_ASK = 17, //固件升级请求 
    WAVE_RESP   = 18,  // 波形数据回复
    WAVE_LF_X   = 19,
    WAVE_LF_Y  = 20,
    WAVE_LF_Z   = 21
};

// 无线传感器请求任务
typedef struct {
    uint8_t cmd;  // kAskTask
    uint16_t sensor_id;
} AskTaskReq;

typedef struct {
    uint8_t cmd; // kAskTask
    uint8_t task_id; // 任务编号, 参考InteractiveCommand
} AskTaskResp;

// 无线传感器请求复活配置
typedef struct {
    uint8_t cmd;
    uint16_t sensor_id;   
} ReviveConfigReq;

typedef struct {
    uint8_t cmd;
    uint16_t eigen_duration; // 如果连不上网关，一直以此间隔复活，并且只连3秒时间    
} ReviveConfigResp;

// 无线传感器异常反馈
typedef struct {
    uint8_t cmd; 
    uint16_t sensor_id;
    uint8_t exception_id;
} ExceptionFeedback;

//=====================================================
//// 交互命令
// 无线传感器发送特征值
typedef struct {
    uint8_t cmd;
    uint16_t sensor_id;
    DataRecvStatic data_static;
    DataRecvDym data_dym;
} EigenValueReport;

// 无线传感器发送波形
typedef struct {
    uint8_t cmd;
    uint16_t sensor_id;
    uint16_t len;
    uint16_t total;
    uint16_t current;
    char data[0];
} WaveFormReport;
// 网关发送给传感器的请求
// 配置传感器下次复活相对时间
typedef struct {
    uint8_t cmd;
    uint16_t shortAddr;
    uint16_t duration;
} ReviveDuration;

typedef enum {
    kSamplingRate12800 = 1,
    kSamplingRate25600 = 2,
} SamplingRate;

typedef enum {
    kRange64g = 1, 
    kRange128g = 2
} MeasurementRange;

// 传感器配置
typedef struct {
    uint8_t cmd;
    uint16_t freq_band_energy_begin[4]; // 频带能量开始
    uint16_t freq_band_energy_end[4];   // 频带能量结束
    uint16_t falut[4];  // 故障频率
    uint16_t impact[2]; // 冲击带通频率
    uint8_t sampling_rate; // 采样率, 参考：SamplingRate
    uint8_t range; // 量程, 参考：MeasurementRange
    uint8_t sampling_time; // 采样时间
    uint16_t velocity_start_frequency;
    uint8_t wave_x_y_z[3]; // 分别为x, y, z
} SensorConfig;

// 下发任务
typedef struct ScheduleTask_{
    uint8_t cmd;
    uint16_t shortAddr;
    uint16_t duration;
    uint32_t timeStamp;
    uint16_t millisecond;
    uint8_t next_taskID;
    uint8_t acc_z;
    bool z; // true: z波形 false: xy波形
    ScheduleTask_(){
        cmd = 0;
        shortAddr = 0;
        duration = 0;
        timeStamp = 0;
        millisecond = 0;
        next_taskID = 0;
        acc_z = 0;
        z = false;
    }
} ScheduleTask;

// 升级任务
typedef struct {
    uint8_t cmd;
    uint16_t len;
    uint8_t encrypt_type; // 加密类型 0: 不加密 
    uint8_t total;
    uint8_t data[0];
} UpgradeData;
// 对任何请求的一般反馈
typedef struct {
    uint8_t cmd;
    uint8_t success;   // 0:成功， 1：其它失败，需要重发
} NormalResp;

class Uart {
public:
    Uart();
    ~Uart();

    void InitZigbeeHW();
    void InitUart(speed_t speed);
    void Close();
    void InitTestUart(speed_t speed);
    void ReadTestUart();

    void WriteToUart(const char* strSend, int pLen);
    int ReadFromUart();
    void setCallBack(onReceiveUart _callback);
    void Run();
    void Stop();

    void UpdateZigbeeInfo(const char* pData);
    void DealRecvData(const char* pData);
    void DelRepeatData(char *pShortAdd,const char* dataNodeNo,const char* measurementID);
    void DealDataNodeInfo(const char* pData);
    void DealDataNodeName(const char* pData);
    void ZigbeeParameterConfig();
    int ZigbeeTest();
    int UartRecv(int fd, char srcshow, char* buffer);
    int FindRecvPackage(int bytesRead, char* mUartRecvBuf, char* head);

    int DealAskTask(uint16_t ushortAdd);
    int DealAskTaskOld(uint16_t ushortAdd);
    int DealFeatureValue(const char* pData, uint16_t ushortAdd);
    int DealException(const char* pData);
    int DealReviveDuration(uint16_t ushortAdd);
    int DealConfig(uint16_t ushortAdd);
    int DealWaveCompress(const char *pData,uint16_t ushortAdd);
    int DealSensorRSSI(const char *pData,uint16_t ushortAdd);
    int DealUpgrade(uint16_t ushortAdd,int status);
    void GetLocalZigbeeRSSI(uint16_t ushortAdd);
    int WaveSendCondition(char* shortAddr);

    // feature parse
    int DealDataNodeFeature(const char* pData, int flag);
    void DealTriger(uint16_t ushortAdd,std::string & measurementID);
    void RecordBattery(std::string& strLongAddr, DataRecvStatic& dataStatic, std::string& nowTimetamp);
    void DealDataNodeWave(const char* pData, int comand);
    void DealWaveThread();
    void DealWave();
    std::vector<float> DealData(int ichannel, float coe, unsigned int sampleRate, float ACCSampleTime, std::string strProduct,int version);
    float Calcoe(int ran, int iChannel, std::string& product, int range);
    void WriteDatFile(int sampleRate, std::string& strMeasurementID, int iChannel, std::vector<float>& vecData,std::string &product,float ACCSampleTime,int version);
    float ScaleConvert(int highbit);
    void DataExtract(RecvData *p, int id, unsigned int &lowbit, float &n);

    // command category
    void modify_info(unsigned short id, char* zigbee);
    void modify_distaddr_info(unsigned short id, char* zigbee, unsigned char* distAddr);
    void modify_LocalAddr(unsigned short id);
    void modify_DistAddr(unsigned char* distAddr);
    void ModifyDistAddr(uint16_t distAddr);
    void modify_Localchannel(unsigned char pad);
    void modify_LocalPanID(unsigned short padID);
    void getZigbeeSignal(uint16_t ushortAdd);
    void zigbee_reset(unsigned short pad, unsigned short type);
    void WriteChanl2Zigbee(unsigned char pad);
    void WritePanId2Zigbee(unsigned short pad);
    void WriteSpeed2Zigbee();
    void WriteTranTimeout2Zigbee(unsigned char Time);
    void WriteShortAddr2Zigbee(unsigned short pad);
    void WriteShortAddr_DistAddr2Zigbee(unsigned short pad, unsigned char* pDestShortAddr);
    bool CheckCrc(char* pCheckBuff, int No);
    void UpdateZigbeeInfoCtrl();

    // tranducer parameter config
    void UpdateWirelessNode(uint16_t ushortAdd);
    int UpdateWirelessNodeTime(unsigned char* pDestShortAddr, int modifyaddr);
    int UpdateConfig(uint16_t ushortAdd);
    int TaskResp(ScheduleTask scheduleTask);
    int SendReviveDuration(ReviveDuration recvDuration);
    int WaveResp(uint16_t shortAddr);
    void openSwitch();
    int CheckZigbeeACK();

public:
    int fd, TestFd;
    bool bUpdate;
    bool bTest;
    bool bZigbeeSinal;
    bool bModifyAddr;
    bool bSendTimeStamp;
    std::string DataNodeUpdateFile;

private:
    boost::posix_time::ptime mLocalTime;
    boost::asio::io_service mIoSev;
    boost::asio::serial_port mUart;
    int mRdLength;
    int mlastSize;
    int mPackgeIndex;
    std::string strTimetamp;

    std::string m_strDestShortAddr;
    uint16_t wave_shortAddr;
    int now_task;
    struct timespec wave_recv_start,wave_recv_end;

    int waittime;
    enum { BUF_LENGTH = 40960 };
    unsigned char mUartRecvBuf[BUF_LENGTH];
    char mUartRecvTmpBuf[BUF_LENGTH * 15];
    boost::asio::io_service::strand mStrand;

    onReceiveUart m_callback;

    unsigned long m_TimeStamp;
    bool wave_trans_;
    int m_waveCountX;
    int m_waveCountY;
    int m_waveCountZ;
    int m_waveCountLowFreX;
    int m_waveCountLowFreY;
    int m_waveCountLowFreZ;
    std::vector<RecvData> VecWaveDataX;
    std::vector<RecvData> VecWaveDataY;
    std::vector<RecvData> VecWaveDataZ;
    std::vector<RecvData> VecWaveDataLowFreX;
    std::vector<RecvData> VecWaveDataLowFreY;
    std::vector<RecvData> VecWaveDataLowFreZ;

    uint8_t send_data[100];
    uint16_t last_short_addr;
    long last_time;
    long last_time_upgrade;
    bool current_z;
    std::map<uint16_t, std::vector<uint8_t>> map_send_data;

    ScheduleStatus schedule_status;
};

typedef boost::container::dtl::singleton_default<Uart> uart_inst;
#endif // UART_HPP_
