This stuff is still a mystery to me - another decoder looks fairly straight forward once I see a working decoder, but the terminology used in this description is beyond my limited knowledge.
4 Bytes in hex: 0 0 0 0 1 0 3 4 (TTN Payload looks like this)
Ascii: 00 00 10 34
Hex: 30 30 30 30 31 30 33 34
Byte1 4bit (bit 7-4): full: 1, not full: 0
Byte1 4bit (bit 3-0): fire: 1, not fire: 0
Byte2 4bit (bit 7-4): fall: 1, not fall: 0
Byte2 4bit (bit 3-0): battery: 1 not: 0
Byte3 and 4: the air level(from sensor to garbage), unit: mm, 1034 means 1034mm; range 0-2000mm;
Example:
Application server get data in payload_hex section 10000230, 4 bytes, in hex 0x
31 30 30 30 30 32 33 30.
That mean it is full, no flame, no fall, air height is 230mm.
Notes: Some application server parsing the payload to the original 4 Bytes.
Please use the half byte as one status to parse accordingly.
Hi @Paul_Stewart, the data makes sense and can understand how its derived from the sensor.
How do you want this split up by the Decoder, ie how do you want this sent?
For example do you want the Decoder to create some variables something like
BinFull (Boolean) 0 or 1
Fire (Boolean) 0 or 1
Fall (Boolean) 0 or 1
Battery (is this a variable for battery voltage or something similar?)
AirLevel (Integer) from 0-2000
If you can define the variable we can then explain how to create the Decoder
To help future readers find the answer: what sensor is that, and can you share the manual? Also, someone recently asked for Rubbish/Trash Can monitoring, so please share there?
And where did you find the hexadecimal encoded version? What you’re calling ASCII is not ASCII. The 4 bytes 00 00 10 34 are already shown in a hexadecimal representation. These are all the same:
base 1, binary: 00000000 00000000 00010000 00110100
Can you use that device to get some actual readings?
To me, it would be really unexpected that a hexadecimal value of 0x0230 would decode to a decimal result of 230 instead of 560 (MSB). That could mean they used something that’s not very storage efficient (though with a range of 0…2000 regular bit shifting needs 2 bytes too), like:
data[3] = height / 100;
data[4] = height % 100;
Or it could mean that they explicitly did this to make the hexadecimal representation easier to read by humans (and a tiny bit harder to process by computers). But then: using 4 bits for a single on/off value might indicate that such is exactly what the manufacturer is trying to do. Weird; unless they explicitly wanted to achieve this, I wouldn’t expect much from, say, low power behaviour then…
We are having troubles with the battery that was shipped with it - so he might have to wait till a new one turns up - we can power it off the TTL cable serial cable but they may mess up the readings, not sure
See if this works for you. There are a number of assumptions here. @arjanvanb i’m a novice with JS so any feedback would be appreciated.
As pointed out earlier, its odd the 4 binary variables (Binfull, Fire, Fall and BatteryLow) are not sent with one bit each but using 4 bits each (half a byte each). So I have assumed 0000 is False and any of the possible non zero values (0001 or 0010 or 0011 or … up to 1111) would mean true.
We could put a Boolean function in the decoder (see below) but since i don’t know how your processing the data downstream i haven’t added this in the code. If its needed then an example would be something like var BinFull = Boolean( (bytes[0] >> 4) != 0 )
In the code (below) I have assumed AirLevel is packed efficiently into the two bytes but looking at your decode it may need something like
AirLevel = ((bytes[2] >> 4) * 1000) + ((bytes[2] & 00001111) * 100) + ((bytes[3] >> 4) * 10) + ((bytes[3] & 00001111))
With this one, give it a try and see what you get. We can help you adjust the code from there.
function Decoder(bytes, port) {
var BinFull = (bytes[0] >> 4);
var Fire = (bytes[0] & 00001111);
var Fall = (bytes[1] >>4);
var BatteryLow = (bytes[1] & 00001111);
var AirLevel = (bytes[2] << 8) | bytes[3]) ;
return {
BinFull:BinFull,
Fire:Fire,
Fall:Fall,
BatteryLow:BatteryLow,
AirLevel:AirLevel,
}
}
It seems the device uses an old standard known as “packed binary-coded decimal” (BCD), which encodes each digit into its own nibble (4 bits). So, Tony is right about this:
Fixed for the octal problem (see further below), that would then read:
Just as another fun fact, one could abuse JavaScript’s type coercion and use intermediate string values:
// Convert to hexadecimal strings without any "0x" prefix, hence
// treated as decimal values when coercing back to a number (due
// to the multiplication and the explicit unary plus operator).
AirLevel = bytes[2].toString(16) * 100 + +bytes[3].toString(16)
Yes, that needs two plus-characters for that second part, one being addition and the second being the unary plus. (One could also multiply the second part by 1, to get a number.)
Above, 00001111 does not denote a binary number, but due to it starting with a zero, it’s interpreted as an octal number, where 10 is decimal 8. So rather than this being hexadecimal 0x0F or decimal 15, using 00001111 yields decimal 585. (This has changed in ECMAScript 6.)
The version of JavaScript that is used by the Payload Formats (being: ECMAScript 5) does not have any prefix to explicitly denote binary, like one can use 0x to prefix hexadecimal numbers, where 0x10 is decimal 16. (ECMAScript 6 allows for writing 0b00001111.)
One could use parseInt("00001111", 2), and as JavaScript is doing all kinds of type coercions for you, even parseInt(1111, 2) would work, where 1111 is first changed into the string “1111” and then interpreted as a binary number. But leaving out the quotes would not work with leading zeroes, as then it would first be interpreted as octal yielding 585 in decimal, after which the string “585” cannot be parsed as a binary number.
No need for explicit casting; (bytes[0] >> 4) != 0 is already a boolean, so suffices.
That’s indeed what I’d expect (though the parentheses are not needed when using a bitwise OR). But like you already wrote: given the examples I guess it’s not.
Wow…thanks guys, would never have got close to that by myself.
I won’t have an opportunity to test for a couple of days but as you did, I put it into the application and tested those few readings we had and it looked good.
Thank goodness someone has come to their senses. I started programming in Fortran, learnt Cobol and Pascal (showing my age). Coded in assembler on PDP11/04 (and many other machines and chips since) but never heard of a language that assumed something that started with a zero to be Octal. (Said i was a novice in JS and I think I might just keep it that way )
I referred to JS documentation but did not realise there are significant differences in the versions. So thanks for the feedback, it’s most appreciated.