@formant/formant-cli 0.1.0 → 0.3.0
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/README.md +380 -116
- package/dist/base-command.d.ts +5 -0
- package/dist/base-command.js +9 -0
- package/dist/base-command.js.map +1 -1
- package/dist/commands/devices/create.d.ts +13 -0
- package/dist/commands/devices/create.js +62 -0
- package/dist/commands/devices/create.js.map +1 -0
- package/dist/commands/devices/delete.d.ts +10 -0
- package/dist/commands/devices/delete.js +49 -0
- package/dist/commands/devices/delete.js.map +1 -0
- package/dist/commands/devices/rename.d.ts +11 -0
- package/dist/commands/devices/rename.js +42 -0
- package/dist/commands/devices/rename.js.map +1 -0
- package/dist/commands/devices/tag.d.ts +13 -0
- package/dist/commands/devices/tag.js +69 -0
- package/dist/commands/devices/tag.js.map +1 -0
- package/dist/commands/devices/untag.d.ts +13 -0
- package/dist/commands/devices/untag.js +79 -0
- package/dist/commands/devices/untag.js.map +1 -0
- package/dist/commands/ingest/batch.d.ts +21 -0
- package/dist/commands/ingest/batch.js +170 -0
- package/dist/commands/ingest/batch.js.map +1 -0
- package/dist/commands/ingest/bitset.d.ts +15 -0
- package/dist/commands/ingest/bitset.js +128 -0
- package/dist/commands/ingest/bitset.js.map +1 -0
- package/dist/commands/ingest/health.d.ts +15 -0
- package/dist/commands/ingest/health.js +94 -0
- package/dist/commands/ingest/health.js.map +1 -0
- package/dist/commands/ingest/image.d.ts +15 -0
- package/dist/commands/ingest/image.js +99 -0
- package/dist/commands/ingest/image.js.map +1 -0
- package/dist/commands/ingest/json.d.ts +16 -0
- package/dist/commands/ingest/json.js +92 -0
- package/dist/commands/ingest/json.js.map +1 -0
- package/dist/commands/ingest/numeric.d.ts +16 -0
- package/dist/commands/ingest/numeric.js +83 -0
- package/dist/commands/ingest/numeric.js.map +1 -0
- package/dist/commands/ingest/text.d.ts +16 -0
- package/dist/commands/ingest/text.js +80 -0
- package/dist/commands/ingest/text.js.map +1 -0
- package/dist/commands/ingest/video.d.ts +16 -0
- package/dist/commands/ingest/video.js +120 -0
- package/dist/commands/ingest/video.js.map +1 -0
- package/dist/commands/org/get.d.ts +7 -0
- package/dist/commands/org/get.js +54 -0
- package/dist/commands/org/get.js.map +1 -0
- package/dist/commands/org/update.d.ts +11 -0
- package/dist/commands/org/update.js +75 -0
- package/dist/commands/org/update.js.map +1 -0
- package/dist/help.js +103 -53
- package/dist/help.js.map +1 -1
- package/dist/lib/api.d.ts +1 -1
- package/dist/lib/api.js +3 -0
- package/dist/lib/api.js.map +1 -1
- package/oclif.manifest.json +1861 -612
- package/package.json +7 -1
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command.js';
|
|
2
|
+
export default class IngestBitset extends BaseCommand<typeof IngestBitset> {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
device: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
stream: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
+
keys: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
values: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
tag: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
timestamp: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
static summary: string;
|
|
14
|
+
run(): Promise<Record<string, unknown>>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../base-command.js';
|
|
3
|
+
export default class IngestBitset extends BaseCommand {
|
|
4
|
+
static description = `Ingest a bitset data point to a device stream.
|
|
5
|
+
|
|
6
|
+
Sends a bitset (array of named boolean values) to the specified device stream. A bitset
|
|
7
|
+
consists of parallel arrays of keys (strings) and values (booleans).
|
|
8
|
+
|
|
9
|
+
Bitsets are useful for representing sets of binary states, flags, or boolean sensor readings
|
|
10
|
+
where you have multiple named on/off states.
|
|
11
|
+
|
|
12
|
+
Constraints:
|
|
13
|
+
- Must have 1-1000 key/value pairs
|
|
14
|
+
- Keys must be max 255 characters each
|
|
15
|
+
- Keys and values arrays must have the same length`;
|
|
16
|
+
static examples = [
|
|
17
|
+
'<%= config.bin %> ingest bitset --device <device-id> --stream sensors --keys "door,window,motion" --values "true,false,true"',
|
|
18
|
+
'<%= config.bin %> ingest bitset --device <device-id> --stream flags --keys "active,paused,error" --values "true,false,false" --tag system=main',
|
|
19
|
+
'<%= config.bin %> ingest bitset --device <device-id> --stream states --keys "a,b" --values "false,true"',
|
|
20
|
+
];
|
|
21
|
+
static flags = {
|
|
22
|
+
device: Flags.string({
|
|
23
|
+
char: 'd',
|
|
24
|
+
description: 'Device ID (UUID)',
|
|
25
|
+
required: true,
|
|
26
|
+
}),
|
|
27
|
+
stream: Flags.string({
|
|
28
|
+
char: 's',
|
|
29
|
+
description: 'Stream name',
|
|
30
|
+
required: true,
|
|
31
|
+
}),
|
|
32
|
+
keys: Flags.string({
|
|
33
|
+
char: 'k',
|
|
34
|
+
description: 'Comma-separated list of key names (1-1000 keys, max 255 chars each)',
|
|
35
|
+
required: true,
|
|
36
|
+
}),
|
|
37
|
+
values: Flags.string({
|
|
38
|
+
char: 'v',
|
|
39
|
+
description: 'Comma-separated list of boolean values (true/false, must match key count)',
|
|
40
|
+
required: true,
|
|
41
|
+
}),
|
|
42
|
+
tag: Flags.string({
|
|
43
|
+
char: 't',
|
|
44
|
+
description: 'Tag as key=value where both are strings (can be specified multiple times)',
|
|
45
|
+
multiple: true,
|
|
46
|
+
}),
|
|
47
|
+
timestamp: Flags.string({
|
|
48
|
+
description: 'Unix timestamp in milliseconds (defaults to now)',
|
|
49
|
+
}),
|
|
50
|
+
};
|
|
51
|
+
static summary = 'Ingest bitset data';
|
|
52
|
+
async run() {
|
|
53
|
+
// Parse keys
|
|
54
|
+
const keys = this.flags.keys.split(',').map((k) => k.trim());
|
|
55
|
+
// Parse values
|
|
56
|
+
const valueStrings = this.flags.values.split(',').map((v) => v.trim().toLowerCase());
|
|
57
|
+
const values = [];
|
|
58
|
+
for (const v of valueStrings) {
|
|
59
|
+
if (v === 'true') {
|
|
60
|
+
values.push(true);
|
|
61
|
+
}
|
|
62
|
+
else if (v === 'false') {
|
|
63
|
+
values.push(false);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
this.error(`Invalid boolean value: "${v}". Must be "true" or "false".`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Validate arrays have same length
|
|
70
|
+
if (keys.length !== values.length) {
|
|
71
|
+
this.error(`Keys and values must have the same count. Got ${keys.length} keys and ${values.length} values.`);
|
|
72
|
+
}
|
|
73
|
+
// Validate count (1-1000)
|
|
74
|
+
if (keys.length < 1 || keys.length > 1000) {
|
|
75
|
+
this.error('Bitset must have between 1 and 1000 key/value pairs.');
|
|
76
|
+
}
|
|
77
|
+
// Validate key lengths
|
|
78
|
+
for (const key of keys) {
|
|
79
|
+
if (key.length > 255) {
|
|
80
|
+
this.error(`Key "${key}" exceeds maximum length of 255 characters.`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Build bitset value
|
|
84
|
+
const bitsetValue = {
|
|
85
|
+
keys,
|
|
86
|
+
values,
|
|
87
|
+
};
|
|
88
|
+
// Parse tags
|
|
89
|
+
const tags = {};
|
|
90
|
+
if (this.flags.tag) {
|
|
91
|
+
for (const tag of this.flags.tag) {
|
|
92
|
+
const [tagKey, ...valueParts] = tag.split('=');
|
|
93
|
+
if (!tagKey || valueParts.length === 0) {
|
|
94
|
+
this.error(`Invalid tag format: "${tag}". Must be key=value.`);
|
|
95
|
+
}
|
|
96
|
+
tags[tagKey] = valueParts.join('=');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Parse timestamp
|
|
100
|
+
let timestamp = Date.now();
|
|
101
|
+
if (this.flags.timestamp) {
|
|
102
|
+
timestamp = Number.parseInt(this.flags.timestamp, 10);
|
|
103
|
+
if (Number.isNaN(timestamp) || timestamp <= 0) {
|
|
104
|
+
this.error(`Invalid timestamp: "${this.flags.timestamp}". Must be a positive integer.`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// Build request body
|
|
108
|
+
const body = {
|
|
109
|
+
items: [
|
|
110
|
+
{
|
|
111
|
+
deviceId: this.flags.device,
|
|
112
|
+
name: this.flags.stream,
|
|
113
|
+
type: 'bitset',
|
|
114
|
+
tags,
|
|
115
|
+
points: [[timestamp, bitsetValue]],
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
};
|
|
119
|
+
// Send request (expect 204 No Content)
|
|
120
|
+
await this.api('ingest', 'batch', { body, method: 'POST' });
|
|
121
|
+
if (!this.jsonEnabled()) {
|
|
122
|
+
this.log(`\n✓ Ingested bitset with ${keys.length} entries to stream "${this.flags.stream}" on device ${this.flags.device} (${this.env})\n`);
|
|
123
|
+
}
|
|
124
|
+
// Return the request body for --json output
|
|
125
|
+
return body;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=bitset.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bitset.js","sourceRoot":"","sources":["../../../src/commands/ingest/bitset.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,aAAa,CAAA;AAEjC,OAAO,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAA;AAEjD,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,WAAgC;IACxE,MAAM,CAAU,WAAW,GAAG;;;;;;;;;;;mDAWmB,CAAA;IAEjD,MAAM,CAAU,QAAQ,GAAG;QACzB,8HAA8H;QAC9H,gJAAgJ;QAChJ,yGAAyG;KAC1G,CAAA;IAED,MAAM,CAAU,KAAK,GAAG;QACtB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;YACnB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,kBAAkB;YAC/B,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;YACnB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,aAAa;YAC1B,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC;YACjB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,qEAAqE;YAClF,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;YACnB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,2EAA2E;YACxF,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC;YAChB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,2EAA2E;YACxF,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC;YACtB,WAAW,EAAE,kDAAkD;SAChE,CAAC;KACH,CAAA;IAED,MAAM,CAAU,OAAO,GAAG,oBAAoB,CAAA;IAEvC,KAAK,CAAC,GAAG;QACd,aAAa;QACb,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;QAE5D,eAAe;QACf,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAA;QACpF,MAAM,MAAM,GAAc,EAAE,CAAA;QAE5B,KAAK,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC;YAC7B,IAAI,CAAC,KAAK,MAAM,EAAE,CAAC;gBACjB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACnB,CAAC;iBAAM,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC;gBACzB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YACpB,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,KAAK,CAAC,2BAA2B,CAAC,+BAA+B,CAAC,CAAA;YACzE,CAAC;QACH,CAAC;QAED,mCAAmC;QACnC,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;YAClC,IAAI,CAAC,KAAK,CACR,iDAAiD,IAAI,CAAC,MAAM,aAAa,MAAM,CAAC,MAAM,UAAU,CACjG,CAAA;QACH,CAAC;QAED,0BAA0B;QAC1B,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;YAC1C,IAAI,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAA;QACpE,CAAC;QAED,uBAAuB;QACvB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;gBACrB,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,6CAA6C,CAAC,CAAA;YACtE,CAAC;QACH,CAAC;QAED,qBAAqB;QACrB,MAAM,WAAW,GAAG;YAClB,IAAI;YACJ,MAAM;SACP,CAAA;QAED,aAAa;QACb,MAAM,IAAI,GAA2B,EAAE,CAAA;QACvC,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;YACnB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;gBACjC,MAAM,CAAC,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;gBAC9C,IAAI,CAAC,MAAM,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACvC,IAAI,CAAC,KAAK,CAAC,wBAAwB,GAAG,uBAAuB,CAAC,CAAA;gBAChE,CAAC;gBAED,IAAI,CAAC,MAAM,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACrC,CAAC;QACH,CAAC;QAED,kBAAkB;QAClB,IAAI,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC1B,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;YACzB,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA;YACrD,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;gBAC9C,IAAI,CAAC,KAAK,CAAC,uBAAuB,IAAI,CAAC,KAAK,CAAC,SAAS,gCAAgC,CAAC,CAAA;YACzF,CAAC;QACH,CAAC;QAED,qBAAqB;QACrB,MAAM,IAAI,GAAG;YACX,KAAK,EAAE;gBACL;oBACE,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM;oBAC3B,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM;oBACvB,IAAI,EAAE,QAAQ;oBACd,IAAI;oBACJ,MAAM,EAAE,CAAC,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;iBACnC;aACF;SACF,CAAA;QAED,uCAAuC;QACvC,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAC,CAAC,CAAA;QAEzD,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,IAAI,CAAC,GAAG,CACN,4BAA4B,IAAI,CAAC,MAAM,uBAAuB,IAAI,CAAC,KAAK,CAAC,MAAM,eAAe,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC,GAAG,KAAK,CAClI,CAAA;QACH,CAAC;QAED,4CAA4C;QAC5C,OAAO,IAAI,CAAA;IACb,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command.js';
|
|
2
|
+
export default class IngestHealth extends BaseCommand<typeof IngestHealth> {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
device: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
stream: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
+
status: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
'clock-skew': import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
tag: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
timestamp: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
static summary: string;
|
|
14
|
+
run(): Promise<Record<string, unknown>>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../base-command.js';
|
|
3
|
+
export default class IngestHealth extends BaseCommand {
|
|
4
|
+
static description = `Ingest a health status data point to a device stream.
|
|
5
|
+
|
|
6
|
+
Sends device health status information to the specified stream. Health data consists of:
|
|
7
|
+
- status: One of "unknown", "operational", "offline", or "error"
|
|
8
|
+
- clockSkewMs (optional): Clock skew in milliseconds between device and server
|
|
9
|
+
|
|
10
|
+
Health streams are used to track device operational state, system health, and time synchronization.`;
|
|
11
|
+
static examples = [
|
|
12
|
+
'<%= config.bin %> ingest health --device <device-id> --stream system_health --status operational',
|
|
13
|
+
'<%= config.bin %> ingest health --device <device-id> --stream health --status error --tag component=motor',
|
|
14
|
+
'<%= config.bin %> ingest health --device <device-id> --stream sync --status operational --clock-skew 150',
|
|
15
|
+
];
|
|
16
|
+
static flags = {
|
|
17
|
+
device: Flags.string({
|
|
18
|
+
char: 'd',
|
|
19
|
+
description: 'Device ID (UUID)',
|
|
20
|
+
required: true,
|
|
21
|
+
}),
|
|
22
|
+
stream: Flags.string({
|
|
23
|
+
char: 's',
|
|
24
|
+
description: 'Stream name',
|
|
25
|
+
required: true,
|
|
26
|
+
}),
|
|
27
|
+
status: Flags.string({
|
|
28
|
+
description: 'Health status (unknown, operational, offline, or error)',
|
|
29
|
+
options: ['unknown', 'operational', 'offline', 'error'],
|
|
30
|
+
required: true,
|
|
31
|
+
}),
|
|
32
|
+
'clock-skew': Flags.integer({
|
|
33
|
+
description: 'Clock skew in milliseconds (optional)',
|
|
34
|
+
}),
|
|
35
|
+
tag: Flags.string({
|
|
36
|
+
char: 't',
|
|
37
|
+
description: 'Tag as key=value where both are strings (can be specified multiple times)',
|
|
38
|
+
multiple: true,
|
|
39
|
+
}),
|
|
40
|
+
timestamp: Flags.string({
|
|
41
|
+
description: 'Unix timestamp in milliseconds (defaults to now)',
|
|
42
|
+
}),
|
|
43
|
+
};
|
|
44
|
+
static summary = 'Ingest health status data';
|
|
45
|
+
async run() {
|
|
46
|
+
// Build health value
|
|
47
|
+
const healthValue = {
|
|
48
|
+
status: this.flags.status,
|
|
49
|
+
};
|
|
50
|
+
if (this.flags['clock-skew'] !== undefined) {
|
|
51
|
+
healthValue.clockSkewMs = this.flags['clock-skew'];
|
|
52
|
+
}
|
|
53
|
+
// Parse tags
|
|
54
|
+
const tags = {};
|
|
55
|
+
if (this.flags.tag) {
|
|
56
|
+
for (const tag of this.flags.tag) {
|
|
57
|
+
const [key, ...valueParts] = tag.split('=');
|
|
58
|
+
if (!key || valueParts.length === 0) {
|
|
59
|
+
this.error(`Invalid tag format: "${tag}". Must be key=value.`);
|
|
60
|
+
}
|
|
61
|
+
tags[key] = valueParts.join('=');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// Parse timestamp
|
|
65
|
+
let timestamp = Date.now();
|
|
66
|
+
if (this.flags.timestamp) {
|
|
67
|
+
timestamp = Number.parseInt(this.flags.timestamp, 10);
|
|
68
|
+
if (Number.isNaN(timestamp) || timestamp <= 0) {
|
|
69
|
+
this.error(`Invalid timestamp: "${this.flags.timestamp}". Must be a positive integer.`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Build request body
|
|
73
|
+
const body = {
|
|
74
|
+
items: [
|
|
75
|
+
{
|
|
76
|
+
deviceId: this.flags.device,
|
|
77
|
+
name: this.flags.stream,
|
|
78
|
+
type: 'health',
|
|
79
|
+
tags,
|
|
80
|
+
points: [[timestamp, healthValue]],
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
};
|
|
84
|
+
// Send request (expect 204 No Content)
|
|
85
|
+
await this.api('ingest', 'batch', { body, method: 'POST' });
|
|
86
|
+
if (!this.jsonEnabled()) {
|
|
87
|
+
const skewInfo = this.flags['clock-skew'] ? `, clock skew: ${this.flags['clock-skew']}ms` : '';
|
|
88
|
+
this.log(`\n✓ Ingested health status "${this.flags.status}"${skewInfo} to stream "${this.flags.stream}" on device ${this.flags.device} (${this.env})\n`);
|
|
89
|
+
}
|
|
90
|
+
// Return the request body for --json output
|
|
91
|
+
return body;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../../src/commands/ingest/health.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command.js';
|
|
2
|
+
export default class IngestImage extends BaseCommand<typeof IngestImage> {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
device: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
stream: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
+
url: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
size: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
tag: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
timestamp: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
static summary: string;
|
|
14
|
+
run(): Promise<Record<string, unknown>>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../base-command.js';
|
|
3
|
+
export default class IngestImage extends BaseCommand {
|
|
4
|
+
static description = `Ingest an image URL to a device stream.
|
|
5
|
+
|
|
6
|
+
Sends an image reference (by URL) to the specified device stream. The image must be accessible
|
|
7
|
+
via HTTP/HTTPS. Formant will fetch and store the image from the provided URL.
|
|
8
|
+
|
|
9
|
+
Image streams are used for camera feeds, snapshots, diagnostic images, etc.`;
|
|
10
|
+
static examples = [
|
|
11
|
+
'<%= config.bin %> ingest image --device <device-id> --stream camera_front --url https://example.com/image.jpg',
|
|
12
|
+
'<%= config.bin %> ingest image --device <device-id> --stream snapshot --url https://example.com/snap.png --size 1024000',
|
|
13
|
+
'<%= config.bin %> ingest image --device <device-id> --stream detection --url https://example.com/detect.jpg --tag frame=123',
|
|
14
|
+
];
|
|
15
|
+
static flags = {
|
|
16
|
+
device: Flags.string({
|
|
17
|
+
char: 'd',
|
|
18
|
+
description: 'Device ID (UUID)',
|
|
19
|
+
required: true,
|
|
20
|
+
}),
|
|
21
|
+
stream: Flags.string({
|
|
22
|
+
char: 's',
|
|
23
|
+
description: 'Stream name',
|
|
24
|
+
required: true,
|
|
25
|
+
}),
|
|
26
|
+
url: Flags.string({
|
|
27
|
+
char: 'u',
|
|
28
|
+
description: 'Image URL (must be http:// or https://)',
|
|
29
|
+
required: true,
|
|
30
|
+
}),
|
|
31
|
+
size: Flags.integer({
|
|
32
|
+
description: 'Image size in bytes (optional)',
|
|
33
|
+
}),
|
|
34
|
+
tag: Flags.string({
|
|
35
|
+
char: 't',
|
|
36
|
+
description: 'Tag as key=value where both are strings (can be specified multiple times)',
|
|
37
|
+
multiple: true,
|
|
38
|
+
}),
|
|
39
|
+
timestamp: Flags.string({
|
|
40
|
+
description: 'Unix timestamp in milliseconds (defaults to now)',
|
|
41
|
+
}),
|
|
42
|
+
};
|
|
43
|
+
static summary = 'Ingest image data';
|
|
44
|
+
async run() {
|
|
45
|
+
// Validate URL format
|
|
46
|
+
if (!this.flags.url.match(/^https?:\/\//i)) {
|
|
47
|
+
this.error('Image URL must start with http:// or https://');
|
|
48
|
+
}
|
|
49
|
+
// Build image value object
|
|
50
|
+
const imageValue = {
|
|
51
|
+
url: this.flags.url,
|
|
52
|
+
};
|
|
53
|
+
if (this.flags.size !== undefined) {
|
|
54
|
+
if (this.flags.size <= 0) {
|
|
55
|
+
this.error('Image size must be a positive number');
|
|
56
|
+
}
|
|
57
|
+
imageValue.size = this.flags.size;
|
|
58
|
+
}
|
|
59
|
+
// Parse tags
|
|
60
|
+
const tags = {};
|
|
61
|
+
if (this.flags.tag) {
|
|
62
|
+
for (const tag of this.flags.tag) {
|
|
63
|
+
const [key, ...valueParts] = tag.split('=');
|
|
64
|
+
if (!key || valueParts.length === 0) {
|
|
65
|
+
this.error(`Invalid tag format: "${tag}". Must be key=value.`);
|
|
66
|
+
}
|
|
67
|
+
tags[key] = valueParts.join('=');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Parse timestamp
|
|
71
|
+
let timestamp = Date.now();
|
|
72
|
+
if (this.flags.timestamp) {
|
|
73
|
+
timestamp = Number.parseInt(this.flags.timestamp, 10);
|
|
74
|
+
if (Number.isNaN(timestamp) || timestamp <= 0) {
|
|
75
|
+
this.error(`Invalid timestamp: "${this.flags.timestamp}". Must be a positive integer.`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Build request body
|
|
79
|
+
const body = {
|
|
80
|
+
items: [
|
|
81
|
+
{
|
|
82
|
+
deviceId: this.flags.device,
|
|
83
|
+
name: this.flags.stream,
|
|
84
|
+
type: 'image',
|
|
85
|
+
tags,
|
|
86
|
+
points: [[timestamp, imageValue]],
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
};
|
|
90
|
+
// Send request (expect 204 No Content)
|
|
91
|
+
await this.api('ingest', 'batch', { body, method: 'POST' });
|
|
92
|
+
if (!this.jsonEnabled()) {
|
|
93
|
+
this.log(`\n✓ Ingested image ${this.flags.url} to stream "${this.flags.stream}" on device ${this.flags.device} (${this.env})\n`);
|
|
94
|
+
}
|
|
95
|
+
// Return the request body for --json output
|
|
96
|
+
return body;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=image.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image.js","sourceRoot":"","sources":["../../../src/commands/ingest/image.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command.js';
|
|
2
|
+
export default class IngestJson extends BaseCommand<typeof IngestJson> {
|
|
3
|
+
static args: {
|
|
4
|
+
value: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
5
|
+
};
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
device: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
stream: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
tag: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
timestamp: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
};
|
|
14
|
+
static summary: string;
|
|
15
|
+
run(): Promise<Record<string, unknown>>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../base-command.js';
|
|
3
|
+
export default class IngestJson extends BaseCommand {
|
|
4
|
+
static args = {
|
|
5
|
+
value: Args.string({ description: 'JSON value to ingest (as a JSON string)', required: true }),
|
|
6
|
+
};
|
|
7
|
+
static description = `Ingest a JSON data point to a device stream.
|
|
8
|
+
|
|
9
|
+
Sends structured JSON data to the specified device stream. The value must be valid JSON.
|
|
10
|
+
JSON streams are used for complex structured data like configuration objects, state machines,
|
|
11
|
+
nested telemetry, etc.
|
|
12
|
+
|
|
13
|
+
Note: The JSON is sent as a JSON-encoded string to Formant.`;
|
|
14
|
+
static examples = [
|
|
15
|
+
'<%= config.bin %> ingest json \'{"x":1,"y":2}\' --device <device-id> --stream position',
|
|
16
|
+
'<%= config.bin %> ingest json \'{"status":"active","mode":"auto"}\' --device <device-id> --stream config',
|
|
17
|
+
'<%= config.bin %> ingest json \'[1,2,3,4,5]\' --device <device-id> --stream array_data',
|
|
18
|
+
];
|
|
19
|
+
static flags = {
|
|
20
|
+
device: Flags.string({
|
|
21
|
+
char: 'd',
|
|
22
|
+
description: 'Device ID (UUID)',
|
|
23
|
+
required: true,
|
|
24
|
+
}),
|
|
25
|
+
stream: Flags.string({
|
|
26
|
+
char: 's',
|
|
27
|
+
description: 'Stream name',
|
|
28
|
+
required: true,
|
|
29
|
+
}),
|
|
30
|
+
tag: Flags.string({
|
|
31
|
+
char: 't',
|
|
32
|
+
description: 'Tag as key=value where both are strings (can be specified multiple times)',
|
|
33
|
+
multiple: true,
|
|
34
|
+
}),
|
|
35
|
+
timestamp: Flags.string({
|
|
36
|
+
description: 'Unix timestamp in milliseconds (defaults to now)',
|
|
37
|
+
}),
|
|
38
|
+
};
|
|
39
|
+
static summary = 'Ingest JSON data';
|
|
40
|
+
async run() {
|
|
41
|
+
// Validate JSON
|
|
42
|
+
let jsonValue;
|
|
43
|
+
try {
|
|
44
|
+
// Parse to validate, but send as string
|
|
45
|
+
JSON.parse(this.args.value);
|
|
46
|
+
jsonValue = this.args.value;
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
this.error(`Invalid JSON value: ${error instanceof Error ? error.message : 'Unknown error'}.\nValue must be valid JSON.`);
|
|
50
|
+
}
|
|
51
|
+
// Parse tags
|
|
52
|
+
const tags = {};
|
|
53
|
+
if (this.flags.tag) {
|
|
54
|
+
for (const tag of this.flags.tag) {
|
|
55
|
+
const [key, ...valueParts] = tag.split('=');
|
|
56
|
+
if (!key || valueParts.length === 0) {
|
|
57
|
+
this.error(`Invalid tag format: "${tag}". Must be key=value.`);
|
|
58
|
+
}
|
|
59
|
+
tags[key] = valueParts.join('=');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// Parse timestamp
|
|
63
|
+
let timestamp = Date.now();
|
|
64
|
+
if (this.flags.timestamp) {
|
|
65
|
+
timestamp = Number.parseInt(this.flags.timestamp, 10);
|
|
66
|
+
if (Number.isNaN(timestamp) || timestamp <= 0) {
|
|
67
|
+
this.error(`Invalid timestamp: "${this.flags.timestamp}". Must be a positive integer.`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Build request body (json type sends the value as a JSON string)
|
|
71
|
+
const body = {
|
|
72
|
+
items: [
|
|
73
|
+
{
|
|
74
|
+
deviceId: this.flags.device,
|
|
75
|
+
name: this.flags.stream,
|
|
76
|
+
type: 'json',
|
|
77
|
+
tags,
|
|
78
|
+
points: [[timestamp, jsonValue]],
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
};
|
|
82
|
+
// Send request (expect 204 No Content)
|
|
83
|
+
await this.api('ingest', 'batch', { body, method: 'POST' });
|
|
84
|
+
if (!this.jsonEnabled()) {
|
|
85
|
+
const preview = jsonValue.length > 50 ? `${jsonValue.slice(0, 47)}...` : jsonValue;
|
|
86
|
+
this.log(`\n✓ Ingested JSON ${preview} to stream "${this.flags.stream}" on device ${this.flags.device} (${this.env})\n`);
|
|
87
|
+
}
|
|
88
|
+
// Return the request body for --json output
|
|
89
|
+
return body;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../../../src/commands/ingest/json.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command.js';
|
|
2
|
+
export default class IngestNumeric extends BaseCommand<typeof IngestNumeric> {
|
|
3
|
+
static args: {
|
|
4
|
+
value: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
5
|
+
};
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
device: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
stream: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
tag: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
timestamp: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
};
|
|
14
|
+
static summary: string;
|
|
15
|
+
run(): Promise<Record<string, unknown>>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../base-command.js';
|
|
3
|
+
export default class IngestNumeric extends BaseCommand {
|
|
4
|
+
static args = {
|
|
5
|
+
value: Args.string({ description: 'Numeric value to ingest', required: true }),
|
|
6
|
+
};
|
|
7
|
+
static description = `Ingest a numeric data point to a device stream.
|
|
8
|
+
|
|
9
|
+
Sends a single numeric value to the specified device stream. The value must be a valid number.
|
|
10
|
+
Numeric streams are commonly used for sensor readings like battery level, temperature, speed, etc.`;
|
|
11
|
+
static examples = [
|
|
12
|
+
'<%= config.bin %> ingest numeric 42.5 --device <device-id> --stream battery_level',
|
|
13
|
+
'<%= config.bin %> ingest numeric 98.6 --device <device-id> --stream temperature --tag unit=fahrenheit',
|
|
14
|
+
'<%= config.bin %> ingest numeric 1500 --device <device-id> --stream rpm --timestamp 1700000000000',
|
|
15
|
+
];
|
|
16
|
+
static flags = {
|
|
17
|
+
device: Flags.string({
|
|
18
|
+
char: 'd',
|
|
19
|
+
description: 'Device ID (UUID)',
|
|
20
|
+
required: true,
|
|
21
|
+
}),
|
|
22
|
+
stream: Flags.string({
|
|
23
|
+
char: 's',
|
|
24
|
+
description: 'Stream name',
|
|
25
|
+
required: true,
|
|
26
|
+
}),
|
|
27
|
+
tag: Flags.string({
|
|
28
|
+
char: 't',
|
|
29
|
+
description: 'Tag as key=value where both are strings (can be specified multiple times)',
|
|
30
|
+
multiple: true,
|
|
31
|
+
}),
|
|
32
|
+
timestamp: Flags.string({
|
|
33
|
+
description: 'Unix timestamp in milliseconds (defaults to now)',
|
|
34
|
+
}),
|
|
35
|
+
};
|
|
36
|
+
static summary = 'Ingest numeric data';
|
|
37
|
+
async run() {
|
|
38
|
+
// Parse and validate numeric value
|
|
39
|
+
const numericValue = Number.parseFloat(this.args.value);
|
|
40
|
+
if (Number.isNaN(numericValue)) {
|
|
41
|
+
this.error(`Invalid numeric value: "${this.args.value}". Must be a valid number.`);
|
|
42
|
+
}
|
|
43
|
+
// Parse tags
|
|
44
|
+
const tags = {};
|
|
45
|
+
if (this.flags.tag) {
|
|
46
|
+
for (const tag of this.flags.tag) {
|
|
47
|
+
const [key, ...valueParts] = tag.split('=');
|
|
48
|
+
if (!key || valueParts.length === 0) {
|
|
49
|
+
this.error(`Invalid tag format: "${tag}". Must be key=value.`);
|
|
50
|
+
}
|
|
51
|
+
tags[key] = valueParts.join('=');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// Parse timestamp
|
|
55
|
+
let timestamp = Date.now();
|
|
56
|
+
if (this.flags.timestamp) {
|
|
57
|
+
timestamp = Number.parseInt(this.flags.timestamp, 10);
|
|
58
|
+
if (Number.isNaN(timestamp) || timestamp <= 0) {
|
|
59
|
+
this.error(`Invalid timestamp: "${this.flags.timestamp}". Must be a positive integer.`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// Build request body
|
|
63
|
+
const body = {
|
|
64
|
+
items: [
|
|
65
|
+
{
|
|
66
|
+
deviceId: this.flags.device,
|
|
67
|
+
name: this.flags.stream,
|
|
68
|
+
type: 'numeric',
|
|
69
|
+
tags,
|
|
70
|
+
points: [[timestamp, numericValue]],
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
};
|
|
74
|
+
// Send request (expect 204 No Content)
|
|
75
|
+
await this.api('ingest', 'batch', { body, method: 'POST' });
|
|
76
|
+
if (!this.jsonEnabled()) {
|
|
77
|
+
this.log(`\n✓ Ingested numeric value ${numericValue} to stream "${this.flags.stream}" on device ${this.flags.device} (${this.env})\n`);
|
|
78
|
+
}
|
|
79
|
+
// Return the request body for --json output
|
|
80
|
+
return body;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=numeric.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"numeric.js","sourceRoot":"","sources":["../../../src/commands/ingest/numeric.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command.js';
|
|
2
|
+
export default class IngestText extends BaseCommand<typeof IngestText> {
|
|
3
|
+
static args: {
|
|
4
|
+
value: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
5
|
+
};
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
device: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
stream: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
tag: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
timestamp: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
};
|
|
14
|
+
static summary: string;
|
|
15
|
+
run(): Promise<Record<string, unknown>>;
|
|
16
|
+
}
|