Initial commit (project based on widgets)
This commit is contained in:
894
bmsinterface.cpp
Normal file
894
bmsinterface.cpp
Normal file
@@ -0,0 +1,894 @@
|
||||
/**
|
||||
Original copyright 2018 Benjamin Vedder benjamin@vedder.se and the VESC Tool project ( https://github.com/vedderb/vesc_tool )
|
||||
|
||||
Forked to:
|
||||
Copyright 2018 Danny Bokma github@diebie.nl (https://github.com/DieBieEngineering/DieBieMS-Tool)
|
||||
|
||||
Now forked to:
|
||||
Copyright 2019 - 2020 Kevin Dionne kevin.dionne@ennoid.me (https://github.com/EnnoidMe/ENNOID-BMS-Tool)
|
||||
|
||||
This file is part of ENNOID-BMS Tool.
|
||||
|
||||
ENNOID-BMS Tool is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ENNOID-BMS Tool is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "bmsinterface.h"
|
||||
#include <QDebug>
|
||||
#include <QHostInfo>
|
||||
#include <QFileInfo>
|
||||
#include <QThread>
|
||||
#include <QEventLoop>
|
||||
#include <utility.h>
|
||||
#include <cmath>
|
||||
#include <QRegularExpression>
|
||||
|
||||
#ifdef HAS_SERIALPORT
|
||||
#include <QSerialPortInfo>
|
||||
#endif
|
||||
|
||||
BMSInterface::BMSInterface(QObject *parent) : QObject(parent)
|
||||
{
|
||||
|
||||
mbmsConfig = new ConfigParams(this);
|
||||
mInfoConfig = new ConfigParams(this);
|
||||
mPacket = new Packet(this);
|
||||
mCommands = new Commands(this);
|
||||
|
||||
// Compatible firmwares
|
||||
mFwVersionReceived = false;
|
||||
mFwRetries = 0;
|
||||
mFwPollCnt = 0;
|
||||
mFwTxt = "x.x";
|
||||
mIsUploadingFw = false;
|
||||
|
||||
mTimer = new QTimer(this);
|
||||
mTimer->setInterval(20);
|
||||
mTimer->start();
|
||||
|
||||
mLastConnType = static_cast<conn_t>(QSettings().value("connection_type", CONN_NONE).toInt());
|
||||
mLastTcpServer = mSettings.value("tcp_server", "127.0.0.1").toString();
|
||||
mLastTcpPort = mSettings.value("tcp_port", 65102).toInt();
|
||||
|
||||
mSendCanBefore = false;
|
||||
mCanIdBefore = 0;
|
||||
mWasConnected = false;
|
||||
mAutoconnectOngoing = false;
|
||||
mAutoconnectProgress = 0.0;
|
||||
|
||||
// Serial
|
||||
#ifdef HAS_SERIALPORT
|
||||
mSerialPort = new QSerialPort(this);
|
||||
mLastSerialPort = "";
|
||||
mLastSerialBaud = 0;
|
||||
|
||||
connect(mSerialPort, SIGNAL(readyRead()),this, SLOT(serialDataAvailable()));
|
||||
connect(mSerialPort, SIGNAL(error(QSerialPort::SerialPortError)),this, SLOT(serialPortError(QSerialPort::SerialPortError)));
|
||||
#endif
|
||||
|
||||
// TCP
|
||||
mTcpSocket = new QTcpSocket(this);
|
||||
mTcpConnected = false;
|
||||
mLastTcpServer = QSettings().value("tcp_server").toString();
|
||||
mLastTcpPort = QSettings().value("tcp_port").toInt();
|
||||
|
||||
connect(mTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpInputDataAvailable()));
|
||||
connect(mTcpSocket, SIGNAL(connected()), this, SLOT(tcpInputConnected()));
|
||||
connect(mTcpSocket, SIGNAL(disconnected()),this, SLOT(tcpInputDisconnected()));
|
||||
connect(mTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),this, SLOT(tcpInputError(QAbstractSocket::SocketError)));
|
||||
|
||||
// BLE
|
||||
|
||||
mBleUart = new BleUart(this);
|
||||
mLastBleAddr = QSettings().value("ble_addr").toString();
|
||||
|
||||
int size = mSettings.beginReadArray("bleNames");
|
||||
for (int i = 0; i < size; ++i) {
|
||||
mSettings.setArrayIndex(i);
|
||||
QString address = mSettings.value("address").toString();
|
||||
QString name = mSettings.value("name").toString();
|
||||
mBleNames.insert(address, name);
|
||||
}
|
||||
mSettings.endArray();
|
||||
|
||||
connect(mBleUart, SIGNAL(dataRx(QByteArray)), this, SLOT(bleDataRx(QByteArray)));
|
||||
|
||||
mCommands->setbmsConfig(mbmsConfig);
|
||||
|
||||
// Other signals/slots
|
||||
connect(mTimer, SIGNAL(timeout()), this, SLOT(timerSlot()));
|
||||
connect(mPacket, SIGNAL(dataToSend(QByteArray&)),this, SLOT(packetDataToSend(QByteArray&)));
|
||||
connect(mPacket, SIGNAL(packetReceived(QByteArray&)),this, SLOT(packetReceived(QByteArray&)));
|
||||
connect(mCommands, SIGNAL(dataToSend(QByteArray&)),this, SLOT(cmdDataToSend(QByteArray&)));
|
||||
connect(mCommands, SIGNAL(fwVersionReceived(int,int,QString,QByteArray)),this, SLOT(fwVersionReceived(int,int,QString,QByteArray)));
|
||||
connect(mCommands, SIGNAL(ackReceived(QString)), this, SLOT(ackReceived(QString)));
|
||||
connect(mbmsConfig, SIGNAL(updated()), this, SLOT(bmsconfUpdated()));
|
||||
connect(mbmsConfig, SIGNAL(stored()), this, SLOT(bmsconfStored()));
|
||||
}
|
||||
|
||||
BMSInterface::~BMSInterface()
|
||||
{
|
||||
mSettings.beginWriteArray("bleNames");
|
||||
|
||||
QHashIterator<QString, QString> i(mBleNames);
|
||||
int ind = 0;
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
mSettings.setArrayIndex(ind);
|
||||
mSettings.setValue("address", i.key());
|
||||
mSettings.setValue("name", i.value());
|
||||
ind++;
|
||||
}
|
||||
|
||||
mSettings.endArray();
|
||||
}
|
||||
|
||||
Commands *BMSInterface::commands() const
|
||||
{
|
||||
return mCommands;
|
||||
}
|
||||
|
||||
ConfigParams *BMSInterface::bmsConfig()
|
||||
{
|
||||
return mbmsConfig;
|
||||
}
|
||||
|
||||
ConfigParams *BMSInterface::infoConfig()
|
||||
{
|
||||
return mInfoConfig;
|
||||
}
|
||||
|
||||
QStringList BMSInterface::getSupportedFirmwares()
|
||||
{
|
||||
QList<QPair<int, int> > fwPairs = getSupportedFirmwarePairs();
|
||||
QStringList fws;
|
||||
|
||||
for (int i = 0;i < fwPairs.size();i++) {
|
||||
QString tmp;
|
||||
tmp.sprintf("%d.%d", fwPairs.at(i).first, fwPairs.at(i).second);
|
||||
fws.append(tmp);
|
||||
}
|
||||
return fws;
|
||||
}
|
||||
|
||||
QList<QPair<int, int> > BMSInterface::getSupportedFirmwarePairs()
|
||||
{
|
||||
QList<QPair<int, int> > fws;
|
||||
|
||||
ConfigParam *p = mInfoConfig->getParam("fw_version");
|
||||
|
||||
if (p) {
|
||||
QStringList strs = p->enumNames;
|
||||
|
||||
for (int i = 0;i < strs.size();i++) {
|
||||
QStringList mami = strs.at(i).split(".");
|
||||
QPair<int, int> fw = qMakePair(mami.at(0).toInt(), mami.at(1).toInt());
|
||||
fws.append(fw);
|
||||
}
|
||||
}
|
||||
|
||||
return fws;
|
||||
}
|
||||
|
||||
QString BMSInterface::getFirmwareNow()
|
||||
{
|
||||
return mFwTxt;
|
||||
}
|
||||
|
||||
void BMSInterface::emitStatusMessage(const QString &msg, bool isGood)
|
||||
{
|
||||
emit statusMessage(msg, isGood);
|
||||
}
|
||||
|
||||
void BMSInterface::emitMessageDialog(const QString &title, const QString &msg, bool isGood, bool richText)
|
||||
{
|
||||
emit messageDialog(title, msg, isGood, richText);
|
||||
}
|
||||
|
||||
bool BMSInterface::fwRx()
|
||||
{
|
||||
return mFwVersionReceived;
|
||||
}
|
||||
|
||||
|
||||
void BMSInterface::storeSettings()
|
||||
{
|
||||
mSettings.beginWriteArray("bleNames");
|
||||
QHashIterator<QString, QString> i(mBleNames);
|
||||
int ind = 0;
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
mSettings.setArrayIndex(ind);
|
||||
mSettings.setValue("address", i.key());
|
||||
mSettings.setValue("name", i.value());
|
||||
ind++;
|
||||
}
|
||||
mSettings.endArray();
|
||||
|
||||
mSettings.beginWriteArray("profiles");
|
||||
for (int i = 0; i < mProfiles.size(); ++i) {
|
||||
MCCONF_TEMP cfg = mProfiles.value(i).value<MCCONF_TEMP>();
|
||||
mSettings.setArrayIndex(i);
|
||||
mSettings.setValue("current_min_scale", cfg.current_min_scale);
|
||||
mSettings.setValue("current_max_scale", cfg.current_max_scale);
|
||||
mSettings.setValue("erpm_or_speed_min", cfg.erpm_or_speed_min);
|
||||
mSettings.setValue("erpm_or_speed_max", cfg.erpm_or_speed_max);
|
||||
mSettings.setValue("duty_min", cfg.duty_min);
|
||||
mSettings.setValue("duty_max", cfg.duty_max);
|
||||
mSettings.setValue("watt_min", cfg.watt_min);
|
||||
mSettings.setValue("watt_max", cfg.watt_max);
|
||||
mSettings.setValue("name", cfg.name);
|
||||
}
|
||||
mSettings.endArray();
|
||||
|
||||
mSettings.beginWriteArray("pairedUuids");
|
||||
for (int i = 0;i < mPairedUuids.size();i++) {
|
||||
mSettings.setArrayIndex(i);
|
||||
mSettings.setValue("uuid", mPairedUuids.at(i));
|
||||
}
|
||||
mSettings.endArray();
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAS_BLUETOOTH
|
||||
BleUart *BMSInterface::bleDevice()
|
||||
{
|
||||
return mBleUart;
|
||||
}
|
||||
|
||||
void BMSInterface::storeBleName(QString address, QString name)
|
||||
{
|
||||
mBleNames.insert(address, name);
|
||||
}
|
||||
|
||||
QString BMSInterface::getBleName(QString address)
|
||||
{
|
||||
QString res;
|
||||
if(mBleNames.contains(address)) {
|
||||
res = mBleNames[address];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
QString BMSInterface::getLastBleAddr() const
|
||||
{
|
||||
return mLastBleAddr;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool BMSInterface::isPortConnected()
|
||||
{
|
||||
bool res = false;
|
||||
|
||||
#ifdef HAS_SERIALPORT
|
||||
if (mSerialPort->isOpen()) {
|
||||
res = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mTcpConnected) {
|
||||
res = true;
|
||||
}
|
||||
|
||||
if (mBleUart->isConnected()) {
|
||||
res = true;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void BMSInterface::disconnectPort()
|
||||
{
|
||||
#ifdef HAS_SERIALPORT
|
||||
if(mSerialPort->isOpen()) {
|
||||
mSerialPort->close();
|
||||
updateFwRx(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mTcpConnected) {
|
||||
mTcpSocket->close();
|
||||
updateFwRx(false);
|
||||
}
|
||||
|
||||
if (mBleUart->isConnected()) {
|
||||
mBleUart->disconnectBle();
|
||||
updateFwRx(false);
|
||||
}
|
||||
|
||||
mFwRetries = 0;
|
||||
}
|
||||
|
||||
bool BMSInterface::reconnectLastPort()
|
||||
{
|
||||
if (mLastConnType == CONN_SERIAL) {
|
||||
#ifdef HAS_SERIALPORT
|
||||
return connectSerial(mLastSerialPort, mLastSerialBaud);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
} else if (mLastConnType == CONN_TCP) {
|
||||
connectTcp(mLastTcpServer, mLastTcpPort);
|
||||
return true;
|
||||
} else if (mLastConnType == CONN_BLE) {
|
||||
mBleUart->startConnect(mLastBleAddr);
|
||||
return true;
|
||||
} else {
|
||||
#ifdef HAS_SERIALPORT
|
||||
QList<VSerialInfo_t> ports = listSerialPorts();
|
||||
if (!ports.isEmpty()) {
|
||||
return connectSerial(ports.first().systemPath);
|
||||
} else {
|
||||
emit messageDialog(tr("Reconnect"), tr("No ports found"), false, false);
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
emit messageDialog(tr("Reconnect"),
|
||||
tr("Please specify the connection manually "
|
||||
"the first time you are connecting."),
|
||||
false, false);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool BMSInterface::autoconnect()
|
||||
{
|
||||
bool res = false;
|
||||
|
||||
#ifdef HAS_SERIALPORT
|
||||
QList<VSerialInfo_t> ports = listSerialPorts();
|
||||
mAutoconnectOngoing = true;
|
||||
mAutoconnectProgress = 0.0;
|
||||
|
||||
disconnectPort();
|
||||
disconnect(mCommands, SIGNAL(fwVersionReceived(int,int,QString,QByteArray)),
|
||||
this, SLOT(fwVersionReceived(int,int,QString,QByteArray)));
|
||||
|
||||
for (int i = 0;i < ports.size();i++) {
|
||||
VSerialInfo_t serial = ports[i];
|
||||
|
||||
if (!connectSerial(serial.systemPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QEventLoop loop;
|
||||
QTimer timeoutTimer;
|
||||
timeoutTimer.setSingleShot(true);
|
||||
timeoutTimer.start(500);
|
||||
connect(mCommands, SIGNAL(fwVersionReceived(int,int,QString,QByteArray)), &loop, SLOT(quit()));
|
||||
connect(&timeoutTimer, SIGNAL(timeout()), &loop, SLOT(quit()));
|
||||
loop.exec();
|
||||
|
||||
if (timeoutTimer.isActive()) {
|
||||
// If the timer is still running a firmware version was received.
|
||||
res = true;
|
||||
break;
|
||||
} else {
|
||||
mAutoconnectProgress = (double)i / (double)ports.size();
|
||||
emit autoConnectProgressUpdated(mAutoconnectProgress, false);
|
||||
disconnectPort();
|
||||
}
|
||||
}
|
||||
|
||||
connect(mCommands, SIGNAL(fwVersionReceived(int,int,QString,QByteArray)),
|
||||
this, SLOT(fwVersionReceived(int,int,QString,QByteArray)));
|
||||
#endif
|
||||
|
||||
emit autoConnectProgressUpdated(1.0, true);
|
||||
emit autoConnectFinished();
|
||||
mAutoconnectOngoing = false;
|
||||
return res;
|
||||
}
|
||||
|
||||
QString BMSInterface::getConnectedPortName()
|
||||
{
|
||||
QString res = tr("Not connected");
|
||||
bool connected = false;
|
||||
|
||||
#ifdef HAS_SERIALPORT
|
||||
if (mSerialPort->isOpen()) {
|
||||
res = tr("Connected (serial) to %1").arg(mSerialPort->portName());
|
||||
connected = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mTcpConnected) {
|
||||
res = tr("Connected (TCP) to %1:%2").arg(mLastTcpServer).arg(mLastTcpPort);
|
||||
connected = true;
|
||||
}
|
||||
|
||||
if (mBleUart->isConnected()) {
|
||||
res = tr("Connected (BLE) to %1").arg(mLastBleAddr);
|
||||
connected = true;
|
||||
}
|
||||
|
||||
if (connected && mCommands->isLimitedMode()) {
|
||||
res += tr(", limited mode");
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool BMSInterface::connectSerial(QString port, int baudrate)
|
||||
{
|
||||
#ifdef HAS_SERIALPORT
|
||||
mLastSerialPort = port;
|
||||
mLastSerialBaud = baudrate;
|
||||
setLastConnectionType(CONN_SERIAL);
|
||||
|
||||
bool found = false;
|
||||
for (VSerialInfo_t ser: listSerialPorts()) {
|
||||
if (ser.systemPath == port) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
emit statusMessage(tr("Invalid serial port: %1").arg(port), false);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(mSerialPort->isOpen()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Maybe this test works on other OSes as well
|
||||
#ifdef Q_OS_UNIX
|
||||
QFileInfo fi(port);
|
||||
if (fi.exists()) {
|
||||
if (!fi.isWritable()) {
|
||||
emit statusMessage(tr("Serial port is not writable"), false);
|
||||
emit serialPortNotWritable(port);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
mSerialPort->setPortName(port);
|
||||
mSerialPort->open(QIODevice::ReadWrite);
|
||||
|
||||
if(!mSerialPort->isOpen()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mSerialPort->setBaudRate(baudrate);
|
||||
mSerialPort->setDataBits(QSerialPort::Data8);
|
||||
mSerialPort->setParity(QSerialPort::NoParity);
|
||||
mSerialPort->setStopBits(QSerialPort::OneStop);
|
||||
mSerialPort->setFlowControl(QSerialPort::NoFlowControl);
|
||||
|
||||
// For nrf
|
||||
mSerialPort->setRequestToSend(true);
|
||||
mSerialPort->setDataTerminalReady(true);
|
||||
QThread::msleep(5);
|
||||
mSerialPort->setDataTerminalReady(false);
|
||||
QThread::msleep(100);
|
||||
|
||||
return true;
|
||||
#else
|
||||
(void)port;
|
||||
(void)baudrate;
|
||||
emit messageDialog(tr("Connect serial"),
|
||||
tr("Serial port support is not enabled in this build "
|
||||
"of ENNOID-BMS Tool."),
|
||||
false, false);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
QList<VSerialInfo_t> BMSInterface::listSerialPorts()
|
||||
{
|
||||
QList<VSerialInfo_t> res;
|
||||
|
||||
#ifdef HAS_SERIALPORT
|
||||
QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts();
|
||||
|
||||
foreach(const QSerialPortInfo &port, ports) {
|
||||
VSerialInfo_t info;
|
||||
info.name = port.portName();
|
||||
info.systemPath = port.systemLocation();
|
||||
int index = res.size();
|
||||
|
||||
if(port.manufacturer().startsWith("Silicon")) {
|
||||
//info.name.insert(0, "ENNOID-BMS - ");
|
||||
info.name.append(" - ENNOID-BMS");
|
||||
info.isVesc = true;
|
||||
index = 0;
|
||||
} else {
|
||||
info.isVesc = false;
|
||||
}
|
||||
|
||||
res.insert(index, info);
|
||||
}
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void BMSInterface::connectTcp(QString server, int port)
|
||||
{
|
||||
mLastTcpServer = server;
|
||||
mLastTcpPort = port;
|
||||
setLastConnectionType(CONN_TCP);
|
||||
|
||||
QHostAddress host;
|
||||
host.setAddress(server);
|
||||
|
||||
// Try DNS lookup
|
||||
if (host.isNull()) {
|
||||
QList<QHostAddress> addresses = QHostInfo::fromName(server).addresses();
|
||||
|
||||
if (!addresses.isEmpty()) {
|
||||
host.setAddress(addresses.first().toString());
|
||||
}
|
||||
}
|
||||
|
||||
mTcpSocket->abort();
|
||||
mTcpSocket->connectToHost(host, port);
|
||||
}
|
||||
|
||||
void BMSInterface::connectBle(QString address)
|
||||
{
|
||||
mBleUart->startConnect(address);
|
||||
mLastConnType = CONN_BLE;
|
||||
mLastBleAddr = address;
|
||||
setLastConnectionType(CONN_BLE);
|
||||
}
|
||||
|
||||
bool BMSInterface::isAutoconnectOngoing() const
|
||||
{
|
||||
return mAutoconnectOngoing;
|
||||
}
|
||||
|
||||
double BMSInterface::getAutoconnectProgress() const
|
||||
{
|
||||
return mAutoconnectProgress;
|
||||
}
|
||||
|
||||
QVector<int> BMSInterface::scanCan()
|
||||
{
|
||||
QVector<int> canDevs;
|
||||
|
||||
if (!isPortConnected()) {
|
||||
return canDevs;
|
||||
}
|
||||
|
||||
QEventLoop loop;
|
||||
|
||||
bool timeout;
|
||||
auto conn = connect(commands(), &Commands::pingCanRx,
|
||||
[&canDevs, &timeout, &loop](QVector<int> devs, bool isTimeout) {
|
||||
for (int dev: devs) {
|
||||
canDevs.append(dev);
|
||||
}
|
||||
timeout = isTimeout;
|
||||
loop.quit();
|
||||
});
|
||||
|
||||
commands()->pingCan();
|
||||
loop.exec();
|
||||
|
||||
disconnect(conn);
|
||||
|
||||
if (!timeout) {
|
||||
mCanDevsLast = canDevs;
|
||||
} else {
|
||||
canDevs.clear();
|
||||
}
|
||||
|
||||
return canDevs;
|
||||
}
|
||||
|
||||
QVector<int> BMSInterface::getCanDevsLast() const
|
||||
{
|
||||
return mCanDevsLast;
|
||||
}
|
||||
|
||||
void BMSInterface::ignoreCanChange(bool ignore)
|
||||
{
|
||||
mIgnoreCanChange = ignore;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAS_SERIALPORT
|
||||
void BMSInterface::serialDataAvailable()
|
||||
{
|
||||
bool b = true;
|
||||
while (mSerialPort->bytesAvailable() > 0) {
|
||||
mPacket->processData(mSerialPort->readAll());
|
||||
}
|
||||
}
|
||||
|
||||
void BMSInterface::serialPortError(QSerialPort::SerialPortError error)
|
||||
{
|
||||
QString message;
|
||||
switch (error) {
|
||||
case QSerialPort::NoError:
|
||||
break;
|
||||
|
||||
default:
|
||||
message = "Serial port error: " + mSerialPort->errorString();
|
||||
break;
|
||||
}
|
||||
|
||||
if(!message.isEmpty()) {
|
||||
emit statusMessage(message, false);
|
||||
|
||||
if (mSerialPort->isOpen()) {
|
||||
mSerialPort->close();
|
||||
}
|
||||
|
||||
updateFwRx(false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void BMSInterface::tcpInputConnected()
|
||||
{
|
||||
bool b = true;
|
||||
mTcpConnected = true;
|
||||
updateFwRx(false);
|
||||
}
|
||||
|
||||
void BMSInterface::tcpInputDisconnected()
|
||||
{
|
||||
mTcpConnected = false;
|
||||
updateFwRx(false);
|
||||
}
|
||||
|
||||
void BMSInterface::tcpInputDataAvailable()
|
||||
{
|
||||
bool b = true;
|
||||
while (mTcpSocket->bytesAvailable() > 0) {
|
||||
mPacket->processData(mTcpSocket->readAll());
|
||||
}
|
||||
}
|
||||
|
||||
void BMSInterface::tcpInputError(QAbstractSocket::SocketError socketError)
|
||||
{
|
||||
(void)socketError;
|
||||
|
||||
QString errorStr = mTcpSocket->errorString();
|
||||
emit statusMessage(tr("TCP Error") + errorStr, false);
|
||||
mTcpSocket->close();
|
||||
updateFwRx(false);
|
||||
}
|
||||
|
||||
#ifdef HAS_BLUETOOTH
|
||||
void BMSInterface::bleDataRx(QByteArray data)
|
||||
{
|
||||
mPacket->processData(data);
|
||||
}
|
||||
#endif
|
||||
|
||||
void BMSInterface::timerSlot()
|
||||
{
|
||||
// Poll the serial port as well since readyRead is not emitted recursively. This
|
||||
// can be a problem when waiting for input with an additional event loop, such as
|
||||
// when using QMessageBox.
|
||||
#ifdef HAS_SERIALPORT
|
||||
serialDataAvailable();
|
||||
#endif
|
||||
|
||||
if (isPortConnected()) {
|
||||
if (mSendCanBefore != mCommands->getSendCan() ||
|
||||
mCanIdBefore != mCommands->getCanSendId()) {
|
||||
updateFwRx(false);
|
||||
mFwRetries = 0;
|
||||
}
|
||||
|
||||
mFwPollCnt++;
|
||||
if (mFwPollCnt >= 4) {
|
||||
mFwPollCnt = 0;
|
||||
if (!mFwVersionReceived) {
|
||||
mCommands->getFwVersion();
|
||||
mFwRetries++;
|
||||
|
||||
// Timeout if the firmware cannot be read
|
||||
if (mFwRetries >= 25) {
|
||||
emit statusMessage(tr("No firmware read response"), false);
|
||||
emit messageDialog(tr("Read Firmware Version"),
|
||||
tr("Could not read firmware version. Make sure "
|
||||
"that selected port really belongs to the ENNOID-BMS. "),
|
||||
false, false);
|
||||
disconnectPort();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
updateFwRx(false);
|
||||
mFwRetries = 0;
|
||||
}
|
||||
mSendCanBefore = mCommands->getSendCan();
|
||||
mCanIdBefore = mCommands->getCanSendId();
|
||||
|
||||
// Update fw upload bar and label
|
||||
double fwProg = mCommands->getFirmwareUploadProgress();
|
||||
QString fwStatus = mCommands->getFirmwareUploadStatus();
|
||||
if (fwProg > -0.1) {
|
||||
mIsUploadingFw = true;
|
||||
emit fwUploadStatus(fwStatus, fwProg, true);
|
||||
} else {
|
||||
// If the firmware upload just finished or failed
|
||||
if (mIsUploadingFw) {
|
||||
updateFwRx(false);
|
||||
mFwRetries = 0;
|
||||
if (fwStatus.compare("FW Upload Done") == 0) {
|
||||
emit fwUploadStatus(fwStatus, 1.0, false);
|
||||
} else {
|
||||
emit fwUploadStatus(fwStatus, 0.0, false);
|
||||
}
|
||||
}
|
||||
mIsUploadingFw = false;
|
||||
}
|
||||
|
||||
if (mWasConnected != isPortConnected()) {
|
||||
mWasConnected = isPortConnected();
|
||||
emit portConnectedChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void BMSInterface::packetDataToSend(QByteArray &data)
|
||||
{
|
||||
#ifdef HAS_SERIALPORT
|
||||
if (mSerialPort->isOpen()) {
|
||||
mSerialPort->write(data);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mTcpConnected && mTcpSocket->isOpen()) {
|
||||
mTcpSocket->write(data);
|
||||
}
|
||||
|
||||
if (mBleUart->isConnected()) {
|
||||
mBleUart->writeData(data);
|
||||
}
|
||||
}
|
||||
|
||||
void BMSInterface::packetReceived(QByteArray &data)
|
||||
{
|
||||
mCommands->processPacket(data);
|
||||
}
|
||||
|
||||
void BMSInterface::cmdDataToSend(QByteArray &data)
|
||||
{
|
||||
mPacket->sendPacket(data);
|
||||
}
|
||||
|
||||
void BMSInterface::fwVersionReceived(int major, int minor, QString hw, QByteArray uuid)
|
||||
{
|
||||
QList<QPair<int, int> > fwPairs = getSupportedFirmwarePairs();
|
||||
|
||||
QString strUuid = Utility::uuid2Str(uuid, true);
|
||||
|
||||
if (fwPairs.isEmpty()) {
|
||||
emit messageDialog(tr("Not Supported Firmwares"),
|
||||
tr("This version of ENNOID-BMS Tool does not seem to have any supported "
|
||||
"firmwares. Something is probably wrong with the BMS configuration "
|
||||
"file."),
|
||||
false, false);
|
||||
updateFwRx(false);
|
||||
mFwRetries = 0;
|
||||
disconnectPort();
|
||||
return;
|
||||
}
|
||||
|
||||
QPair<int, int> highest_supported = *std::max_element(fwPairs.begin(), fwPairs.end());
|
||||
QPair<int, int> fw_connected = qMakePair(major, minor);
|
||||
|
||||
bool wasReceived = mFwVersionReceived;
|
||||
mCommands->setLimitedMode(false);
|
||||
#if 0
|
||||
if (major < 0) {
|
||||
updateFwRx(false);
|
||||
mFwRetries = 0;
|
||||
disconnectPort();
|
||||
emit messageDialog(tr("Error"), tr("The firmware on the connected ENNOID-BMS is too old. Please update it using a programmer."), false, false);
|
||||
} else if (fw_connected > highest_supported) {
|
||||
mCommands->setLimitedMode(true);
|
||||
updateFwRx(true);
|
||||
if (!wasReceived) {
|
||||
emit messageDialog(tr("Warning"), tr("The connected ENNOID-BMS has newer firmware than this version of the"
|
||||
" ENNOID-BMS Tool supports. It is recommended that you update the ENNOID-BMS"
|
||||
" Tool to the latest version. Alternatively, the firmware on"
|
||||
" the connected ENNOID-BMS can be downgraded in the firmware page."
|
||||
" Until then, limited communication mode will be used where"
|
||||
" only the firmware can be changed."), false, false);
|
||||
}
|
||||
} else if (!fwPairs.contains(fw_connected)) {
|
||||
if (fw_connected >= qMakePair(0, 10)) {
|
||||
mCommands->setLimitedMode(true);
|
||||
updateFwRx(true);
|
||||
if (!wasReceived) {
|
||||
emit messageDialog(tr("Warning"), tr("The connected ENNOID-BMS has too old firmware. Since the"
|
||||
" connected ENNOID-BMS has firmware with bootloader support, it can be"
|
||||
" updated from the Firmware page."
|
||||
" Until then, limited communication mode will be used where only the"
|
||||
" firmware can be changed."), false, false);
|
||||
}
|
||||
} else {
|
||||
updateFwRx(false);
|
||||
mFwRetries = 0;
|
||||
disconnectPort();
|
||||
if (!wasReceived) {
|
||||
emit messageDialog(tr("Error"), tr("The firmware on the connected ENNOID-BMS is too old. Please"
|
||||
" update it using a programmer."), false, false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
updateFwRx(true);
|
||||
if ((fw_connected < highest_supported)) {
|
||||
if (!wasReceived) {
|
||||
//emit messageDialog(tr("Warning"), tr("The connected ENNOID-BMS is compatible, but old firmware. It is recommended that you update it."), false, false);
|
||||
}
|
||||
}
|
||||
|
||||
QString fwStr;
|
||||
fwStr.sprintf("ENNOID-BMS Firmware Version %d.%d", major, minor);
|
||||
if (!hw.isEmpty()) {
|
||||
fwStr += ", Hardware: " + hw;
|
||||
}
|
||||
|
||||
if (!strUuid.isEmpty()) {
|
||||
fwStr += ", UUID: " + strUuid;
|
||||
}
|
||||
|
||||
emit statusMessage(fwStr, true);
|
||||
#if 0
|
||||
}
|
||||
#endif
|
||||
|
||||
if (major >= 0) {
|
||||
mFwTxt.sprintf("Fw: %d.%d", major, minor);
|
||||
mHwTxt = hw;
|
||||
if (!hw.isEmpty()) {
|
||||
mFwTxt += ", Hw: " + hw;
|
||||
}
|
||||
|
||||
if (!strUuid.isEmpty()) {
|
||||
mFwTxt += "\n" + strUuid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BMSInterface::bmsconfUpdated()
|
||||
{
|
||||
emit statusMessage(tr("BMS configuration updated"), true);
|
||||
}
|
||||
|
||||
void BMSInterface::bmsconfStored() {
|
||||
emit statusMessage(tr("BMS configuration stored to Flash"), true);
|
||||
}
|
||||
|
||||
void BMSInterface::ackReceived(QString ackType)
|
||||
{
|
||||
emit statusMessage(ackType, true);
|
||||
}
|
||||
|
||||
void BMSInterface::updateFwRx(bool fwRx)
|
||||
{
|
||||
bool change = mFwVersionReceived != fwRx;
|
||||
mFwVersionReceived = fwRx;
|
||||
if (change) {
|
||||
emit fwRxChanged(mFwVersionReceived, mCommands->isLimitedMode());
|
||||
}
|
||||
}
|
||||
|
||||
void BMSInterface::setLastConnectionType(conn_t type)
|
||||
{
|
||||
mLastConnType = type;
|
||||
QSettings().setValue("connection_type", type);
|
||||
}
|
||||
Reference in New Issue
Block a user