@em-foundation/emscope 25.4.0 → 25.5.3
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/CHANGELOG.md +11 -0
- package/README.md +3 -14
- package/dist/emscope +692 -26
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
## VERSION-25.5.0
|
|
2
|
+
|
|
3
|
+
* support for Otii-3 analyzer and battery emulator
|
|
4
|
+
* new `emscope grab -O, --otii3` option
|
|
5
|
+
* new `emscope grab -B, --battery-profile <index>` option
|
|
6
|
+
* new `emscope --soc <percent>` option
|
|
7
|
+
|
|
8
|
+
## VERSION-25-4.1
|
|
9
|
+
|
|
10
|
+
* more robust port enumeration fix for PPK
|
|
11
|
+
|
|
1
12
|
## VERSION-25-4.0
|
|
2
13
|
|
|
3
14
|
* added `--json` option
|
package/README.md
CHANGED
|
@@ -1,15 +1,4 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
<p align="center">
|
|
6
|
-
<img src="docs/images/tagline.png" alt="EM•Scope TagLine" width="750">
|
|
7
|
-
</p>
|
|
8
|
-
|
|
9
|
-
-----
|
|
10
|
-
|
|
11
|
-
The **EM•Scope** tool streamlines the capture, analysis, display, and delivery of real-time power-consumption measurements – used to characterize the overall energy efficiency of resource-constrained embedded systems.  To encourage benchmarks for different HW/SW configurations performing comparable tasks, **EM•Scope** introduces a novel metric for quantifying energy efficiency – the **EM•erald**.
|
|
12
|
-
|
|
13
|
-
<p align="right">
|
|
14
|
-
<a href="https://github.com/em-foundation/emscope/blob/docs-stable/docs/ReadMore.md">read more<b> ➦</b></a>
|
|
15
|
-
</p>
|
|
2
|
+
<img src="https://raw.githubusercontent.com/em-foundation/emscope/main/docs/images/splash.png"
|
|
3
|
+
alt="EM•Scope" width="840">
|
|
4
|
+
</p>
|
package/dist/emscope
CHANGED
|
@@ -32,6 +32,7 @@ var require_constants = __commonJS({
|
|
|
32
32
|
"use strict";
|
|
33
33
|
var WIN_SLASH = "\\\\/";
|
|
34
34
|
var WIN_NO_SLASH = `[^${WIN_SLASH}]`;
|
|
35
|
+
var DEFAULT_MAX_EXTGLOB_RECURSION = 0;
|
|
35
36
|
var DOT_LITERAL = "\\.";
|
|
36
37
|
var PLUS_LITERAL = "\\+";
|
|
37
38
|
var QMARK_LITERAL = "\\?";
|
|
@@ -82,6 +83,7 @@ var require_constants = __commonJS({
|
|
|
82
83
|
SEP: "\\"
|
|
83
84
|
};
|
|
84
85
|
var POSIX_REGEX_SOURCE = {
|
|
86
|
+
__proto__: null,
|
|
85
87
|
alnum: "a-zA-Z0-9",
|
|
86
88
|
alpha: "a-zA-Z",
|
|
87
89
|
ascii: "\\x00-\\x7F",
|
|
@@ -98,6 +100,7 @@ var require_constants = __commonJS({
|
|
|
98
100
|
xdigit: "A-Fa-f0-9"
|
|
99
101
|
};
|
|
100
102
|
module2.exports = {
|
|
103
|
+
DEFAULT_MAX_EXTGLOB_RECURSION,
|
|
101
104
|
MAX_LENGTH: 1024 * 64,
|
|
102
105
|
POSIX_REGEX_SOURCE,
|
|
103
106
|
// regular expressions
|
|
@@ -648,6 +651,213 @@ var require_parse = __commonJS({
|
|
|
648
651
|
var syntaxError = (type2, char) => {
|
|
649
652
|
return `Missing ${type2}: "${char}" - use "\\\\${char}" to match literal characters`;
|
|
650
653
|
};
|
|
654
|
+
var splitTopLevel = (input) => {
|
|
655
|
+
const parts = [];
|
|
656
|
+
let bracket = 0;
|
|
657
|
+
let paren = 0;
|
|
658
|
+
let quote = 0;
|
|
659
|
+
let value = "";
|
|
660
|
+
let escaped = false;
|
|
661
|
+
for (const ch of input) {
|
|
662
|
+
if (escaped === true) {
|
|
663
|
+
value += ch;
|
|
664
|
+
escaped = false;
|
|
665
|
+
continue;
|
|
666
|
+
}
|
|
667
|
+
if (ch === "\\") {
|
|
668
|
+
value += ch;
|
|
669
|
+
escaped = true;
|
|
670
|
+
continue;
|
|
671
|
+
}
|
|
672
|
+
if (ch === '"') {
|
|
673
|
+
quote = quote === 1 ? 0 : 1;
|
|
674
|
+
value += ch;
|
|
675
|
+
continue;
|
|
676
|
+
}
|
|
677
|
+
if (quote === 0) {
|
|
678
|
+
if (ch === "[") {
|
|
679
|
+
bracket++;
|
|
680
|
+
} else if (ch === "]" && bracket > 0) {
|
|
681
|
+
bracket--;
|
|
682
|
+
} else if (bracket === 0) {
|
|
683
|
+
if (ch === "(") {
|
|
684
|
+
paren++;
|
|
685
|
+
} else if (ch === ")" && paren > 0) {
|
|
686
|
+
paren--;
|
|
687
|
+
} else if (ch === "|" && paren === 0) {
|
|
688
|
+
parts.push(value);
|
|
689
|
+
value = "";
|
|
690
|
+
continue;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
value += ch;
|
|
695
|
+
}
|
|
696
|
+
parts.push(value);
|
|
697
|
+
return parts;
|
|
698
|
+
};
|
|
699
|
+
var isPlainBranch = (branch) => {
|
|
700
|
+
let escaped = false;
|
|
701
|
+
for (const ch of branch) {
|
|
702
|
+
if (escaped === true) {
|
|
703
|
+
escaped = false;
|
|
704
|
+
continue;
|
|
705
|
+
}
|
|
706
|
+
if (ch === "\\") {
|
|
707
|
+
escaped = true;
|
|
708
|
+
continue;
|
|
709
|
+
}
|
|
710
|
+
if (/[?*+@!()[\]{}]/.test(ch)) {
|
|
711
|
+
return false;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
return true;
|
|
715
|
+
};
|
|
716
|
+
var normalizeSimpleBranch = (branch) => {
|
|
717
|
+
let value = branch.trim();
|
|
718
|
+
let changed = true;
|
|
719
|
+
while (changed === true) {
|
|
720
|
+
changed = false;
|
|
721
|
+
if (/^@\([^\\()[\]{}|]+\)$/.test(value)) {
|
|
722
|
+
value = value.slice(2, -1);
|
|
723
|
+
changed = true;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
if (!isPlainBranch(value)) {
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
return value.replace(/\\(.)/g, "$1");
|
|
730
|
+
};
|
|
731
|
+
var hasRepeatedCharPrefixOverlap = (branches) => {
|
|
732
|
+
const values = branches.map(normalizeSimpleBranch).filter(Boolean);
|
|
733
|
+
for (let i = 0; i < values.length; i++) {
|
|
734
|
+
for (let j = i + 1; j < values.length; j++) {
|
|
735
|
+
const a = values[i];
|
|
736
|
+
const b = values[j];
|
|
737
|
+
const char = a[0];
|
|
738
|
+
if (!char || a !== char.repeat(a.length) || b !== char.repeat(b.length)) {
|
|
739
|
+
continue;
|
|
740
|
+
}
|
|
741
|
+
if (a === b || a.startsWith(b) || b.startsWith(a)) {
|
|
742
|
+
return true;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
return false;
|
|
747
|
+
};
|
|
748
|
+
var parseRepeatedExtglob = (pattern, requireEnd = true) => {
|
|
749
|
+
if (pattern[0] !== "+" && pattern[0] !== "*" || pattern[1] !== "(") {
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
let bracket = 0;
|
|
753
|
+
let paren = 0;
|
|
754
|
+
let quote = 0;
|
|
755
|
+
let escaped = false;
|
|
756
|
+
for (let i = 1; i < pattern.length; i++) {
|
|
757
|
+
const ch = pattern[i];
|
|
758
|
+
if (escaped === true) {
|
|
759
|
+
escaped = false;
|
|
760
|
+
continue;
|
|
761
|
+
}
|
|
762
|
+
if (ch === "\\") {
|
|
763
|
+
escaped = true;
|
|
764
|
+
continue;
|
|
765
|
+
}
|
|
766
|
+
if (ch === '"') {
|
|
767
|
+
quote = quote === 1 ? 0 : 1;
|
|
768
|
+
continue;
|
|
769
|
+
}
|
|
770
|
+
if (quote === 1) {
|
|
771
|
+
continue;
|
|
772
|
+
}
|
|
773
|
+
if (ch === "[") {
|
|
774
|
+
bracket++;
|
|
775
|
+
continue;
|
|
776
|
+
}
|
|
777
|
+
if (ch === "]" && bracket > 0) {
|
|
778
|
+
bracket--;
|
|
779
|
+
continue;
|
|
780
|
+
}
|
|
781
|
+
if (bracket > 0) {
|
|
782
|
+
continue;
|
|
783
|
+
}
|
|
784
|
+
if (ch === "(") {
|
|
785
|
+
paren++;
|
|
786
|
+
continue;
|
|
787
|
+
}
|
|
788
|
+
if (ch === ")") {
|
|
789
|
+
paren--;
|
|
790
|
+
if (paren === 0) {
|
|
791
|
+
if (requireEnd === true && i !== pattern.length - 1) {
|
|
792
|
+
return;
|
|
793
|
+
}
|
|
794
|
+
return {
|
|
795
|
+
type: pattern[0],
|
|
796
|
+
body: pattern.slice(2, i),
|
|
797
|
+
end: i
|
|
798
|
+
};
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
};
|
|
803
|
+
var getStarExtglobSequenceOutput = (pattern) => {
|
|
804
|
+
let index = 0;
|
|
805
|
+
const chars = [];
|
|
806
|
+
while (index < pattern.length) {
|
|
807
|
+
const match = parseRepeatedExtglob(pattern.slice(index), false);
|
|
808
|
+
if (!match || match.type !== "*") {
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
811
|
+
const branches = splitTopLevel(match.body).map((branch2) => branch2.trim());
|
|
812
|
+
if (branches.length !== 1) {
|
|
813
|
+
return;
|
|
814
|
+
}
|
|
815
|
+
const branch = normalizeSimpleBranch(branches[0]);
|
|
816
|
+
if (!branch || branch.length !== 1) {
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
chars.push(branch);
|
|
820
|
+
index += match.end + 1;
|
|
821
|
+
}
|
|
822
|
+
if (chars.length < 1) {
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
const source = chars.length === 1 ? utils.escapeRegex(chars[0]) : `[${chars.map((ch) => utils.escapeRegex(ch)).join("")}]`;
|
|
826
|
+
return `${source}*`;
|
|
827
|
+
};
|
|
828
|
+
var repeatedExtglobRecursion = (pattern) => {
|
|
829
|
+
let depth = 0;
|
|
830
|
+
let value = pattern.trim();
|
|
831
|
+
let match = parseRepeatedExtglob(value);
|
|
832
|
+
while (match) {
|
|
833
|
+
depth++;
|
|
834
|
+
value = match.body.trim();
|
|
835
|
+
match = parseRepeatedExtglob(value);
|
|
836
|
+
}
|
|
837
|
+
return depth;
|
|
838
|
+
};
|
|
839
|
+
var analyzeRepeatedExtglob = (body, options) => {
|
|
840
|
+
if (options.maxExtglobRecursion === false) {
|
|
841
|
+
return { risky: false };
|
|
842
|
+
}
|
|
843
|
+
const max = typeof options.maxExtglobRecursion === "number" ? options.maxExtglobRecursion : constants.DEFAULT_MAX_EXTGLOB_RECURSION;
|
|
844
|
+
const branches = splitTopLevel(body).map((branch) => branch.trim());
|
|
845
|
+
if (branches.length > 1) {
|
|
846
|
+
if (branches.some((branch) => branch === "") || branches.some((branch) => /^[*?]+$/.test(branch)) || hasRepeatedCharPrefixOverlap(branches)) {
|
|
847
|
+
return { risky: true };
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
for (const branch of branches) {
|
|
851
|
+
const safeOutput = getStarExtglobSequenceOutput(branch);
|
|
852
|
+
if (safeOutput) {
|
|
853
|
+
return { risky: true, safeOutput };
|
|
854
|
+
}
|
|
855
|
+
if (repeatedExtglobRecursion(branch) > max) {
|
|
856
|
+
return { risky: true };
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
return { risky: false };
|
|
860
|
+
};
|
|
651
861
|
var parse = (input, options) => {
|
|
652
862
|
if (typeof input !== "string") {
|
|
653
863
|
throw new TypeError("Expected a string");
|
|
@@ -778,6 +988,8 @@ var require_parse = __commonJS({
|
|
|
778
988
|
token.prev = prev;
|
|
779
989
|
token.parens = state.parens;
|
|
780
990
|
token.output = state.output;
|
|
991
|
+
token.startIndex = state.index;
|
|
992
|
+
token.tokensIndex = tokens.length;
|
|
781
993
|
const output = (opts.capture ? "(" : "") + token.open;
|
|
782
994
|
increment("parens");
|
|
783
995
|
push({ type: type2, value: value2, output: state.output ? "" : ONE_CHAR });
|
|
@@ -785,6 +997,26 @@ var require_parse = __commonJS({
|
|
|
785
997
|
extglobs.push(token);
|
|
786
998
|
};
|
|
787
999
|
const extglobClose = (token) => {
|
|
1000
|
+
const literal = input.slice(token.startIndex, state.index + 1);
|
|
1001
|
+
const body = input.slice(token.startIndex + 2, state.index);
|
|
1002
|
+
const analysis = analyzeRepeatedExtglob(body, opts);
|
|
1003
|
+
if ((token.type === "plus" || token.type === "star") && analysis.risky) {
|
|
1004
|
+
const safeOutput = analysis.safeOutput ? (token.output ? "" : ONE_CHAR) + (opts.capture ? `(${analysis.safeOutput})` : analysis.safeOutput) : void 0;
|
|
1005
|
+
const open = tokens[token.tokensIndex];
|
|
1006
|
+
open.type = "text";
|
|
1007
|
+
open.value = literal;
|
|
1008
|
+
open.output = safeOutput || utils.escapeRegex(literal);
|
|
1009
|
+
for (let i = token.tokensIndex + 1; i < tokens.length; i++) {
|
|
1010
|
+
tokens[i].value = "";
|
|
1011
|
+
tokens[i].output = "";
|
|
1012
|
+
delete tokens[i].suffix;
|
|
1013
|
+
}
|
|
1014
|
+
state.output = token.output + open.output;
|
|
1015
|
+
state.backtrack = true;
|
|
1016
|
+
push({ type: "paren", extglob: true, value, output: "" });
|
|
1017
|
+
decrement("parens");
|
|
1018
|
+
return;
|
|
1019
|
+
}
|
|
788
1020
|
let output = token.close + (opts.capture ? ")" : "");
|
|
789
1021
|
let rest;
|
|
790
1022
|
if (token.type === "negate") {
|
|
@@ -10550,6 +10782,18 @@ function charFromCodepoint(c) {
|
|
|
10550
10782
|
(c - 65536 & 1023) + 56320
|
|
10551
10783
|
);
|
|
10552
10784
|
}
|
|
10785
|
+
function setProperty(object, key, value) {
|
|
10786
|
+
if (key === "__proto__") {
|
|
10787
|
+
Object.defineProperty(object, key, {
|
|
10788
|
+
configurable: true,
|
|
10789
|
+
enumerable: true,
|
|
10790
|
+
writable: true,
|
|
10791
|
+
value
|
|
10792
|
+
});
|
|
10793
|
+
} else {
|
|
10794
|
+
object[key] = value;
|
|
10795
|
+
}
|
|
10796
|
+
}
|
|
10553
10797
|
var simpleEscapeCheck = new Array(256);
|
|
10554
10798
|
var simpleEscapeMap = new Array(256);
|
|
10555
10799
|
for (i = 0; i < 256; i++) {
|
|
@@ -10669,7 +10913,7 @@ function mergeMappings(state, destination, source, overridableKeys) {
|
|
|
10669
10913
|
for (index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {
|
|
10670
10914
|
key = sourceKeys[index];
|
|
10671
10915
|
if (!_hasOwnProperty$1.call(destination, key)) {
|
|
10672
|
-
destination
|
|
10916
|
+
setProperty(destination, key, source[key]);
|
|
10673
10917
|
overridableKeys[key] = true;
|
|
10674
10918
|
}
|
|
10675
10919
|
}
|
|
@@ -10709,16 +10953,7 @@ function storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valu
|
|
|
10709
10953
|
state.position = startPos || state.position;
|
|
10710
10954
|
throwError(state, "duplicated mapping key");
|
|
10711
10955
|
}
|
|
10712
|
-
|
|
10713
|
-
Object.defineProperty(_result, keyNode, {
|
|
10714
|
-
configurable: true,
|
|
10715
|
-
enumerable: true,
|
|
10716
|
-
writable: true,
|
|
10717
|
-
value: valueNode
|
|
10718
|
-
});
|
|
10719
|
-
} else {
|
|
10720
|
-
_result[keyNode] = valueNode;
|
|
10721
|
-
}
|
|
10956
|
+
setProperty(_result, keyNode, valueNode);
|
|
10722
10957
|
delete overridableKeys[keyNode];
|
|
10723
10958
|
}
|
|
10724
10959
|
return _result;
|
|
@@ -12306,7 +12541,6 @@ var jsYaml = {
|
|
|
12306
12541
|
safeLoadAll,
|
|
12307
12542
|
safeDump
|
|
12308
12543
|
};
|
|
12309
|
-
var js_yaml_default = jsYaml;
|
|
12310
12544
|
|
|
12311
12545
|
// src/Core.ts
|
|
12312
12546
|
var TAB = " ";
|
|
@@ -12315,6 +12549,7 @@ var Capture = class _Capture {
|
|
|
12315
12549
|
static #CFILE = "capture.yaml";
|
|
12316
12550
|
static #SAMPLING_RATE = /* @__PURE__ */ new Map([
|
|
12317
12551
|
["JS220", 1e6],
|
|
12552
|
+
["Otii3", 5e4],
|
|
12318
12553
|
["PPK2", 1e5]
|
|
12319
12554
|
]);
|
|
12320
12555
|
static #LOAD_KEYS = [
|
|
@@ -12342,7 +12577,7 @@ var Capture = class _Capture {
|
|
|
12342
12577
|
cap._sampling_rate = _Capture.#SAMPLING_RATE.get(device) ?? 0;
|
|
12343
12578
|
cap._sample_count = duration * cap.sampling_rate;
|
|
12344
12579
|
cap._current_ds = new SampleSet(cap.sample_count);
|
|
12345
|
-
cap._voltage_ds = new SampleSet(device == "
|
|
12580
|
+
cap._voltage_ds = new SampleSet(device == "PPK2" ? 0 : cap.sample_count);
|
|
12346
12581
|
const wd = cap.#workdir;
|
|
12347
12582
|
if (import_fs.default.existsSync(wd)) {
|
|
12348
12583
|
import_fs.default.rmSync(wd, { recursive: true });
|
|
@@ -12355,7 +12590,7 @@ var Capture = class _Capture {
|
|
|
12355
12590
|
cap._rootdir = rootdir;
|
|
12356
12591
|
fail(`captured data not found locally, try running 'emscope pack -u'`, !import_fs.default.existsSync(_Capture.workdir(rootdir)));
|
|
12357
12592
|
const ytxt = import_fs.default.readFileSync(cap.#cpath, "utf-8");
|
|
12358
|
-
const yobj =
|
|
12593
|
+
const yobj = jsYaml.load(ytxt);
|
|
12359
12594
|
for (const k of _Capture.#LOAD_KEYS) {
|
|
12360
12595
|
cap[`_${k}`] = yobj.capture[k];
|
|
12361
12596
|
}
|
|
@@ -12363,6 +12598,7 @@ var Capture = class _Capture {
|
|
|
12363
12598
|
cap.current_ds.load(cap.#workdir, "current");
|
|
12364
12599
|
switch (cap.device) {
|
|
12365
12600
|
case "JS220":
|
|
12601
|
+
case "Otii3":
|
|
12366
12602
|
cap._voltage_ds = new SampleSet(cap.sample_count);
|
|
12367
12603
|
cap.voltage_ds.load(cap.#workdir, "voltage");
|
|
12368
12604
|
break;
|
|
@@ -12371,7 +12607,7 @@ var Capture = class _Capture {
|
|
|
12371
12607
|
break;
|
|
12372
12608
|
}
|
|
12373
12609
|
if (import_fs.default.existsSync(cap.#apath)) {
|
|
12374
|
-
cap._aobj =
|
|
12610
|
+
cap._aobj = jsYaml.load(import_fs.default.readFileSync(cap.#apath, "utf-8"));
|
|
12375
12611
|
}
|
|
12376
12612
|
return cap;
|
|
12377
12613
|
}
|
|
@@ -12431,7 +12667,7 @@ var Capture = class _Capture {
|
|
|
12431
12667
|
}
|
|
12432
12668
|
bind(aobj) {
|
|
12433
12669
|
this._aobj = aobj;
|
|
12434
|
-
const ytxt =
|
|
12670
|
+
const ytxt = jsYaml.dump(aobj, { indent: 4, flowLevel: 4 });
|
|
12435
12671
|
import_fs.default.writeFileSync(this.#apath, ytxt);
|
|
12436
12672
|
infoMsg(`wrote '${_Capture.#AFILE}'`);
|
|
12437
12673
|
}
|
|
@@ -12452,7 +12688,7 @@ var Capture = class _Capture {
|
|
|
12452
12688
|
this.voltage_ds.save(this.#workdir, "voltage");
|
|
12453
12689
|
const cobj = Object.fromEntries(_Capture.#SAVE_KEYS.map((k) => [k, this[k]]));
|
|
12454
12690
|
const yobj = { capture: cobj };
|
|
12455
|
-
const ytxt =
|
|
12691
|
+
const ytxt = jsYaml.dump(yobj, { indent: 4, flowLevel: 4 });
|
|
12456
12692
|
import_fs.default.writeFileSync(this.#cpath, ytxt);
|
|
12457
12693
|
infoMsg(`wrote '${_Capture.#CFILE}'`);
|
|
12458
12694
|
}
|
|
@@ -12620,6 +12856,21 @@ function fail(msg, cond = true) {
|
|
|
12620
12856
|
process.exit(1);
|
|
12621
12857
|
}
|
|
12622
12858
|
}
|
|
12859
|
+
function findConfig() {
|
|
12860
|
+
let dir = process.cwd();
|
|
12861
|
+
let fpath = "";
|
|
12862
|
+
while (true) {
|
|
12863
|
+
const full = import_path.default.join(dir, "emscope-local.json");
|
|
12864
|
+
if (import_fs.default.existsSync(full)) {
|
|
12865
|
+
fpath = full;
|
|
12866
|
+
break;
|
|
12867
|
+
}
|
|
12868
|
+
const parent = import_path.default.dirname(dir);
|
|
12869
|
+
if (parent === dir) break;
|
|
12870
|
+
dir = parent;
|
|
12871
|
+
}
|
|
12872
|
+
return fpath === "" ? void 0 : JSON.parse(import_fs.default.readFileSync(fpath, "utf-8"));
|
|
12873
|
+
}
|
|
12623
12874
|
function infoMsg(msg) {
|
|
12624
12875
|
console.log(`${TAB}${msg}`);
|
|
12625
12876
|
}
|
|
@@ -12689,6 +12940,7 @@ ${dpath}:`);
|
|
|
12689
12940
|
}
|
|
12690
12941
|
|
|
12691
12942
|
// src/Detecter.ts
|
|
12943
|
+
var NO_CURRENT = 0;
|
|
12692
12944
|
function exec(opts) {
|
|
12693
12945
|
const cap = Capture.load(opts.capture);
|
|
12694
12946
|
let params = {};
|
|
@@ -12787,6 +13039,7 @@ function measureSleep(osig) {
|
|
|
12787
13039
|
const wsig = win.toSignal();
|
|
12788
13040
|
const cur = wsig.avg();
|
|
12789
13041
|
const m = win.toMarker();
|
|
13042
|
+
if (cur < NO_CURRENT) continue;
|
|
12790
13043
|
if (cur < min_cur) {
|
|
12791
13044
|
min_cur = cur;
|
|
12792
13045
|
std = wsig.std();
|
|
@@ -13100,6 +13353,379 @@ async function execCapture(opts) {
|
|
|
13100
13353
|
});
|
|
13101
13354
|
}
|
|
13102
13355
|
|
|
13356
|
+
// src/Driver_Otti3.ts
|
|
13357
|
+
var import_net = __toESM(require("net"));
|
|
13358
|
+
async function execCapture2(opts) {
|
|
13359
|
+
const jobj = findConfig();
|
|
13360
|
+
fail("can't find 'emscope-local.json'", jobj === void 0);
|
|
13361
|
+
const config = jobj.otii3;
|
|
13362
|
+
const cap = Capture.create(opts.capture, opts.duration, "Otii3");
|
|
13363
|
+
const progress = new Progress("capturing: ");
|
|
13364
|
+
const otii = new OtiiSession("127.0.0.1", 1905);
|
|
13365
|
+
await otii.connect();
|
|
13366
|
+
if (!await otii.isLoggedIn()) {
|
|
13367
|
+
await otii.login(config.username, config.password);
|
|
13368
|
+
}
|
|
13369
|
+
for (const license of await otii.getLicenses()) {
|
|
13370
|
+
await otii.reserveLicense(license.id);
|
|
13371
|
+
}
|
|
13372
|
+
const dev = await otii.requireDevice();
|
|
13373
|
+
const projectId = await otii.getOrCreateProject();
|
|
13374
|
+
await otii.addToProject(dev.device_id);
|
|
13375
|
+
await otii.setMainVoltage(dev.device_id, opts.voltage);
|
|
13376
|
+
await otii.setMaxCurrent(dev.device_id, 0.5);
|
|
13377
|
+
await otii.enableChannel(dev.device_id, "mc", true);
|
|
13378
|
+
await otii.enableChannel(dev.device_id, "mv", true);
|
|
13379
|
+
const bp = opts.batteryProfile;
|
|
13380
|
+
const soc = opts.soc ?? 100;
|
|
13381
|
+
fail("missing battery profile index", bp !== void 0 && typeof bp != "number");
|
|
13382
|
+
if (bp) {
|
|
13383
|
+
await batteryConfig(otii, bp, soc, dev.device_id, config);
|
|
13384
|
+
} else {
|
|
13385
|
+
await otii.setSupplyPowerBox(dev.device_id);
|
|
13386
|
+
}
|
|
13387
|
+
await otii.setMain(dev.device_id, true);
|
|
13388
|
+
await progress.spin(2500);
|
|
13389
|
+
await record(otii, cap, progress, projectId, dev.device_id);
|
|
13390
|
+
await otii.setSupplyPowerBox(dev.device_id);
|
|
13391
|
+
await otii.close();
|
|
13392
|
+
return cap;
|
|
13393
|
+
}
|
|
13394
|
+
async function batteryConfig(otii, bidx, soc, deviceId, config) {
|
|
13395
|
+
const bname = config.batteries[bidx];
|
|
13396
|
+
fail("invalid battery index", typeof bname != "string");
|
|
13397
|
+
const profiles = await otii.getBatteryProfiles();
|
|
13398
|
+
let bprof = profiles.find((p) => p.name === bname);
|
|
13399
|
+
fail("no corresponding profile found", bprof === void 0);
|
|
13400
|
+
await otii.setSupplyBatteryEmulator(deviceId, {
|
|
13401
|
+
batteryProfileId: bprof.battery_profile_id,
|
|
13402
|
+
soc
|
|
13403
|
+
});
|
|
13404
|
+
}
|
|
13405
|
+
async function record(otii, cap, progress, projectId, deviceId) {
|
|
13406
|
+
const t0 = Date.now();
|
|
13407
|
+
const t1 = t0 + cap.duration * 1e3;
|
|
13408
|
+
await otii.startRecording(projectId);
|
|
13409
|
+
try {
|
|
13410
|
+
while (true) {
|
|
13411
|
+
const now = Date.now();
|
|
13412
|
+
if (now >= t1) {
|
|
13413
|
+
break;
|
|
13414
|
+
}
|
|
13415
|
+
progress.update(`${((now - t0) / 1e3).toFixed(3)} s`);
|
|
13416
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
13417
|
+
}
|
|
13418
|
+
} finally {
|
|
13419
|
+
await otii.setMain(deviceId, false);
|
|
13420
|
+
await otii.stopRecording(projectId);
|
|
13421
|
+
}
|
|
13422
|
+
const recordingId = await otii.getLastRecording(projectId);
|
|
13423
|
+
const current = await otii.getAllChannelData(recordingId, deviceId, "mc");
|
|
13424
|
+
for (const sample of current.values) {
|
|
13425
|
+
cap.current_ds.add(sample);
|
|
13426
|
+
}
|
|
13427
|
+
const voltage = await otii.getAllChannelData(recordingId, deviceId, "mv");
|
|
13428
|
+
for (const sample of voltage.values) {
|
|
13429
|
+
cap.voltage_ds.add(sample);
|
|
13430
|
+
}
|
|
13431
|
+
await otii.deleteRecording(recordingId);
|
|
13432
|
+
progress.clear();
|
|
13433
|
+
}
|
|
13434
|
+
var OtiiSession = class {
|
|
13435
|
+
constructor(host = "127.0.0.1", port = 1905, debug = false) {
|
|
13436
|
+
this.host = host;
|
|
13437
|
+
this.port = port;
|
|
13438
|
+
this.debug = debug;
|
|
13439
|
+
this.socket = new import_net.default.Socket();
|
|
13440
|
+
this.rx = "";
|
|
13441
|
+
this.nextId = 1;
|
|
13442
|
+
this.ready = false;
|
|
13443
|
+
this.pending = /* @__PURE__ */ new Map();
|
|
13444
|
+
this.socket.on("data", (chunk) => this.onData(chunk));
|
|
13445
|
+
this.socket.on("error", (err) => this.onError(err));
|
|
13446
|
+
this.socket.on("close", () => this.onClose());
|
|
13447
|
+
}
|
|
13448
|
+
async connect(timeoutMs = 5e3) {
|
|
13449
|
+
if (this.ready) {
|
|
13450
|
+
return;
|
|
13451
|
+
}
|
|
13452
|
+
await new Promise((resolve, reject) => {
|
|
13453
|
+
const timer = setTimeout(() => {
|
|
13454
|
+
cleanup();
|
|
13455
|
+
reject(new Error("timeout waiting for connect banner"));
|
|
13456
|
+
}, timeoutMs);
|
|
13457
|
+
const onError = (err) => {
|
|
13458
|
+
cleanup();
|
|
13459
|
+
reject(err);
|
|
13460
|
+
};
|
|
13461
|
+
const cleanup = () => {
|
|
13462
|
+
clearTimeout(timer);
|
|
13463
|
+
this.socket.off("error", onError);
|
|
13464
|
+
this._onBanner = void 0;
|
|
13465
|
+
};
|
|
13466
|
+
this.socket.on("error", onError);
|
|
13467
|
+
this._onBanner = () => {
|
|
13468
|
+
cleanup();
|
|
13469
|
+
resolve();
|
|
13470
|
+
};
|
|
13471
|
+
this.socket.connect(this.port, this.host, () => {
|
|
13472
|
+
this.log(`socket connected to ${this.host}:${this.port}`);
|
|
13473
|
+
});
|
|
13474
|
+
});
|
|
13475
|
+
}
|
|
13476
|
+
async close() {
|
|
13477
|
+
if (this.socket.destroyed) {
|
|
13478
|
+
return;
|
|
13479
|
+
}
|
|
13480
|
+
await new Promise((resolve) => {
|
|
13481
|
+
this.socket.once("close", () => resolve());
|
|
13482
|
+
this.socket.end();
|
|
13483
|
+
});
|
|
13484
|
+
}
|
|
13485
|
+
async getDevices(timeoutSec = 5) {
|
|
13486
|
+
const data = await this.cmd("otii_get_devices", { timeout: timeoutSec }, (timeoutSec + 3) * 1e3);
|
|
13487
|
+
return data?.devices ?? [];
|
|
13488
|
+
}
|
|
13489
|
+
async requireDevice(deviceId) {
|
|
13490
|
+
const devices = await this.getDevices();
|
|
13491
|
+
if (deviceId) {
|
|
13492
|
+
const dev = devices.find((d) => d.device_id === deviceId);
|
|
13493
|
+
if (!dev) {
|
|
13494
|
+
throw new Error(`device not found: ${deviceId}`);
|
|
13495
|
+
}
|
|
13496
|
+
return dev;
|
|
13497
|
+
}
|
|
13498
|
+
if (devices.length === 0) {
|
|
13499
|
+
throw new Error("no devices found");
|
|
13500
|
+
}
|
|
13501
|
+
return devices[0];
|
|
13502
|
+
}
|
|
13503
|
+
async getOrCreateProject() {
|
|
13504
|
+
const active = await this.cmd("otii_get_active_project");
|
|
13505
|
+
const projectId = active?.project_id;
|
|
13506
|
+
if (projectId != null && projectId !== -1) {
|
|
13507
|
+
return projectId;
|
|
13508
|
+
}
|
|
13509
|
+
const created = await this.cmd("otii_create_project");
|
|
13510
|
+
if (created?.project_id == null) {
|
|
13511
|
+
throw new Error("failed to create project");
|
|
13512
|
+
}
|
|
13513
|
+
return created.project_id;
|
|
13514
|
+
}
|
|
13515
|
+
async addToProject(deviceId) {
|
|
13516
|
+
await this.cmd("arc_add_to_project", { device_id: deviceId }, 1e4);
|
|
13517
|
+
}
|
|
13518
|
+
async setMainVoltage(deviceId, value) {
|
|
13519
|
+
await this.cmd("arc_set_main_voltage", { device_id: deviceId, value });
|
|
13520
|
+
}
|
|
13521
|
+
async setMaxCurrent(deviceId, value) {
|
|
13522
|
+
await this.cmd("arc_set_max_current", { device_id: deviceId, value });
|
|
13523
|
+
}
|
|
13524
|
+
async enableChannel(deviceId, channel, enable) {
|
|
13525
|
+
await this.cmd("arc_enable_channel", { device_id: deviceId, channel, enable });
|
|
13526
|
+
}
|
|
13527
|
+
async setMain(deviceId, value) {
|
|
13528
|
+
await this.cmd("arc_set_main", { device_id: deviceId, enable: value });
|
|
13529
|
+
}
|
|
13530
|
+
async startRecording(projectId) {
|
|
13531
|
+
await this.cmd("project_start_recording", { project_id: projectId }, 1e4);
|
|
13532
|
+
}
|
|
13533
|
+
async stopRecording(projectId) {
|
|
13534
|
+
await this.cmd("project_stop_recording", { project_id: projectId }, 1e4);
|
|
13535
|
+
}
|
|
13536
|
+
async getLastRecording(projectId) {
|
|
13537
|
+
const data = await this.cmd("project_get_last_recording", { project_id: projectId }, 1e4);
|
|
13538
|
+
const recordingId = data?.recording_id;
|
|
13539
|
+
if (recordingId == null || recordingId === -1) {
|
|
13540
|
+
throw new Error("no recording found");
|
|
13541
|
+
}
|
|
13542
|
+
return recordingId;
|
|
13543
|
+
}
|
|
13544
|
+
async deleteRecording(recordingId) {
|
|
13545
|
+
await this.cmd("recording_delete", {
|
|
13546
|
+
recording_id: recordingId
|
|
13547
|
+
});
|
|
13548
|
+
}
|
|
13549
|
+
async getChannelDataCount(recordingId, deviceId, channel) {
|
|
13550
|
+
const data = await this.cmd("recording_get_channel_data_count", {
|
|
13551
|
+
recording_id: recordingId,
|
|
13552
|
+
device_id: deviceId,
|
|
13553
|
+
channel
|
|
13554
|
+
}, 15e3);
|
|
13555
|
+
return data.count;
|
|
13556
|
+
}
|
|
13557
|
+
async getChannelData(recordingId, deviceId, channel, index, count) {
|
|
13558
|
+
const data = await this.cmd("recording_get_channel_data", {
|
|
13559
|
+
recording_id: recordingId,
|
|
13560
|
+
device_id: deviceId,
|
|
13561
|
+
channel,
|
|
13562
|
+
index,
|
|
13563
|
+
count
|
|
13564
|
+
}, 3e4);
|
|
13565
|
+
return {
|
|
13566
|
+
interval: data.interval,
|
|
13567
|
+
values: data.values ?? []
|
|
13568
|
+
};
|
|
13569
|
+
}
|
|
13570
|
+
async getAllChannelData(recordingId, deviceId, channel) {
|
|
13571
|
+
const total = await this.getChannelDataCount(recordingId, deviceId, channel);
|
|
13572
|
+
let index = 0;
|
|
13573
|
+
let remaining = total;
|
|
13574
|
+
const chunkSize = 1e5;
|
|
13575
|
+
let interval = 0;
|
|
13576
|
+
const values = [];
|
|
13577
|
+
while (remaining > 0) {
|
|
13578
|
+
const count = Math.min(remaining, chunkSize);
|
|
13579
|
+
const data = await this.cmd("recording_get_channel_data", {
|
|
13580
|
+
recording_id: recordingId,
|
|
13581
|
+
device_id: deviceId,
|
|
13582
|
+
channel,
|
|
13583
|
+
index,
|
|
13584
|
+
count
|
|
13585
|
+
}, 3e4);
|
|
13586
|
+
if (index === 0) {
|
|
13587
|
+
interval = data.interval;
|
|
13588
|
+
}
|
|
13589
|
+
values.push(...data.values ?? []);
|
|
13590
|
+
index += count;
|
|
13591
|
+
remaining -= count;
|
|
13592
|
+
}
|
|
13593
|
+
return { interval, values };
|
|
13594
|
+
}
|
|
13595
|
+
async getBatteryProfiles() {
|
|
13596
|
+
const data = await this.cmd("otii_get_battery_profiles");
|
|
13597
|
+
return data?.battery_profiles ?? [];
|
|
13598
|
+
}
|
|
13599
|
+
async setSupplyBatteryEmulator(deviceId, opts) {
|
|
13600
|
+
await this.cmd("arc_set_supply_battery_emulator", {
|
|
13601
|
+
device_id: deviceId,
|
|
13602
|
+
battery_profile_id: opts.batteryProfileId,
|
|
13603
|
+
...opts.series !== void 0 ? { series: opts.series } : {},
|
|
13604
|
+
...opts.parallel !== void 0 ? { parallel: opts.parallel } : {},
|
|
13605
|
+
...opts.soc !== void 0 ? { soc: opts.soc } : {},
|
|
13606
|
+
...opts.usedCapacity !== void 0 ? { used_capacity: opts.usedCapacity } : {},
|
|
13607
|
+
...opts.socTracking !== void 0 ? { soc_tracking: opts.socTracking } : {}
|
|
13608
|
+
}, 1e4);
|
|
13609
|
+
}
|
|
13610
|
+
async setSupplyPowerBox(deviceId) {
|
|
13611
|
+
await this.cmd("arc_set_supply_power_box", {
|
|
13612
|
+
device_id: deviceId
|
|
13613
|
+
}, 1e4);
|
|
13614
|
+
}
|
|
13615
|
+
async isLoggedIn() {
|
|
13616
|
+
const data = await this.cmd("otii_is_logged_in");
|
|
13617
|
+
return data.logged_in;
|
|
13618
|
+
}
|
|
13619
|
+
async login(username, password) {
|
|
13620
|
+
await this.cmd("otii_login", { username, password }, 1e4);
|
|
13621
|
+
}
|
|
13622
|
+
async getLicenses() {
|
|
13623
|
+
const data = await this.cmd("otii_get_licenses");
|
|
13624
|
+
return data?.licenses ?? [];
|
|
13625
|
+
}
|
|
13626
|
+
async hasLicense(licenseType) {
|
|
13627
|
+
const data = await this.cmd("otii_has_license", { license_type: licenseType });
|
|
13628
|
+
return data.has_license;
|
|
13629
|
+
}
|
|
13630
|
+
async reserveLicense(licenseId) {
|
|
13631
|
+
await this.cmd("otii_reserve_license", { license_id: licenseId }, 1e4);
|
|
13632
|
+
}
|
|
13633
|
+
async returnLicense(licenseId) {
|
|
13634
|
+
await this.cmd("otii_return_license", { license_id: licenseId }, 1e4);
|
|
13635
|
+
}
|
|
13636
|
+
async logout() {
|
|
13637
|
+
await this.cmd("otii_logout", void 0, 1e4);
|
|
13638
|
+
}
|
|
13639
|
+
async cmd(cmd, data, timeoutMs = 3e3) {
|
|
13640
|
+
const rsp = await this.request(cmd, data, timeoutMs);
|
|
13641
|
+
return rsp.data;
|
|
13642
|
+
}
|
|
13643
|
+
async request(cmd, data, timeoutMs = 3e3) {
|
|
13644
|
+
if (!this.ready) {
|
|
13645
|
+
throw new Error("not connected");
|
|
13646
|
+
}
|
|
13647
|
+
const transId = String(this.nextId++);
|
|
13648
|
+
const req = {
|
|
13649
|
+
type: "request",
|
|
13650
|
+
cmd,
|
|
13651
|
+
trans_id: transId
|
|
13652
|
+
};
|
|
13653
|
+
if (data !== void 0) {
|
|
13654
|
+
req.data = data;
|
|
13655
|
+
}
|
|
13656
|
+
return await new Promise((resolve, reject) => {
|
|
13657
|
+
const timer = setTimeout(() => {
|
|
13658
|
+
this.pending.delete(transId);
|
|
13659
|
+
reject(new Error(`timeout waiting for ${cmd}`));
|
|
13660
|
+
}, timeoutMs);
|
|
13661
|
+
this.pending.set(transId, { resolve, reject, timer });
|
|
13662
|
+
this.logObj("send", req);
|
|
13663
|
+
this.socket.write(JSON.stringify(req) + "\r\n");
|
|
13664
|
+
});
|
|
13665
|
+
}
|
|
13666
|
+
onData(chunk) {
|
|
13667
|
+
this.rx += chunk.toString("utf8");
|
|
13668
|
+
for (; ; ) {
|
|
13669
|
+
const idx = this.rx.indexOf("\r\n");
|
|
13670
|
+
if (idx < 0) {
|
|
13671
|
+
break;
|
|
13672
|
+
}
|
|
13673
|
+
const line = this.rx.slice(0, idx).trim();
|
|
13674
|
+
this.rx = this.rx.slice(idx + 2);
|
|
13675
|
+
if (!line) {
|
|
13676
|
+
continue;
|
|
13677
|
+
}
|
|
13678
|
+
const msg = JSON.parse(line);
|
|
13679
|
+
this.logObj("recv", msg);
|
|
13680
|
+
if (msg.type === "information" && (msg.info === "connected" || msg.message === "connected")) {
|
|
13681
|
+
this.ready = true;
|
|
13682
|
+
const onBanner = this._onBanner;
|
|
13683
|
+
onBanner?.();
|
|
13684
|
+
continue;
|
|
13685
|
+
}
|
|
13686
|
+
if (!msg.trans_id) {
|
|
13687
|
+
continue;
|
|
13688
|
+
}
|
|
13689
|
+
const p = this.pending.get(msg.trans_id);
|
|
13690
|
+
if (!p) {
|
|
13691
|
+
continue;
|
|
13692
|
+
}
|
|
13693
|
+
clearTimeout(p.timer);
|
|
13694
|
+
this.pending.delete(msg.trans_id);
|
|
13695
|
+
if (msg.type === "error") {
|
|
13696
|
+
p.reject(new Error(msg.errorcode ?? `server error for ${msg.cmd}`));
|
|
13697
|
+
} else {
|
|
13698
|
+
p.resolve(msg);
|
|
13699
|
+
}
|
|
13700
|
+
}
|
|
13701
|
+
}
|
|
13702
|
+
onError(err) {
|
|
13703
|
+
for (const [, p] of this.pending) {
|
|
13704
|
+
clearTimeout(p.timer);
|
|
13705
|
+
p.reject(err);
|
|
13706
|
+
}
|
|
13707
|
+
this.pending.clear();
|
|
13708
|
+
}
|
|
13709
|
+
onClose() {
|
|
13710
|
+
const err = new Error("socket closed");
|
|
13711
|
+
for (const [, p] of this.pending) {
|
|
13712
|
+
clearTimeout(p.timer);
|
|
13713
|
+
p.reject(err);
|
|
13714
|
+
}
|
|
13715
|
+
this.pending.clear();
|
|
13716
|
+
}
|
|
13717
|
+
log(msg) {
|
|
13718
|
+
if (this.debug) {
|
|
13719
|
+
console.log(msg);
|
|
13720
|
+
}
|
|
13721
|
+
}
|
|
13722
|
+
logObj(prefix, obj) {
|
|
13723
|
+
if (this.debug) {
|
|
13724
|
+
console.log(`${prefix}:`, obj);
|
|
13725
|
+
}
|
|
13726
|
+
}
|
|
13727
|
+
};
|
|
13728
|
+
|
|
13103
13729
|
// src/Driver_PPK2.ts
|
|
13104
13730
|
var import_serialport = __toESM(require_dist13());
|
|
13105
13731
|
var mode_cmd_map = /* @__PURE__ */ new Map([
|
|
@@ -13117,7 +13743,7 @@ var MEAS_LOGIC = generateMask(8, 24);
|
|
|
13117
13743
|
var MAX_PAYLOAD_COUNTER = 63;
|
|
13118
13744
|
var DATALOSS_THRESHOLD = 500;
|
|
13119
13745
|
var getMaskedValue = (value, { mask, pos }) => (value & mask) >> pos;
|
|
13120
|
-
async function
|
|
13746
|
+
async function execCapture3(opts) {
|
|
13121
13747
|
const path_list = await findDevices();
|
|
13122
13748
|
const progress = new Progress("capturing: ");
|
|
13123
13749
|
const port = new import_serialport.SerialPort({ path: path_list[0], baudRate: 9600, autoOpen: false });
|
|
@@ -13158,18 +13784,57 @@ async function powerOn(voltage) {
|
|
|
13158
13784
|
progress.done();
|
|
13159
13785
|
}
|
|
13160
13786
|
async function findDevices() {
|
|
13161
|
-
let
|
|
13787
|
+
let candidates = new Array();
|
|
13162
13788
|
for (const port of await import_serialport.SerialPort.list()) {
|
|
13163
13789
|
const vid = port.vendorId;
|
|
13164
13790
|
const pid = port.productId;
|
|
13165
13791
|
if (vid == "1915" && pid.toLowerCase() == "c00a") {
|
|
13166
|
-
|
|
13792
|
+
candidates.push(port.path);
|
|
13793
|
+
}
|
|
13794
|
+
}
|
|
13795
|
+
fail("no PPK2 analyzer found", candidates.length == 0);
|
|
13796
|
+
if (candidates.length == 1) return candidates;
|
|
13797
|
+
const res = new Array();
|
|
13798
|
+
for (const path of candidates) {
|
|
13799
|
+
if (await probeDataPort(path)) {
|
|
13800
|
+
res.push(path);
|
|
13167
13801
|
}
|
|
13168
13802
|
}
|
|
13169
|
-
fail("no PPK2
|
|
13170
|
-
res.sort();
|
|
13803
|
+
fail("no PPK2 data port found (tried probing all candidates)", res.length == 0);
|
|
13171
13804
|
return res;
|
|
13172
13805
|
}
|
|
13806
|
+
async function probeDataPort(path, timeoutMs = 500) {
|
|
13807
|
+
let port;
|
|
13808
|
+
try {
|
|
13809
|
+
port = new import_serialport.SerialPort({ path, baudRate: 9600, autoOpen: false });
|
|
13810
|
+
await new Promise((resolve, reject) => {
|
|
13811
|
+
port.open((err) => err ? reject(err) : resolve());
|
|
13812
|
+
});
|
|
13813
|
+
return await new Promise((resolve) => {
|
|
13814
|
+
let responded = false;
|
|
13815
|
+
const onData = () => {
|
|
13816
|
+
if (!responded) {
|
|
13817
|
+
responded = true;
|
|
13818
|
+
resolve(true);
|
|
13819
|
+
}
|
|
13820
|
+
};
|
|
13821
|
+
port.on("data", onData);
|
|
13822
|
+
port.write([25 /* GET_META_DATA */]);
|
|
13823
|
+
setTimeout(() => {
|
|
13824
|
+
if (!responded) {
|
|
13825
|
+
responded = true;
|
|
13826
|
+
resolve(false);
|
|
13827
|
+
}
|
|
13828
|
+
}, timeoutMs);
|
|
13829
|
+
});
|
|
13830
|
+
} catch {
|
|
13831
|
+
return false;
|
|
13832
|
+
} finally {
|
|
13833
|
+
if (port?.isOpen) {
|
|
13834
|
+
await new Promise((resolve) => port.close(() => resolve()));
|
|
13835
|
+
}
|
|
13836
|
+
}
|
|
13837
|
+
}
|
|
13173
13838
|
function parseMods(mods) {
|
|
13174
13839
|
mods = mods.replace("END", "").trim().toLowerCase().replace(/-nan/g, "null").replace(/\n/g, ',\n"').replace(/: /g, '": ');
|
|
13175
13840
|
let res;
|
|
@@ -13378,6 +14043,8 @@ async function exec3(opts) {
|
|
|
13378
14043
|
}
|
|
13379
14044
|
c = await execCapture(opts);
|
|
13380
14045
|
} else if (opts.ppk2) {
|
|
14046
|
+
c = await execCapture3(opts);
|
|
14047
|
+
} else if (opts.otii3) {
|
|
13381
14048
|
c = await execCapture2(opts);
|
|
13382
14049
|
} else {
|
|
13383
14050
|
fail("you must specify an analyzer device");
|
|
@@ -13573,7 +14240,7 @@ function printEventInfo(cap, markers) {
|
|
|
13573
14240
|
avg += egy * scale;
|
|
13574
14241
|
const dur = (cap.current_sig.offToSecs(m.width) * 1e3).toFixed(2).padStart(5, " ");
|
|
13575
14242
|
const off_s = cap.current_sig.offToSecs(m.offset).toFixed(2).padStart(5, " ");
|
|
13576
|
-
infoMsg(`${lab} :: time = ${off_s} s, energy = ${uJoules(egy)}, duration = ${dur}
|
|
14243
|
+
infoMsg(`${lab} :: time = ${off_s} s, energy = ${uJoules(egy)}, duration = ${dur} ms`);
|
|
13577
14244
|
lab = String.fromCharCode(lab.charCodeAt(0) + 1);
|
|
13578
14245
|
}
|
|
13579
14246
|
infoMsg("----");
|
|
@@ -13672,7 +14339,7 @@ var {
|
|
|
13672
14339
|
var CAP = ["-c --capture <directory path>", "working capture directory", "."];
|
|
13673
14340
|
var VERS = version();
|
|
13674
14341
|
var CMD = new Command("emscope").option("-C, --capture-glob [name pattern]", `apply this command to each matching child capture directory (default "**")`).version(VERS);
|
|
13675
|
-
CMD.command("grab").description("record power signals with an attached capture device").option(CAP[0], CAP[1], CAP[2]).option("-d --duration <value>", "capture duration in seconds", parseFloat, 3).option("-J --js220", "use a Joulescope JS220 device").option("-P --ppk2", "use a Nordic PPK2 device").addOption(new Option("-A --ampere-mode", "enable PPK ampere mode").conflicts(["sourceMode", "js220"])).addOption(new Option("-S --source-mode", "enable PPK source mode").default(true).conflicts(["ampereMode", "js220"])).addOption(new Option("-p, --ppk2-supply
|
|
14342
|
+
CMD.command("grab").description("record power signals with an attached capture device").option(CAP[0], CAP[1], CAP[2]).option("-d --duration <value>", "capture duration in seconds", parseFloat, 3).option("-J --js220", "use a Joulescope JS220 device").option("-O --otii3", "use a Qoitech Otii3 device").option("-P --ppk2", "use a Nordic PPK2 device").addOption(new Option("-A --ampere-mode", "enable PPK ampere mode").conflicts(["sourceMode", "otii3", "js220"])).addOption(new Option("-S --source-mode", "enable PPK source mode").default(true).conflicts(["ampereMode", "otii3", "js220"])).addOption(new Option("-B, --battery-profile <index>", "use Otii battery profile (implies -O)").argParser(parseFloat).implies({ otii3: true }).conflicts(["js220", "ppk2"])).addOption(new Option("-p, --ppk2-supply <voltage>", "supply JS220 voltage from a PPK").argParser(parseFloat).conflicts(["otii3", "ppk2"])).addOption(new Option("-v, --voltage [value]", "source voltage").argParser(parseFloat).default(3.3).conflicts("js220")).addOption(new Option("--soc <percent>", "battery state of charge (implies -O)").argParser(parseFloat).implies({ otii3: true })).action((opts, cmd) => execCmd(exec3, opts, cmd.parent.opts()));
|
|
13676
14343
|
CMD.command("scan").description("analyze captured data and locate active events").option(CAP[0], CAP[1], CAP[2]).option("-d, --min-duration <milliseconds>", "remove events whose duration is under a threshold", parseFloat).option("-e, --min-energy <microJoules>", "remove events whose energy is under a threshold", parseFloat).option("-g, --gap <milliseconds>", "combine adjacent events whose gap is under a threshold", parseFloat).option("-t --trim <event count>", "remove extra events", parseFloat).option("--refresh", "(re-)scan using the last set of options").action((opts, cmd) => execCmd(exec, opts, cmd.parent.opts()));
|
|
13677
14344
|
CMD.command("view").description("present captured data in different formats").option(CAP[0], CAP[1], CAP[2]).option("-e --event-info", "characterize power consumption when active").option("-j --jls-file [event ID]", "generate a Joulescope .jls file containing events").option("-s --sleep-info", "characterize power consumption when inactive").option("-w --what-if [event period]", `extrapolate results for a given event period (default: '00:00:01')`, parseHms).option("--score", "only print the EM\u2022eralds benchmark score").option("--json", "output results as JSON (machine-readable)").action((opts, cmd) => execCmd(exec4, opts, cmd.parent.opts()));
|
|
13678
14345
|
CMD.command("pack").description(`bundle captured data into an 'emscope.zip' file`).option(CAP[0], CAP[1], CAP[2]).option("-a --about-file", `update the 'ABOUT.md' file only`).option("-s,--status", `status of the 'emscope.zip' file`).option("-u --unpack", `deflate the 'emscope.zip' file for local use`).option("-z --zip-file", `generate the 'emscope.zip' file`).option("--restore", `restores the 'emscope.zip' LFS descriptor (debug only)`).action((opts, cmd) => execCmd(exec2, opts, cmd.parent.opts()));
|
|
@@ -13685,6 +14352,5 @@ try {
|
|
|
13685
14352
|
/*! Bundled license information:
|
|
13686
14353
|
|
|
13687
14354
|
js-yaml/dist/js-yaml.mjs:
|
|
13688
|
-
(*! js-yaml 4.1.
|
|
14355
|
+
(*! js-yaml 4.1.1 https://github.com/nodeca/js-yaml @license MIT *)
|
|
13689
14356
|
*/
|
|
13690
|
-
//# sourceMappingURL=emscope.map
|