1 | |
2 |
|
3 | |
4 | * List events |
5 | * List event records (status changes, threshold crossings, uptime resets) in a time window, in chronological order. The time filter uses AKIPS syntax, e.g. last1h, today, "from 2026-01-31 08:00 to 2026-01-31 17:00". AKIPS returns all matches at once; limit/offset page through them. |
6 | */ |
7 | export async function main( |
8 | auth: RT.Akips, |
9 | time_filter: string, |
10 | event_type: "all" | "critical" | "enum" | "threshold" | "uptime" | undefined, |
11 | device: string | undefined, |
12 | child: string | undefined, |
13 | attribute: string | undefined, |
14 | group: string | undefined, |
15 | limit: number | undefined, |
16 | offset: number | undefined |
17 | ) { |
18 | const tf = time_filter.trim() |
19 | const quotedTf = /\s/.test(tf) && !tf.startsWith('"') ? `"${tf}"` : tf |
20 | let cmd = `mget event ${event_type || "all"} time ${quotedTf}` |
21 | if (device || child || attribute) { |
22 | cmd += ` ${device || "*"} ${child || "*"} ${attribute || "*"}` |
23 | } |
24 | if (group) { |
25 | cmd += ` any group ${group}` |
26 | } |
27 |
|
28 | |
29 | if (/[\r\n]/.test(cmd)) throw new Error("api-db command must be a single line") |
30 |
|
31 | |
32 | const url = new URL(`${auth.base_url}/api-db`) |
33 | url.searchParams.append("username", auth.username) |
34 | url.searchParams.append("password", auth.password) |
35 | const response = await fetch(url, { |
36 | method: "POST", |
37 | headers: { "Content-Type": "application/x-www-form-urlencoded" }, |
38 | body: new URLSearchParams({ cmds: cmd }), |
39 | }).catch((e) => { |
40 | |
41 | throw new Error(String(e).replaceAll(url.search, "")) |
42 | }) |
43 | const text = await response.text() |
44 | if (!response.ok || text.startsWith("ERROR:")) { |
45 | throw new Error(`${response.status} ${text}`) |
46 | } |
47 |
|
48 | |
49 | |
50 | const all = [] |
51 | for (const line of text.split("\n")) { |
52 | const match = line.match( |
53 | /^(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*(.*)$/ |
54 | ) |
55 | if (!match) continue |
56 | const [, epoch, parent, childName, attr, type, flags, value, description] = |
57 | match |
58 | all.push({ |
59 | time: new Date(Number(epoch) * 1000).toISOString(), |
60 | epoch: Number(epoch), |
61 | device: parent, |
62 | child: childName, |
63 | attribute: attr, |
64 | type, |
65 | flags: flags.split(","), |
66 | value, |
67 | child_description: description || undefined, |
68 | }) |
69 | } |
70 |
|
71 | const start = offset || 0 |
72 | const size = limit || 500 |
73 | return { |
74 | total: all.length, |
75 | offset: start, |
76 | limit: size, |
77 | next_offset: start + size < all.length ? start + size : null, |
78 | events: all.slice(start, start + size), |
79 | } |
80 | } |
81 |
|