Forgot about version control, here's the whole code at once

This commit is contained in:
leo 2021-06-06 00:10:20 +02:00
commit 228fc3ab24
Signed by: leo
GPG Key ID: 0DD993BFB2B307DB
9 changed files with 441 additions and 0 deletions

25
LivePow.pro Normal file
View File

@ -0,0 +1,25 @@
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
displayarea.cpp \
inputparser.cpp \
main.cpp \
mainwindow.cpp
HEADERS += \
displayarea.h \
inputparser.h \
mainwindow.h
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

13
README.md Normal file
View File

@ -0,0 +1,13 @@
# LivePow
An reader for making heatmap from soapy_power output
## Building
```
mkdir build
qmake ..
make -j4
```
## Usage
### Example scanning the FM radio band
`soapy_power -f 80M:110M -n 10 -e 30 -B 30k -k 30 --pow2 -F rtl_power -R | ./Livepow`

47
displayarea.cpp Normal file
View File

@ -0,0 +1,47 @@
#include "displayarea.h"
#include <qpainter.h>
#include <QPaintEvent>
#include <QTimer>
DisplayArea::DisplayArea(QWidget *parent) : QWidget(parent)
{
setAttribute(Qt::WA_StaticContents);
QTimer* timer = new QTimer(this);
connect(timer,SIGNAL(timeout()),this,SLOT(updateDisp()));
timer->start(100);
}
void DisplayArea::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
QRect rect=event->rect();
painter.drawImage(rect,image,rect);
}
void DisplayArea::setPixel(int x, int y, unsigned int col)
{
if(x>=image.width()||y>=image.height()) resizeImage(&image,QSize(qMax(x+255,image.width()),qMax(y+255,image.height())));
image.setPixel(x,y,col);
}
void DisplayArea::resizeImage(QImage *image, const QSize &newSize)
{
if(image->size()==newSize) return;
QImage newImage(newSize,QImage::Format_ARGB32);
newImage.fill(qRgba(255,255,255,0));
QPainter painter(&newImage);
painter.drawImage(QPoint(0,0),*image);
*image=newImage;
}
void DisplayArea::updateDisp()
{
update();
}
bool DisplayArea::saveImage(const QString &fileName, const char *fileFormat)
{
return image.save(fileName, fileFormat);
}

29
displayarea.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef DISPLAYAREA_H
#define DISPLAYAREA_H
#include <QWidget>
class DisplayArea : public QWidget
{
Q_OBJECT
public:
DisplayArea(QWidget *parent = nullptr);
void setPixel(int x,int y,unsigned int col);
bool saveImage(const QString &fileName, const char *fileFormat);
protected:
void paintEvent(QPaintEvent *event) override;
private:
void resizeImage(QImage *image, const QSize &newSize);
QImage image;
public slots:
void updateDisp();
signals:
};
#endif // DISPLAYAREA_H

132
inputparser.cpp Normal file
View File

@ -0,0 +1,132 @@
#include "inputparser.h"
#include <QTimer>
#include "displayarea.h"
#include <QRandomGenerator>
#include <QDebug>
InputParser::InputParser(FILE* input,DisplayArea* display)
{
InputParser::input=input;
InputParser::display=display;
random=new QRandomGenerator();
/*QTimer* timer = new QTimer(this);
connect(timer,SIGNAL(timeout()),this,SLOT(process()));
timer->start(0);*/
}
void InputParser::process()
{
while(1){
int c=fgetc(input);
if(c==EOF) continue;
switch(c){
case ',':
switch(index){
case 1:
computeEpochDate();
break;
default:
if(index>5){
sendPixel();
}
break;
}
index++;
decimal=false;
break;
case '\n':
index=0;
minFreq=qMin(minFreq,currentLine.minFreq);
maxFreq=qMax(maxFreq,currentLine.maxFreq);
sendPixel();
if(currentLine.maxFreq<=lastMaxFreq){
currentY++;
currentX=0;
}
lastMaxFreq=currentLine.maxFreq;
currentLine=line();
decimal=false;
break;
case '.':
decimal=true;
break;
default:
switch(index){
case 0:
addToString(c,&currentLine.firstDate);
break;
case 1:
addToString(c,&currentLine.secondDate);
break;
case 2:
addToInt(c,&currentLine.minFreq);
break;
case 3:
addToInt(c,&currentLine.maxFreq);
break;
case 4:
addToInt(c,&currentLine.freqStep);
break;
default:
if(index>5) addToFloat(c,&currentPowerValue);
break;
}
break;
}
}
//printf("%c aaa");
}
void InputParser::addToString(char c, QString* str)
{
str->append(c);
}
void InputParser::addToInt(char c, unsigned long* nb)
{
if(decimal||c<'0'||c>'9') return;
*nb*=10;
*nb+=(c-'0');
}
void InputParser::addToFloat(char c, float* nb)
{
if(c<'0'||c>'9') return;
if(!decimal){
*nb*=10;
*nb+=(c-'0');
}
else{
float inc=((c-'0')/pow(10,decimalIndex));
*nb+=inc;
decimalIndex++;
}
}
void InputParser::computeEpochDate()
{
QString dateMerged=QString();
dateMerged.append(currentLine.firstDate);
dateMerged.append(currentLine.secondDate);
//2021-05-28 23:20:36
currentLine.parsedDate=QDateTime::fromString(dateMerged,"yyyy-MM-dd hh:mm:ss");
}
void InputParser::sendPixel()
{
currentPowerValue*=sign;
int col=qRound((80-currentPowerValue)*6);
display->setPixel(currentX,currentY,qRgba(col,col,col,255));
currentX++;
currentPowerValue=0;
decimalIndex=1;
sign=1;
}

63
inputparser.h Normal file
View File

@ -0,0 +1,63 @@
#ifndef INPUTPARSER_H
#define INPUTPARSER_H
#include <stdio.h>
#include <QTimerEvent>
#include <QObject>
#include <QRandomGenerator>
#include <QDateTime>
class DisplayArea;
struct line{
QString firstDate;
QString secondDate;
QDateTime parsedDate;
unsigned long minFreq=0;
unsigned long maxFreq=0;
unsigned long freqStep=0;
};
class InputParser : public QObject
{
Q_OBJECT
public:
InputParser(FILE* input,DisplayArea* display);
private:
unsigned long minFreq=-1;
unsigned long maxFreq=0;
unsigned long lastMaxFreq=0;
unsigned long index=0;
line currentLine;
FILE* input;
bool decimal=false;
int decimalIndex=1;
int sign=1;
unsigned int currentX=0;
unsigned int currentY=0;
DisplayArea* display;
QRandomGenerator* random;
float currentPowerValue=0;
void addToString(char c,QString* str);
void addToInt(char c,unsigned long* nb);
void addToFloat(char c,float* nb);
void computeEpochDate();
void sendPixel();
public slots:
void process();
};
#endif // INPUTPARSER_H

11
main.cpp Normal file
View File

@ -0,0 +1,11 @@
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

82
mainwindow.cpp Normal file
View File

@ -0,0 +1,82 @@
#include <stdio.h>
#include "mainwindow.h"
#include "displayarea.h"
#include "inputparser.h"
#include <QTimer>
#include <QThread>
#include <QAction>
#include <QImageWriter>
#include <QMenu>
#include <QDir>
#include <QFileDialog>
#include <QMenuBar>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent),displayArea(new DisplayArea(this))
{
setCentralWidget(displayArea);
FILE* input=stdin;
parser=new InputParser(input,displayArea);
QThread* workerThread=new QThread();
parser->moveToThread(workerThread);
connect(workerThread, &QThread::started, parser, &InputParser::process);
connect(workerThread, &QThread::finished, workerThread, &QThread::deleteLater);
workerThread->start();
createActions();
createMenus();
setWindowTitle(tr("LivePow"));
}
MainWindow::~MainWindow()
{
}
void MainWindow::save(){
QAction *action = qobject_cast<QAction *>(sender());
QByteArray fileFormat = action->data().toByteArray();
saveFile(fileFormat);
}
bool MainWindow::saveFile(const QByteArray &fileFormat)
{
QString initialPath = QDir::currentPath() + "/untitled." + fileFormat;
QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"),
initialPath,
tr("%1 Files (*.%2);;All Files (*)")
.arg(QString::fromLatin1(fileFormat.toUpper()),QString::fromLatin1(fileFormat)));
if (fileName.isEmpty())
return false;
return displayArea->saveImage(fileName, fileFormat.constData());
}
void MainWindow::createActions()
{
const QList<QByteArray> imageFormats = QImageWriter::supportedImageFormats();
for (const QByteArray &format : imageFormats) {
QString text = tr("%1...").arg(QString::fromLatin1(format).toUpper());
QAction *action = new QAction(text, this);
action->setData(format);
connect(action, &QAction::triggered, this, &MainWindow::save);
saveAsActs.append(action);
}
}
void MainWindow::createMenus()
{
saveAsMenu = new QMenu(tr("&Save As"), this);
for (QAction *action : qAsConst(saveAsActs))
saveAsMenu->addAction(action);
fileMenu = new QMenu(tr("&File"), this);
fileMenu->addMenu(saveAsMenu);
menuBar()->addMenu(fileMenu);
}

39
mainwindow.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class DisplayArea;
class InputParser;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
static void tick();
InputParser *parser;
private:
DisplayArea *displayArea;
void createActions();
void createMenus();
QMenu *saveAsMenu;
QMenu *fileMenu;
QList<QAction *> saveAsActs;
bool saveFile(const QByteArray &fileFormat);
private slots:
void save();
signals:
void operate(const QString &);
};
#endif // MAINWINDOW_H