nep-cli 0.1.5 → 0.1.7

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 CHANGED
@@ -267,7 +267,7 @@ program
267
267
 
268
268
  program
269
269
  .command('ip')
270
- .description('Display current Wi-Fi and Ethernet IP addresses')
270
+ .description('Display current Wi-Fi and Ethernet IP addresses of this computer')
271
271
  .action(() => {
272
272
  const interfaces = os.networkInterfaces();
273
273
 
@@ -324,7 +324,7 @@ program
324
324
 
325
325
  program
326
326
  .command('open [programName]')
327
- .description('Open a program in Windows/macOS')
327
+ .description('Open a NEP+ GUI')
328
328
  .action(async (programName) => {
329
329
  const programs = ['cameras', 'hxri'];
330
330
 
@@ -364,54 +364,11 @@ program
364
364
  });
365
365
  });
366
366
 
367
- program
368
- .command('open [programName]')
369
- .description('Open NEP+ GUI')
370
- .action(async (programName) => {
371
- const programs = ['cameras', 'hxri'];
372
-
373
- // If a program name is provided as an argument, use it; otherwise, show autocomplete
374
- if (!programName) {
375
- const autoComplete = new AutoComplete({
376
- name: 'program',
377
- message: 'Select a program:',
378
- choices: programs,
379
- });
380
- programName = await autoComplete.run();
381
- } else if (!programs.includes(programName)) {
382
- const autoComplete = new AutoComplete({
383
- name: 'program',
384
- message: 'Invalid program name. Select a valid program:',
385
- choices: programs,
386
- });
387
- programName = await autoComplete.run();
388
- }
389
-
390
- // Get the username of the logged-in user
391
- const username = os.userInfo().username;
392
-
393
- // Specify the path to the executable
394
- const appFolderName = 'nepplus' + "-" + programName;
395
- const executableName = 'nepplus' + "-" + `${programName}.exe`;
396
- const executablePath = `C:\\Users\\${username}\\AppData\\Local\\Programs\\${appFolderName}\\${executableName}`;
397
-
398
- // Run the executable with proper escaping
399
- exec(`"${executablePath}"`, (error, stdout, stderr) => {
400
- if (error) {
401
- console.error(`Error: ${error.message}`);
402
- return;
403
- }
404
- console.log(`stdout: ${stdout}`);
405
- console.error(`stderr: ${stderr}`);
406
- });
407
- });
408
-
409
-
410
367
 
411
368
 
412
369
  program
413
370
  .command('master')
414
- .description('Start NEP master in Local host')
371
+ .description('Start NEP master in localhost')
415
372
  .action(async () => {
416
373
  try {
417
374
  var node = new nep.Node("nep-cli");
@@ -428,22 +385,40 @@ program
428
385
  });
429
386
 
430
387
  program
431
- .command('master-ip <ip>' )
432
- .description('Start NEP master in some specific IP')
433
- .action(async (ip) => {
434
-
435
-
436
- console.log(`IP Address: ${ip}`);
437
- var node = new nep.Node("nep-cli");
438
- nep_configuration["IP"] = ip;
439
- var master = new MasterLocal(IP = ip);
440
- var info = new nep.MasterInfoServer(IP = ip, topics = topic_register);
388
+ .command('master-wifi')
389
+ .description('Start NEP master in Wi-Fi network')
390
+ .action(async () => {
441
391
 
442
- });
392
+ const interfaces = os.networkInterfaces();
443
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
+ }
444
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
+ });
445
420
  program
446
- .command('eth')
421
+ .command('master-eth')
447
422
  .description('Start NEP master in Ethernet network')
448
423
  .action(async () => {
449
424
 
@@ -468,39 +443,20 @@ program
468
443
 
469
444
 
470
445
  program
471
- .command('wifi')
472
- .description('Start NEP master in Wi-Fi network')
473
- .action(async () => {
446
+ .command('master-ip <ip>')
447
+ .description('Start NEP master in some specific IP')
448
+ .action(async (ip) => {
474
449
 
475
- const interfaces = os.networkInterfaces();
476
450
 
477
- // Find Wi-Fi interface
478
- const wifiInterface = interfaces['Wi-Fi'] || interfaces['Wi-Fi 2'] || interfaces['wlan0'] || interfaces['wlo1'];
479
- if (wifiInterface) {
480
- const wifiIPv4 = wifiInterface.find(iface => iface.family === 'IPv4');
481
- if (wifiIPv4) {
482
- console.log(`Wi-Fi IP Address: ${wifiIPv4.address}`);
483
- try {
484
- var node = new nep.Node("nep-cli");
485
- nep_configuration["IP"] = wifiIPv4.address;
486
- var master = new MasterLocal(IP = wifiIPv4.address);
487
- var info = new nep.MasterInfoServer(IP = wifiIPv4.address, topics = topic_register);
488
- } catch (error) {
489
- if (error.message.includes('EADDRINUSE')) {
490
- console.error("Error: Address already in use. Another instance of NEP master might be running.");
491
- } else {
492
- console.error("An error occurred:", error.message);
493
- }
494
- }
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);
495
456
 
496
- } else {
497
- console.log('No Wi-Fi IPv4 address found.');
498
- }
499
- } else {
500
- console.log('Wi-Fi interface not found.');
501
- }
502
457
  });
503
458
 
459
+
504
460
  program
505
461
  .command('topics')
506
462
  .description('Get list of NEP+ topics')
@@ -555,7 +511,7 @@ program
555
511
  });
556
512
 
557
513
  program
558
- .command('eth-topics')
514
+ .command('topics-eth')
559
515
  .description('Get list of NEP+ topics over Ethernet')
560
516
  .action(async () => {
561
517
  const interfaces = os.networkInterfaces();
@@ -578,7 +534,7 @@ program
578
534
 
579
535
 
580
536
  program
581
- .command('wifi-topics')
537
+ .command('topics-wifi')
582
538
  .description('Get list of NEP+ topics over Wi-Fi')
583
539
  .action(async () => {
584
540
  const interfaces = os.networkInterfaces();
@@ -607,32 +563,374 @@ program
607
563
  resolve(results);
608
564
  });
609
565
 
610
- const timeoutPromise = new Promise((resolve, reject) => {
611
- setTimeout(() => {
612
- reject(new Error("Timed out, NEP master over Wi-Fi was not found"));
613
- }, TIMEOUT_DURATION);
614
- });
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
+
601
+ program
602
+ .command('listen <topic>')
603
+ .description('Subscribe to a NEP+ topic and display JSON messages')
604
+ .action(async (topic) => {
605
+ const interfaces = os.networkInterfaces();
606
+
607
+ var opensub = function (master_ip = "127.0.0.1") {
608
+ var callback = function (msg) {
609
+ var date = new Date();
610
+ var dateString = date.toISOString();
611
+ console.log(dateString);
612
+
613
+ if (msg.length > 10000) {
614
+ console.log("the message is too long to be displayed");
615
+ } else {
616
+ console.log(msg);
617
+ }
618
+ };
619
+
620
+ var node = new nep.Node("nep-cli-sub");
621
+ var conf = node.hybrid(master_ip);
622
+ sub = node.new_sub(topic, "json", callback, conf);
623
+ };
624
+
625
+ var master_ip = "127.0.0.1";
626
+ async function run() {
627
+ var requester = new zmq.Request();
628
+ requester.connect("tcp://" + master_ip + ":" + PORT_MASTER_INFO);
629
+
630
+ let msg = { "input": "topics" };
631
+ var message = JSON.stringify(msg);
632
+ await requester.send(message);
633
+ const [result] = await requester.receive();
634
+ var results = JSON.parse(result.toString());
635
+
636
+ if (results["state"] === "failure") {
637
+ console.log("Topic is not registered");
638
+ } else {
639
+ console.log("");
640
+ if (results["input"].includes(topic)) {
641
+ opensub(master_ip);
642
+ } else {
643
+ console.log("Topic is not registered");
644
+ }
645
+ }
646
+ }
647
+
648
+ run();
649
+ });
650
+
651
+ program
652
+ .command('listen-eth <topic>')
653
+ .description('Subscribe to a NEP+ topic over Ethernet and display JSON messages')
654
+ .action(async (topic) => {
655
+ const interfaces = os.networkInterfaces();
656
+
657
+ var opensub = function (master_ip = "127.0.0.1") {
658
+ var callback = function (msg) {
659
+ var date = new Date();
660
+ var dateString = date.toISOString();
661
+ console.log(dateString);
662
+
663
+ if (msg.length > 10000) {
664
+ console.log("the message is too long to be displayed");
665
+ } else {
666
+ console.log(msg);
667
+ }
668
+ };
669
+
670
+ var node = new nep.Node("nep-cli-sub");
671
+ var conf = node.hybrid(master_ip);
672
+ sub = node.new_sub(topic, "json", callback, conf);
673
+ };
674
+
675
+ async function run(master_ip) {
676
+ var requester = new zmq.Request();
677
+ requester.connect("tcp://" + master_ip + ":" + PORT_MASTER_INFO);
678
+
679
+ let msg = { "input": "topics" };
680
+ var message = JSON.stringify(msg);
681
+ await requester.send(message);
682
+ const [result] = await requester.receive();
683
+ var results = JSON.parse(result.toString());
684
+
685
+ if (results["state"] === "failure") {
686
+ console.log("Topic is not registered");
687
+ } else {
688
+ console.log("");
689
+ if (results["input"].includes(topic)) {
690
+ opensub(master_ip);
691
+ } else {
692
+ console.log("Topic is not registered");
693
+ }
694
+ }
695
+ }
696
+
697
+ // Find Ethernet interface
698
+ const ethernetInterface = interfaces['Ethernet'] || interfaces['Ethernet 2'] || interfaces['eth0'] || interfaces['イーサネット'] || interfaces['enp0s10'];
699
+ if (ethernetInterface) {
700
+ const ethernetIPv4 = ethernetInterface.find(iface => iface.family === 'IPv4');
701
+ if (ethernetIPv4) {
702
+ console.log(`Ethernet IP Address: ${ethernetIPv4.address}`);
703
+ run(ethernetIPv4.address)
704
+ } else {
705
+ console.log('No Ethernet IPv4 address found.');
706
+ }
707
+ } else {
708
+ console.log('Ethernet interface not found.');
709
+ }
710
+ });
711
+
712
+ program
713
+ .command('listen-wifi <topic>')
714
+ .description('Subscribe to a NEP+ topic over Wi-Fi and display JSON messages')
715
+ .action(async (topic) => {
716
+ const interfaces = os.networkInterfaces();
717
+
718
+ var opensub = function (master_ip = "127.0.0.1") {
719
+ var callback = function (msg) {
720
+ var date = new Date();
721
+ var dateString = date.toISOString();
722
+ console.log(dateString);
723
+
724
+ if (msg.length > 10000) {
725
+ console.log("the message is too long to be displayed");
726
+ } else {
727
+ console.log(msg);
728
+ }
729
+ };
730
+
731
+ var node = new nep.Node("nep-cli-sub");
732
+ var conf = node.hybrid(master_ip);
733
+ sub = node.new_sub(topic, "json", callback, conf);
734
+ };
735
+
736
+ async function run(master_ip) {
737
+ var requester = new zmq.Request();
738
+ requester.connect("tcp://" + master_ip + ":" + PORT_MASTER_INFO);
739
+
740
+ let msg = { "input": "topics" };
741
+ var message = JSON.stringify(msg);
742
+ await requester.send(message);
743
+ const [result] = await requester.receive();
744
+ var results = JSON.parse(result.toString());
745
+
746
+ if (results["state"] === "failure") {
747
+ console.log("Topic is not registered");
748
+ } else {
749
+ console.log("");
750
+ if (results["input"].includes(topic)) {
751
+ opensub(master_ip);
752
+ } else {
753
+ console.log("Topic is not registered");
754
+ }
755
+ }
756
+ }
757
+
758
+ const wifiInterface = interfaces['Wi-Fi'] || interfaces['Wi-Fi 2'] || interfaces['wlan0'] || interfaces['wlo1'];
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
+ }
769
+ });
770
+
771
+
772
+ program
773
+ .command('echo <topic>')
774
+ .description('Subscribe to a NEP+ topic and display raw string messages')
775
+ .action(async (topic) => {
776
+ const interfaces = os.networkInterfaces();
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);
615
910
 
616
- const results = await Promise.race([responsePromise, timeoutPromise]);
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());
617
916
 
618
- if (results["state"] === "success") {
619
- availableTopics = results["input"]; // Store the topics here
620
- console.log("");
621
- results["input"].forEach(element => {
622
- console.log(element);
623
- });
624
- } else {
625
- console.log("No topics yet");
626
- }
627
- } catch (error) {
628
- console.error("Error:", error.message);
629
- } finally {
630
- process.exit();
631
- }
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");
632
925
  }
926
+ }
927
+ }
633
928
 
634
- await getTopics();
635
-
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);
636
934
  } else {
637
935
  console.log('No Wi-Fi IPv4 address found.');
638
936
  }
@@ -641,7 +939,6 @@ program
641
939
  }
642
940
  });
643
941
 
644
-
645
942
  program
646
943
  .command('publish <topic> <message>')
647
944
  .description('Publish a message to a NEP+ topic')
@@ -688,11 +985,9 @@ program
688
985
  run()
689
986
  });
690
987
 
691
-
692
-
693
988
  program
694
- .command('eth-publish <topic> <message>')
695
- .description('Publish a message to a NEP+ topic over Ethernet')
989
+ .command('publish-eth <topic> <message>')
990
+ .description('Publish a JSON message to a NEP+ topic over Ethernet')
696
991
  .action((topic, message) => {
697
992
 
698
993
  const interfaces = os.networkInterfaces();
@@ -756,8 +1051,8 @@ program
756
1051
  });
757
1052
 
758
1053
  program
759
- .command('wifi-publish <topic> <message>')
760
- .description('Publish a message to a NEP+ topic over Wi-Fi')
1054
+ .command('publish-wifi <topic> <message>')
1055
+ .description('Publish a JSON message to a NEP+ topic over Wi-Fi')
761
1056
  .action((topic, message) => {
762
1057
 
763
1058
  const interfaces = os.networkInterfaces();
@@ -821,48 +1116,95 @@ program
821
1116
 
822
1117
 
823
1118
  program
824
- .command('listen <topic>')
825
- .description('Subscribe to a NEP+ topic')
1119
+ .command('hz <topic>')
1120
+ .description('Monitor the publishing rate of a NEP+ topic in localhost')
826
1121
  .action(async (topic) => {
827
1122
  const interfaces = os.networkInterfaces();
1123
+ const master_ip = "127.0.0.1"; // Change to the appropriate master IP
828
1124
 
829
- var opensub = function (master_ip = "127.0.0.1") {
830
- var callback = function (msg) {
831
- var date = new Date();
832
- var dateString = date.toISOString();
833
- console.log(dateString);
1125
+ const opensub = function () {
1126
+ const timestamps = []; // To store message timestamps
834
1127
 
835
- if (msg.length > 10000) {
836
- console.log("the message is too long to be displayed");
837
- } else {
838
- console.log(msg);
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();
839
1138
  }
840
1139
  };
841
1140
 
842
- var node = new nep.Node("nep-cli-sub");
843
- var conf = node.hybrid(master_ip);
844
- sub = node.new_sub(topic, "json", callback, conf);
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);
845
1160
  };
846
1161
 
847
- var master_ip = "127.0.0.1";
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
+
848
1190
  async function run() {
849
- var requester = new zmq.Request();
850
- requester.connect("tcp://" + master_ip + ":" + PORT_MASTER_INFO);
1191
+ const requester = new zmq.Request();
1192
+ requester.connect(`tcp://${master_ip}:${PORT_MASTER_INFO}`);
851
1193
 
852
- let msg = { "input": "topics" };
853
- var message = JSON.stringify(msg);
1194
+ const msg = { "input": "topics" };
1195
+ const message = JSON.stringify(msg);
854
1196
  await requester.send(message);
855
1197
  const [result] = await requester.receive();
856
- var results = JSON.parse(result.toString());
1198
+ const results = JSON.parse(result.toString());
857
1199
 
858
1200
  if (results["state"] === "failure") {
859
- console.log("Topic is not registered");
1201
+ console.log("Topic is not registered, use *nep topics* to see the list of avaliable topics");
860
1202
  } else {
861
1203
  console.log("");
862
1204
  if (results["input"].includes(topic)) {
863
- opensub(master_ip);
1205
+ opensub();
864
1206
  } else {
865
- console.log("Topic is not registered");
1207
+ console.log("Topic is not registered, use *nep topics* to see the list of avaliable topics");
866
1208
  }
867
1209
  }
868
1210
  }
@@ -870,126 +1212,224 @@ program
870
1212
  run();
871
1213
  });
872
1214
 
1215
+
873
1216
  program
874
- .command('eth-listen <topic>')
875
- .description('Subscribe to a NEP+ topic over Ethernet')
1217
+ .command('hz-wifi <topic>')
1218
+ .description('Monitor the publishing rate of a NEP+ topic over Wi-Fi')
876
1219
  .action(async (topic) => {
877
1220
  const interfaces = os.networkInterfaces();
878
1221
 
879
- var opensub = function (master_ip = "127.0.0.1") {
880
- var callback = function (msg) {
881
- var date = new Date();
882
- var dateString = date.toISOString();
883
- console.log(dateString);
884
1222
 
885
- if (msg.length > 10000) {
886
- console.log("the message is too long to be displayed");
887
- } else {
888
- console.log(msg);
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();
889
1236
  }
890
1237
  };
891
1238
 
892
- var node = new nep.Node("nep-cli-sub");
893
- var conf = node.hybrid(master_ip);
894
- sub = node.new_sub(topic, "json", callback, conf);
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;
895
1285
  };
896
1286
 
1287
+
897
1288
  async function run(master_ip) {
898
- var requester = new zmq.Request();
899
- requester.connect("tcp://" + master_ip + ":" + PORT_MASTER_INFO);
1289
+ const requester = new zmq.Request();
1290
+ requester.connect(`tcp://${master_ip}:${PORT_MASTER_INFO}`);
900
1291
 
901
- let msg = { "input": "topics" };
902
- var message = JSON.stringify(msg);
1292
+ const msg = { "input": "topics" };
1293
+ const message = JSON.stringify(msg);
903
1294
  await requester.send(message);
904
1295
  const [result] = await requester.receive();
905
- var results = JSON.parse(result.toString());
1296
+ const results = JSON.parse(result.toString());
906
1297
 
907
1298
  if (results["state"] === "failure") {
908
- console.log("Topic is not registered");
1299
+ console.log("Topic is not registered, use *nep topics* to see the list of avaliable topics");
909
1300
  } else {
910
1301
  console.log("");
911
1302
  if (results["input"].includes(topic)) {
912
1303
  opensub(master_ip);
913
1304
  } else {
914
- console.log("Topic is not registered");
1305
+ console.log("Topic is not registered, use *nep topics* to see the list of avaliable topics");
915
1306
  }
916
1307
  }
917
1308
  }
918
1309
 
919
- // Find Ethernet interface
920
- const ethernetInterface = interfaces['Ethernet'] || interfaces['Ethernet 2'] || interfaces['eth0'] || interfaces['イーサネット'] || interfaces['enp0s10'];
921
- if (ethernetInterface) {
922
- const ethernetIPv4 = ethernetInterface.find(iface => iface.family === 'IPv4');
923
- if (ethernetIPv4) {
924
- console.log(`Ethernet IP Address: ${ethernetIPv4.address}`);
925
- run(ethernetIPv4.address)
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)
926
1316
  } else {
927
- console.log('No Ethernet IPv4 address found.');
1317
+ console.log('No Wi-Fi IPv4 address found.');
928
1318
  }
929
1319
  } else {
930
- console.log('Ethernet interface not found.');
1320
+ console.log('Wi-Fi interface not found.');
931
1321
  }
932
1322
  });
933
1323
 
934
1324
  program
935
- .command('wifi-listen <topic>')
936
- .description('Subscribe to a NEP+ topic over Wi-Fi')
1325
+ .command('hz-eth <topic>')
1326
+ .description('Monitor the publishing rate of a NEP+ topic over Ethernet')
937
1327
  .action(async (topic) => {
938
1328
  const interfaces = os.networkInterfaces();
939
1329
 
940
- var opensub = function (master_ip = "127.0.0.1") {
941
- var callback = function (msg) {
942
- var date = new Date();
943
- var dateString = date.toISOString();
944
- console.log(dateString);
945
1330
 
946
- if (msg.length > 10000) {
947
- console.log("the message is too long to be displayed");
948
- } else {
949
- console.log(msg);
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();
950
1344
  }
951
1345
  };
952
1346
 
953
- var node = new nep.Node("nep-cli-sub");
954
- var conf = node.hybrid(master_ip);
955
- sub = node.new_sub(topic, "json", callback, conf);
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;
956
1393
  };
957
1394
 
1395
+
958
1396
  async function run(master_ip) {
959
- var requester = new zmq.Request();
960
- requester.connect("tcp://" + master_ip + ":" + PORT_MASTER_INFO);
1397
+ const requester = new zmq.Request();
1398
+ requester.connect(`tcp://${master_ip}:${PORT_MASTER_INFO}`);
961
1399
 
962
- let msg = { "input": "topics" };
963
- var message = JSON.stringify(msg);
1400
+ const msg = { "input": "topics" };
1401
+ const message = JSON.stringify(msg);
964
1402
  await requester.send(message);
965
1403
  const [result] = await requester.receive();
966
- var results = JSON.parse(result.toString());
1404
+ const results = JSON.parse(result.toString());
967
1405
 
968
1406
  if (results["state"] === "failure") {
969
- console.log("Topic is not registered");
1407
+ console.log("Topic is not registered, use *nep topics* to see the list of avaliable topics");
970
1408
  } else {
971
1409
  console.log("");
972
1410
  if (results["input"].includes(topic)) {
973
1411
  opensub(master_ip);
974
1412
  } else {
975
- console.log("Topic is not registered");
1413
+ console.log("Topic is not registered, use *nep topics* to see the list of avaliable topics");
976
1414
  }
977
1415
  }
978
1416
  }
979
1417
 
980
- const wifiInterface = interfaces['Wi-Fi'] || interfaces['Wi-Fi 2'] || interfaces['wlan0'] || interfaces['wlo1'];
981
- if (wifiInterface) {
982
- const wifiIPv4 = wifiInterface.find(iface => iface.family === 'IPv4');
983
- if (wifiIPv4) {
984
- run(wifiIPv4.address);
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)
985
1424
  } else {
986
- console.log('No Wi-Fi IPv4 address found.');
1425
+ console.log('No Ethernet IPv4 address found.');
987
1426
  }
988
1427
  } else {
989
- console.log('Wi-Fi interface not found.');
1428
+ console.log('Ethernet interface not found.');
990
1429
  }
991
1430
  });
992
1431
 
1432
+
993
1433
  program
994
1434
  .command('docs')
995
1435
  .description('Open the NEP+ documentation in the default browser')
@@ -1012,6 +1452,14 @@ function timeoutPromise(ms) {
1012
1452
  });
1013
1453
  }
1014
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
+
1015
1463
  async function getAndDisplayTopics(master_ip) {
1016
1464
  const TIMEOUT_DURATION = 5000;
1017
1465
 
@@ -1031,7 +1479,7 @@ async function getAndDisplayTopics(master_ip) {
1031
1479
 
1032
1480
  const timeoutPromise = new Promise((resolve, reject) => {
1033
1481
  setTimeout(() => {
1034
- reject(new Error("Timed out, NEP master over Ethernet was not found"));
1482
+ reject(new Error("Timed out, NEP master over Wi-Fi was not found"));
1035
1483
  }, TIMEOUT_DURATION);
1036
1484
  });
1037
1485
 
@@ -1053,84 +1501,51 @@ async function getAndDisplayTopics(master_ip) {
1053
1501
  }
1054
1502
  }
1055
1503
 
1056
- program
1057
- .command('image <topic>')
1058
- .description('Start image server')
1059
- .action((topic, options) => {
1060
- async function run() {
1061
- var requester = new zmq.Request;
1062
- var master_ip = "127.0.0.1"
1063
- var port = PORT_IMAGE
1064
1504
 
1065
-
1066
1505
 
1067
- requester.connect("tcp://" + master_ip + ":" + PORT_MASTER_INFO);
1068
-
1069
- let msg = { "input": "topics" }
1070
- var message = JSON.stringify(msg);
1071
- await requester.send(message)
1072
- const [result] = await requester.receive()
1073
- var results = JSON.parse(result.toString())
1074
- //console.log(results);
1075
-
1076
-
1077
- const programs = results["input"];
1078
- const filteredList = programs.filter(value => value.includes("image"));
1079
-
1080
- if (!topic) {
1081
- const autoComplete = new AutoComplete({
1082
- name: 'program',
1083
- message: 'Select a program:',
1084
- choices: filteredList,
1085
- });
1086
- topic = await autoComplete.run();
1087
- } else if (!filteredList.includes(topic)) {
1088
- const autoComplete = new AutoComplete({
1089
- name: 'program',
1090
- message: 'Invalid program name. Select a valid program:',
1091
- choices: filteredList,
1092
- });
1093
- topic = await autoComplete.run();
1094
- }
1095
-
1096
-
1097
- startServer(port, topic);
1098
- open(`http://localhost:${port}`);
1099
-
1100
- }
1101
- run()
1102
-
1103
- });
1104
1506
 
1105
- // Function to start the server
1106
- function startServer(port, topic) {
1107
- const app = express();
1108
- const server = http.createServer(app);
1109
- const io = socketIo(server);
1507
+ async function getAndDisplayTopics(master_ip) {
1508
+ const TIMEOUT_DURATION = 5000;
1110
1509
 
1111
- var node = new nep.Node("nep-cli");
1510
+ var requester = new zmq.Request();
1511
+ requester.connect(`tcp://${master_ip}:${PORT_MASTER_INFO}`);
1112
1512
 
1113
- function getImage(msg) {
1114
- // Send the received image data as-is to connected clients
1115
- io.sockets.emit('image', { image: msg });
1116
- }
1513
+ let msg = { "input": "topics" };
1514
+ var message = JSON.stringify(msg);
1117
1515
 
1118
- var sub = node.new_sub(topic, "image", getImage);
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
+ });
1119
1523
 
1120
- app.get('/', (req, res) => {
1121
- res.sendFile(__dirname + '/image.html'); // Serve your HTML file
1122
- });
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
+ });
1123
1529
 
1124
- server.listen(port, () => {
1125
- console.log(`Server is running on http://localhost:${port}`);
1126
- });
1530
+ const results = await Promise.race([responsePromise, timeoutPromise]);
1127
1531
 
1128
- io.on('connection', (socket) => {
1129
- const frameRate = 30; // Desired frame rate
1130
- const interval = 1000 / frameRate; // Interval between frames
1131
- });
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
+ }
1132
1546
  }
1133
1547
 
1548
+
1134
1549
  program.parse(process.argv);
1135
1550
 
1136
1551