knxultimate
Advanced tools
Comparing version 1.0.44 to 1.0.46
@@ -10,3 +10,7 @@ ![Sample Node](img/logo.png) | ||
<p> | ||
<b>Version 1.0.43</b> - December 2023<br/> | ||
<b>Version 1.0.46</b> - January 2024<br/> | ||
- NEW: added DPT 275.100.<br/> | ||
</p> | ||
<p> | ||
<b>Version 1.0.44</b> - December 2023<br/> | ||
- Fixed DPT 9.001 issue when sending numberso having > 2 decimals.<br/> | ||
@@ -13,0 +17,0 @@ </p> |
{ | ||
"name": "knxultimate", | ||
"description": "KNX IP protocol implementation for Node. This is the ENGINE of Node-Red KNX-Ultimate node.", | ||
"version": "1.0.44", | ||
"version": "1.0.46", | ||
"engines": { | ||
@@ -6,0 +6,0 @@ "node": ">=14" |
@@ -6,20 +6,20 @@ /** | ||
const fs = require('fs') | ||
const path = require('path') | ||
const util = require('util') | ||
const knxLog = require('./../KnxLog') | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const util = require('util'); | ||
const knxLog = require("../KnxLog"); | ||
let matches | ||
const dirEntries = fs.readdirSync(__dirname) | ||
const dpts = {} | ||
let matches; | ||
const dirEntries = fs.readdirSync(__dirname); | ||
const dpts = {}; | ||
for (let i = 0; i < dirEntries.length; i++) { | ||
if (matches = dirEntries[i].match(/(dpt.*)\.js/)) { | ||
const dptid = matches[1].toUpperCase() // DPT1..DPTxxx | ||
const mod = require(__dirname + path.sep + dirEntries[i]) | ||
if (!mod.hasOwnProperty('basetype') || | ||
!mod.basetype.hasOwnProperty('bitlength')) { | ||
throw 'incomplete ' + dptid + ', missing basetype and/or bitlength!' | ||
const dptid = matches[1].toUpperCase(); // DPT1..DPTxxx | ||
const mod = require(__dirname + path.sep + dirEntries[i]); | ||
if (!mod.hasOwnProperty('basetype') | ||
|| !mod.basetype.hasOwnProperty('bitlength')) { | ||
throw `incomplete ${dptid}, missing basetype and/or bitlength!`; | ||
} | ||
mod.id = dptid | ||
dpts[dptid] = mod | ||
mod.id = dptid; | ||
dpts[dptid] = mod; | ||
// knxLog.get().trace('DPT library: loaded %s (%s)', dptid, dpts[dptid].basetype.desc); | ||
@@ -32,16 +32,16 @@ } | ||
dpts.resolve = function (dptid) { | ||
const m = dptid.toString().toUpperCase().match(/^(?:DPT)?(\d+)(\.(\d+))?$/) | ||
if (m === null) { throw new Error('Invalid DPT format: ' + dptid) } | ||
const m = dptid.toString().toUpperCase().match(/^(?:DPT)?(\d+)(\.(\d+))?$/); | ||
if (m === null) { throw new Error(`Invalid DPT format: ${dptid}`); } | ||
const dpt = dpts[util.format('DPT%s', m[1])] | ||
if (!dpt) { throw new Error('Unsupported DPT: ' + dptid) } | ||
const dpt = dpts[util.format('DPT%s', m[1])]; | ||
if (!dpt) { throw new Error(`Unsupported DPT: ${dptid}`); } | ||
const cloned_dpt = cloneDpt(dpt) | ||
const cloned_dpt = cloneDpt(dpt); | ||
if (m[3]) { | ||
cloned_dpt.subtypeid = m[3] | ||
cloned_dpt.subtype = cloned_dpt.subtypes[m[3]] | ||
cloned_dpt.subtypeid = m[3]; | ||
cloned_dpt.subtype = cloned_dpt.subtypes[m[3]]; | ||
} | ||
return cloned_dpt | ||
} | ||
return cloned_dpt; | ||
}; | ||
@@ -56,8 +56,8 @@ /* POPULATE an APDU object from a given Javascript value for the given DPT | ||
// console.log ("BANANA " + dptid) | ||
const dpt = dpts.resolve(dptid || 'DPT1') | ||
const nbytes = Math.ceil(dpt.basetype.bitlength / 8) | ||
const dpt = dpts.resolve(dptid || 'DPT1'); | ||
const nbytes = Math.ceil(dpt.basetype.bitlength / 8); | ||
// apdu.data = new Buffer(nbytes); // 14/09/2020 Supregiovane: Deprecated. Replaced with below. | ||
apdu.data = Buffer.alloc(nbytes) | ||
apdu.bitlength = dpt.basetype && dpt.basetype.bitlength || 1 | ||
let tgtvalue = value | ||
apdu.data = Buffer.alloc(nbytes); | ||
apdu.bitlength = dpt.basetype && dpt.basetype.bitlength || 1; | ||
let tgtvalue = value; | ||
// get the raw APDU data for the given JS value | ||
@@ -67,8 +67,10 @@ if (typeof dpt.formatAPDU === 'function') { | ||
// knxLog.get().trace('>>> custom formatAPDU(%s): %j', dptid, value); | ||
apdu.data = dpt.formatAPDU(value) | ||
apdu.data = dpt.formatAPDU(value); | ||
// knxLog.get().trace('<<< custom formatAPDU(%s): %j', dptid, apdu.data); | ||
} else { | ||
if (!isFinite(value)) { | ||
throw new Error(util.format('Invalid value, expected a %s', | ||
dpt.desc)) | ||
throw new Error(util.format( | ||
'Invalid value, expected a %s', | ||
dpt.desc, | ||
)); | ||
} | ||
@@ -78,17 +80,22 @@ // check if value is in range, be it explicitly defined or implied from bitlength | ||
? dpt.basetype.range | ||
: [0, Math.pow(2, dpt.basetype.bitlength) - 1] | ||
: [0, 2 ** dpt.basetype.bitlength - 1]; | ||
// is there a scalar range? eg. DPT5.003 angle degrees (0=0, ff=360) | ||
if (dpt.hasOwnProperty('subtype') && dpt.subtype.hasOwnProperty( | ||
'scalar_range')) { | ||
const scalar = dpt.subtype.scalar_range | ||
'scalar_range', | ||
)) { | ||
const scalar = dpt.subtype.scalar_range; | ||
if (value < scalar[0] || value > scalar[1]) { | ||
knxLog.get().trace( | ||
'Value %j(%s) out of scalar range(%j) for %s', | ||
value, (typeof value), scalar, dpt.id) | ||
value, ( | ||
typeof value), | ||
scalar, | ||
dpt.id, | ||
); | ||
} else { | ||
// convert value from its scalar representation | ||
// e.g. in DPT5.001, 50(%) => 0x7F , 100(%) => 0xFF | ||
const a = (scalar[1] - scalar[0]) / (range[1] - range[0]) | ||
const b = (scalar[0] - range[0]) | ||
tgtvalue = Math.round((value - b) / a) | ||
const a = (scalar[1] - scalar[0]) / (range[1] - range[0]); | ||
const b = (scalar[0] - range[0]); | ||
tgtvalue = Math.round((value - b) / a); | ||
} | ||
@@ -98,4 +105,10 @@ } else { | ||
if (value < range[0] || value > range[1]) { | ||
knxLog.get().trace('Value %j(%s) out of bounds(%j) for %s.%s', | ||
value, (typeof value), range, dpt.id, dpt.subtypeid) | ||
knxLog.get().trace( | ||
'Value %j(%s) out of bounds(%j) for %s.%s', | ||
value, ( | ||
typeof value), | ||
range, | ||
dpt.id, | ||
dpt.subtypeid, | ||
); | ||
} | ||
@@ -105,10 +118,10 @@ } | ||
if (dpt.basetype.hasOwnProperty('signedness') && dpt.basetype.signedness === 'signed') { | ||
apdu.data.writeIntBE(tgtvalue, 0, nbytes) | ||
apdu.data.writeIntBE(tgtvalue, 0, nbytes); | ||
} else { | ||
apdu.data.writeUIntBE(tgtvalue, 0, nbytes) | ||
apdu.data.writeUIntBE(tgtvalue, 0, nbytes); | ||
} | ||
} | ||
// knxLog.get().trace('generic populateAPDU tgtvalue=%j(%s) nbytes=%d => apdu=%j', tgtvalue, typeof tgtvalue, nbytes, apdu); | ||
return apdu | ||
} | ||
return apdu; | ||
}; | ||
@@ -122,8 +135,8 @@ /* get the correct Javascript value from a APDU buffer for the given DPT | ||
// sanity check | ||
if (!dpt) throw util.format('DPT %s not found', dpt) | ||
let value = 0 | ||
if (!dpt) throw util.format('DPT %s not found', dpt); | ||
let value = 0; | ||
// get the raw APDU data for the given JS value | ||
if (typeof dpt.fromBuffer === 'function') { | ||
// nothing to do here, DPT-specific fromBuffer implementation will handle everything | ||
value = dpt.fromBuffer(buf) | ||
value = dpt.fromBuffer(buf); | ||
} else { | ||
@@ -133,21 +146,22 @@ // knxLog.get().trace('%s buflength == %d => %j', typeof buf, buf.length, JSON.stringify(buf) ); | ||
if (buf.length > 6) { | ||
throw 'cannot handle unsigned integers more then 6 bytes in length' | ||
throw 'cannot handle unsigned integers more then 6 bytes in length'; | ||
} | ||
if (dpt.basetype.hasOwnProperty('signedness') && dpt.basetype.signedness == 'signed') { | ||
value = buf.readIntBE(0, buf.length) | ||
value = buf.readIntBE(0, buf.length); | ||
} else { | ||
value = buf.readUIntBE(0, buf.length) | ||
value = buf.readUIntBE(0, buf.length); | ||
} | ||
// knxLog.get().trace(' ../knx/src/index.js : DPT : ' + JSON.stringify(dpt)); // for exploring dpt and implementing description | ||
if (dpt.hasOwnProperty('subtype') && dpt.subtype.hasOwnProperty( | ||
'scalar_range')) { | ||
'scalar_range', | ||
)) { | ||
const range = (dpt.basetype.hasOwnProperty('range')) | ||
? dpt.basetype.range | ||
: [0, Math.pow(2, dpt.basetype.bitlength) - 1] | ||
const scalar = dpt.subtype.scalar_range | ||
: [0, 2 ** dpt.basetype.bitlength - 1]; | ||
const scalar = dpt.subtype.scalar_range; | ||
// convert value from its scalar representation | ||
// e.g. in DPT5.001, 50(%) => 0x7F , 100(%) => 0xFF | ||
const a = (scalar[1] - scalar[0]) / (range[1] - range[0]) | ||
const b = (scalar[0] - range[0]) | ||
value = Math.round(a * value + b) | ||
const a = (scalar[1] - scalar[0]) / (range[1] - range[0]); | ||
const b = (scalar[0] - range[0]); | ||
value = Math.round(a * value + b); | ||
// knxLog.get().trace('fromBuffer scalar a=%j b=%j %j', a,b, value); | ||
@@ -157,13 +171,13 @@ } | ||
// knxLog.get().trace('generic fromBuffer buf=%j, value=%j', buf, value); | ||
return value | ||
} | ||
return value; | ||
}; | ||
function cloneDpt (d) { | ||
let result = {} | ||
result = JSON.parse(JSON.stringify(d)) | ||
result.fromBuffer = d.fromBuffer | ||
result.formatAPDU = d.formatAPDU | ||
return result | ||
function cloneDpt(d) { | ||
let result = {}; | ||
result = JSON.parse(JSON.stringify(d)); | ||
result.fromBuffer = d.fromBuffer; | ||
result.formatAPDU = d.formatAPDU; | ||
return result; | ||
} | ||
module.exports = dpts | ||
module.exports = dpts; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1495696
111
9694