From 6ef5757a4dcf1abc200a782a93b31f397b35af95 Mon Sep 17 00:00:00 2001 From: Collin Kidder Date: Tue, 22 Aug 2017 20:03:58 -0400 Subject: [PATCH] Additional functionality for scripting interface. In progress but raw CAN works now. --- re/udsscanwindow.cpp | 16 +---- scriptcontainer.cpp | 159 +++++++++++++++++++++++------------------- scriptcontainer.h | 56 ++++++++++++--- scriptingwindow.cpp | 30 ++++---- scriptingwindow.h | 1 + ui/scriptingwindow.ui | 13 +++- 6 files changed, 161 insertions(+), 114 deletions(-) diff --git a/re/udsscanwindow.cpp b/re/udsscanwindow.cpp index e880421..f14f396 100644 --- a/re/udsscanwindow.cpp +++ b/re/udsscanwindow.cpp @@ -165,20 +165,8 @@ void UDSScanWindow::dumpNode(QTreeWidgetItem* item, QFile *file, int indent) void UDSScanWindow::sendOnBuses(UDS_MESSAGE test, int buses) { - //int busList = buses; - //if (busList < ui->cbBuses->count() - 1) - //{ - test.bus = buses; - sendingFrames.append(test); - //} - /*else - { - for (int c = 0; c < ui->cbBuses->count() - 1; c++) - { - test.bus = c; - sendingFrames.append(test); - } - }*/ + test.bus = buses; + sendingFrames.append(test); } void UDSScanWindow::scanUDS() diff --git a/scriptcontainer.cpp b/scriptcontainer.cpp index e8f1d02..d534227 100644 --- a/scriptcontainer.cpp +++ b/scriptcontainer.cpp @@ -4,9 +4,12 @@ #include "scriptcontainer.h" #include "connections/canconmanager.h" -ScriptContainer::ScriptContainer(QString& pConName): - mConName(pConName) +ScriptContainer::ScriptContainer() { + canHelper = new CANScriptHelper(&scriptEngine); + isoHelper = new ISOTPScriptHelper; + udsHelper = new UDSScriptHelper; + elapsedTime.start(); connect(&timer, SIGNAL(timeout()), this, SLOT(tick())); } @@ -14,25 +17,39 @@ void ScriptContainer::compileScript() { QJSValue result = scriptEngine.evaluate(scriptText, fileName); - errorWidget->clear(); - - if (result.isError() && errorWidget) + if (logWidget) { - errorWidget->addItem("SCRIPT EXCEPTION!"); - errorWidget->addItem("Line: " + result.property("lineNumber").toString()); - errorWidget->addItem(result.property("message").toString()); - errorWidget->addItem("Stack:"); - errorWidget->addItem(result.property("stack").toString()); + logWidget->addItem(""); + logWidget->addItem("Compiling script " + fileName); + } + + if (result.isError() && logWidget) + { + logWidget->addItem("SCRIPT EXCEPTION!"); + logWidget->addItem("Line: " + result.property("lineNumber").toString()); + logWidget->addItem(result.property("message").toString()); + logWidget->addItem("Stack:"); + logWidget->addItem(result.property("stack").toString()); } else { compiledScript = result; + //Add a bunch of helper objects into javascript that the scripts + //can use to interact with the CAN buses QJSValue hostObj = scriptEngine.newQObject(this); scriptEngine.globalObject().setProperty("host", hostObj); + QJSValue canObj = scriptEngine.newQObject(canHelper); + scriptEngine.globalObject().setProperty("can", canObj); + QJSValue isoObj = scriptEngine.newQObject(isoHelper); + scriptEngine.globalObject().setProperty("isotp", isoObj); + QJSValue udsObj = scriptEngine.newQObject(udsHelper); + scriptEngine.globalObject().setProperty("uds", udsObj); + //Find out which callbacks the script has created. setupFunction = scriptEngine.globalObject().property("setup"); - gotFrameFunction = scriptEngine.globalObject().property("gotFrame"); + canHelper->setRxCallback(scriptEngine.globalObject().property("gotCANFrame")); + tickFunction = scriptEngine.globalObject().property("tick"); if (setupFunction.isCallable()) @@ -41,47 +58,23 @@ void ScriptContainer::compileScript() QJSValue res = setupFunction.call(); if (res.isError()) { - errorWidget->addItem("Error in setup function on line " + res.property("lineNumber").toString()); - errorWidget->addItem(res.property("message").toString()); + logWidget->addItem("Error in setup function on line " + res.property("lineNumber").toString()); + logWidget->addItem(res.property("message").toString()); } } - - if (gotFrameFunction.isCallable()) qDebug() << "gotFrame exists"; if (tickFunction.isCallable()) qDebug() << "tick exists"; } } -void ScriptContainer::setErrorWidget(QListWidget *list) +void ScriptContainer::setLogWidget(QListWidget *list) { - errorWidget = list; + logWidget = list; } -void ScriptContainer::setFilter(QJSValue id, QJSValue mask, QJSValue bus) +void ScriptContainer::log(QJSValue logString) { - uint32_t idVal = id.toUInt(); - uint32_t maskVal = mask.toUInt(); - int busVal = bus.toInt(); - qDebug() << "Called set filter"; - qDebug() << idVal << "*" << maskVal << "*" << busVal; - CANFilter filter; - filter.setFilter(idVal, maskVal, busVal); - filters.append(filter); - - qDebug() << "FIXME setFilter"; - CANConnection* conn_p = CANConManager::getInstance()->getByName(mConName); - if(conn_p) - { - //CANFlt canFlt; - for(int i=0 ; igetNumBuses() ; i++) - { - foreach(const CANFilter& flt, filters) - { - if(flt.bus==i) { - conn_p->addTargettedFrame(busVal, idVal, maskVal, this); - } - } - } - } + QString val = logString.toString(); + logWidget->addItem(QString::number(elapsedTime.elapsed()) + ": " + val); } void ScriptContainer::setTickInterval(QJSValue interval) @@ -96,20 +89,59 @@ void ScriptContainer::setTickInterval(QJSValue interval) else timer.stop(); } -void ScriptContainer::clearFilters() +void ScriptContainer::tick() { - qDebug() << "Called clear filters"; - filters.clear(); - - qDebug() << "FIXME clearFilters"; - CANConnection* conn_p = CANConManager::getInstance()->getByName(mConName); - if(conn_p) + if (tickFunction.isCallable()) { - conn_p->removeAllTargettedFrames(this); + //qDebug() << "Calling tick function"; + QJSValue res = tickFunction.call(); + if (res.isError()) + { + logWidget->addItem("Error in tick function on line " + res.property("lineNumber").toString()); + logWidget->addItem(res.property("message").toString()); + } } } -void ScriptContainer::sendFrame(QJSValue bus, QJSValue id, QJSValue length, QJSValue data) + +/* CANScriptHandler Methods */ + +CANScriptHelper::CANScriptHelper(QJSEngine *engine) +{ + scriptEngine = engine; +} + +void CANScriptHelper::setRxCallback(QJSValue cb) +{ + gotFrameFunction = cb; +} + +void CANScriptHelper::setFilter(QJSValue id, QJSValue mask, QJSValue bus) +{ + uint32_t idVal = id.toUInt(); + uint32_t maskVal = mask.toUInt(); + int busVal = bus.toInt(); + qDebug() << "Called set filter"; + qDebug() << idVal << "*" << maskVal << "*" << busVal; + CANFilter filter; + filter.setFilter(idVal, maskVal, busVal); + filters.append(filter); + + CANConManager::getInstance()->addTargettedFrame(busVal, idVal, maskVal, this); +} + +void CANScriptHelper::clearFilters() +{ + qDebug() << "Called clear filters"; + foreach (CANFilter filter, filters) + { + CANConManager::getInstance()->removeTargettedFrame(filter.bus, filter.ID, filter.mask, this); + } + + filters.clear(); +} + +void CANScriptHelper::sendFrame(QJSValue bus, QJSValue id, QJSValue length, QJSValue data) { CANFrame frame; frame.extended = false; @@ -125,17 +157,15 @@ void ScriptContainer::sendFrame(QJSValue bus, QJSValue id, QJSValue length, QJSV } frame.bus = (uint32_t)bus.toInt(); - if (frame.bus > 1) frame.bus = 1; + //if (frame.bus > 1) frame.bus = 1; if (frame.ID > 0x7FF) frame.extended = true; qDebug() << "sending frame from script"; - CANConnection* conn_p = CANConManager::getInstance()->getByName(mConName); - if(conn_p) - conn_p->sendFrame(frame); + CANConManager::getInstance()->sendFrame(frame); } -void ScriptContainer::gotFrame(const CANFrame &frame) +void CANScriptHelper::gotTargettedFrame(const CANFrame &frame) { if (!gotFrameFunction.isCallable()) return; //nothing to do if we can't even call the function //qDebug() << "Got frame in script interface"; @@ -145,7 +175,8 @@ void ScriptContainer::gotFrame(const CANFrame &frame) { QJSValueList args; args << frame.bus << frame.ID << frame.len; - QJSValue dataBytes = scriptEngine.newArray(frame.len); + QJSValue dataBytes = scriptEngine->newArray(frame.len); + for (unsigned int j = 0; j < frame.len; j++) dataBytes.setProperty(j, QJSValue(frame.data[j])); args.append(dataBytes); gotFrameFunction.call(args); @@ -154,16 +185,4 @@ void ScriptContainer::gotFrame(const CANFrame &frame) } } -void ScriptContainer::tick() -{ - if (tickFunction.isCallable()) - { - //qDebug() << "Calling tick function"; - QJSValue res = tickFunction.call(); - if (res.isError()) - { - errorWidget->addItem("Error in tick function on line " + res.property("lineNumber").toString()); - errorWidget->addItem(res.property("message").toString()); - } - } -} + diff --git a/scriptcontainer.h b/scriptcontainer.h index 241ac23..fbabacd 100644 --- a/scriptcontainer.h +++ b/scriptcontainer.h @@ -4,30 +4,64 @@ #include "can_structs.h" #include "canfilter.h" +#include #include #include #include +class CANScriptHelper: public QObject +{ + Q_OBJECT +public: + CANScriptHelper(QJSEngine *engine); + +public slots: + void setFilter(QJSValue id, QJSValue mask, QJSValue bus); + void clearFilters(); + void sendFrame(QJSValue bus, QJSValue id, QJSValue length, QJSValue data); + void setRxCallback(QJSValue cb); + +private slots: + void gotTargettedFrame(const CANFrame &frame); + +private: + QList filters; + QJSValue gotFrameFunction; + QJSEngine *scriptEngine; +}; + +class ISOTPScriptHelper: public QObject +{ + Q_OBJECT +private: + QJSValue gotFrameFunction; + QJSEngine *scriptEngine; +}; + +class UDSScriptHelper: public QObject +{ + Q_OBJECT +private: + QJSValue gotFrameFunction; + QJSEngine *scriptEngine; +}; + class ScriptContainer : public QObject { Q_OBJECT public: - ScriptContainer(QString&); - void gotFrame(const CANFrame &frame); + ScriptContainer(); + void setLogWidget(QListWidget *list); QString fileName; QString filePath; QString scriptText; - QString mConName; public slots: void compileScript(); - void setErrorWidget(QListWidget *list); - void setFilter(QJSValue id, QJSValue mask, QJSValue bus); void setTickInterval(QJSValue interval); - void clearFilters(); - void sendFrame(QJSValue bus, QJSValue id, QJSValue length, QJSValue data); + void log(QJSValue logString); private slots: void tick(); @@ -36,11 +70,13 @@ private: QJSEngine scriptEngine; QJSValue compiledScript; QJSValue setupFunction; - QJSValue gotFrameFunction; QJSValue tickFunction; QTimer timer; - QListWidget *errorWidget; - QList filters; + QListWidget *logWidget; + CANScriptHelper *canHelper; + ISOTPScriptHelper *isoHelper; + UDSScriptHelper *udsHelper; + QElapsedTimer elapsedTime; }; #endif // SCRIPTCONTAINER_H diff --git a/scriptingwindow.cpp b/scriptingwindow.cpp index 2522308..6b88f56 100644 --- a/scriptingwindow.cpp +++ b/scriptingwindow.cpp @@ -17,6 +17,7 @@ ScriptingWindow::ScriptingWindow(const QVector *frames, QWidget *paren editor->setFrameShape(JSEdit::NoFrame); editor->setWordWrapMode(QTextOption::NoWrap); editor->setTabStopWidth(4); + editor->setEnabled(false); editor->show(); ui->verticalLayout->insertWidget(2,editor, 10); @@ -30,6 +31,7 @@ ScriptingWindow::ScriptingWindow(const QVector *frames, QWidget *paren connect(ui->btnRemoveScript, &QAbstractButton::pressed, this, &ScriptingWindow::deleteCurrentScript); connect(ui->btnRevertScript, &QAbstractButton::pressed, this, &ScriptingWindow::revertScript); connect(ui->btnSaveScript, &QAbstractButton::pressed, this, &ScriptingWindow::saveScript); + connect(ui->btnClearLog, &QAbstractButton::pressed, this, &ScriptingWindow::clickedLogClear); connect(CANConManager::getInstance(), &CANConManager::framesReceived, this, &ScriptingWindow::newFrames); @@ -51,7 +53,7 @@ void ScriptingWindow::newFrames(const CANConnection* pConn, const QVectorgotFrame(frame); + //scripts[j]->gotFrame(frame); } } } @@ -117,23 +119,17 @@ void ScriptingWindow::loadNewScript() QStringList fileList = filename.split('/'); QString justFileName = fileList[fileList.length() - 1]; ui->listLoadedScripts->addItem(justFileName); - /* get the first connection in the list for now */ - qDebug() << "FIXME: connection is always the first in list"; - QString portName; - QList list = CANConManager::getInstance()->getConnections(); - if(!list.isEmpty()) - portName = list.first()->getPort(); - container = new ScriptContainer(portName); + container = new ScriptContainer; container->fileName = justFileName; container->filePath = filename; container->scriptText = contents; - container->setErrorWidget(ui->listErrors); + container->setLogWidget(ui->listLog); container->compileScript(); scripts.append(container); currentScript = container; editor->setPlainText(container->scriptText); - setEnabled(true); + editor->setEnabled(true); } } } @@ -143,17 +139,12 @@ void ScriptingWindow::createNewScript() { ScriptContainer *container; - QString portName; - QList list = CANConManager::getInstance()->getConnections(); - if(!list.isEmpty()) - portName = list.first()->getPort(); - - container = new ScriptContainer(portName); + container = new ScriptContainer; container->fileName = "UNNAMED_" + QString::number((qrand() % 10000)) + ".js"; container->filePath = QString(); container->scriptText = QString(); - container->setErrorWidget(ui->listErrors); + container->setLogWidget(ui->listLog); scripts.append(container); ui->listLoadedScripts->addItem(container->fileName); currentScript = container; @@ -214,3 +205,8 @@ void ScriptingWindow::recompileScript() currentScript->scriptText = editor->toPlainText(); currentScript->compileScript(); } + +void ScriptingWindow::clickedLogClear() +{ + ui->listLog->clear(); +} diff --git a/scriptingwindow.h b/scriptingwindow.h index dfc1a82..986cf75 100644 --- a/scriptingwindow.h +++ b/scriptingwindow.h @@ -31,6 +31,7 @@ private slots: void revertScript(); void recompileScript(); void newFrames(const CANConnection*, const QVector&); + void clickedLogClear(); private: void closeEvent(QCloseEvent *event); diff --git a/ui/scriptingwindow.ui b/ui/scriptingwindow.ui index 66f8a89..4b83343 100644 --- a/ui/scriptingwindow.ui +++ b/ui/scriptingwindow.ui @@ -53,7 +53,7 @@ - + @@ -92,7 +92,7 @@ - Current Scripting Errors + Log Window: Qt::AlignCenter @@ -100,7 +100,14 @@ - + + + + + + Clear Log Window + +