refactor, added README

This commit is contained in:
DELL4 2024-09-12 02:00:26 +02:00
parent 352174cd83
commit 221b739774
11 changed files with 105 additions and 43 deletions

3
.gitignore vendored
View File

@ -1,3 +1,4 @@
node_modules/
apikey.txt
ptt_daemon
ptt_daemon
config.js

View File

@ -8,7 +8,7 @@ function ClientQuery() {
this.onMessage = function (data) { };
this.log = function (msg) {
if (!this.debug) { console.log(msg) }
if (!this.debug) { console.log('TS3:', msg) }
}
this.parse = function (res) {
@ -42,13 +42,18 @@ function ClientQuery() {
}.bind(this)
this.notifyOn = function (action, args, callback) {
console.log('Register notify ' + action)
if (this.actions[action] === undefined) {
console.log('TS3: Register notify ' + action)
} else if (this.actions[action] !== callback) {
console.log('TS3: Change notify ' + action)
}
this.actions[action] = callback;
this.send(`clientnotifyregister event=${action} ${args}`)
}
this.notifyOff = function (action, args) {
console.log('Unregister notify ' + action)
console.log('TS3: Unregister notify ' + action)
this.send(`clientnotifyunregister event=${action} ${args}`)
.then(() => {
this.actions[action] = undefined;
@ -59,7 +64,7 @@ function ClientQuery() {
this.log('Request: ' + data)
return new Promise(function (resolve, reject) {
this.sock.write(data + '\n', 'utf8', (res) => {
console.log('Sent: ' + data)
console.log('TS3: Sent: ' + data)
let func = (data) => {
if (data.toString() != 'error id=0 msg=ok\n\r') {
@ -89,9 +94,7 @@ function ClientQuery() {
this.reInitActions = function () {
let act = this.actions;
console.log('actions', Object.keys(act))
Object.keys(act).forEach(function (key) {
console.log('addNotifyMemes Lol', key, 'schandlerid=1', typeof (act[key]))
this.notifyOn(key, 'schandlerid=1', act[key])
}.bind(this));
}
@ -127,7 +130,7 @@ function ClientQuery() {
sock.on('close', () => {
console.log('Socket closed, reopening..');
console.log('TS3: Socket closed, reopening..');
sock.destroy();
this.connect(host, port, apikey);
});

View File

@ -0,0 +1,23 @@
# ts3_remote_ham
A simple Node.js app that triggers the PTT line of a transceiver when someone in the same channel of a TeamSpeak 3 server starts speaking.
## Requirements
- TeamSpeak 3 with the [Client Query](https://www.myteamspeak.com/addons/L2FkZG9ucy85NDNkZDgxNi03ZWYyLTQ4ZDctODJiOC1kNjBjM2I5YjEwYjM%3D) plugin, which is pre-installed by default.
- If using the serial port, GCC to compile the ptt_daemon.c utility.
## Supported setups
- FLrig via its XML-RPC server. This should be enabled by default in FLrig.
- microHam microKeyer via [mhuxd](https://github.com/dj5qv/mhuxd) or really any tty device (RS-232, USB UART adapters). The `ptt_daemon` utility is responsible for enabling the RTS line of the serial port (high = PTT on).
## Usage:
1. Clone the repository, enter it.
2. `$ npm i` to install the dependencies.
3. `$ npm run compile` to compile the ptt_daemon (optional).
4. Start TeamSpeak.
5. Go to the menu Tools > Options > Addons and click the button *Disabled* to enable the Client Query plugin.
6. Open the plugin's settings and copy the API key. Paste it into the `config.js` file created automatically in step 2.
7. `$ npm run start` to run the program.
8. If using the serial port implementation, change the provider to "serial" and set the path in `config.js`.
Be aware that by running this program on a public server may lead to unauthorized transmissions using your rig, or even damage the rig by exceeding the recommended long-time power limits. Make sure to not let the remote client linger unsupervised. You can mute the reception by pressing the *Mute Speakers/Headphones* button (a "sound muted" voice line will be played) through remote desktop on the remote client. It is recommended to change the local capture activation method to push to talk during remote operation.

22
config.sample.js Normal file
View File

@ -0,0 +1,22 @@
const config = {};
config.teamspeak = {
ip: '127.0.0.1',
port: '25639',
// Key returned by the Client Query plugin in TeamSpeak. Can also be found in ~/.ts3client/clientquery.ini
// It should look something like LKT9-ZLDM-LFK0-CLSB-UDEE-2YVJ.
apiKey: '',
};
config.provider = 'flrig'; // flrig or serial
config.providerOptions = {
serial: {
port: '/dev/mhuxd/ptt1', // path to the serial port of the radio or the VSP created by mhuxd
},
flrig: {
url: 'http://127.0.0.1:12345', // URL to the FLrig XML-RPC server
},
};
export default config;

View File

@ -1,36 +1,37 @@
import * as fs from 'fs';
import ClientQuery from "./ClientQuery.js";
import flrig from './providers/flrig.js';
import mhuxd from './providers/mhuxd.js';
import serial from './providers/serial.js';
import config from './config.js';
const apikey = fs.readFileSync('./apikey.txt').toString();
const client = new ClientQuery();
try {
await client.connect('127.0.0.1', '25639', apikey);
await client.connect(config.teamspeak.host, config.teamspeak.port, config.teamspeak.apiKey);
} catch (error) {
console.error('Cannot connect to TS3 query. Is TeamSpeak running?', error);
console.error('Cannot connect to TS3 query. Is TeamSpeak running?', error);
}
// client.request('sendtextmessage targetmode=2 msg=Node.JS').then( res =>{ console.log(res.toString()) });
await new Promise(r => setTimeout(r, 50));
const speakingUsers = {};
const whoamiData = client.parse((await client.request('whoami')).toString());
const provider = flrig();
const provider = {
flrig, serial
}[config.provider](config.providerOptions);
client.notifyOn('notifytalkstatuschange', '', data => {
let args = client.parse(data.toString());
if (args.clid === whoamiData.clid)
return;
let args = client.parse(data.toString());
if (args.clid === whoamiData.clid)
return;
speakingUsers[args.clid] = parseInt(args.status) === 1;
if (Object.values(speakingUsers).find(el => el)) {
// someone is speaking
provider.pttDown();
} else {
// nobody is speaking
provider.pttUp();
}
speakingUsers[args.clid] = parseInt(args.status) === 1;
if (Object.values(speakingUsers).find(el => el)) {
// someone is speaking
provider.pttDown();
} else {
// nobody is speaking
provider.pttUp();
}
});

1
package-lock.json generated
View File

@ -7,6 +7,7 @@
"": {
"name": "ts3-remote",
"version": "1.0.0",
"hasInstallScript": true,
"license": "GPL",
"dependencies": {
"@foxglove/xmlrpc": "^1.3.0",

View File

@ -4,7 +4,9 @@
"description": "TS3 remote client for MicroKeyer PTT.",
"main": "daemon.js",
"scripts": {
"start": "node daemon.js"
"start": "node daemon.js",
"compile": "gcc -o ptt_daemon ptt_daemon.c",
"postinstall": "cp -n config.sample.js config.js"
},
"type": "module",
"author": "ericek111",

View File

@ -1,14 +1,22 @@
import { XmlRpcClient } from "@foxglove/xmlrpc";
export default function flrig() {
const client = new XmlRpcClient(`http://127.0.0.1:12345`);
export default function flrig(opts) {
const client = new XmlRpcClient(opts.flrig.url);
const setPtt = async (state) => {
try {
await client.methodCall('rig.set_ptt', [state]);
} catch (ex) {
console.error(`Cannot send rig.set_ptt(${state}) to flrig (${opts.flrig.url}) -- perhaps it's not running? ${ex.code ?? 'unknown'} at ${ex.erroredSysCall ?? '?'}`);
}
}
return {
pttDown: () => {
client.methodCall('rig.set_ptt', [1]);
setPtt(1);
},
pttUp: () => {
client.methodCall('rig.set_ptt', [0]);
setPtt(0);
}
};
};

View File

@ -1,12 +0,0 @@
import { spawn } from 'child_process';
export default function() {
return {
pttDown: () => {
spawn('/home/omega/Documents/ts3_remote/ptt_daemon', ['/dev/mhuxd/fsk1', '1']);
},
pttUp: () => {
spawn('/home/omega/Documents/ts3_remote/ptt_daemon', ['/dev/mhuxd/fsk1', '0']);
}
};
};

12
providers/serial.js Normal file
View File

@ -0,0 +1,12 @@
import { spawn } from 'child_process';
export default function serial(opts) {
return {
pttDown: () => {
spawn('./ptt_daemon', [opts.serial.port, '1']);
},
pttUp: () => {
spawn('./ptt_daemon', [opts.serial.port, '0']);
}
};
};

View File

@ -24,8 +24,9 @@ int main(int argc, char **argv)
int flags;
ioctl(fd, TIOCMGET, &flags);
// The below flags can be replaced by TIOCM_DTR to use the DTR line instead, See $ man "TIOCMSET(2const)"
if (rtsEnable != 0) {
flags |= TIOCM_RTS;
flags |= TIOCM_RTS; // brings the RTS line high
} else {
flags &= ~TIOCM_RTS;
}