nep-cli 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/index.js +202 -1018
- package/package.json +2 -2
package/bin/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const { program } = require('commander');
|
|
4
|
+
const { version } = require('../package.json');
|
|
4
5
|
const os = require('os');
|
|
5
6
|
const zmq = require("zeromq");
|
|
6
7
|
var nep = require('nep-js');
|
|
7
|
-
var nep_configuration = { current_port: 10000, IP: "
|
|
8
|
+
var nep_configuration = { current_port: 10000, IP: "0.0.0.0", brokers: {} }
|
|
8
9
|
const { exec } = require('child_process');
|
|
9
10
|
const { AutoComplete } = require('enquirer');
|
|
10
11
|
|
|
@@ -17,6 +18,66 @@ const fs = require('fs');
|
|
|
17
18
|
const zmqc = require("zeromq/v5-compat");
|
|
18
19
|
|
|
19
20
|
|
|
21
|
+
program
|
|
22
|
+
.version(version)
|
|
23
|
+
.description('NEP-CLI')
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
function getIPAddress(interfaceName) {
|
|
27
|
+
const interfaces = os.networkInterfaces();
|
|
28
|
+
const networkInterface = interfaces[interfaceName];
|
|
29
|
+
|
|
30
|
+
if (networkInterface) {
|
|
31
|
+
const ipAddressInfo = networkInterface.find(info => info.family === 'IPv4');
|
|
32
|
+
return ipAddressInfo ? ipAddressInfo.address : null;
|
|
33
|
+
} else {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function printIPAddress(interfaceName, ipAddress) {
|
|
39
|
+
if (ipAddress) {
|
|
40
|
+
console.log(`${interfaceName} IP Address: ${ipAddress}`);
|
|
41
|
+
} else {
|
|
42
|
+
console.log(`No ${interfaceName} IPv4 address found.`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
program
|
|
47
|
+
.command('ip')
|
|
48
|
+
.description('Display current Wi-Fi and Ethernet IP addresses of this computer')
|
|
49
|
+
.action(() => {
|
|
50
|
+
try {
|
|
51
|
+
const platform = os.platform();
|
|
52
|
+
let wifiInterfaces, ethernetInterface;
|
|
53
|
+
|
|
54
|
+
if (platform === 'linux') {
|
|
55
|
+
wifiInterfaces = Object.keys(os.networkInterfaces()).filter(ifname => /^(wlan|wlp|wl|en)\d*$/i.test(ifname));
|
|
56
|
+
ethernetInterface = Object.keys(os.networkInterfaces()).find(ifname => /^(eth|enp|eno)\d*$/i.test(ifname));
|
|
57
|
+
} else if (platform === 'win32') {
|
|
58
|
+
wifiInterfaces = Object.keys(os.networkInterfaces()).filter(ifname => /^(Wireless|Wi-Fi)/i.test(ifname));
|
|
59
|
+
ethernetInterface = Object.keys(os.networkInterfaces()).find(ifname => /^Ethernet/i.test(ifname));
|
|
60
|
+
} else if (platform === 'darwin') {
|
|
61
|
+
wifiInterfaces = Object.keys(os.networkInterfaces()).filter(ifname => /^en\d*$/i.test(ifname));
|
|
62
|
+
ethernetInterface = Object.keys(os.networkInterfaces()).find(ifname => /^en\d*$/i.test(ifname));
|
|
63
|
+
} else {
|
|
64
|
+
console.log('Unsupported operating system.');
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
wifiInterfaces.forEach(wifiInterface => {
|
|
69
|
+
const ipAddress = getIPAddress(wifiInterface);
|
|
70
|
+
printIPAddress(`Wi-Fi (${wifiInterface})`, ipAddress);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
printIPAddress('Ethernet', getIPAddress(ethernetInterface));
|
|
74
|
+
} catch (error) {
|
|
75
|
+
console.error('An error occurred:', error.message);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
|
|
20
81
|
// Node saved here
|
|
21
82
|
var nodes_register = {};
|
|
22
83
|
// ----------- Main variables ---------------
|
|
@@ -24,7 +85,7 @@ var nodes_register = {};
|
|
|
24
85
|
var topic_register = {};
|
|
25
86
|
|
|
26
87
|
class MasterLocal {
|
|
27
|
-
constructor(IP = '
|
|
88
|
+
constructor(IP = '0.0.0.0', port_ = 7000) {
|
|
28
89
|
this.port = String(port_)
|
|
29
90
|
var address = "tcp://" + IP + ":" + this.port
|
|
30
91
|
console.log("New Master in: " + address)
|
|
@@ -136,7 +197,6 @@ var onNewTopic = function (node_request, topic_register) {
|
|
|
136
197
|
}
|
|
137
198
|
|
|
138
199
|
|
|
139
|
-
|
|
140
200
|
var createBroker = function (topic) {
|
|
141
201
|
try {
|
|
142
202
|
var broker = new Broker(nep_configuration["IP"], nep_configuration["current_port"] + 1, nep_configuration["current_port"])
|
|
@@ -261,42 +321,6 @@ for (let i = 3020; i <= 3040; i++) {
|
|
|
261
321
|
}
|
|
262
322
|
|
|
263
323
|
|
|
264
|
-
program
|
|
265
|
-
.version('"0.1.2')
|
|
266
|
-
.description('NEP+ CLI');
|
|
267
|
-
|
|
268
|
-
program
|
|
269
|
-
.command('ip')
|
|
270
|
-
.description('Display current Wi-Fi and Ethernet IP addresses of this computer')
|
|
271
|
-
.action(() => {
|
|
272
|
-
const interfaces = os.networkInterfaces();
|
|
273
|
-
|
|
274
|
-
// Find Wi-Fi interface
|
|
275
|
-
const wifiInterface = interfaces['Wi-Fi'] || interfaces['Wi-Fi 2'] || interfaces['wlan0'] || interfaces['wlo1'];
|
|
276
|
-
if (wifiInterface) {
|
|
277
|
-
const wifiIPv4 = wifiInterface.find(iface => iface.family === 'IPv4');
|
|
278
|
-
if (wifiIPv4) {
|
|
279
|
-
console.log(`Wi-Fi IP Address: ${wifiIPv4.address}`);
|
|
280
|
-
} else {
|
|
281
|
-
console.log('No Wi-Fi IPv4 address found.');
|
|
282
|
-
}
|
|
283
|
-
} else {
|
|
284
|
-
console.log('Wi-Fi interface not found.');
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// Find Ethernet interface
|
|
288
|
-
const ethernetInterface = interfaces['Ethernet'] || interfaces['Ethernet 2'] || interfaces['eth0'] || interfaces['イーサネット'] || interfaces['enp0s10'];
|
|
289
|
-
if (ethernetInterface) {
|
|
290
|
-
const ethernetIPv4 = ethernetInterface.find(iface => iface.family === 'IPv4');
|
|
291
|
-
if (ethernetIPv4) {
|
|
292
|
-
console.log(`Ethernet IP Address: ${ethernetIPv4.address}`);
|
|
293
|
-
} else {
|
|
294
|
-
console.log('No Ethernet IPv4 address found.');
|
|
295
|
-
}
|
|
296
|
-
} else {
|
|
297
|
-
console.log('Ethernet interface not found.');
|
|
298
|
-
}
|
|
299
|
-
});
|
|
300
324
|
|
|
301
325
|
program
|
|
302
326
|
.command('app')
|
|
@@ -306,8 +330,8 @@ program
|
|
|
306
330
|
const username = os.userInfo().username;
|
|
307
331
|
|
|
308
332
|
// Specify the path to the executable
|
|
309
|
-
const appFolderName = 'nepplus';
|
|
310
|
-
const executableName = '
|
|
333
|
+
const appFolderName = 'nepplus-app';
|
|
334
|
+
const executableName = 'nepplus-app.exe';
|
|
311
335
|
const executablePath = `C:\\Users\\${username}\\AppData\\Local\\Programs\\${appFolderName}\\${executableName}`;
|
|
312
336
|
|
|
313
337
|
// Run the executable with proper escaping
|
|
@@ -365,7 +389,6 @@ program
|
|
|
365
389
|
});
|
|
366
390
|
|
|
367
391
|
|
|
368
|
-
|
|
369
392
|
program
|
|
370
393
|
.command('master')
|
|
371
394
|
.description('Start NEP master in localhost')
|
|
@@ -374,7 +397,7 @@ program
|
|
|
374
397
|
var node = new nep.Node("nep-cli");
|
|
375
398
|
console.log("Starting NEP master in terminal")
|
|
376
399
|
var master = new MasterLocal();
|
|
377
|
-
var info = new nep.MasterInfoServer(IP = '
|
|
400
|
+
var info = new nep.MasterInfoServer(IP = '0.0.0.0', topics = topic_register);
|
|
378
401
|
} catch (error) {
|
|
379
402
|
if (error.message.includes('EADDRINUSE')) {
|
|
380
403
|
console.error("Error: Address already in use. Another instance of NEP master might be running.");
|
|
@@ -384,78 +407,6 @@ program
|
|
|
384
407
|
}
|
|
385
408
|
});
|
|
386
409
|
|
|
387
|
-
program
|
|
388
|
-
.command('master-wifi')
|
|
389
|
-
.description('Start NEP master in Wi-Fi network')
|
|
390
|
-
.action(async () => {
|
|
391
|
-
|
|
392
|
-
const interfaces = os.networkInterfaces();
|
|
393
|
-
|
|
394
|
-
// Find Wi-Fi interface
|
|
395
|
-
const wifiInterface = interfaces['Wi-Fi'] || interfaces['Wi-Fi 2'] || interfaces['wlan0'] || interfaces['wlo1'];
|
|
396
|
-
if (wifiInterface) {
|
|
397
|
-
const wifiIPv4 = wifiInterface.find(iface => iface.family === 'IPv4');
|
|
398
|
-
if (wifiIPv4) {
|
|
399
|
-
console.log(`Wi-Fi IP Address: ${wifiIPv4.address}`);
|
|
400
|
-
try {
|
|
401
|
-
var node = new nep.Node("nep-cli");
|
|
402
|
-
nep_configuration["IP"] = wifiIPv4.address;
|
|
403
|
-
var master = new MasterLocal(IP = wifiIPv4.address);
|
|
404
|
-
var info = new nep.MasterInfoServer(IP = wifiIPv4.address, topics = topic_register);
|
|
405
|
-
} catch (error) {
|
|
406
|
-
if (error.message.includes('EADDRINUSE')) {
|
|
407
|
-
console.error("Error: Address already in use. Another instance of NEP master might be running.");
|
|
408
|
-
} else {
|
|
409
|
-
console.error("An error occurred:", error.message);
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
} else {
|
|
414
|
-
console.log('No Wi-Fi IPv4 address found.');
|
|
415
|
-
}
|
|
416
|
-
} else {
|
|
417
|
-
console.log('Wi-Fi interface not found.');
|
|
418
|
-
}
|
|
419
|
-
});
|
|
420
|
-
program
|
|
421
|
-
.command('master-eth')
|
|
422
|
-
.description('Start NEP master in Ethernet network')
|
|
423
|
-
.action(async () => {
|
|
424
|
-
|
|
425
|
-
const interfaces = os.networkInterfaces();
|
|
426
|
-
|
|
427
|
-
const ethernetInterface = interfaces['Ethernet'] || interfaces['Ethernet 2'] || interfaces['eth0'] || interfaces['イーサネット'] || interfaces['enp0s10'];
|
|
428
|
-
if (ethernetInterface) {
|
|
429
|
-
const ethernetIPv4 = ethernetInterface.find(iface => iface.family === 'IPv4');
|
|
430
|
-
if (ethernetIPv4) {
|
|
431
|
-
console.log(`Ethernet IP Address: ${ethernetIPv4.address}`);
|
|
432
|
-
var node = new nep.Node("nep-cli");
|
|
433
|
-
nep_configuration["IP"] = ethernetIPv4.address;
|
|
434
|
-
var master = new MasterLocal(IP = ethernetIPv4.address);
|
|
435
|
-
var info = new nep.MasterInfoServer(IP = ethernetIPv4.address, topics = topic_register);
|
|
436
|
-
} else {
|
|
437
|
-
console.log('No Ethernet IPv4 address found.');
|
|
438
|
-
}
|
|
439
|
-
} else {
|
|
440
|
-
console.log('Ethernet interface not found.');
|
|
441
|
-
}
|
|
442
|
-
});
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
program
|
|
446
|
-
.command('master-ip <ip>')
|
|
447
|
-
.description('Start NEP master in some specific IP')
|
|
448
|
-
.action(async (ip) => {
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
console.log(`IP Address: ${ip}`);
|
|
452
|
-
var node = new nep.Node("nep-cli");
|
|
453
|
-
nep_configuration["IP"] = ip;
|
|
454
|
-
var master = new MasterLocal(IP = ip);
|
|
455
|
-
var info = new nep.MasterInfoServer(IP = ip, topics = topic_register);
|
|
456
|
-
|
|
457
|
-
});
|
|
458
|
-
|
|
459
410
|
|
|
460
411
|
program
|
|
461
412
|
.command('topics')
|
|
@@ -510,93 +461,6 @@ program
|
|
|
510
461
|
await getTopics(); // Call the function to get topics
|
|
511
462
|
});
|
|
512
463
|
|
|
513
|
-
program
|
|
514
|
-
.command('topics-eth')
|
|
515
|
-
.description('Get list of NEP+ topics over Ethernet')
|
|
516
|
-
.action(async () => {
|
|
517
|
-
const interfaces = os.networkInterfaces();
|
|
518
|
-
const ethernetInterface = interfaces['Ethernet'] || interfaces['Ethernet 2'] || interfaces['eth0'] || interfaces['イーサネット'] || interfaces['enp0s10'];
|
|
519
|
-
|
|
520
|
-
if (ethernetInterface) {
|
|
521
|
-
const ethernetIPv4 = ethernetInterface.find(iface => iface.family === 'IPv4');
|
|
522
|
-
if (ethernetIPv4) {
|
|
523
|
-
const master_ip = ethernetIPv4.address;
|
|
524
|
-
console.log('Asking to NEP+ master in -', ethernetIPv4.address);
|
|
525
|
-
console.log("\n")
|
|
526
|
-
await getAndDisplayTopics(master_ip);
|
|
527
|
-
} else {
|
|
528
|
-
console.log('No Ethernet IPv4 address found.');
|
|
529
|
-
}
|
|
530
|
-
} else {
|
|
531
|
-
console.log('Ethernet interface not found.');
|
|
532
|
-
}
|
|
533
|
-
});
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
program
|
|
537
|
-
.command('topics-wifi')
|
|
538
|
-
.description('Get list of NEP+ topics over Wi-Fi')
|
|
539
|
-
.action(async () => {
|
|
540
|
-
const interfaces = os.networkInterfaces();
|
|
541
|
-
const wifiInterface = interfaces['Wi-Fi'] || interfaces['Wi-Fi 2'] || interfaces['wlan0'] || interfaces['wlo1'];
|
|
542
|
-
|
|
543
|
-
if (wifiInterface) {
|
|
544
|
-
const wifiIPv4 = wifiInterface.find(iface => iface.family === 'IPv4');
|
|
545
|
-
if (wifiIPv4) {
|
|
546
|
-
const master_ip = wifiIPv4.address; // Set the Wi-Fi IP address dynamically
|
|
547
|
-
console.log('Asking to NEP+ master in -', wifiIPv4.address);
|
|
548
|
-
console.log("\n")
|
|
549
|
-
const TIMEOUT_DURATION = 5000;
|
|
550
|
-
|
|
551
|
-
async function getTopics() {
|
|
552
|
-
var requester = new zmq.Request();
|
|
553
|
-
requester.connect(`tcp://${master_ip}:${PORT_MASTER_INFO}`);
|
|
554
|
-
|
|
555
|
-
let msg = { "input": "topics" };
|
|
556
|
-
var message = JSON.stringify(msg);
|
|
557
|
-
|
|
558
|
-
try {
|
|
559
|
-
const responsePromise = new Promise(async (resolve, reject) => {
|
|
560
|
-
await requester.send(message);
|
|
561
|
-
const [result] = await requester.receive();
|
|
562
|
-
var results = JSON.parse(result.toString());
|
|
563
|
-
resolve(results);
|
|
564
|
-
});
|
|
565
|
-
|
|
566
|
-
const timeoutPromise = new Promise((resolve, reject) => {
|
|
567
|
-
setTimeout(() => {
|
|
568
|
-
reject(new Error("Timed out, NEP master over Wi-Fi was not found"));
|
|
569
|
-
}, TIMEOUT_DURATION);
|
|
570
|
-
});
|
|
571
|
-
|
|
572
|
-
const results = await Promise.race([responsePromise, timeoutPromise]);
|
|
573
|
-
|
|
574
|
-
if (results["state"] === "success") {
|
|
575
|
-
availableTopics = results["input"]; // Store the topics here
|
|
576
|
-
console.log("");
|
|
577
|
-
results["input"].forEach(element => {
|
|
578
|
-
console.log(element);
|
|
579
|
-
});
|
|
580
|
-
} else {
|
|
581
|
-
console.log("No topics yet");
|
|
582
|
-
}
|
|
583
|
-
} catch (error) {
|
|
584
|
-
console.error("Error:", error.message);
|
|
585
|
-
} finally {
|
|
586
|
-
process.exit();
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
await getTopics();
|
|
591
|
-
|
|
592
|
-
} else {
|
|
593
|
-
console.log('No Wi-Fi IPv4 address found.');
|
|
594
|
-
}
|
|
595
|
-
} else {
|
|
596
|
-
console.log('Wi-Fi interface not found.');
|
|
597
|
-
}
|
|
598
|
-
});
|
|
599
|
-
|
|
600
464
|
|
|
601
465
|
program
|
|
602
466
|
.command('listen <topic>')
|
|
@@ -648,9 +512,10 @@ program
|
|
|
648
512
|
run();
|
|
649
513
|
});
|
|
650
514
|
|
|
515
|
+
|
|
651
516
|
program
|
|
652
|
-
.command('
|
|
653
|
-
.description('Subscribe to a NEP+ topic
|
|
517
|
+
.command('echo <topic>')
|
|
518
|
+
.description('Subscribe to a NEP+ topic and display raw string messages')
|
|
654
519
|
.action(async (topic) => {
|
|
655
520
|
const interfaces = os.networkInterfaces();
|
|
656
521
|
|
|
@@ -669,10 +534,11 @@ program
|
|
|
669
534
|
|
|
670
535
|
var node = new nep.Node("nep-cli-sub");
|
|
671
536
|
var conf = node.hybrid(master_ip);
|
|
672
|
-
sub = node.new_sub(topic, "
|
|
537
|
+
sub = node.new_sub(topic, "string", callback, conf);
|
|
673
538
|
};
|
|
674
539
|
|
|
675
|
-
|
|
540
|
+
var master_ip = "127.0.0.1";
|
|
541
|
+
async function run() {
|
|
676
542
|
var requester = new zmq.Request();
|
|
677
543
|
requester.connect("tcp://" + master_ip + ":" + PORT_MASTER_INFO);
|
|
678
544
|
|
|
@@ -694,747 +560,166 @@ program
|
|
|
694
560
|
}
|
|
695
561
|
}
|
|
696
562
|
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
563
|
+
run();
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
program
|
|
568
|
+
.command('publish <topic> <message>')
|
|
569
|
+
.description('Publish a message to a NEP+ topic')
|
|
570
|
+
.action((topic, message) => {
|
|
571
|
+
|
|
572
|
+
var openpub = function (master_ip = "127.0.0.1") {
|
|
573
|
+
|
|
574
|
+
var pubFunction = function () {
|
|
575
|
+
|
|
576
|
+
var msg = message.replace(/'/g, '"')
|
|
577
|
+
console.log(JSON.parse(msg))
|
|
578
|
+
pub.publish(JSON.parse(msg))
|
|
579
|
+
console.log("Message published")
|
|
580
|
+
|
|
581
|
+
process.exit(1)
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
var node = new nep.Node("nep-cli-pub")
|
|
586
|
+
var pub = node.new_pub(topic, "json")
|
|
587
|
+
setTimeout(pubFunction, 1000)
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
async function run() {
|
|
591
|
+
var requester = new zmq.Request;
|
|
592
|
+
var master_ip = "127.0.0.1"
|
|
593
|
+
|
|
594
|
+
requester.connect("tcp://" + master_ip + ":" + PORT_MASTER_INFO);
|
|
595
|
+
|
|
596
|
+
let msg = { "input": "topics" }
|
|
597
|
+
var message = JSON.stringify(msg);
|
|
598
|
+
await requester.send(message)
|
|
599
|
+
const [result] = await requester.receive()
|
|
600
|
+
var results = JSON.parse(result.toString())
|
|
601
|
+
//console.log(results);
|
|
602
|
+
if (results["input"].includes(topic)) {
|
|
603
|
+
console.log("")
|
|
604
|
+
openpub(master_ip)
|
|
605
|
+
}
|
|
606
|
+
else {
|
|
607
|
+
console.log("Topic is not registered");
|
|
706
608
|
}
|
|
707
|
-
} else {
|
|
708
|
-
console.log('Ethernet interface not found.');
|
|
709
609
|
}
|
|
610
|
+
run()
|
|
710
611
|
});
|
|
711
612
|
|
|
613
|
+
|
|
712
614
|
program
|
|
713
|
-
.command('
|
|
714
|
-
.description('
|
|
715
|
-
.action(async (topic) => {
|
|
615
|
+
.command('hz <topic> <msg_type>')
|
|
616
|
+
.description('Monitor the publishing rate of a NEP+ topic in localhost')
|
|
617
|
+
.action(async (topic, msg_type) => {
|
|
716
618
|
const interfaces = os.networkInterfaces();
|
|
619
|
+
const master_ip = "127.0.0.1"; // Change to the appropriate master IP
|
|
717
620
|
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
var date = new Date();
|
|
721
|
-
var dateString = date.toISOString();
|
|
722
|
-
console.log(dateString);
|
|
621
|
+
const opensub = function () {
|
|
622
|
+
const timestamps = []; // To store message timestamps
|
|
723
623
|
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
624
|
+
const callback = function (msg) {
|
|
625
|
+
const date = new Date();
|
|
626
|
+
const timestamp = date.getTime();
|
|
627
|
+
|
|
628
|
+
timestamps.push(timestamp);
|
|
629
|
+
|
|
630
|
+
// Remove timestamps older than ten seconds
|
|
631
|
+
const tenSecondsAgo = timestamp - 10000;
|
|
632
|
+
while (timestamps[0] < tenSecondsAgo) {
|
|
633
|
+
timestamps.shift();
|
|
728
634
|
}
|
|
729
635
|
};
|
|
730
636
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
637
|
+
const allowedFormats = ["json", "msgpack", "bytes", "images", "image"];
|
|
638
|
+
const messageFormat = allowedFormats.includes(msg_type) ? msg_type : "json";
|
|
639
|
+
const node = new nep.Node("nep-cli-sub");
|
|
640
|
+
const conf = node.hybrid(master_ip);
|
|
641
|
+
|
|
642
|
+
console.log("Topic:", topic)
|
|
643
|
+
console.log("Message type:", messageFormat)
|
|
644
|
+
|
|
645
|
+
const sub = node.new_sub(topic, messageFormat, callback, conf);
|
|
646
|
+
console.log("");
|
|
647
|
+
|
|
648
|
+
setInterval(() => {
|
|
649
|
+
// Calculate statistics for the last 10 seconds
|
|
650
|
+
const now = Date.now();
|
|
651
|
+
const tenSecondsAgo = now - 10000;
|
|
652
|
+
const recentTimestamps = timestamps.filter((ts) => ts > tenSecondsAgo);
|
|
653
|
+
const rate = recentTimestamps.length / 10; // Messages per second for a 10-second window
|
|
654
|
+
|
|
655
|
+
console.log("Average rate:", rate.toFixed(2), "Hz");
|
|
656
|
+
console.log("Min:", (10 / Math.max(rate, 0.1)).toFixed(2), "s");
|
|
657
|
+
console.log("Max:", (10 / Math.min(rate, 10)).toFixed(2), "s");
|
|
658
|
+
console.log("Std dev:", calculateStdDev(recentTimestamps, now).toFixed(2), "s");
|
|
659
|
+
console.log("Window:", recentTimestamps.length);
|
|
660
|
+
console.log("");
|
|
661
|
+
}, 1000);
|
|
734
662
|
};
|
|
735
663
|
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
664
|
+
const calculateStdDev = (timestamps) => {
|
|
665
|
+
if (timestamps.length < 2) {
|
|
666
|
+
return 0; // Standard deviation is not meaningful with less than two timestamps
|
|
667
|
+
}
|
|
739
668
|
|
|
740
|
-
|
|
741
|
-
|
|
669
|
+
// Calculate the time intervals between consecutive timestamps
|
|
670
|
+
const timeIntervals = [];
|
|
671
|
+
for (let i = 1; i < timestamps.length; i++) {
|
|
672
|
+
const interval = timestamps[i] - timestamps[i - 1];
|
|
673
|
+
timeIntervals.push(interval);
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
// Calculate the mean (average) of the time intervals
|
|
677
|
+
const mean = timeIntervals.reduce((acc, val) => acc + val, 0) / timeIntervals.length;
|
|
678
|
+
|
|
679
|
+
// Calculate the squared differences from the mean
|
|
680
|
+
const squaredDifferences = timeIntervals.map((interval) => Math.pow(interval - mean, 2));
|
|
681
|
+
|
|
682
|
+
// Calculate the mean of the squared differences
|
|
683
|
+
const meanSquaredDifference = squaredDifferences.reduce((acc, val) => acc + val, 0) / squaredDifferences.length;
|
|
684
|
+
|
|
685
|
+
// Calculate the square root of the mean squared difference
|
|
686
|
+
const stdDeviation = Math.sqrt(meanSquaredDifference);
|
|
687
|
+
|
|
688
|
+
return stdDeviation;
|
|
689
|
+
};
|
|
690
|
+
|
|
691
|
+
|
|
692
|
+
async function run() {
|
|
693
|
+
const requester = new zmq.Request();
|
|
694
|
+
requester.connect(`tcp://${master_ip}:${PORT_MASTER_INFO}`);
|
|
695
|
+
|
|
696
|
+
const msg = { "input": "topics" };
|
|
697
|
+
const message = JSON.stringify(msg);
|
|
742
698
|
await requester.send(message);
|
|
743
699
|
const [result] = await requester.receive();
|
|
744
|
-
|
|
700
|
+
const results = JSON.parse(result.toString());
|
|
745
701
|
|
|
746
702
|
if (results["state"] === "failure") {
|
|
747
|
-
console.log("Topic is not registered");
|
|
703
|
+
console.log("Topic is not registered, use *nep topics* to see the list of avaliable topics");
|
|
748
704
|
} else {
|
|
749
705
|
console.log("");
|
|
750
706
|
if (results["input"].includes(topic)) {
|
|
751
|
-
opensub(
|
|
707
|
+
opensub();
|
|
752
708
|
} else {
|
|
753
|
-
console.log("Topic is not registered");
|
|
709
|
+
console.log("Topic is not registered, use *nep topics* to see the list of avaliable topics");
|
|
754
710
|
}
|
|
755
711
|
}
|
|
756
712
|
}
|
|
757
713
|
|
|
758
|
-
|
|
759
|
-
if (wifiInterface) {
|
|
760
|
-
const wifiIPv4 = wifiInterface.find(iface => iface.family === 'IPv4');
|
|
761
|
-
if (wifiIPv4) {
|
|
762
|
-
run(wifiIPv4.address);
|
|
763
|
-
} else {
|
|
764
|
-
console.log('No Wi-Fi IPv4 address found.');
|
|
765
|
-
}
|
|
766
|
-
} else {
|
|
767
|
-
console.log('Wi-Fi interface not found.');
|
|
768
|
-
}
|
|
714
|
+
run();
|
|
769
715
|
});
|
|
770
716
|
|
|
771
717
|
|
|
772
718
|
program
|
|
773
|
-
.command('
|
|
774
|
-
.description('
|
|
775
|
-
.action(async (
|
|
776
|
-
const
|
|
777
|
-
|
|
778
|
-
var opensub = function (master_ip = "127.0.0.1") {
|
|
779
|
-
var callback = function (msg) {
|
|
780
|
-
var date = new Date();
|
|
781
|
-
var dateString = date.toISOString();
|
|
782
|
-
console.log(dateString);
|
|
783
|
-
|
|
784
|
-
if (msg.length > 10000) {
|
|
785
|
-
console.log("the message is too long to be displayed");
|
|
786
|
-
} else {
|
|
787
|
-
console.log(msg);
|
|
788
|
-
}
|
|
789
|
-
};
|
|
790
|
-
|
|
791
|
-
var node = new nep.Node("nep-cli-sub");
|
|
792
|
-
var conf = node.hybrid(master_ip);
|
|
793
|
-
sub = node.new_sub(topic, "string", callback, conf);
|
|
794
|
-
};
|
|
795
|
-
|
|
796
|
-
var master_ip = "127.0.0.1";
|
|
797
|
-
async function run() {
|
|
798
|
-
var requester = new zmq.Request();
|
|
799
|
-
requester.connect("tcp://" + master_ip + ":" + PORT_MASTER_INFO);
|
|
800
|
-
|
|
801
|
-
let msg = { "input": "topics" };
|
|
802
|
-
var message = JSON.stringify(msg);
|
|
803
|
-
await requester.send(message);
|
|
804
|
-
const [result] = await requester.receive();
|
|
805
|
-
var results = JSON.parse(result.toString());
|
|
806
|
-
|
|
807
|
-
if (results["state"] === "failure") {
|
|
808
|
-
console.log("Topic is not registered");
|
|
809
|
-
} else {
|
|
810
|
-
console.log("");
|
|
811
|
-
if (results["input"].includes(topic)) {
|
|
812
|
-
opensub(master_ip);
|
|
813
|
-
} else {
|
|
814
|
-
console.log("Topic is not registered");
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
run();
|
|
820
|
-
});
|
|
821
|
-
|
|
822
|
-
program
|
|
823
|
-
.command('echo-eth <topic>')
|
|
824
|
-
.description('Subscribe to a NEP+ topic over Ethernet and display raw string messages')
|
|
825
|
-
.action(async (topic) => {
|
|
826
|
-
const interfaces = os.networkInterfaces();
|
|
827
|
-
|
|
828
|
-
var opensub = function (master_ip = "127.0.0.1") {
|
|
829
|
-
var callback = function (msg) {
|
|
830
|
-
var date = new Date();
|
|
831
|
-
var dateString = date.toISOString();
|
|
832
|
-
console.log(dateString);
|
|
833
|
-
|
|
834
|
-
if (msg.length > 10000) {
|
|
835
|
-
console.log("the message is too long to be displayed");
|
|
836
|
-
} else {
|
|
837
|
-
console.log(msg);
|
|
838
|
-
}
|
|
839
|
-
};
|
|
840
|
-
|
|
841
|
-
var node = new nep.Node("nep-cli-sub");
|
|
842
|
-
var conf = node.hybrid(master_ip);
|
|
843
|
-
sub = node.new_sub(topic, "string", callback, conf);
|
|
844
|
-
};
|
|
845
|
-
|
|
846
|
-
async function run(master_ip) {
|
|
847
|
-
var requester = new zmq.Request();
|
|
848
|
-
requester.connect("tcp://" + master_ip + ":" + PORT_MASTER_INFO);
|
|
849
|
-
|
|
850
|
-
let msg = { "input": "topics" };
|
|
851
|
-
var message = JSON.stringify(msg);
|
|
852
|
-
await requester.send(message);
|
|
853
|
-
const [result] = await requester.receive();
|
|
854
|
-
var results = JSON.parse(result.toString());
|
|
855
|
-
|
|
856
|
-
if (results["state"] === "failure") {
|
|
857
|
-
console.log("Topic is not registered");
|
|
858
|
-
} else {
|
|
859
|
-
console.log("");
|
|
860
|
-
if (results["input"].includes(topic)) {
|
|
861
|
-
opensub(master_ip);
|
|
862
|
-
} else {
|
|
863
|
-
console.log("Topic is not registered");
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
// Find Ethernet interface
|
|
869
|
-
const ethernetInterface = interfaces['Ethernet'] || interfaces['Ethernet 2'] || interfaces['eth0'] || interfaces['イーサネット'] || interfaces['enp0s10'];
|
|
870
|
-
if (ethernetInterface) {
|
|
871
|
-
const ethernetIPv4 = ethernetInterface.find(iface => iface.family === 'IPv4');
|
|
872
|
-
if (ethernetIPv4) {
|
|
873
|
-
console.log(`Ethernet IP Address: ${ethernetIPv4.address}`);
|
|
874
|
-
run(ethernetIPv4.address)
|
|
875
|
-
} else {
|
|
876
|
-
console.log('No Ethernet IPv4 address found.');
|
|
877
|
-
}
|
|
878
|
-
} else {
|
|
879
|
-
console.log('Ethernet interface not found.');
|
|
880
|
-
}
|
|
881
|
-
});
|
|
882
|
-
|
|
883
|
-
program
|
|
884
|
-
.command('echo-wifi <topic>')
|
|
885
|
-
.description('Subscribe to a NEP+ topic over Wi-Fi and display raw string messages')
|
|
886
|
-
.action(async (topic) => {
|
|
887
|
-
const interfaces = os.networkInterfaces();
|
|
888
|
-
|
|
889
|
-
var opensub = function (master_ip = "127.0.0.1") {
|
|
890
|
-
var callback = function (msg) {
|
|
891
|
-
var date = new Date();
|
|
892
|
-
var dateString = date.toISOString();
|
|
893
|
-
console.log(dateString);
|
|
894
|
-
|
|
895
|
-
if (msg.length > 10000) {
|
|
896
|
-
console.log("the message is too long to be displayed");
|
|
897
|
-
} else {
|
|
898
|
-
console.log(msg);
|
|
899
|
-
}
|
|
900
|
-
};
|
|
901
|
-
|
|
902
|
-
var node = new nep.Node("nep-cli-sub");
|
|
903
|
-
var conf = node.hybrid(master_ip);
|
|
904
|
-
sub = node.new_sub(topic, "string", callback, conf);
|
|
905
|
-
};
|
|
906
|
-
|
|
907
|
-
async function run(master_ip) {
|
|
908
|
-
var requester = new zmq.Request();
|
|
909
|
-
requester.connect("tcp://" + master_ip + ":" + PORT_MASTER_INFO);
|
|
910
|
-
|
|
911
|
-
let msg = { "input": "topics" };
|
|
912
|
-
var message = JSON.stringify(msg);
|
|
913
|
-
await requester.send(message);
|
|
914
|
-
const [result] = await requester.receive();
|
|
915
|
-
var results = JSON.parse(result.toString());
|
|
916
|
-
|
|
917
|
-
if (results["state"] === "failure") {
|
|
918
|
-
console.log("Topic is not registered");
|
|
919
|
-
} else {
|
|
920
|
-
console.log("");
|
|
921
|
-
if (results["input"].includes(topic)) {
|
|
922
|
-
opensub(master_ip);
|
|
923
|
-
} else {
|
|
924
|
-
console.log("Topic is not registered");
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
const wifiInterface = interfaces['Wi-Fi'] || interfaces['Wi-Fi 2'] || interfaces['wlan0'] || interfaces['wlo1'];
|
|
930
|
-
if (wifiInterface) {
|
|
931
|
-
const wifiIPv4 = wifiInterface.find(iface => iface.family === 'IPv4');
|
|
932
|
-
if (wifiIPv4) {
|
|
933
|
-
run(wifiIPv4.address);
|
|
934
|
-
} else {
|
|
935
|
-
console.log('No Wi-Fi IPv4 address found.');
|
|
936
|
-
}
|
|
937
|
-
} else {
|
|
938
|
-
console.log('Wi-Fi interface not found.');
|
|
939
|
-
}
|
|
940
|
-
});
|
|
941
|
-
|
|
942
|
-
program
|
|
943
|
-
.command('publish <topic> <message>')
|
|
944
|
-
.description('Publish a message to a NEP+ topic')
|
|
945
|
-
.action((topic, message) => {
|
|
946
|
-
|
|
947
|
-
var openpub = function (master_ip = "127.0.0.1") {
|
|
948
|
-
|
|
949
|
-
var pubFunction = function () {
|
|
950
|
-
|
|
951
|
-
var msg = message.replace(/'/g, '"')
|
|
952
|
-
console.log(JSON.parse(msg))
|
|
953
|
-
pub.publish(JSON.parse(msg))
|
|
954
|
-
console.log("Message published")
|
|
955
|
-
|
|
956
|
-
process.exit(1)
|
|
957
|
-
}
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
var node = new nep.Node("nep-cli-pub")
|
|
961
|
-
var pub = node.new_pub(topic, "json")
|
|
962
|
-
setTimeout(pubFunction, 1000)
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
async function run() {
|
|
966
|
-
var requester = new zmq.Request;
|
|
967
|
-
var master_ip = "127.0.0.1"
|
|
968
|
-
|
|
969
|
-
requester.connect("tcp://" + master_ip + ":" + PORT_MASTER_INFO);
|
|
970
|
-
|
|
971
|
-
let msg = { "input": "topics" }
|
|
972
|
-
var message = JSON.stringify(msg);
|
|
973
|
-
await requester.send(message)
|
|
974
|
-
const [result] = await requester.receive()
|
|
975
|
-
var results = JSON.parse(result.toString())
|
|
976
|
-
//console.log(results);
|
|
977
|
-
if (results["input"].includes(topic)) {
|
|
978
|
-
console.log("")
|
|
979
|
-
openpub(master_ip)
|
|
980
|
-
}
|
|
981
|
-
else {
|
|
982
|
-
console.log("Topic is not registered");
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
run()
|
|
986
|
-
});
|
|
987
|
-
|
|
988
|
-
program
|
|
989
|
-
.command('publish-eth <topic> <message>')
|
|
990
|
-
.description('Publish a JSON message to a NEP+ topic over Ethernet')
|
|
991
|
-
.action((topic, message) => {
|
|
992
|
-
|
|
993
|
-
const interfaces = os.networkInterfaces();
|
|
994
|
-
|
|
995
|
-
var openpub = function (master_ip = "127.0.0.1") {
|
|
996
|
-
|
|
997
|
-
var pubFunction = function () {
|
|
998
|
-
|
|
999
|
-
var msg = message.replace(/'/g, '"')
|
|
1000
|
-
console.log(JSON.parse(msg))
|
|
1001
|
-
pub.publish(JSON.parse(msg))
|
|
1002
|
-
console.log("Message published")
|
|
1003
|
-
|
|
1004
|
-
process.exit(1)
|
|
1005
|
-
}
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
var node = new nep.Node("nep-cli-pub")
|
|
1009
|
-
var pub = node.new_pub(topic, "json")
|
|
1010
|
-
setTimeout(pubFunction, 1000)
|
|
1011
|
-
}
|
|
1012
|
-
|
|
1013
|
-
async function run(master_ip) {
|
|
1014
|
-
var requester = new zmq.Request();
|
|
1015
|
-
requester.connect(`tcp://${master_ip}:${PORT_MASTER_INFO}`);
|
|
1016
|
-
|
|
1017
|
-
let msg = { "input": "topics" };
|
|
1018
|
-
var message = JSON.stringify(msg);
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
try {
|
|
1022
|
-
await requester.send(message);
|
|
1023
|
-
const [result] = await Promise.race([requester.receive(), timeoutPromise(5000)]); // Timeout of 5 seconds
|
|
1024
|
-
var results = JSON.parse(result.toString());
|
|
1025
|
-
|
|
1026
|
-
if (results["input"].includes(topic)) {
|
|
1027
|
-
console.log("");
|
|
1028
|
-
openpub(master_ip);
|
|
1029
|
-
} else {
|
|
1030
|
-
console.log("Topic is not registered");
|
|
1031
|
-
}
|
|
1032
|
-
} catch (error) {
|
|
1033
|
-
console.error("Error:", error.message);
|
|
1034
|
-
} finally {
|
|
1035
|
-
process.exit(1)
|
|
1036
|
-
}
|
|
1037
|
-
}
|
|
1038
|
-
|
|
1039
|
-
const ethernetInterface = interfaces['Ethernet'] || interfaces['Ethernet 2'] || interfaces['eth0'] || interfaces['イーサネット'] || interfaces['enp0s10'];
|
|
1040
|
-
if (ethernetInterface) {
|
|
1041
|
-
const ethernetIPv4 = ethernetInterface.find(iface => iface.family === 'IPv4');
|
|
1042
|
-
if (ethernetIPv4) {
|
|
1043
|
-
console.log(`Ethernet IP Address: ${ethernetIPv4.address}`);
|
|
1044
|
-
run(ethernetIPv4.address)
|
|
1045
|
-
} else {
|
|
1046
|
-
console.log('No Ethernet IPv4 address found.');
|
|
1047
|
-
}
|
|
1048
|
-
} else {
|
|
1049
|
-
console.log('Ethernet interface not found.');
|
|
1050
|
-
}
|
|
1051
|
-
});
|
|
1052
|
-
|
|
1053
|
-
program
|
|
1054
|
-
.command('publish-wifi <topic> <message>')
|
|
1055
|
-
.description('Publish a JSON message to a NEP+ topic over Wi-Fi')
|
|
1056
|
-
.action((topic, message) => {
|
|
1057
|
-
|
|
1058
|
-
const interfaces = os.networkInterfaces();
|
|
1059
|
-
|
|
1060
|
-
var openpub = function (master_ip = "127.0.0.1") {
|
|
1061
|
-
|
|
1062
|
-
var pubFunction = function () {
|
|
1063
|
-
|
|
1064
|
-
var msg = message.replace(/'/g, '"')
|
|
1065
|
-
console.log(JSON.parse(msg))
|
|
1066
|
-
pub.publish(JSON.parse(msg))
|
|
1067
|
-
console.log("Message published")
|
|
1068
|
-
|
|
1069
|
-
process.exit(1)
|
|
1070
|
-
}
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
var node = new nep.Node("nep-cli-pub")
|
|
1074
|
-
var pub = node.new_pub(topic, "json")
|
|
1075
|
-
setTimeout(pubFunction, 1000)
|
|
1076
|
-
}
|
|
1077
|
-
|
|
1078
|
-
async function run(master_ip) {
|
|
1079
|
-
var requester = new zmq.Request();
|
|
1080
|
-
requester.connect(`tcp://${master_ip}:${PORT_MASTER_INFO}`);
|
|
1081
|
-
|
|
1082
|
-
let msg = { "input": "topics" };
|
|
1083
|
-
var message = JSON.stringify(msg);
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
try {
|
|
1087
|
-
await requester.send(message);
|
|
1088
|
-
const [result] = await Promise.race([requester.receive(), timeoutPromise(5000)]); // Timeout of 5 seconds
|
|
1089
|
-
var results = JSON.parse(result.toString());
|
|
1090
|
-
|
|
1091
|
-
if (results["input"].includes(topic)) {
|
|
1092
|
-
console.log("");
|
|
1093
|
-
openpub(master_ip);
|
|
1094
|
-
} else {
|
|
1095
|
-
console.log("Topic is not registered");
|
|
1096
|
-
}
|
|
1097
|
-
} catch (error) {
|
|
1098
|
-
console.error("Error:", error.message);
|
|
1099
|
-
} finally {
|
|
1100
|
-
process.exit(1)
|
|
1101
|
-
}
|
|
1102
|
-
}
|
|
1103
|
-
const wifiInterface = interfaces['Wi-Fi'] || interfaces['Wi-Fi 2'] || interfaces['wlan0'] || interfaces['wlo1'];
|
|
1104
|
-
if (wifiInterface) {
|
|
1105
|
-
const wifiIPv4 = wifiInterface.find(iface => iface.family === 'IPv4');
|
|
1106
|
-
if (wifiIPv4) {
|
|
1107
|
-
console.log(`Wi-Fi IP Address: ${wifiIPv4.address}`);
|
|
1108
|
-
run(wifiIPv4.address)
|
|
1109
|
-
} else {
|
|
1110
|
-
console.log('No Wi-Fi IPv4 address found.');
|
|
1111
|
-
}
|
|
1112
|
-
} else {
|
|
1113
|
-
console.log('Wi-Fi interface not found.');
|
|
1114
|
-
}
|
|
1115
|
-
});
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
program
|
|
1119
|
-
.command('hz <topic>')
|
|
1120
|
-
.description('Monitor the publishing rate of a NEP+ topic in localhost')
|
|
1121
|
-
.action(async (topic) => {
|
|
1122
|
-
const interfaces = os.networkInterfaces();
|
|
1123
|
-
const master_ip = "127.0.0.1"; // Change to the appropriate master IP
|
|
1124
|
-
|
|
1125
|
-
const opensub = function () {
|
|
1126
|
-
const timestamps = []; // To store message timestamps
|
|
1127
|
-
|
|
1128
|
-
const callback = function (msg) {
|
|
1129
|
-
const date = new Date();
|
|
1130
|
-
const timestamp = date.getTime();
|
|
1131
|
-
|
|
1132
|
-
timestamps.push(timestamp);
|
|
1133
|
-
|
|
1134
|
-
// Remove timestamps older than ten seconds
|
|
1135
|
-
const tenSecondsAgo = timestamp - 10000;
|
|
1136
|
-
while (timestamps[0] < tenSecondsAgo) {
|
|
1137
|
-
timestamps.shift();
|
|
1138
|
-
}
|
|
1139
|
-
};
|
|
1140
|
-
|
|
1141
|
-
const messageFormat = topic.endsWith("/image") ? "string" : "string";
|
|
1142
|
-
const node = new nep.Node("nep-cli-sub");
|
|
1143
|
-
const conf = node.hybrid(master_ip);
|
|
1144
|
-
const sub = node.new_sub(topic, messageFormat, callback, conf);
|
|
1145
|
-
|
|
1146
|
-
setInterval(() => {
|
|
1147
|
-
// Calculate statistics for the last 10 seconds
|
|
1148
|
-
const now = Date.now();
|
|
1149
|
-
const tenSecondsAgo = now - 10000;
|
|
1150
|
-
const recentTimestamps = timestamps.filter((ts) => ts > tenSecondsAgo);
|
|
1151
|
-
const rate = recentTimestamps.length / 10; // Messages per second for a 10-second window
|
|
1152
|
-
|
|
1153
|
-
console.log("Average rate:", rate.toFixed(2), "Hz");
|
|
1154
|
-
console.log("Min:", (10 / Math.max(rate, 0.1)).toFixed(2), "s");
|
|
1155
|
-
console.log("Max:", (10 / Math.min(rate, 10)).toFixed(2), "s");
|
|
1156
|
-
console.log("Std dev:", calculateStdDev(recentTimestamps, now).toFixed(2), "s");
|
|
1157
|
-
console.log("Window:", recentTimestamps.length);
|
|
1158
|
-
console.log("");
|
|
1159
|
-
}, 1000);
|
|
1160
|
-
};
|
|
1161
|
-
|
|
1162
|
-
const calculateStdDev = (timestamps) => {
|
|
1163
|
-
if (timestamps.length < 2) {
|
|
1164
|
-
return 0; // Standard deviation is not meaningful with less than two timestamps
|
|
1165
|
-
}
|
|
1166
|
-
|
|
1167
|
-
// Calculate the time intervals between consecutive timestamps
|
|
1168
|
-
const timeIntervals = [];
|
|
1169
|
-
for (let i = 1; i < timestamps.length; i++) {
|
|
1170
|
-
const interval = timestamps[i] - timestamps[i - 1];
|
|
1171
|
-
timeIntervals.push(interval);
|
|
1172
|
-
}
|
|
1173
|
-
|
|
1174
|
-
// Calculate the mean (average) of the time intervals
|
|
1175
|
-
const mean = timeIntervals.reduce((acc, val) => acc + val, 0) / timeIntervals.length;
|
|
1176
|
-
|
|
1177
|
-
// Calculate the squared differences from the mean
|
|
1178
|
-
const squaredDifferences = timeIntervals.map((interval) => Math.pow(interval - mean, 2));
|
|
1179
|
-
|
|
1180
|
-
// Calculate the mean of the squared differences
|
|
1181
|
-
const meanSquaredDifference = squaredDifferences.reduce((acc, val) => acc + val, 0) / squaredDifferences.length;
|
|
1182
|
-
|
|
1183
|
-
// Calculate the square root of the mean squared difference
|
|
1184
|
-
const stdDeviation = Math.sqrt(meanSquaredDifference);
|
|
1185
|
-
|
|
1186
|
-
return stdDeviation;
|
|
1187
|
-
};
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
async function run() {
|
|
1191
|
-
const requester = new zmq.Request();
|
|
1192
|
-
requester.connect(`tcp://${master_ip}:${PORT_MASTER_INFO}`);
|
|
1193
|
-
|
|
1194
|
-
const msg = { "input": "topics" };
|
|
1195
|
-
const message = JSON.stringify(msg);
|
|
1196
|
-
await requester.send(message);
|
|
1197
|
-
const [result] = await requester.receive();
|
|
1198
|
-
const results = JSON.parse(result.toString());
|
|
1199
|
-
|
|
1200
|
-
if (results["state"] === "failure") {
|
|
1201
|
-
console.log("Topic is not registered, use *nep topics* to see the list of avaliable topics");
|
|
1202
|
-
} else {
|
|
1203
|
-
console.log("");
|
|
1204
|
-
if (results["input"].includes(topic)) {
|
|
1205
|
-
opensub();
|
|
1206
|
-
} else {
|
|
1207
|
-
console.log("Topic is not registered, use *nep topics* to see the list of avaliable topics");
|
|
1208
|
-
}
|
|
1209
|
-
}
|
|
1210
|
-
}
|
|
1211
|
-
|
|
1212
|
-
run();
|
|
1213
|
-
});
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
program
|
|
1217
|
-
.command('hz-wifi <topic>')
|
|
1218
|
-
.description('Monitor the publishing rate of a NEP+ topic over Wi-Fi')
|
|
1219
|
-
.action(async (topic) => {
|
|
1220
|
-
const interfaces = os.networkInterfaces();
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
const opensub = function (master_ip) {
|
|
1224
|
-
const timestamps = []; // To store message timestamps
|
|
1225
|
-
|
|
1226
|
-
const callback = function (msg) {
|
|
1227
|
-
const date = new Date();
|
|
1228
|
-
const timestamp = date.getTime();
|
|
1229
|
-
|
|
1230
|
-
timestamps.push(timestamp);
|
|
1231
|
-
|
|
1232
|
-
// Remove timestamps older than ten seconds
|
|
1233
|
-
const tenSecondsAgo = timestamp - 10000;
|
|
1234
|
-
while (timestamps[0] < tenSecondsAgo) {
|
|
1235
|
-
timestamps.shift();
|
|
1236
|
-
}
|
|
1237
|
-
};
|
|
1238
|
-
|
|
1239
|
-
const messageFormat = topic.endsWith("/image") ? "string" : "string";
|
|
1240
|
-
const node = new nep.Node("nep-cli-sub");
|
|
1241
|
-
const conf = node.hybrid(master_ip);
|
|
1242
|
-
const sub = node.new_sub(topic, messageFormat, callback, conf);
|
|
1243
|
-
|
|
1244
|
-
setInterval(() => {
|
|
1245
|
-
// Calculate statistics for the last 10 seconds
|
|
1246
|
-
const now = Date.now();
|
|
1247
|
-
const tenSecondsAgo = now - 10000;
|
|
1248
|
-
const recentTimestamps = timestamps.filter((ts) => ts > tenSecondsAgo);
|
|
1249
|
-
const rate = recentTimestamps.length / 10; // Messages per second for a 10-second window
|
|
1250
|
-
|
|
1251
|
-
console.log("Average rate:", rate.toFixed(2), "Hz");
|
|
1252
|
-
console.log("Min:", (10 / Math.max(rate, 0.1)).toFixed(2), "s");
|
|
1253
|
-
console.log("Max:", (10 / Math.min(rate, 10)).toFixed(2), "s");
|
|
1254
|
-
console.log("Std dev:", calculateStdDev(recentTimestamps, now).toFixed(2), "s");
|
|
1255
|
-
console.log("Window:", recentTimestamps.length);
|
|
1256
|
-
console.log("");
|
|
1257
|
-
}, 1000);
|
|
1258
|
-
};
|
|
1259
|
-
|
|
1260
|
-
const calculateStdDev = (timestamps) => {
|
|
1261
|
-
if (timestamps.length < 2) {
|
|
1262
|
-
return 0; // Standard deviation is not meaningful with less than two timestamps
|
|
1263
|
-
}
|
|
1264
|
-
|
|
1265
|
-
// Calculate the time intervals between consecutive timestamps
|
|
1266
|
-
const timeIntervals = [];
|
|
1267
|
-
for (let i = 1; i < timestamps.length; i++) {
|
|
1268
|
-
const interval = timestamps[i] - timestamps[i - 1];
|
|
1269
|
-
timeIntervals.push(interval);
|
|
1270
|
-
}
|
|
1271
|
-
|
|
1272
|
-
// Calculate the mean (average) of the time intervals
|
|
1273
|
-
const mean = timeIntervals.reduce((acc, val) => acc + val, 0) / timeIntervals.length;
|
|
1274
|
-
|
|
1275
|
-
// Calculate the squared differences from the mean
|
|
1276
|
-
const squaredDifferences = timeIntervals.map((interval) => Math.pow(interval - mean, 2));
|
|
1277
|
-
|
|
1278
|
-
// Calculate the mean of the squared differences
|
|
1279
|
-
const meanSquaredDifference = squaredDifferences.reduce((acc, val) => acc + val, 0) / squaredDifferences.length;
|
|
1280
|
-
|
|
1281
|
-
// Calculate the square root of the mean squared difference
|
|
1282
|
-
const stdDeviation = Math.sqrt(meanSquaredDifference);
|
|
1283
|
-
|
|
1284
|
-
return stdDeviation;
|
|
1285
|
-
};
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
async function run(master_ip) {
|
|
1289
|
-
const requester = new zmq.Request();
|
|
1290
|
-
requester.connect(`tcp://${master_ip}:${PORT_MASTER_INFO}`);
|
|
1291
|
-
|
|
1292
|
-
const msg = { "input": "topics" };
|
|
1293
|
-
const message = JSON.stringify(msg);
|
|
1294
|
-
await requester.send(message);
|
|
1295
|
-
const [result] = await requester.receive();
|
|
1296
|
-
const results = JSON.parse(result.toString());
|
|
1297
|
-
|
|
1298
|
-
if (results["state"] === "failure") {
|
|
1299
|
-
console.log("Topic is not registered, use *nep topics* to see the list of avaliable topics");
|
|
1300
|
-
} else {
|
|
1301
|
-
console.log("");
|
|
1302
|
-
if (results["input"].includes(topic)) {
|
|
1303
|
-
opensub(master_ip);
|
|
1304
|
-
} else {
|
|
1305
|
-
console.log("Topic is not registered, use *nep topics* to see the list of avaliable topics");
|
|
1306
|
-
}
|
|
1307
|
-
}
|
|
1308
|
-
}
|
|
1309
|
-
|
|
1310
|
-
const wifiInterface = interfaces['Wi-Fi'] || interfaces['Wi-Fi 2'] || interfaces['wlan0'] || interfaces['wlo1'];
|
|
1311
|
-
if (wifiInterface) {
|
|
1312
|
-
const wifiIPv4 = wifiInterface.find(iface => iface.family === 'IPv4');
|
|
1313
|
-
if (wifiIPv4) {
|
|
1314
|
-
console.log(`Wi-Fi IP Address: ${wifiIPv4.address}`);
|
|
1315
|
-
run(wifiIPv4.address)
|
|
1316
|
-
} else {
|
|
1317
|
-
console.log('No Wi-Fi IPv4 address found.');
|
|
1318
|
-
}
|
|
1319
|
-
} else {
|
|
1320
|
-
console.log('Wi-Fi interface not found.');
|
|
1321
|
-
}
|
|
1322
|
-
});
|
|
1323
|
-
|
|
1324
|
-
program
|
|
1325
|
-
.command('hz-eth <topic>')
|
|
1326
|
-
.description('Monitor the publishing rate of a NEP+ topic over Ethernet')
|
|
1327
|
-
.action(async (topic) => {
|
|
1328
|
-
const interfaces = os.networkInterfaces();
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
const opensub = function (master_ip) {
|
|
1332
|
-
const timestamps = []; // To store message timestamps
|
|
1333
|
-
|
|
1334
|
-
const callback = function (msg) {
|
|
1335
|
-
const date = new Date();
|
|
1336
|
-
const timestamp = date.getTime();
|
|
1337
|
-
|
|
1338
|
-
timestamps.push(timestamp);
|
|
1339
|
-
|
|
1340
|
-
// Remove timestamps older than ten seconds
|
|
1341
|
-
const tenSecondsAgo = timestamp - 10000;
|
|
1342
|
-
while (timestamps[0] < tenSecondsAgo) {
|
|
1343
|
-
timestamps.shift();
|
|
1344
|
-
}
|
|
1345
|
-
};
|
|
1346
|
-
|
|
1347
|
-
const messageFormat = topic.endsWith("/image") ? "string" : "string";
|
|
1348
|
-
const node = new nep.Node("nep-cli-sub");
|
|
1349
|
-
const conf = node.hybrid(master_ip);
|
|
1350
|
-
const sub = node.new_sub(topic, messageFormat, callback, conf);
|
|
1351
|
-
|
|
1352
|
-
setInterval(() => {
|
|
1353
|
-
// Calculate statistics for the last 10 seconds
|
|
1354
|
-
const now = Date.now();
|
|
1355
|
-
const tenSecondsAgo = now - 10000;
|
|
1356
|
-
const recentTimestamps = timestamps.filter((ts) => ts > tenSecondsAgo);
|
|
1357
|
-
const rate = recentTimestamps.length / 10; // Messages per second for a 10-second window
|
|
1358
|
-
|
|
1359
|
-
console.log("Average rate:", rate.toFixed(2), "Hz");
|
|
1360
|
-
console.log("Min:", (10 / Math.max(rate, 0.1)).toFixed(2), "s");
|
|
1361
|
-
console.log("Max:", (10 / Math.min(rate, 10)).toFixed(2), "s");
|
|
1362
|
-
console.log("Std dev:", calculateStdDev(recentTimestamps, now).toFixed(2), "s");
|
|
1363
|
-
console.log("Window:", recentTimestamps.length);
|
|
1364
|
-
console.log("");
|
|
1365
|
-
}, 1000);
|
|
1366
|
-
};
|
|
1367
|
-
|
|
1368
|
-
const calculateStdDev = (timestamps) => {
|
|
1369
|
-
if (timestamps.length < 2) {
|
|
1370
|
-
return 0; // Standard deviation is not meaningful with less than two timestamps
|
|
1371
|
-
}
|
|
1372
|
-
|
|
1373
|
-
// Calculate the time intervals between consecutive timestamps
|
|
1374
|
-
const timeIntervals = [];
|
|
1375
|
-
for (let i = 1; i < timestamps.length; i++) {
|
|
1376
|
-
const interval = timestamps[i] - timestamps[i - 1];
|
|
1377
|
-
timeIntervals.push(interval);
|
|
1378
|
-
}
|
|
1379
|
-
|
|
1380
|
-
// Calculate the mean (average) of the time intervals
|
|
1381
|
-
const mean = timeIntervals.reduce((acc, val) => acc + val, 0) / timeIntervals.length;
|
|
1382
|
-
|
|
1383
|
-
// Calculate the squared differences from the mean
|
|
1384
|
-
const squaredDifferences = timeIntervals.map((interval) => Math.pow(interval - mean, 2));
|
|
1385
|
-
|
|
1386
|
-
// Calculate the mean of the squared differences
|
|
1387
|
-
const meanSquaredDifference = squaredDifferences.reduce((acc, val) => acc + val, 0) / squaredDifferences.length;
|
|
1388
|
-
|
|
1389
|
-
// Calculate the square root of the mean squared difference
|
|
1390
|
-
const stdDeviation = Math.sqrt(meanSquaredDifference);
|
|
1391
|
-
|
|
1392
|
-
return stdDeviation;
|
|
1393
|
-
};
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
async function run(master_ip) {
|
|
1397
|
-
const requester = new zmq.Request();
|
|
1398
|
-
requester.connect(`tcp://${master_ip}:${PORT_MASTER_INFO}`);
|
|
1399
|
-
|
|
1400
|
-
const msg = { "input": "topics" };
|
|
1401
|
-
const message = JSON.stringify(msg);
|
|
1402
|
-
await requester.send(message);
|
|
1403
|
-
const [result] = await requester.receive();
|
|
1404
|
-
const results = JSON.parse(result.toString());
|
|
1405
|
-
|
|
1406
|
-
if (results["state"] === "failure") {
|
|
1407
|
-
console.log("Topic is not registered, use *nep topics* to see the list of avaliable topics");
|
|
1408
|
-
} else {
|
|
1409
|
-
console.log("");
|
|
1410
|
-
if (results["input"].includes(topic)) {
|
|
1411
|
-
opensub(master_ip);
|
|
1412
|
-
} else {
|
|
1413
|
-
console.log("Topic is not registered, use *nep topics* to see the list of avaliable topics");
|
|
1414
|
-
}
|
|
1415
|
-
}
|
|
1416
|
-
}
|
|
1417
|
-
|
|
1418
|
-
const ethernetInterface = interfaces['Ethernet'] || interfaces['Ethernet 2'] || interfaces['eth0'] || interfaces['イーサネット'] || interfaces['enp0s10'];
|
|
1419
|
-
if (ethernetInterface) {
|
|
1420
|
-
const ethernetIPv4 = ethernetInterface.find(iface => iface.family === 'IPv4');
|
|
1421
|
-
if (ethernetIPv4) {
|
|
1422
|
-
console.log(`Ethernet IP Address: ${ethernetIPv4.address}`);
|
|
1423
|
-
run(ethernetIPv4.address)
|
|
1424
|
-
} else {
|
|
1425
|
-
console.log('No Ethernet IPv4 address found.');
|
|
1426
|
-
}
|
|
1427
|
-
} else {
|
|
1428
|
-
console.log('Ethernet interface not found.');
|
|
1429
|
-
}
|
|
1430
|
-
});
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
program
|
|
1434
|
-
.command('docs')
|
|
1435
|
-
.description('Open the NEP+ documentation in the default browser')
|
|
1436
|
-
.action(async () => {
|
|
1437
|
-
const url = 'https://enrique-coronado.gitbook.io/nep-docs/';
|
|
719
|
+
.command('docs')
|
|
720
|
+
.description('Open the NEP+ documentation in the default browser')
|
|
721
|
+
.action(async () => {
|
|
722
|
+
const url = 'https://enrique-coronado.gitbook.io/nep-docs/';
|
|
1438
723
|
|
|
1439
724
|
try {
|
|
1440
725
|
const open = await import('open');
|
|
@@ -1444,107 +729,6 @@ program
|
|
|
1444
729
|
}
|
|
1445
730
|
});
|
|
1446
731
|
|
|
1447
|
-
function timeoutPromise(ms) {
|
|
1448
|
-
return new Promise((resolve, reject) => {
|
|
1449
|
-
setTimeout(() => {
|
|
1450
|
-
reject(new Error("Request timed out"));
|
|
1451
|
-
}, ms);
|
|
1452
|
-
});
|
|
1453
|
-
}
|
|
1454
|
-
|
|
1455
|
-
function timeoutPromise(ms) {
|
|
1456
|
-
return new Promise((resolve, reject) => {
|
|
1457
|
-
setTimeout(() => {
|
|
1458
|
-
reject(new Error("Request timed out"));
|
|
1459
|
-
}, ms);
|
|
1460
|
-
});
|
|
1461
|
-
}
|
|
1462
|
-
|
|
1463
|
-
async function getAndDisplayTopics(master_ip) {
|
|
1464
|
-
const TIMEOUT_DURATION = 5000;
|
|
1465
|
-
|
|
1466
|
-
var requester = new zmq.Request();
|
|
1467
|
-
requester.connect(`tcp://${master_ip}:${PORT_MASTER_INFO}`);
|
|
1468
|
-
|
|
1469
|
-
let msg = { "input": "topics" };
|
|
1470
|
-
var message = JSON.stringify(msg);
|
|
1471
|
-
|
|
1472
|
-
try {
|
|
1473
|
-
const responsePromise = new Promise(async (resolve, reject) => {
|
|
1474
|
-
await requester.send(message);
|
|
1475
|
-
const [result] = await requester.receive();
|
|
1476
|
-
var results = JSON.parse(result.toString());
|
|
1477
|
-
resolve(results);
|
|
1478
|
-
});
|
|
1479
|
-
|
|
1480
|
-
const timeoutPromise = new Promise((resolve, reject) => {
|
|
1481
|
-
setTimeout(() => {
|
|
1482
|
-
reject(new Error("Timed out, NEP master over Wi-Fi was not found"));
|
|
1483
|
-
}, TIMEOUT_DURATION);
|
|
1484
|
-
});
|
|
1485
|
-
|
|
1486
|
-
const results = await Promise.race([responsePromise, timeoutPromise]);
|
|
1487
|
-
|
|
1488
|
-
if (results["state"] === "success") {
|
|
1489
|
-
availableTopics = results["input"];
|
|
1490
|
-
console.log("");
|
|
1491
|
-
results["input"].forEach(element => {
|
|
1492
|
-
console.log(element);
|
|
1493
|
-
});
|
|
1494
|
-
} else {
|
|
1495
|
-
console.log("No topics yet");
|
|
1496
|
-
}
|
|
1497
|
-
} catch (error) {
|
|
1498
|
-
console.error("Error:", error.message);
|
|
1499
|
-
} finally {
|
|
1500
|
-
process.exit();
|
|
1501
|
-
}
|
|
1502
|
-
}
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
async function getAndDisplayTopics(master_ip) {
|
|
1508
|
-
const TIMEOUT_DURATION = 5000;
|
|
1509
|
-
|
|
1510
|
-
var requester = new zmq.Request();
|
|
1511
|
-
requester.connect(`tcp://${master_ip}:${PORT_MASTER_INFO}`);
|
|
1512
|
-
|
|
1513
|
-
let msg = { "input": "topics" };
|
|
1514
|
-
var message = JSON.stringify(msg);
|
|
1515
|
-
|
|
1516
|
-
try {
|
|
1517
|
-
const responsePromise = new Promise(async (resolve, reject) => {
|
|
1518
|
-
await requester.send(message);
|
|
1519
|
-
const [result] = await requester.receive();
|
|
1520
|
-
var results = JSON.parse(result.toString());
|
|
1521
|
-
resolve(results);
|
|
1522
|
-
});
|
|
1523
|
-
|
|
1524
|
-
const timeoutPromise = new Promise((resolve, reject) => {
|
|
1525
|
-
setTimeout(() => {
|
|
1526
|
-
reject(new Error("Timed out, NEP master over Ethernet was not found"));
|
|
1527
|
-
}, TIMEOUT_DURATION);
|
|
1528
|
-
});
|
|
1529
|
-
|
|
1530
|
-
const results = await Promise.race([responsePromise, timeoutPromise]);
|
|
1531
|
-
|
|
1532
|
-
if (results["state"] === "success") {
|
|
1533
|
-
availableTopics = results["input"];
|
|
1534
|
-
console.log("");
|
|
1535
|
-
results["input"].forEach(element => {
|
|
1536
|
-
console.log(element);
|
|
1537
|
-
});
|
|
1538
|
-
} else {
|
|
1539
|
-
console.log("No topics yet");
|
|
1540
|
-
}
|
|
1541
|
-
} catch (error) {
|
|
1542
|
-
console.error("Error:", error.message);
|
|
1543
|
-
} finally {
|
|
1544
|
-
process.exit();
|
|
1545
|
-
}
|
|
1546
|
-
}
|
|
1547
|
-
|
|
1548
732
|
|
|
1549
733
|
program.parse(process.argv);
|
|
1550
734
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nep-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"main": "./lib/nep.js",
|
|
5
5
|
"bin": {
|
|
6
6
|
"nep": "./bin/index.js"
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"express": "^4.18.2",
|
|
15
15
|
"fix-path": "^2.1.0",
|
|
16
16
|
"inquirer": "^9.2.10",
|
|
17
|
-
"nep-js": "
|
|
17
|
+
"nep-js": "0.3.5",
|
|
18
18
|
"open": "7.4.2",
|
|
19
19
|
"socket.io": "^4.7.2",
|
|
20
20
|
"zeromq": "6.0.0-beta.6"
|