Skip to content

Commit

Permalink
Merge pull request #18 from bnystrom/feature/ieee
Browse files Browse the repository at this point in the history
Feature/ieee
  • Loading branch information
jayharper authored Mar 15, 2018
2 parents 757e3ad + 004be7f commit 726e8ca
Show file tree
Hide file tree
Showing 9 changed files with 4,043 additions and 95 deletions.
4 changes: 2 additions & 2 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Run the following command in the root directory of your Node-RED install
### API
In addition, you can pass in a msg with one or more payload settings to initiate additional modbus read events.

```json
```javascript
msg.payload = {
"name": "Name1", // Should be a unique name
"topic": "topic1", // Override default topic
Expand Down Expand Up @@ -78,7 +78,7 @@ In addition to passing in a payload value for writing, you can also pass in the
* address

example message input:
```json
```javascript
msg = {
address: 8,
dataType: "Coil",
Expand Down
177 changes: 94 additions & 83 deletions ieee.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,120 +4,131 @@
//
// http://cautionsingularityahead.blogspot.com/2010/04/javascript-and-ieee754-redux.html

function toIEEE754(v, ebits, fbits) {
var LN2 = Math.LN2,
abs = Math.abs,
floor = Math.floor,
log = Math.log,
max = Math.max,
min = Math.min,
pow = Math.pow,
round = Math.round;

function unpackF64(b) { return unpackIEEE754(b, 11, 52); }
function packF64(v) { return packIEEE754(v, 11, 52); }
function unpackF32(b) { return unpackIEEE754(b, 8, 23); }
function packF32(v) { return packIEEE754(v, 8, 23); }

function packIEEE754(v, ebits, fbits) {

var bias = (1 << (ebits - 1)) - 1;

function roundToEven(n) {
var w = floor(n), f = n - w;
if (f < 0.5)
return w;
if (f > 0.5)
return w + 1;
return w % 2 ? w + 1 : w;
}

// Compute sign, exponent, fraction
var s, e, f;
if (isNaN(v)) {
e = (1 << bias) - 1; f = 1; s = 0;
}
else if (v === Infinity || v === -Infinity) {
e = (1 << bias) - 1; f = 0; s = (v < 0) ? 1 : 0;
}
else if (v === 0) {
if (v !== v) {
// NaN
// http://dev.w3.org/2006/webapi/WebIDL/#es-type-mapping
e = (1 << ebits) - 1; f = pow(2, fbits - 1); s = 0;
} else if (v === Infinity || v === -Infinity) {
e = (1 << ebits) - 1; f = 0; s = (v < 0) ? 1 : 0;
} else if (v === 0) {
e = 0; f = 0; s = (1 / v === -Infinity) ? 1 : 0;
}
else {
} else {
s = v < 0;
v = Math.abs(v);
v = abs(v);

if (v >= Math.pow(2,
1 - bias)) {
var ln = Math.min(Math.floor(Math.log(v) / Math.LN2), bias);
e = ln + bias;
f = v * Math.pow(2, fbits - ln) - Math.pow(2, fbits);
}
else {
if (v >= pow(2, 1 - bias)) {
// Normalized
e = min(floor(log(v) / LN2), 1023);
var significand = v / pow(2, e);
if (significand < 1) {
e -= 1;
significand *= 2;
}
if (significand >= 2) {
e += 1;
significand /= 2;
}
var d = pow(2, fbits);
f = roundToEven(significand * d) - d;
e += bias;
if (f / d >= 1) {
e += 1;
f = 0;
}
if (e > 2 * bias) {
// Overflow
e = (1 << ebits) - 1;
f = 0;
}
} else {
// Denormalized
e = 0;
f = v / Math.pow(2,
1 - bias - fbits);
f = roundToEven(v / pow(2, 1 - bias - fbits));
}
}

// Pack sign, exponent, fraction
var i, bits = [];
for (i = fbits; i; i -= 1) {
bits.push(f % 2 ? 1 : 0); f = Math.floor(f / 2);
}
for (i = ebits; i; i -= 1) {
bits.push(e % 2 ? 1 : 0); e = Math.floor(e / 2);
}
var bits = [], i;
for (i = fbits; i; i -= 1) { bits.push(f % 2 ? 1 : 0); f = floor(f / 2); }
for (i = ebits; i; i -= 1) { bits.push(e % 2 ? 1 : 0); e = floor(e / 2); }
bits.push(s ? 1 : 0);
bits.reverse();
var str = bits.join('');

// Bits to bytes
var bytes = [];
while (str.length) {
bytes.push(parseInt(str.substring(0,
8),
2));
bytes.unshift(parseInt(str.substring(0, 8), 2));
str = str.substring(8);
}
return bytes;
}

function fromIEEE754(bytes, ebits, fbits) {
function unpackIEEE754(bytes, ebits, fbits) {
// Bytes to bits
var bits = [];
for (var i = bytes.length; i; i -= 1) {
var byte = bytes[i - 1
];
for (var j = 8; j; j -= 1) {
bits.push(byte % 2 ? 1 : 0); byte = byte >> 1;
var bits = [], i, j, b, str,
bias, s, e, f;
// console.log({bytes});
// console.log('bytes[0]:',bytes[0]);
for (i = 0; i < bytes.length; ++i) {
b = bytes[i];
for (j = 8; j; j -= 1) {
bits.push(b % 2 ? 1 : 0); b = b >> 1;
}
}
bits.reverse();
var str = bits.join('');
str = bits.join('');
// console.log(str);
// Unpack sign, exponent, fraction
var bias = (1 << (ebits - 1)) - 1;
var s = parseInt(str.substring(0,1),2) ? -1 : 1;
var e = parseInt(str.substring(1,1 + ebits),2);
var f = parseInt(str.substring(1 + ebits),2);
bias = (1 << (ebits - 1)) - 1;
s = parseInt(str.substring(0, 1), 2) ? -1 : 1;
e = parseInt(str.substring(1, 1 + ebits), 2);
f = parseInt(str.substring(1 + ebits), 2);

// Produce number
if (e === (1 << ebits) - 1) {
return f !== 0 ? NaN : s * Infinity;
} else if (e > 0) {
// Normalized
return s * pow(2, e - bias) * (1 + f / pow(2, fbits));
} else if (f !== 0) {
// Denormalized
return s * pow(2, -(bias - 1)) * (f / pow(2, fbits));
} else {
return s < 0 ? -0 : 0;
}
else if (e > 0) {
return s * Math.pow(2, e - bias) * (1 + f / Math.pow(2, fbits));
}
else if (f !== 0) {
return s * Math.pow(2, -(bias - 1))* (f / Math.pow(2, fbits));
}
else {
return s * 0;
}
}

function fromIEEE754Double(b) {
return fromIEEE754(b,
11,
52);
}
function toIEEE754Double(v) {
return toIEEE754(v,11,52);
}
function fromIEEE754Single(b) {
return fromIEEE754(b,8,23);
}
function toIEEE754Single(v) {
return toIEEE754(v,
8,
23);
}
// Convert array of octets to string binary representation
// by bartaz

// function toIEEE754DoubleString(v) {
// return toIEEE754Double(v)
// .map(function (n) {
// for (n = n.toString(2); n.length < 8; n = "0" + n);
// return n
// })
// .join('')
// .replace(/(.)(.{11}) (.{52}) /,"$1 $2 $3")
// }

exports.fromIEEE754Single = fromIEEE754Single;
exports.fromIEEE754Double = fromIEEE754Double;

exports.unpackF64 = unpackF64;
exports.unpackF32 = unpackF32;
exports.packF64 = packF64;
exports.packF32 = packF32;
File renamed without changes
File renamed without changes
Binary file modified images/modbustcp-read2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions modbustcp.html
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ <h4>Function codes currently supported include:</h4>
<label for="node-input-server"><i class="icon-globe"></i> Server</label>
<input type="text" id="node-input-server">
</div>
<div class="header">IEEE Formatting</div>
<div class="header">IEEE-754</div>
<div class="bordered">
<div class="form-row">
<label for="node-input-ieeeType"><i class="fa fa-hashtag"></i> Type</label>
Expand Down Expand Up @@ -177,7 +177,7 @@ <h4>Function codes currently supported include:</h4>
</ul>
Choose a function code (FC) from the dropdown menu, select the coil/input/register start address (0:65535), and the quantity of coils/inputs/registers to be read from the start address. Input a poll rate (greater than zero) in seconds to setup the poll rate. Choose or edit the Modbus TCP server configuration.
<br><br>
<p><strong>IEEE Formatting</strong> Valid for register values, you can choose to have the output formatted
<p><strong>IEEE-754</strong> Valid for register values, you can choose to have the output formatted
for IEEE 754 Single and Double percision. Choose also the input format for Big or Little endian</p>
<h3>Input</h3>
You may input one or more payload values to initiate one or more additional timed read events.
Expand Down
17 changes: 11 additions & 6 deletions modbustcp.js
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,13 @@ module.exports = function(RED) {
this.rateUnit = config.rateUnit;
this.connection = null;
this.ieeeType = config.ieeeType || 'off';
this.ieeeBE = config.ieeeBE || true;
//this.ieeeBE =
if (config.hasOwnProperty('ieeeBE')) {
this.ieeeBE = (config.ieeeBE === "true");
}
else{
this.ieeeBE = true;
}

var node = this;

Expand Down Expand Up @@ -447,18 +453,17 @@ module.exports = function(RED) {
z = (isBE) ? i + 1 : i;
num[2] = nums[z] >> 8;
num[3] = (nums[z] & 0x00FF);
data[x] = ieee.fromIEEE754Single(num);
data[x] = ieee.unpackF32(num.reverse());
// console.log(data[x]);
x++;
}
// console.log(data);
return data;

}

function numdouble(nums, isBE)
{
// console.log('Got a numdouble');
//console.log('Got a numdouble:', isBE);
var x = 0;
var data = [];

Expand All @@ -476,7 +481,7 @@ module.exports = function(RED) {
}
}

for (var i=0; i<nums.length; i=i+2) {
for (var i=0; i<nums.length; i=i+4) {
var num = [];
//currently setup for Big Endian (swap i and i+1 for Little Endian)
num[0] = nums[i + offset[0]] >> 8;
Expand All @@ -487,7 +492,7 @@ module.exports = function(RED) {
num[5] = (nums[i+ offset[2]] & 0x00FF);
num[6] = nums[i+ offset[3]] >> 8;
num[7] = (nums[i+ offset[3]] & 0x00FF);
data[x] = ieee.fromIEEE754Double(num);
data[x] = ieee.unpackF64(num.reverse());
x++;
}
return data;
Expand Down
Loading

0 comments on commit 726e8ca

Please sign in to comment.