#include "clightdriver_opt.h"
#include "cmserialport.h"
#include "clight.h"
#include "OPTController.h"
const char* errcode[]=
{
"operation succeed                                              ",
"invalid handle                                                 ",
"error unknown                                                  ",
"failed to initialize a serial port                             ",
"failed to release a serial port                                ",
"attempt to access an unopened serial port                      ",
"failed to create an Ethernet connection                        ",
"failed to destroy an Ethernet connection                       ",
"SN is not found                                                ",
"failed to turn on the specified channel(s)                     ",
"failed to turn off the specified channel(s)                    ",
"failed to set the intensity for the specified channel(s)       ",
"failed to read the intensity for the specified channel(s)      ",
"failed to set trigger pulse width                              ",
"failed to read trigger pulse width                             ",
"failed to read high brightness trigger pulse width             ",
"failed to set high brightness trigger pulse width              ",
"failed to read serial number                                   ",
"failed to read IP address                                      ",
"index(es) out of the range                                     ",
"failed to write data                                           ",
"parameter(s) out of the range                                  ",
"failed to read MAC                                             ",
"failed to set max current                                      ",
"failed to read max current                                     ",
"failed to set trigger activation                               ",
"failed to read trigger activation                              ",
"failed to set work mode                                        ",
"failed to read work mode                                       ",
"failed to set baud rate                                        ",
"failed to set channel amount                                   ",
"failed to set detected min load                                ",
"failed to read outer trigger frequency upper bound             ",
"failed to set auto-strobe frequency                            ",
"failed to read auto-strobe frequency                           ",
"failed to set DHCP                                             ",
"failed to set load mode                                        ",
"failed to read property                                        ",
"failed to reset connection                                     ",
"failed to set ethe connection heartbeat                        ",
"Failed to get controler(s) list                                ",
"Failed to software trigger                                     ",
"Failed to get channelstate                                     ",
"Failed to set keepalvie parameters                             ",
"Failed to enable/disable keepalive                             ",
"Failed to read step count                                      ",
"Failed to set trigger mode                                     ",
"Failed to read trigger mode                                    ",
"Failed to set current step index                               ",
"Failed to read current step index                              ",
"Failed to reset current step index                             ",
"Failed to set trigger delay                                    ",
"Failed to get trigger delay                                    ",
"Failed to set multiple channels trigger delay                  ",
"Failed to set SEQ table data                                   ",
"Failed to Read SEQ table data                                  ",
"Failed to read controller's channel                            ",
"Failed to read the state of keepalive                          ",
"Failed to read the continuous time of keepalive                ",
"Failed to read the delivery times of prop packet               ",
"Failed to read the interval time of prop packet                ",
"Failed to read the vision of output board                      ",
"Failed to read detect mode of load                             ",
"Failed to set mode of boot protection                          ",
"Failed to read the specified channel boot state                ",
"Failed to set outer trigger frequency upper bound              ",
"Failed to set IP configuration of the controller               ",
"Failed to set voltage of specified channel voltage             ",
"Failed to read the specified channel's voltage                 ",
"Failed to set time unit                                        ",
"Failed to read time unit                                       ",
};
const char *CLightDriver_OPT::getErrorString(int iErrID)
{
    if(iErrID)
    {
        iErrID-=3001000;
    }
    return errcode[iErrID];
}

#define OPTFUN_OPERATOR(f) \
do{     \
int irtn=f; \
if(irtn)   \
{       \
    QString s=QString::fromUtf8("OPT LightErr.")+QString::fromUtf8( getErrorString(irtn) );   \
            MQT_THROW_STR(s);   \
}   \
}while (0);

CLightDriver_OPT::CLightDriver_OPT(const QString& name,int32_t id)
    :CLightDriver(name,id)
{

}

CLightDriver_OPT::~CLightDriver_OPT()
{
}


int32_t CLightDriver_OPT::init_driver()
{
	if (m_pSerialPort->open() == -1)
	{
		return false;
	}

	openAllChannel(true);

    return CLightDriver::init_driver();
}

int32_t CLightDriver_OPT::exit_driver()
{
    int irtn= CLightDriver::exit_driver();
	m_pSerialPort->close();

    return irtn;
}


int32_t CLightDriver_OPT::setlight(int32_t iChid, int32_t ibright)
{
	CLight* pLight=(CLight*)FindChannel(iChid);
    Q_ASSERT(pLight);
    int isn=pLight->m_Variants.get_VData(Var_Base_SerialID_ID)->toInt();
    Q_ASSERT(isn>0&&isn<=4);
	
	return setLight(isn-1,ibright);
}

int32_t CLightDriver_OPT::freshlight(int32_t iChid)
{
    CLight* pLight=(CLight*)FindChannel(iChid);
    Q_ASSERT(pLight);
    int isn=pLight->m_Variants.get_VData(Var_Base_SerialID_ID)->toInt();
    Q_ASSERT(isn>0&&isn<=4);
    unsigned short val = 0;
	if (getLight(isn-1,val))
	{
		pLight->m_Variants.get_VData(Var_Light_Bright_ID)->setValue(val);
	}

    return RTN_SUCCESS1;
}

int32_t CLightDriver_OPT::setmultiplier(int32_t iChid, int32_t imultiplier)
{
    CLight* pLight=(CLight*)FindChannel(iChid);
    Q_ASSERT(pLight);
    int isn=pLight->m_Variants.get_VData(Var_Base_SerialID_ID)->toInt();
    Q_ASSERT(isn>0&&isn<=4);
    //OPTFUN_OPERATOR( OPTController_SetMaxCurrent (  controllerHandle,
    //                  isn, imultiplier*10));
    CLightDriver::setmultiplier(  iChid,   imultiplier);

    return RTN_SUCCESS1;
}

bool CLightDriver_OPT::openAllChannel(bool bOpen)
{
	unsigned char sendBuf[8];
	sendBuf[0] = 0x40;
	sendBuf[1] = 0x05;
	sendBuf[2] = 0x01;
	sendBuf[3] = 0x00;
	sendBuf[4] = 0x2A;
	sendBuf[5] = 0xFF;
	sendBuf[6] = bOpen;
	sendBuf[7] = 0x00;
	
	checkoutSum(sendBuf,7,sendBuf[7]);

	if (m_pSerialPort->send((char*)sendBuf, sizeof(sendBuf)) == -1)
	{
		MQT_THROW_STR(QString::fromLocal8Bit("打开光源所有通道失败-openAllChannel"));
		return false;
	}

	unsigned char checkBuf[6] = { 0x40, 0x03, 0x01, 0x00, 0x00, 0x44 };
	unsigned char recvBuf[6] = { 0 };
	
	if (m_pSerialPort->receive((char*)recvBuf, sizeof(recvBuf)) == -1)
	{
		MQT_THROW_STR(QString::fromLocal8Bit("未收到光源控制器命令回复-openAllChannel"));
		return false;
	}

	if(false == checkResponse(recvBuf, checkBuf, 6))
	{
		MQT_THROW_STR(QString::fromLocal8Bit("光源控制器命令回复校验失败-openAllChannel"));
		return false;
	}

	return true;
}

bool CLightDriver_OPT::setLight(unsigned char channelNum, unsigned short val)
{
	unsigned char sendBuf[9];
	sendBuf[0] = 0x40;//标识符
	sendBuf[1] = 0x06;//长度，长度与校验和之间的字节数
	sendBuf[2] = 0x01;//设备型号CODE
	sendBuf[3] = 0x00;//设备编号ID
	sendBuf[4] = 0x1A;//命令码,0x1A表示设置通道亮度
	sendBuf[5] = channelNum;//通道号
	sendBuf[6] = val;//亮度低8位
	sendBuf[7] = val >> 8;//亮度高8位
	sendBuf[8] = 0x00;
	
	checkoutSum(sendBuf,8,sendBuf[8]);

	if (m_pSerialPort->send((char*)sendBuf, sizeof(sendBuf)) == -1)
	{
		MQT_THROW_STR(QString::fromLocal8Bit("设置通道亮度失败-setLight"));
		return false;
	}

	unsigned char checkBuf[6] = { 0x40, 0x03, 0x01, 0x00, 0x00, 0x44 };
	unsigned char recvBuf[6];

	if (m_pSerialPort->receive((char*)recvBuf, sizeof(recvBuf)) == -1)
	{
		MQT_THROW_STR(QString::fromLocal8Bit("未收到光源控制器命令回复-setLight"));
		return false;
	}

	if(false == checkResponse(recvBuf, checkBuf, 6))
	{
		MQT_THROW_STR(QString::fromLocal8Bit("光源控制器命令回复校验失败-setLight"));
	}

	return true;
}

bool CLightDriver_OPT::getLight(unsigned char channelNum, unsigned short& val)
{
	unsigned char sendBuf[7];
	sendBuf[0] = 0x40;
	sendBuf[1] = 0x04;
	sendBuf[2] = 0x01;
	sendBuf[3] = 0x00;
	sendBuf[4] = 0x31;
	sendBuf[5] = channelNum;
	sendBuf[6] = 0x00;
	checkoutSum(sendBuf,6,sendBuf[6]);

	if (m_pSerialPort->send((char*)sendBuf, sizeof(sendBuf)) == -1)
	{
		MQT_THROW_STR(QString::fromLocal8Bit("获取通道亮度失败-getLight"));
		return false;
	}

	unsigned char checkBuf[8] = { 0x40, 0x05, 0x01, 0x00, channelNum, 0, 0, 0 };
	unsigned char recvBuf[8];

	if (m_pSerialPort->receive((char*)recvBuf, sizeof(recvBuf)) == -1)
	{
		MQT_THROW_STR(QString::fromLocal8Bit("未收到光源控制器命令回复-getLight"));
		return false;
	}

	if(false == checkResponse(recvBuf, checkBuf, 5))
	{
		MQT_THROW_STR(QString::fromLocal8Bit("光源控制器命令回复校验失败-getLight"));
		return false;
	}

	unsigned char checkSum = 0;
	for (int i = 0; i < 7;i++)
	{
		checkSum += recvBuf[i];
	}

	if (checkSum != recvBuf[7])
	{
		MQT_THROW_STR(QString::fromLocal8Bit("光源控制器命令回复校验和失败-getLight"));
		return false;
	}

	val = (recvBuf[6] << 8) + recvBuf[5];

	return true;
}

bool CLightDriver_OPT::reset()
{
	unsigned char sendBuf[7];
	sendBuf[0] = 0x40;
	sendBuf[1] = 0x04;
	sendBuf[2] = 0x01;
	sendBuf[3] = 0x00;
	sendBuf[4] = 0x23;
	sendBuf[5] = 0x00;
	sendBuf[6] = 0x00;
	
	checkoutSum(sendBuf,6,sendBuf[6]);

	if (m_pSerialPort->send((char*)sendBuf, sizeof(sendBuf)) == -1)
	{
		MQT_THROW_STR(QString::fromLocal8Bit("获取通道亮度失败-reset"));
		return false;
	}

	unsigned char response[6] = { 0x40, 0x03, 0x01, 0x00, 0x00, 0x44 };
	unsigned char recvBuf[6];
	if (!m_pSerialPort->receive((char*)recvBuf, sizeof(recvBuf)))
	{
		MQT_THROW_STR(QString::fromLocal8Bit("未收到光源控制器命令回复-reset"));
		return false;
	}

	if(false == checkResponse(recvBuf, response, 6))
	{
		MQT_THROW_STR(QString::fromLocal8Bit("光源控制器命令回复校验和失败-reset"));
		return false;
	}

	return true;
}

bool CLightDriver_OPT::setTriggerLevel(unsigned char val)
{
	unsigned char sendBuf[7];
	sendBuf[0] = 0x40;
	sendBuf[1] = 4;
	sendBuf[2] = 1;
	sendBuf[3] = 0;
	sendBuf[4] = 0x10;
	sendBuf[5] = val;
	sendBuf[6] = 0;

	checkoutSum(sendBuf,6,sendBuf[6]);

	if (m_pSerialPort->send((char*)sendBuf, sizeof(sendBuf)) == -1)
	{
		MQT_THROW_STR(QString::fromLocal8Bit("获取通道亮度失败-setTriggerLevel"));
		return false;
	}

	unsigned char response[6] = { 0x40, 0x03, 0x01, 0x00, 0x00, 0x44 };
	unsigned char recvBuf[6];
	if (m_pSerialPort->receive((char*)recvBuf, sizeof(recvBuf)) == -1)
	{
		MQT_THROW_STR(QString::fromLocal8Bit("未收到光源控制器命令回复-setTriggerLevel"));
		return false;
	}

	if(false == checkResponse(recvBuf, response, 6))
	{
		MQT_THROW_STR(QString::fromLocal8Bit("光源控制器命令回复校验和失败-setTriggerLevel"));
		return false;
	}

	return true;
}

bool CLightDriver_OPT::checkResponse(unsigned char *pRecvBuf, unsigned char *pResponse, int nLen)
{
	return true;
	for (int i = 0; i < nLen; i++)
	{
		if (pRecvBuf[i] != pResponse[i])
		{
			return false;
		}
	}

	return true;
}

void CLightDriver_OPT::checkoutSum(unsigned char* pBuf, int nLen, unsigned char& cValue)
{
		for (int i = 0; i < nLen; i++)
	{
		cValue += pBuf[i];
	}
}