nep-cli 0.1.4 → 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/image.html ADDED
@@ -0,0 +1,57 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>NEP+ Image</title>
8
+ <!-- Include Vue 2 and Vuetify 2 from CDN -->
9
+ <link href="https://cdn.jsdelivr.net/npm/vuetify@2.6.3/dist/vuetify.min.css" rel="stylesheet">
10
+ <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
11
+ <script src="https://cdn.jsdelivr.net/npm/vuetify@2.6.3/dist/vuetify.js"></script>
12
+ </head>
13
+
14
+ <body>
15
+ <div id="app">
16
+ <v-app>
17
+ <v-container>
18
+ <v-toolbar dense color="transparent">
19
+ <v-toolbar-title>Camera USB</v-toolbar-title>
20
+ <v-spacer></v-spacer>
21
+
22
+ </v-toolbar>
23
+ <v-row>
24
+ <v-col>
25
+ <v-card color="#1A1A1A">
26
+ <v-img :src="imageSrc" alt="Streamed Image" contain></v-img>
27
+ </v-card>
28
+ </v-col>
29
+ </v-row>
30
+ </v-container>
31
+ </v-app>
32
+ </div>
33
+ <script src="/socket.io/socket.io.js"></script> <!-- Include the Socket.IO client library -->
34
+ <script>
35
+ // Initialize Vue and Vuetify
36
+ new Vue({
37
+ el: '#app',
38
+ vuetify: new Vuetify(),
39
+ data() {
40
+ return {
41
+ imageSrc: '', // Initialize the image source as empty
42
+ };
43
+ },
44
+ mounted() {
45
+ const image = document.getElementById('image');
46
+ const socket = io.connect('http://localhost:3000'); // Connect to your server
47
+
48
+ socket.on('image', (data) => {
49
+ // Set the received image data as the image source
50
+ this.imageSrc = `data:image/jpeg;base64,${data.image}`;
51
+ });
52
+ },
53
+ });
54
+ </script>
55
+ </body>
56
+
57
+ </html>
package/bin/index.js CHANGED
@@ -8,6 +8,14 @@ var nep_configuration = { current_port: 10000, IP: "127.0.0.1", brokers: {} }
8
8
  const { exec } = require('child_process');
9
9
  const { AutoComplete } = require('enquirer');
10
10
 
11
+ const open = require('open'); // Import the 'open' package
12
+
13
+ const express = require('express');
14
+ const http = require('http');
15
+ const socketIo = require('socket.io');
16
+ const fs = require('fs');
17
+ const zmqc = require("zeromq/v5-compat");
18
+
11
19
 
12
20
  // Node saved here
13
21
  var nodes_register = {};
@@ -246,6 +254,12 @@ var processMsg = function (json_msg, nodes_register, topic_register) {
246
254
  }
247
255
 
248
256
  const PORT_MASTER_INFO = 7010; // Default port for master info
257
+ const PORT_IMAGE = 3000;
258
+ const PORT_IMAGES = [];
259
+ for (let i = 3020; i <= 3040; i++) {
260
+ PORT_IMAGES.push(i);
261
+ }
262
+
249
263
 
250
264
  program
251
265
  .version('"0.1.2')
@@ -310,9 +324,9 @@ program
310
324
 
311
325
  program
312
326
  .command('open [programName]')
313
- .description('Open a program in Windows/macOS')
327
+ .description('Open NEP+ GUI')
314
328
  .action(async (programName) => {
315
- const programs = ['camera', 'hxri', 'rize', 'sharo'];
329
+ const programs = ['cameras', 'hxri'];
316
330
 
317
331
  // If a program name is provided as an argument, use it; otherwise, show autocomplete
318
332
  if (!programName) {
@@ -350,6 +364,9 @@ program
350
364
  });
351
365
  });
352
366
 
367
+
368
+
369
+
353
370
  program
354
371
  .command('master')
355
372
  .description('Start NEP master in Local host')
@@ -369,11 +386,11 @@ program
369
386
  });
370
387
 
371
388
  program
372
- .command('master-ip <ip>' )
389
+ .command('master-ip <ip>')
373
390
  .description('Start NEP master in some specific IP')
374
391
  .action(async (ip) => {
375
392
 
376
-
393
+
377
394
  console.log(`IP Address: ${ip}`);
378
395
  var node = new nep.Node("nep-cli");
379
396
  nep_configuration["IP"] = ip;
@@ -811,6 +828,103 @@ program
811
828
  run();
812
829
  });
813
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
+
814
928
  program
815
929
  .command('eth-listen <topic>')
816
930
  .description('Subscribe to a NEP+ topic over Ethernet')
@@ -994,6 +1108,84 @@ async function getAndDisplayTopics(master_ip) {
994
1108
  }
995
1109
  }
996
1110
 
1111
+ program
1112
+ .command('image <topic>')
1113
+ .description('Start image server')
1114
+ .action((topic, options) => {
1115
+ async function run() {
1116
+ var requester = new zmq.Request;
1117
+ var master_ip = "127.0.0.1"
1118
+ var port = PORT_IMAGE
1119
+
1120
+
1121
+
1122
+ requester.connect("tcp://" + master_ip + ":" + PORT_MASTER_INFO);
1123
+
1124
+ let msg = { "input": "topics" }
1125
+ var message = JSON.stringify(msg);
1126
+ await requester.send(message)
1127
+ const [result] = await requester.receive()
1128
+ var results = JSON.parse(result.toString())
1129
+ //console.log(results);
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
+
1155
+ }
1156
+ run()
1157
+
1158
+ });
1159
+
1160
+ // Function to start the server
1161
+ function startServer(port, topic) {
1162
+ const app = express();
1163
+ const server = http.createServer(app);
1164
+ const io = socketIo(server);
1165
+
1166
+ var node = new nep.Node("nep-cli");
1167
+
1168
+ function getImage(msg) {
1169
+ // Send the received image data as-is to connected clients
1170
+ io.sockets.emit('image', { image: msg });
1171
+ }
1172
+
1173
+ var sub = node.new_sub(topic, "image", getImage);
1174
+
1175
+ app.get('/', (req, res) => {
1176
+ res.sendFile(__dirname + '/image.html'); // Serve your HTML file
1177
+ });
1178
+
1179
+ server.listen(port, () => {
1180
+ console.log(`Server is running on http://localhost:${port}`);
1181
+ });
1182
+
1183
+ io.on('connection', (socket) => {
1184
+ const frameRate = 30; // Desired frame rate
1185
+ const interval = 1000 / frameRate; // Interval between frames
1186
+ });
1187
+ }
1188
+
997
1189
  program.parse(process.argv);
998
1190
 
999
1191
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nep-cli",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "main": "./lib/nep.js",
5
5
  "bin": {
6
6
  "nep": "./bin/index.js"
@@ -11,10 +11,12 @@
11
11
  "dependencies": {
12
12
  "commander": "^11.0.0",
13
13
  "enquirer": "^2.4.1",
14
+ "express": "^4.18.2",
14
15
  "fix-path": "^2.1.0",
15
16
  "inquirer": "^9.2.10",
16
- "nep-js": "^0.2.2",
17
- "open": "^9.1.0",
17
+ "nep-js": "^0.3.0",
18
+ "open": "7.4.2",
19
+ "socket.io": "^4.7.2",
18
20
  "zeromq": "6.0.0-beta.6"
19
21
  }
20
22
  }