I am trying to read/write values to a heat pump. How the communication works is described at https://rago600.sourceforge.net/ and in these examples.
For example:
Register 020B is sixteen bit number.
Let's write it in binary form 0000 0010|0000 1011
Now we can mark 7 groups from the end 00|0000100|0001011
And now we have this number in 7 bit form 00 04 0B
We have received temperature 00 04 38
Let's write 7 bit numbers in binary form 0000000|0000010|0111000
We will mark 8 bit delimiters 00000001|00111000
It is: 138(hex) 312(dec)
In that case temperature is 31.2C
We have received temperature 03 7C 1D
Let's write 7 bit numbers in binary form 0000011|1111100|0011101
We will mark 8 bit delimiters 11111110|00011101
It is: FE1D(hex) 65053(dec)-483(signed integer)
Received temperature is -48.3C
I have succeeded in decoding the values coming from the heat pump with this function but cannot get the reverse to work ie from dec to 7 bit hex.
var data = Buffer.from(msg.payload);
var decoded_int = (data[1] << 14) + (data[2] << 7) + data[3];
var decoded_buffer = Buffer.from([decoded_int & 0xff, decoded_int >> 8]);
var decoded = decoded_buffer.readInt16LE();
return { "decoded": decoded };
Related
I have a regex:
<[a-z]+>(.{2,}?)<\/
To extract from this string
<OperatingSystem>Windows 10 Enterprise 64-bit (10.0, Build 17763) (17763.rs5_release.180914-1434)</OperatingSystem> <Processor>Intel(R) Xeon(R) CPU E3-1270 v3 # 3.50GHz (8 CPUs), ~3.5GHz</Processor> <Memory>16384MB RAM</Memory> <UserDPISettings>96 DPI (100 percent)</UserDPISettings> <CardName>NVIDIA Quadro K2000</CardName> <DedicatedMemory>2007 MB</DedicatedMemory> <CurrentMode>1920 x 1200 (32 bit) (59Hz)</CurrentMode> <NativeMode>1920 x 1200(p) (59.950Hz)</NativeMode> <DriverVersion>26.21.14.4166</DriverVersion> <DriverVersion>6.00.0001.6070</DriverVersion>
an array of selected groups (not the full matches, see the difference):
[[Windows 10 Enterprise 64-bit (10.0, Build 17763) (17763.rs5_release.180914-1434), Intel(R) Xeon(R) CPU E3-1270 v3 # 3.50GHz (8 CPUs), ~3.5GHz, 16384MB RAM, 96 DPI (100 percent), NVIDIA Quadro K2000, 2007 MB, 1920 x 1200 (32 bit) (59Hz), 1920 x 1200(p) (59.950Hz), 26.21.14.4166, 6.00.0001.6070]]
Is the following code the simplest way to do that?
let r = /<[a-z]+>(.{2,}?)<\//gi, out = []; //Extract everything between quotes
let arr = [...str.matchAll(r)];
out = arr.map(x => x[1]);
If I run the following, I get an array of full matches:
var out = str.match(r); //["<OperatingSystem>Windows 10 Enterprise 64-bit (10.0, Build 17763) (17763.rs5_release.180914-1434)</", "<Processor>Intel(R) Xeon(R) CPU E3-1270 v3 # 3.50GHz (8 CPUs), ~3.5GHz</", "<Memory>16384MB RAM</", "<UserDPISettings>96 DPI (100 percent)</", "<CardName>NVIDIA Quadro K2000</", "<DedicatedMemory>2007 MB</", "<CurrentMode>1920 x 1200 (32 bit) (59Hz)</", "<NativeMode>1920 x 1200(p) (59.950Hz)</", "<DriverVersion>26.21.14.4166</", "<DriverVersion>6.00.0001.6070</"]
Is there something similar to str.match(r) for returning an array of the groups directly?
Thanks!
Edit: The simplest way I've found is:
let r = /<[a-z]+>(.{2,}?)<\//gi, out = [];
let arr= Array.from(str.matchAll(r), m => m[1]);
An even easier solution is to use lookbehinds and lookaheads to just select the fields you are interested in, as demonstrated in this example with the following regex:
/(?<=>\b).*?(?=<\/)/gi
That way you skip all the extra steps to extract the group matches and just get an array of the results you want with a mere str.match(r).
I'm new to JavaScript and I use Node-Red to read an write from a Database.
I receive from the database an object that contains the status of 8 digital inputs.
Each inputs is represented as a bit.
I'm looking for a method to combine each bits into a byte.
This is the object that I receive from the database:
array[1]
0: object
idx: 10
ts: "2018-11-21T06:12:45.000Z"
in_0: 1
in_1: 1
in_2: 1
in_3: 1
in_4: 1
in_5: 1
in_6: 1
in_7: 1
in_x represent the input position.
As out I would like to receive a byte that represent the combination of each single byte.
For example:
in0: 0,
in1: 1,
in2: 0,
in3: 0,
in4: 0,
in5: 1,
in6: 0,
in7: 0,
The output byte will be: 00100001 in binary that converted to byte is 33
Any suggestions?
Thanks in advance.
The following code works as you requested*:
var output =
arr[0].in_0 +
(arr[0].in_1 << 1) +
(arr[0].in_2 << 2) +
(arr[0].in_3 << 3) +
(arr[0].in_4 << 4) +
(arr[0].in_5 << 5) +
(arr[0].in_6 << 6) +
(arr[0].in_7 << 7);
This code assumes that each variable can only be a 1 or a 0. Anything else will result in nonsense.
I have used the Left Bit Shift operator (<<) to obtain the power of two for each on bit.
You have specified that in_7 is the Most Significant Bit. If it is actually the Least Significant Bit, reverse the order of the in_x variables.
*The result is not a byte, but it does contain the number that I think you're expecting.
I transmit a byte that's always less than 127 with a 1 bit flag to the client by ORing the byte with 0x80.
On the client side, in JavaScript, I have an Array() of numbers representing the bytes of the message (yes it's probably dumb but I haven't figured out typed arrays yet).
Everything works fine until I hit a number with the highest bit of the lowest byte set.
Number: 0011 0101
flag: 1000 0000
---------
1011 0101
Stored as
integer in ???
JavaScript
How can I retrieve the original byte (with the highest bit set to 0), plus the flag (denoted by the value of the highest bit)?
EXAMPLE:
(server)
byte x = 90
x | 0x80
> -38
(client - JavaScript)
var x = -38
x ^ 0x80
> -166
How do I get 90 back?
EDIT - I discovered this was due to another bug in my code... I wasn't going crazy with the encoding... sorry all...
Try the following in JavaScript:
var received = -38;
var adjusted = received & 0xFF; // 218
var original = adjusted ^ 0x80; // 90
That should solve your problem.
Explanation: All numbers in JavaScript stored in the double-precision floating point format:
Bitwise operators however can't deal with floating point numbers. Hence they convert their operands into 32-bit signed integers. [source]
-38 = 11111111 11111111 11111111 11011010
Hence if you do -38 ^ 0x80 you get the wrong answer as only the 8th bit from the right is set to 0. You need to first limit -38 to 8-bits before xoring it with 0x80. Only the least significant byte (i.e. 11011010) is needed. Hence we do -38 & 0xFF to get the least significant byte.
Now that you have the correct byte you may simply xor it with 0x80.
TLDR: Use byte & 0xFF ^ 0x80.
Not sure I understand the question, but I will give a shot: you have just to XORing the 0x80:
var received = 181; // 10110101
var num = received ^ 0x80;
console.log(num); // 53, 00110101
If you have a different result, probably there is something different in your code – if you run the code above, should give the expected result.
I'm not seeing a problem.
Here is some code I've written to test, with JSFiddle live demo
var val = 57;
var flag = 1;
var valWithFlag = val | (flag ? 0x80 : 0);
var newVal = (valWithFlag & 0x7F);
var newValFlag = (valWithFlag & 0x80 ? 1 : 0);
alert("Val: " + val.toString() + "\n" +
"Flag: " + flag.toString() + "\n" +
"Val With Flag: " + valWithFlag.toString() + "\n" +
"New Val Without Flag: " + newVal.toString() + "\n" +
"New Val Flag: " + newValFlag.toString() + "\n");
It is giving the desired results...
Val: 57
Flag: 1
Val With Flag: 185
New Val Without Flag: 57
New Val Flag: 1
UPDATE based on extra details provided by the OP
I think this is probably due to integers in javascript being held either as 32 or 64 bit values... so when you pass through -38 to javascript it isn't being held in the same way as the single byte on your server.
You need to convert that -38 into an 8-byte...
var val = -38;
var jsVal = (val & 0xFF);
Which should give you your 90 value to work with. Here is an updated JSFiddle
first of all I'm sorry for the dumb question but I'm new with nodejs.
I read from a socket a 64bit little endian signed integer, and put it on a Buffer, so let's say i have the number 256 represented as:
<Buffer 00 01 00 00 00 00 00 00>
Since the Buffer class has only readInt32LE and readUInt32LE how can i convert this buffer to its equivalent js number, using 32 bit operations ?
Should i read two 32bit big endian numbers and then somehow bitwise or them ? should i read them little endian ?
Thanks
ECMA Section 8.5 - Numbers
Note that all the positive and negative integers whose magnitude is no greater than 253 are representable in the Number type (indeed, the integer 0 has two representations, +0 and −0).
Javascript uses internally 64 bit floating numbers, wich means you can only represent exactly numbers up to 253, or 9007199254740992. If it's ok for you, you can use following code to read 64 bit signed/unsigned int into 64 bit float:
function readUInt64(buff, offset) {
return buff.readInt32LE(offset) + 0x100000000*buff.readUInt32LE(offset + 4);
}
function readInt64(buff, offset) {
var word0 = buff.readUInt32LE(offset);
var word1 = buff.readUInt32LE(offset+4);
if (!(word1 & 0x80000000))
return word0 + 0x100000000*word1;
return -((((~word1)>>>0) * 0x100000000) + ((~word0)>>>0) + 1);
}
If you need exact representation - use bignumber.js library
function readUInt64(buff, offset) {
var word0 = buff.readUInt32LE(offset);
var word1 = buff.readUInt32LE(offset+4);
return new BigNumber(word0).plus(new BigNumber(word1).times(0x100000000));
}
I'm looking for a lossless compression algorithm (like LZW or Huffman or anything) in javascript, that accepts and returns raw, binary data.
With 'binary data' I mean a sequence of bytes, which may come in any of the following forms:
a string containing characters with any value from 0 to 255
an array containing integers with any value from 0 to 255
a string containing a hexadecimal representation of the data (i.e. 2 hex digits per byte)
a string containing the base64 encoded representation of the data
or anything else that can be unambiguously converted from or to any of the above
Now obviously there are TONS of javascript implementations available everywhere, for a wide range of algorithms. However EVERYTHING I find seems to do crazy stuff like:
returning an array containing also values >255 (so what is the compression ratio now? how do I represent this in bytes, or how would I go about saving this to a file for example?)
messing with character encodings in strings, converting from/to unicode or url/html entities or whatnot (it's BINARY, character encoding does not apply here!)
return other representations that don't seem suitable for binary storage (i.e. cannot be converted to sequence of bytes)
Would anyone know of a good javascript compression (+decompression) implementation that suits my binary fetish?
I think I found what I was looking for after all: this deflate + inflate implementation in javascript seems to work with strings as byte sequences.
first of all create a closure for hold the binar or hex or decimal flags
function ASearch() { }
ASearch.Flag = {
Front_Wheel_Drive: 0xF, Rear_Wheel_Drive: 0xF0, Four_Wheel_Drive: 0xF00,
Auto: 0xFF, Manual: 0xFF00,
Gas: 0xF, Diesel: 0xF0, Hybrid: 0xF00, Electrical: 0xF000,
Two: 1, Three: 2, Four: 4, Five: 8, Six: 16, Eight: 32, Ten: 64, Twelve: 128
};
then set like this
SetFlag = (function (e) {
e = e.srcElement;
$("#" + e.parentNode.name).val(e.checked ?
$("#" + e.parentNode.name).val() | ASearch.Flag[e.id] :
$("#" + e.parentNode.name).val() ^ ASearch.Flag[e.id]);
});
this is an example for packed data in a 32 bit integer
there are four variable... i've used them for 18 flags.. this is fast and super effective
for example...
int i = 0; //binary = 0000 0000 0000 0000
i = i | 255; //binary = 0000 0000 1111 1111
i = i ^ 255; //binary = 0000 0000 0000 0000
i = i | 0xFF00; //binary = 1111 1111 0000 0000
i = i | 255; //binary = 1111 1111 1111 1111
i = i ^ 0xFF00; //binary = 0000 0000 1111 1111