mirror of
https://github.com/DJ2LS/FreeDATA
synced 2024-05-14 08:04:33 +00:00
Merge pull request #358 from DJ2LS/qm-guiabout
adjusted settings menu and is writing notification
This commit is contained in:
commit
a6701da5b0
31 changed files with 11552 additions and 7727 deletions
13
.github/ISSUE_TEMPLATE/bug_report.md
vendored
13
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -1,10 +1,9 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve FreeDATA
|
||||
title: ''
|
||||
title: ""
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
|
@ -12,6 +11,7 @@ A clear and concise description of what the bug is.
|
|||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
|
@ -27,9 +27,10 @@ https://wiki.freedata.app/en/usage/logging
|
|||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. iOS]
|
||||
- Version [e.g. 22]
|
||||
- Platform [Raspberry Pi, Desktop]
|
||||
|
||||
- OS: [e.g. iOS]
|
||||
- Version [e.g. 22]
|
||||
- Platform [Raspberry Pi, Desktop]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
|
|
5
.github/ISSUE_TEMPLATE/feature_request.md
vendored
5
.github/ISSUE_TEMPLATE/feature_request.md
vendored
|
@ -1,10 +1,9 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
title: ""
|
||||
labels: feature request
|
||||
assignees: ''
|
||||
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
**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
|
40
README.md
40
README.md
|
@ -1,4 +1,5 @@
|
|||
# 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.
|
||||
|
||||
[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)
|
||||
[![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.
|
||||
|
||||
### existing/planned TNC features
|
||||
|
||||
- [x] network based
|
||||
- [x] raw data transfer
|
||||
- [x] fft output
|
||||
|
@ -24,32 +25,37 @@ Please keep in mind, this project is still under development with many issues wh
|
|||
- [x] channel measurement
|
||||
- [ ] hybrid ARQ
|
||||
- [ ] tbc...
|
||||
|
||||
### existing/planned Chat features
|
||||
- [x] chat messages
|
||||
- [x] file transfer
|
||||
- [x] file transfer with chat message
|
||||
- [x] database for not loosing messages
|
||||
- [x] smileys
|
||||
- [ ] database network sync
|
||||
- [ ] voice messages
|
||||
- [ ] image compression
|
||||
- [ ] status messages
|
||||
- [ ] avatars
|
||||
- [ ] tbc...
|
||||
|
||||
- [x] chat messages
|
||||
- [x] file transfer
|
||||
- [x] file transfer with chat message
|
||||
- [x] database for not loosing messages
|
||||
- [x] smileys
|
||||
- [ ] database network sync
|
||||
- [ ] voice messages
|
||||
- [ ] image compression
|
||||
- [ ] status messages
|
||||
- [ ] avatars
|
||||
- [ ] tbc...
|
||||
|
||||
## Data Preview
|
||||
|
||||
![preview](https://github.com/DJ2LS/FreeDATA/blob/main/documentation/data_preview.gif?raw=true "Preview")
|
||||
|
||||
## Chat Preview
|
||||
|
||||
![preview](https://github.com/DJ2LS/FreeDATA/blob/main/documentation/chat_preview_fast.gif?raw=true "Preview")
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
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
|
||||
|
||||
## Credits
|
||||
* David Rowe and the FreeDV team for developing the modem and libraries -
|
||||
FreeDV Codec 2 : https://github.com/drowe67/codec2
|
||||
* xssfox, her repository helped a lot in an early stage of development -
|
||||
xssfox : https://github.com/xssfox/freedv-tnc
|
||||
|
||||
- David Rowe and the FreeDV team for developing the modem and libraries -
|
||||
FreeDV Codec 2 : https://github.com/drowe67/codec2
|
||||
- xssfox, her repository helped a lot in an early stage of development -
|
||||
xssfox : https://github.com/xssfox/freedv-tnc
|
||||
|
|
|
@ -1,21 +1,25 @@
|
|||
# FreeDATA - DAEMON network documentation
|
||||
|
||||
# FreeDATA - DAEMON network documentation
|
||||
|
||||
## GET DAEMON STATE
|
||||
|
||||
#### Description:
|
||||
|
||||
Get the current daemon state
|
||||
|
||||
#### Parameters
|
||||
- Type: GET
|
||||
|
||||
- Type: GET
|
||||
- Command: DAEMON_STATE
|
||||
- Parameter: --- (str)
|
||||
|
||||
#### Example
|
||||
#### Example
|
||||
|
||||
```
|
||||
{"type" : "GET", "command" : "DAEMON_STATE"}
|
||||
```
|
||||
|
||||
#### Returns
|
||||
|
||||
```
|
||||
{
|
||||
"COMMAND": "DAEMON_STATE",
|
||||
|
@ -24,67 +28,74 @@ Get the current daemon state
|
|||
"HAMLIB_VERSION": str(hamlib_version),
|
||||
"INPUT_DEVICES": [],
|
||||
"OUTPUT_DEVICES": [],
|
||||
"SERIAL_DEVICES": [],
|
||||
"CPU": "",
|
||||
"RAM": "",
|
||||
"SERIAL_DEVICES": [],
|
||||
"CPU": "",
|
||||
"RAM": "",
|
||||
"VERSION": "0.1-prototype"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## SET CALLSIGN
|
||||
|
||||
#### Description:
|
||||
|
||||
Save your callsign to the daemon
|
||||
|
||||
#### Parameters
|
||||
- Type: SET
|
||||
|
||||
- Type: SET
|
||||
- Command: MYCALLSIGN
|
||||
- Parameter: callsign (str)
|
||||
- timestamp: unix timestamp (str)
|
||||
|
||||
#### Example
|
||||
#### Example
|
||||
|
||||
```
|
||||
{"type" : "SET", "command": "MYCALLSIGN" , "parameter": "<callsign>", "timestamp" : "123456789"}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## SET GRIDSQUARE
|
||||
|
||||
#### Description:
|
||||
|
||||
Save your gridsquare/maidenhead-locator to the daemon
|
||||
|
||||
#### Parameters
|
||||
- Type: SET
|
||||
|
||||
- Type: SET
|
||||
- Command: MYGRID
|
||||
- Parameter: gridsquare (str)
|
||||
- timestamp: unix timestamp (str)
|
||||
|
||||
#### Example
|
||||
#### Example
|
||||
|
||||
```
|
||||
{"type" : "SET", "command": "MYGRID" , "parameter": "<gridsquare>", "timestamp" : "123456789"}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## TEST HAMLIB
|
||||
|
||||
#### Description:
|
||||
|
||||
Test your hamlib settings
|
||||
|
||||
#### Parameters
|
||||
- Type: GET
|
||||
|
||||
- Type: GET
|
||||
- Command: TEST_HAMLIB
|
||||
- Parameter: obj
|
||||
- devicename
|
||||
- deviceport
|
||||
- pttprotocol
|
||||
- pttport
|
||||
- serialspeed
|
||||
- data_bits
|
||||
- stop_bits
|
||||
- handshake
|
||||
- devicename
|
||||
- deviceport
|
||||
- pttprotocol
|
||||
- pttport
|
||||
- serialspeed
|
||||
- data_bits
|
||||
- stop_bits
|
||||
- handshake
|
||||
- timestamp: unix timestamp (str)
|
||||
|
||||
#### Example
|
||||
#### Example
|
||||
|
||||
```
|
||||
{
|
||||
"type": "GET",
|
||||
|
@ -102,29 +113,32 @@ Test your hamlib settings
|
|||
}
|
||||
```
|
||||
|
||||
|
||||
## START TNC
|
||||
|
||||
#### Description:
|
||||
|
||||
Start the tnc process
|
||||
|
||||
#### Parameters
|
||||
- Type: GET
|
||||
|
||||
- Type: GET
|
||||
- Command: TEST_HAMLIB
|
||||
- Parameter: obj
|
||||
- mycall
|
||||
- mygrid
|
||||
- rx_audio
|
||||
- tx_audio
|
||||
- devicename
|
||||
- deviceport
|
||||
- pttprotocol
|
||||
- pttport
|
||||
- serialspeed
|
||||
- data_bits
|
||||
- stop_bits
|
||||
- handshake
|
||||
- mycall
|
||||
- mygrid
|
||||
- rx_audio
|
||||
- tx_audio
|
||||
- devicename
|
||||
- deviceport
|
||||
- pttprotocol
|
||||
- pttport
|
||||
- serialspeed
|
||||
- data_bits
|
||||
- stop_bits
|
||||
- handshake
|
||||
|
||||
#### Example
|
||||
|
||||
#### Example
|
||||
```
|
||||
{
|
||||
type: 'SET',
|
||||
|
@ -148,23 +162,19 @@ Start the tnc process
|
|||
```
|
||||
|
||||
## STOP TNC
|
||||
|
||||
#### Description:
|
||||
|
||||
Stop the tnc process
|
||||
|
||||
#### Parameters
|
||||
- Type: SET
|
||||
|
||||
- Type: SET
|
||||
- Command: STOPTNC
|
||||
- Parameter: ---
|
||||
|
||||
#### Example
|
||||
#### Example
|
||||
|
||||
```
|
||||
{"type" : "SET", "command": "STOPTNC" , "parameter": "---" }
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
522
gui/daemon.js
522
gui/daemon.js
|
@ -1,74 +1,72 @@
|
|||
var net = require('net');
|
||||
const path = require('path')
|
||||
const {
|
||||
ipcRenderer
|
||||
} = require('electron')
|
||||
const log = require('electron-log');
|
||||
const daemonLog = log.scope('daemon');
|
||||
|
||||
|
||||
var net = require("net");
|
||||
const path = require("path");
|
||||
const { ipcRenderer } = require("electron");
|
||||
const log = require("electron-log");
|
||||
const daemonLog = log.scope("daemon");
|
||||
|
||||
// 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 configPath = path.join(configFolder, 'config.json')
|
||||
var configPath = path.join(configFolder, "config.json");
|
||||
const config = require(configPath);
|
||||
|
||||
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
|
||||
var daemonShowConnectStateError = 1
|
||||
var daemonShowConnectStateError = 1;
|
||||
|
||||
// global for storing ip information
|
||||
var daemon_port = config.daemon_port;
|
||||
var daemon_host = config.daemon_host;
|
||||
|
||||
setTimeout(connectDAEMON, 500)
|
||||
setTimeout(connectDAEMON, 500);
|
||||
|
||||
function connectDAEMON() {
|
||||
if (daemonShowConnectStateError == 1) {
|
||||
daemonLog.info('connecting to daemon');
|
||||
}
|
||||
if (daemonShowConnectStateError == 1) {
|
||||
daemonLog.info("connecting to daemon");
|
||||
}
|
||||
|
||||
//clear message buffer after reconnecting or initial connection
|
||||
socketchunk = '';
|
||||
|
||||
if (config.tnclocation == 'localhost') {
|
||||
daemon.connect(3001, '127.0.0.1')
|
||||
} else {
|
||||
daemon.connect(daemon_port, daemon_host)
|
||||
//clear message buffer after reconnecting or initial connection
|
||||
socketchunk = "";
|
||||
|
||||
}
|
||||
if (config.tnclocation == "localhost") {
|
||||
daemon.connect(3001, "127.0.0.1");
|
||||
} else {
|
||||
daemon.connect(daemon_port, daemon_host);
|
||||
}
|
||||
|
||||
//client.setTimeout(5000);
|
||||
//client.setTimeout(5000);
|
||||
}
|
||||
|
||||
daemon.on('connect', function(err) {
|
||||
daemonLog.info('daemon connection established');
|
||||
let Data = {
|
||||
daemon_connection: daemon.readyState,
|
||||
};
|
||||
ipcRenderer.send('request-update-daemon-connection', Data);
|
||||
daemon.on("connect", function (err) {
|
||||
daemonLog.info("daemon connection established");
|
||||
let Data = {
|
||||
daemon_connection: daemon.readyState,
|
||||
};
|
||||
ipcRenderer.send("request-update-daemon-connection", Data);
|
||||
|
||||
daemonShowConnectStateError = 1
|
||||
})
|
||||
daemonShowConnectStateError = 1;
|
||||
});
|
||||
|
||||
daemon.on('error', function(err) {
|
||||
if (daemonShowConnectStateError == 1) {
|
||||
daemonLog.error('daemon connection error');
|
||||
daemonLog.info('Make sure the daemon is started.');
|
||||
daemonLog.info('Run "python daemon.py" in the tnc directory.');
|
||||
daemonLog.debug(err)
|
||||
|
||||
daemonShowConnectStateError = 0
|
||||
}
|
||||
setTimeout(connectDAEMON, 500)
|
||||
daemon.destroy();
|
||||
let Data = {
|
||||
daemon_connection: daemon.readyState,
|
||||
};
|
||||
ipcRenderer.send('request-update-daemon-connection', Data);
|
||||
daemon.on("error", function (err) {
|
||||
if (daemonShowConnectStateError == 1) {
|
||||
daemonLog.error("daemon connection error");
|
||||
daemonLog.info("Make sure the daemon is started.");
|
||||
daemonLog.info('Run "python daemon.py" in the tnc directory.');
|
||||
|
||||
daemonShowConnectStateError = 0;
|
||||
}
|
||||
setTimeout(connectDAEMON, 500);
|
||||
daemon.destroy();
|
||||
let Data = {
|
||||
daemon_connection: daemon.readyState,
|
||||
};
|
||||
ipcRenderer.send("request-update-daemon-connection", Data);
|
||||
});
|
||||
|
||||
/*
|
||||
|
@ -82,242 +80,264 @@ client.on('close', function(data) {
|
|||
});
|
||||
*/
|
||||
|
||||
daemon.on('end', function(data) {
|
||||
|
||||
daemonLog.warn('daemon connection ended');
|
||||
daemon.destroy();
|
||||
setTimeout(connectDAEMON, 500)
|
||||
let Data = {
|
||||
daemon_connection: daemon.readyState,
|
||||
};
|
||||
ipcRenderer.send('request-update-daemon-connection', Data);
|
||||
daemon.on("end", function (data) {
|
||||
daemonLog.warn("daemon connection ended");
|
||||
daemon.destroy();
|
||||
setTimeout(connectDAEMON, 500);
|
||||
let Data = {
|
||||
daemon_connection: daemon.readyState,
|
||||
};
|
||||
ipcRenderer.send("request-update-daemon-connection", Data);
|
||||
});
|
||||
|
||||
//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
|
||||
// if socket opened, we are able to run commands
|
||||
if (daemon.readyState == "open") {
|
||||
//uiMain.setDAEMONconnection('open')
|
||||
daemon.write(command + "\n");
|
||||
}
|
||||
|
||||
// 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 (daemon.readyState == 'open') {
|
||||
//uiMain.setDAEMONconnection('open')
|
||||
daemon.write(command + '\n');
|
||||
}
|
||||
if (daemon.readyState == "closed") {
|
||||
//uiMain.setDAEMONconnection('closed')
|
||||
}
|
||||
|
||||
if (daemon.readyState == 'closed') {
|
||||
//uiMain.setDAEMONconnection('closed')
|
||||
}
|
||||
if (daemon.readyState == "opening") {
|
||||
//uiMain.setDAEMONconnection('opening')
|
||||
}
|
||||
|
||||
if (daemon.readyState == 'opening') {
|
||||
//uiMain.setDAEMONconnection('opening')
|
||||
}
|
||||
|
||||
let Data = {
|
||||
daemon_connection: daemon.readyState,
|
||||
};
|
||||
ipcRenderer.send('request-update-daemon-connection', Data);
|
||||
}
|
||||
let Data = {
|
||||
daemon_connection: daemon.readyState,
|
||||
};
|
||||
ipcRenderer.send("request-update-daemon-connection", Data);
|
||||
};
|
||||
|
||||
// "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:
|
||||
stackoverflow.com questions 9070700 nodejs-net-createserver-large-amount-of-data-coming-in
|
||||
*/
|
||||
|
||||
socketdata = socketdata.toString("utf8"); // convert data to string
|
||||
socketchunk += socketdata; // append data to buffer so we can stick long data together
|
||||
|
||||
socketdata = socketdata.toString('utf8'); // convert data to string
|
||||
socketchunk += socketdata// append data to buffer so we can stick long data together
|
||||
// check if we received begin and end of json data
|
||||
if (socketchunk.startsWith('{"') && socketchunk.endsWith('"}\n')) {
|
||||
var data = "";
|
||||
|
||||
// split data into chunks if we received multiple commands
|
||||
socketchunk = socketchunk.split("\n");
|
||||
data = JSON.parse(socketchunk[0]);
|
||||
|
||||
// check if we received begin and end of json data
|
||||
if (socketchunk.startsWith('{"') && socketchunk.endsWith('"}\n')) {
|
||||
|
||||
var data = ''
|
||||
|
||||
// split data into chunks if we received multiple commands
|
||||
socketchunk = socketchunk.split("\n");
|
||||
data = JSON.parse(socketchunk[0])
|
||||
|
||||
|
||||
// search for empty entries in socketchunk and remove them
|
||||
for (i = 0; i < socketchunk.length; i++) {
|
||||
if (socketchunk[i] === ''){
|
||||
socketchunk.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//iterate through socketchunks array to execute multiple commands in row
|
||||
for (i = 0; i < socketchunk.length; i++) {
|
||||
|
||||
//check if data is not empty
|
||||
if(socketchunk[i].length > 0){
|
||||
|
||||
//try to parse JSON
|
||||
try {
|
||||
|
||||
data = JSON.parse(socketchunk[i])
|
||||
|
||||
} catch (e) {
|
||||
console.log(e); // "SyntaxError
|
||||
daemonLog.error(e);
|
||||
daemonLog.debug(socketchunk[i])
|
||||
socketchunk = ''
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (data['command'] == 'daemon_state') {
|
||||
let Data = {
|
||||
input_devices: data['input_devices'],
|
||||
output_devices: data['output_devices'],
|
||||
python_version: data['python_version'],
|
||||
hamlib_version: data['hamlib_version'],
|
||||
serial_devices: data['serial_devices'],
|
||||
tnc_running_state: data['daemon_state'][0]['status'],
|
||||
ram_usage: data['ram'],
|
||||
cpu_usage: data['cpu'],
|
||||
version: data['version'],
|
||||
};
|
||||
ipcRenderer.send('request-update-daemon-state', Data);
|
||||
}
|
||||
|
||||
if (data['command'] == 'test_hamlib') {
|
||||
let Data = {
|
||||
hamlib_result: data['result'],
|
||||
|
||||
};
|
||||
ipcRenderer.send('request-update-hamlib-test', Data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
//finally delete message buffer
|
||||
socketchunk = '';
|
||||
|
||||
// search for empty entries in socketchunk and remove them
|
||||
for (i = 0; i < socketchunk.length; i++) {
|
||||
if (socketchunk[i] === "") {
|
||||
socketchunk.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
//iterate through socketchunks array to execute multiple commands in row
|
||||
for (i = 0; i < socketchunk.length; i++) {
|
||||
//check if data is not empty
|
||||
if (socketchunk[i].length > 0) {
|
||||
//try to parse JSON
|
||||
try {
|
||||
data = JSON.parse(socketchunk[i]);
|
||||
} catch (e) {
|
||||
console.log(e); // "SyntaxError
|
||||
daemonLog.error(e);
|
||||
daemonLog.debug(socketchunk[i]);
|
||||
socketchunk = "";
|
||||
}
|
||||
}
|
||||
|
||||
if (data["command"] == "daemon_state") {
|
||||
let Data = {
|
||||
input_devices: data["input_devices"],
|
||||
output_devices: data["output_devices"],
|
||||
python_version: data["python_version"],
|
||||
hamlib_version: data["hamlib_version"],
|
||||
serial_devices: data["serial_devices"],
|
||||
tnc_running_state: data["daemon_state"][0]["status"],
|
||||
ram_usage: data["ram"],
|
||||
cpu_usage: data["cpu"],
|
||||
version: data["version"],
|
||||
};
|
||||
ipcRenderer.send("request-update-daemon-state", Data);
|
||||
}
|
||||
|
||||
if (data["command"] == "test_hamlib") {
|
||||
let Data = {
|
||||
hamlib_result: data["result"],
|
||||
};
|
||||
ipcRenderer.send("request-update-hamlib-test", Data);
|
||||
}
|
||||
}
|
||||
|
||||
//finally delete message buffer
|
||||
socketchunk = "";
|
||||
}
|
||||
});
|
||||
|
||||
function hexToBytes(hex) {
|
||||
for (var bytes = [], c = 0; c < hex.length; c += 2)
|
||||
bytes.push(parseInt(hex.substr(c, 2), 16));
|
||||
return bytes;
|
||||
for (var bytes = [], c = 0; c < hex.length; c += 2)
|
||||
bytes.push(parseInt(hex.substr(c, 2), 16));
|
||||
return bytes;
|
||||
}
|
||||
|
||||
exports.getDaemonState = function() {
|
||||
//function getDaemonState(){
|
||||
command = '{"type" : "get", "command" : "daemon_state"}'
|
||||
writeDaemonCommand(command)
|
||||
}
|
||||
exports.getDaemonState = function () {
|
||||
//function getDaemonState(){
|
||||
command = '{"type" : "get", "command" : "daemon_state"}';
|
||||
writeDaemonCommand(command);
|
||||
};
|
||||
|
||||
// START TNC
|
||||
// ` `== 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) {
|
||||
var json_command = JSON.stringify({
|
||||
type: 'set',
|
||||
command: 'start_tnc',
|
||||
parameter: [{
|
||||
mycall: mycall,
|
||||
mygrid: mygrid,
|
||||
rx_audio: rx_audio,
|
||||
tx_audio: tx_audio,
|
||||
radiocontrol: radiocontrol,
|
||||
devicename: devicename,
|
||||
deviceport: deviceport,
|
||||
pttprotocol: pttprotocol,
|
||||
pttport: pttport,
|
||||
serialspeed: serialspeed,
|
||||
data_bits: data_bits,
|
||||
stop_bits: stop_bits,
|
||||
handshake: handshake,
|
||||
rigctld_port: rigctld_port,
|
||||
rigctld_ip: rigctld_ip,
|
||||
enable_scatter: enable_scatter,
|
||||
enable_fft: enable_fft,
|
||||
enable_fsk: enable_fsk,
|
||||
low_bandwidth_mode : low_bandwidth_mode,
|
||||
tuning_range_fmin : tuning_range_fmin,
|
||||
tuning_range_fmax : tuning_range_fmax,
|
||||
tx_audio_level : tx_audio_level,
|
||||
respond_to_cq : respond_to_cq,
|
||||
rx_buffer_size : rx_buffer_size,
|
||||
enable_explorer : enable_explorer,
|
||||
enable_stats: explorer_stats,
|
||||
enable_auto_tune: 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({
|
||||
type: "set",
|
||||
command: "start_tnc",
|
||||
parameter: [
|
||||
{
|
||||
mycall: mycall,
|
||||
mygrid: mygrid,
|
||||
rx_audio: rx_audio,
|
||||
tx_audio: tx_audio,
|
||||
radiocontrol: radiocontrol,
|
||||
devicename: devicename,
|
||||
deviceport: deviceport,
|
||||
pttprotocol: pttprotocol,
|
||||
pttport: pttport,
|
||||
serialspeed: serialspeed,
|
||||
data_bits: data_bits,
|
||||
stop_bits: stop_bits,
|
||||
handshake: handshake,
|
||||
rigctld_port: rigctld_port,
|
||||
rigctld_ip: rigctld_ip,
|
||||
enable_scatter: enable_scatter,
|
||||
enable_fft: enable_fft,
|
||||
enable_fsk: enable_fsk,
|
||||
low_bandwidth_mode: low_bandwidth_mode,
|
||||
tuning_range_fmin: tuning_range_fmin,
|
||||
tuning_range_fmax: tuning_range_fmax,
|
||||
tx_audio_level: tx_audio_level,
|
||||
respond_to_cq: respond_to_cq,
|
||||
rx_buffer_size: rx_buffer_size,
|
||||
enable_explorer: enable_explorer,
|
||||
enable_stats: explorer_stats,
|
||||
enable_auto_tune: auto_tune,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
daemonLog.debug(json_command);
|
||||
writeDaemonCommand(json_command)
|
||||
|
||||
}
|
||||
daemonLog.debug(json_command);
|
||||
writeDaemonCommand(json_command);
|
||||
};
|
||||
|
||||
// STOP TNC
|
||||
exports.stopTNC = function() {
|
||||
command = '{"type" : "set", "command": "stop_tnc" , "parameter": "---" }'
|
||||
writeDaemonCommand(command)
|
||||
}
|
||||
exports.stopTNC = function () {
|
||||
command = '{"type" : "set", "command": "stop_tnc" , "parameter": "---" }';
|
||||
writeDaemonCommand(command);
|
||||
};
|
||||
|
||||
// TEST HAMLIB
|
||||
exports.testHamlib = function(radiocontrol, devicename, deviceport, serialspeed, pttprotocol, pttport, data_bits, stop_bits, handshake, rigctld_ip, rigctld_port) {
|
||||
|
||||
var json_command = JSON.stringify({
|
||||
type: 'get',
|
||||
command: 'test_hamlib',
|
||||
parameter: [{
|
||||
radiocontrol: radiocontrol,
|
||||
devicename: devicename,
|
||||
deviceport: deviceport,
|
||||
pttprotocol: pttprotocol,
|
||||
pttport: pttport,
|
||||
serialspeed: serialspeed,
|
||||
data_bits: data_bits,
|
||||
stop_bits: stop_bits,
|
||||
handshake: handshake,
|
||||
rigctld_port: rigctld_port,
|
||||
rigctld_ip: rigctld_ip
|
||||
}]
|
||||
})
|
||||
daemonLog.debug(json_command);
|
||||
writeDaemonCommand(json_command)
|
||||
}
|
||||
|
||||
|
||||
exports.testHamlib = function (
|
||||
radiocontrol,
|
||||
devicename,
|
||||
deviceport,
|
||||
serialspeed,
|
||||
pttprotocol,
|
||||
pttport,
|
||||
data_bits,
|
||||
stop_bits,
|
||||
handshake,
|
||||
rigctld_ip,
|
||||
rigctld_port
|
||||
) {
|
||||
var json_command = JSON.stringify({
|
||||
type: "get",
|
||||
command: "test_hamlib",
|
||||
parameter: [
|
||||
{
|
||||
radiocontrol: radiocontrol,
|
||||
devicename: devicename,
|
||||
deviceport: deviceport,
|
||||
pttprotocol: pttprotocol,
|
||||
pttport: pttport,
|
||||
serialspeed: serialspeed,
|
||||
data_bits: data_bits,
|
||||
stop_bits: stop_bits,
|
||||
handshake: handshake,
|
||||
rigctld_port: rigctld_port,
|
||||
rigctld_ip: rigctld_ip,
|
||||
},
|
||||
],
|
||||
});
|
||||
daemonLog.debug(json_command);
|
||||
writeDaemonCommand(json_command);
|
||||
};
|
||||
|
||||
//Save myCall
|
||||
exports.saveMyCall = function(callsign) {
|
||||
command = '{"type" : "set", "command": "mycallsign" , "parameter": "' + callsign + '"}'
|
||||
writeDaemonCommand(command)
|
||||
}
|
||||
exports.saveMyCall = function (callsign) {
|
||||
command =
|
||||
'{"type" : "set", "command": "mycallsign" , "parameter": "' +
|
||||
callsign +
|
||||
'"}';
|
||||
writeDaemonCommand(command);
|
||||
};
|
||||
|
||||
// Save myGrid
|
||||
exports.saveMyGrid = function(grid) {
|
||||
command = '{"type" : "set", "command": "mygrid" , "parameter": "' + grid + '"}'
|
||||
writeDaemonCommand(command)
|
||||
}
|
||||
exports.saveMyGrid = function (grid) {
|
||||
command =
|
||||
'{"type" : "set", "command": "mygrid" , "parameter": "' + grid + '"}';
|
||||
writeDaemonCommand(command);
|
||||
};
|
||||
|
||||
ipcRenderer.on('action-update-daemon-ip', (event, arg) => {
|
||||
daemon.destroy();
|
||||
let Data = {
|
||||
busy_state: "-",
|
||||
arq_state: "-",
|
||||
//channel_state: "-",
|
||||
frequency: "-",
|
||||
mode: "-",
|
||||
bandwidth: "-",
|
||||
dbfs_level: 0
|
||||
};
|
||||
ipcRenderer.send('request-update-tnc-state', Data);
|
||||
daemon_port = arg.port;
|
||||
daemon_host = arg.adress;
|
||||
connectDAEMON();
|
||||
ipcRenderer.on("action-update-daemon-ip", (event, arg) => {
|
||||
daemon.destroy();
|
||||
let Data = {
|
||||
busy_state: "-",
|
||||
arq_state: "-",
|
||||
//channel_state: "-",
|
||||
frequency: "-",
|
||||
mode: "-",
|
||||
bandwidth: "-",
|
||||
dbfs_level: 0,
|
||||
};
|
||||
ipcRenderer.send("request-update-tnc-state", Data);
|
||||
daemon_port = arg.port;
|
||||
daemon_host = arg.adress;
|
||||
connectDAEMON();
|
||||
});
|
||||
|
|
1148
gui/main.js
1148
gui/main.js
File diff suppressed because it is too large
Load diff
|
@ -35,28 +35,28 @@
|
|||
"bootstrap": "^5.2.3",
|
||||
"bootstrap-icons": "^1.10.3",
|
||||
"bootswatch": "^5.2.3",
|
||||
"chart.js": "^4.2.0",
|
||||
"chart.js": "^4.2.1",
|
||||
"chartjs-plugin-annotation": "^2.1.2",
|
||||
"electron-log": "^4.4.8",
|
||||
"electron-updater": "^5.3.0",
|
||||
"emoji-picker-element": "^1.15.0",
|
||||
"emoji-picker-element": "^1.15.1",
|
||||
"emoji-picker-element-data": "^1.3.0",
|
||||
"express-pouchdb": "^4.2.0",
|
||||
"mime": "^3.0.0",
|
||||
"pouchdb": "^8.0.0",
|
||||
"pouchdb-browser": "^8.0.0",
|
||||
"pouchdb": "^8.0.1",
|
||||
"pouchdb-browser": "^8.0.1",
|
||||
"pouchdb-express-router": "^0.0.11",
|
||||
"pouchdb-find": "^8.0.0",
|
||||
"pouchdb-replication": "^8.0.0",
|
||||
"pouchdb-find": "^8.0.1",
|
||||
"pouchdb-replication": "^8.0.1",
|
||||
"qth-locator": "^2.1.0",
|
||||
"utf8": "^3.0.0",
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^22.0.2",
|
||||
"electron": "^23.0.0",
|
||||
"electron-builder": "^23.6.0",
|
||||
"@electron/notarize": "^1.2.3",
|
||||
"electron-builder-notarize": "^1.5.0"
|
||||
"electron-builder-notarize": "^1.5.1"
|
||||
},
|
||||
"build": {
|
||||
"productName": "FreeDATA",
|
||||
|
|
1642
gui/preload-chat.js
1642
gui/preload-chat.js
File diff suppressed because it is too large
Load diff
|
@ -1,192 +1,186 @@
|
|||
const path = require('path');
|
||||
const {ipcRenderer} = require('electron');
|
||||
const path = require("path");
|
||||
const { ipcRenderer } = require("electron");
|
||||
|
||||
// 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 configPath = path.join(configFolder, 'config.json')
|
||||
var configPath = path.join(configFolder, "config.json");
|
||||
const config = require(configPath);
|
||||
|
||||
|
||||
// WINDOW LISTENER
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
document.getElementById('enable_filter_info').addEventListener('click', () => {
|
||||
if (document.getElementById('enable_filter_info').checked){
|
||||
display_class("table-info", true)
|
||||
} else {
|
||||
display_class("table-info", false)
|
||||
}
|
||||
})
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
document
|
||||
.getElementById("enable_filter_info")
|
||||
.addEventListener("click", () => {
|
||||
if (document.getElementById("enable_filter_info").checked) {
|
||||
display_class("table-info", true);
|
||||
} else {
|
||||
display_class("table-info", false);
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('enable_filter_debug').addEventListener('click', () => {
|
||||
if (document.getElementById('enable_filter_debug').checked){
|
||||
display_class("table-debug", true)
|
||||
} else {
|
||||
display_class("table-debug", false)
|
||||
}
|
||||
})
|
||||
document
|
||||
.getElementById("enable_filter_debug")
|
||||
.addEventListener("click", () => {
|
||||
if (document.getElementById("enable_filter_debug").checked) {
|
||||
display_class("table-debug", true);
|
||||
} else {
|
||||
display_class("table-debug", false);
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('enable_filter_warning').addEventListener('click', () => {
|
||||
if (document.getElementById('enable_filter_warning').checked){
|
||||
display_class("table-warning", true)
|
||||
} else {
|
||||
display_class("table-warning", false)
|
||||
}
|
||||
})
|
||||
document
|
||||
.getElementById("enable_filter_warning")
|
||||
.addEventListener("click", () => {
|
||||
if (document.getElementById("enable_filter_warning").checked) {
|
||||
display_class("table-warning", true);
|
||||
} else {
|
||||
display_class("table-warning", false);
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('enable_filter_error').addEventListener('click', () => {
|
||||
if (document.getElementById('enable_filter_error').checked){
|
||||
display_class("table-danger", true)
|
||||
} else {
|
||||
display_class("table-danger", false)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
function display_class(class_name, state){
|
||||
var collection = document.getElementsByClassName(class_name);
|
||||
console.log(collection)
|
||||
for (let i = 0; i < collection.length; i++) {
|
||||
if (state == true){
|
||||
collection[i].style.display = "table-row";
|
||||
} else {
|
||||
collection[i].style.display = "None";
|
||||
}
|
||||
document
|
||||
.getElementById("enable_filter_error")
|
||||
.addEventListener("click", () => {
|
||||
if (document.getElementById("enable_filter_error").checked) {
|
||||
display_class("table-danger", true);
|
||||
} else {
|
||||
display_class("table-danger", false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function display_class(class_name, state) {
|
||||
var collection = document.getElementsByClassName(class_name);
|
||||
console.log(collection);
|
||||
for (let i = 0; i < collection.length; i++) {
|
||||
if (state == true) {
|
||||
collection[i].style.display = "table-row";
|
||||
} else {
|
||||
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
|
||||
// https://stackoverflow.com/a/29497680
|
||||
entry = entry.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,'')
|
||||
// remove ANSI characters from string, caused by color logging
|
||||
// https://stackoverflow.com/a/29497680
|
||||
entry = entry.replace(
|
||||
/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,
|
||||
""
|
||||
);
|
||||
|
||||
var tbl = document.getElementById("log");
|
||||
var row = document.createElement("tr");
|
||||
|
||||
var tbl = document.getElementById("log");
|
||||
var row = document.createElement("tr");
|
||||
var timestamp = document.createElement("td");
|
||||
var timestampText = document.createElement("span");
|
||||
|
||||
var timestamp = document.createElement("td");
|
||||
var timestampText = document.createElement('span');
|
||||
//datetime = new Date();
|
||||
//timestampText.innerText = datetime.toISOString();
|
||||
timestampText.innerText = entry.slice(0, 19);
|
||||
timestamp.appendChild(timestampText);
|
||||
|
||||
//datetime = new Date();
|
||||
//timestampText.innerText = datetime.toISOString();
|
||||
timestampText.innerText = entry.slice(0, 19);
|
||||
timestamp.appendChild(timestampText);
|
||||
var type = document.createElement("td");
|
||||
var typeText = document.createElement("span");
|
||||
// typeText.innerText = entry.slice(10, 30).match(/[\[](.*)[^\]]/g);
|
||||
console.log(entry.match(/\[[^\]]+\]/g));
|
||||
|
||||
var type = document.createElement("td");
|
||||
var typeText = document.createElement('span');
|
||||
// typeText.innerText = entry.slice(10, 30).match(/[\[](.*)[^\]]/g);
|
||||
console.log(entry.match(/\[[^\]]+\]/g))
|
||||
try {
|
||||
typeText.innerText = entry.match(/\[[^\]]+\]/g)[0];
|
||||
} catch (e) {
|
||||
typeText.innerText = "-";
|
||||
}
|
||||
|
||||
try{
|
||||
typeText.innerText = entry.match(/\[[^\]]+\]/g)[0];
|
||||
} catch(e){
|
||||
typeText.innerText = '-'
|
||||
}
|
||||
// let res = str.match(/[\[](.*)[^\]]/g);
|
||||
|
||||
type.appendChild(typeText);
|
||||
|
||||
// let res = str.match(/[\[](.*)[^\]]/g);
|
||||
var area = document.createElement("td");
|
||||
var areaText = document.createElement("span");
|
||||
//areaText.innerText = entry.slice(10, 50).match(/[\] \[](.*)[^\]]/g);
|
||||
//areaText.innerText = entry.match(/\[[^\]]+\]/g)[1];
|
||||
|
||||
type.appendChild(typeText);
|
||||
try {
|
||||
areaText.innerText = entry.match(/\[[^\]]+\]/g)[1];
|
||||
} catch (e) {
|
||||
areaText.innerText = "-";
|
||||
}
|
||||
area.appendChild(areaText);
|
||||
|
||||
var area = document.createElement("td");
|
||||
var areaText = document.createElement('span');
|
||||
//areaText.innerText = entry.slice(10, 50).match(/[\] \[](.*)[^\]]/g);
|
||||
//areaText.innerText = entry.match(/\[[^\]]+\]/g)[1];
|
||||
var logEntry = document.createElement("td");
|
||||
var logEntryText = document.createElement("span");
|
||||
try {
|
||||
logEntryText.innerText = entry.split("]")[2];
|
||||
} catch (e) {
|
||||
logEntryText.innerText = "-";
|
||||
}
|
||||
logEntry.appendChild(logEntryText);
|
||||
|
||||
try{
|
||||
areaText.innerText = entry.match(/\[[^\]]+\]/g)[1];
|
||||
} catch(e){
|
||||
areaText.innerText = '-'
|
||||
}
|
||||
area.appendChild(areaText);
|
||||
|
||||
var logEntry = document.createElement("td");
|
||||
var logEntryText = document.createElement('span');
|
||||
try{logEntryText.innerText = entry.split("]")[2];
|
||||
} catch(e){
|
||||
logEntryText.innerText = "-";
|
||||
}
|
||||
logEntry.appendChild(logEntryText);
|
||||
row.appendChild(timestamp);
|
||||
row.appendChild(type);
|
||||
row.appendChild(area);
|
||||
row.appendChild(logEntry);
|
||||
|
||||
row.appendChild(timestamp);
|
||||
row.appendChild(type);
|
||||
row.appendChild(area);
|
||||
row.appendChild(logEntry);
|
||||
|
||||
//row.classList.add("table-blablubb");
|
||||
/*
|
||||
//row.classList.add("table-blablubb");
|
||||
/*
|
||||
if (logEntryText.innerText.includes('ALSA lib pcm')) {
|
||||
row.classList.add("table-secondary");
|
||||
}
|
||||
*/
|
||||
if (typeText.innerText.includes('info')) {
|
||||
row.classList.add("table-info");
|
||||
}
|
||||
if (typeText.innerText.includes('debug')) {
|
||||
row.classList.add("table-secondary");
|
||||
}
|
||||
if (typeText.innerText.includes("info")) {
|
||||
row.classList.add("table-info");
|
||||
}
|
||||
if (typeText.innerText.includes("debug")) {
|
||||
row.classList.add("table-secondary");
|
||||
}
|
||||
|
||||
if (typeText.innerText.includes('warning')) {
|
||||
row.classList.add("table-warning");
|
||||
}
|
||||
|
||||
if (typeText.innerText.includes('error')) {
|
||||
row.classList.add("table-danger");
|
||||
}
|
||||
if (typeText.innerText.includes("warning")) {
|
||||
row.classList.add("table-warning");
|
||||
}
|
||||
|
||||
if (typeText.innerText.includes("error")) {
|
||||
row.classList.add("table-danger");
|
||||
}
|
||||
|
||||
if (document.getElementById('enable_filter_info').checked) {
|
||||
row.style.display = "table-row"
|
||||
display_class("table-info", true)
|
||||
} else {
|
||||
row.style.display = "None"
|
||||
display_class("table-info", false)
|
||||
if (document.getElementById("enable_filter_info").checked) {
|
||||
row.style.display = "table-row";
|
||||
display_class("table-info", true);
|
||||
} else {
|
||||
row.style.display = "None";
|
||||
display_class("table-info", false);
|
||||
}
|
||||
if (document.getElementById("enable_filter_debug").checked) {
|
||||
row.style.display = "table-row";
|
||||
display_class("table-secondary", true);
|
||||
} else {
|
||||
row.style.display = "None";
|
||||
display_class("table-secondary", false);
|
||||
}
|
||||
if (document.getElementById("enable_filter_warning").checked) {
|
||||
row.style.display = "table-row";
|
||||
display_class("table-warning", true);
|
||||
} else {
|
||||
row.style.display = "None";
|
||||
display_class("table-warning", false);
|
||||
}
|
||||
if (document.getElementById("enable_filter_error").checked) {
|
||||
row.style.display = "table-row";
|
||||
display_class("table-danger", true);
|
||||
} else {
|
||||
row.style.display = "None";
|
||||
display_class("table-danger", false);
|
||||
}
|
||||
|
||||
}
|
||||
if (document.getElementById('enable_filter_debug').checked) {
|
||||
row.style.display = "table-row"
|
||||
display_class("table-secondary", true)
|
||||
} else {
|
||||
row.style.display = "None"
|
||||
display_class("table-secondary", false)
|
||||
tbl.appendChild(row);
|
||||
|
||||
}
|
||||
if (document.getElementById('enable_filter_warning').checked) {
|
||||
row.style.display = "table-row"
|
||||
display_class("table-warning", true)
|
||||
} else {
|
||||
row.style.display = "None"
|
||||
display_class("table-warning", false)
|
||||
|
||||
}
|
||||
if (document.getElementById('enable_filter_error').checked) {
|
||||
row.style.display = "table-row"
|
||||
display_class("table-danger", true)
|
||||
} else {
|
||||
row.style.display = "None"
|
||||
display_class("table-danger", false)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
tbl.appendChild(row);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// scroll to bottom of page
|
||||
// https://stackoverflow.com/a/11715670
|
||||
window.scrollTo(0,document.body.scrollHeight);
|
||||
|
||||
|
||||
})
|
||||
// scroll to bottom of page
|
||||
// https://stackoverflow.com/a/11715670
|
||||
window.scrollTo(0, document.body.scrollHeight);
|
||||
});
|
||||
|
|
5390
gui/preload-main.js
5390
gui/preload-main.js
File diff suppressed because it is too large
Load diff
1233
gui/sock.js
1233
gui/sock.js
File diff suppressed because it is too large
Load diff
|
@ -1,83 +1,180 @@
|
|||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self';" />
|
||||
<!-- Bootstrap CSS -->
|
||||
<link
|
||||
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 -->
|
||||
<link rel="stylesheet" type="text/css" href="styles.css" />
|
||||
<title>FreeDATA - CHAT</title>
|
||||
</head>
|
||||
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self';">
|
||||
<!-- Bootstrap CSS -->
|
||||
<link 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 -->
|
||||
<link rel="stylesheet" type="text/css" href="styles.css" />
|
||||
<title>FreeDATA - CHAT</title>
|
||||
</head>
|
||||
<body>
|
||||
<!-- bootstrap -->
|
||||
<script src="../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<!-- chart.js -->
|
||||
<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 type="module" src="../node_modules/emoji-picker-element/index.js"></script>-->
|
||||
<script
|
||||
type="module"
|
||||
src="../node_modules/emoji-picker-element/picker.js"
|
||||
></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 class="container-fluid">
|
||||
<div class="row h-100">
|
||||
<div class="col-4 p-2 bg-light">
|
||||
<! ------Chats area ---------------------------------------------------------------------->
|
||||
<div class="container-fluid m-0 p-0">
|
||||
<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"
|
||||
/>
|
||||
<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>
|
||||
<hr class="m-2" />
|
||||
<div class="overflow-auto vh-100">
|
||||
<div
|
||||
class="list-group overflow-auto"
|
||||
id="list-tab"
|
||||
role="tablist"
|
||||
style="height: calc(100vh - 70px)"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-8 border vh-100 p-0">
|
||||
<! ------ chat navbar ---------------------------------------------------------------------->
|
||||
<div class="container-fluid m-2 p-0">
|
||||
<div class="input-group bottom-0">
|
||||
<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">
|
||||
<li>
|
||||
<a
|
||||
class="dropdown-item bg-danger text-white"
|
||||
id="delete_selected_chat"
|
||||
href="#"
|
||||
>Delete chat</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="m-0" />
|
||||
<! ------messages area ---------------------------------------------------------------------->
|
||||
<div
|
||||
class="container overflow-auto"
|
||||
id="message-container"
|
||||
style="height: calc(100% - 150px)"
|
||||
>
|
||||
<div class="tab-content" id="nav-tabContent"></div>
|
||||
<!--<div class="container position-absolute bottom-0">-->
|
||||
</div>
|
||||
<!-- </div>-->
|
||||
<div class="container-fluid mt-2 p-0">
|
||||
<input
|
||||
type="checkbox"
|
||||
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>
|
||||
|
||||
<body>
|
||||
<!-- bootstrap -->
|
||||
<script src="../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<!-- chart.js -->
|
||||
<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 type="module" src="../node_modules/emoji-picker-element/index.js"></script>-->
|
||||
<script type="module" src="../node_modules/emoji-picker-element/picker.js"></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 class="container-fluid">
|
||||
<div class="row h-100">
|
||||
<div class="col-4 p-2 bg-light">
|
||||
<! ------Chats area ---------------------------------------------------------------------->
|
||||
<div class="container-fluid m-0 p-0">
|
||||
<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">
|
||||
<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>
|
||||
<hr class="m-2">
|
||||
<div class="overflow-auto vh-100">
|
||||
<div class="list-group overflow-auto" id="list-tab" role="tablist" style="height: calc(100vh - 70px)"> </div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-8 border vh-100 p-0">
|
||||
<! ------ chat navbar ---------------------------------------------------------------------->
|
||||
<div class="container-fluid m-2 p-0">
|
||||
<div class="input-group bottom-0">
|
||||
<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">
|
||||
<li><a class="dropdown-item bg-danger text-white" id="delete_selected_chat" href="#">Delete chat</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="m-0">
|
||||
<! ------messages area ---------------------------------------------------------------------->
|
||||
<div class="container overflow-auto" id="message-container" style="height: calc(100% - 150px);">
|
||||
<div class="tab-content" id="nav-tabContent"> </div>
|
||||
<!--<div class="container position-absolute bottom-0">--></div>
|
||||
<!-- </div>-->
|
||||
<div class="container-fluid mt-2 p-0">
|
||||
<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>-->
|
||||
<!--<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 type="checkbox" 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">
|
||||
<!--<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>-->
|
||||
<!--<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>
|
||||
|
||||
|
||||
<!--<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>
|
||||
<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>
|
||||
</body>
|
||||
<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
|
||||
class="bi bi-paperclip m-1"
|
||||
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>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,150 +1,285 @@
|
|||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<!--<meta http-equiv="Content-Security-Policy" content="script-src 'self';">-->
|
||||
<!-- Bootstrap CSS -->
|
||||
<link rel="stylesheet" href="../node_modules/bootstrap/dist/css/bootstrap.min.css">
|
||||
<title>Send & Receive Data</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container-fluid">
|
||||
<div class="container mt-1">
|
||||
<div class="row mb-1">
|
||||
<div class="col">
|
||||
<div class="card text-dark bg-light mb-0 " >
|
||||
<div class="card-header">Select data </div>
|
||||
<div class="card-body">
|
||||
<div class="input-group input-group-sm mb-0">
|
||||
<input type="file" class="form-control" id="inputGroupFile02">
|
||||
<label class="input-group-text" for="inputGroupFile02">kB</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--col-->
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<!--<meta http-equiv="Content-Security-Policy" content="script-src 'self';">-->
|
||||
<!-- Bootstrap CSS -->
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="../node_modules/bootstrap/dist/css/bootstrap.min.css"
|
||||
/>
|
||||
<title>Send & Receive Data</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container-fluid">
|
||||
<div class="container mt-1">
|
||||
<div class="row mb-1">
|
||||
<div class="col">
|
||||
<div class="card text-dark bg-light mb-0">
|
||||
<div class="card-header">Select data</div>
|
||||
<div class="card-body">
|
||||
<div class="input-group input-group-sm mb-0">
|
||||
<input
|
||||
type="file"
|
||||
class="form-control"
|
||||
id="inputGroupFile02"
|
||||
/>
|
||||
<label class="input-group-text" for="inputGroupFile02"
|
||||
>kB</label
|
||||
>
|
||||
</div>
|
||||
<!--row-->
|
||||
<div class="row mb-2">
|
||||
<div class="col">
|
||||
<div class="card text-dark bg-light mb-0" >
|
||||
<div class="card-header">Transmission </div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-2">
|
||||
<div class="col-auto">
|
||||
<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">
|
||||
<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 class="row">
|
||||
<div class="col-auto">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-text" id="basic-addon1">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 value="DATAC3">DATAC3</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-text" id="basic-addon1">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 value="2">2</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="input-group input-group-sm">
|
||||
<button type="button" id="startTransmission"class="btn btn-success">Send</button>
|
||||
<!--<button type="button" id="stopTNC"class="btn btn-danger">STOP</button>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--col-->
|
||||
</div>
|
||||
<!--row-->
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="card text-dark bg-light mb-0" >
|
||||
<div class="card-header">Info </div>
|
||||
<div class="card-body">
|
||||
123
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<hr>
|
||||
</div>
|
||||
</div>
|
||||
<!--row-->
|
||||
</div>
|
||||
</div>
|
||||
<!--container-->
|
||||
</div>
|
||||
<!--col-->
|
||||
</div>
|
||||
<!---------------------------------------------------------------------- FOOTER AREA ------------------------------------------------------------>
|
||||
<nav class="navbar fixed-bottom navbar-light bg-light">
|
||||
<div class="container-fluid">
|
||||
<div 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">
|
||||
<svg 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>
|
||||
</button>
|
||||
</div>
|
||||
<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">
|
||||
<svg 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>
|
||||
</button>
|
||||
</div>
|
||||
<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">
|
||||
<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">
|
||||
<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>
|
||||
</button>
|
||||
</div>
|
||||
<div class="btn-group btn-group-sm me-2 " role="group" aria-label="Third group">
|
||||
<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>
|
||||
</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">
|
||||
<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>
|
||||
</button>
|
||||
</div>
|
||||
<div class="input-group input-group-sm me-2">
|
||||
<span class="input-group-text" id="basic-addon1">Bytes/s</span>
|
||||
<span class="input-group-text" id="basic-addon1">----</span>
|
||||
</div>
|
||||
<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>
|
||||
<!--row-->
|
||||
<div class="row mb-2">
|
||||
<div class="col">
|
||||
<div class="card text-dark bg-light mb-0">
|
||||
<div class="card-header">Transmission</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-2">
|
||||
<div class="col-auto">
|
||||
<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"
|
||||
/>
|
||||
<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 class="row">
|
||||
<div class="col-auto">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-text" id="basic-addon1"
|
||||
>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 value="DATAC3">DATAC3</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-text" id="basic-addon1"
|
||||
>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 value="2">2</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="input-group input-group-sm">
|
||||
<button
|
||||
type="button"
|
||||
id="startTransmission"
|
||||
class="btn btn-success"
|
||||
>
|
||||
Send
|
||||
</button>
|
||||
<!--<button type="button" id="stopTNC"class="btn btn-danger">STOP</button>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<script src="../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
<!--col-->
|
||||
</div>
|
||||
<!--row-->
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="card text-dark bg-light mb-0">
|
||||
<div class="card-header">Info</div>
|
||||
<div class="card-body">123</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<hr />
|
||||
</div>
|
||||
</div>
|
||||
<!--row-->
|
||||
</div>
|
||||
<!--container-->
|
||||
</div>
|
||||
<!---------------------------------------------------------------------- FOOTER AREA ------------------------------------------------------------>
|
||||
<nav class="navbar fixed-bottom navbar-light bg-light">
|
||||
<div class="container-fluid">
|
||||
<div
|
||||
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">
|
||||
<svg
|
||||
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>
|
||||
</button>
|
||||
</div>
|
||||
<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">
|
||||
<svg
|
||||
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>
|
||||
</button>
|
||||
</div>
|
||||
<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">
|
||||
<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"
|
||||
>
|
||||
<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>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="btn-group btn-group-sm me-2"
|
||||
role="group"
|
||||
aria-label="Third group"
|
||||
>
|
||||
<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>
|
||||
</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"
|
||||
>
|
||||
<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>
|
||||
</button>
|
||||
</div>
|
||||
<div class="input-group input-group-sm me-2">
|
||||
<span class="input-group-text" id="basic-addon1">Bytes/s</span>
|
||||
<span class="input-group-text" id="basic-addon1">----</span>
|
||||
</div>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<script src="../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,261 +1,261 @@
|
|||
<option value="1">Hamlib Dummy</option>
|
||||
<option value="2">Hamlib NET rigctl </option>
|
||||
<option value="4">FLRig FLRig </option>
|
||||
<option value="5">TRXManager TRXManager 5.7.630+</option>
|
||||
<option value="6"> Hamlib Dummy No VFO </option>
|
||||
<option value="1001"> Yaesu FT-847 </option>
|
||||
<option value="1003"> Yaesu FT-1000D </option>
|
||||
<option value="1004"> Yaesu MARK-V FT-1000MP </option>
|
||||
<option value="1005"> Yaesu FT-747GX </option>
|
||||
<option value="1006"> Yaesu FT-757GX </option>
|
||||
<option value="1007"> Yaesu FT-757GXII</option>
|
||||
<option value="1009"> Yaesu FT-767GX </option>
|
||||
<option value="1010"> Yaesu FT-736R </option>
|
||||
<option value="1011"> Yaesu FT-840 </option>
|
||||
<option value="1013"> Yaesu FT-900 </option>
|
||||
<option value="1014"> Yaesu FT-920 </option>
|
||||
<option value="1015"> Yaesu FT-890 </option>
|
||||
<option value="1016"> Yaesu FT-990 </option>
|
||||
<option value="1017"> Yaesu FRG-100 </option>
|
||||
<option value="1018"> Yaesu FRG-9600 </option>
|
||||
<option value="1019"> Yaesu FRG-8800 </option>
|
||||
<option value="1020"> Yaesu FT-817 </option>
|
||||
<option value="1021"> Yaesu FT-100 </option>
|
||||
<option value="1022"> Yaesu FT-857 </option>
|
||||
<option value="1023"> Yaesu FT-897 </option>
|
||||
<option value="1024"> Yaesu FT-1000MP </option>
|
||||
<option value="1025"> Yaesu MARK-V Field FT-1000MP </option>
|
||||
<option value="1026"> Yaesu VR-5000 </option>
|
||||
<option value="1027"> Yaesu FT-450 </option>
|
||||
<option value="1028"> Yaesu FT-950 </option>
|
||||
<option value="1029"> Yaesu FT-2000 </option>
|
||||
<option value="1030"> Yaesu FTDX-9000 </option>
|
||||
<option value="1031"> Yaesu FT-980 </option>
|
||||
<option value="1032"> Yaesu FTDX-5000 </option>
|
||||
<option value="1033"> Vertex Standard VX-1700 </option>
|
||||
<option value="1034"> Yaesu FTDX-1200 </option>
|
||||
<option value="1035"> Yaesu FT-991 </option>
|
||||
<option value="1036"> Yaesu FT-891 </option>
|
||||
<option value="1037"> Yaesu FTDX-3000 </option>
|
||||
<option value="1038"> Yaesu FT-847UNI </option>
|
||||
<option value="1039"> Yaesu FT-600 </option>
|
||||
<option value="1040"> Yaesu FTDX-101D </option>
|
||||
<option value="1041"> Yaesu FT-818 </option>
|
||||
<option value="1042"> Yaesu FTDX-10 </option>
|
||||
<option value="1043"> Yaesu FT-897D </option>
|
||||
<option value="1044"> Yaesu FTDX-101MP </option>
|
||||
<option value="2001"> Kenwood TS-50S </option>
|
||||
<option value="2002"> Kenwood TS-440S </option>
|
||||
<option value="2003"> Kenwood TS-450S </option>
|
||||
<option value="2004"> Kenwood TS-570D </option>
|
||||
<option value="2005"> Kenwood TS-690S </option>
|
||||
<option value="2006"> Kenwood TS-711 </option>
|
||||
<option value="2007"> Kenwood TS-790 </option>
|
||||
<option value="2008"> Kenwood TS-811 </option>
|
||||
<option value="2009"> Kenwood TS-850 </option>
|
||||
<option value="2010"> Kenwood TS-870S </option>
|
||||
<option value="2011"> Kenwood TS-940S </option>
|
||||
<option value="2012"> Kenwood TS-950S </option>
|
||||
<option value="2013"> Kenwood TS-950SDX </option>
|
||||
<option value="2014"> Kenwood TS-2000 </option>
|
||||
<option value="2015"> Kenwood R-5000 </option>
|
||||
<option value="2016"> Kenwood TS-570S </option>
|
||||
<option value="2017"> Kenwood TH-D7A </option>
|
||||
<option value="2019"> Kenwood TH-F6A </option>
|
||||
<option value="2020"> Kenwood TH-F7E </option>
|
||||
<option value="2021"> Elecraft K2 </option>
|
||||
<option value="2022"> Kenwood TS-930 </option>
|
||||
<option value="2023"> Kenwood TH-G71 </option>
|
||||
<option value="2024"> Kenwood TS-680S </option>
|
||||
<option value="2025"> Kenwood TS-140S </option>
|
||||
<option value="2026"> Kenwood TM-D700 </option>
|
||||
<option value="2027"> Kenwood TM-V7 </option>
|
||||
<option value="2028"> Kenwood TS-480 </option>
|
||||
<option value="2029"> Elecraft K3 </option>
|
||||
<option value="2030"> Kenwood TRC-80 </option>
|
||||
<option value="2031"> Kenwood TS-590S </option>
|
||||
<option value="2032"> SigFox Transfox </option>
|
||||
<option value="2033"> Kenwood TH-D72A </option>
|
||||
<option value="2034"> Kenwood TM-D710(G) </option>
|
||||
<option value="2036"> FlexRadio 6xxx </option>
|
||||
<option value="2037"> Kenwood TS-590SG </option>
|
||||
<option value="2038"> Elecraft XG3 </option>
|
||||
<option value="2039"> Kenwood TS-990s </option>
|
||||
<option value="2040"> OpenHPSDR PiHPSDR </option>
|
||||
<option value="2041"> Kenwood TS-890S </option>
|
||||
<option value="2042"> Kenwood TH-D74 </option>
|
||||
<option value="2043"> Elecraft K3S </option>
|
||||
<option value="2044"> Elecraft KX2 </option>
|
||||
<option value="2045"> Elecraft KX3 </option>
|
||||
<option value="2046"> Hilberling PT-8000A </option>
|
||||
<option value="2047"> Elecraft K4 </option>
|
||||
<option value="2048"> FlexRadio/ANAN PowerSDR/Thetis </option>
|
||||
<option value="2049"> Malachite DSP </option>
|
||||
<option value="3002"> Icom IC-1275 </option>
|
||||
<option value="3003"> Icom IC-271 </option>
|
||||
<option value="3004"> Icom IC-275 </option>
|
||||
<option value="3006"> Icom IC-471 </option>
|
||||
<option value="3007"> Icom IC-475 </option>
|
||||
<option value="3009"> Icom IC-706 </option>
|
||||
<option value="3010"> Icom IC-706MkII </option>
|
||||
<option value="3011"> Icom IC-706MkIIG </option>
|
||||
<option value="3012"> Icom IC-707 </option>
|
||||
<option value="3013"> Icom IC-718 </option>
|
||||
<option value="3014"> Icom IC-725 </option>
|
||||
<option value="3015"> Icom IC-726 </option>
|
||||
<option value="3016"> Icom IC-728 </option>
|
||||
<option value="3017"> Icom IC-729 </option>
|
||||
<option value="3019"> Icom IC-735 </option>
|
||||
<option value="3020"> Icom IC-736 </option>
|
||||
<option value="3021"> Icom IC-737 </option>
|
||||
<option value="3022"> Icom IC-738 </option>
|
||||
<option value="3023"> Icom IC-746 </option>
|
||||
<option value="3024"> Icom IC-751 </option>
|
||||
<option value="3026"> Icom IC-756 </option>
|
||||
<option value="3027"> Icom IC-756PRO </option>
|
||||
<option value="3028"> Icom IC-761 </option>
|
||||
<option value="3029"> Icom IC-765 </option>
|
||||
<option value="3030"> Icom IC-775 </option>
|
||||
<option value="3031"> Icom IC-781 </option>
|
||||
<option value="3032"> Icom IC-820H </option>
|
||||
<option value="3034"> Icom IC-821H </option>
|
||||
<option value="3035"> Icom IC-970 </option>
|
||||
<option value="3036"> Icom IC-R10 </option>
|
||||
<option value="3037"> Icom IC-R71 </option>
|
||||
<option value="3038"> Icom IC-R72 </option>
|
||||
<option value="3039"> Icom IC-R75 </option>
|
||||
<option value="3040"> Icom IC-R7000 </option>
|
||||
<option value="3041"> Icom IC-R7100 </option>
|
||||
<option value="3042"> Icom ICR-8500 </option>
|
||||
<option value="3043"> Icom IC-R9000 </option>
|
||||
<option value="3044"> Icom IC-910 </option>
|
||||
<option value="3045"> Icom IC-78 </option>
|
||||
<option value="3046"> Icom IC-746PRO </option>
|
||||
<option value="3047"> Icom IC-756PROII </option>
|
||||
<option value="3051">Ten-Tec Omni VI Plus </option>
|
||||
<option value="3052"> Optoelectronics OptoScan535 </option>
|
||||
<option value="3053"> Optoelectronics OptoScan456 </option>
|
||||
<option value="3054"> Icom IC ID-1 </option>
|
||||
<option value="3055"> Icom IC-703 </option>
|
||||
<option value="3056"> Icom IC-7800 </option>
|
||||
<option value="3057"> Icom IC-756PROIII </option>
|
||||
<option value="3058"> Icom IC-R20 </option>
|
||||
<option value="3060"> Icom IC-7000 </option>
|
||||
<option value="3061"> Icom IC-7200 </option>
|
||||
<option value="3062"> Icom IC-7700 </option>
|
||||
<option value="3063"> Icom IC-7600 </option>
|
||||
<option value="3064"> Ten-Tec Delta II </option>
|
||||
<option value="3065"> Icom IC-92D </option>
|
||||
<option value="3066"> Icom IC-R9500 </option>
|
||||
<option value="3067"> Icom IC-7410 </option>
|
||||
<option value="3068"> Icom IC-9100 </option>
|
||||
<option value="3069"> Icom IC-RX7 </option>
|
||||
<option value="3070"> Icom IC-7100 </option>
|
||||
<option value="3071"> Icom ID-5100 </option>
|
||||
<option value="3072"> Icom IC-2730 </option>
|
||||
<option value="3073"> Icom IC-7300 </option>
|
||||
<option value="3074"> Microtelecom Perseus </option>
|
||||
<option value="3075"> Icom IC-785x </option>
|
||||
<option value="3076"> Xeigu X108G </option>
|
||||
<option value="3077"> Icom IC-R6 </option>
|
||||
<option value="3078"> Icom IC-7610 </option>
|
||||
<option value="3079"> Icom IC-R8600 </option>
|
||||
<option value="3080"> Icom IC-R30 </option>
|
||||
<option value="3081"> Icom IC-9700 </option>
|
||||
<option value="3082"> Icom ID-4100 </option>
|
||||
<option value="3083"> Icom ID-31 </option>
|
||||
<option value="3084"> Icom ID-51 </option>
|
||||
<option value="3085"> Icom IC-705 </option>
|
||||
<option value="4001"> Icom IC-PCR1000 </option>
|
||||
<option value="4002"> Icom IC-PCR100 </option>
|
||||
<option value="4003"> Icom IC-PCR1500 </option>
|
||||
<option value="4004"> Icom IC-PCR2500 </option>
|
||||
<option value="5001"> AOR AR8200 </option>
|
||||
<option value="5002"> AOR AR8000 </option>
|
||||
<option value="5003"> AOR AR7030 </option>
|
||||
<option value="5004"> AOR AR5000 </option>
|
||||
<option value="5005"> AOR AR3030 </option>
|
||||
<option value="5006"> AOR AR3000A </option>
|
||||
<option value="5008"> AOR AR2700 </option>
|
||||
<option value="5013"> AOR AR8600 </option>
|
||||
<option value="5014"> AOR AR5000A </option>
|
||||
<option value="5015"> AOR AR7030 Plus </option>
|
||||
<option value="5016"> AOR SR2200 </option>
|
||||
<option value="6005"> JRC NRD-525 </option>
|
||||
<option value="6006"> JRC NRD-535D </option>
|
||||
<option value="6007"> JRC NRD-545 DSP </option>
|
||||
<option value="8001"> Uniden BC780xlt </option>
|
||||
<option value="8002"> Uniden BC245xlt </option>
|
||||
<option value="8003"> Uniden BC895xlt </option>
|
||||
<option value="8004"> Radio Shack PRO-2052 </option>
|
||||
<option value="8006"> Uniden BC250D </option>
|
||||
<option value="8010"> Uniden BCD-396T </option>
|
||||
<option value="8011"> Uniden BCD-996T </option>
|
||||
<option value="8012"> Uniden BC898T </option>
|
||||
<option value="9002"> Drake R-8A </option>
|
||||
<option value="9003"> Drake R-8B </option>
|
||||
<option value="10004"> Lowe HF-235 </option>
|
||||
<option value="11003">Racal RA6790/GM </option>
|
||||
<option value="11005"> Racal RA3702 </option>
|
||||
<option value="12004"> Watkins-Johnson WJ-8888 </option>
|
||||
<option value="14002"> Skanti TRP8000 </option>
|
||||
<option value="14004"> Skanti TRP 8255 S R </option>
|
||||
<option value="15001"> Winradio WR-1000 </option>
|
||||
<option value="15002"> Winradio WR-1500 </option>
|
||||
<option value="15003"> Winradio WR-1550 </option>
|
||||
<option value="15004"> Winradio WR-3100 </option>
|
||||
<option value="15005"> Winradio WR-3150 </option>
|
||||
<option value="15006">Winradio WR-3500 </option>
|
||||
<option value="15007"> Winradio WR-3700 </option>
|
||||
<option value="15009"> Winradio WR-G313 </option>
|
||||
<option value="16001"> Ten-Tec TT-550 </option>
|
||||
<option value="16002"> Ten-Tec TT-538 Jupiter </option>
|
||||
<option value="16003"> Ten-Tec RX-320 </option>
|
||||
<option value="16004"> Ten-Tec RX-340 </option>
|
||||
<option value="16005"> Ten-Tec RX-350 </option>
|
||||
<option value="16007"> Ten-Tec TT-516 Argonaut V </option>
|
||||
<option value="16008"> Ten-Tec TT-565 Orion </option>
|
||||
<option value="16009"> Ten-Tec TT-585 Paragon </option>
|
||||
<option value="16011"> Ten-Tec TT-588 Omni VII </option>
|
||||
<option value="16012"> Ten-Tec RX-331 </option>
|
||||
<option value="16013"> Ten-Tec TT-599 Eagle </option>
|
||||
<option value="17001"> Alinco DX-77 </option>
|
||||
<option value="17002"> Alinco DX-SR8 </option>
|
||||
<option value="18001"> Kachina 505DSP </option>
|
||||
<option value="22001"> TAPR DSP-10 </option>
|
||||
<option value="23001"> Flex-radio SDR-1000 </option>
|
||||
<option value="23003"> DTTS Microwave Society DttSP IPC </option>
|
||||
<option value="23004"> DTTS Microwave Society DttSP UDP </option>
|
||||
<option value="24001"> RFT EKD-500 </option>
|
||||
<option value="25001"> Elektor Elektor 3/04 </option>
|
||||
<option value="25002"> SAT-Schneider DRT1 </option>
|
||||
<option value="25003"> Coding Technologies Digital World Traveller</option>
|
||||
<option value="25006"> AmQRP DDS-60 </option>
|
||||
<option value="25007"> Elektor Elektor SDR-USB </option>
|
||||
<option value="25008"> mRS miniVNA </option>
|
||||
<option value="25009"> SoftRock Si570 AVR-USB </option>
|
||||
<option value="25011"> KTH-SDR kit Si570 PIC-USB </option>
|
||||
<option value="25012"> FiFi FiFi-SDR </option>
|
||||
<option value="25013"> AMSAT-UK FUNcube Dongle </option>
|
||||
<option value="25014"> N2ADR HiQSDR </option>
|
||||
<option value="25015"> Funkamateur FA-SDR </option>
|
||||
<option value="25016"> AE9RB Si570 Peaberry V1 </option>
|
||||
<option value="25017"> AE9RB Si570 Peaberry V2 </option>
|
||||
<option value="25018"> AMSAT-UK FUNcube Dongle Pro+ </option>
|
||||
<option value="25019"> HobbyPCB RS-HFIQ </option>
|
||||
<option value="26001"> Video4Linux SW/FM radio </option>
|
||||
<option value="26002"> Video4Linux2 SW/FM radio </option>
|
||||
<option value="27001"> Rohde&Schwarz ESMC </option>
|
||||
<option value="27002"> Rohde&Schwarz EB200 </option>
|
||||
<option value="27003"> Rohde&Schwarz XK2100 </option>
|
||||
<option value="28001"> Philips/Simoco PRM8060 </option>
|
||||
<option value="29001"> ADAT www.adat.ch ADT-200A </option>
|
||||
<option value="30001"> Icom IC-M700PRO </option>
|
||||
<option value="30002"> Icom IC-M802 </option>
|
||||
<option value="30003"> Icom IC-M710 </option>
|
||||
<option value="30004"> Icom IC-M803 </option>
|
||||
<option value="31001"> Dorji DRA818V </option>
|
||||
<option value="31002"> Dorji DRA818U </option>
|
||||
<option value="32001"> Barrett 2050 </option>
|
||||
<option value="32002"> Barrett 950 </option>
|
||||
<option value="33001"> ELAD FDM-DUO </option>
|
||||
<option value="1">Hamlib Dummy</option>
|
||||
<option value="2">Hamlib NET rigctl</option>
|
||||
<option value="4">FLRig FLRig</option>
|
||||
<option value="5">TRXManager TRXManager 5.7.630+</option>
|
||||
<option value="6">Hamlib Dummy No VFO</option>
|
||||
<option value="1001">Yaesu FT-847</option>
|
||||
<option value="1003">Yaesu FT-1000D</option>
|
||||
<option value="1004">Yaesu MARK-V FT-1000MP</option>
|
||||
<option value="1005">Yaesu FT-747GX</option>
|
||||
<option value="1006">Yaesu FT-757GX</option>
|
||||
<option value="1007">Yaesu FT-757GXII</option>
|
||||
<option value="1009">Yaesu FT-767GX</option>
|
||||
<option value="1010">Yaesu FT-736R</option>
|
||||
<option value="1011">Yaesu FT-840</option>
|
||||
<option value="1013">Yaesu FT-900</option>
|
||||
<option value="1014">Yaesu FT-920</option>
|
||||
<option value="1015">Yaesu FT-890</option>
|
||||
<option value="1016">Yaesu FT-990</option>
|
||||
<option value="1017">Yaesu FRG-100</option>
|
||||
<option value="1018">Yaesu FRG-9600</option>
|
||||
<option value="1019">Yaesu FRG-8800</option>
|
||||
<option value="1020">Yaesu FT-817</option>
|
||||
<option value="1021">Yaesu FT-100</option>
|
||||
<option value="1022">Yaesu FT-857</option>
|
||||
<option value="1023">Yaesu FT-897</option>
|
||||
<option value="1024">Yaesu FT-1000MP</option>
|
||||
<option value="1025">Yaesu MARK-V Field FT-1000MP</option>
|
||||
<option value="1026">Yaesu VR-5000</option>
|
||||
<option value="1027">Yaesu FT-450</option>
|
||||
<option value="1028">Yaesu FT-950</option>
|
||||
<option value="1029">Yaesu FT-2000</option>
|
||||
<option value="1030">Yaesu FTDX-9000</option>
|
||||
<option value="1031">Yaesu FT-980</option>
|
||||
<option value="1032">Yaesu FTDX-5000</option>
|
||||
<option value="1033">Vertex Standard VX-1700</option>
|
||||
<option value="1034">Yaesu FTDX-1200</option>
|
||||
<option value="1035">Yaesu FT-991</option>
|
||||
<option value="1036">Yaesu FT-891</option>
|
||||
<option value="1037">Yaesu FTDX-3000</option>
|
||||
<option value="1038">Yaesu FT-847UNI</option>
|
||||
<option value="1039">Yaesu FT-600</option>
|
||||
<option value="1040">Yaesu FTDX-101D</option>
|
||||
<option value="1041">Yaesu FT-818</option>
|
||||
<option value="1042">Yaesu FTDX-10</option>
|
||||
<option value="1043">Yaesu FT-897D</option>
|
||||
<option value="1044">Yaesu FTDX-101MP</option>
|
||||
<option value="2001">Kenwood TS-50S</option>
|
||||
<option value="2002">Kenwood TS-440S</option>
|
||||
<option value="2003">Kenwood TS-450S</option>
|
||||
<option value="2004">Kenwood TS-570D</option>
|
||||
<option value="2005">Kenwood TS-690S</option>
|
||||
<option value="2006">Kenwood TS-711</option>
|
||||
<option value="2007">Kenwood TS-790</option>
|
||||
<option value="2008">Kenwood TS-811</option>
|
||||
<option value="2009">Kenwood TS-850</option>
|
||||
<option value="2010">Kenwood TS-870S</option>
|
||||
<option value="2011">Kenwood TS-940S</option>
|
||||
<option value="2012">Kenwood TS-950S</option>
|
||||
<option value="2013">Kenwood TS-950SDX</option>
|
||||
<option value="2014">Kenwood TS-2000</option>
|
||||
<option value="2015">Kenwood R-5000</option>
|
||||
<option value="2016">Kenwood TS-570S</option>
|
||||
<option value="2017">Kenwood TH-D7A</option>
|
||||
<option value="2019">Kenwood TH-F6A</option>
|
||||
<option value="2020">Kenwood TH-F7E</option>
|
||||
<option value="2021">Elecraft K2</option>
|
||||
<option value="2022">Kenwood TS-930</option>
|
||||
<option value="2023">Kenwood TH-G71</option>
|
||||
<option value="2024">Kenwood TS-680S</option>
|
||||
<option value="2025">Kenwood TS-140S</option>
|
||||
<option value="2026">Kenwood TM-D700</option>
|
||||
<option value="2027">Kenwood TM-V7</option>
|
||||
<option value="2028">Kenwood TS-480</option>
|
||||
<option value="2029">Elecraft K3</option>
|
||||
<option value="2030">Kenwood TRC-80</option>
|
||||
<option value="2031">Kenwood TS-590S</option>
|
||||
<option value="2032">SigFox Transfox</option>
|
||||
<option value="2033">Kenwood TH-D72A</option>
|
||||
<option value="2034">Kenwood TM-D710(G)</option>
|
||||
<option value="2036">FlexRadio 6xxx</option>
|
||||
<option value="2037">Kenwood TS-590SG</option>
|
||||
<option value="2038">Elecraft XG3</option>
|
||||
<option value="2039">Kenwood TS-990s</option>
|
||||
<option value="2040">OpenHPSDR PiHPSDR</option>
|
||||
<option value="2041">Kenwood TS-890S</option>
|
||||
<option value="2042">Kenwood TH-D74</option>
|
||||
<option value="2043">Elecraft K3S</option>
|
||||
<option value="2044">Elecraft KX2</option>
|
||||
<option value="2045">Elecraft KX3</option>
|
||||
<option value="2046">Hilberling PT-8000A</option>
|
||||
<option value="2047">Elecraft K4</option>
|
||||
<option value="2048">FlexRadio/ANAN PowerSDR/Thetis</option>
|
||||
<option value="2049">Malachite DSP</option>
|
||||
<option value="3002">Icom IC-1275</option>
|
||||
<option value="3003">Icom IC-271</option>
|
||||
<option value="3004">Icom IC-275</option>
|
||||
<option value="3006">Icom IC-471</option>
|
||||
<option value="3007">Icom IC-475</option>
|
||||
<option value="3009">Icom IC-706</option>
|
||||
<option value="3010">Icom IC-706MkII</option>
|
||||
<option value="3011">Icom IC-706MkIIG</option>
|
||||
<option value="3012">Icom IC-707</option>
|
||||
<option value="3013">Icom IC-718</option>
|
||||
<option value="3014">Icom IC-725</option>
|
||||
<option value="3015">Icom IC-726</option>
|
||||
<option value="3016">Icom IC-728</option>
|
||||
<option value="3017">Icom IC-729</option>
|
||||
<option value="3019">Icom IC-735</option>
|
||||
<option value="3020">Icom IC-736</option>
|
||||
<option value="3021">Icom IC-737</option>
|
||||
<option value="3022">Icom IC-738</option>
|
||||
<option value="3023">Icom IC-746</option>
|
||||
<option value="3024">Icom IC-751</option>
|
||||
<option value="3026">Icom IC-756</option>
|
||||
<option value="3027">Icom IC-756PRO</option>
|
||||
<option value="3028">Icom IC-761</option>
|
||||
<option value="3029">Icom IC-765</option>
|
||||
<option value="3030">Icom IC-775</option>
|
||||
<option value="3031">Icom IC-781</option>
|
||||
<option value="3032">Icom IC-820H</option>
|
||||
<option value="3034">Icom IC-821H</option>
|
||||
<option value="3035">Icom IC-970</option>
|
||||
<option value="3036">Icom IC-R10</option>
|
||||
<option value="3037">Icom IC-R71</option>
|
||||
<option value="3038">Icom IC-R72</option>
|
||||
<option value="3039">Icom IC-R75</option>
|
||||
<option value="3040">Icom IC-R7000</option>
|
||||
<option value="3041">Icom IC-R7100</option>
|
||||
<option value="3042">Icom ICR-8500</option>
|
||||
<option value="3043">Icom IC-R9000</option>
|
||||
<option value="3044">Icom IC-910</option>
|
||||
<option value="3045">Icom IC-78</option>
|
||||
<option value="3046">Icom IC-746PRO</option>
|
||||
<option value="3047">Icom IC-756PROII</option>
|
||||
<option value="3051">Ten-Tec Omni VI Plus</option>
|
||||
<option value="3052">Optoelectronics OptoScan535</option>
|
||||
<option value="3053">Optoelectronics OptoScan456</option>
|
||||
<option value="3054">Icom IC ID-1</option>
|
||||
<option value="3055">Icom IC-703</option>
|
||||
<option value="3056">Icom IC-7800</option>
|
||||
<option value="3057">Icom IC-756PROIII</option>
|
||||
<option value="3058">Icom IC-R20</option>
|
||||
<option value="3060">Icom IC-7000</option>
|
||||
<option value="3061">Icom IC-7200</option>
|
||||
<option value="3062">Icom IC-7700</option>
|
||||
<option value="3063">Icom IC-7600</option>
|
||||
<option value="3064">Ten-Tec Delta II</option>
|
||||
<option value="3065">Icom IC-92D</option>
|
||||
<option value="3066">Icom IC-R9500</option>
|
||||
<option value="3067">Icom IC-7410</option>
|
||||
<option value="3068">Icom IC-9100</option>
|
||||
<option value="3069">Icom IC-RX7</option>
|
||||
<option value="3070">Icom IC-7100</option>
|
||||
<option value="3071">Icom ID-5100</option>
|
||||
<option value="3072">Icom IC-2730</option>
|
||||
<option value="3073">Icom IC-7300</option>
|
||||
<option value="3074">Microtelecom Perseus</option>
|
||||
<option value="3075">Icom IC-785x</option>
|
||||
<option value="3076">Xeigu X108G</option>
|
||||
<option value="3077">Icom IC-R6</option>
|
||||
<option value="3078">Icom IC-7610</option>
|
||||
<option value="3079">Icom IC-R8600</option>
|
||||
<option value="3080">Icom IC-R30</option>
|
||||
<option value="3081">Icom IC-9700</option>
|
||||
<option value="3082">Icom ID-4100</option>
|
||||
<option value="3083">Icom ID-31</option>
|
||||
<option value="3084">Icom ID-51</option>
|
||||
<option value="3085">Icom IC-705</option>
|
||||
<option value="4001">Icom IC-PCR1000</option>
|
||||
<option value="4002">Icom IC-PCR100</option>
|
||||
<option value="4003">Icom IC-PCR1500</option>
|
||||
<option value="4004">Icom IC-PCR2500</option>
|
||||
<option value="5001">AOR AR8200</option>
|
||||
<option value="5002">AOR AR8000</option>
|
||||
<option value="5003">AOR AR7030</option>
|
||||
<option value="5004">AOR AR5000</option>
|
||||
<option value="5005">AOR AR3030</option>
|
||||
<option value="5006">AOR AR3000A</option>
|
||||
<option value="5008">AOR AR2700</option>
|
||||
<option value="5013">AOR AR8600</option>
|
||||
<option value="5014">AOR AR5000A</option>
|
||||
<option value="5015">AOR AR7030 Plus</option>
|
||||
<option value="5016">AOR SR2200</option>
|
||||
<option value="6005">JRC NRD-525</option>
|
||||
<option value="6006">JRC NRD-535D</option>
|
||||
<option value="6007">JRC NRD-545 DSP</option>
|
||||
<option value="8001">Uniden BC780xlt</option>
|
||||
<option value="8002">Uniden BC245xlt</option>
|
||||
<option value="8003">Uniden BC895xlt</option>
|
||||
<option value="8004">Radio Shack PRO-2052</option>
|
||||
<option value="8006">Uniden BC250D</option>
|
||||
<option value="8010">Uniden BCD-396T</option>
|
||||
<option value="8011">Uniden BCD-996T</option>
|
||||
<option value="8012">Uniden BC898T</option>
|
||||
<option value="9002">Drake R-8A</option>
|
||||
<option value="9003">Drake R-8B</option>
|
||||
<option value="10004">Lowe HF-235</option>
|
||||
<option value="11003">Racal RA6790/GM</option>
|
||||
<option value="11005">Racal RA3702</option>
|
||||
<option value="12004">Watkins-Johnson WJ-8888</option>
|
||||
<option value="14002">Skanti TRP8000</option>
|
||||
<option value="14004">Skanti TRP 8255 S R</option>
|
||||
<option value="15001">Winradio WR-1000</option>
|
||||
<option value="15002">Winradio WR-1500</option>
|
||||
<option value="15003">Winradio WR-1550</option>
|
||||
<option value="15004">Winradio WR-3100</option>
|
||||
<option value="15005">Winradio WR-3150</option>
|
||||
<option value="15006">Winradio WR-3500</option>
|
||||
<option value="15007">Winradio WR-3700</option>
|
||||
<option value="15009">Winradio WR-G313</option>
|
||||
<option value="16001">Ten-Tec TT-550</option>
|
||||
<option value="16002">Ten-Tec TT-538 Jupiter</option>
|
||||
<option value="16003">Ten-Tec RX-320</option>
|
||||
<option value="16004">Ten-Tec RX-340</option>
|
||||
<option value="16005">Ten-Tec RX-350</option>
|
||||
<option value="16007">Ten-Tec TT-516 Argonaut V</option>
|
||||
<option value="16008">Ten-Tec TT-565 Orion</option>
|
||||
<option value="16009">Ten-Tec TT-585 Paragon</option>
|
||||
<option value="16011">Ten-Tec TT-588 Omni VII</option>
|
||||
<option value="16012">Ten-Tec RX-331</option>
|
||||
<option value="16013">Ten-Tec TT-599 Eagle</option>
|
||||
<option value="17001">Alinco DX-77</option>
|
||||
<option value="17002">Alinco DX-SR8</option>
|
||||
<option value="18001">Kachina 505DSP</option>
|
||||
<option value="22001">TAPR DSP-10</option>
|
||||
<option value="23001">Flex-radio SDR-1000</option>
|
||||
<option value="23003">DTTS Microwave Society DttSP IPC</option>
|
||||
<option value="23004">DTTS Microwave Society DttSP UDP</option>
|
||||
<option value="24001">RFT EKD-500</option>
|
||||
<option value="25001">Elektor Elektor 3/04</option>
|
||||
<option value="25002">SAT-Schneider DRT1</option>
|
||||
<option value="25003">Coding Technologies Digital World Traveller</option>
|
||||
<option value="25006">AmQRP DDS-60</option>
|
||||
<option value="25007">Elektor Elektor SDR-USB</option>
|
||||
<option value="25008">mRS miniVNA</option>
|
||||
<option value="25009">SoftRock Si570 AVR-USB</option>
|
||||
<option value="25011">KTH-SDR kit Si570 PIC-USB</option>
|
||||
<option value="25012">FiFi FiFi-SDR</option>
|
||||
<option value="25013">AMSAT-UK FUNcube Dongle</option>
|
||||
<option value="25014">N2ADR HiQSDR</option>
|
||||
<option value="25015">Funkamateur FA-SDR</option>
|
||||
<option value="25016">AE9RB Si570 Peaberry V1</option>
|
||||
<option value="25017">AE9RB Si570 Peaberry V2</option>
|
||||
<option value="25018">AMSAT-UK FUNcube Dongle Pro+</option>
|
||||
<option value="25019">HobbyPCB RS-HFIQ</option>
|
||||
<option value="26001">Video4Linux SW/FM radio</option>
|
||||
<option value="26002">Video4Linux2 SW/FM radio</option>
|
||||
<option value="27001">Rohde&Schwarz ESMC</option>
|
||||
<option value="27002">Rohde&Schwarz EB200</option>
|
||||
<option value="27003">Rohde&Schwarz XK2100</option>
|
||||
<option value="28001">Philips/Simoco PRM8060</option>
|
||||
<option value="29001">ADAT www.adat.ch ADT-200A</option>
|
||||
<option value="30001">Icom IC-M700PRO</option>
|
||||
<option value="30002">Icom IC-M802</option>
|
||||
<option value="30003">Icom IC-M710</option>
|
||||
<option value="30004">Icom IC-M803</option>
|
||||
<option value="31001">Dorji DRA818V</option>
|
||||
<option value="31002">Dorji DRA818U</option>
|
||||
<option value="32001">Barrett 2050</option>
|
||||
<option value="32002">Barrett 950</option>
|
||||
<option value="33001">ELAD FDM-DUO</option>
|
||||
|
|
4041
gui/src/index.html
4041
gui/src/index.html
File diff suppressed because it is too large
Load diff
|
@ -1,56 +1,82 @@
|
|||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self';">
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self';" />
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="../node_modules/bootstrap/dist/css/bootstrap.min.css"
|
||||
/>
|
||||
<link rel="stylesheet" type="text/css" href="styles.css" />
|
||||
<title>FreeDATA - Live Log</title>
|
||||
</head>
|
||||
<body>
|
||||
<!-- bootstrap -->
|
||||
<script src="../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<!-- chart.js -->
|
||||
|
||||
<nav class="navbar fixed-top bg-light">
|
||||
<div class="container-fluid">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="btn-check"
|
||||
id="enable_filter_info"
|
||||
autocomplete="off"
|
||||
checked
|
||||
/>
|
||||
<label class="btn btn-outline-info" for="enable_filter_info"
|
||||
>info</label
|
||||
>
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link rel="stylesheet" href="../node_modules/bootstrap/dist/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="styles.css" />
|
||||
<title>FreeDATA - Live Log</title>
|
||||
</head>
|
||||
<body>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="btn-check"
|
||||
id="enable_filter_debug"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<label class="btn btn-outline-primary" for="enable_filter_debug"
|
||||
>debug</label
|
||||
>
|
||||
|
||||
<!-- bootstrap -->
|
||||
<script src="../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<!-- chart.js -->
|
||||
<input
|
||||
type="checkbox"
|
||||
class="btn-check"
|
||||
id="enable_filter_warning"
|
||||
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>
|
||||
</nav>
|
||||
|
||||
<nav class="navbar fixed-top bg-light">
|
||||
<div class="container-fluid">
|
||||
<input 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">
|
||||
<label class="btn btn-outline-primary" for="enable_filter_debug">debug</label>
|
||||
|
||||
<input type="checkbox" class="btn-check" id="enable_filter_warning" 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>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="container-fluid mt-5">
|
||||
<div class="tableFixHead">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Timestamp</th>
|
||||
<th scope="col">Type</th>
|
||||
<th scope="col">Area</th>
|
||||
<th scope="col">Log entry</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="log">
|
||||
<!--
|
||||
<div class="container-fluid mt-5">
|
||||
<div class="tableFixHead">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Timestamp</th>
|
||||
<th scope="col">Type</th>
|
||||
<th scope="col">Area</th>
|
||||
<th scope="col">Log entry</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="log">
|
||||
<!--
|
||||
<tr>
|
||||
<th scope="row">1</th>
|
||||
<td>Mark</td>
|
||||
|
@ -58,9 +84,9 @@
|
|||
<td>@mdo</td>
|
||||
</tr>
|
||||
-->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self';">
|
||||
</head>
|
||||
<body style="overflow:hidden;">
|
||||
<img src="img/icon_cube_border.png" width="100%" height="100%">
|
||||
</body>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self';" />
|
||||
</head>
|
||||
<body style="overflow: hidden">
|
||||
<img src="img/icon_cube_border.png" width="100%" height="100%" />
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,22 +1,21 @@
|
|||
/* disable scrolling in main window */
|
||||
body {
|
||||
padding-right: 0px !important;
|
||||
overflow-y: hidden !important;
|
||||
overflow-x: hidden !important;
|
||||
|
||||
padding-right: 0px !important;
|
||||
overflow-y: hidden !important;
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
|
||||
/*Progress bars with centered text*/
|
||||
.progress {
|
||||
position: relative;
|
||||
transform: translateZ(0);
|
||||
position: relative;
|
||||
transform: translateZ(0);
|
||||
}
|
||||
|
||||
.progress span {
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: 100%;
|
||||
color: black;
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: 100%;
|
||||
color: black;
|
||||
}
|
||||
|
||||
/* smooth scrolling */
|
||||
|
@ -30,42 +29,41 @@ html {
|
|||
}
|
||||
|
||||
#chatModuleMessage {
|
||||
resize: none;
|
||||
border-radius:15px;
|
||||
resize: none;
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
#expand_textarea_label{
|
||||
border: 0;
|
||||
padding: 1px;
|
||||
#expand_textarea_label {
|
||||
border: 0;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
/* fixed border table header */
|
||||
.tableFixHead {
|
||||
overflow: auto;
|
||||
height: 90vh;
|
||||
overflow: auto;
|
||||
height: 90vh;
|
||||
}
|
||||
.tableFixHead thead th {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
}
|
||||
th, td {
|
||||
padding: 8px 16px;
|
||||
th,
|
||||
td {
|
||||
padding: 8px 16px;
|
||||
}
|
||||
|
||||
th {
|
||||
background:#eee;
|
||||
th {
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
|
||||
/* ------ emoji picker customization --------- */
|
||||
.picker {
|
||||
border-radius: 10px:
|
||||
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
/* force gpu usage
|
||||
|
@ -73,19 +71,19 @@ https://stackoverflow.com/questions/13176746/css-keyframe-animation-cpu-usage-is
|
|||
*/
|
||||
|
||||
.force-gpu {
|
||||
transform: translateZ(0);
|
||||
-webkit-transform: translateZ(0);
|
||||
-ms-transform: translateZ(0);
|
||||
will-change: transform;
|
||||
transform: translateZ(0);
|
||||
-webkit-transform: translateZ(0);
|
||||
-ms-transform: translateZ(0);
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
/* force disable transition effects
|
||||
https://stackoverflow.com/a/9622873
|
||||
*/
|
||||
.disable-effects {
|
||||
-webkit-transition: none;
|
||||
-moz-transition: none;
|
||||
-ms-transition: none;
|
||||
-o-transition: none;
|
||||
transition: none;
|
||||
-webkit-transition: none;
|
||||
-moz-transition: none;
|
||||
-ms-transition: none;
|
||||
-o-transition: none;
|
||||
transition: none;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,16 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="author" content="Jeppe Ledet-Pedersen">
|
||||
<title>Spectrum Plot</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="author" content="Jeppe Ledet-Pedersen" />
|
||||
<title>Spectrum Plot</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<canvas id="waterfall"></canvas>
|
||||
<script src="colormap.js"></script>
|
||||
<script src="spectrum.js"></script>
|
||||
<script src="script.js"></script>
|
||||
</body>
|
||||
<body>
|
||||
<canvas id="waterfall"></canvas>
|
||||
<script src="colormap.js"></script>
|
||||
<script src="spectrum.js"></script>
|
||||
<script src="script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
'use strict';
|
||||
"use strict";
|
||||
/*
|
||||
function connectWebSocket(spectrum) {
|
||||
// var ws = new WebSocket("ws://" + window.location.host + "/websocket");
|
||||
|
@ -34,32 +34,29 @@ function connectWebSocket(spectrum) {
|
|||
*/
|
||||
|
||||
function main() {
|
||||
// Create spectrum object on canvas with ID "waterfall"
|
||||
var spectrum = new Spectrum(
|
||||
"waterfall", {
|
||||
spectrumPercent: 20
|
||||
});
|
||||
// Create spectrum object on canvas with ID "waterfall"
|
||||
var spectrum = new Spectrum("waterfall", {
|
||||
spectrumPercent: 20,
|
||||
});
|
||||
|
||||
// Connect to websocket
|
||||
//connectWebSocket(spectrum);
|
||||
|
||||
|
||||
//spectrum.setCenterHz("2000");
|
||||
//spectrum.setSpanHz("1");
|
||||
// Connect to websocket
|
||||
//connectWebSocket(spectrum);
|
||||
|
||||
/*
|
||||
//spectrum.setCenterHz("2000");
|
||||
//spectrum.setSpanHz("1");
|
||||
|
||||
/*
|
||||
for (var i = 0; i < 1000; i++) {
|
||||
var randomstring = Math.floor(Math.random())
|
||||
spectrum.addData(randomstring.toString());
|
||||
// more statements
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// Bind keypress handler
|
||||
window.addEventListener("keydown", function (e) {
|
||||
spectrum.onKeypress(e);
|
||||
});
|
||||
// Bind keypress handler
|
||||
window.addEventListener("keydown", function (e) {
|
||||
spectrum.onKeypress(e);
|
||||
});
|
||||
}
|
||||
|
||||
window.onload = main;
|
||||
|
|
|
@ -36,13 +36,11 @@
|
|||
|
||||
var Waterfall, Rasterscan;
|
||||
|
||||
(function(){
|
||||
Waterfall = function(ipBufAry, w, h, dir, options)
|
||||
{
|
||||
var direction = (typeof(dir) === "string")? dir.toLowerCase() : "down";
|
||||
(function () {
|
||||
Waterfall = function (ipBufAry, w, h, dir, options) {
|
||||
var direction = typeof dir === "string" ? dir.toLowerCase() : "down";
|
||||
|
||||
switch (direction)
|
||||
{
|
||||
switch (direction) {
|
||||
case "up":
|
||||
return new Spectrogram(ipBufAry, w, h, "WF", false, true, options);
|
||||
case "down":
|
||||
|
@ -51,16 +49,14 @@ var Waterfall, Rasterscan;
|
|||
case "left":
|
||||
return new Spectrogram(ipBufAry, w, h, "WF", false, false, options);
|
||||
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)
|
||||
{
|
||||
const direction = (typeof(dir) === "string")? dir.toLowerCase() : "down";
|
||||
Rasterscan = function (ipBufAry, w, h, dir, options) {
|
||||
const direction = typeof dir === "string" ? dir.toLowerCase() : "down";
|
||||
|
||||
switch (direction)
|
||||
{
|
||||
switch (direction) {
|
||||
case "up":
|
||||
return new Spectrogram(ipBufAry, w, h, "RS", true, true, options);
|
||||
case "down":
|
||||
|
@ -69,28 +65,27 @@ var Waterfall, Rasterscan;
|
|||
case "left":
|
||||
return new Spectrogram(ipBufAry, w, h, "RS", false, false, options);
|
||||
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)
|
||||
{
|
||||
const opt = (typeof options === 'object')? options: {}; // avoid undeclared object errors
|
||||
let offScreenCtx; // offscreen canvas drawing context
|
||||
function Spectrogram(ipBufAry, w, h, sgMode, rhc, vert, options) {
|
||||
const opt = typeof options === "object" ? options : {}; // avoid undeclared object errors
|
||||
let offScreenCtx; // offscreen canvas drawing context
|
||||
const pxPerLine = w || 200;
|
||||
const lines = h || 200;
|
||||
let lineRate = 30; // requested line rate for dynamic waterfalls
|
||||
let interval = 0; // msec
|
||||
let lineRate = 30; // requested line rate for dynamic waterfalls
|
||||
let interval = 0; // msec
|
||||
let startOfs = 0;
|
||||
const lineBuf = new ArrayBuffer(pxPerLine * 4); // 1 line
|
||||
const lineBuf8 = new Uint8ClampedArray(lineBuf);
|
||||
const lineImgData = new ImageData(lineBuf8, pxPerLine, 1); // 1 line of canvas pixels
|
||||
let pageImgData; // lines * pxPerLine of canvas pixels
|
||||
let ipBuf8; // map input data to 0..255 unsigned bytes
|
||||
const lineImgData = new ImageData(lineBuf8, pxPerLine, 1); // 1 line of canvas pixels
|
||||
let pageImgData; // lines * pxPerLine of canvas pixels
|
||||
let ipBuf8; // map input data to 0..255 unsigned bytes
|
||||
const blankBuf = new ArrayBuffer(pxPerLine * 4); // 1 line
|
||||
const blankBuf8 = new Uint8ClampedArray(blankBuf);
|
||||
const blankImgData = new ImageData(blankBuf8, pxPerLine, 1); // 1 line of canvas pixels
|
||||
const clearBuf = new ArrayBuffer(pxPerLine * lines * 4); // fills with 0s ie. rgba 0,0,0,0 = transparent
|
||||
const blankImgData = new ImageData(blankBuf8, pxPerLine, 1); // 1 line of canvas pixels
|
||||
const clearBuf = new ArrayBuffer(pxPerLine * lines * 4); // fills with 0s ie. rgba 0,0,0,0 = transparent
|
||||
const clearBuf8 = new Uint8ClampedArray(clearBuf);
|
||||
let clearImgData;
|
||||
let nextLine = 0;
|
||||
|
@ -100,367 +95,513 @@ var Waterfall, Rasterscan;
|
|||
let sgStartTime = 0;
|
||||
|
||||
// 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],
|
||||
[ 0, 0, 143, 255], [ 0, 0, 147, 255], [ 0, 0, 151, 255], [ 0, 0, 155, 255],
|
||||
[ 0, 0, 159, 255], [ 0, 0, 163, 255], [ 0, 0, 167, 255], [ 0, 0, 171, 255],
|
||||
[ 0, 0, 175, 255], [ 0, 0, 179, 255], [ 0, 0, 183, 255], [ 0, 0, 187, 255],
|
||||
[ 0, 0, 191, 255], [ 0, 0, 195, 255], [ 0, 0, 199, 255], [ 0, 0, 203, 255],
|
||||
[ 0, 0, 207, 255], [ 0, 0, 211, 255], [ 0, 0, 215, 255], [ 0, 0, 219, 255],
|
||||
[ 0, 0, 223, 255], [ 0, 0, 227, 255], [ 0, 0, 231, 255], [ 0, 0, 235, 255],
|
||||
[ 0, 0, 239, 255], [ 0, 0, 243, 255], [ 0, 0, 247, 255], [ 0, 0, 251, 255],
|
||||
[ 0, 0, 255, 255], [ 0, 4, 255, 255], [ 0, 8, 255, 255], [ 0, 12, 255, 255],
|
||||
[ 0, 16, 255, 255], [ 0, 20, 255, 255], [ 0, 24, 255, 255], [ 0, 28, 255, 255],
|
||||
[ 0, 32, 255, 255], [ 0, 36, 255, 255], [ 0, 40, 255, 255], [ 0, 44, 255, 255],
|
||||
[ 0, 48, 255, 255], [ 0, 52, 255, 255], [ 0, 56, 255, 255], [ 0, 60, 255, 255],
|
||||
[ 0, 64, 255, 255], [ 0, 68, 255, 255], [ 0, 72, 255, 255], [ 0, 76, 255, 255],
|
||||
[ 0, 80, 255, 255], [ 0, 84, 255, 255], [ 0, 88, 255, 255], [ 0, 92, 255, 255],
|
||||
[ 0, 96, 255, 255], [ 0, 100, 255, 255], [ 0, 104, 255, 255], [ 0, 108, 255, 255],
|
||||
[ 0, 112, 255, 255], [ 0, 116, 255, 255], [ 0, 120, 255, 255], [ 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]];
|
||||
let colMap = [
|
||||
[0, 0, 128, 255],
|
||||
[0, 0, 131, 255],
|
||||
[0, 0, 135, 255],
|
||||
[0, 0, 139, 255],
|
||||
[0, 0, 143, 255],
|
||||
[0, 0, 147, 255],
|
||||
[0, 0, 151, 255],
|
||||
[0, 0, 155, 255],
|
||||
[0, 0, 159, 255],
|
||||
[0, 0, 163, 255],
|
||||
[0, 0, 167, 255],
|
||||
[0, 0, 171, 255],
|
||||
[0, 0, 175, 255],
|
||||
[0, 0, 179, 255],
|
||||
[0, 0, 183, 255],
|
||||
[0, 0, 187, 255],
|
||||
[0, 0, 191, 255],
|
||||
[0, 0, 195, 255],
|
||||
[0, 0, 199, 255],
|
||||
[0, 0, 203, 255],
|
||||
[0, 0, 207, 255],
|
||||
[0, 0, 211, 255],
|
||||
[0, 0, 215, 255],
|
||||
[0, 0, 219, 255],
|
||||
[0, 0, 223, 255],
|
||||
[0, 0, 227, 255],
|
||||
[0, 0, 231, 255],
|
||||
[0, 0, 235, 255],
|
||||
[0, 0, 239, 255],
|
||||
[0, 0, 243, 255],
|
||||
[0, 0, 247, 255],
|
||||
[0, 0, 251, 255],
|
||||
[0, 0, 255, 255],
|
||||
[0, 4, 255, 255],
|
||||
[0, 8, 255, 255],
|
||||
[0, 12, 255, 255],
|
||||
[0, 16, 255, 255],
|
||||
[0, 20, 255, 255],
|
||||
[0, 24, 255, 255],
|
||||
[0, 28, 255, 255],
|
||||
[0, 32, 255, 255],
|
||||
[0, 36, 255, 255],
|
||||
[0, 40, 255, 255],
|
||||
[0, 44, 255, 255],
|
||||
[0, 48, 255, 255],
|
||||
[0, 52, 255, 255],
|
||||
[0, 56, 255, 255],
|
||||
[0, 60, 255, 255],
|
||||
[0, 64, 255, 255],
|
||||
[0, 68, 255, 255],
|
||||
[0, 72, 255, 255],
|
||||
[0, 76, 255, 255],
|
||||
[0, 80, 255, 255],
|
||||
[0, 84, 255, 255],
|
||||
[0, 88, 255, 255],
|
||||
[0, 92, 255, 255],
|
||||
[0, 96, 255, 255],
|
||||
[0, 100, 255, 255],
|
||||
[0, 104, 255, 255],
|
||||
[0, 108, 255, 255],
|
||||
[0, 112, 255, 255],
|
||||
[0, 116, 255, 255],
|
||||
[0, 120, 255, 255],
|
||||
[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()
|
||||
{
|
||||
if ((vert && !rhc) || (!vert && rhc))
|
||||
{
|
||||
function incrLine() {
|
||||
if ((vert && !rhc) || (!vert && rhc)) {
|
||||
nextLine++;
|
||||
if (nextLine >= lines)
|
||||
{
|
||||
if (nextLine >= lines) {
|
||||
nextLine = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
nextLine--;
|
||||
if (nextLine < 0)
|
||||
{
|
||||
nextLine = lines-1;
|
||||
if (nextLine < 0) {
|
||||
nextLine = lines - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateWaterfall() // update dynamic waterfalls at a fixed rate
|
||||
{
|
||||
function updateWaterfall() {
|
||||
// update dynamic waterfalls at a fixed rate
|
||||
let sgDiff;
|
||||
|
||||
|
||||
// grab latest line of data, write it to off screen buffer, inc 'nextLine'
|
||||
sgNewLine();
|
||||
// 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
|
||||
sgTime += interval;
|
||||
sgDiff = (Date.now() - sgStartTime) - sgTime;
|
||||
if (running)
|
||||
{
|
||||
sgDiff = Date.now() - sgStartTime - sgTime;
|
||||
if (running) {
|
||||
timerID = setTimeout(updateWaterfall, interval - sgDiff);
|
||||
}
|
||||
}
|
||||
|
||||
function sgSetLineRate(newRate)
|
||||
{
|
||||
if (isNaN(newRate) || newRate > 50 || newRate < 0)
|
||||
{
|
||||
function sgSetLineRate(newRate) {
|
||||
if (isNaN(newRate) || newRate > 50 || newRate < 0) {
|
||||
console.error("invalid line rate [0 <= lineRate < 50 lines/sec]");
|
||||
// don't change the lineRate;
|
||||
}
|
||||
else if (newRate === 0) // static (one pass) raster
|
||||
{
|
||||
} else if (newRate === 0) {
|
||||
// static (one pass) raster
|
||||
lineRate = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
lineRate = newRate;
|
||||
interval = 1000/lineRate; // msec
|
||||
interval = 1000 / lineRate; // msec
|
||||
}
|
||||
}
|
||||
|
||||
this.setLineRate = sgSetLineRate;
|
||||
|
||||
function setProperty(propertyName, value)
|
||||
{
|
||||
if ((typeof propertyName !== "string")||(value === undefined)) // null is OK, forces default
|
||||
{
|
||||
function setProperty(propertyName, value) {
|
||||
if (typeof propertyName !== "string" || value === undefined) {
|
||||
// null is OK, forces default
|
||||
return;
|
||||
}
|
||||
switch (propertyName.toLowerCase())
|
||||
{
|
||||
switch (propertyName.toLowerCase()) {
|
||||
case "linerate":
|
||||
sgSetLineRate(value); // setLine does checks for number etc
|
||||
break;
|
||||
sgSetLineRate(value); // setLine does checks for number etc
|
||||
break;
|
||||
case "startbin":
|
||||
if (!isNaN(value) && value > 0)
|
||||
{
|
||||
if (!isNaN(value) && value > 0) {
|
||||
startOfs = value;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case "onscreenparentid":
|
||||
if (typeof value === "string" && document.getElementById(value))
|
||||
{
|
||||
if (typeof value === "string" && document.getElementById(value)) {
|
||||
demoCvsId = value;
|
||||
}
|
||||
break;
|
||||
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
|
||||
if (colMap.length<256) // fill out the remaining colors with last color
|
||||
{
|
||||
for (let i=colMap.length; i<256; i++)
|
||||
{
|
||||
colMap[i] = colMap[colMap.length-1];
|
||||
if (colMap.length < 256) {
|
||||
// fill out the remaining colors with last color
|
||||
for (let i = colMap.length; i < 256; i++) {
|
||||
colMap[i] = colMap[colMap.length - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function verticalNewLine()
|
||||
{
|
||||
|
||||
function verticalNewLine() {
|
||||
let tmpImgData, ipBuf8;
|
||||
|
||||
if (sgMode == "WF")
|
||||
{
|
||||
if (rhc)
|
||||
{
|
||||
if (sgMode == "WF") {
|
||||
if (rhc) {
|
||||
// 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
ipBuf8 = Uint8ClampedArray.from(ipBufAry[0]);
|
||||
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
|
||||
rgba = colMap[sigVal]; // array of rgba values
|
||||
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
|
||||
rgba = colMap[sigVal]; // array of rgba values
|
||||
// byte reverse so number aa bb gg rr
|
||||
lineBuf8[opIdx] = rgba[0]; // red
|
||||
lineBuf8[opIdx+1] = rgba[1]; // green
|
||||
lineBuf8[opIdx+2] = rgba[2]; // blue
|
||||
lineBuf8[opIdx+3] = rgba[3]; // alpha
|
||||
lineBuf8[opIdx] = rgba[0]; // red
|
||||
lineBuf8[opIdx + 1] = rgba[1]; // green
|
||||
lineBuf8[opIdx + 2] = rgba[2]; // blue
|
||||
lineBuf8[opIdx + 3] = rgba[3]; // alpha
|
||||
}
|
||||
offScreenCtx.putImageData(lineImgData, 0, nextLine);
|
||||
if (sgMode === "RS")
|
||||
{
|
||||
if (sgMode === "RS") {
|
||||
incrLine();
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function horizontalNewLine()
|
||||
{
|
||||
function horizontalNewLine() {
|
||||
let tmpImgData, ipBuf8;
|
||||
|
||||
if (sgMode == "WF")
|
||||
{
|
||||
if (rhc)
|
||||
{
|
||||
if (sgMode == "WF") {
|
||||
if (rhc) {
|
||||
// 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
// refresh the page image (it was just shifted)
|
||||
pageImgData = offScreenCtx.getImageData(0, 0, lines, pxPerLine);
|
||||
if (ipBufAry[0].constructor !== Uint8Array)
|
||||
{
|
||||
pageImgData = offScreenCtx.getImageData(0, 0, lines, pxPerLine);
|
||||
if (ipBufAry[0].constructor !== Uint8Array) {
|
||||
ipBuf8 = Uint8ClampedArray.from(ipBufAry[0]); // clamp input values to 0..255 range
|
||||
}
|
||||
else
|
||||
{
|
||||
ipBuf8 = ipBufAry[0]; // conversion already done
|
||||
} else {
|
||||
ipBuf8 = ipBufAry[0]; // conversion already done
|
||||
}
|
||||
|
||||
for (let sigVal, rgba, opIdx, ipIdx=0; ipIdx < pxPerLine; ipIdx++)
|
||||
{
|
||||
sigVal = ipBuf8[ipIdx+startOfs] || 0; // if input line too short add zeros
|
||||
rgba = colMap[sigVal]; // array of rgba values
|
||||
opIdx = 4*((pxPerLine-ipIdx-1)*lines+nextLine);
|
||||
for (let sigVal, rgba, opIdx, ipIdx = 0; ipIdx < pxPerLine; ipIdx++) {
|
||||
sigVal = ipBuf8[ipIdx + startOfs] || 0; // if input line too short add zeros
|
||||
rgba = colMap[sigVal]; // array of rgba values
|
||||
opIdx = 4 * ((pxPerLine - ipIdx - 1) * lines + nextLine);
|
||||
// byte reverse so number aa bb gg rr
|
||||
pageImgData.data[opIdx] = rgba[0]; // red
|
||||
pageImgData.data[opIdx+1] = rgba[1]; // green
|
||||
pageImgData.data[opIdx+2] = rgba[2]; // blue
|
||||
pageImgData.data[opIdx+3] = rgba[3]; // alpha
|
||||
pageImgData.data[opIdx] = rgba[0]; // red
|
||||
pageImgData.data[opIdx + 1] = rgba[1]; // green
|
||||
pageImgData.data[opIdx + 2] = rgba[2]; // blue
|
||||
pageImgData.data[opIdx + 3] = rgba[3]; // alpha
|
||||
}
|
||||
if (sgMode === "RS")
|
||||
{
|
||||
if (sgMode === "RS") {
|
||||
incrLine();
|
||||
// if not draw a white line in front of the current line to indicate new data point
|
||||
if (lineRate)
|
||||
{
|
||||
for (let j=0; j < pxPerLine; j++)
|
||||
{
|
||||
if (rhc)
|
||||
{
|
||||
opIdx = 4*(j*lines+nextLine);
|
||||
}
|
||||
else
|
||||
{
|
||||
opIdx = 4*((pxPerLine-j-1)*lines+nextLine);
|
||||
if (lineRate) {
|
||||
for (let j = 0; j < pxPerLine; j++) {
|
||||
if (rhc) {
|
||||
opIdx = 4 * (j * lines + nextLine);
|
||||
} else {
|
||||
opIdx = 4 * ((pxPerLine - j - 1) * lines + nextLine);
|
||||
}
|
||||
// byte reverse so number aa bb gg rr
|
||||
pageImgData.data[opIdx] = 255; // red
|
||||
pageImgData.data[opIdx+1] = 255; // green
|
||||
pageImgData.data[opIdx+2] = 255; // blue
|
||||
pageImgData.data[opIdx+3] = 255; // alpha
|
||||
pageImgData.data[opIdx] = 255; // red
|
||||
pageImgData.data[opIdx + 1] = 255; // green
|
||||
pageImgData.data[opIdx + 2] = 255; // blue
|
||||
pageImgData.data[opIdx + 3] = 255; // alpha
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
offScreenCtx.putImageData(pageImgData, 0, 0);
|
||||
};
|
||||
}
|
||||
|
||||
const sgNewLine = (vert)? verticalNewLine: horizontalNewLine; // function pointers
|
||||
const sgNewLine = vert ? verticalNewLine : horizontalNewLine; // function pointers
|
||||
|
||||
//===== set all the options ================
|
||||
for (let prop in opt)
|
||||
{
|
||||
//===== set all the options ================
|
||||
for (let prop in opt) {
|
||||
// check that this is opt's own property, not inherited from prototype
|
||||
if (opt.hasOwnProperty(prop))
|
||||
{
|
||||
if (opt.hasOwnProperty(prop)) {
|
||||
setProperty(prop, opt[prop]);
|
||||
}
|
||||
}
|
||||
|
||||
// ===== now make the exposed properties and methods ===============
|
||||
// ===== now make the exposed properties and methods ===============
|
||||
this.newLine = sgNewLine;
|
||||
|
||||
this.offScreenCvs = document.createElement("canvas");
|
||||
if (vert)
|
||||
{
|
||||
this.offScreenCvs.setAttribute('width', pxPerLine); // reset canvas pixels width
|
||||
this.offScreenCvs.setAttribute('height', lines); // don't use style for this
|
||||
if (vert) {
|
||||
this.offScreenCvs.setAttribute("width", pxPerLine); // reset canvas pixels width
|
||||
this.offScreenCvs.setAttribute("height", lines); // don't use style for this
|
||||
clearImgData = new ImageData(clearBuf8, pxPerLine, lines);
|
||||
}
|
||||
else // data written in columns
|
||||
{
|
||||
this.offScreenCvs.setAttribute('width', lines); // reset canvas pixels width
|
||||
this.offScreenCvs.setAttribute('height', pxPerLine); // don't use style for this
|
||||
} // data written in columns
|
||||
else {
|
||||
this.offScreenCvs.setAttribute("width", lines); // reset canvas pixels width
|
||||
this.offScreenCvs.setAttribute("height", pxPerLine); // don't use style for this
|
||||
clearImgData = new ImageData(clearBuf8, lines, pxPerLine);
|
||||
}
|
||||
offScreenCtx = this.offScreenCvs.getContext("2d");
|
||||
|
||||
this.clear = function()
|
||||
{
|
||||
this.clear = function () {
|
||||
offScreenCtx.putImageData(clearImgData, 0, 0);
|
||||
};
|
||||
|
||||
this.start = function()
|
||||
{
|
||||
sgStartTime = Date.now();
|
||||
this.start = function () {
|
||||
sgStartTime = Date.now();
|
||||
sgTime = 0;
|
||||
running = true;
|
||||
updateWaterfall(); // start the update loop
|
||||
updateWaterfall(); // start the update loop
|
||||
};
|
||||
|
||||
this.stop = function()
|
||||
{
|
||||
this.stop = function () {
|
||||
running = false;
|
||||
if (timerID)
|
||||
{
|
||||
if (timerID) {
|
||||
clearTimeout(timerID);
|
||||
}
|
||||
// reset where the next line is to be written
|
||||
if (sgMode === "RS")
|
||||
{
|
||||
if (vert)
|
||||
{
|
||||
nextLine = (rhc)? lines-1 : 0;
|
||||
if (sgMode === "RS") {
|
||||
if (vert) {
|
||||
nextLine = rhc ? lines - 1 : 0;
|
||||
} else {
|
||||
nextLine = rhc ? 0 : lines - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextLine = (rhc)? 0 : lines-1;
|
||||
}
|
||||
}
|
||||
else // WF
|
||||
{
|
||||
nextLine = (rhc)? 0 : lines-1;
|
||||
} // WF
|
||||
else {
|
||||
nextLine = rhc ? 0 : lines - 1;
|
||||
}
|
||||
};
|
||||
|
||||
// make a white line, it will show the input line for RS displays
|
||||
blankBuf8.fill(255);
|
||||
// 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
|
||||
clearBuf8[i] = colMap[0][0]; // red
|
||||
clearBuf8[i+1] = colMap[0][1]; // green
|
||||
clearBuf8[i+2] = colMap[0][2]; // blue
|
||||
clearBuf8[i+3] = colMap[0][3]; // alpha
|
||||
clearBuf8[i] = colMap[0][0]; // red
|
||||
clearBuf8[i + 1] = colMap[0][1]; // green
|
||||
clearBuf8[i + 2] = colMap[0][2]; // blue
|
||||
clearBuf8[i + 3] = colMap[0][3]; // alpha
|
||||
}
|
||||
// for diagnostics only
|
||||
if (typeof(demoCvsId) == "string")
|
||||
{
|
||||
document.getElementById(demoCvsId).appendChild(this.offScreenCvs);
|
||||
if (typeof demoCvsId == "string") {
|
||||
document.getElementById(demoCvsId).appendChild(this.offScreenCvs);
|
||||
}
|
||||
// initialize the direction and first line position
|
||||
this.stop();
|
||||
|
||||
// everything is set
|
||||
// everything is set
|
||||
// if dynamic, wait for the start or newLine methods to be called
|
||||
}
|
||||
}())
|
||||
}
|
||||
})();
|
||||
|
|
|
@ -4,82 +4,93 @@
|
|||
* See the LICENSE file for further details.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
Spectrum.prototype.squeeze = function(value, out_min, out_max) {
|
||||
if (value <= this.min_db)
|
||||
return out_min;
|
||||
else if (value >= this.max_db)
|
||||
return out_max;
|
||||
else
|
||||
return Math.round((value - this.min_db) / (this.max_db - this.min_db) * out_max);
|
||||
}
|
||||
Spectrum.prototype.squeeze = function (value, out_min, out_max) {
|
||||
if (value <= this.min_db) return out_min;
|
||||
else if (value >= this.max_db) return out_max;
|
||||
else
|
||||
return Math.round(
|
||||
((value - this.min_db) / (this.max_db - this.min_db)) * out_max
|
||||
);
|
||||
};
|
||||
|
||||
Spectrum.prototype.rowToImageData = function(bins) {
|
||||
for (var i = 0; i < this.imagedata.data.length; i += 4) {
|
||||
var cindex = this.squeeze(bins[i/4], 0, 255);
|
||||
var color = this.colormap[cindex];
|
||||
this.imagedata.data[i+0] = color[0];
|
||||
this.imagedata.data[i+1] = color[1];
|
||||
this.imagedata.data[i+2] = color[2];
|
||||
this.imagedata.data[i+3] = 255;
|
||||
}
|
||||
}
|
||||
Spectrum.prototype.rowToImageData = function (bins) {
|
||||
for (var i = 0; i < this.imagedata.data.length; i += 4) {
|
||||
var cindex = this.squeeze(bins[i / 4], 0, 255);
|
||||
var color = this.colormap[cindex];
|
||||
this.imagedata.data[i + 0] = color[0];
|
||||
this.imagedata.data[i + 1] = color[1];
|
||||
this.imagedata.data[i + 2] = color[2];
|
||||
this.imagedata.data[i + 3] = 255;
|
||||
}
|
||||
};
|
||||
|
||||
Spectrum.prototype.addWaterfallRow = function(bins) {
|
||||
// Shift waterfall 1 row down
|
||||
this.ctx_wf.drawImage(this.ctx_wf.canvas,
|
||||
0, 0, this.wf_size, this.wf_rows - 1,
|
||||
0, 1, this.wf_size, this.wf_rows - 1);
|
||||
Spectrum.prototype.addWaterfallRow = function (bins) {
|
||||
// Shift waterfall 1 row down
|
||||
this.ctx_wf.drawImage(
|
||||
this.ctx_wf.canvas,
|
||||
0,
|
||||
0,
|
||||
this.wf_size,
|
||||
this.wf_rows - 1,
|
||||
0,
|
||||
1,
|
||||
this.wf_size,
|
||||
this.wf_rows - 1
|
||||
);
|
||||
|
||||
// Draw new line on waterfall canvas
|
||||
this.rowToImageData(bins);
|
||||
this.ctx_wf.putImageData(this.imagedata, 0, 0);
|
||||
// Draw new line on waterfall canvas
|
||||
this.rowToImageData(bins);
|
||||
this.ctx_wf.putImageData(this.imagedata, 0, 0);
|
||||
|
||||
var width = this.ctx.canvas.width;
|
||||
var height = this.ctx.canvas.height;
|
||||
var width = this.ctx.canvas.width;
|
||||
var height = this.ctx.canvas.height;
|
||||
|
||||
// Copy scaled FFT canvas to screen. Only copy the number of rows that will
|
||||
// fit in waterfall area to avoid vertical scaling.
|
||||
this.ctx.imageSmoothingEnabled = false;
|
||||
var rows = Math.min(this.wf_rows, height - this.spectrumHeight);
|
||||
this.ctx.drawImage(this.ctx_wf.canvas,
|
||||
0, 0, this.wf_size, rows,
|
||||
0, this.spectrumHeight, width, height - this.spectrumHeight);
|
||||
}
|
||||
// Copy scaled FFT canvas to screen. Only copy the number of rows that will
|
||||
// fit in waterfall area to avoid vertical scaling.
|
||||
this.ctx.imageSmoothingEnabled = false;
|
||||
var rows = Math.min(this.wf_rows, height - this.spectrumHeight);
|
||||
this.ctx.drawImage(
|
||||
this.ctx_wf.canvas,
|
||||
0,
|
||||
0,
|
||||
this.wf_size,
|
||||
rows,
|
||||
0,
|
||||
this.spectrumHeight,
|
||||
width,
|
||||
height - this.spectrumHeight
|
||||
);
|
||||
};
|
||||
|
||||
Spectrum.prototype.drawFFT = function(bins) {
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(-1, this.spectrumHeight + 1);
|
||||
for (var i = 0; i < bins.length; i++) {
|
||||
var y = this.spectrumHeight - this.squeeze(bins[i], 0, this.spectrumHeight);
|
||||
if (y > this.spectrumHeight - 1)
|
||||
y = this.spectrumHeight + 1; // Hide underflow
|
||||
if (y < 0)
|
||||
y = 0;
|
||||
if (i == 0)
|
||||
this.ctx.lineTo(-1, y);
|
||||
this.ctx.lineTo(i, y);
|
||||
if (i == bins.length - 1)
|
||||
this.ctx.lineTo(this.wf_size + 1, y);
|
||||
}
|
||||
this.ctx.lineTo(this.wf_size + 1, this.spectrumHeight + 1);
|
||||
this.ctx.strokeStyle = "#fefefe";
|
||||
this.ctx.stroke();
|
||||
}
|
||||
Spectrum.prototype.drawFFT = function (bins) {
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(-1, this.spectrumHeight + 1);
|
||||
for (var i = 0; i < bins.length; i++) {
|
||||
var y = this.spectrumHeight - this.squeeze(bins[i], 0, this.spectrumHeight);
|
||||
if (y > this.spectrumHeight - 1) y = this.spectrumHeight + 1; // Hide underflow
|
||||
if (y < 0) y = 0;
|
||||
if (i == 0) this.ctx.lineTo(-1, y);
|
||||
this.ctx.lineTo(i, y);
|
||||
if (i == bins.length - 1) this.ctx.lineTo(this.wf_size + 1, y);
|
||||
}
|
||||
this.ctx.lineTo(this.wf_size + 1, this.spectrumHeight + 1);
|
||||
this.ctx.strokeStyle = "#fefefe";
|
||||
this.ctx.stroke();
|
||||
};
|
||||
|
||||
//Spectrum.prototype.drawSpectrum = function(bins) {
|
||||
Spectrum.prototype.drawSpectrum = function() {
|
||||
var width = this.ctx.canvas.width;
|
||||
var height = this.ctx.canvas.height;
|
||||
Spectrum.prototype.drawSpectrum = function () {
|
||||
var width = this.ctx.canvas.width;
|
||||
var height = this.ctx.canvas.height;
|
||||
|
||||
|
||||
// Modification by DJ2LS
|
||||
// Draw bandwidth lines
|
||||
// TODO: Math not correct. But a first attempt
|
||||
// it seems position is more or less equal to frequenzy by factor 10
|
||||
// eg. position 150 == 1500Hz
|
||||
/*
|
||||
// Modification by DJ2LS
|
||||
// Draw bandwidth lines
|
||||
// TODO: Math not correct. But a first attempt
|
||||
// it seems position is more or less equal to frequenzy by factor 10
|
||||
// eg. position 150 == 1500Hz
|
||||
/*
|
||||
// CENTER LINE
|
||||
this.ctx_wf.beginPath();
|
||||
this.ctx_wf.moveTo(150,0);
|
||||
|
@ -89,34 +100,33 @@ Spectrum.prototype.drawFFT = function(bins) {
|
|||
this.ctx_wf.stroke()
|
||||
*/
|
||||
|
||||
// 586Hz and 1700Hz LINES
|
||||
var linePositionLow = 121.6; //150 - bandwith/20
|
||||
var linePositionHigh = 178.4; //150 + bandwidth/20
|
||||
var linePositionLow2 = 65; //150 - bandwith/20
|
||||
var linePositionHigh2 = 235; //150 + bandwith/20
|
||||
this.ctx_wf.beginPath();
|
||||
this.ctx_wf.moveTo(linePositionLow,0);
|
||||
this.ctx_wf.lineTo(linePositionLow, height);
|
||||
this.ctx_wf.moveTo(linePositionHigh,0);
|
||||
this.ctx_wf.lineTo(linePositionHigh, height);
|
||||
this.ctx_wf.moveTo(linePositionLow2,0);
|
||||
this.ctx_wf.lineTo(linePositionLow2, height);
|
||||
this.ctx_wf.moveTo(linePositionHigh2,0);
|
||||
this.ctx_wf.lineTo(linePositionHigh2, height);
|
||||
this.ctx_wf.lineWidth = 1;
|
||||
this.ctx_wf.strokeStyle = '#C3C3C3';
|
||||
this.ctx_wf.stroke()
|
||||
// 586Hz and 1700Hz LINES
|
||||
var linePositionLow = 121.6; //150 - bandwith/20
|
||||
var linePositionHigh = 178.4; //150 + bandwidth/20
|
||||
var linePositionLow2 = 65; //150 - bandwith/20
|
||||
var linePositionHigh2 = 235; //150 + bandwith/20
|
||||
this.ctx_wf.beginPath();
|
||||
this.ctx_wf.moveTo(linePositionLow, 0);
|
||||
this.ctx_wf.lineTo(linePositionLow, height);
|
||||
this.ctx_wf.moveTo(linePositionHigh, 0);
|
||||
this.ctx_wf.lineTo(linePositionHigh, height);
|
||||
this.ctx_wf.moveTo(linePositionLow2, 0);
|
||||
this.ctx_wf.lineTo(linePositionLow2, height);
|
||||
this.ctx_wf.moveTo(linePositionHigh2, 0);
|
||||
this.ctx_wf.lineTo(linePositionHigh2, height);
|
||||
this.ctx_wf.lineWidth = 1;
|
||||
this.ctx_wf.strokeStyle = "#C3C3C3";
|
||||
this.ctx_wf.stroke();
|
||||
|
||||
// ---- END OF MODIFICATION ------
|
||||
// ---- END OF MODIFICATION ------
|
||||
|
||||
// Fill with black
|
||||
this.ctx.fillStyle = "white";
|
||||
this.ctx.fillRect(0, 0, width, height);
|
||||
|
||||
// Fill with black
|
||||
this.ctx.fillStyle = "white";
|
||||
this.ctx.fillRect(0, 0, width, height);
|
||||
|
||||
//Commenting out the remainder of this code, it's not needed and unused as of 6.9.11 and saves three if statements
|
||||
return;
|
||||
/*
|
||||
//Commenting out the remainder of this code, it's not needed and unused as of 6.9.11 and saves three if statements
|
||||
return;
|
||||
/*
|
||||
// FFT averaging
|
||||
if (this.averaging > 0) {
|
||||
if (!this.binsAverage || this.binsAverage.length != bins.length) {
|
||||
|
@ -170,309 +180,309 @@ Spectrum.prototype.drawFFT = function(bins) {
|
|||
// Copy axes from offscreen canvas
|
||||
this.ctx.drawImage(this.ctx_axes.canvas, 0, 0);
|
||||
*/
|
||||
}
|
||||
};
|
||||
|
||||
//Allow setting colormap
|
||||
Spectrum.prototype.setColorMap = function(index) {
|
||||
this.colormap = colormaps[index];
|
||||
}
|
||||
Spectrum.prototype.setColorMap = function (index) {
|
||||
this.colormap = colormaps[index];
|
||||
};
|
||||
|
||||
Spectrum.prototype.updateAxes = function() {
|
||||
var width = this.ctx_axes.canvas.width;
|
||||
var height = this.ctx_axes.canvas.height;
|
||||
Spectrum.prototype.updateAxes = function () {
|
||||
var width = this.ctx_axes.canvas.width;
|
||||
var height = this.ctx_axes.canvas.height;
|
||||
|
||||
// Clear axes canvas
|
||||
this.ctx_axes.clearRect(0, 0, width, height);
|
||||
// Clear axes canvas
|
||||
this.ctx_axes.clearRect(0, 0, width, height);
|
||||
|
||||
// Draw axes
|
||||
this.ctx_axes.font = "12px sans-serif";
|
||||
this.ctx_axes.fillStyle = "white";
|
||||
this.ctx_axes.textBaseline = "middle";
|
||||
// Draw axes
|
||||
this.ctx_axes.font = "12px sans-serif";
|
||||
this.ctx_axes.fillStyle = "white";
|
||||
this.ctx_axes.textBaseline = "middle";
|
||||
|
||||
this.ctx_axes.textAlign = "left";
|
||||
var step = 10;
|
||||
for (var i = this.min_db + 10; i <= this.max_db - 10; i += step) {
|
||||
var y = height - this.squeeze(i, 0, height);
|
||||
this.ctx_axes.fillText(i, 5, y);
|
||||
this.ctx_axes.textAlign = "left";
|
||||
var step = 10;
|
||||
for (var i = this.min_db + 10; i <= this.max_db - 10; i += step) {
|
||||
var y = height - this.squeeze(i, 0, height);
|
||||
this.ctx_axes.fillText(i, 5, y);
|
||||
|
||||
this.ctx_axes.beginPath();
|
||||
this.ctx_axes.moveTo(20, y);
|
||||
this.ctx_axes.lineTo(width, y);
|
||||
this.ctx_axes.strokeStyle = "rgba(200, 200, 200, 0.10)";
|
||||
this.ctx_axes.stroke();
|
||||
this.ctx_axes.beginPath();
|
||||
this.ctx_axes.moveTo(20, y);
|
||||
this.ctx_axes.lineTo(width, y);
|
||||
this.ctx_axes.strokeStyle = "rgba(200, 200, 200, 0.10)";
|
||||
this.ctx_axes.stroke();
|
||||
}
|
||||
|
||||
this.ctx_axes.textBaseline = "bottom";
|
||||
for (var i = 0; i < 11; i++) {
|
||||
var x = Math.round(width / 10) * i;
|
||||
|
||||
if (this.spanHz > 0) {
|
||||
var adjust = 0;
|
||||
if (i == 0) {
|
||||
this.ctx_axes.textAlign = "left";
|
||||
adjust = 3;
|
||||
} else if (i == 10) {
|
||||
this.ctx_axes.textAlign = "right";
|
||||
adjust = -3;
|
||||
} else {
|
||||
this.ctx_axes.textAlign = "center";
|
||||
}
|
||||
|
||||
var freq = this.centerHz + (this.spanHz / 10) * (i - 5);
|
||||
if (this.centerHz + this.spanHz > 1e6) freq = freq / 1e6 + "M";
|
||||
else if (this.centerHz + this.spanHz > 1e3) freq = freq / 1e3 + "k";
|
||||
this.ctx_axes.fillText(freq, x + adjust, height - 3);
|
||||
}
|
||||
|
||||
this.ctx_axes.textBaseline = "bottom";
|
||||
for (var i = 0; i < 11; i++) {
|
||||
var x = Math.round(width / 10) * i;
|
||||
this.ctx_axes.beginPath();
|
||||
this.ctx_axes.moveTo(x, 0);
|
||||
this.ctx_axes.lineTo(x, height);
|
||||
this.ctx_axes.strokeStyle = "rgba(200, 200, 200, 0.10)";
|
||||
this.ctx_axes.stroke();
|
||||
}
|
||||
};
|
||||
|
||||
if (this.spanHz > 0) {
|
||||
var adjust = 0;
|
||||
if (i == 0) {
|
||||
this.ctx_axes.textAlign = "left";
|
||||
adjust = 3;
|
||||
} else if (i == 10) {
|
||||
this.ctx_axes.textAlign = "right";
|
||||
adjust = -3;
|
||||
} else {
|
||||
this.ctx_axes.textAlign = "center";
|
||||
}
|
||||
|
||||
var freq = this.centerHz + this.spanHz / 10 * (i - 5);
|
||||
if (this.centerHz + this.spanHz > 1e6)
|
||||
freq = freq / 1e6 + "M";
|
||||
else if (this.centerHz + this.spanHz > 1e3)
|
||||
freq = freq / 1e3 + "k";
|
||||
this.ctx_axes.fillText(freq, x + adjust, height - 3);
|
||||
}
|
||||
|
||||
this.ctx_axes.beginPath();
|
||||
this.ctx_axes.moveTo(x, 0);
|
||||
this.ctx_axes.lineTo(x, height);
|
||||
this.ctx_axes.strokeStyle = "rgba(200, 200, 200, 0.10)";
|
||||
this.ctx_axes.stroke();
|
||||
Spectrum.prototype.addData = function (data) {
|
||||
if (!this.paused) {
|
||||
if (data.length != this.wf_size) {
|
||||
this.wf_size = data.length;
|
||||
this.ctx_wf.canvas.width = data.length;
|
||||
this.ctx_wf.fillStyle = "white";
|
||||
this.ctx_wf.fillRect(0, 0, this.wf.width, this.wf.height);
|
||||
this.imagedata = this.ctx_wf.createImageData(data.length, 1);
|
||||
}
|
||||
}
|
||||
//this.drawSpectrum(data);
|
||||
this.drawSpectrum();
|
||||
this.addWaterfallRow(data);
|
||||
this.resize();
|
||||
}
|
||||
};
|
||||
|
||||
Spectrum.prototype.addData = function(data) {
|
||||
if (!this.paused) {
|
||||
if (data.length != this.wf_size) {
|
||||
this.wf_size = data.length;
|
||||
this.ctx_wf.canvas.width = data.length;
|
||||
this.ctx_wf.fillStyle = "white";
|
||||
this.ctx_wf.fillRect(0, 0, this.wf.width, this.wf.height);
|
||||
this.imagedata = this.ctx_wf.createImageData(data.length, 1);
|
||||
}
|
||||
//this.drawSpectrum(data);
|
||||
this.drawSpectrum();
|
||||
this.addWaterfallRow(data);
|
||||
this.resize();
|
||||
}
|
||||
}
|
||||
Spectrum.prototype.updateSpectrumRatio = function () {
|
||||
this.spectrumHeight = Math.round(
|
||||
(this.canvas.height * this.spectrumPercent) / 100.0
|
||||
);
|
||||
|
||||
Spectrum.prototype.updateSpectrumRatio = function() {
|
||||
this.spectrumHeight = Math.round(this.canvas.height * this.spectrumPercent / 100.0);
|
||||
this.gradient = this.ctx.createLinearGradient(0, 0, 0, this.spectrumHeight);
|
||||
for (var i = 0; i < this.colormap.length; i++) {
|
||||
var c = this.colormap[this.colormap.length - 1 - i];
|
||||
this.gradient.addColorStop(
|
||||
i / this.colormap.length,
|
||||
"rgba(" + c[0] + "," + c[1] + "," + c[2] + ", 1.0)"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
this.gradient = this.ctx.createLinearGradient(0, 0, 0, this.spectrumHeight);
|
||||
for (var i = 0; i < this.colormap.length; i++) {
|
||||
var c = this.colormap[this.colormap.length - 1 - i];
|
||||
this.gradient.addColorStop(i / this.colormap.length,
|
||||
"rgba(" + c[0] + "," + c[1] + "," + c[2] + ", 1.0)");
|
||||
}
|
||||
}
|
||||
Spectrum.prototype.resize = function () {
|
||||
var width = this.canvas.clientWidth;
|
||||
var height = this.canvas.clientHeight;
|
||||
|
||||
Spectrum.prototype.resize = function() {
|
||||
var width = this.canvas.clientWidth;
|
||||
var height = this.canvas.clientHeight;
|
||||
|
||||
if (this.canvas.width != width ||
|
||||
this.canvas.height != height) {
|
||||
this.canvas.width = width;
|
||||
this.canvas.height = height;
|
||||
this.updateSpectrumRatio();
|
||||
}
|
||||
|
||||
if (this.axes.width != width ||
|
||||
this.axes.height != this.spectrumHeight) {
|
||||
this.axes.width = width;
|
||||
this.axes.height = this.spectrumHeight;
|
||||
this.updateAxes();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Spectrum.prototype.setSpectrumPercent = function(percent) {
|
||||
if (percent >= 0 && percent <= 100) {
|
||||
this.spectrumPercent = percent;
|
||||
this.updateSpectrumRatio();
|
||||
}
|
||||
}
|
||||
|
||||
Spectrum.prototype.incrementSpectrumPercent = function() {
|
||||
if (this.spectrumPercent + this.spectrumPercentStep <= 100) {
|
||||
this.setSpectrumPercent(this.spectrumPercent + this.spectrumPercentStep);
|
||||
}
|
||||
}
|
||||
|
||||
Spectrum.prototype.decrementSpectrumPercent = function() {
|
||||
if (this.spectrumPercent - this.spectrumPercentStep >= 0) {
|
||||
this.setSpectrumPercent(this.spectrumPercent - this.spectrumPercentStep);
|
||||
}
|
||||
}
|
||||
|
||||
Spectrum.prototype.toggleColor = function() {
|
||||
this.colorindex++;
|
||||
if (this.colorindex >= colormaps.length)
|
||||
this.colorindex = 0;
|
||||
this.colormap = colormaps[this.colorindex];
|
||||
if (this.canvas.width != width || this.canvas.height != height) {
|
||||
this.canvas.width = width;
|
||||
this.canvas.height = height;
|
||||
this.updateSpectrumRatio();
|
||||
}
|
||||
}
|
||||
|
||||
Spectrum.prototype.setRange = function(min_db, max_db) {
|
||||
this.min_db = min_db;
|
||||
this.max_db = max_db;
|
||||
if (this.axes.width != width || this.axes.height != this.spectrumHeight) {
|
||||
this.axes.width = width;
|
||||
this.axes.height = this.spectrumHeight;
|
||||
this.updateAxes();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Spectrum.prototype.rangeUp = function() {
|
||||
this.setRange(this.min_db - 5, this.max_db - 5);
|
||||
}
|
||||
Spectrum.prototype.setSpectrumPercent = function (percent) {
|
||||
if (percent >= 0 && percent <= 100) {
|
||||
this.spectrumPercent = percent;
|
||||
this.updateSpectrumRatio();
|
||||
}
|
||||
};
|
||||
|
||||
Spectrum.prototype.rangeDown = function() {
|
||||
this.setRange(this.min_db + 5, this.max_db + 5);
|
||||
}
|
||||
Spectrum.prototype.incrementSpectrumPercent = function () {
|
||||
if (this.spectrumPercent + this.spectrumPercentStep <= 100) {
|
||||
this.setSpectrumPercent(this.spectrumPercent + this.spectrumPercentStep);
|
||||
}
|
||||
};
|
||||
|
||||
Spectrum.prototype.rangeIncrease = function() {
|
||||
this.setRange(this.min_db - 5, this.max_db + 5);
|
||||
}
|
||||
Spectrum.prototype.decrementSpectrumPercent = function () {
|
||||
if (this.spectrumPercent - this.spectrumPercentStep >= 0) {
|
||||
this.setSpectrumPercent(this.spectrumPercent - this.spectrumPercentStep);
|
||||
}
|
||||
};
|
||||
|
||||
Spectrum.prototype.rangeDecrease = function() {
|
||||
if (this.max_db - this.min_db > 10)
|
||||
this.setRange(this.min_db + 5, this.max_db - 5);
|
||||
}
|
||||
Spectrum.prototype.toggleColor = function () {
|
||||
this.colorindex++;
|
||||
if (this.colorindex >= colormaps.length) this.colorindex = 0;
|
||||
this.colormap = colormaps[this.colorindex];
|
||||
this.updateSpectrumRatio();
|
||||
};
|
||||
|
||||
Spectrum.prototype.setCenterHz = function(hz) {
|
||||
this.centerHz = hz;
|
||||
this.updateAxes();
|
||||
}
|
||||
Spectrum.prototype.setRange = function (min_db, max_db) {
|
||||
this.min_db = min_db;
|
||||
this.max_db = max_db;
|
||||
this.updateAxes();
|
||||
};
|
||||
|
||||
Spectrum.prototype.setSpanHz = function(hz) {
|
||||
this.spanHz = hz;
|
||||
this.updateAxes();
|
||||
}
|
||||
Spectrum.prototype.rangeUp = function () {
|
||||
this.setRange(this.min_db - 5, this.max_db - 5);
|
||||
};
|
||||
|
||||
Spectrum.prototype.setAveraging = function(num) {
|
||||
if (num >= 0) {
|
||||
this.averaging = num;
|
||||
this.alpha = 2 / (this.averaging + 1)
|
||||
Spectrum.prototype.rangeDown = function () {
|
||||
this.setRange(this.min_db + 5, this.max_db + 5);
|
||||
};
|
||||
|
||||
Spectrum.prototype.rangeIncrease = function () {
|
||||
this.setRange(this.min_db - 5, this.max_db + 5);
|
||||
};
|
||||
|
||||
Spectrum.prototype.rangeDecrease = function () {
|
||||
if (this.max_db - this.min_db > 10)
|
||||
this.setRange(this.min_db + 5, this.max_db - 5);
|
||||
};
|
||||
|
||||
Spectrum.prototype.setCenterHz = function (hz) {
|
||||
this.centerHz = hz;
|
||||
this.updateAxes();
|
||||
};
|
||||
|
||||
Spectrum.prototype.setSpanHz = function (hz) {
|
||||
this.spanHz = hz;
|
||||
this.updateAxes();
|
||||
};
|
||||
|
||||
Spectrum.prototype.setAveraging = function (num) {
|
||||
if (num >= 0) {
|
||||
this.averaging = num;
|
||||
this.alpha = 2 / (this.averaging + 1);
|
||||
}
|
||||
};
|
||||
|
||||
Spectrum.prototype.incrementAveraging = function () {
|
||||
this.setAveraging(this.averaging + 1);
|
||||
};
|
||||
|
||||
Spectrum.prototype.decrementAveraging = function () {
|
||||
if (this.averaging > 0) {
|
||||
this.setAveraging(this.averaging - 1);
|
||||
}
|
||||
};
|
||||
|
||||
Spectrum.prototype.setPaused = function (paused) {
|
||||
this.paused = paused;
|
||||
};
|
||||
|
||||
Spectrum.prototype.togglePaused = function () {
|
||||
this.setPaused(!this.paused);
|
||||
};
|
||||
|
||||
Spectrum.prototype.setMaxHold = function (maxhold) {
|
||||
this.maxHold = maxhold;
|
||||
this.binsMax = undefined;
|
||||
};
|
||||
|
||||
Spectrum.prototype.toggleMaxHold = function () {
|
||||
this.setMaxHold(!this.maxHold);
|
||||
};
|
||||
|
||||
Spectrum.prototype.toggleFullscreen = function () {
|
||||
if (!this.fullscreen) {
|
||||
if (this.canvas.requestFullscreen) {
|
||||
this.canvas.requestFullscreen();
|
||||
} else if (this.canvas.mozRequestFullScreen) {
|
||||
this.canvas.mozRequestFullScreen();
|
||||
} else if (this.canvas.webkitRequestFullscreen) {
|
||||
this.canvas.webkitRequestFullscreen();
|
||||
} else if (this.canvas.msRequestFullscreen) {
|
||||
this.canvas.msRequestFullscreen();
|
||||
}
|
||||
}
|
||||
|
||||
Spectrum.prototype.incrementAveraging = function() {
|
||||
this.setAveraging(this.averaging + 1);
|
||||
}
|
||||
|
||||
Spectrum.prototype.decrementAveraging = function() {
|
||||
if (this.averaging > 0) {
|
||||
this.setAveraging(this.averaging - 1);
|
||||
this.fullscreen = true;
|
||||
} else {
|
||||
if (document.exitFullscreen) {
|
||||
document.exitFullscreen();
|
||||
} else if (document.mozCancelFullScreen) {
|
||||
document.mozCancelFullScreen();
|
||||
} else if (document.webkitExitFullscreen) {
|
||||
document.webkitExitFullscreen();
|
||||
} else if (document.msExitFullscreen) {
|
||||
document.msExitFullscreen();
|
||||
}
|
||||
}
|
||||
this.fullscreen = false;
|
||||
}
|
||||
};
|
||||
|
||||
Spectrum.prototype.setPaused = function(paused) {
|
||||
this.paused = paused;
|
||||
}
|
||||
|
||||
Spectrum.prototype.togglePaused = function() {
|
||||
this.setPaused(!this.paused);
|
||||
}
|
||||
|
||||
Spectrum.prototype.setMaxHold = function(maxhold) {
|
||||
this.maxHold = maxhold;
|
||||
this.binsMax = undefined;
|
||||
}
|
||||
|
||||
Spectrum.prototype.toggleMaxHold = function() {
|
||||
this.setMaxHold(!this.maxHold);
|
||||
}
|
||||
|
||||
Spectrum.prototype.toggleFullscreen = function() {
|
||||
if (!this.fullscreen) {
|
||||
if (this.canvas.requestFullscreen) {
|
||||
this.canvas.requestFullscreen();
|
||||
} else if (this.canvas.mozRequestFullScreen) {
|
||||
this.canvas.mozRequestFullScreen();
|
||||
} else if (this.canvas.webkitRequestFullscreen) {
|
||||
this.canvas.webkitRequestFullscreen();
|
||||
} else if (this.canvas.msRequestFullscreen) {
|
||||
this.canvas.msRequestFullscreen();
|
||||
}
|
||||
this.fullscreen = true;
|
||||
} else {
|
||||
if (document.exitFullscreen) {
|
||||
document.exitFullscreen();
|
||||
} else if (document.mozCancelFullScreen) {
|
||||
document.mozCancelFullScreen();
|
||||
} else if (document.webkitExitFullscreen) {
|
||||
document.webkitExitFullscreen();
|
||||
} else if (document.msExitFullscreen) {
|
||||
document.msExitFullscreen();
|
||||
}
|
||||
this.fullscreen = false;
|
||||
}
|
||||
}
|
||||
|
||||
Spectrum.prototype.onKeypress = function(e) {
|
||||
if (e.key == " ") {
|
||||
this.togglePaused();
|
||||
} else if (e.key == "f") {
|
||||
this.toggleFullscreen();
|
||||
} else if (e.key == "c") {
|
||||
this.toggleColor();
|
||||
} else if (e.key == "ArrowUp") {
|
||||
this.rangeUp();
|
||||
} else if (e.key == "ArrowDown") {
|
||||
this.rangeDown();
|
||||
} else if (e.key == "ArrowLeft") {
|
||||
this.rangeDecrease();
|
||||
} else if (e.key == "ArrowRight") {
|
||||
this.rangeIncrease();
|
||||
} else if (e.key == "s") {
|
||||
this.incrementSpectrumPercent();
|
||||
} else if (e.key == "w") {
|
||||
this.decrementSpectrumPercent();
|
||||
} else if (e.key == "+") {
|
||||
this.incrementAveraging();
|
||||
} else if (e.key == "-") {
|
||||
this.decrementAveraging();
|
||||
} else if (e.key == "m") {
|
||||
this.toggleMaxHold();
|
||||
}
|
||||
}
|
||||
Spectrum.prototype.onKeypress = function (e) {
|
||||
if (e.key == " ") {
|
||||
this.togglePaused();
|
||||
} else if (e.key == "f") {
|
||||
this.toggleFullscreen();
|
||||
} else if (e.key == "c") {
|
||||
this.toggleColor();
|
||||
} else if (e.key == "ArrowUp") {
|
||||
this.rangeUp();
|
||||
} else if (e.key == "ArrowDown") {
|
||||
this.rangeDown();
|
||||
} else if (e.key == "ArrowLeft") {
|
||||
this.rangeDecrease();
|
||||
} else if (e.key == "ArrowRight") {
|
||||
this.rangeIncrease();
|
||||
} else if (e.key == "s") {
|
||||
this.incrementSpectrumPercent();
|
||||
} else if (e.key == "w") {
|
||||
this.decrementSpectrumPercent();
|
||||
} else if (e.key == "+") {
|
||||
this.incrementAveraging();
|
||||
} else if (e.key == "-") {
|
||||
this.decrementAveraging();
|
||||
} else if (e.key == "m") {
|
||||
this.toggleMaxHold();
|
||||
}
|
||||
};
|
||||
|
||||
function Spectrum(id, options) {
|
||||
// Handle options
|
||||
this.centerHz = (options && options.centerHz) ? options.centerHz : 1500;
|
||||
this.spanHz = (options && options.spanHz) ? options.spanHz : 0;
|
||||
this.wf_size = (options && options.wf_size) ? options.wf_size : 0;
|
||||
this.wf_rows = (options && options.wf_rows) ? options.wf_rows : 1024;
|
||||
this.spectrumPercent = (options && options.spectrumPercent) ? options.spectrumPercent : 0;
|
||||
this.spectrumPercentStep = (options && options.spectrumPercentStep) ? options.spectrumPercentStep : 0;
|
||||
this.averaging = (options && options.averaging) ? options.averaging : 0;
|
||||
this.maxHold = (options && options.maxHold) ? options.maxHold : false;
|
||||
// Handle options
|
||||
this.centerHz = options && options.centerHz ? options.centerHz : 1500;
|
||||
this.spanHz = options && options.spanHz ? options.spanHz : 0;
|
||||
this.wf_size = options && options.wf_size ? options.wf_size : 0;
|
||||
this.wf_rows = options && options.wf_rows ? options.wf_rows : 1024;
|
||||
this.spectrumPercent =
|
||||
options && options.spectrumPercent ? options.spectrumPercent : 0;
|
||||
this.spectrumPercentStep =
|
||||
options && options.spectrumPercentStep ? options.spectrumPercentStep : 0;
|
||||
this.averaging = options && options.averaging ? options.averaging : 0;
|
||||
this.maxHold = options && options.maxHold ? options.maxHold : false;
|
||||
|
||||
// Setup state
|
||||
this.paused = false;
|
||||
this.fullscreen = false;
|
||||
this.min_db = 0;
|
||||
this.max_db = 70;
|
||||
this.spectrumHeight = 0;
|
||||
// Setup state
|
||||
this.paused = false;
|
||||
this.fullscreen = false;
|
||||
this.min_db = 0;
|
||||
this.max_db = 70;
|
||||
this.spectrumHeight = 0;
|
||||
|
||||
// Colors
|
||||
this.colorindex = 0;
|
||||
this.colormap = colormaps[2];
|
||||
// Colors
|
||||
this.colorindex = 0;
|
||||
this.colormap = colormaps[2];
|
||||
|
||||
// Create main canvas and adjust dimensions to match actual
|
||||
this.canvas = document.getElementById(id);
|
||||
this.canvas.height = this.canvas.clientHeight;
|
||||
this.canvas.width = this.canvas.clientWidth;
|
||||
this.ctx = this.canvas.getContext("2d");
|
||||
this.ctx.fillStyle = "white";
|
||||
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
||||
// Create main canvas and adjust dimensions to match actual
|
||||
this.canvas = document.getElementById(id);
|
||||
this.canvas.height = this.canvas.clientHeight;
|
||||
this.canvas.width = this.canvas.clientWidth;
|
||||
this.ctx = this.canvas.getContext("2d");
|
||||
this.ctx.fillStyle = "white";
|
||||
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
||||
|
||||
// Create offscreen canvas for axes
|
||||
this.axes = document.createElement("canvas");
|
||||
this.axes.height = 1; // Updated later
|
||||
this.axes.width = this.canvas.width;
|
||||
this.ctx_axes = this.axes.getContext("2d");
|
||||
// Create offscreen canvas for axes
|
||||
this.axes = document.createElement("canvas");
|
||||
this.axes.height = 1; // Updated later
|
||||
this.axes.width = this.canvas.width;
|
||||
this.ctx_axes = this.axes.getContext("2d");
|
||||
|
||||
// Create offscreen canvas for waterfall
|
||||
this.wf = document.createElement("canvas");
|
||||
this.wf.height = this.wf_rows;
|
||||
this.wf.width = this.wf_size;
|
||||
this.ctx_wf = this.wf.getContext("2d");
|
||||
// Create offscreen canvas for waterfall
|
||||
this.wf = document.createElement("canvas");
|
||||
this.wf.height = this.wf_rows;
|
||||
this.wf.width = this.wf_size;
|
||||
this.ctx_wf = this.wf.getContext("2d");
|
||||
|
||||
// Trigger first render
|
||||
this.setAveraging(this.averaging);
|
||||
this.updateSpectrumRatio();
|
||||
this.resize();
|
||||
// Trigger first render
|
||||
this.setAveraging(this.averaging);
|
||||
this.updateSpectrumRatio();
|
||||
this.resize();
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
html, body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0px;
|
||||
html,
|
||||
body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
#waterfall {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
|
||||
# FreeDV-JATE [Just Another TNC Experiment]
|
||||
|
||||
## 002_HIGHSNR_PING_PONG
|
||||
|
||||
### INSTALL TEST SUITE
|
||||
|
||||
#### Install prerequierements
|
||||
|
||||
```
|
||||
sudo apt update
|
||||
sudo apt upgrade
|
||||
|
@ -15,41 +16,41 @@ pip3 install threading
|
|||
|
||||
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
|
||||
|
||||
```
|
||||
wget https://raw.githubusercontent.com/DJ2LS/FreeDV-JATE/002_HIGHSNR_PING_PONG/install_test_suite.sh
|
||||
chmod +x install_test_suite.sh
|
||||
./install_test_suite.sh
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 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
|
||||
|
||||
#### Create audio sinkhole and subdevices
|
||||
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
|
||||
#### Create audio sinkhole and subdevices
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
check if devices have been created
|
||||
|
||||
|
||||
|
||||
aplay -l
|
||||
|
||||
Output should be like this:
|
||||
|
||||
```
|
||||
Karte 0: Intel [HDA Intel], Gerät 0: Generic Analog [Generic Analog]
|
||||
Sub-Geräte: 1/1
|
||||
|
@ -71,10 +72,13 @@ Output should be like this:
|
|||
### Run tests:
|
||||
|
||||
#### Terminal 1: Ping
|
||||
|
||||
```
|
||||
python3 PING.py --txmode 12 --rxmode 14 --audioinput 2 --audiooutput 2 --frames 1 --bursts 2
|
||||
```
|
||||
|
||||
Output
|
||||
|
||||
```
|
||||
BURSTS: 2 FRAMES: 1
|
||||
-----------------------------------------------------------------
|
||||
|
@ -86,10 +90,13 @@ RX | PONG | BURST [2/2] FRAME [1/1]
|
|||
```
|
||||
|
||||
#### Terminal 2: Pong
|
||||
|
||||
```
|
||||
python3 PONG.py --txmode 14 --rxmode 12 --audioinput 2 --audiooutput 2
|
||||
```
|
||||
|
||||
Output
|
||||
|
||||
```
|
||||
RX | BURST [1/2] FRAME [1/1] >>> SENDING PONG
|
||||
RX | BURST [2/2] FRAME [1/1] >>> SENDING PONG
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
# Unit Test Menu
|
||||
|
||||
The following `CTest` tests cover some TNC functionality and the interface to codec2:
|
||||
|
||||
1. Name: `audio_buffer`
|
||||
Tests the thread safety of the audio buffer routines.
|
||||
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
|
||||
kernel module to be installed. They also do not perform reliably. These tests are slowly being
|
||||
replaced with equivalent pipeline-compatible tests.
|
||||
|
||||
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.
|
||||
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_outside`
|
||||
|
||||
|
||||
# Instructions
|
||||
|
||||
1. Install:
|
||||
|
@ -57,6 +57,7 @@ replaced with equivalent pipeline-compatible tests.
|
|||
cmake -DCODEC2_BUILD_DIR=$HOME/codec2/build_linux ..
|
||||
```
|
||||
2. List available tests:
|
||||
|
||||
```
|
||||
ctest -N
|
||||
Test project /home/david/FreeDATA/build
|
||||
|
@ -65,6 +66,7 @@ replaced with equivalent pipeline-compatible tests.
|
|||
|
||||
Total Tests: 2
|
||||
```
|
||||
|
||||
3. Run tests:
|
||||
```
|
||||
ctest --output-on-failure
|
||||
|
@ -78,7 +80,6 @@ replaced with equivalent pipeline-compatible tests.
|
|||
ctest -V
|
||||
```
|
||||
|
||||
|
||||
# 001_HIGHSNR_STDIO_AUDIO TEST SUITE
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
|
||||
### 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.
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
1. Check if devices have been created
|
||||
|
||||
```
|
||||
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:
|
||||
|
||||
```
|
||||
python3 util_rx.py --list
|
||||
<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: 7 Loopback: PCM (hw:2,1)
|
||||
```
|
||||
|
||||
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:
|
||||
```
|
||||
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
|
||||
```
|
||||
|
|
|
@ -4,20 +4,20 @@ tncport = 3000
|
|||
|
||||
[STATION]
|
||||
#station settings
|
||||
mycall = DJ2LS-4
|
||||
mygrid = JN48cs
|
||||
ssid_list = [0,1,2,3,4,5]
|
||||
mycall = DJ2LS-9
|
||||
mygrid = JN12AA
|
||||
ssid_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
|
||||
[AUDIO]
|
||||
#audio settings
|
||||
rx = hw:2,0
|
||||
tx = USB Audio CODEC
|
||||
txaudiolevel = 120
|
||||
rx = 0
|
||||
tx = 2
|
||||
txaudiolevel = 78
|
||||
auto_tune = False
|
||||
|
||||
[RADIO]
|
||||
#radio settings
|
||||
radiocontrol = rigctld
|
||||
radiocontrol = disabled
|
||||
rigctld_ip = 127.0.0.1
|
||||
rigctld_port = 4532
|
||||
|
||||
|
@ -30,5 +30,6 @@ fmin = -50.0
|
|||
fmax = 50.0
|
||||
qrv = True
|
||||
rxbuffersize = 16
|
||||
explorer = False
|
||||
explorer = True
|
||||
stats = False
|
||||
|
||||
|
|
|
@ -190,6 +190,8 @@ class DAEMON:
|
|||
# hamlib_version = rig.hamlib_version
|
||||
|
||||
hamlib.set_ptt(True)
|
||||
#Allow a little time for network based rig to register PTT is active
|
||||
time.sleep(.250);
|
||||
if hamlib.get_ptt():
|
||||
self.log.info("[DMN] Hamlib PTT", status="SUCCESS")
|
||||
response = {"command": "test_hamlib", "result": "SUCCESS"}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
# PyAudio
|
||||
## downloaded from
|
||||
|
||||
## downloaded from
|
||||
|
||||
https://www.lfd.uci.edu/~gohlke/pythonlibs/#pyaudio
|
||||
|
|
Loading…
Reference in a new issue