
#ifndef __DEVICEGASV3_HPP_
#define __DEVICEGASV3_HPP_

#include <iostream>
#include "deviceBase.h"

#define DEVICEGASV3_DATA_HEAD          (0XC5AB) // 数据头
#define DEVICEGASV3_DATA_DEVTYPE       (0x05)  // 设备类型
#define DEVICEGASV3_COMMAND_PLAY_NOW       3
#define DEVICEGASV3_COMMAND_PAUSE          4
#define DEVICEGASV3_COMMAND_STOP           5
#define DEVICEGASV3_COMMAND_NEXT           6
#define DEVICEGASV3_COMMAND_UP             7
#define DEVICEGASV3_COMMAND_SET_VOLUME     14
#define DEVICEGASV3_COMMAND_PLAY_SET       15

class deviceGasV3:public deviceBase
{
    private:
        enum RECV_STEP{
            STEP_HEAD_1 = 0,
            STEP_HEAD_2 = 1,
            STEP_TYPE = 2,
            STEP_DEVID = 3,
            STEP_COM = 4, 
            STEP_ACK = 5
        };

        typedef struct {
            uint8_t dataCount;
            uint8_t dataLength;
            uint8_t dataCheckSum;
            uint8_t data[6];
            enum RECV_STEP step = STEP_HEAD_1;
        }ExpelComm;

        ExpelComm _comm;

    public:
        deviceGasV3():deviceBase(){
            this->setDeviceToken(tcp);
            this->setDeviceInfo("赛为智能 驱鸟器协议");
        }
    public:
        // 电压
        float voltage = 0;
        // 气压
        float pressure = 0;
        // 状态
        int state = 0;
        // 纬度
        float latitude = 0;
        // 经度
        float longitude = 0;
        
        // LRC校验
        static unsigned char check(unsigned char *pSendBuf,unsigned char num)
        {
            char bylrc = 0,i = 0;
            for(i = 0; i < num; i++){
                bylrc += pSendBuf[i];
            }
            return (bylrc & 0x00ff);
        }

        static void serialization(const GasV1Control gasV1Control,char *data){
            data[0] = 0XC5;
            data[1] = 0XAB;
            data[2] = DEVICEGASV3_DATA_DEVTYPE;
            data[3] = gasV1Control.deviceId;
            data[4] = gasV1Control.msgId;
            data[5] = 0;
            data[6] = 0;
            data[7] = 0;
            data[8] = 0;
            data[9] = check((unsigned char *)(data + 2), 7);
        }

        bool deserialization()
        {
            return true;
        }

        bool Consumer(uint8_t *data, int len, int &msg_id)
        {
            bool ReceiveSuccessful = false;
            for (int i = 0; i < len; i++)
            {
                switch(_comm.step){
                    case STEP_HEAD_1:
                        if(data[i] == 0xAB){
                            _comm.data[0] = 0xAB;
                            _comm.step = STEP_HEAD_2;
                        }
                        break;
                    case STEP_HEAD_2:
                        if(data[i] == 0xC5){
                            _comm.data[1] = 0xC5;
                            _comm.step = STEP_TYPE;
                        }
                        break;
                    case STEP_TYPE:
                        _comm.data[2] = data[i];
                        _comm.step = STEP_DEVID;
                        break; 
                    case STEP_DEVID:
                        _comm.data[3] = data[i];
                        _comm.step = STEP_COM;
                        break;
                    case STEP_COM:
                        _comm.data[4] = data[i];
                        _comm.step = STEP_ACK;
                        break;
                    case STEP_ACK:
                        _comm.data[5] = data[i];
                       _comm.step = STEP_HEAD_1;
                       ReceiveSuccessful = true;
                        _comm.dataCount = 6;
                        break;
                    default:
                        _comm.step = STEP_HEAD_1;
                        break;   
                }
            }
            if(!ReceiveSuccessful) return false;
            return deserialization(_comm.data, _comm.dataCount, msg_id);
        }

        bool deserialization(const uint8_t *data, int len, int &msg_id){
            if(len == 6 && data[5] == 0x01){
                this->deviceId = data[3];
                return true;
            }
            return false;
        }

        /**
         * @description: 打开
         * @param {int} deivceId
         * @return {*}
         */    
        int32_t Open(std::string DeviceId, uint8_t* data, int& length){
            GasV1Control gasControl;
            gasControl.deviceId = atoi(DeviceId.c_str());
            gasControl.msgId = DEVICEGASV3_COMMAND_PLAY_NOW;
            gasControl.data = 0x00;
            length = 10;
            serialization(gasControl, (char *)data);
            return 0;
        }

        /**
         * @description: 关闭
         * @param {int} deivceId
         * @return {*}
         */    
        int32_t Close(std::string DeviceId, uint8_t* data, int& length){
            GasV1Control gasControl;
            gasControl.deviceId = atoi(DeviceId.c_str());
            gasControl.msgId = DEVICEGASV3_COMMAND_STOP;
            gasControl.data = 0x00;
            length = 10;
            serialization(gasControl, (char *)data);
            return 0;
        }

        /**
         * @description: 开炮
         * @param {int} deivceId
         * @return {*}
         */    
        int32_t Fire(std::string DeviceId, uint8_t* data, int& length){
            GasV1Control gasControl;
            gasControl.deviceId = atoi(DeviceId.c_str());
            gasControl.msgId = DEVICEGASV3_COMMAND_PLAY_NOW;
            gasControl.data = 0x00;
            length = 10;
            serialization(gasControl, (char *)data);
            return 0;
        }

        /**
         * @description: 状态
         * @param {int} deivceId
         * @return {*}
         */    
        int32_t Status(std::string DeviceId, uint8_t* data, int& length){
            return 0;
        }

        /**
         * @description: 判定msg是否为status
         * @param {int} &msg_id
         * @return {*}
         */    
        bool getStatusMsg(int &msg_id){
            return true;
        }
    
        /**
         * @description: 构建设备信息
         * @param {SendDevice&} sendDevice
         * @return {*}
         */    
        void BuildDeviceInfo(SendDevice& sendDevice){
            sendDevice.deviceId = atoi(this->getDeviceId().c_str());
            sendDevice.commandCode = "1";
            sendDevice.status = 1;
            sendDevice.workStatus = 1;
            sendDevice.powerStatus = 1;
            sendDevice.batteryStatus = 1;
            sendDevice.num  = 0;
            sendDevice.oxyPressure  = 0;
            sendDevice.gasPressure  = 0;
            sendDevice.remark = "";
            sendDevice.attr1 = std::to_string(this->voltage);     // 电压
            sendDevice.attr2 = std::to_string(this->pressure);     // 声压
        }

};


#endif