mirror of
https://github.com/DJ2LS/FreeDATA
synced 2024-05-14 08:04:33 +00:00
Merge remote-tracking branch 'origin/main' into ls-arq
This commit is contained in:
commit
92f5e6e03e
32 changed files with 11554 additions and 7729 deletions
7
.github/ISSUE_TEMPLATE/bug_report.md
vendored
7
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -1,10 +1,9 @@
|
||||||
---
|
---
|
||||||
name: Bug report
|
name: Bug report
|
||||||
about: Create a report to help us improve FreeDATA
|
about: Create a report to help us improve FreeDATA
|
||||||
title: ''
|
title: ""
|
||||||
labels: bug
|
labels: bug
|
||||||
assignees: ''
|
assignees: ""
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Describe the bug**
|
**Describe the bug**
|
||||||
|
@ -12,6 +11,7 @@ A clear and concise description of what the bug is.
|
||||||
|
|
||||||
**To Reproduce**
|
**To Reproduce**
|
||||||
Steps to reproduce the behavior:
|
Steps to reproduce the behavior:
|
||||||
|
|
||||||
1. Go to '...'
|
1. Go to '...'
|
||||||
2. Click on '....'
|
2. Click on '....'
|
||||||
3. Scroll down to '....'
|
3. Scroll down to '....'
|
||||||
|
@ -27,6 +27,7 @@ https://wiki.freedata.app/en/usage/logging
|
||||||
If applicable, add screenshots to help explain your problem.
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
**Desktop (please complete the following information):**
|
**Desktop (please complete the following information):**
|
||||||
|
|
||||||
- OS: [e.g. iOS]
|
- OS: [e.g. iOS]
|
||||||
- Version [e.g. 22]
|
- Version [e.g. 22]
|
||||||
- Platform [Raspberry Pi, Desktop]
|
- Platform [Raspberry Pi, Desktop]
|
||||||
|
|
5
.github/ISSUE_TEMPLATE/feature_request.md
vendored
5
.github/ISSUE_TEMPLATE/feature_request.md
vendored
|
@ -1,10 +1,9 @@
|
||||||
---
|
---
|
||||||
name: Feature request
|
name: Feature request
|
||||||
about: Suggest an idea for this project
|
about: Suggest an idea for this project
|
||||||
title: ''
|
title: ""
|
||||||
labels: feature request
|
labels: feature request
|
||||||
assignees: ''
|
assignees: ""
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
|
21
.github/workflows/prettier.yaml
vendored
Normal file
21
.github/workflows/prettier.yaml
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
name: Prettier
|
||||||
|
|
||||||
|
# This action works with pull requests and pushes
|
||||||
|
on: [push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
prettier:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
# Make sure the actual branch is checked out when running on pull requests
|
||||||
|
ref: ${{ github.head_ref }}
|
||||||
|
|
||||||
|
- name: Prettify code
|
||||||
|
uses: creyD/prettier_action@v4.2
|
||||||
|
with:
|
||||||
|
# This part is also where you can pass other options, for example:
|
||||||
|
prettier_options: --write **/*.{js,md,css,html}
|
5
.prettierignore
Normal file
5
.prettierignore
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# Ignore artifacts:
|
||||||
|
build
|
||||||
|
coverage
|
||||||
|
assets
|
||||||
|
gui/src/waterfall
|
14
README.md
14
README.md
|
@ -1,4 +1,5 @@
|
||||||
# FreeDATA
|
# FreeDATA
|
||||||
|
|
||||||
My attempt to create a free and open-source TNC with a GUI for [codec2](https://github.com/drowe67/codec2) with the idea of sending messages and data from one network based application.
|
My attempt to create a free and open-source TNC with a GUI for [codec2](https://github.com/drowe67/codec2) with the idea of sending messages and data from one network based application.
|
||||||
|
|
||||||
[mailing-list](https://groups.io/g/freedata)
|
[mailing-list](https://groups.io/g/freedata)
|
||||||
|
@ -8,10 +9,10 @@ My attempt to create a free and open-source TNC with a GUI for [codec2](https://
|
||||||
![Build](https://github.com/DJ2LS/FreeDATA/actions/workflows/build_multiplatform.yml/badge.svg)
|
![Build](https://github.com/DJ2LS/FreeDATA/actions/workflows/build_multiplatform.yml/badge.svg)
|
||||||
[![CodeFactor](https://www.codefactor.io/repository/github/dj2ls/freedata/badge)](https://www.codefactor.io/repository/github/dj2ls/freedata)
|
[![CodeFactor](https://www.codefactor.io/repository/github/dj2ls/freedata/badge)](https://www.codefactor.io/repository/github/dj2ls/freedata)
|
||||||
|
|
||||||
|
|
||||||
Please keep in mind, this project is still under development with many issues which need to be solved.
|
Please keep in mind, this project is still under development with many issues which need to be solved.
|
||||||
|
|
||||||
### existing/planned TNC features
|
### existing/planned TNC features
|
||||||
|
|
||||||
- [x] network based
|
- [x] network based
|
||||||
- [x] raw data transfer
|
- [x] raw data transfer
|
||||||
- [x] fft output
|
- [x] fft output
|
||||||
|
@ -24,7 +25,9 @@ Please keep in mind, this project is still under development with many issues wh
|
||||||
- [x] channel measurement
|
- [x] channel measurement
|
||||||
- [ ] hybrid ARQ
|
- [ ] hybrid ARQ
|
||||||
- [ ] tbc...
|
- [ ] tbc...
|
||||||
|
|
||||||
### existing/planned Chat features
|
### existing/planned Chat features
|
||||||
|
|
||||||
- [x] chat messages
|
- [x] chat messages
|
||||||
- [x] file transfer
|
- [x] file transfer
|
||||||
- [x] file transfer with chat message
|
- [x] file transfer with chat message
|
||||||
|
@ -38,18 +41,21 @@ Please keep in mind, this project is still under development with many issues wh
|
||||||
- [ ] tbc...
|
- [ ] tbc...
|
||||||
|
|
||||||
## Data Preview
|
## Data Preview
|
||||||
|
|
||||||
![preview](https://github.com/DJ2LS/FreeDATA/blob/main/documentation/data_preview.gif?raw=true "Preview")
|
![preview](https://github.com/DJ2LS/FreeDATA/blob/main/documentation/data_preview.gif?raw=true "Preview")
|
||||||
|
|
||||||
## Chat Preview
|
## Chat Preview
|
||||||
|
|
||||||
![preview](https://github.com/DJ2LS/FreeDATA/blob/main/documentation/chat_preview_fast.gif?raw=true "Preview")
|
![preview](https://github.com/DJ2LS/FreeDATA/blob/main/documentation/chat_preview_fast.gif?raw=true "Preview")
|
||||||
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Please check the [wiki](https://wiki.freedata.app) for installation instructions
|
Please check the [wiki](https://wiki.freedata.app) for installation instructions
|
||||||
Please check the ['Releases'](https://github.com/DJ2LS/FreeDATA/releases) section for downloading precompiled builds
|
Please check the ['Releases'](https://github.com/DJ2LS/FreeDATA/releases) section for downloading precompiled builds
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
* David Rowe and the FreeDV team for developing the modem and libraries -
|
|
||||||
|
- David Rowe and the FreeDV team for developing the modem and libraries -
|
||||||
FreeDV Codec 2 : https://github.com/drowe67/codec2
|
FreeDV Codec 2 : https://github.com/drowe67/codec2
|
||||||
* xssfox, her repository helped a lot in an early stage of development -
|
- xssfox, her repository helped a lot in an early stage of development -
|
||||||
xssfox : https://github.com/xssfox/freedv-tnc
|
xssfox : https://github.com/xssfox/freedv-tnc
|
||||||
|
|
|
@ -1,21 +1,25 @@
|
||||||
# FreeDATA - DAEMON network documentation
|
# FreeDATA - DAEMON network documentation
|
||||||
|
|
||||||
|
|
||||||
## GET DAEMON STATE
|
## GET DAEMON STATE
|
||||||
|
|
||||||
#### Description:
|
#### Description:
|
||||||
|
|
||||||
Get the current daemon state
|
Get the current daemon state
|
||||||
|
|
||||||
#### Parameters
|
#### Parameters
|
||||||
|
|
||||||
- Type: GET
|
- Type: GET
|
||||||
- Command: DAEMON_STATE
|
- Command: DAEMON_STATE
|
||||||
- Parameter: --- (str)
|
- Parameter: --- (str)
|
||||||
|
|
||||||
#### Example
|
#### Example
|
||||||
|
|
||||||
```
|
```
|
||||||
{"type" : "GET", "command" : "DAEMON_STATE"}
|
{"type" : "GET", "command" : "DAEMON_STATE"}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Returns
|
#### Returns
|
||||||
|
|
||||||
```
|
```
|
||||||
{
|
{
|
||||||
"COMMAND": "DAEMON_STATE",
|
"COMMAND": "DAEMON_STATE",
|
||||||
|
@ -31,46 +35,52 @@ Get the current daemon state
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## SET CALLSIGN
|
## SET CALLSIGN
|
||||||
|
|
||||||
#### Description:
|
#### Description:
|
||||||
|
|
||||||
Save your callsign to the daemon
|
Save your callsign to the daemon
|
||||||
|
|
||||||
#### Parameters
|
#### Parameters
|
||||||
|
|
||||||
- Type: SET
|
- Type: SET
|
||||||
- Command: MYCALLSIGN
|
- Command: MYCALLSIGN
|
||||||
- Parameter: callsign (str)
|
- Parameter: callsign (str)
|
||||||
- timestamp: unix timestamp (str)
|
- timestamp: unix timestamp (str)
|
||||||
|
|
||||||
#### Example
|
#### Example
|
||||||
|
|
||||||
```
|
```
|
||||||
{"type" : "SET", "command": "MYCALLSIGN" , "parameter": "<callsign>", "timestamp" : "123456789"}
|
{"type" : "SET", "command": "MYCALLSIGN" , "parameter": "<callsign>", "timestamp" : "123456789"}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## SET GRIDSQUARE
|
## SET GRIDSQUARE
|
||||||
|
|
||||||
#### Description:
|
#### Description:
|
||||||
|
|
||||||
Save your gridsquare/maidenhead-locator to the daemon
|
Save your gridsquare/maidenhead-locator to the daemon
|
||||||
|
|
||||||
#### Parameters
|
#### Parameters
|
||||||
|
|
||||||
- Type: SET
|
- Type: SET
|
||||||
- Command: MYGRID
|
- Command: MYGRID
|
||||||
- Parameter: gridsquare (str)
|
- Parameter: gridsquare (str)
|
||||||
- timestamp: unix timestamp (str)
|
- timestamp: unix timestamp (str)
|
||||||
|
|
||||||
#### Example
|
#### Example
|
||||||
|
|
||||||
```
|
```
|
||||||
{"type" : "SET", "command": "MYGRID" , "parameter": "<gridsquare>", "timestamp" : "123456789"}
|
{"type" : "SET", "command": "MYGRID" , "parameter": "<gridsquare>", "timestamp" : "123456789"}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## TEST HAMLIB
|
## TEST HAMLIB
|
||||||
|
|
||||||
#### Description:
|
#### Description:
|
||||||
|
|
||||||
Test your hamlib settings
|
Test your hamlib settings
|
||||||
|
|
||||||
#### Parameters
|
#### Parameters
|
||||||
|
|
||||||
- Type: GET
|
- Type: GET
|
||||||
- Command: TEST_HAMLIB
|
- Command: TEST_HAMLIB
|
||||||
- Parameter: obj
|
- Parameter: obj
|
||||||
|
@ -85,6 +95,7 @@ Test your hamlib settings
|
||||||
- timestamp: unix timestamp (str)
|
- timestamp: unix timestamp (str)
|
||||||
|
|
||||||
#### Example
|
#### Example
|
||||||
|
|
||||||
```
|
```
|
||||||
{
|
{
|
||||||
"type": "GET",
|
"type": "GET",
|
||||||
|
@ -102,12 +113,14 @@ Test your hamlib settings
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## START TNC
|
## START TNC
|
||||||
|
|
||||||
#### Description:
|
#### Description:
|
||||||
|
|
||||||
Start the tnc process
|
Start the tnc process
|
||||||
|
|
||||||
#### Parameters
|
#### Parameters
|
||||||
|
|
||||||
- Type: GET
|
- Type: GET
|
||||||
- Command: TEST_HAMLIB
|
- Command: TEST_HAMLIB
|
||||||
- Parameter: obj
|
- Parameter: obj
|
||||||
|
@ -125,6 +138,7 @@ Start the tnc process
|
||||||
- handshake
|
- handshake
|
||||||
|
|
||||||
#### Example
|
#### Example
|
||||||
|
|
||||||
```
|
```
|
||||||
{
|
{
|
||||||
type: 'SET',
|
type: 'SET',
|
||||||
|
@ -148,23 +162,19 @@ Start the tnc process
|
||||||
```
|
```
|
||||||
|
|
||||||
## STOP TNC
|
## STOP TNC
|
||||||
|
|
||||||
#### Description:
|
#### Description:
|
||||||
|
|
||||||
Stop the tnc process
|
Stop the tnc process
|
||||||
|
|
||||||
#### Parameters
|
#### Parameters
|
||||||
|
|
||||||
- Type: SET
|
- Type: SET
|
||||||
- Command: STOPTNC
|
- Command: STOPTNC
|
||||||
- Parameter: ---
|
- Parameter: ---
|
||||||
|
|
||||||
#### Example
|
#### Example
|
||||||
|
|
||||||
```
|
```
|
||||||
{"type" : "SET", "command": "STOPTNC" , "parameter": "---" }
|
{"type" : "SET", "command": "STOPTNC" , "parameter": "---" }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
272
gui/daemon.js
272
gui/daemon.js
|
@ -1,74 +1,72 @@
|
||||||
var net = require('net');
|
var net = require("net");
|
||||||
const path = require('path')
|
const path = require("path");
|
||||||
const {
|
const { ipcRenderer } = require("electron");
|
||||||
ipcRenderer
|
const log = require("electron-log");
|
||||||
} = require('electron')
|
const daemonLog = log.scope("daemon");
|
||||||
const log = require('electron-log');
|
|
||||||
const daemonLog = log.scope('daemon');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// https://stackoverflow.com/a/26227660
|
// https://stackoverflow.com/a/26227660
|
||||||
var appDataFolder = process.env.APPDATA || (process.platform == 'darwin' ? process.env.HOME + '/Library/Application Support' : process.env.HOME + "/.config")
|
var appDataFolder =
|
||||||
|
process.env.APPDATA ||
|
||||||
|
(process.platform == "darwin"
|
||||||
|
? process.env.HOME + "/Library/Application Support"
|
||||||
|
: process.env.HOME + "/.config");
|
||||||
var configFolder = path.join(appDataFolder, "FreeDATA");
|
var configFolder = path.join(appDataFolder, "FreeDATA");
|
||||||
var configPath = path.join(configFolder, 'config.json')
|
var configPath = path.join(configFolder, "config.json");
|
||||||
const config = require(configPath);
|
const config = require(configPath);
|
||||||
|
|
||||||
var daemon = new net.Socket();
|
var daemon = new net.Socket();
|
||||||
var socketchunk = ''; // Current message, per connection.
|
var socketchunk = ""; // Current message, per connection.
|
||||||
|
|
||||||
// global to keep track of daemon connection error emissions
|
// global to keep track of daemon connection error emissions
|
||||||
var daemonShowConnectStateError = 1
|
var daemonShowConnectStateError = 1;
|
||||||
|
|
||||||
// global for storing ip information
|
// global for storing ip information
|
||||||
var daemon_port = config.daemon_port;
|
var daemon_port = config.daemon_port;
|
||||||
var daemon_host = config.daemon_host;
|
var daemon_host = config.daemon_host;
|
||||||
|
|
||||||
setTimeout(connectDAEMON, 500)
|
setTimeout(connectDAEMON, 500);
|
||||||
|
|
||||||
function connectDAEMON() {
|
function connectDAEMON() {
|
||||||
if (daemonShowConnectStateError == 1) {
|
if (daemonShowConnectStateError == 1) {
|
||||||
daemonLog.info('connecting to daemon');
|
daemonLog.info("connecting to daemon");
|
||||||
}
|
}
|
||||||
|
|
||||||
//clear message buffer after reconnecting or initial connection
|
//clear message buffer after reconnecting or initial connection
|
||||||
socketchunk = '';
|
socketchunk = "";
|
||||||
|
|
||||||
if (config.tnclocation == 'localhost') {
|
if (config.tnclocation == "localhost") {
|
||||||
daemon.connect(3001, '127.0.0.1')
|
daemon.connect(3001, "127.0.0.1");
|
||||||
} else {
|
} else {
|
||||||
daemon.connect(daemon_port, daemon_host)
|
daemon.connect(daemon_port, daemon_host);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//client.setTimeout(5000);
|
//client.setTimeout(5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
daemon.on('connect', function(err) {
|
daemon.on("connect", function (err) {
|
||||||
daemonLog.info('daemon connection established');
|
daemonLog.info("daemon connection established");
|
||||||
let Data = {
|
let Data = {
|
||||||
daemon_connection: daemon.readyState,
|
daemon_connection: daemon.readyState,
|
||||||
};
|
};
|
||||||
ipcRenderer.send('request-update-daemon-connection', Data);
|
ipcRenderer.send("request-update-daemon-connection", Data);
|
||||||
|
|
||||||
daemonShowConnectStateError = 1
|
daemonShowConnectStateError = 1;
|
||||||
})
|
});
|
||||||
|
|
||||||
daemon.on('error', function(err) {
|
daemon.on("error", function (err) {
|
||||||
if (daemonShowConnectStateError == 1) {
|
if (daemonShowConnectStateError == 1) {
|
||||||
daemonLog.error('daemon connection error');
|
daemonLog.error("daemon connection error");
|
||||||
daemonLog.info('Make sure the daemon is started.');
|
daemonLog.info("Make sure the daemon is started.");
|
||||||
daemonLog.info('Run "python daemon.py" in the tnc directory.');
|
daemonLog.info('Run "python daemon.py" in the tnc directory.');
|
||||||
daemonLog.debug(err)
|
|
||||||
|
|
||||||
daemonShowConnectStateError = 0
|
daemonShowConnectStateError = 0;
|
||||||
}
|
}
|
||||||
setTimeout(connectDAEMON, 500)
|
setTimeout(connectDAEMON, 500);
|
||||||
daemon.destroy();
|
daemon.destroy();
|
||||||
let Data = {
|
let Data = {
|
||||||
daemon_connection: daemon.readyState,
|
daemon_connection: daemon.readyState,
|
||||||
};
|
};
|
||||||
ipcRenderer.send('request-update-daemon-connection', Data);
|
ipcRenderer.send("request-update-daemon-connection", Data);
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -82,127 +80,105 @@ client.on('close', function(data) {
|
||||||
});
|
});
|
||||||
*/
|
*/
|
||||||
|
|
||||||
daemon.on('end', function(data) {
|
daemon.on("end", function (data) {
|
||||||
|
daemonLog.warn("daemon connection ended");
|
||||||
daemonLog.warn('daemon connection ended');
|
|
||||||
daemon.destroy();
|
daemon.destroy();
|
||||||
setTimeout(connectDAEMON, 500)
|
setTimeout(connectDAEMON, 500);
|
||||||
let Data = {
|
let Data = {
|
||||||
daemon_connection: daemon.readyState,
|
daemon_connection: daemon.readyState,
|
||||||
};
|
};
|
||||||
ipcRenderer.send('request-update-daemon-connection', Data);
|
ipcRenderer.send("request-update-daemon-connection", Data);
|
||||||
});
|
});
|
||||||
|
|
||||||
//exports.writeCommand = function(command){
|
//exports.writeCommand = function(command){
|
||||||
writeDaemonCommand = function (command) {
|
writeDaemonCommand = function (command) {
|
||||||
|
|
||||||
// we use the writingCommand function to update our TCPIP state because we are calling this function a lot
|
// we use the writingCommand function to update our TCPIP state because we are calling this function a lot
|
||||||
// if socket opened, we are able to run commands
|
// if socket opened, we are able to run commands
|
||||||
if (daemon.readyState == 'open') {
|
if (daemon.readyState == "open") {
|
||||||
//uiMain.setDAEMONconnection('open')
|
//uiMain.setDAEMONconnection('open')
|
||||||
daemon.write(command + '\n');
|
daemon.write(command + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daemon.readyState == 'closed') {
|
if (daemon.readyState == "closed") {
|
||||||
//uiMain.setDAEMONconnection('closed')
|
//uiMain.setDAEMONconnection('closed')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daemon.readyState == 'opening') {
|
if (daemon.readyState == "opening") {
|
||||||
//uiMain.setDAEMONconnection('opening')
|
//uiMain.setDAEMONconnection('opening')
|
||||||
}
|
}
|
||||||
|
|
||||||
let Data = {
|
let Data = {
|
||||||
daemon_connection: daemon.readyState,
|
daemon_connection: daemon.readyState,
|
||||||
};
|
};
|
||||||
ipcRenderer.send('request-update-daemon-connection', Data);
|
ipcRenderer.send("request-update-daemon-connection", Data);
|
||||||
}
|
};
|
||||||
|
|
||||||
// "https://stackoverflow.com/questions/9070700/nodejs-net-createserver-large-amount-of-data-coming-in"
|
// "https://stackoverflow.com/questions/9070700/nodejs-net-createserver-large-amount-of-data-coming-in"
|
||||||
|
|
||||||
daemon.on('data', function(socketdata) {
|
daemon.on("data", function (socketdata) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
inspired by:
|
inspired by:
|
||||||
stackoverflow.com questions 9070700 nodejs-net-createserver-large-amount-of-data-coming-in
|
stackoverflow.com questions 9070700 nodejs-net-createserver-large-amount-of-data-coming-in
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
socketdata = socketdata.toString("utf8"); // convert data to string
|
||||||
socketdata = socketdata.toString('utf8'); // convert data to string
|
socketchunk += socketdata; // append data to buffer so we can stick long data together
|
||||||
socketchunk += socketdata// append data to buffer so we can stick long data together
|
|
||||||
|
|
||||||
|
|
||||||
// check if we received begin and end of json data
|
// check if we received begin and end of json data
|
||||||
if (socketchunk.startsWith('{"') && socketchunk.endsWith('"}\n')) {
|
if (socketchunk.startsWith('{"') && socketchunk.endsWith('"}\n')) {
|
||||||
|
var data = "";
|
||||||
var data = ''
|
|
||||||
|
|
||||||
// split data into chunks if we received multiple commands
|
// split data into chunks if we received multiple commands
|
||||||
socketchunk = socketchunk.split("\n");
|
socketchunk = socketchunk.split("\n");
|
||||||
data = JSON.parse(socketchunk[0])
|
data = JSON.parse(socketchunk[0]);
|
||||||
|
|
||||||
|
|
||||||
// search for empty entries in socketchunk and remove them
|
// search for empty entries in socketchunk and remove them
|
||||||
for (i = 0; i < socketchunk.length; i++) {
|
for (i = 0; i < socketchunk.length; i++) {
|
||||||
if (socketchunk[i] === ''){
|
if (socketchunk[i] === "") {
|
||||||
socketchunk.splice(i, 1);
|
socketchunk.splice(i, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//iterate through socketchunks array to execute multiple commands in row
|
//iterate through socketchunks array to execute multiple commands in row
|
||||||
for (i = 0; i < socketchunk.length; i++) {
|
for (i = 0; i < socketchunk.length; i++) {
|
||||||
|
|
||||||
//check if data is not empty
|
//check if data is not empty
|
||||||
if (socketchunk[i].length > 0) {
|
if (socketchunk[i].length > 0) {
|
||||||
|
|
||||||
//try to parse JSON
|
//try to parse JSON
|
||||||
try {
|
try {
|
||||||
|
data = JSON.parse(socketchunk[i]);
|
||||||
data = JSON.parse(socketchunk[i])
|
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e); // "SyntaxError
|
console.log(e); // "SyntaxError
|
||||||
daemonLog.error(e);
|
daemonLog.error(e);
|
||||||
daemonLog.debug(socketchunk[i])
|
daemonLog.debug(socketchunk[i]);
|
||||||
socketchunk = ''
|
socketchunk = "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
if (data["command"] == "daemon_state") {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (data['command'] == 'daemon_state') {
|
|
||||||
let Data = {
|
let Data = {
|
||||||
input_devices: data['input_devices'],
|
input_devices: data["input_devices"],
|
||||||
output_devices: data['output_devices'],
|
output_devices: data["output_devices"],
|
||||||
python_version: data['python_version'],
|
python_version: data["python_version"],
|
||||||
hamlib_version: data['hamlib_version'],
|
hamlib_version: data["hamlib_version"],
|
||||||
serial_devices: data['serial_devices'],
|
serial_devices: data["serial_devices"],
|
||||||
tnc_running_state: data['daemon_state'][0]['status'],
|
tnc_running_state: data["daemon_state"][0]["status"],
|
||||||
ram_usage: data['ram'],
|
ram_usage: data["ram"],
|
||||||
cpu_usage: data['cpu'],
|
cpu_usage: data["cpu"],
|
||||||
version: data['version'],
|
version: data["version"],
|
||||||
};
|
};
|
||||||
ipcRenderer.send('request-update-daemon-state', Data);
|
ipcRenderer.send("request-update-daemon-state", Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data['command'] == 'test_hamlib') {
|
if (data["command"] == "test_hamlib") {
|
||||||
let Data = {
|
let Data = {
|
||||||
hamlib_result: data['result'],
|
hamlib_result: data["result"],
|
||||||
|
|
||||||
};
|
};
|
||||||
ipcRenderer.send('request-update-hamlib-test', Data);
|
ipcRenderer.send("request-update-hamlib-test", Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//finally delete message buffer
|
//finally delete message buffer
|
||||||
socketchunk = '';
|
socketchunk = "";
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -214,18 +190,47 @@ function hexToBytes(hex) {
|
||||||
|
|
||||||
exports.getDaemonState = function () {
|
exports.getDaemonState = function () {
|
||||||
//function getDaemonState(){
|
//function getDaemonState(){
|
||||||
command = '{"type" : "get", "command" : "daemon_state"}'
|
command = '{"type" : "get", "command" : "daemon_state"}';
|
||||||
writeDaemonCommand(command)
|
writeDaemonCommand(command);
|
||||||
}
|
};
|
||||||
|
|
||||||
// START TNC
|
// START TNC
|
||||||
// ` `== multi line string
|
// ` `== multi line string
|
||||||
|
|
||||||
exports.startTNC = function(mycall, mygrid, rx_audio, tx_audio, radiocontrol, devicename, deviceport, pttprotocol, pttport, serialspeed, data_bits, stop_bits, handshake, rigctld_ip, rigctld_port, enable_fft, enable_scatter, low_bandwidth_mode, tuning_range_fmin, tuning_range_fmax, enable_fsk, tx_audio_level, respond_to_cq, rx_buffer_size, enable_explorer, explorer_stats, auto_tune) {
|
exports.startTNC = function (
|
||||||
|
mycall,
|
||||||
|
mygrid,
|
||||||
|
rx_audio,
|
||||||
|
tx_audio,
|
||||||
|
radiocontrol,
|
||||||
|
devicename,
|
||||||
|
deviceport,
|
||||||
|
pttprotocol,
|
||||||
|
pttport,
|
||||||
|
serialspeed,
|
||||||
|
data_bits,
|
||||||
|
stop_bits,
|
||||||
|
handshake,
|
||||||
|
rigctld_ip,
|
||||||
|
rigctld_port,
|
||||||
|
enable_fft,
|
||||||
|
enable_scatter,
|
||||||
|
low_bandwidth_mode,
|
||||||
|
tuning_range_fmin,
|
||||||
|
tuning_range_fmax,
|
||||||
|
enable_fsk,
|
||||||
|
tx_audio_level,
|
||||||
|
respond_to_cq,
|
||||||
|
rx_buffer_size,
|
||||||
|
enable_explorer,
|
||||||
|
explorer_stats,
|
||||||
|
auto_tune
|
||||||
|
) {
|
||||||
var json_command = JSON.stringify({
|
var json_command = JSON.stringify({
|
||||||
type: 'set',
|
type: "set",
|
||||||
command: 'start_tnc',
|
command: "start_tnc",
|
||||||
parameter: [{
|
parameter: [
|
||||||
|
{
|
||||||
mycall: mycall,
|
mycall: mycall,
|
||||||
mygrid: mygrid,
|
mygrid: mygrid,
|
||||||
rx_audio: rx_audio,
|
rx_audio: rx_audio,
|
||||||
|
@ -252,28 +257,40 @@ exports.startTNC = function(mycall, mygrid, rx_audio, tx_audio, radiocontrol, de
|
||||||
rx_buffer_size: rx_buffer_size,
|
rx_buffer_size: rx_buffer_size,
|
||||||
enable_explorer: enable_explorer,
|
enable_explorer: enable_explorer,
|
||||||
enable_stats: explorer_stats,
|
enable_stats: explorer_stats,
|
||||||
enable_auto_tune: auto_tune
|
enable_auto_tune: auto_tune,
|
||||||
}]
|
},
|
||||||
})
|
],
|
||||||
|
});
|
||||||
|
|
||||||
daemonLog.debug(json_command);
|
daemonLog.debug(json_command);
|
||||||
writeDaemonCommand(json_command)
|
writeDaemonCommand(json_command);
|
||||||
|
};
|
||||||
}
|
|
||||||
|
|
||||||
// STOP TNC
|
// STOP TNC
|
||||||
exports.stopTNC = function () {
|
exports.stopTNC = function () {
|
||||||
command = '{"type" : "set", "command": "stop_tnc" , "parameter": "---" }'
|
command = '{"type" : "set", "command": "stop_tnc" , "parameter": "---" }';
|
||||||
writeDaemonCommand(command)
|
writeDaemonCommand(command);
|
||||||
}
|
};
|
||||||
|
|
||||||
// TEST HAMLIB
|
// TEST HAMLIB
|
||||||
exports.testHamlib = function(radiocontrol, devicename, deviceport, serialspeed, pttprotocol, pttport, data_bits, stop_bits, handshake, rigctld_ip, rigctld_port) {
|
exports.testHamlib = function (
|
||||||
|
radiocontrol,
|
||||||
|
devicename,
|
||||||
|
deviceport,
|
||||||
|
serialspeed,
|
||||||
|
pttprotocol,
|
||||||
|
pttport,
|
||||||
|
data_bits,
|
||||||
|
stop_bits,
|
||||||
|
handshake,
|
||||||
|
rigctld_ip,
|
||||||
|
rigctld_port
|
||||||
|
) {
|
||||||
var json_command = JSON.stringify({
|
var json_command = JSON.stringify({
|
||||||
type: 'get',
|
type: "get",
|
||||||
command: 'test_hamlib',
|
command: "test_hamlib",
|
||||||
parameter: [{
|
parameter: [
|
||||||
|
{
|
||||||
radiocontrol: radiocontrol,
|
radiocontrol: radiocontrol,
|
||||||
devicename: devicename,
|
devicename: devicename,
|
||||||
deviceport: deviceport,
|
deviceport: deviceport,
|
||||||
|
@ -284,28 +301,31 @@ exports.testHamlib = function(radiocontrol, devicename, deviceport, serialspeed,
|
||||||
stop_bits: stop_bits,
|
stop_bits: stop_bits,
|
||||||
handshake: handshake,
|
handshake: handshake,
|
||||||
rigctld_port: rigctld_port,
|
rigctld_port: rigctld_port,
|
||||||
rigctld_ip: rigctld_ip
|
rigctld_ip: rigctld_ip,
|
||||||
}]
|
},
|
||||||
})
|
],
|
||||||
|
});
|
||||||
daemonLog.debug(json_command);
|
daemonLog.debug(json_command);
|
||||||
writeDaemonCommand(json_command)
|
writeDaemonCommand(json_command);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Save myCall
|
//Save myCall
|
||||||
exports.saveMyCall = function (callsign) {
|
exports.saveMyCall = function (callsign) {
|
||||||
command = '{"type" : "set", "command": "mycallsign" , "parameter": "' + callsign + '"}'
|
command =
|
||||||
writeDaemonCommand(command)
|
'{"type" : "set", "command": "mycallsign" , "parameter": "' +
|
||||||
}
|
callsign +
|
||||||
|
'"}';
|
||||||
|
writeDaemonCommand(command);
|
||||||
|
};
|
||||||
|
|
||||||
// Save myGrid
|
// Save myGrid
|
||||||
exports.saveMyGrid = function (grid) {
|
exports.saveMyGrid = function (grid) {
|
||||||
command = '{"type" : "set", "command": "mygrid" , "parameter": "' + grid + '"}'
|
command =
|
||||||
writeDaemonCommand(command)
|
'{"type" : "set", "command": "mygrid" , "parameter": "' + grid + '"}';
|
||||||
}
|
writeDaemonCommand(command);
|
||||||
|
};
|
||||||
|
|
||||||
ipcRenderer.on('action-update-daemon-ip', (event, arg) => {
|
ipcRenderer.on("action-update-daemon-ip", (event, arg) => {
|
||||||
daemon.destroy();
|
daemon.destroy();
|
||||||
let Data = {
|
let Data = {
|
||||||
busy_state: "-",
|
busy_state: "-",
|
||||||
|
@ -314,9 +334,9 @@ ipcRenderer.on('action-update-daemon-ip', (event, arg) => {
|
||||||
frequency: "-",
|
frequency: "-",
|
||||||
mode: "-",
|
mode: "-",
|
||||||
bandwidth: "-",
|
bandwidth: "-",
|
||||||
dbfs_level: 0
|
dbfs_level: 0,
|
||||||
};
|
};
|
||||||
ipcRenderer.send('request-update-tnc-state', Data);
|
ipcRenderer.send("request-update-tnc-state", Data);
|
||||||
daemon_port = arg.port;
|
daemon_port = arg.port;
|
||||||
daemon_host = arg.adress;
|
daemon_host = arg.adress;
|
||||||
connectDAEMON();
|
connectDAEMON();
|
||||||
|
|
676
gui/main.js
676
gui/main.js
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "FreeDATA",
|
"name": "FreeDATA",
|
||||||
"version": "0.7.2-alpha.2",
|
"version": "0.7.3-alpha.2",
|
||||||
"description": "FreeDATA ",
|
"description": "FreeDATA ",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -35,28 +35,28 @@
|
||||||
"bootstrap": "^5.2.3",
|
"bootstrap": "^5.2.3",
|
||||||
"bootstrap-icons": "^1.10.3",
|
"bootstrap-icons": "^1.10.3",
|
||||||
"bootswatch": "^5.2.3",
|
"bootswatch": "^5.2.3",
|
||||||
"chart.js": "^4.2.0",
|
"chart.js": "^4.2.1",
|
||||||
"chartjs-plugin-annotation": "^2.1.2",
|
"chartjs-plugin-annotation": "^2.1.2",
|
||||||
"electron-log": "^4.4.8",
|
"electron-log": "^4.4.8",
|
||||||
"electron-updater": "^5.3.0",
|
"electron-updater": "^5.3.0",
|
||||||
"emoji-picker-element": "^1.15.0",
|
"emoji-picker-element": "^1.15.1",
|
||||||
"emoji-picker-element-data": "^1.3.0",
|
"emoji-picker-element-data": "^1.3.0",
|
||||||
"express-pouchdb": "^4.2.0",
|
"express-pouchdb": "^4.2.0",
|
||||||
"mime": "^3.0.0",
|
"mime": "^3.0.0",
|
||||||
"pouchdb": "^8.0.0",
|
"pouchdb": "^8.0.1",
|
||||||
"pouchdb-browser": "^8.0.0",
|
"pouchdb-browser": "^8.0.1",
|
||||||
"pouchdb-express-router": "^0.0.11",
|
"pouchdb-express-router": "^0.0.11",
|
||||||
"pouchdb-find": "^8.0.0",
|
"pouchdb-find": "^8.0.1",
|
||||||
"pouchdb-replication": "^8.0.0",
|
"pouchdb-replication": "^8.0.1",
|
||||||
"qth-locator": "^2.1.0",
|
"qth-locator": "^2.1.0",
|
||||||
"utf8": "^3.0.0",
|
"utf8": "^3.0.0",
|
||||||
"uuid": "^9.0.0"
|
"uuid": "^9.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"electron": "^22.0.2",
|
"electron": "^23.0.0",
|
||||||
"electron-builder": "^23.6.0",
|
"electron-builder": "^23.6.0",
|
||||||
"@electron/notarize": "^1.2.3",
|
"@electron/notarize": "^1.2.3",
|
||||||
"electron-builder-notarize": "^1.5.0"
|
"electron-builder-notarize": "^1.5.1"
|
||||||
},
|
},
|
||||||
"build": {
|
"build": {
|
||||||
"productName": "FreeDATA",
|
"productName": "FreeDATA",
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,76 +1,86 @@
|
||||||
const path = require('path');
|
const path = require("path");
|
||||||
const {ipcRenderer} = require('electron');
|
const { ipcRenderer } = require("electron");
|
||||||
|
|
||||||
// https://stackoverflow.com/a/26227660
|
// https://stackoverflow.com/a/26227660
|
||||||
var appDataFolder = process.env.APPDATA || (process.platform == 'darwin' ? process.env.HOME + '/Library/Application Support' : process.env.HOME + "/.config")
|
var appDataFolder =
|
||||||
|
process.env.APPDATA ||
|
||||||
|
(process.platform == "darwin"
|
||||||
|
? process.env.HOME + "/Library/Application Support"
|
||||||
|
: process.env.HOME + "/.config");
|
||||||
var configFolder = path.join(appDataFolder, "FreeDATA");
|
var configFolder = path.join(appDataFolder, "FreeDATA");
|
||||||
var configPath = path.join(configFolder, 'config.json')
|
var configPath = path.join(configFolder, "config.json");
|
||||||
const config = require(configPath);
|
const config = require(configPath);
|
||||||
|
|
||||||
|
|
||||||
// WINDOW LISTENER
|
// WINDOW LISTENER
|
||||||
window.addEventListener('DOMContentLoaded', () => {
|
window.addEventListener("DOMContentLoaded", () => {
|
||||||
document.getElementById('enable_filter_info').addEventListener('click', () => {
|
document
|
||||||
if (document.getElementById('enable_filter_info').checked){
|
.getElementById("enable_filter_info")
|
||||||
display_class("table-info", true)
|
.addEventListener("click", () => {
|
||||||
|
if (document.getElementById("enable_filter_info").checked) {
|
||||||
|
display_class("table-info", true);
|
||||||
} else {
|
} else {
|
||||||
display_class("table-info", false)
|
display_class("table-info", false);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
document.getElementById('enable_filter_debug').addEventListener('click', () => {
|
document
|
||||||
if (document.getElementById('enable_filter_debug').checked){
|
.getElementById("enable_filter_debug")
|
||||||
display_class("table-debug", true)
|
.addEventListener("click", () => {
|
||||||
|
if (document.getElementById("enable_filter_debug").checked) {
|
||||||
|
display_class("table-debug", true);
|
||||||
} else {
|
} else {
|
||||||
display_class("table-debug", false)
|
display_class("table-debug", false);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
document.getElementById('enable_filter_warning').addEventListener('click', () => {
|
document
|
||||||
if (document.getElementById('enable_filter_warning').checked){
|
.getElementById("enable_filter_warning")
|
||||||
display_class("table-warning", true)
|
.addEventListener("click", () => {
|
||||||
|
if (document.getElementById("enable_filter_warning").checked) {
|
||||||
|
display_class("table-warning", true);
|
||||||
} else {
|
} else {
|
||||||
display_class("table-warning", false)
|
display_class("table-warning", false);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
document.getElementById('enable_filter_error').addEventListener('click', () => {
|
document
|
||||||
if (document.getElementById('enable_filter_error').checked){
|
.getElementById("enable_filter_error")
|
||||||
display_class("table-danger", true)
|
.addEventListener("click", () => {
|
||||||
|
if (document.getElementById("enable_filter_error").checked) {
|
||||||
|
display_class("table-danger", true);
|
||||||
} else {
|
} else {
|
||||||
display_class("table-danger", false)
|
display_class("table-danger", false);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
|
|
||||||
function display_class(class_name, state) {
|
function display_class(class_name, state) {
|
||||||
var collection = document.getElementsByClassName(class_name);
|
var collection = document.getElementsByClassName(class_name);
|
||||||
console.log(collection)
|
console.log(collection);
|
||||||
for (let i = 0; i < collection.length; i++) {
|
for (let i = 0; i < collection.length; i++) {
|
||||||
if (state == true) {
|
if (state == true) {
|
||||||
collection[i].style.display = "table-row";
|
collection[i].style.display = "table-row";
|
||||||
} else {
|
} else {
|
||||||
collection[i].style.display = "None";
|
collection[i].style.display = "None";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ipcRenderer.on('action-update-log', (event, arg) => {
|
ipcRenderer.on("action-update-log", (event, arg) => {
|
||||||
|
var entry = arg.entry;
|
||||||
var entry = arg.entry
|
|
||||||
|
|
||||||
// remove ANSI characters from string, caused by color logging
|
// remove ANSI characters from string, caused by color logging
|
||||||
// https://stackoverflow.com/a/29497680
|
// https://stackoverflow.com/a/29497680
|
||||||
entry = entry.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,'')
|
entry = entry.replace(
|
||||||
|
/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,
|
||||||
|
""
|
||||||
|
);
|
||||||
|
|
||||||
var tbl = document.getElementById("log");
|
var tbl = document.getElementById("log");
|
||||||
var row = document.createElement("tr");
|
var row = document.createElement("tr");
|
||||||
|
|
||||||
var timestamp = document.createElement("td");
|
var timestamp = document.createElement("td");
|
||||||
var timestampText = document.createElement('span');
|
var timestampText = document.createElement("span");
|
||||||
|
|
||||||
//datetime = new Date();
|
//datetime = new Date();
|
||||||
//timestampText.innerText = datetime.toISOString();
|
//timestampText.innerText = datetime.toISOString();
|
||||||
|
@ -78,36 +88,36 @@ ipcRenderer.on('action-update-log', (event, arg) => {
|
||||||
timestamp.appendChild(timestampText);
|
timestamp.appendChild(timestampText);
|
||||||
|
|
||||||
var type = document.createElement("td");
|
var type = document.createElement("td");
|
||||||
var typeText = document.createElement('span');
|
var typeText = document.createElement("span");
|
||||||
// typeText.innerText = entry.slice(10, 30).match(/[\[](.*)[^\]]/g);
|
// typeText.innerText = entry.slice(10, 30).match(/[\[](.*)[^\]]/g);
|
||||||
console.log(entry.match(/\[[^\]]+\]/g))
|
console.log(entry.match(/\[[^\]]+\]/g));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
typeText.innerText = entry.match(/\[[^\]]+\]/g)[0];
|
typeText.innerText = entry.match(/\[[^\]]+\]/g)[0];
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
typeText.innerText = '-'
|
typeText.innerText = "-";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// let res = str.match(/[\[](.*)[^\]]/g);
|
// let res = str.match(/[\[](.*)[^\]]/g);
|
||||||
|
|
||||||
type.appendChild(typeText);
|
type.appendChild(typeText);
|
||||||
|
|
||||||
var area = document.createElement("td");
|
var area = document.createElement("td");
|
||||||
var areaText = document.createElement('span');
|
var areaText = document.createElement("span");
|
||||||
//areaText.innerText = entry.slice(10, 50).match(/[\] \[](.*)[^\]]/g);
|
//areaText.innerText = entry.slice(10, 50).match(/[\] \[](.*)[^\]]/g);
|
||||||
//areaText.innerText = entry.match(/\[[^\]]+\]/g)[1];
|
//areaText.innerText = entry.match(/\[[^\]]+\]/g)[1];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
areaText.innerText = entry.match(/\[[^\]]+\]/g)[1];
|
areaText.innerText = entry.match(/\[[^\]]+\]/g)[1];
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
areaText.innerText = '-'
|
areaText.innerText = "-";
|
||||||
}
|
}
|
||||||
area.appendChild(areaText);
|
area.appendChild(areaText);
|
||||||
|
|
||||||
var logEntry = document.createElement("td");
|
var logEntry = document.createElement("td");
|
||||||
var logEntryText = document.createElement('span');
|
var logEntryText = document.createElement("span");
|
||||||
try{logEntryText.innerText = entry.split("]")[2];
|
try {
|
||||||
|
logEntryText.innerText = entry.split("]")[2];
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logEntryText.innerText = "-";
|
logEntryText.innerText = "-";
|
||||||
}
|
}
|
||||||
|
@ -124,69 +134,53 @@ ipcRenderer.on('action-update-log', (event, arg) => {
|
||||||
row.classList.add("table-secondary");
|
row.classList.add("table-secondary");
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
if (typeText.innerText.includes('info')) {
|
if (typeText.innerText.includes("info")) {
|
||||||
row.classList.add("table-info");
|
row.classList.add("table-info");
|
||||||
}
|
}
|
||||||
if (typeText.innerText.includes('debug')) {
|
if (typeText.innerText.includes("debug")) {
|
||||||
row.classList.add("table-secondary");
|
row.classList.add("table-secondary");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeText.innerText.includes('warning')) {
|
if (typeText.innerText.includes("warning")) {
|
||||||
row.classList.add("table-warning");
|
row.classList.add("table-warning");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeText.innerText.includes('error')) {
|
if (typeText.innerText.includes("error")) {
|
||||||
row.classList.add("table-danger");
|
row.classList.add("table-danger");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (document.getElementById("enable_filter_info").checked) {
|
||||||
if (document.getElementById('enable_filter_info').checked) {
|
row.style.display = "table-row";
|
||||||
row.style.display = "table-row"
|
display_class("table-info", true);
|
||||||
display_class("table-info", true)
|
|
||||||
} else {
|
} else {
|
||||||
row.style.display = "None"
|
row.style.display = "None";
|
||||||
display_class("table-info", false)
|
display_class("table-info", false);
|
||||||
|
|
||||||
}
|
}
|
||||||
if (document.getElementById('enable_filter_debug').checked) {
|
if (document.getElementById("enable_filter_debug").checked) {
|
||||||
row.style.display = "table-row"
|
row.style.display = "table-row";
|
||||||
display_class("table-secondary", true)
|
display_class("table-secondary", true);
|
||||||
} else {
|
} else {
|
||||||
row.style.display = "None"
|
row.style.display = "None";
|
||||||
display_class("table-secondary", false)
|
display_class("table-secondary", false);
|
||||||
|
|
||||||
}
|
}
|
||||||
if (document.getElementById('enable_filter_warning').checked) {
|
if (document.getElementById("enable_filter_warning").checked) {
|
||||||
row.style.display = "table-row"
|
row.style.display = "table-row";
|
||||||
display_class("table-warning", true)
|
display_class("table-warning", true);
|
||||||
} else {
|
} else {
|
||||||
row.style.display = "None"
|
row.style.display = "None";
|
||||||
display_class("table-warning", false)
|
display_class("table-warning", false);
|
||||||
|
|
||||||
}
|
}
|
||||||
if (document.getElementById('enable_filter_error').checked) {
|
if (document.getElementById("enable_filter_error").checked) {
|
||||||
row.style.display = "table-row"
|
row.style.display = "table-row";
|
||||||
display_class("table-danger", true)
|
display_class("table-danger", true);
|
||||||
} else {
|
} else {
|
||||||
row.style.display = "None"
|
row.style.display = "None";
|
||||||
display_class("table-danger", false)
|
display_class("table-danger", false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
tbl.appendChild(row);
|
tbl.appendChild(row);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// scroll to bottom of page
|
// scroll to bottom of page
|
||||||
// https://stackoverflow.com/a/11715670
|
// https://stackoverflow.com/a/11715670
|
||||||
window.scrollTo(0, document.body.scrollHeight);
|
window.scrollTo(0, document.body.scrollHeight);
|
||||||
|
});
|
||||||
|
|
||||||
})
|
|
||||||
|
|
2542
gui/preload-main.js
2542
gui/preload-main.js
File diff suppressed because it is too large
Load diff
823
gui/sock.js
823
gui/sock.js
File diff suppressed because it is too large
Load diff
|
@ -1,14 +1,20 @@
|
||||||
<!doctype html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<!-- Required meta tags -->
|
<!-- Required meta tags -->
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self';">
|
<meta http-equiv="Content-Security-Policy" content="script-src 'self';" />
|
||||||
<!-- Bootstrap CSS -->
|
<!-- Bootstrap CSS -->
|
||||||
<link rel="stylesheet" id="bootstrap_theme" href="../node_modules/bootstrap/dist/css/bootstrap.min.css">
|
<link
|
||||||
<link rel="stylesheet" href="../node_modules/bootstrap-icons/font/bootstrap-icons.css">
|
rel="stylesheet"
|
||||||
|
id="bootstrap_theme"
|
||||||
|
href="../node_modules/bootstrap/dist/css/bootstrap.min.css"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="../node_modules/bootstrap-icons/font/bootstrap-icons.css"
|
||||||
|
/>
|
||||||
<!-- Custom CSS -->
|
<!-- Custom CSS -->
|
||||||
<link rel="stylesheet" type="text/css" href="styles.css" />
|
<link rel="stylesheet" type="text/css" href="styles.css" />
|
||||||
<title>FreeDATA - CHAT</title>
|
<title>FreeDATA - CHAT</title>
|
||||||
|
@ -21,10 +27,24 @@
|
||||||
<script src="../node_modules/chart.js/dist/chart.umd.js"></script>
|
<script src="../node_modules/chart.js/dist/chart.umd.js"></script>
|
||||||
<!--<script src="../node_modules/chartjs-plugin-annotation/dist/chartjs-plugin-annotation.min.js"></script>-->
|
<!--<script src="../node_modules/chartjs-plugin-annotation/dist/chartjs-plugin-annotation.min.js"></script>-->
|
||||||
<!--<script type="module" src="../node_modules/emoji-picker-element/index.js"></script>-->
|
<!--<script type="module" src="../node_modules/emoji-picker-element/index.js"></script>-->
|
||||||
<script type="module" src="../node_modules/emoji-picker-element/picker.js"></script>
|
<script
|
||||||
<script type="module" src="../node_modules/emoji-picker-element/database.js"></script>
|
type="module"
|
||||||
<div class="position-absolute container w-100 h-100 bottom-0 end-0 mb-5" style="z-index:100; display: none" id="emojipickercontainer">
|
src="../node_modules/emoji-picker-element/picker.js"
|
||||||
<emoji-picker locale="en" class="position-absolute bottom-0 end-0 p-1 mb-2" data-source="../node_modules/emoji-picker-element-data/en/emojibase/data.json"></emoji-picker>
|
></script>
|
||||||
|
<script
|
||||||
|
type="module"
|
||||||
|
src="../node_modules/emoji-picker-element/database.js"
|
||||||
|
></script>
|
||||||
|
<div
|
||||||
|
class="position-absolute container w-100 h-100 bottom-0 end-0 mb-5"
|
||||||
|
style="z-index: 100; display: none"
|
||||||
|
id="emojipickercontainer"
|
||||||
|
>
|
||||||
|
<emoji-picker
|
||||||
|
locale="en"
|
||||||
|
class="position-absolute bottom-0 end-0 p-1 mb-2"
|
||||||
|
data-source="../node_modules/emoji-picker-element-data/en/emojibase/data.json"
|
||||||
|
></emoji-picker>
|
||||||
</div>
|
</div>
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row h-100">
|
<div class="row h-100">
|
||||||
|
@ -32,52 +52,129 @@
|
||||||
<! ------Chats area ---------------------------------------------------------------------->
|
<! ------Chats area ---------------------------------------------------------------------->
|
||||||
<div class="container-fluid m-0 p-0">
|
<div class="container-fluid m-0 p-0">
|
||||||
<div class="input-group bottom-0 m-0 w-100">
|
<div class="input-group bottom-0 m-0 w-100">
|
||||||
<input class="form-control w-50" maxlength="9" style="text-transform:uppercase;" id="chatModuleNewDxCall" placeholder="DX CALL">
|
<input
|
||||||
<button class="btn btn-sm btn-success w-50" id="createNewChatButton" type="button"><i class="bi bi-pencil-square" style="font-size: 1.2rem;"></i></button>
|
class="form-control w-50"
|
||||||
|
maxlength="9"
|
||||||
|
style="text-transform: uppercase"
|
||||||
|
id="chatModuleNewDxCall"
|
||||||
|
placeholder="DX CALL"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
class="btn btn-sm btn-success w-50"
|
||||||
|
id="createNewChatButton"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<i class="bi bi-pencil-square" style="font-size: 1.2rem"></i>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr class="m-2">
|
<hr class="m-2" />
|
||||||
<div class="overflow-auto vh-100">
|
<div class="overflow-auto vh-100">
|
||||||
<div class="list-group overflow-auto" id="list-tab" role="tablist" style="height: calc(100vh - 70px)"> </div>
|
<div
|
||||||
|
class="list-group overflow-auto"
|
||||||
|
id="list-tab"
|
||||||
|
role="tablist"
|
||||||
|
style="height: calc(100vh - 70px)"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-8 border vh-100 p-0">
|
<div class="col-8 border vh-100 p-0">
|
||||||
<! ------ chat navbar ---------------------------------------------------------------------->
|
<! ------ chat navbar ---------------------------------------------------------------------->
|
||||||
<div class="container-fluid m-2 p-0">
|
<div class="container-fluid m-2 p-0">
|
||||||
<div class="input-group bottom-0">
|
<div class="input-group bottom-0">
|
||||||
<button class="btn btn-sm btn-secondary me-2" id="ping" type="button">Ping</button>
|
<button
|
||||||
<button id="chatSettingsDropDown" type="button" class="btn btn-outline-secondary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false"> <i class="bi bi-three-dots-vertical"></i> </button>
|
class="btn btn-sm btn-secondary me-2"
|
||||||
|
id="ping"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
Ping
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
id="chatSettingsDropDown"
|
||||||
|
type="button"
|
||||||
|
class="btn btn-outline-secondary dropdown-toggle"
|
||||||
|
data-bs-toggle="dropdown"
|
||||||
|
aria-expanded="false"
|
||||||
|
>
|
||||||
|
<i class="bi bi-three-dots-vertical"></i>
|
||||||
|
</button>
|
||||||
<ul class="dropdown-menu" aria-labelledby="chatSettingsDropDown">
|
<ul class="dropdown-menu" aria-labelledby="chatSettingsDropDown">
|
||||||
<li><a class="dropdown-item bg-danger text-white" id="delete_selected_chat" href="#">Delete chat</a></li>
|
<li>
|
||||||
|
<a
|
||||||
|
class="dropdown-item bg-danger text-white"
|
||||||
|
id="delete_selected_chat"
|
||||||
|
href="#"
|
||||||
|
>Delete chat</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr class="m-0">
|
<hr class="m-0" />
|
||||||
<! ------messages area ---------------------------------------------------------------------->
|
<! ------messages area ---------------------------------------------------------------------->
|
||||||
<div class="container overflow-auto" id="message-container" style="height: calc(100% - 150px);">
|
<div
|
||||||
|
class="container overflow-auto"
|
||||||
|
id="message-container"
|
||||||
|
style="height: calc(100% - 150px)"
|
||||||
|
>
|
||||||
<div class="tab-content" id="nav-tabContent"></div>
|
<div class="tab-content" id="nav-tabContent"></div>
|
||||||
<!--<div class="container position-absolute bottom-0">--></div>
|
<!--<div class="container position-absolute bottom-0">-->
|
||||||
|
</div>
|
||||||
<!-- </div>-->
|
<!-- </div>-->
|
||||||
<div class="container-fluid mt-2 p-0">
|
<div class="container-fluid mt-2 p-0">
|
||||||
|
<input
|
||||||
<input type="checkbox" id="expand_textarea" class="btn-check" autocomplete="off">
|
type="checkbox"
|
||||||
<label class="btn d-flex justify-content-center" id="expand_textarea_label" for="expand_textarea"><i id="expand_textarea_button" class="bi bi-chevron-compact-up"></i></label>
|
id="expand_textarea"
|
||||||
|
class="btn-check"
|
||||||
|
autocomplete="off"
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
class="btn d-flex justify-content-center"
|
||||||
|
id="expand_textarea_label"
|
||||||
|
for="expand_textarea"
|
||||||
|
><i
|
||||||
|
id="expand_textarea_button"
|
||||||
|
class="bi bi-chevron-compact-up"
|
||||||
|
></i
|
||||||
|
></label>
|
||||||
|
|
||||||
<div class="input-group bottom-0 w-100">
|
<div class="input-group bottom-0 w-100">
|
||||||
<!--<input class="form-control" maxlength="8" style="max-width: 6rem; text-transform:uppercase; display:none" id="chatModuleDxCall" placeholder="DX CALL"></input>-->
|
<!--<input class="form-control" maxlength="8" style="max-width: 6rem; text-transform:uppercase; display:none" id="chatModuleDxCall" placeholder="DX CALL"></input>-->
|
||||||
<!--<button class="btn btn-sm btn-primary me-2" id="emojipickerbutton" type="button">--><i id="emojipickerbutton" class="bi bi-emoji-smile m-1" style="font-size: 1.5rem; color: grey;"></i><!--</button>-->
|
<!--<button class="btn btn-sm btn-primary me-2" id="emojipickerbutton" type="button">--><i
|
||||||
|
id="emojipickerbutton"
|
||||||
|
class="bi bi-emoji-smile m-1"
|
||||||
|
style="font-size: 1.5rem; color: grey"
|
||||||
|
></i
|
||||||
|
><!--</button>-->
|
||||||
<!--<input class="form-control rounded-pill m-1 p-1" id="chatModuleMessage" placeholder="Message - Send with [Enter]"></input>-->
|
<!--<input class="form-control rounded-pill m-1 p-1" id="chatModuleMessage" placeholder="Message - Send with [Enter]"></input>-->
|
||||||
|
|
||||||
<textarea class="form-control m-1 p-1" rows="1" id="chatModuleMessage" placeholder="Message - Send with [Enter]"></textarea>
|
<textarea
|
||||||
|
class="form-control m-1 p-1"
|
||||||
|
rows="1"
|
||||||
|
id="chatModuleMessage"
|
||||||
|
placeholder="Message - Send with [Enter]"
|
||||||
|
></textarea>
|
||||||
|
|
||||||
|
<!--<button class="btn btn-sm btn-primary me-2" style="width: 3rem" id="selectFilesButton" type="button"><i class="bi bi-paperclip" style="font-size: 1.2rem; color: white;"></i></button>--><i
|
||||||
<!--<button class="btn btn-sm btn-primary me-2" style="width: 3rem" id="selectFilesButton" type="button"><i class="bi bi-paperclip" style="font-size: 1.2rem; color: white;"></i></button>--><i class="bi bi-paperclip m-1" style="font-size: 1.5rem; color: grey;" id="selectFilesButton"></i>
|
class="bi bi-paperclip m-1"
|
||||||
<button class="btn btn-sm btn-secondary me-2" style="width: 5rem; display: none" id="sendMessage" type="button"><i class="bi bi-send" style="font-size: 1.2rem; color: white;"></i></button>
|
style="font-size: 1.5rem; color: grey"
|
||||||
|
id="selectFilesButton"
|
||||||
|
></i>
|
||||||
|
<button
|
||||||
|
class="btn btn-sm btn-secondary me-2"
|
||||||
|
style="width: 5rem; display: none"
|
||||||
|
id="sendMessage"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
class="bi bi-send"
|
||||||
|
style="font-size: 1.2rem; color: white"
|
||||||
|
></i>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
<!doctype html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<!-- Required meta tags -->
|
<!-- Required meta tags -->
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<!--<meta http-equiv="Content-Security-Policy" content="script-src 'self';">-->
|
<!--<meta http-equiv="Content-Security-Policy" content="script-src 'self';">-->
|
||||||
<!-- Bootstrap CSS -->
|
<!-- Bootstrap CSS -->
|
||||||
<link rel="stylesheet" href="../node_modules/bootstrap/dist/css/bootstrap.min.css">
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="../node_modules/bootstrap/dist/css/bootstrap.min.css"
|
||||||
|
/>
|
||||||
<title>Send & Receive Data</title>
|
<title>Send & Receive Data</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -18,8 +21,14 @@
|
||||||
<div class="card-header">Select data</div>
|
<div class="card-header">Select data</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="input-group input-group-sm mb-0">
|
<div class="input-group input-group-sm mb-0">
|
||||||
<input type="file" class="form-control" id="inputGroupFile02">
|
<input
|
||||||
<label class="input-group-text" for="inputGroupFile02">kB</label>
|
type="file"
|
||||||
|
class="form-control"
|
||||||
|
id="inputGroupFile02"
|
||||||
|
/>
|
||||||
|
<label class="input-group-text" for="inputGroupFile02"
|
||||||
|
>kB</label
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -35,19 +44,46 @@
|
||||||
<div class="row mb-2">
|
<div class="row mb-2">
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<div class="input-group input-group-sm">
|
<div class="input-group input-group-sm">
|
||||||
<input type="text" class="form-control" style="max-width: 6rem" placeholder="DX Call" id="dxCall" maxlength="6" aria-label="Input group example" aria-describedby="btnGroupAddon">
|
<input
|
||||||
<button type="button" id="sendPing"class="btn btn-primary">Ping</button>
|
type="text"
|
||||||
<span class="input-group-text" id="tnc_running_state">ACK</span>
|
class="form-control"
|
||||||
<span class="input-group-text" id="tnc_running_state">0000 km</span>
|
style="max-width: 6rem"
|
||||||
<span class="input-group-text" id="tnc_running_state">0 dB</span>
|
placeholder="DX Call"
|
||||||
|
id="dxCall"
|
||||||
|
maxlength="6"
|
||||||
|
aria-label="Input group example"
|
||||||
|
aria-describedby="btnGroupAddon"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
id="sendPing"
|
||||||
|
class="btn btn-primary"
|
||||||
|
>
|
||||||
|
Ping
|
||||||
|
</button>
|
||||||
|
<span class="input-group-text" id="tnc_running_state"
|
||||||
|
>ACK</span
|
||||||
|
>
|
||||||
|
<span class="input-group-text" id="tnc_running_state"
|
||||||
|
>0000 km</span
|
||||||
|
>
|
||||||
|
<span class="input-group-text" id="tnc_running_state"
|
||||||
|
>0 dB</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<div class="input-group input-group-sm">
|
<div class="input-group input-group-sm">
|
||||||
<span class="input-group-text" id="basic-addon1">Mode</span>
|
<span class="input-group-text" id="basic-addon1"
|
||||||
<select class="form-select form-select-sm" aria-label=".form-select-sm example" id="hamlib_deviceport">
|
>Mode</span
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
class="form-select form-select-sm"
|
||||||
|
aria-label=".form-select-sm example"
|
||||||
|
id="hamlib_deviceport"
|
||||||
|
>
|
||||||
<option selected value="DATAC1">DATAC1</option>
|
<option selected value="DATAC1">DATAC1</option>
|
||||||
<option value="DATAC3">DATAC3</option>
|
<option value="DATAC3">DATAC3</option>
|
||||||
</select>
|
</select>
|
||||||
|
@ -55,8 +91,14 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<div class="input-group input-group-sm">
|
<div class="input-group input-group-sm">
|
||||||
<span class="input-group-text" id="basic-addon1">Frames</span>
|
<span class="input-group-text" id="basic-addon1"
|
||||||
<select class="form-select form-select-sm" aria-label=".form-select-sm example" id="hamlib_deviceport">
|
>Frames</span
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
class="form-select form-select-sm"
|
||||||
|
aria-label=".form-select-sm example"
|
||||||
|
id="hamlib_deviceport"
|
||||||
|
>
|
||||||
<option selected value="1">1</option>
|
<option selected value="1">1</option>
|
||||||
<option value="2">2</option>
|
<option value="2">2</option>
|
||||||
</select>
|
</select>
|
||||||
|
@ -64,7 +106,13 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="input-group input-group-sm">
|
<div class="input-group input-group-sm">
|
||||||
<button type="button" id="startTransmission"class="btn btn-success">Send</button>
|
<button
|
||||||
|
type="button"
|
||||||
|
id="startTransmission"
|
||||||
|
class="btn btn-success"
|
||||||
|
>
|
||||||
|
Send
|
||||||
|
</button>
|
||||||
<!--<button type="button" id="stopTNC"class="btn btn-danger">STOP</button>-->
|
<!--<button type="button" id="stopTNC"class="btn btn-danger">STOP</button>-->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -79,15 +127,13 @@
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card text-dark bg-light mb-0">
|
<div class="card text-dark bg-light mb-0">
|
||||||
<div class="card-header">Info</div>
|
<div class="card-header">Info</div>
|
||||||
<div class="card-body">
|
<div class="card-body">123</div>
|
||||||
123
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<hr>
|
<hr />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--row-->
|
<!--row-->
|
||||||
|
@ -97,41 +143,120 @@
|
||||||
<!---------------------------------------------------------------------- FOOTER AREA ------------------------------------------------------------>
|
<!---------------------------------------------------------------------- FOOTER AREA ------------------------------------------------------------>
|
||||||
<nav class="navbar fixed-bottom navbar-light bg-light">
|
<nav class="navbar fixed-bottom navbar-light bg-light">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="btn-toolbar" role="toolbar" aria-label="Toolbar with button groups">
|
<div
|
||||||
<div class="btn-group btn-group-sm me-2" role="group" aria-label="First group">
|
class="btn-toolbar"
|
||||||
|
role="toolbar"
|
||||||
|
aria-label="Toolbar with button groups"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="btn-group btn-group-sm me-2"
|
||||||
|
role="group"
|
||||||
|
aria-label="First group"
|
||||||
|
>
|
||||||
<button class="btn btn-secondary" id="ptt_state" type="button">
|
<button class="btn btn-secondary" id="ptt_state" type="button">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-broadcast-pin" viewBox="0 0 16 16">
|
<svg
|
||||||
<path d="M3.05 3.05a7 7 0 0 0 0 9.9.5.5 0 0 1-.707.707 8 8 0 0 1 0-11.314.5.5 0 0 1 .707.707zm2.122 2.122a4 4 0 0 0 0 5.656.5.5 0 1 1-.708.708 5 5 0 0 1 0-7.072.5.5 0 0 1 .708.708zm5.656-.708a.5.5 0 0 1 .708 0 5 5 0 0 1 0 7.072.5.5 0 1 1-.708-.708 4 4 0 0 0 0-5.656.5.5 0 0 1 0-.708zm2.122-2.12a.5.5 0 0 1 .707 0 8 8 0 0 1 0 11.313.5.5 0 0 1-.707-.707 7 7 0 0 0 0-9.9.5.5 0 0 1 0-.707zM6 8a2 2 0 1 1 2.5 1.937V15.5a.5.5 0 0 1-1 0V9.937A2 2 0 0 1 6 8z"/>
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
fill="currentColor"
|
||||||
|
class="bi bi-broadcast-pin"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M3.05 3.05a7 7 0 0 0 0 9.9.5.5 0 0 1-.707.707 8 8 0 0 1 0-11.314.5.5 0 0 1 .707.707zm2.122 2.122a4 4 0 0 0 0 5.656.5.5 0 1 1-.708.708 5 5 0 0 1 0-7.072.5.5 0 0 1 .708.708zm5.656-.708a.5.5 0 0 1 .708 0 5 5 0 0 1 0 7.072.5.5 0 1 1-.708-.708 4 4 0 0 0 0-5.656.5.5 0 0 1 0-.708zm2.122-2.12a.5.5 0 0 1 .707 0 8 8 0 0 1 0 11.313.5.5 0 0 1-.707-.707 7 7 0 0 0 0-9.9.5.5 0 0 1 0-.707zM6 8a2 2 0 1 1 2.5 1.937V15.5a.5.5 0 0 1-1 0V9.937A2 2 0 0 1 6 8z"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-group btn-group-sm me-2" role="group" aria-label="Second group">
|
<div
|
||||||
|
class="btn-group btn-group-sm me-2"
|
||||||
|
role="group"
|
||||||
|
aria-label="Second group"
|
||||||
|
>
|
||||||
<button class="btn btn-secondary" id="busy_state" type="button">
|
<button class="btn btn-secondary" id="busy_state" type="button">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-cpu" viewBox="0 0 16 16">
|
<svg
|
||||||
<path d="M5 0a.5.5 0 0 1 .5.5V2h1V.5a.5.5 0 0 1 1 0V2h1V.5a.5.5 0 0 1 1 0V2h1V.5a.5.5 0 0 1 1 0V2A2.5 2.5 0 0 1 14 4.5h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14a2.5 2.5 0 0 1-2.5 2.5v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14A2.5 2.5 0 0 1 2 11.5H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2A2.5 2.5 0 0 1 4.5 2V.5A.5.5 0 0 1 5 0zm-.5 3A1.5 1.5 0 0 0 3 4.5v7A1.5 1.5 0 0 0 4.5 13h7a1.5 1.5 0 0 0 1.5-1.5v-7A1.5 1.5 0 0 0 11.5 3h-7zM5 6.5A1.5 1.5 0 0 1 6.5 5h3A1.5 1.5 0 0 1 11 6.5v3A1.5 1.5 0 0 1 9.5 11h-3A1.5 1.5 0 0 1 5 9.5v-3zM6.5 6a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3z"/>
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
fill="currentColor"
|
||||||
|
class="bi bi-cpu"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M5 0a.5.5 0 0 1 .5.5V2h1V.5a.5.5 0 0 1 1 0V2h1V.5a.5.5 0 0 1 1 0V2h1V.5a.5.5 0 0 1 1 0V2A2.5 2.5 0 0 1 14 4.5h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14a2.5 2.5 0 0 1-2.5 2.5v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14A2.5 2.5 0 0 1 2 11.5H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2A2.5 2.5 0 0 1 4.5 2V.5A.5.5 0 0 1 5 0zm-.5 3A1.5 1.5 0 0 0 3 4.5v7A1.5 1.5 0 0 0 4.5 13h7a1.5 1.5 0 0 0 1.5-1.5v-7A1.5 1.5 0 0 0 11.5 3h-7zM5 6.5A1.5 1.5 0 0 1 6.5 5h3A1.5 1.5 0 0 1 11 6.5v3A1.5 1.5 0 0 1 9.5 11h-3A1.5 1.5 0 0 1 5 9.5v-3zM6.5 6a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3z"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-group btn-group-sm me-2" role="group" aria-label="Second group">
|
<div
|
||||||
|
class="btn-group btn-group-sm me-2"
|
||||||
|
role="group"
|
||||||
|
aria-label="Second group"
|
||||||
|
>
|
||||||
<button class="btn btn-secondary" id="arq_state" type="button">
|
<button class="btn btn-secondary" id="arq_state" type="button">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left-right" viewBox="0 0 16 16">
|
<svg
|
||||||
<path fill-rule="evenodd" d="M1 11.5a.5.5 0 0 0 .5.5h11.793l-3.147 3.146a.5.5 0 0 0 .708.708l4-4a.5.5 0 0 0 0-.708l-4-4a.5.5 0 0 0-.708.708L13.293 11H1.5a.5.5 0 0 0-.5.5zm14-7a.5.5 0 0 1-.5.5H2.707l3.147 3.146a.5.5 0 1 1-.708.708l-4-4a.5.5 0 0 1 0-.708l4-4a.5.5 0 1 1 .708.708L2.707 4H14.5a.5.5 0 0 1 .5.5z"/>
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
fill="currentColor"
|
||||||
|
class="bi bi-arrow-left-right"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M1 11.5a.5.5 0 0 0 .5.5h11.793l-3.147 3.146a.5.5 0 0 0 .708.708l4-4a.5.5 0 0 0 0-.708l-4-4a.5.5 0 0 0-.708.708L13.293 11H1.5a.5.5 0 0 0-.5.5zm14-7a.5.5 0 0 1-.5.5H2.707l3.147 3.146a.5.5 0 1 1-.708.708l-4-4a.5.5 0 0 1 0-.708l4-4a.5.5 0 1 1 .708.708L2.707 4H14.5a.5.5 0 0 1 .5.5z"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-group btn-group-sm me-2 " role="group" aria-label="Third group">
|
<div
|
||||||
<button class="btn btn-secondary" id="signalling_state" type="button">
|
class="btn-group btn-group-sm me-2"
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-journal-code" viewBox="0 0 16 16">
|
role="group"
|
||||||
<path fill-rule="evenodd" d="M8.646 5.646a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1 0 .708l-2 2a.5.5 0 0 1-.708-.708L10.293 8 8.646 6.354a.5.5 0 0 1 0-.708zm-1.292 0a.5.5 0 0 0-.708 0l-2 2a.5.5 0 0 0 0 .708l2 2a.5.5 0 0 0 .708-.708L5.707 8l1.647-1.646a.5.5 0 0 0 0-.708z"/>
|
aria-label="Third group"
|
||||||
<path d="M3 0h10a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2v-1h1v1a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v1H1V2a2 2 0 0 1 2-2z"/>
|
>
|
||||||
<path d="M1 5v-.5a.5.5 0 0 1 1 0V5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0V8h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0v.5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1z"/>
|
<button
|
||||||
|
class="btn btn-secondary"
|
||||||
|
id="signalling_state"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
fill="currentColor"
|
||||||
|
class="bi bi-journal-code"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M8.646 5.646a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1 0 .708l-2 2a.5.5 0 0 1-.708-.708L10.293 8 8.646 6.354a.5.5 0 0 1 0-.708zm-1.292 0a.5.5 0 0 0-.708 0l-2 2a.5.5 0 0 0 0 .708l2 2a.5.5 0 0 0 .708-.708L5.707 8l1.647-1.646a.5.5 0 0 0 0-.708z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M3 0h10a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2v-1h1v1a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v1H1V2a2 2 0 0 1 2-2z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M1 5v-.5a.5.5 0 0 1 1 0V5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0V8h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0v.5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1z"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-secondary" id="data_state" type="button">
|
<button class="btn btn-secondary" id="data_state" type="button">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-journal-richtext" viewBox="0 0 16 16">
|
<svg
|
||||||
<path d="M7.5 3.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0zm-.861 1.542 1.33.886 1.854-1.855a.25.25 0 0 1 .289-.047L11 4.75V7a.5.5 0 0 1-.5.5h-5A.5.5 0 0 1 5 7v-.5s1.54-1.274 1.639-1.208zM5 9.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5zm0 2a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5z"/>
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
<path d="M3 0h10a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2v-1h1v1a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v1H1V2a2 2 0 0 1 2-2z"/>
|
width="16"
|
||||||
<path d="M1 5v-.5a.5.5 0 0 1 1 0V5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0V8h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0v.5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1z"/>
|
height="16"
|
||||||
|
fill="currentColor"
|
||||||
|
class="bi bi-journal-richtext"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M7.5 3.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0zm-.861 1.542 1.33.886 1.854-1.855a.25.25 0 0 1 .289-.047L11 4.75V7a.5.5 0 0 1-.5.5h-5A.5.5 0 0 1 5 7v-.5s1.54-1.274 1.639-1.208zM5 9.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5zm0 2a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M3 0h10a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2v-1h1v1a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v1H1V2a2 2 0 0 1 2-2z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M1 5v-.5a.5.5 0 0 1 1 0V5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0V8h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0v.5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1z"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -140,7 +265,17 @@
|
||||||
<span class="input-group-text" id="basic-addon1">----</span>
|
<span class="input-group-text" id="basic-addon1">----</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="progress" style="height: 100%; width: 200px">
|
<div class="progress" style="height: 100%; width: 200px">
|
||||||
<div class="progress-bar progress-bar-striped bg-primary" id="arq-progress" role="progressbar" style="width: 25%" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100">25%</div>
|
<div
|
||||||
|
class="progress-bar progress-bar-striped bg-primary"
|
||||||
|
id="arq-progress"
|
||||||
|
role="progressbar"
|
||||||
|
style="width: 25%"
|
||||||
|
aria-valuenow="25"
|
||||||
|
aria-valuemin="0"
|
||||||
|
aria-valuemax="100"
|
||||||
|
>
|
||||||
|
25%
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
3159
gui/src/index.html
3159
gui/src/index.html
File diff suppressed because it is too large
Load diff
|
@ -1,43 +1,69 @@
|
||||||
<!doctype html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<!-- Required meta tags -->
|
<!-- Required meta tags -->
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self';">
|
<meta http-equiv="Content-Security-Policy" content="script-src 'self';" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Bootstrap CSS -->
|
<!-- Bootstrap CSS -->
|
||||||
<link rel="stylesheet" href="../node_modules/bootstrap/dist/css/bootstrap.min.css">
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="../node_modules/bootstrap/dist/css/bootstrap.min.css"
|
||||||
|
/>
|
||||||
<link rel="stylesheet" type="text/css" href="styles.css" />
|
<link rel="stylesheet" type="text/css" href="styles.css" />
|
||||||
<title>FreeDATA - Live Log</title>
|
<title>FreeDATA - Live Log</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<!-- bootstrap -->
|
<!-- bootstrap -->
|
||||||
<script src="../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
<!-- chart.js -->
|
<!-- chart.js -->
|
||||||
|
|
||||||
|
|
||||||
<nav class="navbar fixed-top bg-light">
|
<nav class="navbar fixed-top bg-light">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<input type="checkbox" class="btn-check" id="enable_filter_info" autocomplete="off" checked>
|
<input
|
||||||
<label class="btn btn-outline-info" for="enable_filter_info">info</label>
|
type="checkbox"
|
||||||
|
class="btn-check"
|
||||||
|
id="enable_filter_info"
|
||||||
|
autocomplete="off"
|
||||||
|
checked
|
||||||
|
/>
|
||||||
|
<label class="btn btn-outline-info" for="enable_filter_info"
|
||||||
|
>info</label
|
||||||
|
>
|
||||||
|
|
||||||
<input type="checkbox" class="btn-check" id="enable_filter_debug" autocomplete="off">
|
<input
|
||||||
<label class="btn btn-outline-primary" for="enable_filter_debug">debug</label>
|
type="checkbox"
|
||||||
|
class="btn-check"
|
||||||
|
id="enable_filter_debug"
|
||||||
|
autocomplete="off"
|
||||||
|
/>
|
||||||
|
<label class="btn btn-outline-primary" for="enable_filter_debug"
|
||||||
|
>debug</label
|
||||||
|
>
|
||||||
|
|
||||||
<input type="checkbox" class="btn-check" id="enable_filter_warning" autocomplete="off">
|
<input
|
||||||
<label class="btn btn-outline-warning" for="enable_filter_warning">warning</label>
|
type="checkbox"
|
||||||
|
class="btn-check"
|
||||||
<input type="checkbox" class="btn-check" id="enable_filter_error" autocomplete="off">
|
id="enable_filter_warning"
|
||||||
<label class="btn btn-outline-danger" for="enable_filter_error">error</label>
|
autocomplete="off"
|
||||||
|
/>
|
||||||
|
<label class="btn btn-outline-warning" for="enable_filter_warning"
|
||||||
|
>warning</label
|
||||||
|
>
|
||||||
|
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
class="btn-check"
|
||||||
|
id="enable_filter_error"
|
||||||
|
autocomplete="off"
|
||||||
|
/>
|
||||||
|
<label class="btn btn-outline-danger" for="enable_filter_error"
|
||||||
|
>error</label
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
|
||||||
<div class="container-fluid mt-5">
|
<div class="container-fluid mt-5">
|
||||||
<div class="tableFixHead">
|
<div class="tableFixHead">
|
||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self';">
|
<meta http-equiv="Content-Security-Policy" content="script-src 'self';" />
|
||||||
</head>
|
</head>
|
||||||
<body style="overflow:hidden;">
|
<body style="overflow: hidden">
|
||||||
<img src="img/icon_cube_border.png" width="100%" height="100%">
|
<img src="img/icon_cube_border.png" width="100%" height="100%" />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -3,7 +3,6 @@ body {
|
||||||
padding-right: 0px !important;
|
padding-right: 0px !important;
|
||||||
overflow-y: hidden !important;
|
overflow-y: hidden !important;
|
||||||
overflow-x: hidden !important;
|
overflow-x: hidden !important;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*Progress bars with centered text*/
|
/*Progress bars with centered text*/
|
||||||
|
@ -53,7 +52,8 @@ table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
th, td {
|
th,
|
||||||
|
td {
|
||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,11 +61,9 @@ th {
|
||||||
background: #eee;
|
background: #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ------ emoji picker customization --------- */
|
/* ------ emoji picker customization --------- */
|
||||||
.picker {
|
.picker {
|
||||||
border-radius: 10px:
|
border-radius: 10px;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* force gpu usage
|
/* force gpu usage
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,8 +1,8 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8" />
|
||||||
<meta name="author" content="Jeppe Ledet-Pedersen">
|
<meta name="author" content="Jeppe Ledet-Pedersen" />
|
||||||
<title>Spectrum Plot</title>
|
<title>Spectrum Plot</title>
|
||||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
'use strict';
|
"use strict";
|
||||||
/*
|
/*
|
||||||
function connectWebSocket(spectrum) {
|
function connectWebSocket(spectrum) {
|
||||||
// var ws = new WebSocket("ws://" + window.location.host + "/websocket");
|
// var ws = new WebSocket("ws://" + window.location.host + "/websocket");
|
||||||
|
@ -35,15 +35,13 @@ function connectWebSocket(spectrum) {
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
// Create spectrum object on canvas with ID "waterfall"
|
// Create spectrum object on canvas with ID "waterfall"
|
||||||
var spectrum = new Spectrum(
|
var spectrum = new Spectrum("waterfall", {
|
||||||
"waterfall", {
|
spectrumPercent: 20,
|
||||||
spectrumPercent: 20
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Connect to websocket
|
// Connect to websocket
|
||||||
//connectWebSocket(spectrum);
|
//connectWebSocket(spectrum);
|
||||||
|
|
||||||
|
|
||||||
//spectrum.setCenterHz("2000");
|
//spectrum.setCenterHz("2000");
|
||||||
//spectrum.setSpanHz("1");
|
//spectrum.setSpanHz("1");
|
||||||
|
|
||||||
|
@ -55,7 +53,6 @@ for (var i = 0; i < 1000; i++) {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// Bind keypress handler
|
// Bind keypress handler
|
||||||
window.addEventListener("keydown", function (e) {
|
window.addEventListener("keydown", function (e) {
|
||||||
spectrum.onKeypress(e);
|
spectrum.onKeypress(e);
|
||||||
|
|
|
@ -37,12 +37,10 @@
|
||||||
var Waterfall, Rasterscan;
|
var Waterfall, Rasterscan;
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
Waterfall = function(ipBufAry, w, h, dir, options)
|
Waterfall = function (ipBufAry, w, h, dir, options) {
|
||||||
{
|
var direction = typeof dir === "string" ? dir.toLowerCase() : "down";
|
||||||
var direction = (typeof(dir) === "string")? dir.toLowerCase() : "down";
|
|
||||||
|
|
||||||
switch (direction)
|
switch (direction) {
|
||||||
{
|
|
||||||
case "up":
|
case "up":
|
||||||
return new Spectrogram(ipBufAry, w, h, "WF", false, true, options);
|
return new Spectrogram(ipBufAry, w, h, "WF", false, true, options);
|
||||||
case "down":
|
case "down":
|
||||||
|
@ -53,14 +51,12 @@ var Waterfall, Rasterscan;
|
||||||
case "right":
|
case "right":
|
||||||
return new Spectrogram(ipBufAry, w, h, "WF", true, false, options);
|
return new Spectrogram(ipBufAry, w, h, "WF", true, false, options);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
Rasterscan = function(ipBufAry, w, h, dir, options)
|
Rasterscan = function (ipBufAry, w, h, dir, options) {
|
||||||
{
|
const direction = typeof dir === "string" ? dir.toLowerCase() : "down";
|
||||||
const direction = (typeof(dir) === "string")? dir.toLowerCase() : "down";
|
|
||||||
|
|
||||||
switch (direction)
|
switch (direction) {
|
||||||
{
|
|
||||||
case "up":
|
case "up":
|
||||||
return new Spectrogram(ipBufAry, w, h, "RS", true, true, options);
|
return new Spectrogram(ipBufAry, w, h, "RS", true, true, options);
|
||||||
case "down":
|
case "down":
|
||||||
|
@ -71,11 +67,10 @@ var Waterfall, Rasterscan;
|
||||||
case "right":
|
case "right":
|
||||||
return new Spectrogram(ipBufAry, w, h, "RS", true, false, options);
|
return new Spectrogram(ipBufAry, w, h, "RS", true, false, options);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
function Spectrogram(ipBufAry, w, h, sgMode, rhc, vert, options)
|
function Spectrogram(ipBufAry, w, h, sgMode, rhc, vert, options) {
|
||||||
{
|
const opt = typeof options === "object" ? options : {}; // avoid undeclared object errors
|
||||||
const opt = (typeof options === 'object')? options: {}; // avoid undeclared object errors
|
|
||||||
let offScreenCtx; // offscreen canvas drawing context
|
let offScreenCtx; // offscreen canvas drawing context
|
||||||
const pxPerLine = w || 200;
|
const pxPerLine = w || 200;
|
||||||
const lines = h || 200;
|
const lines = h || 200;
|
||||||
|
@ -100,94 +95,282 @@ var Waterfall, Rasterscan;
|
||||||
let sgStartTime = 0;
|
let sgStartTime = 0;
|
||||||
|
|
||||||
// Matlab Jet ref: stackoverflow.com grayscale-to-red-green-blue-matlab-jet-color-scale
|
// Matlab Jet ref: stackoverflow.com grayscale-to-red-green-blue-matlab-jet-color-scale
|
||||||
let colMap = [[ 0, 0, 128, 255], [ 0, 0, 131, 255], [ 0, 0, 135, 255], [ 0, 0, 139, 255],
|
let colMap = [
|
||||||
[ 0, 0, 143, 255], [ 0, 0, 147, 255], [ 0, 0, 151, 255], [ 0, 0, 155, 255],
|
[0, 0, 128, 255],
|
||||||
[ 0, 0, 159, 255], [ 0, 0, 163, 255], [ 0, 0, 167, 255], [ 0, 0, 171, 255],
|
[0, 0, 131, 255],
|
||||||
[ 0, 0, 175, 255], [ 0, 0, 179, 255], [ 0, 0, 183, 255], [ 0, 0, 187, 255],
|
[0, 0, 135, 255],
|
||||||
[ 0, 0, 191, 255], [ 0, 0, 195, 255], [ 0, 0, 199, 255], [ 0, 0, 203, 255],
|
[0, 0, 139, 255],
|
||||||
[ 0, 0, 207, 255], [ 0, 0, 211, 255], [ 0, 0, 215, 255], [ 0, 0, 219, 255],
|
[0, 0, 143, 255],
|
||||||
[ 0, 0, 223, 255], [ 0, 0, 227, 255], [ 0, 0, 231, 255], [ 0, 0, 235, 255],
|
[0, 0, 147, 255],
|
||||||
[ 0, 0, 239, 255], [ 0, 0, 243, 255], [ 0, 0, 247, 255], [ 0, 0, 251, 255],
|
[0, 0, 151, 255],
|
||||||
[ 0, 0, 255, 255], [ 0, 4, 255, 255], [ 0, 8, 255, 255], [ 0, 12, 255, 255],
|
[0, 0, 155, 255],
|
||||||
[ 0, 16, 255, 255], [ 0, 20, 255, 255], [ 0, 24, 255, 255], [ 0, 28, 255, 255],
|
[0, 0, 159, 255],
|
||||||
[ 0, 32, 255, 255], [ 0, 36, 255, 255], [ 0, 40, 255, 255], [ 0, 44, 255, 255],
|
[0, 0, 163, 255],
|
||||||
[ 0, 48, 255, 255], [ 0, 52, 255, 255], [ 0, 56, 255, 255], [ 0, 60, 255, 255],
|
[0, 0, 167, 255],
|
||||||
[ 0, 64, 255, 255], [ 0, 68, 255, 255], [ 0, 72, 255, 255], [ 0, 76, 255, 255],
|
[0, 0, 171, 255],
|
||||||
[ 0, 80, 255, 255], [ 0, 84, 255, 255], [ 0, 88, 255, 255], [ 0, 92, 255, 255],
|
[0, 0, 175, 255],
|
||||||
[ 0, 96, 255, 255], [ 0, 100, 255, 255], [ 0, 104, 255, 255], [ 0, 108, 255, 255],
|
[0, 0, 179, 255],
|
||||||
[ 0, 112, 255, 255], [ 0, 116, 255, 255], [ 0, 120, 255, 255], [ 0, 124, 255, 255],
|
[0, 0, 183, 255],
|
||||||
[ 0, 128, 255, 255], [ 0, 131, 255, 255], [ 0, 135, 255, 255], [ 0, 139, 255, 255],
|
[0, 0, 187, 255],
|
||||||
[ 0, 143, 255, 255], [ 0, 147, 255, 255], [ 0, 151, 255, 255], [ 0, 155, 255, 255],
|
[0, 0, 191, 255],
|
||||||
[ 0, 159, 255, 255], [ 0, 163, 255, 255], [ 0, 167, 255, 255], [ 0, 171, 255, 255],
|
[0, 0, 195, 255],
|
||||||
[ 0, 175, 255, 255], [ 0, 179, 255, 255], [ 0, 183, 255, 255], [ 0, 187, 255, 255],
|
[0, 0, 199, 255],
|
||||||
[ 0, 191, 255, 255], [ 0, 195, 255, 255], [ 0, 199, 255, 255], [ 0, 203, 255, 255],
|
[0, 0, 203, 255],
|
||||||
[ 0, 207, 255, 255], [ 0, 211, 255, 255], [ 0, 215, 255, 255], [ 0, 219, 255, 255],
|
[0, 0, 207, 255],
|
||||||
[ 0, 223, 255, 255], [ 0, 227, 255, 255], [ 0, 231, 255, 255], [ 0, 235, 255, 255],
|
[0, 0, 211, 255],
|
||||||
[ 0, 239, 255, 255], [ 0, 243, 255, 255], [ 0, 247, 255, 255], [ 0, 251, 255, 255],
|
[0, 0, 215, 255],
|
||||||
[ 0, 255, 255, 255], [ 4, 255, 251, 255], [ 8, 255, 247, 255], [ 12, 255, 243, 255],
|
[0, 0, 219, 255],
|
||||||
[ 16, 255, 239, 255], [ 20, 255, 235, 255], [ 24, 255, 231, 255], [ 28, 255, 227, 255],
|
[0, 0, 223, 255],
|
||||||
[ 32, 255, 223, 255], [ 36, 255, 219, 255], [ 40, 255, 215, 255], [ 44, 255, 211, 255],
|
[0, 0, 227, 255],
|
||||||
[ 48, 255, 207, 255], [ 52, 255, 203, 255], [ 56, 255, 199, 255], [ 60, 255, 195, 255],
|
[0, 0, 231, 255],
|
||||||
[ 64, 255, 191, 255], [ 68, 255, 187, 255], [ 72, 255, 183, 255], [ 76, 255, 179, 255],
|
[0, 0, 235, 255],
|
||||||
[ 80, 255, 175, 255], [ 84, 255, 171, 255], [ 88, 255, 167, 255], [ 92, 255, 163, 255],
|
[0, 0, 239, 255],
|
||||||
[ 96, 255, 159, 255], [100, 255, 155, 255], [104, 255, 151, 255], [108, 255, 147, 255],
|
[0, 0, 243, 255],
|
||||||
[112, 255, 143, 255], [116, 255, 139, 255], [120, 255, 135, 255], [124, 255, 131, 255],
|
[0, 0, 247, 255],
|
||||||
[128, 255, 128, 255], [131, 255, 124, 255], [135, 255, 120, 255], [139, 255, 116, 255],
|
[0, 0, 251, 255],
|
||||||
[143, 255, 112, 255], [147, 255, 108, 255], [151, 255, 104, 255], [155, 255, 100, 255],
|
[0, 0, 255, 255],
|
||||||
[159, 255, 96, 255], [163, 255, 92, 255], [167, 255, 88, 255], [171, 255, 84, 255],
|
[0, 4, 255, 255],
|
||||||
[175, 255, 80, 255], [179, 255, 76, 255], [183, 255, 72, 255], [187, 255, 68, 255],
|
[0, 8, 255, 255],
|
||||||
[191, 255, 64, 255], [195, 255, 60, 255], [199, 255, 56, 255], [203, 255, 52, 255],
|
[0, 12, 255, 255],
|
||||||
[207, 255, 48, 255], [211, 255, 44, 255], [215, 255, 40, 255], [219, 255, 36, 255],
|
[0, 16, 255, 255],
|
||||||
[223, 255, 32, 255], [227, 255, 28, 255], [231, 255, 24, 255], [235, 255, 20, 255],
|
[0, 20, 255, 255],
|
||||||
[239, 255, 16, 255], [243, 255, 12, 255], [247, 255, 8, 255], [251, 255, 4, 255],
|
[0, 24, 255, 255],
|
||||||
[255, 255, 0, 255], [255, 251, 0, 255], [255, 247, 0, 255], [255, 243, 0, 255],
|
[0, 28, 255, 255],
|
||||||
[255, 239, 0, 255], [255, 235, 0, 255], [255, 231, 0, 255], [255, 227, 0, 255],
|
[0, 32, 255, 255],
|
||||||
[255, 223, 0, 255], [255, 219, 0, 255], [255, 215, 0, 255], [255, 211, 0, 255],
|
[0, 36, 255, 255],
|
||||||
[255, 207, 0, 255], [255, 203, 0, 255], [255, 199, 0, 255], [255, 195, 0, 255],
|
[0, 40, 255, 255],
|
||||||
[255, 191, 0, 255], [255, 187, 0, 255], [255, 183, 0, 255], [255, 179, 0, 255],
|
[0, 44, 255, 255],
|
||||||
[255, 175, 0, 255], [255, 171, 0, 255], [255, 167, 0, 255], [255, 163, 0, 255],
|
[0, 48, 255, 255],
|
||||||
[255, 159, 0, 255], [255, 155, 0, 255], [255, 151, 0, 255], [255, 147, 0, 255],
|
[0, 52, 255, 255],
|
||||||
[255, 143, 0, 255], [255, 139, 0, 255], [255, 135, 0, 255], [255, 131, 0, 255],
|
[0, 56, 255, 255],
|
||||||
[255, 128, 0, 255], [255, 124, 0, 255], [255, 120, 0, 255], [255, 116, 0, 255],
|
[0, 60, 255, 255],
|
||||||
[255, 112, 0, 255], [255, 108, 0, 255], [255, 104, 0, 255], [255, 100, 0, 255],
|
[0, 64, 255, 255],
|
||||||
[255, 96, 0, 255], [255, 92, 0, 255], [255, 88, 0, 255], [255, 84, 0, 255],
|
[0, 68, 255, 255],
|
||||||
[255, 80, 0, 255], [255, 76, 0, 255], [255, 72, 0, 255], [255, 68, 0, 255],
|
[0, 72, 255, 255],
|
||||||
[255, 64, 0, 255], [255, 60, 0, 255], [255, 56, 0, 255], [255, 52, 0, 255],
|
[0, 76, 255, 255],
|
||||||
[255, 48, 0, 255], [255, 44, 0, 255], [255, 40, 0, 255], [255, 36, 0, 255],
|
[0, 80, 255, 255],
|
||||||
[255, 32, 0, 255], [255, 28, 0, 255], [255, 24, 0, 255], [255, 20, 0, 255],
|
[0, 84, 255, 255],
|
||||||
[255, 16, 0, 255], [255, 12, 0, 255], [255, 8, 0, 255], [255, 4, 0, 255],
|
[0, 88, 255, 255],
|
||||||
[255, 0, 0, 255], [251, 0, 0, 255], [247, 0, 0, 255], [243, 0, 0, 255],
|
[0, 92, 255, 255],
|
||||||
[239, 0, 0, 255], [235, 0, 0, 255], [231, 0, 0, 255], [227, 0, 0, 255],
|
[0, 96, 255, 255],
|
||||||
[223, 0, 0, 255], [219, 0, 0, 255], [215, 0, 0, 255], [211, 0, 0, 255],
|
[0, 100, 255, 255],
|
||||||
[207, 0, 0, 255], [203, 0, 0, 255], [199, 0, 0, 255], [195, 0, 0, 255],
|
[0, 104, 255, 255],
|
||||||
[191, 0, 0, 255], [187, 0, 0, 255], [183, 0, 0, 255], [179, 0, 0, 255],
|
[0, 108, 255, 255],
|
||||||
[175, 0, 0, 255], [171, 0, 0, 255], [167, 0, 0, 255], [163, 0, 0, 255],
|
[0, 112, 255, 255],
|
||||||
[159, 0, 0, 255], [155, 0, 0, 255], [151, 0, 0, 255], [147, 0, 0, 255],
|
[0, 116, 255, 255],
|
||||||
[143, 0, 0, 255], [139, 0, 0, 255], [135, 0, 0, 255], [131, 0, 0, 255],
|
[0, 120, 255, 255],
|
||||||
[ 0, 0, 0, 0]];
|
[0, 124, 255, 255],
|
||||||
|
[0, 128, 255, 255],
|
||||||
|
[0, 131, 255, 255],
|
||||||
|
[0, 135, 255, 255],
|
||||||
|
[0, 139, 255, 255],
|
||||||
|
[0, 143, 255, 255],
|
||||||
|
[0, 147, 255, 255],
|
||||||
|
[0, 151, 255, 255],
|
||||||
|
[0, 155, 255, 255],
|
||||||
|
[0, 159, 255, 255],
|
||||||
|
[0, 163, 255, 255],
|
||||||
|
[0, 167, 255, 255],
|
||||||
|
[0, 171, 255, 255],
|
||||||
|
[0, 175, 255, 255],
|
||||||
|
[0, 179, 255, 255],
|
||||||
|
[0, 183, 255, 255],
|
||||||
|
[0, 187, 255, 255],
|
||||||
|
[0, 191, 255, 255],
|
||||||
|
[0, 195, 255, 255],
|
||||||
|
[0, 199, 255, 255],
|
||||||
|
[0, 203, 255, 255],
|
||||||
|
[0, 207, 255, 255],
|
||||||
|
[0, 211, 255, 255],
|
||||||
|
[0, 215, 255, 255],
|
||||||
|
[0, 219, 255, 255],
|
||||||
|
[0, 223, 255, 255],
|
||||||
|
[0, 227, 255, 255],
|
||||||
|
[0, 231, 255, 255],
|
||||||
|
[0, 235, 255, 255],
|
||||||
|
[0, 239, 255, 255],
|
||||||
|
[0, 243, 255, 255],
|
||||||
|
[0, 247, 255, 255],
|
||||||
|
[0, 251, 255, 255],
|
||||||
|
[0, 255, 255, 255],
|
||||||
|
[4, 255, 251, 255],
|
||||||
|
[8, 255, 247, 255],
|
||||||
|
[12, 255, 243, 255],
|
||||||
|
[16, 255, 239, 255],
|
||||||
|
[20, 255, 235, 255],
|
||||||
|
[24, 255, 231, 255],
|
||||||
|
[28, 255, 227, 255],
|
||||||
|
[32, 255, 223, 255],
|
||||||
|
[36, 255, 219, 255],
|
||||||
|
[40, 255, 215, 255],
|
||||||
|
[44, 255, 211, 255],
|
||||||
|
[48, 255, 207, 255],
|
||||||
|
[52, 255, 203, 255],
|
||||||
|
[56, 255, 199, 255],
|
||||||
|
[60, 255, 195, 255],
|
||||||
|
[64, 255, 191, 255],
|
||||||
|
[68, 255, 187, 255],
|
||||||
|
[72, 255, 183, 255],
|
||||||
|
[76, 255, 179, 255],
|
||||||
|
[80, 255, 175, 255],
|
||||||
|
[84, 255, 171, 255],
|
||||||
|
[88, 255, 167, 255],
|
||||||
|
[92, 255, 163, 255],
|
||||||
|
[96, 255, 159, 255],
|
||||||
|
[100, 255, 155, 255],
|
||||||
|
[104, 255, 151, 255],
|
||||||
|
[108, 255, 147, 255],
|
||||||
|
[112, 255, 143, 255],
|
||||||
|
[116, 255, 139, 255],
|
||||||
|
[120, 255, 135, 255],
|
||||||
|
[124, 255, 131, 255],
|
||||||
|
[128, 255, 128, 255],
|
||||||
|
[131, 255, 124, 255],
|
||||||
|
[135, 255, 120, 255],
|
||||||
|
[139, 255, 116, 255],
|
||||||
|
[143, 255, 112, 255],
|
||||||
|
[147, 255, 108, 255],
|
||||||
|
[151, 255, 104, 255],
|
||||||
|
[155, 255, 100, 255],
|
||||||
|
[159, 255, 96, 255],
|
||||||
|
[163, 255, 92, 255],
|
||||||
|
[167, 255, 88, 255],
|
||||||
|
[171, 255, 84, 255],
|
||||||
|
[175, 255, 80, 255],
|
||||||
|
[179, 255, 76, 255],
|
||||||
|
[183, 255, 72, 255],
|
||||||
|
[187, 255, 68, 255],
|
||||||
|
[191, 255, 64, 255],
|
||||||
|
[195, 255, 60, 255],
|
||||||
|
[199, 255, 56, 255],
|
||||||
|
[203, 255, 52, 255],
|
||||||
|
[207, 255, 48, 255],
|
||||||
|
[211, 255, 44, 255],
|
||||||
|
[215, 255, 40, 255],
|
||||||
|
[219, 255, 36, 255],
|
||||||
|
[223, 255, 32, 255],
|
||||||
|
[227, 255, 28, 255],
|
||||||
|
[231, 255, 24, 255],
|
||||||
|
[235, 255, 20, 255],
|
||||||
|
[239, 255, 16, 255],
|
||||||
|
[243, 255, 12, 255],
|
||||||
|
[247, 255, 8, 255],
|
||||||
|
[251, 255, 4, 255],
|
||||||
|
[255, 255, 0, 255],
|
||||||
|
[255, 251, 0, 255],
|
||||||
|
[255, 247, 0, 255],
|
||||||
|
[255, 243, 0, 255],
|
||||||
|
[255, 239, 0, 255],
|
||||||
|
[255, 235, 0, 255],
|
||||||
|
[255, 231, 0, 255],
|
||||||
|
[255, 227, 0, 255],
|
||||||
|
[255, 223, 0, 255],
|
||||||
|
[255, 219, 0, 255],
|
||||||
|
[255, 215, 0, 255],
|
||||||
|
[255, 211, 0, 255],
|
||||||
|
[255, 207, 0, 255],
|
||||||
|
[255, 203, 0, 255],
|
||||||
|
[255, 199, 0, 255],
|
||||||
|
[255, 195, 0, 255],
|
||||||
|
[255, 191, 0, 255],
|
||||||
|
[255, 187, 0, 255],
|
||||||
|
[255, 183, 0, 255],
|
||||||
|
[255, 179, 0, 255],
|
||||||
|
[255, 175, 0, 255],
|
||||||
|
[255, 171, 0, 255],
|
||||||
|
[255, 167, 0, 255],
|
||||||
|
[255, 163, 0, 255],
|
||||||
|
[255, 159, 0, 255],
|
||||||
|
[255, 155, 0, 255],
|
||||||
|
[255, 151, 0, 255],
|
||||||
|
[255, 147, 0, 255],
|
||||||
|
[255, 143, 0, 255],
|
||||||
|
[255, 139, 0, 255],
|
||||||
|
[255, 135, 0, 255],
|
||||||
|
[255, 131, 0, 255],
|
||||||
|
[255, 128, 0, 255],
|
||||||
|
[255, 124, 0, 255],
|
||||||
|
[255, 120, 0, 255],
|
||||||
|
[255, 116, 0, 255],
|
||||||
|
[255, 112, 0, 255],
|
||||||
|
[255, 108, 0, 255],
|
||||||
|
[255, 104, 0, 255],
|
||||||
|
[255, 100, 0, 255],
|
||||||
|
[255, 96, 0, 255],
|
||||||
|
[255, 92, 0, 255],
|
||||||
|
[255, 88, 0, 255],
|
||||||
|
[255, 84, 0, 255],
|
||||||
|
[255, 80, 0, 255],
|
||||||
|
[255, 76, 0, 255],
|
||||||
|
[255, 72, 0, 255],
|
||||||
|
[255, 68, 0, 255],
|
||||||
|
[255, 64, 0, 255],
|
||||||
|
[255, 60, 0, 255],
|
||||||
|
[255, 56, 0, 255],
|
||||||
|
[255, 52, 0, 255],
|
||||||
|
[255, 48, 0, 255],
|
||||||
|
[255, 44, 0, 255],
|
||||||
|
[255, 40, 0, 255],
|
||||||
|
[255, 36, 0, 255],
|
||||||
|
[255, 32, 0, 255],
|
||||||
|
[255, 28, 0, 255],
|
||||||
|
[255, 24, 0, 255],
|
||||||
|
[255, 20, 0, 255],
|
||||||
|
[255, 16, 0, 255],
|
||||||
|
[255, 12, 0, 255],
|
||||||
|
[255, 8, 0, 255],
|
||||||
|
[255, 4, 0, 255],
|
||||||
|
[255, 0, 0, 255],
|
||||||
|
[251, 0, 0, 255],
|
||||||
|
[247, 0, 0, 255],
|
||||||
|
[243, 0, 0, 255],
|
||||||
|
[239, 0, 0, 255],
|
||||||
|
[235, 0, 0, 255],
|
||||||
|
[231, 0, 0, 255],
|
||||||
|
[227, 0, 0, 255],
|
||||||
|
[223, 0, 0, 255],
|
||||||
|
[219, 0, 0, 255],
|
||||||
|
[215, 0, 0, 255],
|
||||||
|
[211, 0, 0, 255],
|
||||||
|
[207, 0, 0, 255],
|
||||||
|
[203, 0, 0, 255],
|
||||||
|
[199, 0, 0, 255],
|
||||||
|
[195, 0, 0, 255],
|
||||||
|
[191, 0, 0, 255],
|
||||||
|
[187, 0, 0, 255],
|
||||||
|
[183, 0, 0, 255],
|
||||||
|
[179, 0, 0, 255],
|
||||||
|
[175, 0, 0, 255],
|
||||||
|
[171, 0, 0, 255],
|
||||||
|
[167, 0, 0, 255],
|
||||||
|
[163, 0, 0, 255],
|
||||||
|
[159, 0, 0, 255],
|
||||||
|
[155, 0, 0, 255],
|
||||||
|
[151, 0, 0, 255],
|
||||||
|
[147, 0, 0, 255],
|
||||||
|
[143, 0, 0, 255],
|
||||||
|
[139, 0, 0, 255],
|
||||||
|
[135, 0, 0, 255],
|
||||||
|
[131, 0, 0, 255],
|
||||||
|
[0, 0, 0, 0],
|
||||||
|
];
|
||||||
|
|
||||||
function incrLine()
|
function incrLine() {
|
||||||
{
|
if ((vert && !rhc) || (!vert && rhc)) {
|
||||||
if ((vert && !rhc) || (!vert && rhc))
|
|
||||||
{
|
|
||||||
nextLine++;
|
nextLine++;
|
||||||
if (nextLine >= lines)
|
if (nextLine >= lines) {
|
||||||
{
|
|
||||||
nextLine = 0;
|
nextLine = 0;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
nextLine--;
|
nextLine--;
|
||||||
if (nextLine < 0)
|
if (nextLine < 0) {
|
||||||
{
|
|
||||||
nextLine = lines - 1;
|
nextLine = lines - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateWaterfall() // update dynamic waterfalls at a fixed rate
|
function updateWaterfall() {
|
||||||
{
|
// update dynamic waterfalls at a fixed rate
|
||||||
let sgDiff;
|
let sgDiff;
|
||||||
|
|
||||||
// grab latest line of data, write it to off screen buffer, inc 'nextLine'
|
// grab latest line of data, write it to off screen buffer, inc 'nextLine'
|
||||||
|
@ -195,26 +378,20 @@ var Waterfall, Rasterscan;
|
||||||
// loop to write data data at the desired rate, data is being updated asynchronously
|
// loop to write data data at the desired rate, data is being updated asynchronously
|
||||||
// ref for accurate timeout: http://www.sitepoint.com/creating-accurate-timers-in-javascript
|
// ref for accurate timeout: http://www.sitepoint.com/creating-accurate-timers-in-javascript
|
||||||
sgTime += interval;
|
sgTime += interval;
|
||||||
sgDiff = (Date.now() - sgStartTime) - sgTime;
|
sgDiff = Date.now() - sgStartTime - sgTime;
|
||||||
if (running)
|
if (running) {
|
||||||
{
|
|
||||||
timerID = setTimeout(updateWaterfall, interval - sgDiff);
|
timerID = setTimeout(updateWaterfall, interval - sgDiff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function sgSetLineRate(newRate)
|
function sgSetLineRate(newRate) {
|
||||||
{
|
if (isNaN(newRate) || newRate > 50 || newRate < 0) {
|
||||||
if (isNaN(newRate) || newRate > 50 || newRate < 0)
|
|
||||||
{
|
|
||||||
console.error("invalid line rate [0 <= lineRate < 50 lines/sec]");
|
console.error("invalid line rate [0 <= lineRate < 50 lines/sec]");
|
||||||
// don't change the lineRate;
|
// don't change the lineRate;
|
||||||
}
|
} else if (newRate === 0) {
|
||||||
else if (newRate === 0) // static (one pass) raster
|
// static (one pass) raster
|
||||||
{
|
|
||||||
lineRate = 0;
|
lineRate = 0;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
lineRate = newRate;
|
lineRate = newRate;
|
||||||
interval = 1000 / lineRate; // msec
|
interval = 1000 / lineRate; // msec
|
||||||
}
|
}
|
||||||
|
@ -222,37 +399,35 @@ var Waterfall, Rasterscan;
|
||||||
|
|
||||||
this.setLineRate = sgSetLineRate;
|
this.setLineRate = sgSetLineRate;
|
||||||
|
|
||||||
function setProperty(propertyName, value)
|
function setProperty(propertyName, value) {
|
||||||
{
|
if (typeof propertyName !== "string" || value === undefined) {
|
||||||
if ((typeof propertyName !== "string")||(value === undefined)) // null is OK, forces default
|
// null is OK, forces default
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (propertyName.toLowerCase())
|
switch (propertyName.toLowerCase()) {
|
||||||
{
|
|
||||||
case "linerate":
|
case "linerate":
|
||||||
sgSetLineRate(value); // setLine does checks for number etc
|
sgSetLineRate(value); // setLine does checks for number etc
|
||||||
break;
|
break;
|
||||||
case "startbin":
|
case "startbin":
|
||||||
if (!isNaN(value) && value > 0)
|
if (!isNaN(value) && value > 0) {
|
||||||
{
|
|
||||||
startOfs = value;
|
startOfs = value;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "onscreenparentid":
|
case "onscreenparentid":
|
||||||
if (typeof value === "string" && document.getElementById(value))
|
if (typeof value === "string" && document.getElementById(value)) {
|
||||||
{
|
|
||||||
demoCvsId = value;
|
demoCvsId = value;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "colormap":
|
case "colormap":
|
||||||
if (Array.isArray(value) && Array.isArray(value[0]) && value[0].length == 4)
|
if (
|
||||||
{
|
Array.isArray(value) &&
|
||||||
|
Array.isArray(value[0]) &&
|
||||||
|
value[0].length == 4
|
||||||
|
) {
|
||||||
colMap = value; // value must be an array of 4 element arrays to get here
|
colMap = value; // value must be an array of 4 element arrays to get here
|
||||||
if (colMap.length<256) // fill out the remaining colors with last color
|
if (colMap.length < 256) {
|
||||||
{
|
// fill out the remaining colors with last color
|
||||||
for (let i=colMap.length; i<256; i++)
|
for (let i = colMap.length; i < 256; i++) {
|
||||||
{
|
|
||||||
colMap[i] = colMap[colMap.length - 1];
|
colMap[i] = colMap[colMap.length - 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -263,28 +438,26 @@ var Waterfall, Rasterscan;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function verticalNewLine()
|
function verticalNewLine() {
|
||||||
{
|
|
||||||
let tmpImgData, ipBuf8;
|
let tmpImgData, ipBuf8;
|
||||||
|
|
||||||
if (sgMode == "WF")
|
if (sgMode == "WF") {
|
||||||
{
|
if (rhc) {
|
||||||
if (rhc)
|
|
||||||
{
|
|
||||||
// shift the current display down 1 line, oldest line drops off
|
// shift the current display down 1 line, oldest line drops off
|
||||||
tmpImgData = offScreenCtx.getImageData(0, 0, pxPerLine, lines - 1);
|
tmpImgData = offScreenCtx.getImageData(0, 0, pxPerLine, lines - 1);
|
||||||
offScreenCtx.putImageData(tmpImgData, 0, 1);
|
offScreenCtx.putImageData(tmpImgData, 0, 1);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// shift the current display up 1 line, oldest line drops off
|
// shift the current display up 1 line, oldest line drops off
|
||||||
tmpImgData = offScreenCtx.getImageData(0, 1, pxPerLine, lines - 1);
|
tmpImgData = offScreenCtx.getImageData(0, 1, pxPerLine, lines - 1);
|
||||||
offScreenCtx.putImageData(tmpImgData, 0, 0);
|
offScreenCtx.putImageData(tmpImgData, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ipBuf8 = Uint8ClampedArray.from(ipBufAry[0]);
|
ipBuf8 = Uint8ClampedArray.from(ipBufAry[0]);
|
||||||
for (let sigVal, rgba, opIdx = 0, ipIdx = startOfs; ipIdx < pxPerLine+startOfs; opIdx += 4, ipIdx++)
|
for (
|
||||||
{
|
let sigVal, rgba, opIdx = 0, ipIdx = startOfs;
|
||||||
|
ipIdx < pxPerLine + startOfs;
|
||||||
|
opIdx += 4, ipIdx++
|
||||||
|
) {
|
||||||
sigVal = ipBuf8[ipIdx] || 0; // if input line too short add zeros
|
sigVal = ipBuf8[ipIdx] || 0; // if input line too short add zeros
|
||||||
rgba = colMap[sigVal]; // array of rgba values
|
rgba = colMap[sigVal]; // array of rgba values
|
||||||
// byte reverse so number aa bb gg rr
|
// byte reverse so number aa bb gg rr
|
||||||
|
@ -294,31 +467,24 @@ var Waterfall, Rasterscan;
|
||||||
lineBuf8[opIdx + 3] = rgba[3]; // alpha
|
lineBuf8[opIdx + 3] = rgba[3]; // alpha
|
||||||
}
|
}
|
||||||
offScreenCtx.putImageData(lineImgData, 0, nextLine);
|
offScreenCtx.putImageData(lineImgData, 0, nextLine);
|
||||||
if (sgMode === "RS")
|
if (sgMode === "RS") {
|
||||||
{
|
|
||||||
incrLine();
|
incrLine();
|
||||||
// if not static draw a white line in front of the current line to indicate new data point
|
// if not static draw a white line in front of the current line to indicate new data point
|
||||||
if (lineRate)
|
if (lineRate) {
|
||||||
{
|
|
||||||
offScreenCtx.putImageData(blankImgData, 0, nextLine);
|
offScreenCtx.putImageData(blankImgData, 0, nextLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
function horizontalNewLine()
|
function horizontalNewLine() {
|
||||||
{
|
|
||||||
let tmpImgData, ipBuf8;
|
let tmpImgData, ipBuf8;
|
||||||
|
|
||||||
if (sgMode == "WF")
|
if (sgMode == "WF") {
|
||||||
{
|
if (rhc) {
|
||||||
if (rhc)
|
|
||||||
{
|
|
||||||
// shift the current display right 1 line, oldest line drops off
|
// shift the current display right 1 line, oldest line drops off
|
||||||
tmpImgData = offScreenCtx.getImageData(0, 0, lines - 1, pxPerLine);
|
tmpImgData = offScreenCtx.getImageData(0, 0, lines - 1, pxPerLine);
|
||||||
offScreenCtx.putImageData(tmpImgData, 1, 0);
|
offScreenCtx.putImageData(tmpImgData, 1, 0);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// shift the current display left 1 line, oldest line drops off
|
// shift the current display left 1 line, oldest line drops off
|
||||||
tmpImgData = offScreenCtx.getImageData(1, 0, lines - 1, pxPerLine);
|
tmpImgData = offScreenCtx.getImageData(1, 0, lines - 1, pxPerLine);
|
||||||
offScreenCtx.putImageData(tmpImgData, 0, 0);
|
offScreenCtx.putImageData(tmpImgData, 0, 0);
|
||||||
|
@ -326,17 +492,13 @@ var Waterfall, Rasterscan;
|
||||||
}
|
}
|
||||||
// refresh the page image (it was just shifted)
|
// refresh the page image (it was just shifted)
|
||||||
pageImgData = offScreenCtx.getImageData(0, 0, lines, pxPerLine);
|
pageImgData = offScreenCtx.getImageData(0, 0, lines, pxPerLine);
|
||||||
if (ipBufAry[0].constructor !== Uint8Array)
|
if (ipBufAry[0].constructor !== Uint8Array) {
|
||||||
{
|
|
||||||
ipBuf8 = Uint8ClampedArray.from(ipBufAry[0]); // clamp input values to 0..255 range
|
ipBuf8 = Uint8ClampedArray.from(ipBufAry[0]); // clamp input values to 0..255 range
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
ipBuf8 = ipBufAry[0]; // conversion already done
|
ipBuf8 = ipBufAry[0]; // conversion already done
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let sigVal, rgba, opIdx, ipIdx=0; ipIdx < pxPerLine; ipIdx++)
|
for (let sigVal, rgba, opIdx, ipIdx = 0; ipIdx < pxPerLine; ipIdx++) {
|
||||||
{
|
|
||||||
sigVal = ipBuf8[ipIdx + startOfs] || 0; // if input line too short add zeros
|
sigVal = ipBuf8[ipIdx + startOfs] || 0; // if input line too short add zeros
|
||||||
rgba = colMap[sigVal]; // array of rgba values
|
rgba = colMap[sigVal]; // array of rgba values
|
||||||
opIdx = 4 * ((pxPerLine - ipIdx - 1) * lines + nextLine);
|
opIdx = 4 * ((pxPerLine - ipIdx - 1) * lines + nextLine);
|
||||||
|
@ -346,20 +508,14 @@ var Waterfall, Rasterscan;
|
||||||
pageImgData.data[opIdx + 2] = rgba[2]; // blue
|
pageImgData.data[opIdx + 2] = rgba[2]; // blue
|
||||||
pageImgData.data[opIdx + 3] = rgba[3]; // alpha
|
pageImgData.data[opIdx + 3] = rgba[3]; // alpha
|
||||||
}
|
}
|
||||||
if (sgMode === "RS")
|
if (sgMode === "RS") {
|
||||||
{
|
|
||||||
incrLine();
|
incrLine();
|
||||||
// if not draw a white line in front of the current line to indicate new data point
|
// if not draw a white line in front of the current line to indicate new data point
|
||||||
if (lineRate)
|
if (lineRate) {
|
||||||
{
|
for (let j = 0; j < pxPerLine; j++) {
|
||||||
for (let j=0; j < pxPerLine; j++)
|
if (rhc) {
|
||||||
{
|
|
||||||
if (rhc)
|
|
||||||
{
|
|
||||||
opIdx = 4 * (j * lines + nextLine);
|
opIdx = 4 * (j * lines + nextLine);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
opIdx = 4 * ((pxPerLine - j - 1) * lines + nextLine);
|
opIdx = 4 * ((pxPerLine - j - 1) * lines + nextLine);
|
||||||
}
|
}
|
||||||
// byte reverse so number aa bb gg rr
|
// byte reverse so number aa bb gg rr
|
||||||
|
@ -371,16 +527,14 @@ var Waterfall, Rasterscan;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
offScreenCtx.putImageData(pageImgData, 0, 0);
|
offScreenCtx.putImageData(pageImgData, 0, 0);
|
||||||
};
|
}
|
||||||
|
|
||||||
const sgNewLine = (vert)? verticalNewLine: horizontalNewLine; // function pointers
|
const sgNewLine = vert ? verticalNewLine : horizontalNewLine; // function pointers
|
||||||
|
|
||||||
//===== set all the options ================
|
//===== set all the options ================
|
||||||
for (let prop in opt)
|
for (let prop in opt) {
|
||||||
{
|
|
||||||
// check that this is opt's own property, not inherited from prototype
|
// check that this is opt's own property, not inherited from prototype
|
||||||
if (opt.hasOwnProperty(prop))
|
if (opt.hasOwnProperty(prop)) {
|
||||||
{
|
|
||||||
setProperty(prop, opt[prop]);
|
setProperty(prop, opt[prop]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -389,63 +543,51 @@ var Waterfall, Rasterscan;
|
||||||
this.newLine = sgNewLine;
|
this.newLine = sgNewLine;
|
||||||
|
|
||||||
this.offScreenCvs = document.createElement("canvas");
|
this.offScreenCvs = document.createElement("canvas");
|
||||||
if (vert)
|
if (vert) {
|
||||||
{
|
this.offScreenCvs.setAttribute("width", pxPerLine); // reset canvas pixels width
|
||||||
this.offScreenCvs.setAttribute('width', pxPerLine); // reset canvas pixels width
|
this.offScreenCvs.setAttribute("height", lines); // don't use style for this
|
||||||
this.offScreenCvs.setAttribute('height', lines); // don't use style for this
|
|
||||||
clearImgData = new ImageData(clearBuf8, pxPerLine, lines);
|
clearImgData = new ImageData(clearBuf8, pxPerLine, lines);
|
||||||
}
|
} // data written in columns
|
||||||
else // data written in columns
|
else {
|
||||||
{
|
this.offScreenCvs.setAttribute("width", lines); // reset canvas pixels width
|
||||||
this.offScreenCvs.setAttribute('width', lines); // reset canvas pixels width
|
this.offScreenCvs.setAttribute("height", pxPerLine); // don't use style for this
|
||||||
this.offScreenCvs.setAttribute('height', pxPerLine); // don't use style for this
|
|
||||||
clearImgData = new ImageData(clearBuf8, lines, pxPerLine);
|
clearImgData = new ImageData(clearBuf8, lines, pxPerLine);
|
||||||
}
|
}
|
||||||
offScreenCtx = this.offScreenCvs.getContext("2d");
|
offScreenCtx = this.offScreenCvs.getContext("2d");
|
||||||
|
|
||||||
this.clear = function()
|
this.clear = function () {
|
||||||
{
|
|
||||||
offScreenCtx.putImageData(clearImgData, 0, 0);
|
offScreenCtx.putImageData(clearImgData, 0, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.start = function()
|
this.start = function () {
|
||||||
{
|
|
||||||
sgStartTime = Date.now();
|
sgStartTime = Date.now();
|
||||||
sgTime = 0;
|
sgTime = 0;
|
||||||
running = true;
|
running = true;
|
||||||
updateWaterfall(); // start the update loop
|
updateWaterfall(); // start the update loop
|
||||||
};
|
};
|
||||||
|
|
||||||
this.stop = function()
|
this.stop = function () {
|
||||||
{
|
|
||||||
running = false;
|
running = false;
|
||||||
if (timerID)
|
if (timerID) {
|
||||||
{
|
|
||||||
clearTimeout(timerID);
|
clearTimeout(timerID);
|
||||||
}
|
}
|
||||||
// reset where the next line is to be written
|
// reset where the next line is to be written
|
||||||
if (sgMode === "RS")
|
if (sgMode === "RS") {
|
||||||
{
|
if (vert) {
|
||||||
if (vert)
|
nextLine = rhc ? lines - 1 : 0;
|
||||||
{
|
} else {
|
||||||
nextLine = (rhc)? lines-1 : 0;
|
nextLine = rhc ? 0 : lines - 1;
|
||||||
}
|
}
|
||||||
else
|
} // WF
|
||||||
{
|
else {
|
||||||
nextLine = (rhc)? 0 : lines-1;
|
nextLine = rhc ? 0 : lines - 1;
|
||||||
}
|
|
||||||
}
|
|
||||||
else // WF
|
|
||||||
{
|
|
||||||
nextLine = (rhc)? 0 : lines-1;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// make a white line, it will show the input line for RS displays
|
// make a white line, it will show the input line for RS displays
|
||||||
blankBuf8.fill(255);
|
blankBuf8.fill(255);
|
||||||
// make a full canvas of the color map 0 values
|
// make a full canvas of the color map 0 values
|
||||||
for (let i=0; i<pxPerLine*lines*4; i+=4)
|
for (let i = 0; i < pxPerLine * lines * 4; i += 4) {
|
||||||
{
|
|
||||||
// byte reverse so number aa bb gg rr
|
// byte reverse so number aa bb gg rr
|
||||||
clearBuf8[i] = colMap[0][0]; // red
|
clearBuf8[i] = colMap[0][0]; // red
|
||||||
clearBuf8[i + 1] = colMap[0][1]; // green
|
clearBuf8[i + 1] = colMap[0][1]; // green
|
||||||
|
@ -453,8 +595,7 @@ var Waterfall, Rasterscan;
|
||||||
clearBuf8[i + 3] = colMap[0][3]; // alpha
|
clearBuf8[i + 3] = colMap[0][3]; // alpha
|
||||||
}
|
}
|
||||||
// for diagnostics only
|
// for diagnostics only
|
||||||
if (typeof(demoCvsId) == "string")
|
if (typeof demoCvsId == "string") {
|
||||||
{
|
|
||||||
document.getElementById(demoCvsId).appendChild(this.offScreenCvs);
|
document.getElementById(demoCvsId).appendChild(this.offScreenCvs);
|
||||||
}
|
}
|
||||||
// initialize the direction and first line position
|
// initialize the direction and first line position
|
||||||
|
@ -463,4 +604,4 @@ var Waterfall, Rasterscan;
|
||||||
// everything is set
|
// everything is set
|
||||||
// if dynamic, wait for the start or newLine methods to be called
|
// if dynamic, wait for the start or newLine methods to be called
|
||||||
}
|
}
|
||||||
}())
|
})();
|
||||||
|
|
|
@ -4,16 +4,16 @@
|
||||||
* See the LICENSE file for further details.
|
* See the LICENSE file for further details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
Spectrum.prototype.squeeze = function (value, out_min, out_max) {
|
Spectrum.prototype.squeeze = function (value, out_min, out_max) {
|
||||||
if (value <= this.min_db)
|
if (value <= this.min_db) return out_min;
|
||||||
return out_min;
|
else if (value >= this.max_db) return out_max;
|
||||||
else if (value >= this.max_db)
|
|
||||||
return out_max;
|
|
||||||
else
|
else
|
||||||
return Math.round((value - this.min_db) / (this.max_db - this.min_db) * out_max);
|
return Math.round(
|
||||||
}
|
((value - this.min_db) / (this.max_db - this.min_db)) * out_max
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
Spectrum.prototype.rowToImageData = function (bins) {
|
Spectrum.prototype.rowToImageData = function (bins) {
|
||||||
for (var i = 0; i < this.imagedata.data.length; i += 4) {
|
for (var i = 0; i < this.imagedata.data.length; i += 4) {
|
||||||
|
@ -24,13 +24,21 @@ Spectrum.prototype.rowToImageData = function(bins) {
|
||||||
this.imagedata.data[i + 2] = color[2];
|
this.imagedata.data[i + 2] = color[2];
|
||||||
this.imagedata.data[i + 3] = 255;
|
this.imagedata.data[i + 3] = 255;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
Spectrum.prototype.addWaterfallRow = function (bins) {
|
Spectrum.prototype.addWaterfallRow = function (bins) {
|
||||||
// Shift waterfall 1 row down
|
// Shift waterfall 1 row down
|
||||||
this.ctx_wf.drawImage(this.ctx_wf.canvas,
|
this.ctx_wf.drawImage(
|
||||||
0, 0, this.wf_size, this.wf_rows - 1,
|
this.ctx_wf.canvas,
|
||||||
0, 1, this.wf_size, this.wf_rows - 1);
|
0,
|
||||||
|
0,
|
||||||
|
this.wf_size,
|
||||||
|
this.wf_rows - 1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
this.wf_size,
|
||||||
|
this.wf_rows - 1
|
||||||
|
);
|
||||||
|
|
||||||
// Draw new line on waterfall canvas
|
// Draw new line on waterfall canvas
|
||||||
this.rowToImageData(bins);
|
this.rowToImageData(bins);
|
||||||
|
@ -43,37 +51,40 @@ Spectrum.prototype.addWaterfallRow = function(bins) {
|
||||||
// fit in waterfall area to avoid vertical scaling.
|
// fit in waterfall area to avoid vertical scaling.
|
||||||
this.ctx.imageSmoothingEnabled = false;
|
this.ctx.imageSmoothingEnabled = false;
|
||||||
var rows = Math.min(this.wf_rows, height - this.spectrumHeight);
|
var rows = Math.min(this.wf_rows, height - this.spectrumHeight);
|
||||||
this.ctx.drawImage(this.ctx_wf.canvas,
|
this.ctx.drawImage(
|
||||||
0, 0, this.wf_size, rows,
|
this.ctx_wf.canvas,
|
||||||
0, this.spectrumHeight, width, height - this.spectrumHeight);
|
0,
|
||||||
}
|
0,
|
||||||
|
this.wf_size,
|
||||||
|
rows,
|
||||||
|
0,
|
||||||
|
this.spectrumHeight,
|
||||||
|
width,
|
||||||
|
height - this.spectrumHeight
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
Spectrum.prototype.drawFFT = function (bins) {
|
Spectrum.prototype.drawFFT = function (bins) {
|
||||||
this.ctx.beginPath();
|
this.ctx.beginPath();
|
||||||
this.ctx.moveTo(-1, this.spectrumHeight + 1);
|
this.ctx.moveTo(-1, this.spectrumHeight + 1);
|
||||||
for (var i = 0; i < bins.length; i++) {
|
for (var i = 0; i < bins.length; i++) {
|
||||||
var y = this.spectrumHeight - this.squeeze(bins[i], 0, this.spectrumHeight);
|
var y = this.spectrumHeight - this.squeeze(bins[i], 0, this.spectrumHeight);
|
||||||
if (y > this.spectrumHeight - 1)
|
if (y > this.spectrumHeight - 1) y = this.spectrumHeight + 1; // Hide underflow
|
||||||
y = this.spectrumHeight + 1; // Hide underflow
|
if (y < 0) y = 0;
|
||||||
if (y < 0)
|
if (i == 0) this.ctx.lineTo(-1, y);
|
||||||
y = 0;
|
|
||||||
if (i == 0)
|
|
||||||
this.ctx.lineTo(-1, y);
|
|
||||||
this.ctx.lineTo(i, y);
|
this.ctx.lineTo(i, y);
|
||||||
if (i == bins.length - 1)
|
if (i == bins.length - 1) this.ctx.lineTo(this.wf_size + 1, y);
|
||||||
this.ctx.lineTo(this.wf_size + 1, y);
|
|
||||||
}
|
}
|
||||||
this.ctx.lineTo(this.wf_size + 1, this.spectrumHeight + 1);
|
this.ctx.lineTo(this.wf_size + 1, this.spectrumHeight + 1);
|
||||||
this.ctx.strokeStyle = "#fefefe";
|
this.ctx.strokeStyle = "#fefefe";
|
||||||
this.ctx.stroke();
|
this.ctx.stroke();
|
||||||
}
|
};
|
||||||
|
|
||||||
//Spectrum.prototype.drawSpectrum = function(bins) {
|
//Spectrum.prototype.drawSpectrum = function(bins) {
|
||||||
Spectrum.prototype.drawSpectrum = function () {
|
Spectrum.prototype.drawSpectrum = function () {
|
||||||
var width = this.ctx.canvas.width;
|
var width = this.ctx.canvas.width;
|
||||||
var height = this.ctx.canvas.height;
|
var height = this.ctx.canvas.height;
|
||||||
|
|
||||||
|
|
||||||
// Modification by DJ2LS
|
// Modification by DJ2LS
|
||||||
// Draw bandwidth lines
|
// Draw bandwidth lines
|
||||||
// TODO: Math not correct. But a first attempt
|
// TODO: Math not correct. But a first attempt
|
||||||
|
@ -104,12 +115,11 @@ Spectrum.prototype.drawFFT = function(bins) {
|
||||||
this.ctx_wf.moveTo(linePositionHigh2, 0);
|
this.ctx_wf.moveTo(linePositionHigh2, 0);
|
||||||
this.ctx_wf.lineTo(linePositionHigh2, height);
|
this.ctx_wf.lineTo(linePositionHigh2, height);
|
||||||
this.ctx_wf.lineWidth = 1;
|
this.ctx_wf.lineWidth = 1;
|
||||||
this.ctx_wf.strokeStyle = '#C3C3C3';
|
this.ctx_wf.strokeStyle = "#C3C3C3";
|
||||||
this.ctx_wf.stroke()
|
this.ctx_wf.stroke();
|
||||||
|
|
||||||
// ---- END OF MODIFICATION ------
|
// ---- END OF MODIFICATION ------
|
||||||
|
|
||||||
|
|
||||||
// Fill with black
|
// Fill with black
|
||||||
this.ctx.fillStyle = "white";
|
this.ctx.fillStyle = "white";
|
||||||
this.ctx.fillRect(0, 0, width, height);
|
this.ctx.fillRect(0, 0, width, height);
|
||||||
|
@ -170,12 +180,12 @@ Spectrum.prototype.drawFFT = function(bins) {
|
||||||
// Copy axes from offscreen canvas
|
// Copy axes from offscreen canvas
|
||||||
this.ctx.drawImage(this.ctx_axes.canvas, 0, 0);
|
this.ctx.drawImage(this.ctx_axes.canvas, 0, 0);
|
||||||
*/
|
*/
|
||||||
}
|
};
|
||||||
|
|
||||||
//Allow setting colormap
|
//Allow setting colormap
|
||||||
Spectrum.prototype.setColorMap = function (index) {
|
Spectrum.prototype.setColorMap = function (index) {
|
||||||
this.colormap = colormaps[index];
|
this.colormap = colormaps[index];
|
||||||
}
|
};
|
||||||
|
|
||||||
Spectrum.prototype.updateAxes = function () {
|
Spectrum.prototype.updateAxes = function () {
|
||||||
var width = this.ctx_axes.canvas.width;
|
var width = this.ctx_axes.canvas.width;
|
||||||
|
@ -218,11 +228,9 @@ Spectrum.prototype.updateAxes = function() {
|
||||||
this.ctx_axes.textAlign = "center";
|
this.ctx_axes.textAlign = "center";
|
||||||
}
|
}
|
||||||
|
|
||||||
var freq = this.centerHz + this.spanHz / 10 * (i - 5);
|
var freq = this.centerHz + (this.spanHz / 10) * (i - 5);
|
||||||
if (this.centerHz + this.spanHz > 1e6)
|
if (this.centerHz + this.spanHz > 1e6) freq = freq / 1e6 + "M";
|
||||||
freq = freq / 1e6 + "M";
|
else if (this.centerHz + this.spanHz > 1e3) freq = freq / 1e3 + "k";
|
||||||
else if (this.centerHz + this.spanHz > 1e3)
|
|
||||||
freq = freq / 1e3 + "k";
|
|
||||||
this.ctx_axes.fillText(freq, x + adjust, height - 3);
|
this.ctx_axes.fillText(freq, x + adjust, height - 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,7 +240,7 @@ Spectrum.prototype.updateAxes = function() {
|
||||||
this.ctx_axes.strokeStyle = "rgba(200, 200, 200, 0.10)";
|
this.ctx_axes.strokeStyle = "rgba(200, 200, 200, 0.10)";
|
||||||
this.ctx_axes.stroke();
|
this.ctx_axes.stroke();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
Spectrum.prototype.addData = function (data) {
|
Spectrum.prototype.addData = function (data) {
|
||||||
if (!this.paused) {
|
if (!this.paused) {
|
||||||
|
@ -248,132 +256,132 @@ Spectrum.prototype.addData = function(data) {
|
||||||
this.addWaterfallRow(data);
|
this.addWaterfallRow(data);
|
||||||
this.resize();
|
this.resize();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
Spectrum.prototype.updateSpectrumRatio = function () {
|
Spectrum.prototype.updateSpectrumRatio = function () {
|
||||||
this.spectrumHeight = Math.round(this.canvas.height * this.spectrumPercent / 100.0);
|
this.spectrumHeight = Math.round(
|
||||||
|
(this.canvas.height * this.spectrumPercent) / 100.0
|
||||||
|
);
|
||||||
|
|
||||||
this.gradient = this.ctx.createLinearGradient(0, 0, 0, this.spectrumHeight);
|
this.gradient = this.ctx.createLinearGradient(0, 0, 0, this.spectrumHeight);
|
||||||
for (var i = 0; i < this.colormap.length; i++) {
|
for (var i = 0; i < this.colormap.length; i++) {
|
||||||
var c = this.colormap[this.colormap.length - 1 - i];
|
var c = this.colormap[this.colormap.length - 1 - i];
|
||||||
this.gradient.addColorStop(i / this.colormap.length,
|
this.gradient.addColorStop(
|
||||||
"rgba(" + c[0] + "," + c[1] + "," + c[2] + ", 1.0)");
|
i / this.colormap.length,
|
||||||
}
|
"rgba(" + c[0] + "," + c[1] + "," + c[2] + ", 1.0)"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Spectrum.prototype.resize = function () {
|
Spectrum.prototype.resize = function () {
|
||||||
var width = this.canvas.clientWidth;
|
var width = this.canvas.clientWidth;
|
||||||
var height = this.canvas.clientHeight;
|
var height = this.canvas.clientHeight;
|
||||||
|
|
||||||
if (this.canvas.width != width ||
|
if (this.canvas.width != width || this.canvas.height != height) {
|
||||||
this.canvas.height != height) {
|
|
||||||
this.canvas.width = width;
|
this.canvas.width = width;
|
||||||
this.canvas.height = height;
|
this.canvas.height = height;
|
||||||
this.updateSpectrumRatio();
|
this.updateSpectrumRatio();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.axes.width != width ||
|
if (this.axes.width != width || this.axes.height != this.spectrumHeight) {
|
||||||
this.axes.height != this.spectrumHeight) {
|
|
||||||
this.axes.width = width;
|
this.axes.width = width;
|
||||||
this.axes.height = this.spectrumHeight;
|
this.axes.height = this.spectrumHeight;
|
||||||
this.updateAxes();
|
this.updateAxes();
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
|
||||||
|
|
||||||
Spectrum.prototype.setSpectrumPercent = function (percent) {
|
Spectrum.prototype.setSpectrumPercent = function (percent) {
|
||||||
if (percent >= 0 && percent <= 100) {
|
if (percent >= 0 && percent <= 100) {
|
||||||
this.spectrumPercent = percent;
|
this.spectrumPercent = percent;
|
||||||
this.updateSpectrumRatio();
|
this.updateSpectrumRatio();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
Spectrum.prototype.incrementSpectrumPercent = function () {
|
Spectrum.prototype.incrementSpectrumPercent = function () {
|
||||||
if (this.spectrumPercent + this.spectrumPercentStep <= 100) {
|
if (this.spectrumPercent + this.spectrumPercentStep <= 100) {
|
||||||
this.setSpectrumPercent(this.spectrumPercent + this.spectrumPercentStep);
|
this.setSpectrumPercent(this.spectrumPercent + this.spectrumPercentStep);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
Spectrum.prototype.decrementSpectrumPercent = function () {
|
Spectrum.prototype.decrementSpectrumPercent = function () {
|
||||||
if (this.spectrumPercent - this.spectrumPercentStep >= 0) {
|
if (this.spectrumPercent - this.spectrumPercentStep >= 0) {
|
||||||
this.setSpectrumPercent(this.spectrumPercent - this.spectrumPercentStep);
|
this.setSpectrumPercent(this.spectrumPercent - this.spectrumPercentStep);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
Spectrum.prototype.toggleColor = function () {
|
Spectrum.prototype.toggleColor = function () {
|
||||||
this.colorindex++;
|
this.colorindex++;
|
||||||
if (this.colorindex >= colormaps.length)
|
if (this.colorindex >= colormaps.length) this.colorindex = 0;
|
||||||
this.colorindex = 0;
|
|
||||||
this.colormap = colormaps[this.colorindex];
|
this.colormap = colormaps[this.colorindex];
|
||||||
this.updateSpectrumRatio();
|
this.updateSpectrumRatio();
|
||||||
}
|
};
|
||||||
|
|
||||||
Spectrum.prototype.setRange = function (min_db, max_db) {
|
Spectrum.prototype.setRange = function (min_db, max_db) {
|
||||||
this.min_db = min_db;
|
this.min_db = min_db;
|
||||||
this.max_db = max_db;
|
this.max_db = max_db;
|
||||||
this.updateAxes();
|
this.updateAxes();
|
||||||
}
|
};
|
||||||
|
|
||||||
Spectrum.prototype.rangeUp = function () {
|
Spectrum.prototype.rangeUp = function () {
|
||||||
this.setRange(this.min_db - 5, this.max_db - 5);
|
this.setRange(this.min_db - 5, this.max_db - 5);
|
||||||
}
|
};
|
||||||
|
|
||||||
Spectrum.prototype.rangeDown = function () {
|
Spectrum.prototype.rangeDown = function () {
|
||||||
this.setRange(this.min_db + 5, this.max_db + 5);
|
this.setRange(this.min_db + 5, this.max_db + 5);
|
||||||
}
|
};
|
||||||
|
|
||||||
Spectrum.prototype.rangeIncrease = function () {
|
Spectrum.prototype.rangeIncrease = function () {
|
||||||
this.setRange(this.min_db - 5, this.max_db + 5);
|
this.setRange(this.min_db - 5, this.max_db + 5);
|
||||||
}
|
};
|
||||||
|
|
||||||
Spectrum.prototype.rangeDecrease = function () {
|
Spectrum.prototype.rangeDecrease = function () {
|
||||||
if (this.max_db - this.min_db > 10)
|
if (this.max_db - this.min_db > 10)
|
||||||
this.setRange(this.min_db + 5, this.max_db - 5);
|
this.setRange(this.min_db + 5, this.max_db - 5);
|
||||||
}
|
};
|
||||||
|
|
||||||
Spectrum.prototype.setCenterHz = function (hz) {
|
Spectrum.prototype.setCenterHz = function (hz) {
|
||||||
this.centerHz = hz;
|
this.centerHz = hz;
|
||||||
this.updateAxes();
|
this.updateAxes();
|
||||||
}
|
};
|
||||||
|
|
||||||
Spectrum.prototype.setSpanHz = function (hz) {
|
Spectrum.prototype.setSpanHz = function (hz) {
|
||||||
this.spanHz = hz;
|
this.spanHz = hz;
|
||||||
this.updateAxes();
|
this.updateAxes();
|
||||||
}
|
};
|
||||||
|
|
||||||
Spectrum.prototype.setAveraging = function (num) {
|
Spectrum.prototype.setAveraging = function (num) {
|
||||||
if (num >= 0) {
|
if (num >= 0) {
|
||||||
this.averaging = num;
|
this.averaging = num;
|
||||||
this.alpha = 2 / (this.averaging + 1)
|
this.alpha = 2 / (this.averaging + 1);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Spectrum.prototype.incrementAveraging = function () {
|
Spectrum.prototype.incrementAveraging = function () {
|
||||||
this.setAveraging(this.averaging + 1);
|
this.setAveraging(this.averaging + 1);
|
||||||
}
|
};
|
||||||
|
|
||||||
Spectrum.prototype.decrementAveraging = function () {
|
Spectrum.prototype.decrementAveraging = function () {
|
||||||
if (this.averaging > 0) {
|
if (this.averaging > 0) {
|
||||||
this.setAveraging(this.averaging - 1);
|
this.setAveraging(this.averaging - 1);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
Spectrum.prototype.setPaused = function (paused) {
|
Spectrum.prototype.setPaused = function (paused) {
|
||||||
this.paused = paused;
|
this.paused = paused;
|
||||||
}
|
};
|
||||||
|
|
||||||
Spectrum.prototype.togglePaused = function () {
|
Spectrum.prototype.togglePaused = function () {
|
||||||
this.setPaused(!this.paused);
|
this.setPaused(!this.paused);
|
||||||
}
|
};
|
||||||
|
|
||||||
Spectrum.prototype.setMaxHold = function (maxhold) {
|
Spectrum.prototype.setMaxHold = function (maxhold) {
|
||||||
this.maxHold = maxhold;
|
this.maxHold = maxhold;
|
||||||
this.binsMax = undefined;
|
this.binsMax = undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
Spectrum.prototype.toggleMaxHold = function () {
|
Spectrum.prototype.toggleMaxHold = function () {
|
||||||
this.setMaxHold(!this.maxHold);
|
this.setMaxHold(!this.maxHold);
|
||||||
}
|
};
|
||||||
|
|
||||||
Spectrum.prototype.toggleFullscreen = function () {
|
Spectrum.prototype.toggleFullscreen = function () {
|
||||||
if (!this.fullscreen) {
|
if (!this.fullscreen) {
|
||||||
|
@ -399,7 +407,7 @@ Spectrum.prototype.toggleFullscreen = function() {
|
||||||
}
|
}
|
||||||
this.fullscreen = false;
|
this.fullscreen = false;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
Spectrum.prototype.onKeypress = function (e) {
|
Spectrum.prototype.onKeypress = function (e) {
|
||||||
if (e.key == " ") {
|
if (e.key == " ") {
|
||||||
|
@ -427,18 +435,20 @@ Spectrum.prototype.onKeypress = function(e) {
|
||||||
} else if (e.key == "m") {
|
} else if (e.key == "m") {
|
||||||
this.toggleMaxHold();
|
this.toggleMaxHold();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
function Spectrum(id, options) {
|
function Spectrum(id, options) {
|
||||||
// Handle options
|
// Handle options
|
||||||
this.centerHz = (options && options.centerHz) ? options.centerHz : 1500;
|
this.centerHz = options && options.centerHz ? options.centerHz : 1500;
|
||||||
this.spanHz = (options && options.spanHz) ? options.spanHz : 0;
|
this.spanHz = options && options.spanHz ? options.spanHz : 0;
|
||||||
this.wf_size = (options && options.wf_size) ? options.wf_size : 0;
|
this.wf_size = options && options.wf_size ? options.wf_size : 0;
|
||||||
this.wf_rows = (options && options.wf_rows) ? options.wf_rows : 1024;
|
this.wf_rows = options && options.wf_rows ? options.wf_rows : 1024;
|
||||||
this.spectrumPercent = (options && options.spectrumPercent) ? options.spectrumPercent : 0;
|
this.spectrumPercent =
|
||||||
this.spectrumPercentStep = (options && options.spectrumPercentStep) ? options.spectrumPercentStep : 0;
|
options && options.spectrumPercent ? options.spectrumPercent : 0;
|
||||||
this.averaging = (options && options.averaging) ? options.averaging : 0;
|
this.spectrumPercentStep =
|
||||||
this.maxHold = (options && options.maxHold) ? options.maxHold : false;
|
options && options.spectrumPercentStep ? options.spectrumPercentStep : 0;
|
||||||
|
this.averaging = options && options.averaging ? options.averaging : 0;
|
||||||
|
this.maxHold = options && options.maxHold ? options.maxHold : false;
|
||||||
|
|
||||||
// Setup state
|
// Setup state
|
||||||
this.paused = false;
|
this.paused = false;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
html, body {
|
html,
|
||||||
|
body {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
|
|
||||||
# FreeDV-JATE [Just Another TNC Experiment]
|
# FreeDV-JATE [Just Another TNC Experiment]
|
||||||
|
|
||||||
## 002_HIGHSNR_PING_PONG
|
## 002_HIGHSNR_PING_PONG
|
||||||
|
|
||||||
### INSTALL TEST SUITE
|
### INSTALL TEST SUITE
|
||||||
|
|
||||||
#### Install prerequierements
|
#### Install prerequierements
|
||||||
|
|
||||||
```
|
```
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt upgrade
|
sudo apt upgrade
|
||||||
|
@ -15,41 +16,41 @@ pip3 install threading
|
||||||
|
|
||||||
Go into a directory of your choice
|
Go into a directory of your choice
|
||||||
Run the following commands --> They will download and compile the latest codec2 ( dr-packet ) files and LPCNet as well into the directory of your choice
|
Run the following commands --> They will download and compile the latest codec2 ( dr-packet ) files and LPCNet as well into the directory of your choice
|
||||||
|
|
||||||
```
|
```
|
||||||
wget https://raw.githubusercontent.com/DJ2LS/FreeDV-JATE/002_HIGHSNR_PING_PONG/install_test_suite.sh
|
wget https://raw.githubusercontent.com/DJ2LS/FreeDV-JATE/002_HIGHSNR_PING_PONG/install_test_suite.sh
|
||||||
chmod +x install_test_suite.sh
|
chmod +x install_test_suite.sh
|
||||||
./install_test_suite.sh
|
./install_test_suite.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### PARAMETERS
|
### PARAMETERS
|
||||||
| parameter | description | side
|
|
||||||
|--|--|--|
|
|
||||||
| - -txmode 12 | set the mode for FreeDV ( 10,11,12,14 ) | Terminal 1 & Terminal 2
|
|
||||||
| - -rxmode 14 | set the mode for FreeDV ( 10,11,12,14 ) | Terminal 1 & Terminal 2
|
|
||||||
| - -frames 1 | set the number of frames per burst | Terminal 1
|
|
||||||
| - -bursts 1 | set the number of bursts | Terminal 1
|
|
||||||
| - -audioinput 2 | set the audio device | Terminal 1 & Terminal 2
|
|
||||||
| - -audiooutput 1 | set the audio device | Terminal 1 & Terminal 2
|
|
||||||
| - -debug | if used, print additional debugging output | Terminal 1 & Terminal 2
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| parameter | description | side |
|
||||||
|
| ---------------- | ------------------------------------------ | ----------------------- |
|
||||||
|
| - -txmode 12 | set the mode for FreeDV ( 10,11,12,14 ) | Terminal 1 & Terminal 2 |
|
||||||
|
| - -rxmode 14 | set the mode for FreeDV ( 10,11,12,14 ) | Terminal 1 & Terminal 2 |
|
||||||
|
| - -frames 1 | set the number of frames per burst | Terminal 1 |
|
||||||
|
| - -bursts 1 | set the number of bursts | Terminal 1 |
|
||||||
|
| - -audioinput 2 | set the audio device | Terminal 1 & Terminal 2 |
|
||||||
|
| - -audiooutput 1 | set the audio device | Terminal 1 & Terminal 2 |
|
||||||
|
| - -debug | if used, print additional debugging output | Terminal 1 & Terminal 2 |
|
||||||
|
|
||||||
### AUDIO TESTS VIA VIRTUAL AUDIO DEVICE
|
### AUDIO TESTS VIA VIRTUAL AUDIO DEVICE
|
||||||
|
|
||||||
#### Create audio sinkhole and subdevices
|
#### Create audio sinkhole and subdevices
|
||||||
|
|
||||||
Note: This command needs to be run again after every reboot
|
Note: This command needs to be run again after every reboot
|
||||||
|
|
||||||
```
|
```
|
||||||
sudo modprobe snd-aloop index=1,2 enable=1,1 pcm_substreams=1,1 id=CHAT1,CHAT2
|
sudo modprobe snd-aloop index=1,2 enable=1,1 pcm_substreams=1,1 id=CHAT1,CHAT2
|
||||||
```
|
```
|
||||||
|
|
||||||
check if devices have been created
|
check if devices have been created
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
aplay -l
|
aplay -l
|
||||||
|
|
||||||
Output should be like this:
|
Output should be like this:
|
||||||
|
|
||||||
```
|
```
|
||||||
Karte 0: Intel [HDA Intel], Gerät 0: Generic Analog [Generic Analog]
|
Karte 0: Intel [HDA Intel], Gerät 0: Generic Analog [Generic Analog]
|
||||||
Sub-Geräte: 1/1
|
Sub-Geräte: 1/1
|
||||||
|
@ -71,10 +72,13 @@ Output should be like this:
|
||||||
### Run tests:
|
### Run tests:
|
||||||
|
|
||||||
#### Terminal 1: Ping
|
#### Terminal 1: Ping
|
||||||
|
|
||||||
```
|
```
|
||||||
python3 PING.py --txmode 12 --rxmode 14 --audioinput 2 --audiooutput 2 --frames 1 --bursts 2
|
python3 PING.py --txmode 12 --rxmode 14 --audioinput 2 --audiooutput 2 --frames 1 --bursts 2
|
||||||
```
|
```
|
||||||
|
|
||||||
Output
|
Output
|
||||||
|
|
||||||
```
|
```
|
||||||
BURSTS: 2 FRAMES: 1
|
BURSTS: 2 FRAMES: 1
|
||||||
-----------------------------------------------------------------
|
-----------------------------------------------------------------
|
||||||
|
@ -86,10 +90,13 @@ RX | PONG | BURST [2/2] FRAME [1/1]
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Terminal 2: Pong
|
#### Terminal 2: Pong
|
||||||
|
|
||||||
```
|
```
|
||||||
python3 PONG.py --txmode 14 --rxmode 12 --audioinput 2 --audiooutput 2
|
python3 PONG.py --txmode 14 --rxmode 12 --audioinput 2 --audiooutput 2
|
||||||
```
|
```
|
||||||
|
|
||||||
Output
|
Output
|
||||||
|
|
||||||
```
|
```
|
||||||
RX | BURST [1/2] FRAME [1/1] >>> SENDING PONG
|
RX | BURST [1/2] FRAME [1/1] >>> SENDING PONG
|
||||||
RX | BURST [2/2] FRAME [1/1] >>> SENDING PONG
|
RX | BURST [2/2] FRAME [1/1] >>> SENDING PONG
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
# Unit Test Menu
|
# Unit Test Menu
|
||||||
|
|
||||||
The following `CTest` tests cover some TNC functionality and the interface to codec2:
|
The following `CTest` tests cover some TNC functionality and the interface to codec2:
|
||||||
|
|
||||||
1. Name: `audio_buffer`
|
1. Name: `audio_buffer`
|
||||||
Tests the thread safety of the audio buffer routines.
|
Tests the thread safety of the audio buffer routines.
|
||||||
1. Name: `resampler`
|
1. Name: `resampler`
|
||||||
|
@ -32,6 +32,7 @@ The following `CTest` tests cover some TNC functionality and the interface to co
|
||||||
The following tests can not currently be run with GitHub's pipeline as they require the ALSA dummy device
|
The following tests can not currently be run with GitHub's pipeline as they require the ALSA dummy device
|
||||||
kernel module to be installed. They also do not perform reliably. These tests are slowly being
|
kernel module to be installed. They also do not perform reliably. These tests are slowly being
|
||||||
replaced with equivalent pipeline-compatible tests.
|
replaced with equivalent pipeline-compatible tests.
|
||||||
|
|
||||||
1. Name: `highsnr_virtual1_P_P_single_alsa`
|
1. Name: `highsnr_virtual1_P_P_single_alsa`
|
||||||
Tests a high signal-to-noise ratio audio path using a single codec directly over an ALSA dummy device.
|
Tests a high signal-to-noise ratio audio path using a single codec directly over an ALSA dummy device.
|
||||||
1. Name: `highsnr_virtual2_P_P_single`
|
1. Name: `highsnr_virtual2_P_P_single`
|
||||||
|
@ -46,7 +47,6 @@ replaced with equivalent pipeline-compatible tests.
|
||||||
1. Name: `highsnr_virtual5_P_P_multi_callback`
|
1. Name: `highsnr_virtual5_P_P_multi_callback`
|
||||||
1. Name: `highsnr_virtual5_P_P_multi_callback_outside`
|
1. Name: `highsnr_virtual5_P_P_multi_callback_outside`
|
||||||
|
|
||||||
|
|
||||||
# Instructions
|
# Instructions
|
||||||
|
|
||||||
1. Install:
|
1. Install:
|
||||||
|
@ -57,6 +57,7 @@ replaced with equivalent pipeline-compatible tests.
|
||||||
cmake -DCODEC2_BUILD_DIR=$HOME/codec2/build_linux ..
|
cmake -DCODEC2_BUILD_DIR=$HOME/codec2/build_linux ..
|
||||||
```
|
```
|
||||||
2. List available tests:
|
2. List available tests:
|
||||||
|
|
||||||
```
|
```
|
||||||
ctest -N
|
ctest -N
|
||||||
Test project /home/david/FreeDATA/build
|
Test project /home/david/FreeDATA/build
|
||||||
|
@ -65,6 +66,7 @@ replaced with equivalent pipeline-compatible tests.
|
||||||
|
|
||||||
Total Tests: 2
|
Total Tests: 2
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Run tests:
|
3. Run tests:
|
||||||
```
|
```
|
||||||
ctest --output-on-failure
|
ctest --output-on-failure
|
||||||
|
@ -78,7 +80,6 @@ replaced with equivalent pipeline-compatible tests.
|
||||||
ctest -V
|
ctest -V
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
# 001_HIGHSNR_STDIO_AUDIO TEST SUITE
|
# 001_HIGHSNR_STDIO_AUDIO TEST SUITE
|
||||||
|
|
||||||
1. Install
|
1. Install
|
||||||
|
@ -103,18 +104,23 @@ python3 util_tx.py --mode datac1 --delay 500 --frames 2 --bursts 1 | python3 uti
|
||||||
```
|
```
|
||||||
|
|
||||||
## Moderate signal-to-noise ratio (SNR)
|
## Moderate signal-to-noise ratio (SNR)
|
||||||
|
|
||||||
Tests need to be written that test a low SNR data path so that the TNC performance when packets are lost can be evaluated.
|
Tests need to be written that test a low SNR data path so that the TNC performance when packets are lost can be evaluated.
|
||||||
|
|
||||||
## AUDIO test via virtual audio devices
|
## AUDIO test via virtual audio devices
|
||||||
|
|
||||||
### Important:
|
### Important:
|
||||||
|
|
||||||
The virtual audio devices are great for testing, but they are also a little tricky to handle. So there's a high chance, the tests will fail, if you are running them via virtual audio devices. You should run the tests several times, while keeping this in mind. Most time the ctest is working even if it is failing.
|
The virtual audio devices are great for testing, but they are also a little tricky to handle. So there's a high chance, the tests will fail, if you are running them via virtual audio devices. You should run the tests several times, while keeping this in mind. Most time the ctest is working even if it is failing.
|
||||||
|
|
||||||
1. Create virtual audio devices. Note: This command needs to be run again after every reboot
|
1. Create virtual audio devices. Note: This command needs to be run again after every reboot
|
||||||
|
|
||||||
```
|
```
|
||||||
sudo modprobe snd-aloop index=1,2 enable=1,1 pcm_substreams=1,1 id=CHAT1,CHAT2
|
sudo modprobe snd-aloop index=1,2 enable=1,1 pcm_substreams=1,1 id=CHAT1,CHAT2
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Check if devices have been created
|
1. Check if devices have been created
|
||||||
|
|
||||||
```
|
```
|
||||||
aplay -l
|
aplay -l
|
||||||
|
|
||||||
|
@ -136,6 +142,7 @@ The virtual audio devices are great for testing, but they are also a little tric
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Determine the audio device number you would like to use:
|
1. Determine the audio device number you would like to use:
|
||||||
|
|
||||||
```
|
```
|
||||||
python3 util_rx.py --list
|
python3 util_rx.py --list
|
||||||
<snip>
|
<snip>
|
||||||
|
@ -148,9 +155,11 @@ The virtual audio devices are great for testing, but they are also a little tric
|
||||||
audiodev: 6 Loopback: PCM (hw:2,0)
|
audiodev: 6 Loopback: PCM (hw:2,0)
|
||||||
audiodev: 7 Loopback: PCM (hw:2,1)
|
audiodev: 7 Loopback: PCM (hw:2,1)
|
||||||
```
|
```
|
||||||
|
|
||||||
In this case we choose audiodev 4 for the RX and 5 for the Tx.
|
In this case we choose audiodev 4 for the RX and 5 for the Tx.
|
||||||
|
|
||||||
1. Start the Rx first, then Tx in separate consoles:
|
1. Start the Rx first, then Tx in separate consoles:
|
||||||
```
|
```
|
||||||
python3 util_rx.py --mode datac0 --frames 2 --bursts 1 --audiodev 4 --debug
|
python3 util_rx.py --mode datac0 --frames 2 --bursts 1 --audiodev 4 --debug
|
||||||
python3 util_tx.py --mode datac0 --frames 2 --bursts 1 --audiodev 5
|
python3 util_tx.py --mode datac0 --frames 2 --bursts 1 --audiodev 5
|
||||||
|
```
|
||||||
|
|
|
@ -4,20 +4,20 @@ tncport = 3000
|
||||||
|
|
||||||
[STATION]
|
[STATION]
|
||||||
#station settings
|
#station settings
|
||||||
mycall = DJ2LS-4
|
mycall = DJ2LS-9
|
||||||
mygrid = JN48cs
|
mygrid = JN12AA
|
||||||
ssid_list = [0,1,2,3,4,5]
|
ssid_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||||
|
|
||||||
[AUDIO]
|
[AUDIO]
|
||||||
#audio settings
|
#audio settings
|
||||||
rx = hw:2,0
|
rx = 0
|
||||||
tx = USB Audio CODEC
|
tx = 2
|
||||||
txaudiolevel = 120
|
txaudiolevel = 78
|
||||||
auto_tune = False
|
auto_tune = False
|
||||||
|
|
||||||
[RADIO]
|
[RADIO]
|
||||||
#radio settings
|
#radio settings
|
||||||
radiocontrol = rigctld
|
radiocontrol = disabled
|
||||||
rigctld_ip = 127.0.0.1
|
rigctld_ip = 127.0.0.1
|
||||||
rigctld_port = 4532
|
rigctld_port = 4532
|
||||||
|
|
||||||
|
@ -30,5 +30,6 @@ fmin = -50.0
|
||||||
fmax = 50.0
|
fmax = 50.0
|
||||||
qrv = True
|
qrv = True
|
||||||
rxbuffersize = 16
|
rxbuffersize = 16
|
||||||
explorer = False
|
explorer = True
|
||||||
stats = False
|
stats = False
|
||||||
|
|
||||||
|
|
|
@ -190,6 +190,8 @@ class DAEMON:
|
||||||
# hamlib_version = rig.hamlib_version
|
# hamlib_version = rig.hamlib_version
|
||||||
|
|
||||||
hamlib.set_ptt(True)
|
hamlib.set_ptt(True)
|
||||||
|
#Allow a little time for network based rig to register PTT is active
|
||||||
|
time.sleep(.250);
|
||||||
if hamlib.get_ptt():
|
if hamlib.get_ptt():
|
||||||
self.log.info("[DMN] Hamlib PTT", status="SUCCESS")
|
self.log.info("[DMN] Hamlib PTT", status="SUCCESS")
|
||||||
response = {"command": "test_hamlib", "result": "SUCCESS"}
|
response = {"command": "test_hamlib", "result": "SUCCESS"}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
# PyAudio
|
# PyAudio
|
||||||
|
|
||||||
## downloaded from
|
## downloaded from
|
||||||
|
|
||||||
https://www.lfd.uci.edu/~gohlke/pythonlibs/#pyaudio
|
https://www.lfd.uci.edu/~gohlke/pythonlibs/#pyaudio
|
||||||
|
|
|
@ -11,7 +11,7 @@ Not nice, suggestions are appreciated :-)
|
||||||
import subprocess
|
import subprocess
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
VERSION = "0.7.2-alpha.2"
|
VERSION = "0.7.3-alpha.2"
|
||||||
|
|
||||||
ENABLE_EXPLORER = False
|
ENABLE_EXPLORER = False
|
||||||
ENABLE_STATS = False
|
ENABLE_STATS = False
|
||||||
|
|
Loading…
Reference in a new issue