/*
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 .
*/
#include "utility.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef Q_OS_ANDROID
#include
#include
#include
#endif
Utility::Utility(QObject *parent) : QObject(parent)
{
}
double Utility::map(double x, double in_min, double in_max, double out_min, double out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
float Utility::throttle_curve(float val, float curve_acc, float curve_brake, int mode)
{
float ret = 0.0;
float val_a = fabsf(val);
if (val < -1.0f) {
val = -1.0;
}
if (val > 1.0f) {
val = 1.0;
}
float curve;
if (val >= 0.0f) {
curve = curve_acc;
} else {
curve = curve_brake;
}
// See
// http://math.stackexchange.com/questions/297768/how-would-i-create-a-exponential-ramp-function-from-0-0-to-1-1-with-a-single-val
if (mode == 0) { // Power
if (curve >= 0.0f) {
ret = 1.0f - powf(1.0f - val_a, 1.0f + curve);
} else {
ret = powf(val_a, 1.0f - curve);
}
} else if (mode == 1) { // Exponential
if (fabsf(curve) < 1e-10f) {
ret = val_a;
} else {
if (curve >= 0.0f) {
ret = 1.0f - ((expf(curve * (1.0f - val_a)) - 1.0f) / (expf(curve) - 1.0f));
} else {
ret = (expf(-curve * val_a) - 1.0f) / (expf(-curve) - 1.0f);
}
}
} else if (mode == 2) { // Polynomial
if (curve >= 0.0f) {
ret = 1.0f - ((1.0f - val_a) / (1.0f + curve * val_a));
} else {
ret = val_a / (1.0f - curve * (1.0f - val_a));
}
} else { // Linear
ret = val_a;
}
if (val < 0.0f) {
ret = -ret;
}
return ret;
}
bool Utility::autoconnectBlockingWithProgress(BMSInterface *dieBieMS, QWidget *parent)
{
if (!dieBieMS) {
return false;
}
QProgressDialog dialog("Autoconnecting...", QString(), 0, 0, parent);
dialog.setWindowModality(Qt::WindowModal);
dialog.show();
bool res = dieBieMS->autoconnect();
if (!res) {
dieBieMS->emitMessageDialog(QObject::tr("Autoconnect"),
QObject::tr("Could not autoconnect. Make sure that the USB cable is plugged in"
" and that the ENNOID-BMS is powered."),
false);
}
return res;
}
void Utility::checkVersion(BMSInterface *dieBieMS)
{
QString version = QString::number(DT_VERSION);
QUrl url("https://raw.githubusercontent.com/EnnoidMe/ENNOID-BMS-Tool/ENNOID/res/ennoidbmstool-version.html");
QNetworkAccessManager manager;
QNetworkRequest request(url);
QNetworkReply *reply = manager.get(request);
QEventLoop loop;
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
QString res = QString::fromUtf8(reply->readAll());
if (res.startsWith("ennoidbmstoolversion")) {
res.remove(0, 20);
res.remove(res.indexOf("ennoidbmstoolversion"), res.size());
if (res.toDouble() > version.toDouble()) {
if (dieBieMS) {
dieBieMS->emitStatusMessage("A new version of ENNOID-BMS Tool is available", true);
} else {
qDebug() << "A new version of ENNOID-BMS Tool is available. Go to www.ennoid.me to download it"
"and get all the latest features.";
}
}
} else {
qWarning() << res;
}
}
QString Utility::fwChangeLog()
{
QFile cl("://res/firmwares/CHANGELOG");
if (cl.open(QIODevice::ReadOnly | QIODevice::Text)) {
return QString::fromUtf8(cl.readAll());
} else {
return "";
}
}
QString Utility::vescToolChangeLog()
{
QFile cl("://res/CHANGELOG");
if (cl.open(QIODevice::ReadOnly | QIODevice::Text)) {
return QString::fromUtf8(cl.readAll());
} else {
return "";
}
}
QString Utility::aboutText()
{
return tr("ENNOID-BMS Tool V%1
"
"© Kevin Dionne 2019
"
"kevin.dionne@ennoid.me
"
"https://www.ennoid.me/
"
"Based on: DieBieMS-tool
"
"
"
"DieBieMS Tool
"
"© Danny Bokma 2018
"
"bms@diebie.nl
"
"https://diebie.nl/
"
"Based on: VESC-tool
"
"
"
"VESC Tool
"
"© Benjamin Vedder 2018
"
"benjamin@vedder.se
"
"https://vesc-project.com/
"
"
").
arg(QString::number(DT_VERSION, 'f', 1));
}
QString Utility::uuid2Str(QByteArray uuid, bool space)
{
QString strUuid;
for (int i = 0;i < uuid.size();i++) {
QString str = QString::number(uuid.at(i), 16).
rightJustified(2, '0').toUpper();
strUuid.append(((i > 0 && space) ? " " : "") + str);
}
return strUuid;
}
bool Utility::requestFilePermission()
{
#ifdef Q_OS_ANDROID
// Note: The following should work on Qt 5.10
// https://codereview.qt-project.org/#/c/199162/
// QtAndroid::PermissionResult r = QtAndroid::checkPermission("android.permission.WRITE_EXTERNAL_STORAGE");
// if(r == QtAndroid::PermissionResult::Denied) {
// QtAndroid::requestPermissionsSync( QStringList() << "android.permission.WRITE_EXTERNAL_STORAGE" );
// r = QtAndroid::checkPermission("android.permission.WRITE_EXTERNAL_STORAGE");
// if(r == QtAndroid::PermissionResult::Denied) {
// return false;
// }
// }
return true;
#else
return true;
#endif
}
bool Utility::waitSignal(QObject *sender, QString signal, int timeoutMs)
{
QEventLoop loop;
QTimer timeoutTimer;
timeoutTimer.setSingleShot(true);
timeoutTimer.start(timeoutMs);
auto conn1 = QObject::connect(sender, signal.toLocal8Bit().data(), &loop, SLOT(quit()));
auto conn2 = QObject::connect(&timeoutTimer, SIGNAL(timeout()), &loop, SLOT(quit()));
loop.exec();
QObject::disconnect(conn1);
QObject::disconnect(conn2);
return timeoutTimer.isActive();
}
bool Utility::almostEqual(double A, double B, double eps)
{
return fabs(A - B) <= eps * fmax(1.0f, fmax(fabs(A), fabs(B)));
}