node-red-contrib-knx-ultimate 2.3.4 → 2.4.1
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/.github/ISSUE_TEMPLATE/bug_report.md +7 -7
- package/CHANGELOG.md +29 -0
- package/KNXEngine/CHANGELOG.md +5 -1
- package/KNXEngine/package.json +1 -1
- package/KNXEngine/src/dptlib/dpt275.js +60 -0
- package/KNXEngine/src/dptlib/index.js +79 -65
- package/nodes/commonFunctions.js +419 -0
- package/nodes/hue-config.html +56 -40
- package/nodes/hue-config.js +0 -108
- package/nodes/knxUltimate-config.html +1 -1
- package/nodes/knxUltimate-config.js +13 -232
- package/nodes/knxUltimate.html +2 -2
- package/nodes/knxUltimateHueBattery.html +2 -2
- package/nodes/knxUltimateHueButton.html +4 -4
- package/nodes/knxUltimateHueLight.html +989 -947
- package/nodes/knxUltimateHueLight.js +50 -26
- package/nodes/knxUltimateHueLightSensor.html +2 -2
- package/nodes/knxUltimateHueMotion.html +2 -2
- package/nodes/knxUltimateHueScene.html +4 -4
- package/nodes/knxUltimateHueTapDial.html +2 -2
- package/nodes/knxUltimateHueTemperatureSensor.html +2 -2
- package/nodes/knxUltimateLoadControl.html +1 -1
- package/nodes/knxUltimateSceneController.html +6 -6
- package/nodes/knxUltimateSceneController.js +1 -9
- package/package.json +2 -2
- package/nodes/utils/commonFunctions.js +0 -21
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: Bug report
|
|
3
|
-
about:
|
|
3
|
+
about: Signal a bug
|
|
4
4
|
title: ''
|
|
5
5
|
labels: ''
|
|
6
6
|
assignees: Supergiovane
|
|
@@ -10,26 +10,26 @@ assignees: Supergiovane
|
|
|
10
10
|
**Salutation (i'll not respond to users that doesn’t wrote at least "Hello")**
|
|
11
11
|
|
|
12
12
|
**Describe the bug**
|
|
13
|
-
|
|
13
|
+
Write here a clear and concise description of what the bug is.
|
|
14
14
|
|
|
15
15
|
**To Reproduce**
|
|
16
|
-
|
|
16
|
+
Write here the steps to reproduce the behavior, for example:
|
|
17
17
|
1. Go to '...'
|
|
18
18
|
2. Click on '....'
|
|
19
19
|
3. Scroll down to '....'
|
|
20
20
|
4. See error
|
|
21
21
|
|
|
22
22
|
**Expected behavior**
|
|
23
|
-
|
|
23
|
+
Write here a clear and concise description of what you expected to happen.
|
|
24
24
|
|
|
25
25
|
**Screenshots**
|
|
26
|
-
|
|
26
|
+
Here, if applicable, add screenshots to help explain your problem.
|
|
27
27
|
|
|
28
28
|
**Knx-Ultimate Version**
|
|
29
|
-
- Eg.
|
|
29
|
+
- Eg. 2.3.5
|
|
30
30
|
|
|
31
31
|
**Are you running node-red behind homematic, docker or anything similar?**
|
|
32
32
|
- Eg. Node-Red running alone in RaspberryPi
|
|
33
33
|
|
|
34
34
|
**Additional context**
|
|
35
|
-
|
|
35
|
+
Write here any other context about the problem here.
|
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,35 @@
|
|
|
6
6
|
|
|
7
7
|
# CHANGELOG
|
|
8
8
|
|
|
9
|
+
**Version 2.4.1** - Jan 2024<br/>
|
|
10
|
+
- NEW: Added KNX Datapoint 275.100<br/>
|
|
11
|
+
- HUE Light: fixed https://github.com/Supergiovane/node-red-contrib-knx-ultimate/issues/317<br/>
|
|
12
|
+
- HUE Light: corrected the 7.600 kelvin range https://github.com/Supergiovane/node-red-contrib-knx-ultimate/issues/316<br/>
|
|
13
|
+
- HUE Light: blinking effect and color cyle are now stopped, whenever an FALSE KNX telegram is received by the light switching group address.<br/>
|
|
14
|
+
- HUE Light: when the light is off, the dim up sequence starts now with initial brightness = zero.<br/>
|
|
15
|
+
- KNX Engine: moved all HTTP calls to a single js file, loaded at startup, to avoid multi KNX gateway or multi HUE bridges issues.<br/>
|
|
16
|
+
- Minor fixes.<br/>
|
|
17
|
+
|
|
18
|
+
**Version 2.4.0-beta.1** - Jan 2024<br/>
|
|
19
|
+
- This is a public installable beta.<br/>
|
|
20
|
+
- HUE Light: fixed https://github.com/Supergiovane/node-red-contrib-knx-ultimate/issues/317<br/>
|
|
21
|
+
- HUE Light: corrected the 7.600 kelvin range https://github.com/Supergiovane/node-red-contrib-knx-ultimate/issues/316<br/>
|
|
22
|
+
- HUE Light: blinking effect and color cyle are now stopped, whenever an FALSE KNX telegram is received by the light switching group address.<br/>
|
|
23
|
+
- HUE Light: when the light is off, the dim up sequence starts now with initial brightness = zero.<br/>
|
|
24
|
+
- KNX Engine: moved all HTTP calls to a single js file, loaded at startup, to avoid multi KNX gateway or multi HUE bridges issues.<br/>
|
|
25
|
+
- Minor fixes.<br/>
|
|
26
|
+
|
|
27
|
+
**Version 2.4.0-beta.0** - Jan 2024<br/>
|
|
28
|
+
- THIS IS A BETA VERSION. INSTALL ONLY IF YOU HAVE MANY HUE BRIDGES.<br/>
|
|
29
|
+
- HUE Light: fixed https://github.com/Supergiovane/node-red-contrib-knx-ultimate/issues/317<br/>
|
|
30
|
+
- HUE Light: corrected the 7.600 kelvin range https://github.com/Supergiovane/node-red-contrib-knx-ultimate/issues/316<br/>
|
|
31
|
+
- HUE Light: blinking effect and color cyle are now stopped, whenever an FALSE KNX telegram is received by the light switching group address.<br/>
|
|
32
|
+
- HUE Light: when the light is off, the dim up sequence starts now with initial brightness = zero.<br/>
|
|
33
|
+
- KNX Engine: moved all HTTP calls to a single js file, loaded at startup, to avoid multi KNX gateway or multi HUE bridges issues.<br/>
|
|
34
|
+
|
|
35
|
+
**Version 2.3.5** - Jan 2024<br/>
|
|
36
|
+
- HUE Light: fixed multi HUE Bridge GUI issue.<br/>
|
|
37
|
+
|
|
9
38
|
**Version 2.3.4** - Jan 2024<br/>
|
|
10
39
|
- HUE Light: fixex tab "DIM/Brightness" inaccessible, when "KNX Brightness Status" was set to use the default knx behaviour.<br/>
|
|
11
40
|
|
package/KNXEngine/CHANGELOG.md
CHANGED
|
@@ -7,7 +7,11 @@
|
|
|
7
7
|
# CHANGELOG
|
|
8
8
|
|
|
9
9
|
<p>
|
|
10
|
-
<b>Version 1.0.
|
|
10
|
+
<b>Version 1.0.46</b> - January 2024<br/>
|
|
11
|
+
- NEW: added DPT 275.100.<br/>
|
|
12
|
+
</p>
|
|
13
|
+
<p>
|
|
14
|
+
<b>Version 1.0.44</b> - December 2023<br/>
|
|
11
15
|
- Fixed DPT 9.001 issue when sending numberso having > 2 decimals.<br/>
|
|
12
16
|
</p>
|
|
13
17
|
<p>
|
package/KNXEngine/package.json
CHANGED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/* eslint-disable no-prototype-builtins */
|
|
2
|
+
/**
|
|
3
|
+
* KNXEngine - a KNX protocol stack in Javascript
|
|
4
|
+
* (C) 2020-2024 Supergiovane
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const knxLog = require("../KnxLog");
|
|
8
|
+
const dpt9 = require("./dpt9");
|
|
9
|
+
|
|
10
|
+
//
|
|
11
|
+
// 4x DPT9.* 2-byte floating point value
|
|
12
|
+
//
|
|
13
|
+
|
|
14
|
+
exports.formatAPDU = function (value) {
|
|
15
|
+
// Get the javascript object and create a telegram for the KNX bus.
|
|
16
|
+
if (typeof value === 'object' && value.hasOwnProperty('comfort') && value.hasOwnProperty('standby') && value.hasOwnProperty('economy') && value.hasOwnProperty('buildingProtection')) {
|
|
17
|
+
const comfort = dpt9.formatAPDU(value.comfort);
|
|
18
|
+
const standby = dpt9.formatAPDU(value.standby);
|
|
19
|
+
const economy = dpt9.formatAPDU(value.economy);
|
|
20
|
+
const buildingProtection = dpt9.formatAPDU(value.buildingProtection);
|
|
21
|
+
return Buffer.concat([comfort, standby, economy, buildingProtection]);
|
|
22
|
+
} else {
|
|
23
|
+
knxLog.get().error('DPT275.formatAPDU: Must supply all values, for example {comfort:22, standby:21.5, economy:21, buildingProtection:15}');
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
exports.fromBuffer = function (buf) {
|
|
28
|
+
// Get the telegram from the KNX bus and create a javascript object.
|
|
29
|
+
if (buf.length !== 8) {
|
|
30
|
+
knxLog.get().warn('DPT275.fromBuffer: buf should be 8 bytes long (got %d bytes)', buf.length);
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const comfort = dpt9.fromBuffer(buf.slice(0, 2));
|
|
34
|
+
const standby = dpt9.fromBuffer(buf.slice(2, 4));
|
|
35
|
+
const economy = dpt9.fromBuffer(buf.slice(4, 6));
|
|
36
|
+
const buildingProtection = dpt9.fromBuffer(buf.slice(6, 8));
|
|
37
|
+
return { comfort: comfort, standby: standby, economy: economy, buildingProtection: buildingProtection };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// DPT275 basetype info
|
|
41
|
+
exports.basetype = {
|
|
42
|
+
bitlength: 64,
|
|
43
|
+
valuetype: 'basic',
|
|
44
|
+
desc: 'Quadruple setpoints (comfort,standby,economy,buildingProtection) (4 float with 16 Bit)',
|
|
45
|
+
help:
|
|
46
|
+
`// Send comfort, standby, economy mode and buildingProtection temperatures, as n.4 DPT9.001.
|
|
47
|
+
msg.payload = {comfort:22, standby:21.5, economy:21, buildingProtection:15};
|
|
48
|
+
return msg;`
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// DPT9 subtypes
|
|
52
|
+
exports.subtypes = {
|
|
53
|
+
// 9.001 temperature (oC)
|
|
54
|
+
'100': {
|
|
55
|
+
name: 'Quadruple setpoints (comfort,standby,economy,buildingProtection) (4 float with 16 Bit)',
|
|
56
|
+
desc: 'DPT_TempRoomSetpSetF16[4]',
|
|
57
|
+
unit: '°C',
|
|
58
|
+
range: [-273, 670760]
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -3,24 +3,24 @@
|
|
|
3
3
|
* (C) 2020-2022 Supergiovane
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const fs = require('fs')
|
|
7
|
-
const path = require('path')
|
|
8
|
-
const util = require('util')
|
|
9
|
-
const knxLog = require(
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const util = require('util');
|
|
9
|
+
const knxLog = require("../KnxLog");
|
|
10
10
|
|
|
11
|
-
let matches
|
|
12
|
-
const dirEntries = fs.readdirSync(__dirname)
|
|
13
|
-
const dpts = {}
|
|
11
|
+
let matches;
|
|
12
|
+
const dirEntries = fs.readdirSync(__dirname);
|
|
13
|
+
const dpts = {};
|
|
14
14
|
for (let i = 0; i < dirEntries.length; i++) {
|
|
15
15
|
if (matches = dirEntries[i].match(/(dpt.*)\.js/)) {
|
|
16
|
-
const dptid = matches[1].toUpperCase() // DPT1..DPTxxx
|
|
17
|
-
const mod = require(__dirname + path.sep + dirEntries[i])
|
|
18
|
-
if (!mod.hasOwnProperty('basetype')
|
|
19
|
-
!mod.basetype.hasOwnProperty('bitlength')) {
|
|
20
|
-
throw
|
|
16
|
+
const dptid = matches[1].toUpperCase(); // DPT1..DPTxxx
|
|
17
|
+
const mod = require(__dirname + path.sep + dirEntries[i]);
|
|
18
|
+
if (!mod.hasOwnProperty('basetype')
|
|
19
|
+
|| !mod.basetype.hasOwnProperty('bitlength')) {
|
|
20
|
+
throw `incomplete ${dptid}, missing basetype and/or bitlength!`;
|
|
21
21
|
}
|
|
22
|
-
mod.id = dptid
|
|
23
|
-
dpts[dptid] = mod
|
|
22
|
+
mod.id = dptid;
|
|
23
|
+
dpts[dptid] = mod;
|
|
24
24
|
// knxLog.get().trace('DPT library: loaded %s (%s)', dptid, dpts[dptid].basetype.desc);
|
|
25
25
|
}
|
|
26
26
|
}
|
|
@@ -28,20 +28,20 @@ for (let i = 0; i < dirEntries.length; i++) {
|
|
|
28
28
|
// a generic DPT resolution function
|
|
29
29
|
// DPTs might come in as 9/"9"/"9.001"/"DPT9.001"
|
|
30
30
|
dpts.resolve = function (dptid) {
|
|
31
|
-
const m = dptid.toString().toUpperCase().match(/^(?:DPT)?(\d+)(\.(\d+))?$/)
|
|
32
|
-
if (m === null) { throw new Error(
|
|
31
|
+
const m = dptid.toString().toUpperCase().match(/^(?:DPT)?(\d+)(\.(\d+))?$/);
|
|
32
|
+
if (m === null) { throw new Error(`Invalid DPT format: ${dptid}`); }
|
|
33
33
|
|
|
34
|
-
const dpt = dpts[util.format('DPT%s', m[1])]
|
|
35
|
-
if (!dpt) { throw new Error(
|
|
34
|
+
const dpt = dpts[util.format('DPT%s', m[1])];
|
|
35
|
+
if (!dpt) { throw new Error(`Unsupported DPT: ${dptid}`); }
|
|
36
36
|
|
|
37
|
-
const cloned_dpt = cloneDpt(dpt)
|
|
37
|
+
const cloned_dpt = cloneDpt(dpt);
|
|
38
38
|
if (m[3]) {
|
|
39
|
-
cloned_dpt.subtypeid = m[3]
|
|
40
|
-
cloned_dpt.subtype = cloned_dpt.subtypes[m[3]]
|
|
39
|
+
cloned_dpt.subtypeid = m[3];
|
|
40
|
+
cloned_dpt.subtype = cloned_dpt.subtypes[m[3]];
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
return cloned_dpt
|
|
44
|
-
}
|
|
43
|
+
return cloned_dpt;
|
|
44
|
+
};
|
|
45
45
|
|
|
46
46
|
/* POPULATE an APDU object from a given Javascript value for the given DPT
|
|
47
47
|
* - either by a custom DPT formatAPDU function
|
|
@@ -51,59 +51,72 @@ dpts.resolve = function (dptid) {
|
|
|
51
51
|
*/
|
|
52
52
|
dpts.populateAPDU = function (value, apdu, dptid) {
|
|
53
53
|
// console.log ("BANANA " + dptid)
|
|
54
|
-
const dpt = dpts.resolve(dptid || 'DPT1')
|
|
55
|
-
const nbytes = Math.ceil(dpt.basetype.bitlength / 8)
|
|
54
|
+
const dpt = dpts.resolve(dptid || 'DPT1');
|
|
55
|
+
const nbytes = Math.ceil(dpt.basetype.bitlength / 8);
|
|
56
56
|
// apdu.data = new Buffer(nbytes); // 14/09/2020 Supregiovane: Deprecated. Replaced with below.
|
|
57
|
-
apdu.data = Buffer.alloc(nbytes)
|
|
58
|
-
apdu.bitlength = dpt.basetype && dpt.basetype.bitlength || 1
|
|
59
|
-
let tgtvalue = value
|
|
57
|
+
apdu.data = Buffer.alloc(nbytes);
|
|
58
|
+
apdu.bitlength = dpt.basetype && dpt.basetype.bitlength || 1;
|
|
59
|
+
let tgtvalue = value;
|
|
60
60
|
// get the raw APDU data for the given JS value
|
|
61
61
|
if (typeof dpt.formatAPDU === 'function') {
|
|
62
62
|
// nothing to do here, DPT-specific formatAPDU implementation will handle everything
|
|
63
63
|
// knxLog.get().trace('>>> custom formatAPDU(%s): %j', dptid, value);
|
|
64
|
-
apdu.data = dpt.formatAPDU(value)
|
|
64
|
+
apdu.data = dpt.formatAPDU(value);
|
|
65
65
|
// knxLog.get().trace('<<< custom formatAPDU(%s): %j', dptid, apdu.data);
|
|
66
66
|
} else {
|
|
67
67
|
if (!isFinite(value)) {
|
|
68
|
-
throw new Error(util.format(
|
|
69
|
-
|
|
68
|
+
throw new Error(util.format(
|
|
69
|
+
'Invalid value, expected a %s',
|
|
70
|
+
dpt.desc,
|
|
71
|
+
));
|
|
70
72
|
}
|
|
71
73
|
// check if value is in range, be it explicitly defined or implied from bitlength
|
|
72
74
|
const range = (dpt.basetype.hasOwnProperty('range'))
|
|
73
75
|
? dpt.basetype.range
|
|
74
|
-
: [0,
|
|
76
|
+
: [0, 2 ** dpt.basetype.bitlength - 1];
|
|
75
77
|
// is there a scalar range? eg. DPT5.003 angle degrees (0=0, ff=360)
|
|
76
78
|
if (dpt.hasOwnProperty('subtype') && dpt.subtype.hasOwnProperty(
|
|
77
|
-
'scalar_range'
|
|
78
|
-
|
|
79
|
+
'scalar_range',
|
|
80
|
+
)) {
|
|
81
|
+
const scalar = dpt.subtype.scalar_range;
|
|
79
82
|
if (value < scalar[0] || value > scalar[1]) {
|
|
80
83
|
knxLog.get().trace(
|
|
81
84
|
'Value %j(%s) out of scalar range(%j) for %s',
|
|
82
|
-
value, (
|
|
85
|
+
value, (
|
|
86
|
+
typeof value),
|
|
87
|
+
scalar,
|
|
88
|
+
dpt.id,
|
|
89
|
+
);
|
|
83
90
|
} else {
|
|
84
91
|
// convert value from its scalar representation
|
|
85
92
|
// e.g. in DPT5.001, 50(%) => 0x7F , 100(%) => 0xFF
|
|
86
|
-
const a = (scalar[1] - scalar[0]) / (range[1] - range[0])
|
|
87
|
-
const b = (scalar[0] - range[0])
|
|
88
|
-
tgtvalue = Math.round((value - b) / a)
|
|
93
|
+
const a = (scalar[1] - scalar[0]) / (range[1] - range[0]);
|
|
94
|
+
const b = (scalar[0] - range[0]);
|
|
95
|
+
tgtvalue = Math.round((value - b) / a);
|
|
89
96
|
}
|
|
90
97
|
} else {
|
|
91
98
|
// just a plain numeric value, only check if within bounds
|
|
92
99
|
if (value < range[0] || value > range[1]) {
|
|
93
|
-
knxLog.get().trace(
|
|
94
|
-
|
|
100
|
+
knxLog.get().trace(
|
|
101
|
+
'Value %j(%s) out of bounds(%j) for %s.%s',
|
|
102
|
+
value, (
|
|
103
|
+
typeof value),
|
|
104
|
+
range,
|
|
105
|
+
dpt.id,
|
|
106
|
+
dpt.subtypeid,
|
|
107
|
+
);
|
|
95
108
|
}
|
|
96
109
|
}
|
|
97
110
|
// generic APDU is assumed to convey an unsigned integer of arbitrary bitlength
|
|
98
111
|
if (dpt.basetype.hasOwnProperty('signedness') && dpt.basetype.signedness === 'signed') {
|
|
99
|
-
apdu.data.writeIntBE(tgtvalue, 0, nbytes)
|
|
112
|
+
apdu.data.writeIntBE(tgtvalue, 0, nbytes);
|
|
100
113
|
} else {
|
|
101
|
-
apdu.data.writeUIntBE(tgtvalue, 0, nbytes)
|
|
114
|
+
apdu.data.writeUIntBE(tgtvalue, 0, nbytes);
|
|
102
115
|
}
|
|
103
116
|
}
|
|
104
117
|
// knxLog.get().trace('generic populateAPDU tgtvalue=%j(%s) nbytes=%d => apdu=%j', tgtvalue, typeof tgtvalue, nbytes, apdu);
|
|
105
|
-
return apdu
|
|
106
|
-
}
|
|
118
|
+
return apdu;
|
|
119
|
+
};
|
|
107
120
|
|
|
108
121
|
/* get the correct Javascript value from a APDU buffer for the given DPT
|
|
109
122
|
* - either by a custom DPT formatAPDU function
|
|
@@ -112,48 +125,49 @@ dpts.populateAPDU = function (value, apdu, dptid) {
|
|
|
112
125
|
*/
|
|
113
126
|
dpts.fromBuffer = function (buf, dpt) {
|
|
114
127
|
// sanity check
|
|
115
|
-
if (!dpt) throw util.format('DPT %s not found', dpt)
|
|
116
|
-
let value = 0
|
|
128
|
+
if (!dpt) throw util.format('DPT %s not found', dpt);
|
|
129
|
+
let value = 0;
|
|
117
130
|
// get the raw APDU data for the given JS value
|
|
118
131
|
if (typeof dpt.fromBuffer === 'function') {
|
|
119
132
|
// nothing to do here, DPT-specific fromBuffer implementation will handle everything
|
|
120
|
-
value = dpt.fromBuffer(buf)
|
|
133
|
+
value = dpt.fromBuffer(buf);
|
|
121
134
|
} else {
|
|
122
135
|
// knxLog.get().trace('%s buflength == %d => %j', typeof buf, buf.length, JSON.stringify(buf) );
|
|
123
136
|
// get a raw unsigned integer from the buffer
|
|
124
137
|
if (buf.length > 6) {
|
|
125
|
-
throw 'cannot handle unsigned integers more then 6 bytes in length'
|
|
138
|
+
throw 'cannot handle unsigned integers more then 6 bytes in length';
|
|
126
139
|
}
|
|
127
140
|
if (dpt.basetype.hasOwnProperty('signedness') && dpt.basetype.signedness == 'signed') {
|
|
128
|
-
value = buf.readIntBE(0, buf.length)
|
|
141
|
+
value = buf.readIntBE(0, buf.length);
|
|
129
142
|
} else {
|
|
130
|
-
value = buf.readUIntBE(0, buf.length)
|
|
143
|
+
value = buf.readUIntBE(0, buf.length);
|
|
131
144
|
}
|
|
132
145
|
// knxLog.get().trace(' ../knx/src/index.js : DPT : ' + JSON.stringify(dpt)); // for exploring dpt and implementing description
|
|
133
146
|
if (dpt.hasOwnProperty('subtype') && dpt.subtype.hasOwnProperty(
|
|
134
|
-
'scalar_range'
|
|
147
|
+
'scalar_range',
|
|
148
|
+
)) {
|
|
135
149
|
const range = (dpt.basetype.hasOwnProperty('range'))
|
|
136
150
|
? dpt.basetype.range
|
|
137
|
-
: [0,
|
|
138
|
-
const scalar = dpt.subtype.scalar_range
|
|
151
|
+
: [0, 2 ** dpt.basetype.bitlength - 1];
|
|
152
|
+
const scalar = dpt.subtype.scalar_range;
|
|
139
153
|
// convert value from its scalar representation
|
|
140
154
|
// e.g. in DPT5.001, 50(%) => 0x7F , 100(%) => 0xFF
|
|
141
|
-
const a = (scalar[1] - scalar[0]) / (range[1] - range[0])
|
|
142
|
-
const b = (scalar[0] - range[0])
|
|
143
|
-
value = Math.round(a * value + b)
|
|
155
|
+
const a = (scalar[1] - scalar[0]) / (range[1] - range[0]);
|
|
156
|
+
const b = (scalar[0] - range[0]);
|
|
157
|
+
value = Math.round(a * value + b);
|
|
144
158
|
// knxLog.get().trace('fromBuffer scalar a=%j b=%j %j', a,b, value);
|
|
145
159
|
}
|
|
146
160
|
}
|
|
147
161
|
// knxLog.get().trace('generic fromBuffer buf=%j, value=%j', buf, value);
|
|
148
|
-
return value
|
|
149
|
-
}
|
|
162
|
+
return value;
|
|
163
|
+
};
|
|
150
164
|
|
|
151
|
-
function cloneDpt
|
|
152
|
-
let result = {}
|
|
153
|
-
result = JSON.parse(JSON.stringify(d))
|
|
154
|
-
result.fromBuffer = d.fromBuffer
|
|
155
|
-
result.formatAPDU = d.formatAPDU
|
|
156
|
-
return result
|
|
165
|
+
function cloneDpt(d) {
|
|
166
|
+
let result = {};
|
|
167
|
+
result = JSON.parse(JSON.stringify(d));
|
|
168
|
+
result.fromBuffer = d.fromBuffer;
|
|
169
|
+
result.formatAPDU = d.formatAPDU;
|
|
170
|
+
return result;
|
|
157
171
|
}
|
|
158
172
|
|
|
159
|
-
module.exports = dpts
|
|
173
|
+
module.exports = dpts;
|