nep-cli 0.1.5 → 0.1.6
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 +127 -72
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -323,48 +323,6 @@ program
|
|
|
323
323
|
|
|
324
324
|
|
|
325
325
|
program
|
|
326
|
-
.command('open [programName]')
|
|
327
|
-
.description('Open a program in Windows/macOS')
|
|
328
|
-
.action(async (programName) => {
|
|
329
|
-
const programs = ['cameras', 'hxri'];
|
|
330
|
-
|
|
331
|
-
// If a program name is provided as an argument, use it; otherwise, show autocomplete
|
|
332
|
-
if (!programName) {
|
|
333
|
-
const autoComplete = new AutoComplete({
|
|
334
|
-
name: 'program',
|
|
335
|
-
message: 'Select a program:',
|
|
336
|
-
choices: programs,
|
|
337
|
-
});
|
|
338
|
-
programName = await autoComplete.run();
|
|
339
|
-
} else if (!programs.includes(programName)) {
|
|
340
|
-
const autoComplete = new AutoComplete({
|
|
341
|
-
name: 'program',
|
|
342
|
-
message: 'Invalid program name. Select a valid program:',
|
|
343
|
-
choices: programs,
|
|
344
|
-
});
|
|
345
|
-
programName = await autoComplete.run();
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
// Get the username of the logged-in user
|
|
349
|
-
const username = os.userInfo().username;
|
|
350
|
-
|
|
351
|
-
// Specify the path to the executable
|
|
352
|
-
const appFolderName = 'nepplus' + "-" + programName;
|
|
353
|
-
const executableName = 'nepplus' + "-" + `${programName}.exe`;
|
|
354
|
-
const executablePath = `C:\\Users\\${username}\\AppData\\Local\\Programs\\${appFolderName}\\${executableName}`;
|
|
355
|
-
|
|
356
|
-
// Run the executable with proper escaping
|
|
357
|
-
exec(`"${executablePath}"`, (error, stdout, stderr) => {
|
|
358
|
-
if (error) {
|
|
359
|
-
console.error(`Error: ${error.message}`);
|
|
360
|
-
return;
|
|
361
|
-
}
|
|
362
|
-
console.log(`stdout: ${stdout}`);
|
|
363
|
-
console.error(`stderr: ${stderr}`);
|
|
364
|
-
});
|
|
365
|
-
});
|
|
366
|
-
|
|
367
|
-
program
|
|
368
326
|
.command('open [programName]')
|
|
369
327
|
.description('Open NEP+ GUI')
|
|
370
328
|
.action(async (programName) => {
|
|
@@ -428,11 +386,11 @@ program
|
|
|
428
386
|
});
|
|
429
387
|
|
|
430
388
|
program
|
|
431
|
-
.command('master-ip <ip>'
|
|
389
|
+
.command('master-ip <ip>')
|
|
432
390
|
.description('Start NEP master in some specific IP')
|
|
433
391
|
.action(async (ip) => {
|
|
434
392
|
|
|
435
|
-
|
|
393
|
+
|
|
436
394
|
console.log(`IP Address: ${ip}`);
|
|
437
395
|
var node = new nep.Node("nep-cli");
|
|
438
396
|
nep_configuration["IP"] = ip;
|
|
@@ -870,6 +828,103 @@ program
|
|
|
870
828
|
run();
|
|
871
829
|
});
|
|
872
830
|
|
|
831
|
+
program
|
|
832
|
+
.command('monitor <topic>')
|
|
833
|
+
.description('Monitor the publishing rate of NEP+ topic in local host')
|
|
834
|
+
.action(async (topic) => {
|
|
835
|
+
const interfaces = os.networkInterfaces();
|
|
836
|
+
const master_ip = "127.0.0.1"; // Change to the appropriate master IP
|
|
837
|
+
|
|
838
|
+
const opensub = function () {
|
|
839
|
+
const timestamps = []; // To store message timestamps
|
|
840
|
+
|
|
841
|
+
const callback = function (msg) {
|
|
842
|
+
const date = new Date();
|
|
843
|
+
const timestamp = date.getTime();
|
|
844
|
+
|
|
845
|
+
timestamps.push(timestamp);
|
|
846
|
+
|
|
847
|
+
// Remove timestamps older than ten seconds
|
|
848
|
+
const tenSecondsAgo = timestamp - 10000;
|
|
849
|
+
while (timestamps[0] < tenSecondsAgo) {
|
|
850
|
+
timestamps.shift();
|
|
851
|
+
}
|
|
852
|
+
};
|
|
853
|
+
|
|
854
|
+
const messageFormat = topic.endsWith("/image") ? "string" : "string";
|
|
855
|
+
const node = new nep.Node("nep-cli-sub");
|
|
856
|
+
const conf = node.hybrid(master_ip);
|
|
857
|
+
const sub = node.new_sub(topic, messageFormat, callback, conf);
|
|
858
|
+
|
|
859
|
+
setInterval(() => {
|
|
860
|
+
// Calculate statistics for the last 10 seconds
|
|
861
|
+
const now = Date.now();
|
|
862
|
+
const tenSecondsAgo = now - 10000;
|
|
863
|
+
const recentTimestamps = timestamps.filter((ts) => ts > tenSecondsAgo);
|
|
864
|
+
const rate = recentTimestamps.length / 10; // Messages per second for a 10-second window
|
|
865
|
+
|
|
866
|
+
console.log("Average rate:", rate.toFixed(2), "Hz");
|
|
867
|
+
console.log("Min:", (10 / Math.max(rate, 0.1)).toFixed(2), "s");
|
|
868
|
+
console.log("Max:", (10 / Math.min(rate, 10)).toFixed(2), "s");
|
|
869
|
+
console.log("Std dev:", calculateStdDev(recentTimestamps, now).toFixed(2), "s");
|
|
870
|
+
console.log("Window:", recentTimestamps.length);
|
|
871
|
+
console.log("");
|
|
872
|
+
}, 1000);
|
|
873
|
+
};
|
|
874
|
+
|
|
875
|
+
const calculateStdDev = (timestamps) => {
|
|
876
|
+
if (timestamps.length < 2) {
|
|
877
|
+
return 0; // Standard deviation is not meaningful with less than two timestamps
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
// Calculate the time intervals between consecutive timestamps
|
|
881
|
+
const timeIntervals = [];
|
|
882
|
+
for (let i = 1; i < timestamps.length; i++) {
|
|
883
|
+
const interval = timestamps[i] - timestamps[i - 1];
|
|
884
|
+
timeIntervals.push(interval);
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
// Calculate the mean (average) of the time intervals
|
|
888
|
+
const mean = timeIntervals.reduce((acc, val) => acc + val, 0) / timeIntervals.length;
|
|
889
|
+
|
|
890
|
+
// Calculate the squared differences from the mean
|
|
891
|
+
const squaredDifferences = timeIntervals.map((interval) => Math.pow(interval - mean, 2));
|
|
892
|
+
|
|
893
|
+
// Calculate the mean of the squared differences
|
|
894
|
+
const meanSquaredDifference = squaredDifferences.reduce((acc, val) => acc + val, 0) / squaredDifferences.length;
|
|
895
|
+
|
|
896
|
+
// Calculate the square root of the mean squared difference
|
|
897
|
+
const stdDeviation = Math.sqrt(meanSquaredDifference);
|
|
898
|
+
|
|
899
|
+
return stdDeviation;
|
|
900
|
+
};
|
|
901
|
+
|
|
902
|
+
|
|
903
|
+
async function run() {
|
|
904
|
+
const requester = new zmq.Request();
|
|
905
|
+
requester.connect(`tcp://${master_ip}:${PORT_MASTER_INFO}`);
|
|
906
|
+
|
|
907
|
+
const msg = { "input": "topics" };
|
|
908
|
+
const message = JSON.stringify(msg);
|
|
909
|
+
await requester.send(message);
|
|
910
|
+
const [result] = await requester.receive();
|
|
911
|
+
const results = JSON.parse(result.toString());
|
|
912
|
+
|
|
913
|
+
if (results["state"] === "failure") {
|
|
914
|
+
console.log("Topic is not registered, use *nep topics* to see the list of avaliable topics");
|
|
915
|
+
} else {
|
|
916
|
+
console.log("");
|
|
917
|
+
if (results["input"].includes(topic)) {
|
|
918
|
+
opensub();
|
|
919
|
+
} else {
|
|
920
|
+
console.log("Topic is not registered, use *nep topics* to see the list of avaliable topics");
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
run();
|
|
926
|
+
});
|
|
927
|
+
|
|
873
928
|
program
|
|
874
929
|
.command('eth-listen <topic>')
|
|
875
930
|
.description('Subscribe to a NEP+ topic over Ethernet')
|
|
@@ -1062,7 +1117,7 @@ program
|
|
|
1062
1117
|
var master_ip = "127.0.0.1"
|
|
1063
1118
|
var port = PORT_IMAGE
|
|
1064
1119
|
|
|
1065
|
-
|
|
1120
|
+
|
|
1066
1121
|
|
|
1067
1122
|
requester.connect("tcp://" + master_ip + ":" + PORT_MASTER_INFO);
|
|
1068
1123
|
|
|
@@ -1072,37 +1127,37 @@ program
|
|
|
1072
1127
|
const [result] = await requester.receive()
|
|
1073
1128
|
var results = JSON.parse(result.toString())
|
|
1074
1129
|
//console.log(results);
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1130
|
+
|
|
1131
|
+
|
|
1132
|
+
const programs = results["input"];
|
|
1133
|
+
const filteredList = programs.filter(value => value.includes("image"));
|
|
1134
|
+
|
|
1135
|
+
if (!topic) {
|
|
1136
|
+
const autoComplete = new AutoComplete({
|
|
1137
|
+
name: 'program',
|
|
1138
|
+
message: 'Select a program:',
|
|
1139
|
+
choices: filteredList,
|
|
1140
|
+
});
|
|
1141
|
+
topic = await autoComplete.run();
|
|
1142
|
+
} else if (!filteredList.includes(topic)) {
|
|
1143
|
+
const autoComplete = new AutoComplete({
|
|
1144
|
+
name: 'program',
|
|
1145
|
+
message: 'Invalid program name. Select a valid program:',
|
|
1146
|
+
choices: filteredList,
|
|
1147
|
+
});
|
|
1148
|
+
topic = await autoComplete.run();
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
|
|
1152
|
+
startServer(port, topic);
|
|
1153
|
+
open(`http://localhost:${port}`);
|
|
1154
|
+
|
|
1100
1155
|
}
|
|
1101
1156
|
run()
|
|
1102
|
-
|
|
1157
|
+
|
|
1103
1158
|
});
|
|
1104
1159
|
|
|
1105
|
-
|
|
1160
|
+
// Function to start the server
|
|
1106
1161
|
function startServer(port, topic) {
|
|
1107
1162
|
const app = express();
|
|
1108
1163
|
const server = http.createServer(app);
|