@uns-kit/cli 0.0.2 → 0.0.4
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 +2 -2
- package/package.json +2 -3
- package/templates/default/config.json +3 -1
- package/templates/default/package.json +2 -1
- package/templates/default/src/examples/data-example.ts +50 -0
- package/templates/default/src/examples/load-test-data.ts +90 -0
- package/templates/default/src/examples/table-example.ts +59 -0
package/README.md
CHANGED
|
@@ -6,13 +6,13 @@ Command line scaffolding tool for the UNS toolkit. It bootstraps a new project w
|
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
pnpm --package=@uns-kit/cli dlx uns-kit create my-uns-app
|
|
9
|
+
# or with npx
|
|
10
|
+
npx @uns-kit/cli create my-uns-app
|
|
9
11
|
# or after installing globally
|
|
10
12
|
npm install -g @uns-kit/cli
|
|
11
13
|
uns-kit create my-uns-app
|
|
12
14
|
```
|
|
13
15
|
|
|
14
|
-
> The package exposes both `uns-kit` and `uns` binaries. When using `pnpm dlx`, specify which one to run (`uns-kit` above). If you install globally you can use the shorter `uns create …` alias.
|
|
15
|
-
|
|
16
16
|
The command creates a new directory, copies the starter template, and pins `@uns-kit/core` to the currently published version. After the scaffold finishes:
|
|
17
17
|
|
|
18
18
|
```bash
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uns-kit/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Command line scaffolding tool for UNS applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -11,8 +11,7 @@
|
|
|
11
11
|
"directory": "packages/uns-cli"
|
|
12
12
|
},
|
|
13
13
|
"bin": {
|
|
14
|
-
"uns-kit": "./dist/index.js"
|
|
15
|
-
"uns": "./dist/index.js"
|
|
14
|
+
"uns-kit": "./dist/index.js"
|
|
16
15
|
},
|
|
17
16
|
"keywords": [
|
|
18
17
|
"uns",
|
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
"rest": "http://localhost:3200/api",
|
|
5
5
|
"processName": "__APP_NAME__",
|
|
6
6
|
"instanceMode": "wait",
|
|
7
|
-
"handover": true
|
|
7
|
+
"handover": true,
|
|
8
|
+
"jwksWellKnownUrl": "http://localhost:3200/api/.well-known/jwks.json",
|
|
9
|
+
"kidWellKnownUrl": "http://localhost:3200/api/.well-known/kid"
|
|
8
10
|
},
|
|
9
11
|
"infra": {
|
|
10
12
|
"host": "localhost:1883"
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
"typecheck": "tsc --noEmit",
|
|
7
7
|
"build": "tsc -p tsconfig.json",
|
|
8
8
|
"start": "node ./dist/index.js",
|
|
9
|
-
"dev": "tsx watch src/index.ts"
|
|
9
|
+
"dev": "tsx watch src/index.ts",
|
|
10
|
+
"generate-config-schema": "node ./node_modules/@uns-kit/core/dist/tools/generate-config-schema.js"
|
|
10
11
|
},
|
|
11
12
|
"dependencies": {
|
|
12
13
|
"@uns-kit/core": "__UNS_KIT_CORE_VERSION__"
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Change this file according to your specifications and rename it to index.ts
|
|
3
|
+
*/
|
|
4
|
+
import UnsProxyProcess from "../uns/uns-proxy-process.js";
|
|
5
|
+
import { ConfigFile } from "../config-file.js";
|
|
6
|
+
import logger from "../logger.js";
|
|
7
|
+
import { IUnsMessage } from "../uns/uns-interfaces.js";
|
|
8
|
+
import { PhysicalMeasurements } from "../uns/uns-measurements.js";
|
|
9
|
+
import { UnsPacket } from "../uns/uns-packet.js";
|
|
10
|
+
import { UnsTags } from "../uns/uns-tags.js";
|
|
11
|
+
import { UnsTopics } from "../uns/uns-topics.js";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Load the configuration from a file.
|
|
15
|
+
* On the server, this file is provided by the `uns-datahub-controller`.
|
|
16
|
+
* In the development environment, you are responsible for creating and maintaining this file and its contents.
|
|
17
|
+
*/
|
|
18
|
+
const config = await ConfigFile.loadConfig();
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Connect to input and output brokers
|
|
22
|
+
*/
|
|
23
|
+
const unsProxyProcess = new UnsProxyProcess(config.infra.host, {processName: config.uns.processName});
|
|
24
|
+
const mqttInput = await unsProxyProcess.createUnsMqttProxy(config.input.host, "templateUnsRttInput", config.uns.instanceMode, config.uns.handover, {
|
|
25
|
+
mqttSubToTopics: ["raw/#"],
|
|
26
|
+
});
|
|
27
|
+
const mqttOutput = await unsProxyProcess.createUnsMqttProxy(config.output.host, "templateUnsRttOutput", config.uns.instanceMode, config.uns.handover, { publishThrottlingDelay: 1000});
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Event listener for input events.
|
|
32
|
+
* Transform an input message and publish it with publishMqttMessage function.
|
|
33
|
+
*/
|
|
34
|
+
mqttInput.event.on("input", async (event) => {
|
|
35
|
+
try {
|
|
36
|
+
if (event.topic === "raw/data") {
|
|
37
|
+
const time = UnsPacket.formatToISO8601(new Date());
|
|
38
|
+
const values = event.message.split(",");
|
|
39
|
+
const numberValue: number = parseFloat(values[0]);
|
|
40
|
+
const message: IUnsMessage = { data: { dataGroup:"electricity", time, value: numberValue, uom: PhysicalMeasurements.MiliVolt } };
|
|
41
|
+
const topic: UnsTopics = "sij/";
|
|
42
|
+
const tags: UnsTags[] = [];
|
|
43
|
+
const packet = await UnsPacket.unsPacketFromUnsMessage(message);
|
|
44
|
+
mqttOutput.publishMqttMessage({ topic, attribute: "data-number", packet, description: "Number value", tags });
|
|
45
|
+
}
|
|
46
|
+
} catch (error) {
|
|
47
|
+
logger.error(`Error publishing message to MQTT: ${error.message}`);
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load the configuration from a file.
|
|
3
|
+
* On the server, this file is provided by the `uns-datahub-controller`.
|
|
4
|
+
* In the development environment, you are responsible for creating and maintaining this file and its contents.
|
|
5
|
+
*/
|
|
6
|
+
import readline from "readline";
|
|
7
|
+
import { ConfigFile } from "../config-file.js";
|
|
8
|
+
import UnsMqttProxy from "../uns-mqtt/uns-mqtt-proxy.js";
|
|
9
|
+
import logger from "../logger.js";
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* This script initializes an MQTT output proxy for load testing purposes.
|
|
14
|
+
* It sets up a connection to the specified MQTT broker and configures
|
|
15
|
+
* a proxy instance. The load test is designed to evaluate the performance
|
|
16
|
+
* and reliability of the MQTT broker under simulated load conditions.
|
|
17
|
+
*/
|
|
18
|
+
async function main() {
|
|
19
|
+
try {
|
|
20
|
+
const config = await ConfigFile.loadConfig();
|
|
21
|
+
const mqttOutput = new UnsMqttProxy(
|
|
22
|
+
config.output.host,
|
|
23
|
+
"loadTest",
|
|
24
|
+
"templateUnsRttLoadTest",
|
|
25
|
+
{ publishThrottlingDelay: 0 },
|
|
26
|
+
true
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const rl = readline.createInterface({
|
|
30
|
+
input: process.stdin,
|
|
31
|
+
output: process.stdout,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
35
|
+
|
|
36
|
+
rl.question(`Would you like to continue with load-test on ${config.output.host}? (Y/n) `, async (answer) => {
|
|
37
|
+
if (answer.toLowerCase() === "y" || answer.trim() === "") {
|
|
38
|
+
rl.question("How many iterations should be run? (default is 100) ", async (iterations) => {
|
|
39
|
+
const maxIntervals = parseInt(iterations) || 100;
|
|
40
|
+
|
|
41
|
+
rl.question("What should be the delay between intervals in milliseconds? (default is 0 ms) ", async (intervalDelay) => {
|
|
42
|
+
const delay = parseInt(intervalDelay) || 0;
|
|
43
|
+
|
|
44
|
+
logger.info(`Starting load test with ${maxIntervals} messages and ${delay} ms delay...`);
|
|
45
|
+
|
|
46
|
+
let count = 0;
|
|
47
|
+
const startTime = Date.now();
|
|
48
|
+
|
|
49
|
+
while (count < maxIntervals) {
|
|
50
|
+
try {
|
|
51
|
+
const currentDate = new Date();
|
|
52
|
+
const rawData = `${count},${currentDate.getTime()}`;
|
|
53
|
+
await mqttOutput.publishMessage("raw/data", rawData);
|
|
54
|
+
} catch (error) {
|
|
55
|
+
logger.error("Error publishing message:", error.message);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
count++;
|
|
59
|
+
if (delay > 0) {
|
|
60
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
logger.info(`Sleeping for 50ms.`);
|
|
65
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
66
|
+
|
|
67
|
+
const endTime = Date.now();
|
|
68
|
+
const duration = (endTime - startTime) / 1000;
|
|
69
|
+
const messagesPerSecond = maxIntervals / duration;
|
|
70
|
+
|
|
71
|
+
logger.info(`Load test completed in ${duration.toFixed(2)} seconds.`);
|
|
72
|
+
logger.info(`Message rate: ${messagesPerSecond.toFixed(2)} msg/s.`);
|
|
73
|
+
|
|
74
|
+
rl.close();
|
|
75
|
+
process.exit(0);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
} else {
|
|
79
|
+
logger.info("Load test aborted.");
|
|
80
|
+
rl.close();
|
|
81
|
+
process.exit(0);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
} catch (error) {
|
|
85
|
+
logger.error("Error initializing load test:", error.message);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
main();
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Change this file according to your specifications and rename it to index.ts
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import UnsProxyProcess from "../uns/uns-proxy-process.js";
|
|
6
|
+
import { ConfigFile } from "../config-file.js";
|
|
7
|
+
import logger from "../logger.js";
|
|
8
|
+
import { IUnsMessage } from "../uns/uns-interfaces.js";
|
|
9
|
+
import { UnsPacket } from "../uns/uns-packet.js";
|
|
10
|
+
import { UnsTags } from "../uns/uns-tags.js";
|
|
11
|
+
import { UnsTopics } from "../uns/uns-topics.js";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Load the configuration from a file.
|
|
15
|
+
* On the server, this file is provided by the `uns-datahub-controller`.
|
|
16
|
+
* In the development environment, you are responsible for creating and maintaining this file and its contents.
|
|
17
|
+
*/
|
|
18
|
+
const config = await ConfigFile.loadConfig();
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Load and configure input and output brokers from config.json
|
|
22
|
+
*/
|
|
23
|
+
if (!config.infra?.host || !config.input?.host || !config.output?.host) {
|
|
24
|
+
throw new Error("Missing required configuration in config.json");
|
|
25
|
+
}
|
|
26
|
+
const unsProxyProcess = new UnsProxyProcess(config.infra.host, {processName: config.uns.processName});
|
|
27
|
+
const mqttInput = await unsProxyProcess.createUnsMqttProxy(config.input.host, "templateUnsRttInput", config.uns.instanceMode, config.uns.handover, {
|
|
28
|
+
mqttSubToTopics: ["iba/zrm"],
|
|
29
|
+
publishThrottlingDelay:0,
|
|
30
|
+
subscribeThrottlingDelay:0
|
|
31
|
+
});
|
|
32
|
+
const mqttOutput = await unsProxyProcess.createUnsMqttProxy(config.output.host, "templateUnsRttOutput", config.uns.instanceMode, config.uns.handover, {
|
|
33
|
+
publishThrottlingDelay:0,
|
|
34
|
+
subscribeThrottlingDelay:0
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The input worker connects to the IBA broker and listens for incoming messages.
|
|
39
|
+
* It processes the messages and transforms them into a table-type IUnsMessage.
|
|
40
|
+
* The resulting message is published to the output broker.
|
|
41
|
+
*/
|
|
42
|
+
mqttInput.event.on("input", async (event) => {
|
|
43
|
+
try {
|
|
44
|
+
if (event.topic === "iba/zrm") {
|
|
45
|
+
const jsonObject = JSON.parse(event.message);
|
|
46
|
+
const timestamp = jsonObject.Timestamp;
|
|
47
|
+
delete(jsonObject.Timestamp);
|
|
48
|
+
|
|
49
|
+
const time = UnsPacket.formatToISO8601(new Date(timestamp));
|
|
50
|
+
const message: IUnsMessage = { table: {dataGroup:"iba_test", values:jsonObject, time}};
|
|
51
|
+
const topic: UnsTopics = "sij/acroni/hv/";
|
|
52
|
+
const tags: UnsTags[] = [];
|
|
53
|
+
const packet = await UnsPacket.unsPacketFromUnsMessage(message);
|
|
54
|
+
mqttOutput.publishMqttMessage({ topic, attribute: "zrm", packet, description: "Table", tags });
|
|
55
|
+
}
|
|
56
|
+
} catch (error) {
|
|
57
|
+
logger.error(`Error publishing message to MQTT: ${error.message}`);
|
|
58
|
+
}
|
|
59
|
+
});
|