#include "remote_ctrl.h"
|
#include <QDebug>
|
|
|
quint8 Remote_Ctrl::devAddr = 1;
|
|
Remote_Ctrl::Remote_Ctrl(Work_Thread *wt)
|
{
|
workThread = wt;
|
}
|
|
void Remote_Ctrl::setRemoteDevAddr(const quint8 addr)
|
{
|
devAddr = addr;
|
}
|
|
bool Remote_Ctrl::CheckLen(FRAME_DATA *recv)
|
{
|
if(recv->Len >= FRAMEHEAD && recv->Len <= sizeof(FRAME_DATA)){
|
return true;
|
}
|
|
return false;
|
}
|
|
bool Remote_Ctrl::CheckSYNCode(FRAME_DATA *recv)
|
{
|
bool res = false;
|
quint32 sCode = recv->SYNCode;
|
if((sCode&SYSCODECHECK) == SYSCODE){
|
quint32 id = (sCode&SYSCODECHECKID);
|
id = (quint8)(id>>24);
|
if( (devAddr==id) || (0xAA==id) || (0xFF==id) ){
|
res = true;
|
}
|
}
|
|
return res;
|
}
|
|
bool Remote_Ctrl::CheckCRC(FRAME_DATA *recv)
|
{
|
unsigned short Temp = recv->CRC;
|
recv->CRC =0;
|
recv->CRC = CRC16::CalCRC16(recv,recv->Len);
|
//qDebug("crc1 = 0x%X,crc2 = 0x%X",recv->CRC,Temp);
|
if(recv->CRC == Temp)
|
return true;
|
|
return false;
|
}
|
|
bool Remote_Ctrl::ReadFrameHead(FRAME_DATA *recv, FRAME_DATA *sent)
|
{
|
if(CheckSYNCode(recv) == true)
|
{
|
if(CheckLen(recv) == false){
|
sent->RecState = LEN_ERR;
|
}
|
|
return true;
|
}
|
else
|
return false;
|
}
|
|
bool Remote_Ctrl::ReadFrameData(FRAME_DATA *recv, FRAME_DATA *sent)
|
{
|
// qDebug("******* OK *********");
|
// return true;
|
|
|
|
|
if(ReadFrameHead(recv,sent) == true){
|
|
if(sent->RecState == SUCCEED){
|
if(CheckCRC(recv) == false){
|
sent->RecState = CRC_ERR;
|
}
|
}
|
|
return true;
|
}
|
|
return false;
|
}
|
|
quint16 Remote_Ctrl::getVersion(FRAME_DATA *recv,FRAME_DATA *sent)
|
{
|
sent->RecState = recv->RecState;
|
QString battname = Phone_Version;
|
memcpy(sent->info,battname.toUtf8().data(),battname.toUtf8().length());
|
|
return battname.toUtf8().length();
|
}
|
|
quint16 Remote_Ctrl::getMonData(FRAME_DATA *sent)
|
{
|
COMM_MON_DATA mondata;
|
memset(&mondata,0,sizeof(COMM_MON_DATA));
|
|
mondata.GroupVol[0] = workThread->modTestData.ADCVdc/10;
|
mondata.GroupCur[0] = workThread->modTestData.ADCIdc/10;
|
mondata.BattStatus[0] = workThread->testStateData.workState + 0x80;
|
|
quint16 battsum = workThread->packData.cell_count;
|
quint16 tempsum = workThread->packData.temp_count;
|
|
mondata.tempcount = tempsum;
|
|
memcpy(mondata.MonomerVol,workThread->packData.cell_vol,battsum*sizeof(quint16));
|
memcpy(mondata.MonomerTemp,workThread->packData.cell_temp,tempsum*sizeof(quint16));
|
|
quint8 *pinfo = (quint8 *)sent->info;
|
memcpy(pinfo,&mondata, HEAD_MONDATA + battsum*sizeof(quint16));
|
pinfo += HEAD_MONDATA + battsum*sizeof(quint16);
|
memcpy(pinfo,&(mondata.MonomerTemp), tempsum*sizeof(quint16));
|
|
return (HEAD_MONDATA + battsum*sizeof(quint16) + tempsum*sizeof(quint16));
|
}
|
|
quint16 Remote_Ctrl::getTestData(FRAME_DATA *sent)
|
{
|
COMM_TEST_DATA testdata;
|
memset(&testdata,0,sizeof(testdata));
|
|
testdata.OnlineVol = 0;
|
testdata.GroupVol = workThread->modTestData.ADCVdc;
|
testdata.testStartTime = workThread->getTestStartTime();
|
testdata.testtime = workThread->testStateData.testTime;
|
|
testdata.KeyState = 0;
|
|
if(workThread->testStateData.workState == WORK_STATE_DISCHG)
|
testdata.monomerCount = 0;
|
else if(workThread->testStateData.workState == WORK_STATE_CHARGE)
|
testdata.monomerCount = 0;
|
|
testdata.test_curr = workThread->modTestData.ADCIdc;
|
testdata.AllCap = workThread->testStateData.testCap;
|
testdata.SMaxIndex = 0;
|
testdata.SMaxVol = 0;
|
testdata.SMinIndex = 0;
|
testdata.SMinVol = 0;
|
testdata.cycleTimes = 0;
|
testdata.celltemp[0] = workThread->packData.cell_temp[0];
|
testdata.celltemp[1] = workThread->packData.cell_temp[1];
|
testdata.celltemp[2] = workThread->packData.cell_temp[2];
|
testdata.celltemp[3] = workThread->packData.cell_temp[3];
|
|
testdata.stoptype = workThread->testStateData.alarmState;
|
|
testdata.startfailedtype = workThread->testStateData.startState;
|
|
testdata.pack_vol_inside = workThread->packData.pack_vol_inside;
|
testdata.pack_vol_outside = workThread->packData.pack_vol_outside;
|
testdata.pack_current = workThread->packData.pack_current;
|
testdata.soc = workThread->packData.soc;
|
testdata.soh = workThread->packData.soh;
|
testdata.error[0] = workThread->packData.error[0];
|
testdata.error[1] = workThread->packData.error[1];
|
|
memcpy(sent->info,&testdata,sizeof(COMM_TEST_DATA));
|
|
return sizeof(COMM_TEST_DATA);
|
}
|
|
quint16 Remote_Ctrl::getCommTestParam(FRAME_DATA *sent)
|
{
|
COMM_TEST_PARAM comm_param;
|
memset(&comm_param,0x00,sizeof(COMM_TEST_PARAM));
|
|
comm_param.test_mode = 0; //放电类型;
|
comm_param.acstop_op = 0; //停电处理
|
comm_param.nominal_cap = 100; //标称容量
|
comm_param.hourly_rate = 10; //小时率
|
comm_param.preset_cur = workThread->testParam.disParam.dis_curr/10; //放电电流, 分辨率0.1
|
comm_param.preset_cap = workThread->testParam.disParam.dis_cap/10; //放电容量,分辨率0.1AH
|
comm_param.preset_time = workThread->testParam.disParam.dis_time; //预放时间,分钟
|
comm_param.mon_lower = workThread->testParam.disParam.cell_vol_low/10; //单体下限,分辨率0.01
|
comm_param.group_lower = workThread->testParam.disParam.sum_vol_low/10; //组端下限,分辨率0.1
|
comm_param.dischg_soc = workThread->testParam.disParam.dis_soc;
|
comm_param.mon_number = 30; //单体数量
|
comm_param.group_number = 1; //组数
|
comm_param.lower_number = 1; //下限个数
|
comm_param.mon_vol = 32; //只取值1.2, 2.0,6.0,12.0,3.2,3.7
|
comm_param.dischg_mode = 0; //放电模式:0恒流放电 1恒功率放电
|
comm_param.pre_power = 0; //预放功率
|
comm_param.pre_res = 0; //放电阻值
|
comm_param.chrg_curr = workThread->testParam.chgParam.chg_curr/10; //充电电流 分辨率0.1
|
comm_param.chrg_vol = workThread->testParam.chgParam.sum_vol_high/10; //充电电压 分辨率0.1
|
comm_param.chrg_vol_2 = workThread->testParam.chgParam.sum_vol_high/10; //浮充电压 分辨率0.1//范围小于充电电压
|
comm_param.chrg_cap = workThread->testParam.chgParam.chg_cap/10; //充电容量 分辨率0.1AH
|
comm_param.chrg_time = workThread->testParam.chgParam.chg_time; //充电时长
|
comm_param.chrg_time_2 = workThread->testParam.chgParam.chg_time; //浮充时长
|
comm_param.chrg_stopcurr = workThread->testParam.curr_end/10; //截止电流 分辨率0.1
|
comm_param.grp_uppervol = workThread->testParam.chgParam.sum_vol_high/10; //组端上限 分辨率0.1
|
comm_param.mon_uppervol = workThread->testParam.chgParam.cell_vol_high/10; //单体上限 分辨率0.01
|
comm_param.charge_soc = workThread->testParam.chgParam.chg_soc;
|
comm_param.mon_uppernum = 1; //单体上限数量
|
comm_param.chrg_temp = workThread->testParam.temp_high; //充电过温 分辨率0.1
|
comm_param.dischrg_temp = workThread->testParam.temp_high; //放电过温 分辨率0.1
|
comm_param.cycle_start = TestTypeDischarge - workThread->testParam.test_type; //活化起点 0放电 ,1充电
|
comm_param.cycle_times = 1; //活化次数
|
comm_param.waitdis_time = 1; //充完静置
|
comm_param.waitchr_time = 1; //放完静置
|
comm_param.cell_diffvol = workThread->testParam.cell_vol_diff;
|
|
comm_param.BattPackAddr = workThread->packParam.pack_devaddr;
|
|
memcpy(sent->info,&comm_param,sizeof(COMM_TEST_PARAM));
|
|
return sizeof(COMM_TEST_PARAM);
|
}
|
|
quint16 Remote_Ctrl::getCommPackParam(FRAME_DATA *sent)
|
{
|
memcpy(sent->info,&(workThread->packParam),sizeof(PACK_PARAM));
|
|
return sizeof(PACK_PARAM);
|
}
|
|
quint16 Remote_Ctrl::getPackBarcode(FRAME_DATA *sent)
|
{
|
QString barcode = workThread->packBarcode;
|
memcpy(sent->info,barcode.toUtf8().data(),barcode.toUtf8().length());
|
|
return barcode.toUtf8().length();
|
}
|
|
void Remote_Ctrl::setPackBarcode(FRAME_DATA *recv){
|
|
int len = recv->Len - FRAMEHEAD;
|
|
if(len>0 && len<250){
|
char barcode[256];
|
|
barcode[len] = '\0';
|
|
memcpy(barcode,recv->info,len);
|
|
QString barcodestr(barcode);
|
|
qDebug()<<barcodestr;
|
|
workThread->setPackBarcodeStr(barcodestr);
|
}
|
}
|
|
quint16 Remote_Ctrl::exePassthroughData(FRAME_DATA *recv,FRAME_DATA *sent)
|
{
|
int len = recv->Len-FRAMEHEAD;
|
|
workThread->rs485_Pack->lock_RS485();
|
|
// for(int n=0;n<8;n++){
|
// qDebug("tx - 0x%X",recv->info[n]);
|
// }
|
// qDebug("-----");
|
|
int rxlen = workThread->rs485_Pack->Tx_Rx_Data(recv->info,len,sent->info,300);
|
|
// for(int n=0;n<8;n++){
|
// qDebug("rx - 0x%X",sent->info[n]);
|
// }
|
|
if(0 == rxlen){
|
sent->RecState = PACK_COMM_ERR;
|
}
|
|
workThread->rs485_Pack->unlock_RS485();
|
|
return rxlen;
|
}
|
|
quint16 Remote_Ctrl::getPackDataModbus(FRAME_DATA *recv,FRAME_DATA *sent)
|
{
|
quint16 len = 0;
|
|
/*
|
for(int n=0;n<8;n++){
|
qDebug("0x%X",recv->info[n]);
|
}
|
qDebug("************************************************");
|
*/
|
|
if( (recv->info[0]==0x06) && (recv->info[1]==0x03) ){
|
quint16 regaddr = recv->info[2]*256+recv->info[3];
|
quint16 regnum = recv->info[4]*256+recv->info[5];
|
|
sent->info[0] = recv->info[0];
|
sent->info[1] = recv->info[1];
|
|
if(regnum > 124){
|
regnum = 124;
|
}
|
|
if( (regaddr>=Halo_RegAddr_Version && regaddr<(Halo_RegAddr_Version+Halo_RegCount_Version))
|
|| (regaddr>=Halo_RegAddr_Soc && regaddr<(Halo_RegAddr_Soc+Halo_RegCount_Soc)) ){
|
|
quint16 *pdata = 0;
|
|
if(regaddr>=Halo_RegAddr_Version && regaddr<(Halo_RegAddr_Version+Halo_RegCount_Version)){
|
if((regaddr+regnum)>(Halo_RegAddr_Version+Halo_RegCount_Version)){
|
regnum = (Halo_RegAddr_Version+Halo_RegCount_Version)-regaddr;
|
}
|
|
pdata = (quint16 *)(&(workThread->packData_Origin.soft_version));
|
pdata += regaddr-Halo_RegAddr_Version;
|
}
|
else if(regaddr>=Halo_RegAddr_Soc && regaddr<(Halo_RegAddr_Soc+Halo_RegCount_Soc)){
|
if((regaddr+regnum)>(Halo_RegAddr_Soc+Halo_RegCount_Soc)){
|
regnum = (Halo_RegAddr_Soc+Halo_RegCount_Soc)-regaddr;
|
}
|
|
pdata = (quint16 *)(&(workThread->packData_Origin.soc));
|
pdata += regaddr-Halo_RegAddr_Soc;
|
|
}
|
|
sent->info[2] = regnum*2;
|
for(qint8 n=0;n<regnum;n++){
|
//qDebug("regaddr = %d,regnum = %d,n = %d,data = %d",regaddr,regnum,n+1,pdata[n]);
|
sent->info[3+n*2] = pdata[n]/256;
|
sent->info[4+n*2] = pdata[n]%256;
|
}
|
//qDebug("*******************************************************************");
|
unsigned short crc = CRC16::CalModbusCRC16(sent->info, 3+2*regnum);
|
sent->info[3+2*regnum] = (quint8)(crc>>8);
|
sent->info[4+2*regnum] = (quint8)crc;
|
|
len = 5+2*regnum;
|
}
|
else{
|
sent->RecState = PACK_COMM_ERR;
|
}
|
}
|
else{
|
sent->RecState = PACK_COMM_ERR;
|
}
|
|
return len;
|
}
|
|
void Remote_Ctrl::setCommTestParam(FRAME_DATA *recv)
|
{
|
COMM_TEST_PARAM comm_param;
|
memcpy(&comm_param,recv->info,sizeof(COMM_TEST_PARAM));
|
|
TEST_PARAM testparam;
|
testparam = workThread->testParam;
|
|
testparam.disParam.dis_curr = comm_param.preset_cur*10;
|
testparam.disParam.dis_cap = comm_param.preset_cap*10;
|
testparam.disParam.dis_time = comm_param.preset_time;
|
testparam.disParam.cell_vol_low = comm_param.mon_lower*10;
|
testparam.disParam.sum_vol_low = comm_param.group_lower*10;
|
testparam.disParam.dis_soc = comm_param.dischg_soc;
|
|
testparam.chgParam.chg_curr = comm_param.chrg_curr*10;
|
testparam.chgParam.sum_vol_high = comm_param.chrg_vol*10;
|
testparam.chgParam.chg_cap = comm_param.chrg_cap*10;
|
testparam.chgParam.chg_time = comm_param.chrg_time;
|
testparam.chgParam.cell_vol_high = comm_param.mon_uppervol*10;
|
testparam.chgParam.chg_soc = comm_param.charge_soc;
|
testparam.curr_end = comm_param.chrg_stopcurr*10;
|
|
testparam.cell_vol_diff = comm_param.cell_diffvol;
|
testparam.temp_high = comm_param.chrg_temp;
|
//testparam.test_type = TestTypeDischarge-comm_param.cycle_start;
|
|
workThread->saveTestParam(testparam);
|
}
|
|
void Remote_Ctrl::setCommPackParam(FRAME_DATA *recv)
|
{
|
PACK_PARAM comm_param;
|
memcpy(&comm_param,recv->info,sizeof(PACK_PARAM));
|
|
if(comm_param.pack_devaddr < 1){
|
comm_param.pack_devaddr = 1;
|
}
|
|
//PACK_PARAM packparam;
|
//packparam = workThread->packParam;
|
|
//packparam = comm_param;
|
|
workThread->savePackParam(comm_param);
|
}
|
|
bool Remote_Ctrl::processRxData(FRAME_DATA *recv, FRAME_DATA *sent,const quint8 contype)
|
{
|
//如果需要蓝牙和网络同时使用,可加上 QMutexLocker locker(&ble_net_mutex);
|
|
//qDebug("RX: SYNCode = 0x%X,Len = 0x%X,CMD = 0x%X,RecState = 0x%X,type = 0x%X,workState = 0x%X,Alarm = 0x%X,CRC = 0x%X",recv->SYNCode,recv->Len,recv->CMD,recv->RecState,recv->type,recv->workState,recv->Alarm,recv->CRC);
|
|
if(ReadFrameData(recv, sent)){
|
remote_state = workThread->remoteState;
|
passthrough_Stat = workThread->passthroughState;
|
|
//if( (0==remote_state.enter_slave) && (recv->CMD != EnterSlave) )
|
//sent->RecState = SLAVEMODE_ERR;
|
|
//透传中,只能响应透传和退出透传指令
|
if( (1==passthrough_Stat.passing) && (recv->CMD!=EnterPackPassthrough) && (recv->CMD!=ExitPackPassthrough) ){
|
sent->RecState = SYSTEM_WORKING;
|
}
|
//进入透传时,必须非工作状态
|
else if( (0==passthrough_Stat.passing) && (recv->CMD==EnterPackPassthrough) ){
|
if( (workThread->testStateData.workState != WORK_STATE_STOPPED)
|
|| (1==passthrough_Stat.execing) ){
|
sent->RecState = PASSTHROUGH_ERR;
|
}
|
}
|
|
if(sent->RecState == SUCCEED){
|
|
remote_state.heart_ticks = 0;
|
|
remote_state.conn_type = contype;
|
|
remote_state.enter_slave = 1;
|
|
switch (recv->CMD){
|
case Heartbeat:{
|
}
|
break;
|
case ExitSlave:{
|
remote_state.enter_slave = 0;
|
remote_state.to_workpage = 0;
|
remote_state.conn_type = 0;
|
}
|
break;
|
case EnterSlave:{
|
remote_state.enter_slave = 1;
|
}
|
break;
|
|
case GetCellData:{
|
sent->Db1 = workThread->packData.cell_count/256;
|
sent->Db2 = workThread->packData.cell_count%256;
|
}
|
break;
|
|
case SetDischargeParam:
|
case SetChargeParam:{
|
//if(sizeof(COMM_TEST_PARAM) == (recv->Len - FRAMEHEAD))
|
{
|
setCommTestParam(recv);
|
}
|
}
|
break;
|
|
case GetDischargeParam:
|
case GetChargeParam:{
|
}
|
break;
|
|
case StartDischarge:
|
case PausetDischarge:
|
case StartCharge:
|
case PauseCharge:
|
case StopDischarge:
|
case StopCharge:{
|
remote_state.to_workpage = 1;
|
|
TEST_PARAM testparam = workThread->testParam;
|
if(recv->CMD == StartDischarge){
|
if(WORK_STATE_STOPPED == workThread->testStateData.workState){
|
if(START_OK == workThread->startErrorCheck()){
|
if(TestTypeDischarge != testparam.test_type){
|
testparam.test_type = TestTypeDischarge;
|
workThread->saveTestParam(testparam);
|
}
|
|
workThread->setWorkThreadCMD(workThread->CMD_StartTest);
|
}
|
else{
|
sent->RecState = START_ERR;
|
}
|
}
|
else{
|
sent->RecState = START_ERR;
|
}
|
}
|
else if(recv->CMD == StartCharge){
|
if(WORK_STATE_STOPPED == workThread->testStateData.workState){
|
if(START_OK == workThread->startErrorCheck()){
|
|
if(TestTypeCharge != testparam.test_type){
|
testparam.test_type = TestTypeCharge;
|
workThread->saveTestParam(testparam);
|
}
|
|
workThread->setWorkThreadCMD(workThread->CMD_StartTest);
|
}
|
else{
|
sent->RecState = START_ERR;
|
}
|
}
|
else{
|
sent->RecState = START_ERR;
|
}
|
}
|
else{
|
if(WORK_STATE_STOPPED != workThread->testStateData.workState){
|
workThread->setWorkThreadCMD(workThread->CMD_StopTest);
|
}
|
}
|
}
|
break;
|
|
case GetDischargeData:
|
case GetChargeData:{
|
sent->Db2 = 0;
|
}
|
break;
|
|
case GetVersion:{
|
}
|
break;
|
|
case EnterPackPassthrough:{
|
passthrough_Stat.passing = 1;
|
workThread->rs485_Pack->pausePackComm();
|
workThread->setPassthroughState(passthrough_Stat);
|
}
|
break;
|
|
case EasyPackPassthrough:{
|
}
|
break;
|
|
case ExitPackPassthrough:{
|
passthrough_Stat.passing = 0;
|
workThread->rs485_Pack->remsumPackComm();
|
workThread->setPassthroughState(passthrough_Stat);
|
}
|
break;
|
|
case GetPackParam:
|
case GetPackBarcode:
|
case GetPackData:{
|
}
|
break;
|
|
case SetPackParam:{
|
//if(sizeof(PACK_PARAM) == (recv->Len - FRAMEHEAD))
|
{
|
setCommPackParam(recv);
|
}
|
}
|
break;
|
|
case SetPackBarcode:{
|
//qDebug("Set Pack Barcode....");
|
setPackBarcode(recv);
|
}
|
break;
|
|
case ActivePack:{
|
//qDebug("Active The Pack....");
|
workThread->setWorkThreadCMD(workThread->CMD_SetActivePack);
|
}
|
break;
|
|
|
|
|
}
|
|
workThread->setRemoteState(remote_state);
|
|
prepareSendData(recv,sent);
|
}
|
|
return true;
|
}
|
|
return false;
|
}
|
|
void Remote_Ctrl::prepareSendData(FRAME_DATA *recv,FRAME_DATA *sent)
|
{
|
sent->SYNCode = SYSCODE | (devAddr<<24); //recv->SYNCode;
|
sent->CMD = recv->CMD;
|
sent->Len = FRAMEHEAD;
|
sent->TType = 0x80 + workThread->getPageIndex();
|
sent->workState = workThread->testStateData.workState;
|
sent->Alarm = workThread->testStateData.alarmState;
|
|
switch (recv->CMD){
|
case Heartbeat:
|
case ExitSlave:{
|
|
}
|
break;
|
|
case EnterSlave:{
|
sent->Db1 = 0x20;
|
}
|
break;
|
|
case GetCellData:{
|
sent->Len += getMonData(sent);
|
}
|
break;
|
|
case GetDischargeParam:
|
case GetChargeParam:{
|
sent->Len += getCommTestParam(sent);
|
}
|
break;
|
|
case GetDischargeData:
|
case GetChargeData:{
|
sent->Len += getTestData(sent);
|
}
|
break;
|
|
case GetVersion:{
|
sent->Len += getVersion(recv,sent);
|
}
|
break;
|
|
case EasyPackPassthrough:
|
case EnterPackPassthrough:{
|
sent->Len += exePassthroughData(recv,sent);
|
}
|
break;
|
|
case GetPackData:{
|
sent->Len += getPackDataModbus(recv,sent);
|
}
|
break;
|
|
case GetPackParam:{
|
sent->Len += getCommPackParam(sent);
|
}
|
break;
|
|
case GetPackBarcode:{
|
sent->Len += getPackBarcode(sent);
|
}
|
break;
|
|
case ActivePack:{
|
}
|
break;
|
}
|
|
sent->CRC = CRC16::CalCRC16(sent,sent->Len);
|
}
|