knx.ts 1.0.2 → 1.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/LICENSE +51 -21
- package/README.md +274 -61
- package/dist/@types/interfaces/connection.d.ts +80 -13
- package/dist/@types/interfaces/servers.d.ts +18 -0
- package/dist/@types/interfaces/servers.js +2 -0
- package/dist/connection/KNXService.d.ts +13 -30
- package/dist/connection/KNXService.js +4 -164
- package/dist/connection/KNXTunneling.d.ts +4 -4
- package/dist/connection/KNXTunneling.js +35 -62
- package/dist/connection/KNXUSBConnection.d.ts +20 -0
- package/dist/connection/KNXUSBConnection.js +358 -0
- package/dist/connection/KNXnetIPServer.d.ts +29 -12
- package/dist/connection/KNXnetIPServer.js +261 -83
- package/dist/connection/Router.d.ts +52 -32
- package/dist/connection/Router.js +225 -153
- package/dist/connection/TPUART.d.ts +8 -3
- package/dist/connection/TPUART.js +41 -37
- package/dist/connection/TunnelConnection.d.ts +3 -1
- package/dist/connection/TunnelConnection.js +6 -4
- package/dist/core/CEMI.d.ts +7 -2
- package/dist/core/CEMI.js +5 -8
- package/dist/core/EMI.d.ts +312 -200
- package/dist/core/EMI.js +511 -1007
- package/dist/core/KNXnetIPStructures.d.ts +10 -1
- package/dist/core/KNXnetIPStructures.js +15 -10
- package/dist/core/MessageCodeField.d.ts +1 -1
- package/dist/core/cache/GroupAddressCache.d.ts +57 -0
- package/dist/core/cache/GroupAddressCache.js +227 -0
- package/dist/core/data/KNXDataDecode.d.ts +2 -2
- package/dist/core/data/KNXDataDecode.js +198 -183
- package/dist/core/enum/EnumControlField.d.ts +0 -5
- package/dist/core/enum/EnumControlField.js +1 -7
- package/dist/core/enum/EnumControlFieldExtended.d.ts +1 -1
- package/dist/core/enum/EnumShortACKFrame.d.ts +1 -1
- package/dist/core/enum/ErrorCodeSet.js +59 -0
- package/dist/core/enum/KNXnetIPEnum.d.ts +2 -2
- package/dist/core/enum/KNXnetIPEnum.js +19 -1
- package/dist/core/layers/data/NPDU.d.ts +2 -1
- package/dist/core/layers/data/NPDU.js +6 -3
- package/dist/index.d.ts +19 -2
- package/dist/index.js +36 -1
- package/dist/server/KNXMQTTGateway.d.ts +13 -0
- package/dist/server/KNXMQTTGateway.js +164 -0
- package/dist/server/KNXWebSocketServer.d.ts +12 -0
- package/dist/server/KNXWebSocketServer.js +118 -0
- package/dist/utils/CEMIAdapter.d.ts +4 -3
- package/dist/utils/CEMIAdapter.js +26 -30
- package/dist/utils/Logger.d.ts +4 -4
- package/dist/utils/Logger.js +3 -7
- package/package.json +27 -7
|
@@ -55,6 +55,10 @@ export declare abstract class DIB {
|
|
|
55
55
|
}
|
|
56
56
|
export declare class DeviceInformationDIB extends DIB {
|
|
57
57
|
knxMedium: KNXMedium;
|
|
58
|
+
/**
|
|
59
|
+
* 1 = Device is programmed
|
|
60
|
+
* 0 = Device is not programmed
|
|
61
|
+
*/
|
|
58
62
|
deviceStatus: 1 | 0 | number;
|
|
59
63
|
individualAddress: number;
|
|
60
64
|
projectInstallationId: number;
|
|
@@ -62,7 +66,12 @@ export declare class DeviceInformationDIB extends DIB {
|
|
|
62
66
|
routingMulticastAddress: string;
|
|
63
67
|
macAddress: string;
|
|
64
68
|
friendlyName: string;
|
|
65
|
-
constructor(knxMedium: KNXMedium,
|
|
69
|
+
constructor(knxMedium: KNXMedium,
|
|
70
|
+
/**
|
|
71
|
+
* 1 = Device is programmed
|
|
72
|
+
* 0 = Device is not programmed
|
|
73
|
+
*/
|
|
74
|
+
deviceStatus: 1 | 0 | number, individualAddress: number, projectInstallationId: number, serialNumber: Buffer, routingMulticastAddress: string, macAddress: string, friendlyName: string);
|
|
66
75
|
toBuffer(): Buffer;
|
|
67
76
|
static fromBuffer(buffer: Buffer): DeviceInformationDIB;
|
|
68
77
|
}
|
|
@@ -20,10 +20,7 @@ class HPAI {
|
|
|
20
20
|
return this._hostProtocol;
|
|
21
21
|
}
|
|
22
22
|
set port(port) {
|
|
23
|
-
if (isNaN(port) ||
|
|
24
|
-
typeof port !== 'number' ||
|
|
25
|
-
port < 0 ||
|
|
26
|
-
port > 65535) {
|
|
23
|
+
if (isNaN(port) || typeof port !== "number" || port < 0 || port > 65535) {
|
|
27
24
|
throw new Error(`Invalid port ${port}`);
|
|
28
25
|
}
|
|
29
26
|
this._port = port;
|
|
@@ -33,7 +30,7 @@ class HPAI {
|
|
|
33
30
|
}
|
|
34
31
|
set ipAddress(host) {
|
|
35
32
|
if (host == null) {
|
|
36
|
-
throw new Error(
|
|
33
|
+
throw new Error("Host undefined");
|
|
37
34
|
}
|
|
38
35
|
const m = host.match(/(\d+)\.(\d+)\.(\d+)\.(\d+)/);
|
|
39
36
|
if (m === null) {
|
|
@@ -233,7 +230,12 @@ class DeviceInformationDIB extends DIB {
|
|
|
233
230
|
routingMulticastAddress;
|
|
234
231
|
macAddress;
|
|
235
232
|
friendlyName;
|
|
236
|
-
constructor(knxMedium,
|
|
233
|
+
constructor(knxMedium,
|
|
234
|
+
/**
|
|
235
|
+
* 1 = Device is programmed
|
|
236
|
+
* 0 = Device is not programmed
|
|
237
|
+
*/
|
|
238
|
+
deviceStatus, individualAddress, projectInstallationId, serialNumber, routingMulticastAddress, macAddress, friendlyName) {
|
|
237
239
|
super(KNXnetIPEnum_2.DescriptionType.DEVICE_INFO);
|
|
238
240
|
this.knxMedium = knxMedium;
|
|
239
241
|
this.deviceStatus = deviceStatus;
|
|
@@ -259,6 +261,7 @@ class DeviceInformationDIB extends DIB {
|
|
|
259
261
|
buffer.writeUInt8(mcast[1], 15);
|
|
260
262
|
buffer.writeUInt8(mcast[2], 16);
|
|
261
263
|
buffer.writeUInt8(mcast[3], 17);
|
|
264
|
+
// eslint-disable-next-line no-useless-escape
|
|
262
265
|
const mac = this.macAddress.replace(/[:\-]/g, "");
|
|
263
266
|
Buffer.from(mac, "hex").copy(buffer, 18);
|
|
264
267
|
nameBuf.copy(buffer, 24, 0);
|
|
@@ -367,7 +370,7 @@ class IPCurrentConfigDIB extends DIB {
|
|
|
367
370
|
exports.IPCurrentConfigDIB = IPCurrentConfigDIB;
|
|
368
371
|
class StatusTunnelingSlot {
|
|
369
372
|
_value;
|
|
370
|
-
constructor(initialValue =
|
|
373
|
+
constructor(initialValue = 0xfff8) {
|
|
371
374
|
this._value = initialValue;
|
|
372
375
|
}
|
|
373
376
|
get value() {
|
|
@@ -435,7 +438,7 @@ class TunnellingInfoDIB extends DIB {
|
|
|
435
438
|
for (let i = 4; i < buffer.length; i += 4) {
|
|
436
439
|
slots.push({
|
|
437
440
|
address: buffer.readUInt16BE(i),
|
|
438
|
-
status: new StatusTunnelingSlot(buffer.readUInt16BE(i + 2))
|
|
441
|
+
status: new StatusTunnelingSlot(buffer.readUInt16BE(i + 2)),
|
|
439
442
|
});
|
|
440
443
|
}
|
|
441
444
|
return new TunnellingInfoDIB(apduLength, slots);
|
|
@@ -589,7 +592,9 @@ class UnknownDIB extends DIB {
|
|
|
589
592
|
super(type);
|
|
590
593
|
this.rawData = rawData;
|
|
591
594
|
}
|
|
592
|
-
toBuffer() {
|
|
595
|
+
toBuffer() {
|
|
596
|
+
return this.rawData;
|
|
597
|
+
}
|
|
593
598
|
}
|
|
594
599
|
exports.UnknownDIB = UnknownDIB;
|
|
595
600
|
class SRP {
|
|
@@ -616,7 +621,7 @@ class SRP {
|
|
|
616
621
|
const len = buffer.readUInt8(0);
|
|
617
622
|
const type = buffer.readUInt8(1);
|
|
618
623
|
const data = buffer.subarray(2, len);
|
|
619
|
-
return new SRP(type &
|
|
624
|
+
return new SRP(type & 0x7f, data, (type & 0x80) !== 0);
|
|
620
625
|
}
|
|
621
626
|
}
|
|
622
627
|
exports.SRP = SRP;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The default destination is the layer where the system shall direct the message to if no redirection is set.
|
|
3
3
|
*/
|
|
4
|
-
declare enum DefaultDestination {
|
|
4
|
+
declare const enum DefaultDestination {
|
|
5
5
|
Data_Link_Layer = "DLL",
|
|
6
6
|
Network_Layer = "NL",
|
|
7
7
|
Transport_Layer = "TL",
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { CEMIInstance } from "../CEMI";
|
|
2
|
+
import { KNXService } from "../../connection/KNXService";
|
|
3
|
+
export interface CacheEntry {
|
|
4
|
+
cemi: CEMIInstance;
|
|
5
|
+
timestamp: Date;
|
|
6
|
+
groupAddress: string;
|
|
7
|
+
decodedValue?: any;
|
|
8
|
+
}
|
|
9
|
+
export declare class GroupAddressCache {
|
|
10
|
+
private static instance;
|
|
11
|
+
private enabled;
|
|
12
|
+
/**
|
|
13
|
+
* Maximum number of group addresses to cache. Default is 65535 (all possible group addresses).
|
|
14
|
+
*/
|
|
15
|
+
private maxAddresses;
|
|
16
|
+
/**
|
|
17
|
+
* Maximum number of messages to cache per group address. Default is 10.
|
|
18
|
+
*/
|
|
19
|
+
private maxMessagesPerAddress;
|
|
20
|
+
private cache;
|
|
21
|
+
private dptConfig;
|
|
22
|
+
private constructor();
|
|
23
|
+
static getInstance(): GroupAddressCache;
|
|
24
|
+
setEnabled(enabled: boolean): void;
|
|
25
|
+
isEnabled(): boolean;
|
|
26
|
+
configure(maxAddresses: number, maxMessagesPerAddress?: number): void;
|
|
27
|
+
setAddressDPT(address: string, dpt: string | number): void;
|
|
28
|
+
getAddressDPT(address: string): string | number | undefined;
|
|
29
|
+
encodeValue(address: string, value: any): Buffer | null;
|
|
30
|
+
/**
|
|
31
|
+
* Processes an incoming CEMI message. If caching is enabled, saves the last messages
|
|
32
|
+
* indicating a GroupValue_Read or GroupValue_Response targeted to a Group Address.
|
|
33
|
+
*/
|
|
34
|
+
processCEMI(cemi: CEMIInstance): void;
|
|
35
|
+
/**
|
|
36
|
+
* Clears the entire cache map.
|
|
37
|
+
*/
|
|
38
|
+
clear(): void;
|
|
39
|
+
/**
|
|
40
|
+
* Deletes a specific address from the cache.
|
|
41
|
+
* @param address KNX Group Address e.g. '1/2/3'
|
|
42
|
+
*/
|
|
43
|
+
deleteAddress(address: string): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Core query method to retrieve messages for given address(es) within a time range.
|
|
46
|
+
* If dates aren't specified, retrieves all currently cached items depending on the query payload.
|
|
47
|
+
* By default, it retrieves the absolute latest if neither startDate nor endDate are applied.
|
|
48
|
+
*/
|
|
49
|
+
query(addresses: string | string[], startDate?: Date, endDate?: Date, returnOnlyLatest?: boolean): CacheEntry[];
|
|
50
|
+
/**
|
|
51
|
+
* Prompts the KNXService to issue an A_GroupValue_Read to the bus on the specified address
|
|
52
|
+
* and awaits an A_GroupValue_Response. The response is automatically processed via standard
|
|
53
|
+
* listeners (if processCEMI is hooked properly), but this method attaches an event
|
|
54
|
+
* one-off listener or handles resolving it.
|
|
55
|
+
*/
|
|
56
|
+
readDirectAsync(address: string, serviceContext: KNXService, timeoutMs?: number): Promise<CacheEntry | null>;
|
|
57
|
+
}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GroupAddressCache = void 0;
|
|
4
|
+
const APCIEnum_1 = require("../enum/APCIEnum");
|
|
5
|
+
const KNXDataDecode_1 = require("../data/KNXDataDecode");
|
|
6
|
+
const KNXDataEncode_1 = require("../data/KNXDataEncode");
|
|
7
|
+
class GroupAddressCache {
|
|
8
|
+
static instance;
|
|
9
|
+
enabled = false;
|
|
10
|
+
/**
|
|
11
|
+
* Maximum number of group addresses to cache. Default is 65535 (all possible group addresses).
|
|
12
|
+
*/
|
|
13
|
+
maxAddresses = 65535;
|
|
14
|
+
/**
|
|
15
|
+
* Maximum number of messages to cache per group address. Default is 10.
|
|
16
|
+
*/
|
|
17
|
+
maxMessagesPerAddress = 10;
|
|
18
|
+
cache = new Map();
|
|
19
|
+
dptConfig = new Map();
|
|
20
|
+
constructor() { }
|
|
21
|
+
static getInstance() {
|
|
22
|
+
if (!GroupAddressCache.instance) {
|
|
23
|
+
GroupAddressCache.instance = new GroupAddressCache();
|
|
24
|
+
}
|
|
25
|
+
return GroupAddressCache.instance;
|
|
26
|
+
}
|
|
27
|
+
setEnabled(enabled) {
|
|
28
|
+
this.enabled = enabled;
|
|
29
|
+
}
|
|
30
|
+
isEnabled() {
|
|
31
|
+
return this.enabled;
|
|
32
|
+
}
|
|
33
|
+
configure(maxAddresses, maxMessagesPerAddress = 10) {
|
|
34
|
+
this.maxAddresses = maxAddresses;
|
|
35
|
+
this.maxMessagesPerAddress = maxMessagesPerAddress;
|
|
36
|
+
}
|
|
37
|
+
setAddressDPT(address, dpt) {
|
|
38
|
+
this.dptConfig.set(address, dpt);
|
|
39
|
+
}
|
|
40
|
+
getAddressDPT(address) {
|
|
41
|
+
return this.dptConfig.get(address);
|
|
42
|
+
}
|
|
43
|
+
encodeValue(address, value) {
|
|
44
|
+
const dpt = this.dptConfig.get(address);
|
|
45
|
+
if (!dpt)
|
|
46
|
+
return null;
|
|
47
|
+
try {
|
|
48
|
+
return KNXDataEncode_1.KnxDataEncoder.encodeThis(dpt, value);
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Processes an incoming CEMI message. If caching is enabled, saves the last messages
|
|
57
|
+
* indicating a GroupValue_Read or GroupValue_Response targeted to a Group Address.
|
|
58
|
+
*/
|
|
59
|
+
processCEMI(cemi) {
|
|
60
|
+
if (!("controlField2" in cemi) || !("TPDU" in cemi))
|
|
61
|
+
return;
|
|
62
|
+
if (!this.enabled)
|
|
63
|
+
return;
|
|
64
|
+
if (cemi.controlField2?.addressType !== 1) {
|
|
65
|
+
return; // Not a group address
|
|
66
|
+
}
|
|
67
|
+
const apciObj = cemi.TPDU.apdu.apci;
|
|
68
|
+
if (!apciObj)
|
|
69
|
+
return;
|
|
70
|
+
const apci = apciObj;
|
|
71
|
+
if (apci.value !== APCIEnum_1.APCIEnum.A_GroupValue_Read_Protocol_Data_Unit &&
|
|
72
|
+
apci.value !== APCIEnum_1.APCIEnum.A_GroupValue_Response_Protocol_Data_Unit) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const targetAddress = cemi.destinationAddress;
|
|
76
|
+
if (!targetAddress)
|
|
77
|
+
return;
|
|
78
|
+
// Initialize list if needed
|
|
79
|
+
if (!this.cache.has(targetAddress)) {
|
|
80
|
+
if (this.cache.size >= this.maxAddresses) {
|
|
81
|
+
// Enforce max addresses limit (naive approach: evict oldest entry by insertion order)
|
|
82
|
+
const firstKey = this.cache.keys().next().value;
|
|
83
|
+
if (firstKey !== undefined) {
|
|
84
|
+
this.cache.delete(firstKey);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
this.cache.set(targetAddress, []);
|
|
88
|
+
}
|
|
89
|
+
const entries = this.cache.get(targetAddress);
|
|
90
|
+
let decodedValue = undefined;
|
|
91
|
+
const dpt = this.dptConfig.get(targetAddress);
|
|
92
|
+
if (dpt && cemi.TPDU.apdu.data) {
|
|
93
|
+
try {
|
|
94
|
+
decodedValue = KNXDataDecode_1.KnxDataDecode.decodeThis(dpt, cemi.TPDU.apdu.data);
|
|
95
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
// failed to decode
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Create new entry
|
|
102
|
+
const entry = {
|
|
103
|
+
cemi: cemi,
|
|
104
|
+
timestamp: new Date(),
|
|
105
|
+
groupAddress: targetAddress,
|
|
106
|
+
decodedValue: decodedValue,
|
|
107
|
+
};
|
|
108
|
+
// Insert at front
|
|
109
|
+
entries.unshift(entry);
|
|
110
|
+
// Trim length
|
|
111
|
+
if (entries.length > this.maxMessagesPerAddress) {
|
|
112
|
+
entries.length = this.maxMessagesPerAddress;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Clears the entire cache map.
|
|
117
|
+
*/
|
|
118
|
+
clear() {
|
|
119
|
+
this.cache.clear();
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Deletes a specific address from the cache.
|
|
123
|
+
* @param address KNX Group Address e.g. '1/2/3'
|
|
124
|
+
*/
|
|
125
|
+
deleteAddress(address) {
|
|
126
|
+
return this.cache.delete(address);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Core query method to retrieve messages for given address(es) within a time range.
|
|
130
|
+
* If dates aren't specified, retrieves all currently cached items depending on the query payload.
|
|
131
|
+
* By default, it retrieves the absolute latest if neither startDate nor endDate are applied.
|
|
132
|
+
*/
|
|
133
|
+
query(addresses, startDate, endDate = new Date(), returnOnlyLatest = true) {
|
|
134
|
+
const addressArray = Array.isArray(addresses) ? addresses : [addresses];
|
|
135
|
+
const results = [];
|
|
136
|
+
for (const address of addressArray) {
|
|
137
|
+
const entries = this.cache.get(address) || [];
|
|
138
|
+
if (entries.length === 0)
|
|
139
|
+
continue;
|
|
140
|
+
if (!startDate) {
|
|
141
|
+
// If no start date, we return the very latest (index 0) if default or requested
|
|
142
|
+
if (returnOnlyLatest) {
|
|
143
|
+
results.push(entries[0]);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
// Or return everything relative to the endDate
|
|
147
|
+
results.push(...entries.filter((e) => e.timestamp <= endDate));
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
// Filter by date range
|
|
152
|
+
const validEntries = entries.filter((e) => e.timestamp >= startDate && e.timestamp <= endDate);
|
|
153
|
+
if (returnOnlyLatest && validEntries.length > 0) {
|
|
154
|
+
results.push(validEntries[0]);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
results.push(...validEntries);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return results;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Prompts the KNXService to issue an A_GroupValue_Read to the bus on the specified address
|
|
165
|
+
* and awaits an A_GroupValue_Response. The response is automatically processed via standard
|
|
166
|
+
* listeners (if processCEMI is hooked properly), but this method attaches an event
|
|
167
|
+
* one-off listener or handles resolving it.
|
|
168
|
+
*/
|
|
169
|
+
async readDirectAsync(address, serviceContext, timeoutMs = 3000) {
|
|
170
|
+
return new Promise((resolve, reject) => {
|
|
171
|
+
// eslint-disable-next-line prefer-const
|
|
172
|
+
let timer;
|
|
173
|
+
// Listener context reference to intercept indications specifically for this read call
|
|
174
|
+
const listener = (cemi) => {
|
|
175
|
+
if (cemi.controlField2?.addressType === 1 && cemi.destinationAddress === address) {
|
|
176
|
+
const apciObj = cemi.TPDU.apdu.apci;
|
|
177
|
+
if (apciObj && apciObj.value === APCIEnum_1.APCIEnum.A_GroupValue_Response_Protocol_Data_Unit) {
|
|
178
|
+
// Clean up
|
|
179
|
+
clearTimeout(timer);
|
|
180
|
+
serviceContext.off("indication", listener);
|
|
181
|
+
// Ensure caching happens if not processed previously (if processCEMI wasn't hooked at higher layer for some reason)
|
|
182
|
+
this.processCEMI(cemi);
|
|
183
|
+
// Find in cache
|
|
184
|
+
const entries = this.cache.get(address);
|
|
185
|
+
if (entries && entries.length > 0 && entries[0].cemi === cemi) {
|
|
186
|
+
resolve(entries[0]);
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
// Return mock CacheEntry if cache processing was disabled or failed
|
|
190
|
+
let decodedValue = undefined;
|
|
191
|
+
const dpt = this.dptConfig.get(address);
|
|
192
|
+
if (dpt && cemi.TPDU.apdu.data) {
|
|
193
|
+
try {
|
|
194
|
+
decodedValue = KNXDataDecode_1.KnxDataDecode.decodeThis(dpt, cemi.TPDU.apdu.data);
|
|
195
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
196
|
+
}
|
|
197
|
+
catch (e) {
|
|
198
|
+
// empty
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
resolve({
|
|
202
|
+
cemi: cemi,
|
|
203
|
+
timestamp: new Date(),
|
|
204
|
+
groupAddress: address,
|
|
205
|
+
decodedValue: decodedValue,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
// Set explicit listener on the service context
|
|
212
|
+
serviceContext.on("indication", listener);
|
|
213
|
+
// Start the timer to abort request
|
|
214
|
+
timer = setTimeout(() => {
|
|
215
|
+
serviceContext.off("indication", listener);
|
|
216
|
+
reject(new Error(`Timeout of ${timeoutMs}ms exceeded while waiting for GroupValue_Response on ${address}`));
|
|
217
|
+
}, timeoutMs);
|
|
218
|
+
// Issue the command to the bus
|
|
219
|
+
serviceContext.read(address).catch((err) => {
|
|
220
|
+
clearTimeout(timer);
|
|
221
|
+
serviceContext.off("indication", listener);
|
|
222
|
+
reject(err);
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
exports.GroupAddressCache = GroupAddressCache;
|
|
@@ -5,7 +5,7 @@ import { KNXData } from "./KNXData";
|
|
|
5
5
|
*/
|
|
6
6
|
export declare class KnxDataDecode extends KNXData {
|
|
7
7
|
private constructor();
|
|
8
|
-
static decodeThis<T extends typeof KnxDataDecode.dptEnum[number] | string>(dpt: T, buffer: Buffer): DecodedDPTType<T>;
|
|
8
|
+
static decodeThis<T extends (typeof KnxDataDecode.dptEnum)[number] | string>(dpt: T, buffer: Buffer): DecodedDPTType<T>;
|
|
9
9
|
static get dptEnum(): readonly [1, 2, 3007, 3008, 4001, 4002, 5, 5001, 5002, 6, 6001, 6010, 6020, 7, 7001, 7002, 7003, 7004, 7005, 7006, 7007, 7011, 7012, 7013, 8, 9, 10001, 11001, 12001, 12002, 13, 13001, 13002, 13010, 13011, 13012, 13013, 13014, 13015, 13016, 13100, 14, 15000, 16, 16002, 20, 20001, 20002, 20003, 20004, 20005, 20006, 20007, 20008, 20011, 20012, 20013, 20014, 20017, 20020, 20021, 20022, 27001, 28001, 29, 29010, 29011, 29012, 232600, 238600, 245600, 250600, 251600];
|
|
10
10
|
private static toPercentage;
|
|
11
11
|
private static toAngle;
|
|
@@ -187,7 +187,7 @@ export declare class KnxDataDecode extends KNXData {
|
|
|
187
187
|
*
|
|
188
188
|
* @returns Un objeto con el valor sin signo y la unidad seleccionada.
|
|
189
189
|
*/
|
|
190
|
-
static asDpt12002(buffer: Buffer, variant?:
|
|
190
|
+
static asDpt12002(buffer: Buffer, variant?: "sec" | "min" | "hrs"): {
|
|
191
191
|
value: number;
|
|
192
192
|
unit: string;
|
|
193
193
|
};
|