homematic-manager 3.0.0-beta.25 → 3.0.0-beta.26
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/node_modules/@homematic-manager/backend/dist/api/backend.js +87 -26
- package/node_modules/@homematic-manager/backend/dist/rega/scripts.d.ts +19 -7
- package/node_modules/@homematic-manager/backend/dist/rega/scripts.js +30 -8
- package/node_modules/@homematic-manager/backend/package.json +1 -1
- package/node_modules/@homematic-manager/core/dist/api/types.d.ts +7 -0
- package/node_modules/@homematic-manager/core/package.json +1 -1
- package/package.json +3 -3
- package/ui/assets/{index-DEU9sglJ.css → index-CefOsuf7.css} +1 -1
- package/ui/assets/{index-_ilAhuHR.js → index-SByoB-1p.js} +9 -9
- package/ui/index.html +2 -2
|
@@ -99,8 +99,8 @@ export class Backend {
|
|
|
99
99
|
* swallows packets takes 30 s); a store that has not started by then never will.
|
|
100
100
|
*/
|
|
101
101
|
#metaStarting;
|
|
102
|
-
/** Task 36: ReGa's
|
|
103
|
-
#
|
|
102
|
+
/** Task 36, B-74: ReGa's pending alarms per `<interface>|<address>|<datapoint>` - the CCU's own list. */
|
|
103
|
+
#regaAlarms = new Map();
|
|
104
104
|
/** Task 64: `getParamsetId` answers by `<interface>|<address>`; emptied on every connect. */
|
|
105
105
|
#paramsetIds = new Map();
|
|
106
106
|
#serviceMessageTimer;
|
|
@@ -665,7 +665,7 @@ export class Backend {
|
|
|
665
665
|
});
|
|
666
666
|
// B-54: the names are waited for only so long; the store starts after them either way,
|
|
667
667
|
// so its names still land over ReGa's as before (task 27, D-40)
|
|
668
|
-
this.#
|
|
668
|
+
this.#regaAlarms.clear();
|
|
669
669
|
const names = this.#rega.refreshNames().then((changed) => {
|
|
670
670
|
if (changed && this.#manager === manager) {
|
|
671
671
|
this.#caches.saveNames();
|
|
@@ -1085,7 +1085,8 @@ export class Backend {
|
|
|
1085
1085
|
*/
|
|
1086
1086
|
#stickyUnreachMessages() {
|
|
1087
1087
|
const states = this.#manager?.states() ?? [];
|
|
1088
|
-
|
|
1088
|
+
// B-74: with the messages only ReGa lists - the WebUI's "war gestört" the interface forgot
|
|
1089
|
+
return this.#serviceMessages().filter((message) => {
|
|
1089
1090
|
if (message.datapoint !== 'STICKY_UNREACH' || message.value === false) {
|
|
1090
1091
|
return false;
|
|
1091
1092
|
}
|
|
@@ -1102,9 +1103,7 @@ export class Backend {
|
|
|
1102
1103
|
*/
|
|
1103
1104
|
async #acknowledgeExisting(messages) {
|
|
1104
1105
|
for (const message of messages) {
|
|
1105
|
-
const listed = this.#
|
|
1106
|
-
.listServiceMessages(message.interfaceName)
|
|
1107
|
-
.some((entry) => entry.address === message.address && entry.datapoint === message.datapoint);
|
|
1106
|
+
const listed = this.#serviceMessages(message.interfaceName).some((entry) => entry.address === message.address && entry.datapoint === message.datapoint);
|
|
1108
1107
|
if (!listed || this.#stopped) {
|
|
1109
1108
|
continue;
|
|
1110
1109
|
}
|
|
@@ -1432,20 +1431,56 @@ export class Backend {
|
|
|
1432
1431
|
return matrix;
|
|
1433
1432
|
}
|
|
1434
1433
|
#serviceMessages(interfaceName) {
|
|
1435
|
-
return this.#
|
|
1434
|
+
return this.#withRegaAlarms(this.#caches.listServiceMessages(interfaceName), interfaceName);
|
|
1436
1435
|
}
|
|
1437
1436
|
/**
|
|
1438
1437
|
* Task 36: where ReGa knows a message, its first report (the WebUI's *Erste Meldung*) replaces
|
|
1439
1438
|
* the time this application first saw it, and says so.
|
|
1439
|
+
*
|
|
1440
|
+
* B-74 (#150): and a pending alarm whose datapoint the interface process does not list becomes
|
|
1441
|
+
* a row of its own, as the WebUI shows it - value and first report from ReGa, marked as listed
|
|
1442
|
+
* by the CCU only. rfd forgets a `STICKY_UNREACH` at a restart while ReGa keeps the alarm until
|
|
1443
|
+
* it is receipted, so the WebUI had nine messages this list lacked. Only the connection's own
|
|
1444
|
+
* interfaces and the datapoints that are service messages here: an alarm on a system variable
|
|
1445
|
+
* or a CUxD datapoint stays the WebUI's.
|
|
1440
1446
|
*/
|
|
1441
|
-
#
|
|
1442
|
-
if (this.#
|
|
1447
|
+
#withRegaAlarms(messages, interfaceName) {
|
|
1448
|
+
if (this.#regaAlarms.size === 0) {
|
|
1443
1449
|
return messages;
|
|
1444
1450
|
}
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1451
|
+
const listed = new Set();
|
|
1452
|
+
const result = messages.map((message) => {
|
|
1453
|
+
const key = `${message.interfaceName}|${message.address}|${message.datapoint}`;
|
|
1454
|
+
listed.add(key);
|
|
1455
|
+
const alarm = this.#regaAlarms.get(key);
|
|
1456
|
+
return alarm === undefined ? message : { ...message, since: alarm.first, sinceSource: 'rega' };
|
|
1448
1457
|
});
|
|
1458
|
+
const known = new Set(this.#manager?.names() ?? []);
|
|
1459
|
+
for (const [key, alarm] of this.#regaAlarms) {
|
|
1460
|
+
if (listed.has(key) ||
|
|
1461
|
+
!known.has(alarm.interfaceName) ||
|
|
1462
|
+
(interfaceName !== undefined && alarm.interfaceName !== interfaceName) ||
|
|
1463
|
+
!countsAsServiceMessage(alarm.datapoint, alarm.value)) {
|
|
1464
|
+
continue;
|
|
1465
|
+
}
|
|
1466
|
+
result.push({
|
|
1467
|
+
interfaceName: alarm.interfaceName,
|
|
1468
|
+
address: alarm.address,
|
|
1469
|
+
datapoint: alarm.datapoint,
|
|
1470
|
+
value: alarm.value,
|
|
1471
|
+
since: alarm.first,
|
|
1472
|
+
sinceSource: 'rega',
|
|
1473
|
+
source: 'rega',
|
|
1474
|
+
});
|
|
1475
|
+
}
|
|
1476
|
+
return result;
|
|
1477
|
+
}
|
|
1478
|
+
/** B-74: is this message one only ReGa lists - a pending alarm without the interface's datapoint? */
|
|
1479
|
+
#isRegaOnly(interfaceName, address, datapoint) {
|
|
1480
|
+
return (this.#regaAlarms.has(`${interfaceName}|${address}|${datapoint}`) &&
|
|
1481
|
+
!this.#caches
|
|
1482
|
+
.listServiceMessages(interfaceName)
|
|
1483
|
+
.some((message) => message.address === address && message.datapoint === datapoint));
|
|
1449
1484
|
}
|
|
1450
1485
|
/**
|
|
1451
1486
|
* Task 36: reads ReGa's pending service messages (one short script, read-only) and keeps their
|
|
@@ -1457,8 +1492,8 @@ export class Backend {
|
|
|
1457
1492
|
async #refreshRegaAlarms() {
|
|
1458
1493
|
const rega = this.#rega;
|
|
1459
1494
|
if (!rega?.state.enabled) {
|
|
1460
|
-
if (this.#
|
|
1461
|
-
this.#
|
|
1495
|
+
if (this.#regaAlarms.size > 0) {
|
|
1496
|
+
this.#regaAlarms.clear();
|
|
1462
1497
|
this.events.emit('serviceMessages.changed', this.#serviceMessages());
|
|
1463
1498
|
}
|
|
1464
1499
|
return;
|
|
@@ -1467,12 +1502,15 @@ export class Backend {
|
|
|
1467
1502
|
if (alarms === undefined || this.#rega !== rega) {
|
|
1468
1503
|
return;
|
|
1469
1504
|
}
|
|
1470
|
-
const next = new Map(alarms.map((alarm) => [`${alarm.interfaceName}|${alarm.address}|${alarm.datapoint}`, alarm
|
|
1471
|
-
const changed = next.size !== this.#
|
|
1472
|
-
[...next].some(([key,
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1505
|
+
const next = new Map(alarms.map((alarm) => [`${alarm.interfaceName}|${alarm.address}|${alarm.datapoint}`, alarm]));
|
|
1506
|
+
const changed = next.size !== this.#regaAlarms.size ||
|
|
1507
|
+
[...next].some(([key, alarm]) => {
|
|
1508
|
+
const before = this.#regaAlarms.get(key);
|
|
1509
|
+
return before === undefined || before.first !== alarm.first || before.value !== alarm.value;
|
|
1510
|
+
});
|
|
1511
|
+
this.#regaAlarms.clear();
|
|
1512
|
+
for (const [key, alarm] of next) {
|
|
1513
|
+
this.#regaAlarms.set(key, alarm);
|
|
1476
1514
|
}
|
|
1477
1515
|
if (changed) {
|
|
1478
1516
|
this.events.emit('serviceMessages.changed', this.#serviceMessages());
|
|
@@ -1705,21 +1743,44 @@ export class Backend {
|
|
|
1705
1743
|
if (!isAcknowledgeable(datapoint)) {
|
|
1706
1744
|
throw validationError(`${datapoint} cannot be acknowledged`);
|
|
1707
1745
|
}
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1746
|
+
// B-74: a message only ReGa lists has no flag left to clear on the interface; the write is
|
|
1747
|
+
// still sent (rfd takes a `false` for a flag it does not hold), but its failure - a device
|
|
1748
|
+
// the interface no longer knows, say - must not keep the alarm standing in the WebUI
|
|
1749
|
+
const regaOnly = this.#isRegaOnly(interfaceName, address, datapoint);
|
|
1750
|
+
try {
|
|
1751
|
+
const description = await this.#describe(interfaceName, address, 'VALUES');
|
|
1752
|
+
const parameter = description[datapoint];
|
|
1753
|
+
const value = parameter?.TYPE === 'ACTION';
|
|
1754
|
+
await this.#writer.setValue(interfaceName, address, datapoint, value);
|
|
1755
|
+
}
|
|
1756
|
+
catch (error) {
|
|
1757
|
+
if (!regaOnly) {
|
|
1758
|
+
throw error;
|
|
1759
|
+
}
|
|
1760
|
+
this.#notice('info', `${address}: ${datapoint} is listed by the CCU only; the interface did not take the write (${errorMessage(error)}), the alarm is receipted in ReGa`, interfaceName);
|
|
1761
|
+
}
|
|
1712
1762
|
if (this.#caches.serviceMessages.clear(interfaceName, address, datapoint)) {
|
|
1713
1763
|
this.events.emit('serviceMessages.changed', this.#serviceMessages());
|
|
1714
1764
|
}
|
|
1715
1765
|
// Issue #94: the datapoint write above is the acknowledgement that matters, and it happened
|
|
1716
1766
|
// whether ReGa exists or not. This clears the CCU's own alarm on top, so the WebUI stops
|
|
1717
1767
|
// showing a message the user has already dealt with here. D-2: silent when ReGa is off.
|
|
1718
|
-
|
|
1768
|
+
// B-74: for a message only ReGa lists the receipt *is* the acknowledgement, so it is waited
|
|
1769
|
+
// for, and the row goes with the list that follows it.
|
|
1770
|
+
const receipt = (this.#rega?.acknowledgeAlarm(interfaceName, address, datapoint) ?? Promise.resolve(false)).then(async (receipted) => {
|
|
1719
1771
|
if (receipted) {
|
|
1720
1772
|
await this.#refreshRegaAlarms();
|
|
1721
1773
|
}
|
|
1774
|
+
else if (regaOnly) {
|
|
1775
|
+
this.#notice('warn', `${address}: ${datapoint} is listed by the CCU only, and ReGa did not receipt it`, interfaceName);
|
|
1776
|
+
}
|
|
1722
1777
|
});
|
|
1778
|
+
if (regaOnly) {
|
|
1779
|
+
await receipt;
|
|
1780
|
+
}
|
|
1781
|
+
else {
|
|
1782
|
+
void receipt;
|
|
1783
|
+
}
|
|
1723
1784
|
return null;
|
|
1724
1785
|
}
|
|
1725
1786
|
#recentEvents(interfaceName, limit) {
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
* the interface process, or is a convenience; a system without ReGa loses nothing but the CCU-side
|
|
21
21
|
* bookkeeping.
|
|
22
22
|
*/
|
|
23
|
+
import type { ParamsetValue } from '@homematic-manager/core';
|
|
23
24
|
/** Escapes a string for the ReGa string literal it is written into. */
|
|
24
25
|
export declare function escapeRegaString(value: string): string;
|
|
25
26
|
/** One entry of a rename: the ReGa object id and the name it should carry. */
|
|
@@ -72,24 +73,35 @@ export declare function parseConfirmedDevices(output: string): ConfirmedDevice[]
|
|
|
72
73
|
*/
|
|
73
74
|
export declare function acknowledgeAlarmScript(interfaceName: string, address: string, datapoint: string): string | undefined;
|
|
74
75
|
/**
|
|
75
|
-
* Task 36: the CCU's pending service messages with their times, as the WebUI's
|
|
76
|
-
*
|
|
77
|
-
*
|
|
76
|
+
* Task 36, B-74: the CCU's pending service messages with their times and values, as the WebUI's
|
|
77
|
+
* service-message page lists them: every `OT_ALARMDP` of `ID_SERVICES` that is `Used()`,
|
|
78
|
+
* `Enabled()` and `asOncoming` (`serviceMessages.htm` of OpenCCU 3.89.8), one line per alarm with
|
|
79
|
+
* the trigger datapoint's name, `AlOccurrenceTime()` (the WebUI's *Erste Meldung*), `Timestamp()`
|
|
78
80
|
* (*Letzte Meldung*), both as Unix seconds (`ToInteger()`, checked against `date +%s` on the lab's
|
|
79
|
-
* OpenCCU)
|
|
81
|
+
* OpenCCU), and the trigger's `Value()` - ReGa's own last value of the datapoint, which is what
|
|
82
|
+
* the WebUI shows for the message (`true`/`false`, an ENUM as its index). Read-only.
|
|
83
|
+
*
|
|
84
|
+
* B-74 (#150): an alarm stays oncoming until it is receipted, whatever the interface process
|
|
85
|
+
* reports meanwhile - rfd forgets a `STICKY_UNREACH` at a restart, ReGa does not - so the
|
|
86
|
+
* WebUI lists messages `getServiceMessages` does not. The value is what such a message is shown
|
|
87
|
+
* with.
|
|
80
88
|
*/
|
|
81
|
-
export declare const REGA_ALARMS_SCRIPT = "string sId;\nforeach (sId, dom.GetObject(ID_SERVICES).EnumIDs()) {\n object oAlarm = dom.GetObject(sId);\n if (oAlarm) {\n if (oAlarm.IsTypeOf(OT_ALARMDP) && (oAlarm.AlState() == asOncoming)) {\n object oTrigger = dom.GetObject(oAlarm.AlTriggerDP());\n if (oTrigger) {\n Write(oTrigger.Name() # \"\\t\" # oAlarm.AlOccurrenceTime().ToInteger() # \"\\t\" # oAlarm.Timestamp().ToInteger() # \"\\n\");\n }\n }\n }\n}\n";
|
|
82
|
-
/** One pending ReGa service message: whose datapoint, first and last reported (epoch ms). */
|
|
89
|
+
export declare const REGA_ALARMS_SCRIPT = "string sId;\nforeach (sId, dom.GetObject(ID_SERVICES).EnumIDs()) {\n object oAlarm = dom.GetObject(sId);\n if (oAlarm) {\n if (oAlarm.IsTypeOf(OT_ALARMDP) && (oAlarm.Used() == true) && (oAlarm.Enabled() == true) && (oAlarm.AlState() == asOncoming)) {\n object oTrigger = dom.GetObject(oAlarm.AlTriggerDP());\n if (oTrigger) {\n Write(oTrigger.Name() # \"\\t\" # oAlarm.AlOccurrenceTime().ToInteger() # \"\\t\" # oAlarm.Timestamp().ToInteger() # \"\\t\" # oTrigger.Value() # \"\\n\");\n }\n }\n }\n}\n";
|
|
90
|
+
/** One pending ReGa service message: whose datapoint, its value, first and last reported (epoch ms). */
|
|
83
91
|
export interface RegaAlarm {
|
|
84
92
|
readonly interfaceName: string;
|
|
85
93
|
readonly address: string;
|
|
86
94
|
readonly datapoint: string;
|
|
95
|
+
/** ReGa's last value of the trigger datapoint; `true` when the line carries none (older script). */
|
|
96
|
+
readonly value: ParamsetValue;
|
|
87
97
|
readonly first: number;
|
|
88
98
|
readonly last: number;
|
|
89
99
|
}
|
|
90
100
|
/**
|
|
91
101
|
* Reads what {@link REGA_ALARMS_SCRIPT} wrote. A line whose name is not `<interface>.<channel>.<datapoint>`
|
|
92
|
-
* (a system alarm, a CUxD name with more dots) or whose time is no positive number is skipped.
|
|
102
|
+
* (a system alarm, a CUxD name with more dots) or whose time is no positive number is skipped. The
|
|
103
|
+
* value column is ReGa's text of the value: `true`/`false`, a number as it prints it (an ENUM by
|
|
104
|
+
* its index), anything else stays a string; a line without it means `true`.
|
|
93
105
|
*/
|
|
94
106
|
export declare function parseRegaAlarms(output: string): RegaAlarm[];
|
|
95
107
|
/**
|
|
@@ -124,20 +124,27 @@ Write(iDone);
|
|
|
124
124
|
`;
|
|
125
125
|
}
|
|
126
126
|
/**
|
|
127
|
-
* Task 36: the CCU's pending service messages with their times, as the WebUI's
|
|
128
|
-
*
|
|
129
|
-
*
|
|
127
|
+
* Task 36, B-74: the CCU's pending service messages with their times and values, as the WebUI's
|
|
128
|
+
* service-message page lists them: every `OT_ALARMDP` of `ID_SERVICES` that is `Used()`,
|
|
129
|
+
* `Enabled()` and `asOncoming` (`serviceMessages.htm` of OpenCCU 3.89.8), one line per alarm with
|
|
130
|
+
* the trigger datapoint's name, `AlOccurrenceTime()` (the WebUI's *Erste Meldung*), `Timestamp()`
|
|
130
131
|
* (*Letzte Meldung*), both as Unix seconds (`ToInteger()`, checked against `date +%s` on the lab's
|
|
131
|
-
* OpenCCU)
|
|
132
|
+
* OpenCCU), and the trigger's `Value()` - ReGa's own last value of the datapoint, which is what
|
|
133
|
+
* the WebUI shows for the message (`true`/`false`, an ENUM as its index). Read-only.
|
|
134
|
+
*
|
|
135
|
+
* B-74 (#150): an alarm stays oncoming until it is receipted, whatever the interface process
|
|
136
|
+
* reports meanwhile - rfd forgets a `STICKY_UNREACH` at a restart, ReGa does not - so the
|
|
137
|
+
* WebUI lists messages `getServiceMessages` does not. The value is what such a message is shown
|
|
138
|
+
* with.
|
|
132
139
|
*/
|
|
133
140
|
export const REGA_ALARMS_SCRIPT = `string sId;
|
|
134
141
|
foreach (sId, dom.GetObject(ID_SERVICES).EnumIDs()) {
|
|
135
142
|
object oAlarm = dom.GetObject(sId);
|
|
136
143
|
if (oAlarm) {
|
|
137
|
-
if (oAlarm.IsTypeOf(OT_ALARMDP) && (oAlarm.AlState() == asOncoming)) {
|
|
144
|
+
if (oAlarm.IsTypeOf(OT_ALARMDP) && (oAlarm.Used() == true) && (oAlarm.Enabled() == true) && (oAlarm.AlState() == asOncoming)) {
|
|
138
145
|
object oTrigger = dom.GetObject(oAlarm.AlTriggerDP());
|
|
139
146
|
if (oTrigger) {
|
|
140
|
-
Write(oTrigger.Name() # "\\t" # oAlarm.AlOccurrenceTime().ToInteger() # "\\t" # oAlarm.Timestamp().ToInteger() # "\\n");
|
|
147
|
+
Write(oTrigger.Name() # "\\t" # oAlarm.AlOccurrenceTime().ToInteger() # "\\t" # oAlarm.Timestamp().ToInteger() # "\\t" # oTrigger.Value() # "\\n");
|
|
141
148
|
}
|
|
142
149
|
}
|
|
143
150
|
}
|
|
@@ -145,12 +152,14 @@ foreach (sId, dom.GetObject(ID_SERVICES).EnumIDs()) {
|
|
|
145
152
|
`;
|
|
146
153
|
/**
|
|
147
154
|
* Reads what {@link REGA_ALARMS_SCRIPT} wrote. A line whose name is not `<interface>.<channel>.<datapoint>`
|
|
148
|
-
* (a system alarm, a CUxD name with more dots) or whose time is no positive number is skipped.
|
|
155
|
+
* (a system alarm, a CUxD name with more dots) or whose time is no positive number is skipped. The
|
|
156
|
+
* value column is ReGa's text of the value: `true`/`false`, a number as it prints it (an ENUM by
|
|
157
|
+
* its index), anything else stays a string; a line without it means `true`.
|
|
149
158
|
*/
|
|
150
159
|
export function parseRegaAlarms(output) {
|
|
151
160
|
const alarms = [];
|
|
152
161
|
for (const line of output.split('\n')) {
|
|
153
|
-
const [name, first, last] = line.split('\t');
|
|
162
|
+
const [name, first, last, value] = line.split('\t');
|
|
154
163
|
const match = /^([^.\s]+)\.([^.\s]+)\.([^.\s]+)$/u.exec(name?.trim() ?? '');
|
|
155
164
|
const firstSeconds = Number(first);
|
|
156
165
|
const lastSeconds = Number(last);
|
|
@@ -161,12 +170,25 @@ export function parseRegaAlarms(output) {
|
|
|
161
170
|
interfaceName: match[1] ?? '',
|
|
162
171
|
address: match[2] ?? '',
|
|
163
172
|
datapoint: match[3] ?? '',
|
|
173
|
+
value: parseRegaValue(value),
|
|
164
174
|
first: firstSeconds * 1000,
|
|
165
175
|
last: Number.isFinite(lastSeconds) && lastSeconds > 0 ? lastSeconds * 1000 : firstSeconds * 1000,
|
|
166
176
|
});
|
|
167
177
|
}
|
|
168
178
|
return alarms;
|
|
169
179
|
}
|
|
180
|
+
/** ReGa's text of a datapoint value, as `Write(oDP.Value())` prints it. */
|
|
181
|
+
function parseRegaValue(text) {
|
|
182
|
+
const trimmed = text?.trim() ?? '';
|
|
183
|
+
if (trimmed === '' || trimmed === 'true') {
|
|
184
|
+
return true;
|
|
185
|
+
}
|
|
186
|
+
if (trimmed === 'false') {
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
const number = Number(trimmed);
|
|
190
|
+
return Number.isFinite(number) ? number : trimmed;
|
|
191
|
+
}
|
|
170
192
|
/**
|
|
171
193
|
* Is this safe to put inside a ReGa string literal *unescaped*?
|
|
172
194
|
*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@homematic-manager/backend",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.26",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Homematic Manager backend: XML-RPC/BIN-RPC clients and callback servers, caches, optional ReGa",
|
|
6
6
|
"license": "AGPL-3.0-or-later",
|
|
@@ -589,6 +589,13 @@ export interface ServiceMessage {
|
|
|
589
589
|
* WebUI's *Erste Meldung*); absent when it is when this application first saw it.
|
|
590
590
|
*/
|
|
591
591
|
sinceSource?: 'rega';
|
|
592
|
+
/**
|
|
593
|
+
* B-74 (#150): `rega` when only the CCU's ReGa lists this message - its alarm is pending while
|
|
594
|
+
* the interface process no longer reports the datapoint (rfd forgets a `STICKY_UNREACH` at a
|
|
595
|
+
* restart, ReGa keeps the alarm until it is receipted). The WebUI shows such a message; so does
|
|
596
|
+
* this list. Absent when the interface reports it.
|
|
597
|
+
*/
|
|
598
|
+
source?: 'rega';
|
|
592
599
|
}
|
|
593
600
|
export interface EventRecord {
|
|
594
601
|
/** Milliseconds since epoch. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homematic-manager",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.26",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Configure and administer Homematic and HomematicIP devices - devices and channels, direct links, paramsets, RSSI, service messages, events and an RPC console - from a local HTTP/WebSocket server that also serves the web UI",
|
|
6
6
|
"keywords": [
|
|
@@ -67,8 +67,8 @@
|
|
|
67
67
|
"hm-simulator": "^1.0.0"
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@homematic-manager/backend": "3.0.0-beta.
|
|
71
|
-
"@homematic-manager/core": "3.0.0-beta.
|
|
70
|
+
"@homematic-manager/backend": "3.0.0-beta.26",
|
|
71
|
+
"@homematic-manager/core": "3.0.0-beta.26",
|
|
72
72
|
"binrpc": "^4.2.0",
|
|
73
73
|
"homematic-rega": "^2.0.0",
|
|
74
74
|
"homematic-xmlrpc": "^2.0.0",
|