#include "lock.h" #include "config.h" #include #include extern config *pconfig; lock::lock(QObject *parent) : QThread(parent) { QLoggingCategory::setFilterRules("qt.serialport*=true"); } void lock::slot_set_thread_stop(void) { this->threadstatus = false; } #define PRESET_VALUE 0xFFFF #define POLYNOMIAL 0xA001 quint16 lock::uiCrc16Cal(QByteArray &data, quint8 count) { quint8 ucI,ucJ; quint16 uiCrcValue = PRESET_VALUE; for(ucI = 0; ucI < count; ucI++) { uiCrcValue = uiCrcValue ^ (quint8)(data.at(ucI)); for(ucJ = 0; ucJ < 8; ucJ++) { if(uiCrcValue & 0x0001) { uiCrcValue = (uiCrcValue >> 1) ^ POLYNOMIAL; } else { uiCrcValue = (uiCrcValue >> 1); } } } return uiCrcValue; } // 发送数据给下位机 void lock::sendData(QByteArray &sendData) { // qDebug() << "sendData: " << sendData.toHex(); quint16 crc = uiCrc16Cal(sendData, sendData.size()); // 输出CRC16校验和 // qDebug() << "CRC16:" << QString::number(crc, 16).toUpper(); sendData.append((quint8)crc); sendData.append((quint8)(crc >> 8)); // qDebug() << "QByteArray: " << sendData.toHex(); // 发送数据帧 // this->devserial->clear(QSerialPort::AllDirections); qint64 bytesWritten = this->devserial->write(sendData); if (bytesWritten == -1) { qWarning() << "Failed to write data:" << this->devserial->errorString(); } // 等待数据写入完成 if (!this->devserial->waitForBytesWritten(1000)) { qWarning() << "Timeout: Failed to write data within 5000 milliseconds."; } } // 读取下位机发来数据 bool lock::readData(QByteArray *data, quint16 timeout) { if(!this->devserial->waitForReadyRead(timeout)) { return false; } msleep(100); *data = this->devserial->readAll(); qDebug() << "readData: " << data->toHex(); quint8 addr = data->at(0); if(addr == ELECTLOCKBOARD_ADDR || addr == 0x90) { quint16 crc1 = uiCrc16Cal(*data, data->size() - 2); quint16 crc2 = quint8(data->at(data->size() - 1)); crc2 <<= 8; crc2 += quint8(data->at(data->size() - 2)); if(crc1 == crc2) { return true; } } return false; } bool lock::openSerial(void) { this->devserial->setPortName(pconfig->lockPort); // 设定串口名称,根据你的系统修改 this->devserial->setBaudRate(pconfig->lockBaud); this->devserial->setDataBits(QSerialPort::Data8); this->devserial->setParity(QSerialPort::NoParity); this->devserial->setStopBits(QSerialPort::OneStop); this->devserial->setFlowControl(QSerialPort::NoFlowControl); // this->devserial->setTextModeEnabled(true); if (this->devserial->open(QIODevice::ReadWrite)) { qDebug() << "电磁锁控板串口打开成功"; this->devserial->setReadBufferSize(1024); //信号与槽函数关联 // connect(devserial, &QSerialPort::readyRead, this, &uart::slot_uartReadData); return true; } return false; } void lock::slot_uartinfo_change(void) { if(openPort == true) { this->devserial->close(); openPort = false; workstat = lockWorkStat::init; } } bool lock::slot_openLock(void) { if(workstat != lockWorkStat::init) { workstat = lockWorkStat::controlLock; return true; } else{ return false; } } void lock::getBoardType(void) { quint8 dataArray[] = {ELECTLOCKBOARD_ADDR, 0x03, DEVTYPE_REG >> 8, DEVTYPE_REG, 0x00, 0x01}; QByteArray ba(reinterpret_cast(dataArray), sizeof(dataArray)); this->sendData(ba); QByteArray data; if(this->devserial->waitForReadyRead(1000)) { msleep(200); data = this->devserial->readAll(); int size = data.size(); int idx = 0; if(size == 7) { QByteArray lockData = data.mid(idx, 5); // qDebug() << "lockData: " << lockData.toHex(); quint16 crc1 = uiCrc16Cal(lockData, 5); quint16 crc2 = quint8(data.at(6)); crc2 <<= 8; crc2 += quint8(data.at(5)); if(crc1 != crc2) { return; } if((quint8)(lockData.at(0)) != ELECTLOCKBOARD_ADDR) { return; } if(lockData.at(1) != 0x03) { return; } if(lockData.at(2) != 0x02) { return; } // quint16 boardtype = 0x00; // boardtype = lockData.at(3); // boardtype <<= 8; // boardtype += lockData.at(4); // if(boardtype != DEVTYPE_ELECTLOCK) // { // break; // } workstat = lockWorkStat::readLockStat; emit signal_lock_run(true); } } else{ qWarning() << "Timeout: No data received within 1000 milliseconds."; } } void lock::openLock(void) { // quint8 dataArray[] = {0x90, 0x06, 0x00, 0x08, 0x00, 0x01}; quint8 dataArray[] = {ELECTLOCKBOARD_ADDR, 0x06, LOCKCONTRO_REG >> 8, LOCKCONTRO_REG, 0x03, 0x00}; QByteArray ba(reinterpret_cast(dataArray), sizeof(dataArray)); this->sendData(ba); QByteArray data; if(true == this->readData(&data, 1000)) { workstat = lockWorkStat::readLockStat; } } void lock::openLight(void) { quint8 dataArray[] = {ELECTLOCKBOARD_ADDR, 0x06, LIGHTCONTROL_REG >> 8, LIGHTCONTROL_REG, 0x03, 0x00}; if(setRightlightStat == true) { dataArray[5] = dataArray[5] | 0x02; } if(setLeftlightStat == true) { dataArray[5] = dataArray[5] | 0x01; } QByteArray ba(reinterpret_cast(dataArray), sizeof(dataArray)); this->sendData(ba); QByteArray data; if(true == this->readData(&data, 1000)) { workstat = lockWorkStat::readLockStat; } } void lock::readLockStat(void) { quint8 dataArray[] = {ELECTLOCKBOARD_ADDR, 0x03, LOCKCONTRO_REG >> 8, LOCKCONTRO_REG, 0x00, 0x01}; QByteArray ba(reinterpret_cast(dataArray), sizeof(dataArray)); this->sendData(ba); QByteArray data; if(this->devserial->waitForReadyRead(1000)) { msleep(200); data = this->devserial->readAll(); int size = data.size(); int idx = 0; if(size == 7) { QByteArray lockData = data.mid(idx, 5); // qDebug() << "lockData: " << lockData.toHex(); quint16 crc1 = uiCrc16Cal(lockData, 5); quint16 crc2 = quint8(data.at(6)); crc2 <<= 8; crc2 += quint8(data.at(5)); if(crc1 != crc2) { return; } if((quint8)(lockData.at(0)) != ELECTLOCKBOARD_ADDR) { return; } if(lockData.at(1) != 0x03) { return; } if(lockData.at(2) != 0x02) { return; } bool right = false; bool left = false; left = ((lockData.at(4) & 0x01) == 0x01)?true:false; right = ((lockData.at(4) & 0x02) == 0x02)?true:false; if(left != leftLockStat || right != rightLockStat) { leftLockStat = left; rightLockStat = right; setLeftlightStat = (leftLockStat == false)?true:false; setRightlightStat = (rightLockStat == false)?true:false; workstat = lockWorkStat::controlLight; emit signal_lockStat(leftLockStat, rightLockStat); } } } } void lock::run() { this->devserial = new QSerialPort; while(this->threadstatus) { if(pconfig->lockInit == true) { if(openPort == false) { openPort = this->openSerial(); } else{ switch(workstat) { case lockWorkStat::init:getBoardType();break; case lockWorkStat::readLockStat:readLockStat();break; case lockWorkStat::controlLock:openLock();break; case lockWorkStat::controlLight:openLight();break; } } } msleep(20); } if(openPort == true) { this->devserial->close(); } qDebug() << "lock thread exit!"; }