FreeDATA/gui/daemon.js
2023-02-05 12:54:23 -05:00

323 lines
9.5 KiB
JavaScript

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 configFolder = path.join(appDataFolder, "FreeDATA");
var configPath = path.join(configFolder, 'config.json')
const config = require(configPath);
var daemon = new net.Socket();
var socketchunk = ''; // Current message, per connection.
// global to keep track of daemon connection error emissions
var daemonShowConnectStateError = 1
// global for storing ip information
var daemon_port = config.daemon_port;
var daemon_host = config.daemon_host;
setTimeout(connectDAEMON, 500)
function connectDAEMON() {
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)
}
//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);
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);
});
/*
client.on('close', function(data) {
console.log(' TNC connection closed');
setTimeout(connectTNC, 2000)
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) {
// 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 == 'opening') {
//uiMain.setDAEMONconnection('opening')
}
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) {
/*
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
// 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 = '';
}
});
function hexToBytes(hex) {
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)
}
// 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
}]
})
daemonLog.debug(json_command);
writeDaemonCommand(json_command)
}
// STOP TNC
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)
}
//Save myCall
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)
}
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();
});