|
//---------------------------------------------------------------------
|
#include <stdio.h> /*标准输入输出定义*/
|
#include <stdlib.h> /*标准函数库定义*/
|
#include <string.h>
|
#include <unistd.h> /*Unix 标准函数定义*/
|
#include <sys/types.h>
|
#include <sys/stat.h>
|
#include <fcntl.h> /*文件控制定义*/
|
#include <termios.h> /*PPSIX 终端控制定义*/
|
#include <errno.h> /*错误号定义*/
|
//---------------------------------------------------------------------
|
#include "LoRaCell.h"
|
#include "gpio_driver.h"
|
#include "Common/crc16.h"
|
#include "Common/classxml.h"
|
|
//#define EN_THREAD_WORK_DEBUG
|
#ifdef EN_THREAD_WORK_DEBUG
|
#define THREAD_WORK_DEBUG qDebug
|
#else
|
#define THREAD_WORK_DEBUG(...)
|
#endif
|
|
#define Swap16(u16) ((quint16)(((quint16)(u16) >> 8)|((quint16)(u16) << 8)))
|
#define Swap32(u32) ((quint32)(((quint32)(u32) >> 16)|((quint32)(u32) << 16)))
|
//---------------------------------------------------------------------
|
static unsigned char S_LoRaConfig[6] =
|
{
|
0x00,0xA0, //AddrH,AddrL
|
0x64, //011 00 100 UART=9600,8N1, 空速9.6kbps
|
0xC0, //11 0 000 00 分包32字节,RSSI禁用,发射功率22dbm
|
0x17, //信道23 ,实际频率 = 410.125+ch*1M = 433.125M
|
0x40 //0 1 0 0 0 000 ,禁用RSSI字节,定点传输,禁用LBT
|
};
|
|
static QMutex rs485_mutex;
|
|
//---------------------------------------------------------------------
|
LORACELL::LORACELL(const char *dev, int fre, int order)
|
{
|
memset(battVolData,0x00,sizeof(battVolData));
|
memset(battVolErrCnt,0x00,sizeof(battVolErrCnt));
|
memset(module0vol,0x00,sizeof(module0vol));
|
memset(monversion,0x00,sizeof(monversion));
|
|
memset(tx_count,0x00,sizeof(tx_count));
|
memset(rx_count,0x00,sizeof(rx_count));
|
all_tx = all_rx = 0;
|
|
FD_NRF905 = this->OpenDev(dev);
|
if (-1 == FD_NRF905)
|
qDebug("Can't Open %s\n", dev);
|
else
|
qDebug("Open %s OK!\n", dev);
|
this->SetDevAttr(FD_NRF905,9600, 8,1,'N');
|
//初始配置
|
Write_LoRa_Config(fre);
|
|
Work_Order = order;
|
Work_Num = 0;
|
BattGroup = 0;
|
EachGroupBattSum = 1;
|
EachGroupModule = 1;
|
readmode = MODE_CYCLE;
|
addr_singlemodule = 0;
|
adj_index = 0;
|
}
|
|
LORACELL::~LORACELL()
|
{
|
quit();
|
wait();
|
}
|
|
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
/**
|
*@brief 设置串口通信速率
|
*@param fd 类型 int 打开串口的文件句柄
|
*@param speed 类型 int 串口速度
|
*@return void
|
*/
|
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
static int speed_arr1[] = { B115200, B57600, B38400, B19200, B9600};
|
static int name_arr1[] = { 115200, 57600, 38400, 19200, 9600};
|
void LORACELL::set_speed(int fd, int speed)
|
{
|
int status;
|
struct termios Opt;
|
tcgetattr(fd, &Opt);
|
for ( unsigned int i= 0; i < sizeof(speed_arr1) / sizeof(int); i++)
|
{
|
if(speed == name_arr1[i])
|
{
|
tcflush(fd, TCIOFLUSH);
|
cfsetispeed(&Opt, speed_arr1[i]);
|
cfsetospeed(&Opt, speed_arr1[i]);
|
status = tcsetattr(fd, TCSANOW, &Opt);
|
if(status != 0)
|
{
|
perror("tcsetattr fd1");
|
return;
|
}
|
tcflush(fd,TCIOFLUSH);
|
}
|
}
|
}
|
//---------------------------------------------------------------------
|
/**
|
*@brief 设置串口数据位,停止位和效验位
|
*@param fd 类型 int 打开的串口文件句柄
|
*@param databits 类型 int 数据位 取值 为 7 或者8
|
*@param stopbits 类型 int 停止位 取值为 1 或者2
|
*@param parity 类型 int 效验类型 取值为N,E,O,,S
|
*/
|
//---------------------------------------------------------------------
|
int LORACELL::set_Parity(int fd,int databits,int stopbits,int parity)
|
{
|
struct termios options;
|
if(tcgetattr(fd, &options) != 0)
|
{
|
perror("SetupSerial 1");
|
return(-1);
|
}
|
|
//--------------- 二进制传输模式 -------------------------
|
options.c_iflag = 0;
|
options.c_oflag = 0;
|
//------------------------------------------------------
|
|
options.c_cflag &= ~CSIZE;
|
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);/*Input*/
|
options.c_oflag &= ~OPOST;/*Output*/
|
switch (databits) /*设置数据位数*/
|
{
|
case 7:
|
options.c_cflag |= CS7;
|
break;
|
case 8:
|
options.c_cflag |= CS8;
|
break;
|
default:
|
fprintf(stderr,"Unsupported data size\n");
|
return (-1);
|
}
|
switch (parity)
|
{
|
case 'n':
|
case 'N':
|
options.c_cflag &= ~PARENB; /* Clear parity enable */
|
options.c_iflag &= ~INPCK; /* Enable parity checking */
|
break;
|
case 'o':
|
case 'O':
|
options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/
|
options.c_iflag |= INPCK; /* Disnable parity checking */
|
break;
|
case 'e':
|
case 'E':
|
options.c_cflag |= PARENB; /* Enable parity */
|
options.c_cflag &= ~PARODD; /* 转换为偶效验*/
|
options.c_iflag |= INPCK; /* Disnable parity checking */
|
break;
|
case 'S':
|
case 's': /*as no parity*/
|
options.c_cflag &= ~PARENB;
|
options.c_cflag &= ~CSTOPB;
|
break;
|
default:
|
fprintf(stderr,"Unsupported parity\n");
|
return (-1);
|
}
|
/* 设置停止位*/
|
switch (stopbits)
|
{
|
case 1:
|
options.c_cflag &= ~CSTOPB;
|
break;
|
case 2:
|
options.c_cflag |= CSTOPB;
|
break;
|
default:
|
fprintf(stderr,"Unsupported stop bits\n");
|
return (-1);
|
}
|
/* Set input parity option */
|
if (parity != 'n')
|
options.c_iflag |= INPCK;
|
|
tcflush(fd, TCIFLUSH);
|
options.c_cc[VTIME] = 0; /* 0.1S */
|
options.c_cc[VMIN] = 0;
|
/* Update the options and do it NOW */
|
if (tcsetattr(fd,TCSANOW,&options) != 0)
|
{
|
perror("SetupSerial 3");
|
return (-1);
|
}
|
return (0);
|
}
|
//---------------------------------------------------------------------
|
int LORACELL::OpenDev(const char *Dev)
|
{
|
int fd = open(Dev, O_RDWR|O_NOCTTY|O_NDELAY);
|
|
return fd;
|
}
|
//---------------------------------------------------------------------
|
void LORACELL::SetDevAttr(int fd, int bitrate, char bitlen,
|
char stopbitlen, char checktype)
|
{
|
if(fd < 0)
|
return;
|
|
set_speed(fd, bitrate);
|
|
if(set_Parity(fd, bitlen, stopbitlen, checktype) < 0)
|
{
|
qDebug("Set Parity Error\n");
|
}
|
|
|
if(fcntl(fd, F_SETFL, FNDELAY) < 0)//非阻塞,覆盖前面open的属性
|
{
|
qDebug("fcntl failed\n");
|
}
|
}
|
//---------------------------------------------------------------------
|
int LORACELL::WriteDev(int fd,void *buf, int len)
|
{
|
if(fd < 0)
|
return 0;
|
|
return write(fd, (char *)buf, len);
|
}
|
//---------------------------------------------------------------------
|
int LORACELL::ReadDev(int fd,void *buf, int len)
|
{
|
if(fd < 0)
|
return 0;
|
|
char *pbuff = (char *)buf;
|
return (read(fd, pbuff, len));
|
}
|
//---------------------------------------------------------------------
|
void LORACELL::run()
|
{
|
runEn = true;
|
|
if(FD_NRF905<0)
|
runEn = false;
|
|
bool error_count[75];
|
int error_num = 0;
|
|
while(true == runEn)
|
{
|
if(readmode == MODE_CYCLE){
|
memset(error_count,0x01,sizeof(error_count));
|
for(int retry=1;retry<2;retry++){
|
error_num = retryerrormodule(retry,retry*500,error_count);
|
if(error_num == 0)
|
break;
|
}
|
msleep(1000);
|
}
|
else {
|
readMonVol(addr_singlemodule,2000);
|
msleep(1000);
|
// qDebug("addr_singlemodule = %d",addr_singlemodule);
|
readMonVersion(addr_singlemodule,2000);
|
msleep(1000);
|
}
|
|
}
|
}
|
|
void LORACELL::set_readmode(int mode){
|
readmode = mode;
|
}
|
|
void LORACELL::set_addrsingle(int addr){
|
addr_singlemodule = addr;
|
}
|
|
int LORACELL::retryerrormodule(int times, int timeout_ms, bool *error_count){
|
int error_num = 0;
|
for(int maddr=0;maddr<Work_Num;maddr++){
|
if(!error_count[maddr]){
|
continue;
|
}
|
int res = readMonVol(maddr,timeout_ms);
|
if(res == CommOK){
|
tx_count[maddr]++;
|
rx_count[maddr]++;
|
all_tx++;
|
all_rx++;
|
error_count[maddr] = false;
|
}
|
else {
|
error_count[maddr] = true;
|
error_num++;
|
if(res != CommTxError){
|
tx_count[maddr]++;
|
all_tx++;
|
}
|
}
|
// battVolData[(maddr)*4+2] = tx_count[maddr];
|
// battVolData[(maddr)*4+3] = rx_count[maddr];
|
msleep(times*100);
|
if(readmode == MODE_SINGLE)
|
break;
|
}
|
QString tmp;
|
tmp.clear();
|
for(int i=0;i<Work_Num;i++){
|
if(error_count[i]){
|
tmp.append(QString::number(i+1)).append(",");
|
}
|
}
|
|
return error_num;
|
}
|
|
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
int LORACELL::TxPacket(const unsigned char *addr, const void *datas,int fre)
|
{
|
int res = CommOK;
|
unsigned char tx_data[24] = {0};
|
unsigned char index = 0;
|
|
unsigned char *pdatas = (unsigned char *)datas;
|
|
tx_data[index++] = addr[2]; //addrH
|
tx_data[index++] = addr[3]; //addrL
|
int xd = addr[3]+fre;
|
if(xd<0)
|
xd = 0;
|
tx_data[index++] = xd;//信道
|
//tx_data[index++] = S_LoRaConfig[4]; //FM_CH
|
|
for(int n=0;n<TRDATA_len;n++)
|
{
|
tx_data[index++] = *pdatas++;
|
}
|
|
// for(int i=0;i<index;i++){
|
// qDebug("tx_data[%d]=%x",i,tx_data[i]);
|
// }
|
if(index != WriteDev(FD_NRF905, tx_data, index))
|
res = CommTxError;
|
|
return res;
|
}
|
|
unsigned char LORACELL::CheckDataIfOK(const unsigned char *ADDR,RFData m_TXData, RFData* m_RFData)
|
{
|
unsigned int crc;
|
//---------------- 数据的CRC校验和从机的地址核对 -------------------
|
crc = CRC16::CalCRC16(m_RFData, sizeof(RFData)-2);
|
if((crc==m_RFData->CRC)&&(m_RFData->CMD == m_TXData.CMD)
|
&&((m_RFData->Addr[2])==ADDR[2])&&((m_RFData->Addr[3])==ADDR[3]))
|
{
|
return 0;
|
}
|
else
|
{
|
return 1;
|
}
|
}
|
|
int LORACELL::Write_LoRa_Config(int fre)
|
{
|
QMutexLocker locker(&rs485_mutex);//添加锁
|
nowfre = fre;//0,15
|
int ret = 0;
|
Set_LoRa_Mode(3);
|
//msleep(500);如果出现设置不了频段
|
for(unsigned char n=0;n<3;n++){
|
ret = Uart_Write_LoRa_Config(fre);
|
if(0 == ret)
|
break;
|
else
|
msleep(500);
|
}
|
Set_LoRa_Mode(0);
|
//msleep(500);
|
return ret;
|
}
|
|
int LORACELL::Uart_Write_LoRa_Config(int fre)
|
{
|
int res = CommOK;
|
unsigned char tx_data[9] = {0};
|
unsigned char rx_data[9] = {0};
|
// switch(fre)
|
// {
|
// case 0: S_LoRaConfig[4] = 23; break;
|
// case 1: S_LoRaConfig[4] = 25; break;
|
// case 2: S_LoRaConfig[4] = 27; break;
|
// case 3: S_LoRaConfig[4] = 29; break;
|
// case 4: S_LoRaConfig[4] = 31; break;
|
// case 5: S_LoRaConfig[4] = 33; break;
|
// case 6: S_LoRaConfig[4] = 35; break;
|
// case 7: S_LoRaConfig[4] = 37; break;
|
// case 8: S_LoRaConfig[4] = 39; break;
|
// case 9: S_LoRaConfig[4] = 41; break;
|
// case 10: S_LoRaConfig[4] = 43; break;
|
// case 11: S_LoRaConfig[4] = 45; break;
|
// case 12: S_LoRaConfig[4] = 47; break;
|
// case 13: S_LoRaConfig[4] = 49; break;
|
// case 14: S_LoRaConfig[4] = 51; break;
|
// case 15: S_LoRaConfig[4] = 53; break;
|
|
// default:break;
|
// }
|
// switch(fre)
|
// {
|
// case 0: S_LoRaConfig[1] = 0xF0; break;
|
// case 1: S_LoRaConfig[1] = 0xF1; break;
|
// case 2: S_LoRaConfig[1] = 0xF2; break;
|
// case 3: S_LoRaConfig[1] = 0xF3; break;
|
// case 4: S_LoRaConfig[1] = 0xF4; break;
|
// case 5: S_LoRaConfig[1] = 0xF5; break;
|
// case 6: S_LoRaConfig[1] = 0xF6; break;
|
// case 7: S_LoRaConfig[1] = 0xF7; break;
|
// case 8: S_LoRaConfig[1] = 0xF8; break;
|
// case 9: S_LoRaConfig[1] = 0xF9; break;
|
// case 10: S_LoRaConfig[1] = 0xFA; break;
|
// case 11: S_LoRaConfig[1] = 0xFB; break;
|
// case 12: S_LoRaConfig[1] = 0xFC; break;
|
// case 13: S_LoRaConfig[1] = 0xFD; break;
|
// case 14: S_LoRaConfig[1] = 0xFE; break;
|
// case 15: S_LoRaConfig[1] = 0xFF; break;
|
|
// default:break;
|
// }
|
|
S_LoRaConfig[1] = 0xA0+fre;
|
S_LoRaConfig[4] = fre;
|
|
tx_data[0] = 0xC0; //指令
|
tx_data[1] = 0x00; //起始地址
|
tx_data[2] = 0x06;
|
|
for(unsigned char n=0;n<6;n++)
|
{
|
tx_data[3+n] = S_LoRaConfig[n];
|
}
|
// for(quint8 i=0;i<9;i++)
|
// qDebug("tx_data %d %x",i,tx_data[i]);
|
|
struct timeval tv;
|
fd_set rfds;
|
for(quint8 t = 0;t<1;t++) //retry 3 times
|
{
|
res = CommOK;
|
|
//flush rx buffer
|
char tmp[64] = {0};
|
while(1)
|
{
|
int len = ReadDev(FD_NRF905,tmp, 64);
|
if(len > 0)
|
continue;
|
else break;
|
}
|
|
if(sizeof(tx_data) != WriteDev(FD_NRF905, tx_data, sizeof(tx_data)))
|
res = CommTxError;
|
if(res == CommOK){
|
tv.tv_sec = 0;
|
tv.tv_usec = 200000;
|
|
FD_ZERO(&rfds);
|
FD_SET( FD_NRF905,&rfds );
|
int sres = select(FD_NRF905+1,&rfds,NULL,NULL,&tv);
|
if(sres>0){
|
if(sizeof(rx_data) == ReadDev(FD_NRF905,rx_data,sizeof(rx_data)))
|
{
|
if(rx_data[0] != 0xC1)
|
{
|
res = CommDataError;
|
}
|
for(unsigned char n=1;n<sizeof(rx_data);n++)
|
{
|
if(rx_data[n] != tx_data[n])
|
{
|
res = CommDataError;
|
break;
|
}
|
}
|
}
|
else
|
{
|
res = CommRxError;
|
}
|
}
|
else{//无返回
|
res = CommWrFailError;
|
}
|
}
|
if(res == CommOK)
|
break;
|
else
|
{
|
msleep(200);
|
qDebug("Uart_Write_LoRa_Config res = %d",res);
|
}
|
}
|
return res;
|
}
|
|
int LORACELL::Read_LoRa_Config(unsigned char *pbuf)
|
{
|
int ret = CommOK;
|
Set_LoRa_Mode(3);
|
ret = Uart_Read_LoRa_Config(pbuf);
|
Set_LoRa_Mode(0);
|
return ret;
|
}
|
|
int LORACELL::Uart_Read_LoRa_Config(unsigned char *pbuf)
|
{
|
unsigned char tx_data[3] = {0};
|
unsigned char rx_data[9] = {0};
|
int res = CommOK;
|
tx_data[0] = 0xC1; //指令
|
tx_data[1] = 0x00; //起始地址
|
tx_data[2] = 0x06;
|
|
struct timeval tv;
|
fd_set rfds;
|
for(quint8 t = 0;t<3;t++) //retry 3 times
|
{
|
res = CommOK;
|
|
//flush rx buffer
|
char tmp[64] = {0};
|
while(1)
|
{
|
int len = ReadDev(FD_NRF905,tmp, 64);
|
if(len > 0)
|
continue;
|
else break;
|
}
|
|
if(sizeof(tx_data) != WriteDev(FD_NRF905, tx_data, sizeof(tx_data)))
|
res = CommTxError;
|
if(res == CommOK){
|
tv.tv_sec = 0;
|
tv.tv_usec = 200000;
|
|
FD_ZERO(&rfds);
|
FD_SET( FD_NRF905,&rfds );
|
int sres = select(FD_NRF905+1,&rfds,NULL,NULL,&tv);
|
if(sres>0){
|
if(sizeof(rx_data) == ReadDev(FD_NRF905,rx_data,sizeof(rx_data)))
|
{
|
for(unsigned char n=0;n<sizeof(tx_data);n++)
|
{
|
if(rx_data[n] != tx_data[n])
|
{
|
res = CommDataError;
|
break;
|
}
|
}
|
memcpy(pbuf,&rx_data[3],6);
|
}
|
else
|
{
|
res = CommRxError;
|
}
|
}
|
else{//无返回
|
res = CommWrFailError;
|
}
|
}
|
if(res == CommOK)
|
break;
|
else
|
{
|
msleep(200);
|
qDebug("Uart_Read_LoRa_Config res = %d",res);
|
}
|
}
|
return res;
|
}
|
|
void LORACELL::Set_LoRa_Mode(const unsigned char mode){
|
msleep(20); //延时,重要
|
switch(mode)
|
{
|
case 0: //M1_0; M0_0;break; //透传模式
|
{
|
gpio_set_level(GPIO_INDEX_TX,GPIO_LEVEL_LOW);
|
gpio_set_level(GPIO_INDEX_RX,GPIO_LEVEL_LOW);
|
break;
|
}
|
case 3: //M1_1; M0_1;break; //休眠模式,可配置参数
|
{
|
gpio_set_level(GPIO_INDEX_TX,GPIO_LEVEL_HIGH);
|
gpio_set_level(GPIO_INDEX_RX,GPIO_LEVEL_HIGH);
|
break;
|
}
|
default:break;
|
}
|
msleep(20); //延时,重要
|
}
|
|
void LORACELL::setWorkNum(int num_g,int num_eachm){
|
BattGroup = num_g;
|
EachGroupBattSum = num_eachm;
|
if((EachGroupBattSum%4) == 0)
|
EachGroupModule = EachGroupBattSum/4;
|
else EachGroupModule = EachGroupBattSum/4 + 1;
|
|
Work_Num = EachGroupModule*num_g;
|
}
|
|
void LORACELL::setWorkParam(int param1, int param2){
|
//编号顺序、频段
|
Work_Order = param1;
|
if(param2>=1 && param2 <=16)
|
Write_LoRa_Config(param2);
|
memset(battVolData,0x00,sizeof(battVolData));
|
memset(battVolErrCnt,0x00,sizeof(battVolErrCnt));
|
}
|
|
int LORACELL::setWorkFre(int fre){
|
int res = CommOK;
|
if(fre>=0 && fre <=15)
|
res = Write_LoRa_Config(fre);
|
memset(battVolData,0x00,sizeof(battVolData));
|
memset(battVolErrCnt,0x00,sizeof(battVolErrCnt));
|
return res;
|
}
|
|
int LORACELL::getWorkFre(){
|
int workfre = -1;
|
unsigned char rx_data[6] = {0};
|
if(Read_LoRa_Config(rx_data)==CommOK){
|
switch(rx_data[4])
|
{
|
case 23: workfre = 0; break;
|
case 25: workfre = 1; break;
|
case 27: workfre = 2; break;
|
case 29: workfre = 3; break;
|
case 31: workfre = 4; break;
|
case 33: workfre = 5; break;
|
case 35: workfre = 6; break;
|
case 37: workfre = 7; break;
|
case 39: workfre = 8; break;
|
case 41: workfre = 9; break;
|
case 43: workfre = 10; break;
|
case 45: workfre = 11; break;
|
case 47: workfre = 12; break;
|
case 49: workfre = 13; break;
|
case 51: workfre = 14; break;
|
case 53: workfre = 15; break;
|
|
default:break;
|
}
|
}
|
return workfre+1;
|
}
|
|
bool LORACELL::readMonVol(int maddr,int timeout_ms){
|
QMutexLocker locker(&rs485_mutex);
|
int res = CommOK;
|
RFData TX_Data;
|
RFData RX_Data;
|
quint8 tx_addr[4] = {0xAB,0xCD,0x00,0x01};
|
if(readmode == MODE_CYCLE){
|
tx_addr[3] = maddr+1;
|
}
|
else {
|
tx_addr[3] = maddr;
|
}
|
memset(&TX_Data,0,sizeof(TX_Data));
|
memset(&RX_Data,0,sizeof(RX_Data));
|
|
TX_Data.Addr[0] = 0xAB;
|
TX_Data.Addr[1] = 0xCD;
|
TX_Data.Addr[2] = S_LoRaConfig[4];
|
TX_Data.Addr[3] = S_LoRaConfig[1];
|
TX_Data.CMD = CMD_READVOL;
|
TX_Data.CRC = CRC16::CalCRC16(&TX_Data,sizeof(TX_Data)-2);
|
|
res = TxPacket(tx_addr,&TX_Data,nowfre);
|
if(res == CommOK){
|
res = ReadData(&RX_Data,sizeof(RX_Data),timeout_ms/5);
|
}
|
if(res == CommOK){
|
if(CheckDataIfOK(tx_addr,TX_Data,&RX_Data)!=0)//校验失败
|
res = CommDataError;
|
}
|
if(res == CommOK){
|
for(int i=0;i<4;i++){
|
if(RX_Data.VolData[i]>MON_MAX_VOL)
|
RX_Data.VolData[i] = MON_MAX_VOL;
|
}
|
if(readmode == MODE_CYCLE){
|
ClassXML::set_battVolData(maddr,RX_Data.VolData,battVolData,
|
Work_Order,EachGroupBattSum,EachGroupModule,BattGroup);
|
if(battVolErrCnt[maddr] != 0)
|
{
|
//qDebug("clean maddr=%d, battVolErrCnt=%d",maddr+1,battVolErrCnt[maddr]);
|
battVolErrCnt[maddr] = 0;
|
}
|
}
|
else {
|
module0vol[0] = RX_Data.VolData[0];
|
module0vol[1] = RX_Data.VolData[1];
|
module0vol[2] = RX_Data.VolData[2];
|
module0vol[3] = RX_Data.VolData[3];
|
}
|
}
|
else {
|
if(readmode == MODE_CYCLE){
|
if(++battVolErrCnt[maddr] > 4)
|
{
|
//数据清零
|
Rx_Data_RF temp;
|
memset(&temp,0,sizeof(temp));
|
temp.Addr = maddr+1;
|
ClassXML::set_battVolData(maddr,temp.VolData,battVolData,Work_Order,
|
EachGroupBattSum,EachGroupModule,BattGroup);
|
battVolErrCnt[maddr] = 0;
|
}
|
}
|
else {
|
for(int b=0;b<4;b++)
|
{
|
module0vol[b] = 0;
|
}
|
}
|
}
|
return res;
|
}
|
|
bool LORACELL::readMonVersion(int maddr,int timeout_ms){
|
QMutexLocker locker(&rs485_mutex);
|
int res = CommOK;
|
RFData TX_Data;
|
RFData RX_Data;
|
quint8 tx_addr[4] = {0xAB,0xCD,0x00,0x01};
|
tx_addr[3] = maddr;
|
|
memset(&TX_Data,0,sizeof(TX_Data));
|
memset(&RX_Data,0,sizeof(RX_Data));
|
|
TX_Data.Addr[0] = 0xAB;
|
TX_Data.Addr[1] = 0xCD;
|
TX_Data.Addr[2] = S_LoRaConfig[4];
|
TX_Data.Addr[3] = S_LoRaConfig[1];
|
TX_Data.CMD = CMD_VERSION;
|
TX_Data.CRC = CRC16::CalCRC16(&TX_Data,sizeof(TX_Data)-2);
|
|
res = TxPacket(tx_addr,&TX_Data,nowfre);
|
if(res == CommOK){
|
res = ReadData(&RX_Data,sizeof(RX_Data),timeout_ms/5);
|
}
|
if(res == CommOK){
|
if(CheckDataIfOK(tx_addr,TX_Data,&RX_Data)!=0)//校验失败
|
res = CommDataError;
|
}
|
if(res == CommOK){
|
if(readmode == MODE_CYCLE){
|
;
|
}
|
else {
|
monversion[0] = RX_Data.VolData[0];
|
monversion[1] = RX_Data.VolData[1];
|
monversion[2] = RX_Data.VolData[2];
|
monversion[3] = RX_Data.VolData[3];
|
}
|
}
|
else {
|
memset(monversion,0x00,sizeof(monversion));
|
}
|
return res;
|
}
|
|
bool LORACELL::setmoduleaddr(int num, int num2){//目标模块,设置地址
|
QMutexLocker locker(&rs485_mutex);
|
int res = CommOK;
|
RFData TX_Data;
|
RFData RX_Data;
|
quint8 tx_addr[4] = {0xAB,0xCD,0x00,0x00};
|
tx_addr[3] = num;
|
|
memset(&TX_Data,0,sizeof(TX_Data));
|
|
TX_Data.Addr[0] = 0xAB;
|
TX_Data.Addr[1] = 0xCD;
|
TX_Data.Addr[2] = S_LoRaConfig[4];
|
TX_Data.Addr[3] = S_LoRaConfig[1];
|
TX_Data.CMD = CMD_SETMONADDR;//0x00A2
|
TX_Data.VolData[0] = 0xCDAB;
|
TX_Data.VolData[1] = (num2<<8);
|
TX_Data.VolData[2] = 0;
|
TX_Data.VolData[3] = 0;
|
TX_Data.CRC = CRC16::CalCRC16(&TX_Data,sizeof(TX_Data)-2);
|
|
struct timeval tv;
|
fd_set rfds;
|
for(quint8 t = 0;t<3;t++) //retry 3 times
|
{
|
memset(&RX_Data,0,sizeof(RX_Data));
|
res = CommOK;
|
|
//flush rx buffer
|
char tmp[64] = {0};
|
while(1)
|
{
|
int len = ReadDev(FD_NRF905,tmp, 64);
|
if(len > 0)
|
continue;
|
else break;
|
}
|
|
res = TxPacket(tx_addr,&TX_Data,nowfre);
|
if(res == CommOK){
|
tv.tv_sec = 2;
|
tv.tv_usec = 0;
|
|
FD_ZERO(&rfds);
|
FD_SET( FD_NRF905,&rfds );
|
int sres = select(FD_NRF905+1,&rfds,NULL,NULL,&tv);
|
if(sres>0){
|
if(sizeof(RX_Data) != ReadDev(FD_NRF905,&RX_Data,sizeof(RX_Data))){//读取失败
|
res = CommRxError;
|
}
|
else {
|
tx_addr[3] = num2;
|
if(CheckDataIfOK(tx_addr,TX_Data,&RX_Data)!=0)//校验失败
|
res = CommDataError;
|
}
|
}
|
else{//无返回
|
res = CommWrFailError;
|
}
|
}
|
|
if(res == CommOK)
|
break;
|
else
|
{
|
msleep(200);
|
qDebug("setmoduleaddr res = %d",res);
|
}
|
}
|
return res;
|
}
|
|
bool LORACELL::setmodulefre(int num, int num2){
|
QMutexLocker locker(&rs485_mutex);
|
int res = CommOK;
|
RFData TX_Data;
|
RFData RX_Data;
|
quint8 tx_addr[4] = {0xAB,0xCD,0x00,0x00};
|
tx_addr[3] = num;
|
|
memset(&TX_Data,0,sizeof(TX_Data));
|
memset(&RX_Data,0,sizeof(RX_Data));
|
|
TX_Data.Addr[0] = 0xAB;
|
TX_Data.Addr[1] = 0xCD;
|
TX_Data.Addr[2] = S_LoRaConfig[4];
|
TX_Data.Addr[3] = S_LoRaConfig[1];
|
TX_Data.CMD = CMD_SETMONFRE;//0x00A8
|
TX_Data.VolData[0] = 0xCDAB;
|
TX_Data.VolData[1] = (num2<<8);
|
TX_Data.VolData[2] = 0;
|
TX_Data.VolData[3] = 0;
|
TX_Data.CRC = CRC16::CalCRC16(&TX_Data,sizeof(TX_Data)-2);
|
|
struct timeval tv;
|
fd_set rfds;
|
for(quint8 t = 0;t<3;t++) //retry 3 times
|
{
|
res = CommOK;
|
|
//flush rx buffer
|
char tmp[64] = {0};
|
while(1)
|
{
|
int len = ReadDev(FD_NRF905,tmp, 64);
|
if(len > 0)
|
continue;
|
else break;
|
}
|
|
res = TxPacket(tx_addr,&TX_Data,nowfre);
|
if(res == CommOK){
|
tv.tv_sec = 2;
|
tv.tv_usec = 0;
|
|
FD_ZERO(&rfds);
|
FD_SET( FD_NRF905,&rfds );
|
int sres = select(FD_NRF905+1,&rfds,NULL,NULL,&tv);
|
if(sres>0){
|
if(sizeof(RX_Data) != ReadDev(FD_NRF905,&RX_Data,sizeof(RX_Data))){//读取失败
|
res = CommRxError;
|
}
|
else {
|
if(CheckDataIfOK(tx_addr,TX_Data,&RX_Data)!=0)//校验失败
|
res = CommDataError;
|
}
|
}
|
else{//无返回
|
res = CommWrFailError;
|
}
|
}
|
if(res == CommOK)
|
break;
|
else
|
{
|
msleep(200);
|
qDebug("setmodulefre res = %d",res);
|
}
|
}
|
return res;
|
}
|
|
void LORACELL::GetBattVolData(void *data)
|
{
|
int monnum = BattGroup*EachGroupBattSum;
|
for(int i=monnum;i<MONOMER_NUM_MAX;i++)
|
battVolData[i]=0;
|
memcpy(data,battVolData,sizeof(battVolData));
|
}
|
|
int LORACELL::ReadData(void *buf, const int len, const int timeout_5ms)
|
{
|
quint16 rx_len = 0;
|
quint16 rx_time_out = 0;
|
quint8 *p_rxdata = (quint8 *)buf;
|
|
quint8 rx_databuff[512] = {0};
|
quint16 bytes = 16;
|
|
while(1)
|
{
|
int rlen = ReadDev(FD_NRF905,&rx_databuff, bytes);
|
//qDebug("rlen = %d",rlen);
|
if(rlen > 0){
|
for(int i=0;i<rlen;i++)
|
{
|
if(rx_len < len){
|
p_rxdata[rx_len++] = rx_databuff[i];
|
//qDebug("p_rxdata[%d]=%x",rx_len,p_rxdata[rx_len-1]);
|
}
|
else
|
break;
|
}
|
|
rx_time_out = 0;
|
}
|
else{
|
if(rx_len>0 && rx_time_out>20) //收到了部分字节后,字节之间超时 x*5ms
|
{
|
//qDebug("rx_len = %d",rx_len);
|
return CommRxError;
|
}
|
//qDebug("rx_time_out = %d timeout_5ms = %d",rx_time_out,timeout_5ms);
|
if(rx_time_out > timeout_5ms) //接收超时 timeout_5ms * 5ms
|
{
|
return CommWrFailError;
|
}
|
}
|
|
if(rx_len >= len){
|
return CommOK;
|
}
|
|
rx_time_out++;
|
|
msleep(5);
|
}
|
}
|
|
//一个单体模块的四节单体一起校准
|
bool LORACELL::adjmon_offset(int num, int vol){//模块地址,偏移量(差值)mV
|
QMutexLocker locker(&rs485_mutex);
|
int res = CommOK;
|
RFData TX_Data;
|
RFData RX_Data;
|
quint8 tx_addr[4] = {0xAB,0xCD,0x00,0x00};
|
unsigned int TXmoduladdr = 0;
|
TXmoduladdr = num;//单体模块地址
|
|
tx_addr[3] = (unsigned char)TXmoduladdr;
|
tx_addr[2] = (unsigned char)(TXmoduladdr>>8);
|
|
memset(&TX_Data,0,sizeof(TX_Data));
|
if(vol<0)
|
vol = 0;
|
TX_Data.Addr[0] = 0xAB;
|
TX_Data.Addr[1] = 0xCD;
|
TX_Data.Addr[2] = S_LoRaConfig[4];
|
TX_Data.Addr[3] = S_LoRaConfig[1];
|
TX_Data.CMD = CMD_SetADJOffSet;
|
TX_Data.VolData[0] = vol;
|
TX_Data.VolData[1] = 0;
|
TX_Data.VolData[2] = 0;
|
TX_Data.VolData[3] = 0;
|
TX_Data.CRC = CRC16::CalCRC16(&TX_Data,sizeof(TX_Data)-2);
|
|
struct timeval tv;
|
fd_set rfds;
|
for(quint8 t = 0;t<3;t++) //retry 3 times
|
{
|
memset(&RX_Data,0,sizeof(RX_Data));
|
res = CommOK;
|
|
//flush rx buffer
|
char tmp[64] = {0};
|
while(1)
|
{
|
int len = ReadDev(FD_NRF905,tmp, 64);
|
if(len > 0)
|
continue;
|
else break;
|
}
|
|
res = TxPacket(tx_addr,&TX_Data,nowfre);
|
if(res == CommOK){
|
tv.tv_sec = 0;
|
tv.tv_usec = 2000000;
|
|
FD_ZERO(&rfds);
|
FD_SET( FD_NRF905,&rfds );
|
int sres = select(FD_NRF905+1,&rfds,NULL,NULL,&tv);
|
if(sres>0){
|
if(sizeof(RX_Data) != ReadDev(FD_NRF905,&RX_Data,sizeof(RX_Data))){//读取失败
|
res = CommRxError;
|
}
|
else {
|
if(CheckDataIfOK(tx_addr,TX_Data,&RX_Data)!=0)//校验失败
|
res = CommDataError;
|
}
|
}
|
else{//无返回
|
res = CommWrFailError;
|
}
|
}
|
|
if(res == CommOK)
|
break;
|
else
|
{
|
msleep(200);
|
qDebug("adjmon_offset res = %d",res);
|
}
|
}
|
if(res == CommOK)
|
return true;
|
else
|
return false;
|
}
|
|
bool LORACELL::adjmon_slope(int num, int vol){//模块地址,斜率值*10000
|
QMutexLocker locker(&rs485_mutex);
|
int res = CommOK;
|
RFData TX_Data;
|
RFData RX_Data;
|
quint8 tx_addr[4] = {0xAB,0xCD,0x00,0x00};
|
unsigned int TXmoduladdr = 0;
|
TXmoduladdr = num;//单体模块地址
|
|
tx_addr[3] = (unsigned char)TXmoduladdr;
|
tx_addr[2] = (unsigned char)(TXmoduladdr>>8);
|
|
memset(&TX_Data,0,sizeof(TX_Data));
|
|
TX_Data.Addr[0] = 0xAB;
|
TX_Data.Addr[1] = 0xCD;
|
TX_Data.Addr[2] = S_LoRaConfig[4];
|
TX_Data.Addr[3] = S_LoRaConfig[1];
|
TX_Data.CMD = CMD_SetADJSlope;
|
TX_Data.VolData[0] = vol;
|
TX_Data.VolData[1] = 0;
|
TX_Data.VolData[2] = 0;
|
TX_Data.VolData[3] = 0;
|
TX_Data.CRC = CRC16::CalCRC16(&TX_Data,sizeof(TX_Data)-2);
|
|
struct timeval tv;
|
fd_set rfds;
|
for(quint8 t = 0;t<3;t++) //retry 3 times
|
{
|
memset(&RX_Data,0,sizeof(RX_Data));
|
res = CommOK;
|
|
//flush rx buffer
|
char tmp[64] = {0};
|
while(1)
|
{
|
int len = ReadDev(FD_NRF905,tmp, 64);
|
if(len > 0)
|
continue;
|
else break;
|
}
|
|
res = TxPacket(tx_addr,&TX_Data,nowfre);
|
if(res == CommOK){
|
tv.tv_sec = 0;
|
tv.tv_usec = 2000000;
|
|
FD_ZERO(&rfds);
|
FD_SET( FD_NRF905,&rfds );
|
int sres = select(FD_NRF905+1,&rfds,NULL,NULL,&tv);
|
if(sres>0){
|
if(sizeof(RX_Data) != ReadDev(FD_NRF905,&RX_Data,sizeof(RX_Data))){//读取失败
|
res = CommRxError;
|
}
|
else {
|
if(CheckDataIfOK(tx_addr,TX_Data,&RX_Data)!=0)//校验失败
|
res = CommDataError;
|
}
|
}
|
else{//无返回
|
res = CommWrFailError;
|
}
|
}
|
|
if(res == CommOK)
|
break;
|
else
|
{
|
msleep(200);
|
qDebug("adjmon_slope res = %d",res);
|
}
|
}
|
if(res == CommOK)
|
return true;
|
else
|
return false;
|
}
|
|
void LORACELL::setadjindex(int param){
|
adj_index = param;
|
}
|
|
int LORACELL::AdjMonoVol(const quint8 index,const quint16 vol,int index_type)
|
{
|
QMutexLocker locker(&rs485_mutex);
|
int res = CommOK;
|
int get_index = index;
|
if(index_type == 1)
|
get_index = adj_index;
|
quint8 addr_index = ClassXML::getMonModuleAddr(get_index,EachGroupModule,EachGroupBattSum);//计算单体号对应的模块地址
|
|
if(addr_index >= Work_Num)
|
res = CommTxError;
|
|
if(res == CommOK){
|
RFData TX_Data;
|
RFData RX_Data;
|
quint8 tx_addr[4] = {0xAB,0xCD,0x00,0x00};
|
unsigned int TXmoduladdr = 0;
|
TXmoduladdr = addr_index+1;//单体模块地址
|
|
tx_addr[3] = (unsigned char)TXmoduladdr;
|
tx_addr[2] = (unsigned char)(TXmoduladdr>>8);
|
|
memset(&TX_Data,0,sizeof(TX_Data));
|
|
TX_Data.Addr[0] = 0xAB;
|
TX_Data.Addr[1] = 0xCD;
|
TX_Data.Addr[2] = S_LoRaConfig[4];
|
TX_Data.Addr[3] = S_LoRaConfig[1];
|
TX_Data.CMD = CMD_ADJMONVOL;
|
for(int i=0;i<4;i++)
|
TX_Data.VolData[i] = 0;
|
|
ClassXML::set_addr_VolData(addr_index,TX_Data.VolData,battVolData,
|
Work_Order,EachGroupBattSum,EachGroupModule,BattGroup);
|
|
ClassXML::set_adj_vol(addr_index,get_index,TX_Data.VolData,vol,
|
Work_Order,EachGroupBattSum,EachGroupModule);
|
|
TX_Data.CRC = CRC16::CalCRC16(&TX_Data,sizeof(TX_Data)-2);
|
|
struct timeval tv;
|
fd_set rfds;
|
for(quint8 t = 0;t<3;t++) //retry 3 times
|
{
|
memset(&RX_Data,0,sizeof(RX_Data));
|
res = CommOK;
|
|
//flush rx buffer
|
char tmp[64] = {0};
|
while(1)
|
{
|
int len = ReadDev(FD_NRF905,tmp, 64);
|
if(len > 0)
|
continue;
|
else break;
|
}
|
|
res = TxPacket(tx_addr,&TX_Data,nowfre);
|
if(res == CommOK){
|
tv.tv_sec = 0;
|
tv.tv_usec = 2000000;
|
|
FD_ZERO(&rfds);
|
FD_SET( FD_NRF905,&rfds );
|
int sres = select(FD_NRF905+1,&rfds,NULL,NULL,&tv);
|
if(sres>0){
|
if(sizeof(RX_Data) != ReadDev(FD_NRF905,&RX_Data,sizeof(RX_Data))){//读取失败
|
res = CommRxError;
|
}
|
else {
|
if(CheckDataIfOK(tx_addr,TX_Data,&RX_Data)!=0)//校验失败
|
res = CommDataError;
|
}
|
}
|
else{//无返回
|
res = CommWrFailError;
|
}
|
}
|
|
if(res == CommOK)
|
break;
|
else
|
{
|
msleep(200);
|
}
|
}
|
}
|
if(res == CommOK)
|
return true;
|
else
|
return false;
|
}
|
|
QString LORACELL::get_version(){
|
QString ver = QString("version: %1.%2.%3").arg(QString::number(monversion[2]))
|
.arg(QString::number(monversion[1]))
|
.arg(QString::number(monversion[0]));
|
return ver;
|
}
|
|
void LORACELL::getmodulevol(void *data){
|
memcpy(data,module0vol,sizeof(module0vol));
|
}
|