FreeDATA/gui/daemon.js
2023-07-05 16:43:56 +00:00

351 lines
8.9 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.');
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,
tx_delay,
tci_ip,
tci_port,
enable_mesh,
) {
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,
tx_delay: tx_delay,
tci_ip: tci_ip,
tci_port: tci_port,
enable_mesh: enable_mesh,
},
],
});
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();
});