├── .github └── workflows │ └── build-windows.yml ├── .gitignore ├── CloudLogCatQt.pro ├── README.md ├── cloudlogcatqt.cpp ├── cloudlogcatqt.h ├── cloudlogcatqt.ui ├── doc ├── CATSelection.png ├── CloudLogCATQt.png ├── HardwareInterfaces.png ├── Linux.png └── Windows.png ├── main.cpp └── sat.dat /.github/workflows/build-windows.yml: -------------------------------------------------------------------------------- 1 | name: Build Windows Release 2 | on: 3 | push: 4 | branches: 5 | - main 6 | - master 7 | 8 | env: 9 | QT_VERSION: 5.15.2 10 | 11 | jobs: 12 | build-windows: 13 | runs-on: windows-2019 14 | steps: 15 | - uses: actions/checkout@v2 16 | 17 | - name: Add short SHA to env 18 | run: echo "GITHUB_SHA_SHORT=$(echo $env:GITHUB_SHA | cut -c 1-6)" >> $env:GITHUB_ENV 19 | 20 | - name: Install Qt environment 21 | run: | 22 | choco install -y qt5-default --version ${{ env.QT_VERSION }} 23 | choco install -y cmake 24 | 25 | - name: qmake 26 | run: "C:/Qt/${{ env.QT_VERSION }}/mingw81_64/bin/qmake.exe CloudLogCatQt.pro" 27 | 28 | - name: make 29 | run: mingw32-make.exe -j4 30 | 31 | - name: windeployqt 32 | run: "C:/Qt/${{ env.QT_VERSION }}/mingw81_64/bin/windeployqt.exe release" 33 | 34 | - name: Upload a Build Artifact 35 | uses: actions/upload-artifact@v3.1.1 36 | with: 37 | name: CloudLogCatQt-win 38 | path: release 39 | 40 | release: 41 | needs: [build-windows] 42 | runs-on: ubuntu-latest 43 | steps: 44 | - uses: actions/checkout@v1 45 | 46 | - name: Add short SHA to env 47 | run: echo "GITHUB_SHA_SHORT=$(echo $GITHUB_SHA | cut -c 1-6)" >> $GITHUB_ENV 48 | 49 | - name: Download Artifacts 50 | uses: actions/download-artifact@v2 51 | with: 52 | name: CloudLogCatQt-win 53 | path: CloudLogCatQt-win 54 | 55 | - name: ZIP build files 56 | uses: montudor/action-zip@v1 57 | with: 58 | args: zip -qq -r CloudLogCatQt-${{ env.GITHUB_SHA_SHORT }}-win.zip CloudLogCatQt-win 59 | 60 | - name: Automatic Release 61 | uses: marvinpinto/action-automatic-releases@latest 62 | with: 63 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 64 | automatic_release_tag: "latest" 65 | draft: true 66 | prerelease: false 67 | title: CloudLogCatQt (${{ env.GITHUB_SHA_SHORT }}) 68 | files: | 69 | CloudLogCatQt-${{ env.GITHUB_SHA_SHORT }}-win.zip 70 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | CloudLogCatQt.pro.user 3 | doc/.DS_Store 4 | -------------------------------------------------------------------------------- /CloudLogCatQt.pro: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020, Matthias Jung (DL9MJ) 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are 6 | # met: 7 | # 8 | # 1. Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # 11 | # 2. Redistributions in binary form must reproduce the above copyright 12 | # notice, this list of conditions and the following disclaimer in the 13 | # documentation and/or other materials provided with the distribution. 14 | # 15 | # 3. Neither the name of the copyright holder nor the names of its 16 | # contributors may be used to endorse or promote products derived from 17 | # this software without specific prior written permission. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 20 | # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 | # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 22 | # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 25 | # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | QT += core gui 32 | QT += network 33 | QT += xml 34 | 35 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 36 | 37 | CONFIG += c++11 38 | 39 | # The following define makes your compiler emit warnings if you use 40 | # any Qt feature that has been marked deprecated (the exact warnings 41 | # depend on your compiler). Please consult the documentation of the 42 | # deprecated API in order to know how to port your code away from it. 43 | DEFINES += QT_DEPRECATED_WARNINGS 44 | 45 | # You can also make your code fail to compile if it uses deprecated APIs. 46 | # In order to do so, uncomment the following line. 47 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 48 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 49 | 50 | SOURCES += cloudlogcatqt.cpp \ 51 | main.cpp 52 | 53 | HEADERS += cloudlogcatqt.h 54 | 55 | FORMS += cloudlogcatqt.ui 56 | 57 | # Default rules for deployment. 58 | qnx: target.path = /tmp/$${TARGET}/bin 59 | else: unix:!android: target.path = /opt/$${TARGET}/bin 60 | !isEmpty(target.path): INSTALLS += target 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CloudLogCatQt 2 | 3 | Qt app that can be compiled on Linux, Windows or Mac for providing CAT support for Cloudlog (http://www.cloudlog.co.uk/). 4 | The app uses a connection to FlRig (http://www.w1hkj.com) 5 | 6 | _The app is still in development and therefore it can not be considered as fully stable._ 7 | 8 | ## Table of Contents 9 | 10 | - [CloudLogCatQt](#cloudlogcatqt) 11 | - [Table of Contents](#table-of-contents) 12 | - [Build](#build) 13 | - [Linux](#linux) 14 | - [macOS](#macos) 15 | - [Side Notes](#side-notes) 16 | - [Windows](#windows) 17 | - [Settings](#settings) 18 | - [Screenshots](#screenshots) 19 | 20 | ## Build 21 | 22 | ### Linux 23 | 24 | ```bash 25 | apt install qt5-default 26 | git clone --recursive https://github.com/myzinsky/CloudLogCatQt.git 27 | cd CloudLogCatQt 28 | mkdir build 29 | cd build 30 | qmake ../CloudLogCatQt.pro 31 | make -j4 32 | ``` 33 | 34 | ### macOS 35 | 36 | 1. Install [Homebrew] 37 | 2. Open a Terminal 38 | 3. Run `brew install qt@5` 39 | 4. Clone this repository and _cd_ into it 40 | 5. `mkdir build` 41 | 6. `cd build` 42 | 7. `/usr/local/opt/qt@5/bin/qmake ../CloudLogCatQt.pro` 43 | 8. `make -j4` 44 | 45 | 46 | #### Side Notes 47 | 48 | After successfully installing [Homebrew], take a look at the output in the terminal. You'll find a "Caveats" block having some information on the installation paths of Qt5. Maybe you have to adapt Step 7 to your needs. 49 | 50 | _Terminal output example:_ 51 | 52 | Caveats 53 | We agreed to the Qt open source license for you. 54 | If this is unacceptable you should uninstall. 55 | 56 | qt@5 is keg-only, which means it was not symlinked into /usr/local, 57 | because this is an alternate version of another formula. 58 | 59 | If you need to have qt@5 first in your PATH, run: 60 | echo 'export PATH="/usr/local/opt/qt@5/bin:$PATH"' >> /Users/michael/.bash_profile 61 | 62 | For compilers to find qt@5 you may need to set: 63 | export LDFLAGS="-L/usr/local/opt/qt@5/lib" 64 | export CPPFLAGS="-I/usr/local/opt/qt@5/include" 65 | 66 | ### Windows 67 | 68 | For building CloudLogCatQt on Windows 10 follow the steps below. 69 | 70 | 1. Install [Chocolatey] (The Package Manager For Windows) 71 | 2. Open an elevated PowerShell and run 72 | `choco install -y qt5-default cmake qtcreator` 73 | 3. Clone this repository 74 | 4. Start _QT Creator_ 75 | 5. Open project file [CloudLogCatQt.pro]() 76 | 6. Change the projects build settings for _Release_ and add a _Custom Process Step_ 77 | - Command: `%{Qt:QT_INSTALL_BINS}\windeployqt.exe` 78 | - Arguments: `%{buildDir}\release` 79 | - Working directory: `%{buildDir}\release` 80 | 7. Click on _Build Project_ [`CTRL+B`] 81 | 8. The release and all it's dependencies should now be located in the _Build directory_ as defined in the Projects Build Settings (e.g. in _build-CloudLogCatQt-Desktop-Release/release_ next to your project) 82 | 83 | _Read more on the deployment process: [Qt for Windows - Deployment]_ 84 | 85 | ## Settings 86 | 87 | The settings are almost self explaining. According to https://github.com/magicbug/Cloudlog/wiki/API create an API key and fill this together with your CloudLog URL e.g. ```https:///index.php/api/radio``` into the settings pane. Furthermore, add the conneciton to FlRig. The default settings are ```localhost``` and the port ```12345``` 88 | 89 | Besides that you can optionally configure local oscillators for RX and TX (e.g. if you are using a transverter). The output power can be set (is not read from CAT). If you make use of specific propagation modes this can also be selected from a pre-defined list. For SAT QSOs you can also select the satellite name from the drop-down menu. This list is read from an external file called `sat.dat` which you my need to copy to the folder the executable is in. 90 | 91 | With version 2 of Cloudlog there is also an option to configure an identifier. This enables for distinguishing more than one runnig instance of CloudLogCatQt without overwriting each other on the Cloudlog side. The identifier is shown in the hardware interfaces section as well as the drop-down menu during station selection when logging a QSO. 92 | 93 | ![CloudLogCatQt in Hardware Interfaces Section](doc/HardwareInterfaces.png "Hardware Interfaces") 94 | 95 | ![CloudLogCatQt Instances selectable during QSO Logging](doc/CATSelection.png "CAT Selection") 96 | 97 | ## Screenshots 98 | 99 | **Linux** 100 | 101 | ![CloudLogCatQt Linux Screenshot](doc/Linux.png "CloudLogCatQt") 102 | 103 | **macOS** 104 | 105 | ![CloudLogCatQt macOS Screenshot](doc/CloudLogCATQt.png "CloudLogCatQt") 106 | 107 | **Windows** 108 | 109 | ![CloudLogCatQt Windows Screenshot](doc/Windows.png "CloudLogCatQt") 110 | 111 | 112 | 113 | [Chocolatey]: https://chocolatey.org/install 114 | [Homebrew]: https://brew.sh 115 | [Qt for Windows - Deployment]: https://doc.qt.io/qt-5/windows-deployment.html 116 | -------------------------------------------------------------------------------- /cloudlogcatqt.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020, Matthias Jung (DL9MJ) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * 3. Neither the name of the copyright holder nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 26 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | * 32 | */ 33 | 34 | #include "cloudlogcatqt.h" 35 | #include "ui_cloudlogcatqt.h" 36 | 37 | CloudLogCATQt::CloudLogCATQt(QWidget *parent) 38 | : QMainWindow(parent) 39 | , ui(new Ui::CloudLogCATQt) 40 | { 41 | ui->setupUi(this); 42 | timerId = startTimer(1000); 43 | 44 | // Setup HTTP Request Managers: 45 | frequencyManager = new QNetworkAccessManager(this); 46 | connect(frequencyManager, 47 | SIGNAL(finished(QNetworkReply*)), 48 | this, 49 | SLOT(callbackFrequency(QNetworkReply*)) 50 | ); 51 | 52 | modeManager = new QNetworkAccessManager(this); 53 | connect(modeManager, 54 | SIGNAL(finished(QNetworkReply*)), 55 | this, 56 | SLOT(callbackMode(QNetworkReply*)) 57 | ); 58 | 59 | powerManager = new QNetworkAccessManager(this); 60 | connect(powerManager, 61 | SIGNAL(finished(QNetworkReply*)), 62 | this, 63 | SLOT(callbackPower(QNetworkReply*)) 64 | ); 65 | 66 | cloudLogManager = new QNetworkAccessManager(this); 67 | connect(cloudLogManager, 68 | SIGNAL(finished(QNetworkReply*)), 69 | this, 70 | SLOT(callbackCloudLog(QNetworkReply*)) 71 | ); 72 | 73 | QObject::connect(ui->propMode, 74 | SIGNAL(currentTextChanged(QString)), 75 | this, 76 | SLOT(callbackPropMode()) 77 | ); 78 | 79 | QObject::connect(ui->satellite, 80 | SIGNAL(currentTextChanged(QString)), 81 | this, 82 | SLOT(callbackSatellite()) 83 | ); 84 | 85 | // Setup prop modes 86 | propModes = (QStringList()<<"" 87 | <<"AS|Aircraft Scatter" 88 | <<"AUE|Aurora-E" 89 | <<"AUR|Aurora" 90 | <<"BS|Back scatter" 91 | <<"ECH|EchoLink" 92 | <<"EME|Earth-Moon-Earth" 93 | <<"ES|Sporadic E" 94 | <<"F2|F2 Reflection" 95 | <<"FAI|Field Aligned Irregularities" 96 | <<"INTERNET|Internet-assisted" 97 | <<"ION|Ionoscatter" 98 | <<"IRL|IRLP" 99 | <<"MS|Meteor scatter" 100 | <<"RPT|Terrestrial or atmospheric repeater or transponder" 101 | <<"RS|Rain scatter" 102 | <<"SAT|Satellite" 103 | <<"TEP|Trans-equatorial" 104 | <<"TR|Tropospheric ducting" 105 | ); 106 | ui->propMode->addItems(propModes); 107 | 108 | // Setup satellite names 109 | QFile file("sat.dat"); 110 | QTextStream stream(&file); 111 | QString line; 112 | satNames.append(""); 113 | 114 | if(file.open (QIODevice::ReadOnly | QIODevice::Text)) 115 | { 116 | while (!stream.atEnd()) 117 | { 118 | line = stream.readLine (); 119 | if(!line.isNull ()) 120 | { 121 | satNames.append(line); 122 | } 123 | } 124 | stream.flush(); 125 | file.close(); 126 | } 127 | ui->satellite->addItems(satNames); 128 | 129 | // Setup Settings File: 130 | settingsFile = QApplication::applicationDirPath() + "/settings.ini"; 131 | loadSettings(); 132 | txOffset = ui->TXOffset->text().toDouble(); 133 | qDebug() << "TX Offset:" << txOffset << "Hz"; 134 | rxOffset = ui->RXOffset->text().toDouble(); 135 | qDebug() << "RX Offset:" << rxOffset << "Hz"; 136 | propModeDesc = ui->propMode->currentText(); 137 | propMode = propModeDesc.split('|'); 138 | qDebug() << "Prop Mode:" << propMode[0]; 139 | satelliteDesc = ui->satellite->currentText(); 140 | satellite = satelliteDesc.split('|'); 141 | qDebug() << "Sat:" << satellite[0]; 142 | realTxFrequency = 0.0; 143 | realRxFrequency = 0.0; 144 | 145 | // Set Status Bar 146 | ui->statusbar->showMessage("(c) 2020 DL9MJ"); 147 | 148 | // Set Placeholders 149 | ui->cloudLogUrl->setPlaceholderText("https://yourdomain.com/index.php/api/radio"); 150 | ui->cloudLogKey->setPlaceholderText("cl632adab771259"); 151 | ui->cloudLogIdentifier->setPlaceholderText("Rig Name"); 152 | ui->FLRigHostname->setPlaceholderText("localhost"); 153 | ui->FLRigPort->setPlaceholderText("12345"); 154 | ui->TXOffset->setPlaceholderText("0"); 155 | ui->RXOffset->setPlaceholderText("0"); 156 | 157 | // Set Input Constraints 158 | QRegExp identifierRe("[ \\w\\d-_#]{0,50}"); 159 | QRegExpValidator *idValidator = new QRegExpValidator(identifierRe, this); 160 | ui->cloudLogIdentifier->setValidator(idValidator); 161 | QRegExp loRe("\\d*"); 162 | QRegExpValidator *loValidator = new QRegExpValidator(loRe, this); 163 | ui->TXOffset->setValidator(loValidator); 164 | ui->RXOffset->setValidator(loValidator); 165 | } 166 | 167 | CloudLogCATQt::~CloudLogCATQt() 168 | { 169 | killTimer(timerId); 170 | delete ui; 171 | } 172 | 173 | void CloudLogCATQt::timerEvent(QTimerEvent *event) 174 | { 175 | getMode(); 176 | getFrequency(); 177 | getPower(); 178 | } 179 | 180 | QString CloudLogCATQt::parseXML(QString xml) 181 | { 182 | /* 183 | * 184 | * 185 | * 186 | * 187 | * XXX 188 | * 189 | * 190 | * 191 | */ 192 | 193 | QXmlStreamReader reader(xml); 194 | while(!reader.atEnd() && !reader.hasError()) { 195 | if(reader.readNext() == QXmlStreamReader::StartElement && reader.name() == "i4") { 196 | return reader.readElementText(); 197 | } 198 | } 199 | reader.clear(); 200 | reader.addData(xml); 201 | while(!reader.atEnd() && !reader.hasError()) { 202 | if(reader.readNext() == QXmlStreamReader::StartElement && reader.name() == "value") { 203 | return reader.readElementText(); 204 | } 205 | } 206 | 207 | return QString("ERROR"); 208 | } 209 | 210 | void CloudLogCATQt::uploadToCloudLog() 211 | { 212 | // Prevent upload until variables are set 213 | if (ui->cloudLogKey->text() == "" || mode == "") { 214 | return; 215 | } 216 | QDateTime currentTime = QDateTime::currentDateTime(); 217 | QByteArray data; 218 | 219 | propMode = propModeDesc.split('|'); 220 | satellite = satelliteDesc.split('|'); 221 | QString str = QString("") 222 | + "{" 223 | + "\"key\" : \"" + ui->cloudLogKey->text() + "\" ," 224 | + "\"radio\" : \"CloudLogCATQt (" + ui->cloudLogIdentifier->text() + ")\" ," 225 | + "\"prop_mode\" : \"" + propMode[0] + "\" ," 226 | + "\"frequency\" : \"" + QString{ "%1" }.arg( realTxFrequency, 1, 'f', 0) + "\" ," 227 | + "\"mode\" : \"" + mode + "\" ,"; 228 | if (propMode[0] == "SAT") { 229 | str += "\"sat_name\" : \"" + satellite[0] + "\" ," 230 | + "\"frequency_rx\" : \"" + QString{ "%1" }.arg( realRxFrequency, 1, 'f', 0) + "\" ," 231 | + "\"mode_rx\" : \"" + mode + "\" ,"; 232 | } 233 | str += "\"power\" : \"" + QString{ "%1" }.arg(power) + "\" ," 234 | + "\"timestamp\" : \"" + currentTime.toString("yyyy/MM/dd hh:mm") + "\"" 235 | + "}"; 236 | data = str.toUtf8(); 237 | 238 | QUrl url = QUrl(ui->cloudLogUrl->text()); 239 | 240 | QNetworkRequest request(url); 241 | request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json")); 242 | cloudLogManager->post(request, data); 243 | 244 | qDebug() << "Update Cloud Log: " << data; 245 | ui->statusbar->showMessage("Cloudlog Updated: " 246 | + currentTime.toString("yyyy/MM/dd hh:mm:ss") 247 | + " | (c) 2020 DL9MJ"); 248 | } 249 | 250 | void CloudLogCATQt::loadSettings() 251 | { 252 | qDebug() << "LOAD"; 253 | QSettings settings(settingsFile, QSettings::IniFormat); 254 | 255 | ui->cloudLogUrl->setText(settings.value("cloudLogUrl","").toString()); 256 | ui->cloudLogKey->setText(settings.value("cloudLogKey","").toString()); 257 | ui->cloudLogIdentifier->setText(settings.value("cloudLogIdentifier","").toString()); 258 | ui->FLRigHostname->setText(settings.value("FLRigHostname", "localhost").toString()); 259 | ui->FLRigPort->setText(settings.value("FLRigPort", "12345").toString()); 260 | ui->TXOffset->setText(settings.value("TXOffset", "0").toString()); 261 | ui->RXOffset->setText(settings.value("RXOffset", "0").toString()); 262 | propModeShort = settings.value("PropMode", "").toString(); 263 | for (int i=0; ipropMode->findText(propModeDesc); 270 | ui->propMode->setCurrentIndex(index); 271 | 272 | satelliteShort = settings.value("Sat", "").toString(); 273 | for (int i=0; isatellite->findText(satelliteDesc); 280 | ui->satellite->setCurrentIndex(index); 281 | } 282 | 283 | void CloudLogCATQt::callbackFrequency(QNetworkReply *rep) 284 | { 285 | double f = parseXML(QString(rep->readAll())).toDouble(); 286 | 287 | if(f != frequency) { // Update UI and Cloudlog 288 | frequency = f; 289 | realTxFrequency = frequency; 290 | if (txOffset != 0.0) { 291 | realTxFrequency += txOffset; 292 | } 293 | if (rxOffset != 0.0) { 294 | realRxFrequency = frequency + rxOffset; 295 | } 296 | ui->lcdNumber->display(QString{ "%1" }.arg(realTxFrequency/1000.0/1000.0, 6, 'f', 5, '0' )); 297 | uploadToCloudLog(); 298 | } 299 | } 300 | 301 | void CloudLogCATQt::callbackMode(QNetworkReply *rep) 302 | { 303 | QString m = parseXML(QString(rep->readAll())); 304 | if(m != mode) { // Update UI and Cloudlog 305 | mode = m; 306 | ui->mode->setText(mode); 307 | qDebug() << mode; 308 | uploadToCloudLog(); 309 | } 310 | } 311 | 312 | void CloudLogCATQt::callbackCloudLog(QNetworkReply *rep) 313 | { 314 | qDebug () << QString(rep->readAll()); 315 | } 316 | 317 | void CloudLogCATQt::callbackPower(QNetworkReply *rep) 318 | { 319 | int p = parseXML(QString(rep->readAll())).toInt(); 320 | if(p != power) { // Update UI and Cloudlog 321 | power = p; 322 | ui->Power->setValue(power); 323 | uploadToCloudLog(); 324 | } 325 | 326 | } 327 | 328 | void CloudLogCATQt::callbackPropMode() 329 | { 330 | propModeDesc = ui->propMode->currentText(); 331 | QStringList temp = propModeDesc.split('|'); 332 | if (temp[0] == "SAT") { 333 | ui->satellite->setEnabled(true); 334 | } else { 335 | ui->satellite->setEnabled(false); 336 | } 337 | uploadToCloudLog(); 338 | } 339 | 340 | void CloudLogCATQt::callbackSatellite() 341 | { 342 | satelliteDesc = ui->satellite->currentText(); 343 | uploadToCloudLog(); 344 | } 345 | 346 | void CloudLogCATQt::getFromFLRig(QString command, QNetworkAccessManager *manager) 347 | { 348 | QByteArray data; 349 | data.append("" 350 | + command 351 | + ""); 352 | 353 | QUrl url = QUrl("http://"+ui->FLRigHostname->text()); 354 | url.setPort(ui->FLRigPort->text().toInt()); 355 | 356 | QNetworkRequest request(url); 357 | request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/x-www-form-urlencoded")); 358 | manager->post(request, data); 359 | } 360 | 361 | void CloudLogCATQt::getFrequency() 362 | { 363 | getFromFLRig("rig.get_vfo", frequencyManager); 364 | } 365 | 366 | void CloudLogCATQt::getMode() 367 | { 368 | getFromFLRig("rig.get_mode", modeManager); 369 | } 370 | 371 | void CloudLogCATQt::getPower() 372 | { 373 | getFromFLRig("rig.get_power", powerManager); 374 | } 375 | 376 | void CloudLogCATQt::on_save_clicked() 377 | { 378 | qDebug() << "SAVE"; 379 | QSettings settings(settingsFile, QSettings::IniFormat); 380 | 381 | propModeDesc = ui->propMode->currentText(); 382 | QStringList propMode = propModeDesc.split('|'); 383 | satelliteDesc = ui->satellite->currentText(); 384 | QStringList satellite = satelliteDesc.split('|'); 385 | settings.setValue("cloudLogUrl", ui->cloudLogUrl->text()); 386 | settings.setValue("cloudLogKey", ui->cloudLogKey->text()); 387 | settings.setValue("cloudLogIdentifier", ui->cloudLogIdentifier->text()); 388 | settings.setValue("FLRigHostname", ui->FLRigHostname->text()); 389 | settings.setValue("FLRigPort", ui->FLRigPort->text()); 390 | settings.setValue("TXOffset", ui->TXOffset->text()); 391 | settings.setValue("RXOffset", ui->RXOffset->text()); 392 | settings.setValue("Power", ui->Power->text()); 393 | settings.setValue("PropMode", propMode[0]); 394 | settings.setValue("Sat", satellite[0]); 395 | txOffset = ui->TXOffset->text().toDouble(); 396 | rxOffset = ui->RXOffset->text().toDouble(); 397 | } 398 | -------------------------------------------------------------------------------- /cloudlogcatqt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020, Matthias Jung (DL9MJ) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * 3. Neither the name of the copyright holder nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 26 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | * 32 | */ 33 | 34 | #ifndef CLOUDLOGCATMACOS_H 35 | #define CLOUDLOGCATMACOS_H 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | QT_BEGIN_NAMESPACE 46 | namespace Ui { class CloudLogCATQt; } 47 | QT_END_NAMESPACE 48 | 49 | class CloudLogCATQt : public QMainWindow 50 | { 51 | Q_OBJECT 52 | 53 | public: 54 | CloudLogCATQt(QWidget *parent = nullptr); 55 | ~CloudLogCATQt(); 56 | 57 | private slots: 58 | void callbackFrequency(QNetworkReply *rep); 59 | void callbackMode(QNetworkReply *rep); 60 | void callbackCloudLog(QNetworkReply *rep); 61 | void callbackPower(QNetworkReply *rep); 62 | void callbackPropMode(); 63 | void callbackSatellite(); 64 | 65 | void on_save_clicked(); 66 | 67 | private: 68 | Ui::CloudLogCATQt *ui; 69 | int timerId; 70 | void getFrequency(); 71 | void getMode(); 72 | void getPower(); 73 | void getFromFLRig(QString command, QNetworkAccessManager *manager); 74 | QString parseXML(QString xml); 75 | void uploadToCloudLog(); 76 | void loadSettings(); 77 | 78 | QNetworkAccessManager *frequencyManager; 79 | QNetworkAccessManager *modeManager; 80 | QNetworkAccessManager *powerManager; 81 | QNetworkAccessManager *cloudLogManager; 82 | double frequency; 83 | double realTxFrequency; 84 | double realRxFrequency; 85 | QString mode; 86 | QString propModeDesc; 87 | QString propModeShort; 88 | QStringList propMode; 89 | QStringList propModes; 90 | QStringList satNames; 91 | QString satelliteDesc; 92 | QString satelliteShort; 93 | QStringList satellite; 94 | double txOffset; 95 | double rxOffset; 96 | int power; 97 | 98 | QString settingsFile; 99 | 100 | protected: 101 | void timerEvent(QTimerEvent *event); 102 | 103 | }; 104 | #endif // CLOUDLOGCATMACOS_H 105 | -------------------------------------------------------------------------------- /cloudlogcatqt.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | CloudLogCATQt 4 | 5 | 6 | 7 | 0 8 | 0 9 | 415 10 | 515 11 | 12 | 13 | 14 | CloudLogCATQt 15 | 16 | 17 | 18 | 19 | 389 20 | 0 21 | 22 | 23 | 24 | 25 | 26 | 27 | Save 28 | 29 | 30 | 31 | 32 | 33 | 34 | QFrame::Box 35 | 36 | 37 | QFrame::Plain 38 | 39 | 40 | false 41 | 42 | 43 | 12 44 | 45 | 46 | QLCDNumber::Filled 47 | 48 | 49 | 0.000000000000000 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 0 58 | 0 59 | 60 | 61 | 62 | 63 | 50 64 | 16777215 65 | 66 | 67 | 68 | Mode 69 | 70 | 71 | 72 | 73 | 74 | 75 | QLayout::SetDefaultConstraint 76 | 77 | 78 | QFormLayout::ExpandingFieldsGrow 79 | 80 | 81 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 82 | 83 | 84 | 20 85 | 86 | 87 | 6 88 | 89 | 90 | 0 91 | 92 | 93 | 0 94 | 95 | 96 | 97 | 98 | TX LO Offset (Hz): 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | RX LO Offset (Hz): 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | Power (W): 119 | 120 | 121 | 122 | 123 | 124 | 125 | 10000 126 | 127 | 128 | 129 | 130 | 131 | 132 | Propagation Mode: 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | Satellite: 143 | 144 | 145 | 146 | 147 | 148 | 149 | false 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 120 158 | 16777215 159 | 160 | 161 | 162 | FLRig Hostname: 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 0 171 | 0 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 120 184 | 16777215 185 | 186 | 187 | 188 | FLRig Port: 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 120 204 | 16777215 205 | 206 | 207 | 208 | CloudLog Url: 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 120 224 | 16777215 225 | 226 | 227 | 228 | 229 | 120 230 | 0 231 | 232 | 233 | 234 | Cloudlog Key: 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | Cloudlog Identifier: 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 0 263 | 0 264 | 415 265 | 22 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | -------------------------------------------------------------------------------- /doc/CATSelection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myzinsky/CloudLogCatQt/c067920158675c40d180d9139043c37d28d5cb9b/doc/CATSelection.png -------------------------------------------------------------------------------- /doc/CloudLogCATQt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myzinsky/CloudLogCatQt/c067920158675c40d180d9139043c37d28d5cb9b/doc/CloudLogCATQt.png -------------------------------------------------------------------------------- /doc/HardwareInterfaces.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myzinsky/CloudLogCatQt/c067920158675c40d180d9139043c37d28d5cb9b/doc/HardwareInterfaces.png -------------------------------------------------------------------------------- /doc/Linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myzinsky/CloudLogCatQt/c067920158675c40d180d9139043c37d28d5cb9b/doc/Linux.png -------------------------------------------------------------------------------- /doc/Windows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myzinsky/CloudLogCatQt/c067920158675c40d180d9139043c37d28d5cb9b/doc/Windows.png -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020, Matthias Jung (DL9MJ) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * 3. Neither the name of the copyright holder nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 26 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | * 32 | */ 33 | 34 | #include "cloudlogcatqt.h" 35 | 36 | #include 37 | 38 | int main(int argc, char *argv[]) 39 | { 40 | QApplication a(argc, argv); 41 | CloudLogCATQt w; 42 | w.show(); 43 | return a.exec(); 44 | } 45 | -------------------------------------------------------------------------------- /sat.dat: -------------------------------------------------------------------------------- 1 | AISAT1|AISAT-1 AMSAT India APRS Digipeater 2 | AO-10|AMSAT-OSCAR 10 3 | AO-109|AMSAT-OSCAR 109 4 | AO-13|AMSAT-OSCAR 13 5 | AO-16|AMSAT-OSCAR 16 6 | AO-21|OSCAR 21/RS-14 7 | AO-27|AMRAD-OSCAR 27 8 | AO-3|AMSAT-OSCAR 3 9 | AO-4|AMSAT-OSCAR 4 10 | AO-40|AMSAT-OSCAR 40 11 | AO-51|AMSAT-OSCAR 51 12 | AO-6|AMSAT-OSCAR 6 13 | AO-7|AMSAT-OSCAR 7 14 | AO-73|AMSAT-OSCAR 73 15 | AO-8|AMSAT-OSCAR 8 16 | AO-85|AMSAT-OSCAR 85 (Fox-1A) 17 | AO-91|AMSAT-OSCAR 91 (RadFxSat / Fox-1B) 18 | AO-92|AMSAT-OSCAR 92 (Fox-1D) 19 | ARISS|ARISS 20 | Arsene|OSCAR 24 21 | BO-102|BIT Progress-OSCAR 102 (CAS-7B) 22 | BY70-1|Bayi Kepu Weixing 1 23 | CAS-3H|LilacSat-2 24 | CAS-4A|CAMSAT 4A (CAS-4A) 25 | CAS-4B|CAMSAT 4B (CAS-4B) 26 | DO-64|Delfi OSCAR-64 27 | EO-79|FUNcube-3 28 | EO-88|Emirates-OSCAR 88 (Nayif-1) 29 | FO-12|Fuji-OSCAR 12 30 | FO-20|Fuji-OSCAR 20 31 | FO-29|Fuji-OSCAR 29 32 | FO-99|Fuji-OSCAR 99 (NEXUS) 33 | FS-3|FalconSAT 3 34 | HO-107|HuskySat OSCAR 107 35 | HO-113|HO-113 36 | HO-68|Hope-Oscar 68 37 | IO-86|Indonesia-OSCAR 86 (LAPAN-ORARI) 38 | JO-97|Jordan-OSCAR 97(JY1Sat) 39 | KEDR|ARISSat-1 40 | LO-19|Lusat-OSCAR 19 41 | LO-78|LituanicaSAT-1 42 | LO-87|LUSEX-OSCAR 87 43 | LO-90|LilacSat-OSCAR 90 (LilacSat-1) 44 | MAYA-3|Cubesat 45 | MAYA-4|Cubesat 46 | MIREX|MIR Packet Digipeater 47 | NO-103|Navy-OSCAR 103 (BRICSAT 2) 48 | NO-104|Navy-OSCAR 104 (PSAT 2) 49 | NO-44|Navy-OSCAR 44 50 | NO-83|BRICsat 51 | NO-84|PSAT 52 | PO-101|Phillipines-OSCAR-101 (Diwata-2) 53 | QO-100|Qatar-OSCAR 100 (Es'hail-2/P4A) 54 | RS-1|Radio Sputnik 1 55 | RS-10|Radio Sputnik 10 56 | RS-11|Radio Sputnik 11 57 | RS-12|Radio Sputnik 12 58 | RS-13|Radio Sputnik 13 59 | RS-15|Radio Sputnik 15 60 | RS-2|Radio Sputnik 2 61 | RS-44|Radio Sputnik 44 (DOSAAF-85) 62 | RS-5|Radio Sputnik 5 63 | RS-6|Radio Sputnik 6 64 | RS-7|Radio Sputnik 7 65 | RS-8|Radio Sputnik 8 66 | SAREX|Shuttle Amateur Radio Experiment (SAREX) Digipeater 67 | SO-35|Sunsat-OSCAR 35 68 | SO-41|Saudi-OSCAR 41 69 | SO-50|Saudi-OSCAR 50 70 | SO-67|Sumbandila Oscar 67 71 | TAURUS|Taurus-1 (Jinniuzuo-1) 72 | TO-108|TQ-OSCAR 108 (CAS-6 / TQ-1) 73 | UKUBE1|UKube-1 (FUNcube-2) 74 | UO-14|UOSAT-OSCAR 14 75 | UVSQ|CubeSat 76 | VO-52|VUsat-OSCAR 52 77 | XW-2A|Hope 2A (CAS-3A) 78 | XW-2B|Hope 2B (CAS-3B) 79 | XW-2C|Hope 2C (CAS-3C) 80 | XW-2D|Hope 2D (CAS-3D) 81 | XW-2E|Hope 2E (CAS-3E) 82 | XW-2F|Hope 2F (CAS-2F) --------------------------------------------------------------------------------