#include "remote_ctrl.h" #include 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()<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;ninfo[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); }