sigfox-gcloud
Version:
Framework for building a Sigfox server, based on Google Cloud Functions
77 lines (70 loc) • 2.94 kB
JavaScript
// Decode the structured message sent by unabiz-arduino library.
const firstLetter = 1; // Letters are assigned codes 1 to 26, for A to Z
const firstDigit = 27; // Digits are assigned codes 27 to 36, for 0 to 9
function decodeLetter(code) {
// Convert the 5-bit code to a letter.
if (code === 0) return 0;
if (code >= firstLetter && code < firstDigit) return (code - firstLetter) + 'a'.charCodeAt(0);
if (code >= firstDigit) return (code - firstDigit) + '0'.charCodeAt(0);
return 0;
}
function decodeText(encodedText0) { /* eslint-disable no-bitwise, operator-assignment */
// Decode a text string with packed 5-bit letters.
let encodedText = encodedText0;
const text = [0, 0, 0];
for (let j = 0; j < 3; j = j + 1) {
const code = encodedText & 31;
const ch = decodeLetter(code);
if (ch > 0) text[2 - j] = ch;
encodedText = encodedText >> 5;
}
// Look for the terminating null and decode name with 1, 2 or 3 letters.
// Skip invalid chars.
return [
(text[0] >= 48 && text[0] <= 122) ? String.fromCharCode(text[0]) : '',
(text[1] >= 48 && text[1] <= 122) ? String.fromCharCode(text[1]) : '',
(text[2] >= 48 && text[2] <= 122) ? String.fromCharCode(text[2]) : '',
].join('');
} /* eslint-enable no-bitwise, operator-assignment */
function decodeMessage(data, textFields) { /* eslint-disable no-bitwise, operator-assignment */
// Decode the packed binary SIGFOX message body data e.g. 920e5a00b051680194597b00
// 2 bytes name, 2 bytes float * 10, 2 bytes name, 2 bytes float * 10, ...
// Returns an object with the decoded data e.g. {ctr: 999, lig: 754, tmp: 23}
// If the message contains text fields, provide the field names in textFields as an array,
// e.g. ['d1', 'd2, 'd3'].
if (!data) return {};
// Messages must be either 8, 16 or 24 chars (4, 8 or 12 bytes).
if (data.length !== 8 && data.length !== 16 && data.length !== 24) return {};
try {
const result = {};
for (let i = 0; i < data.length; i = i + 8) {
const name = data.substring(i, i + 4);
const val = data.substring(i + 4, i + 8);
const encodedName =
(parseInt(name[2], 16) << 12) +
(parseInt(name[3], 16) << 8) +
(parseInt(name[0], 16) << 4) +
parseInt(name[1], 16);
const encodedVal =
(parseInt(val[2], 16) << 12) +
(parseInt(val[3], 16) << 8) +
(parseInt(val[0], 16) << 4) +
parseInt(val[1], 16);
// Decode name.
const decodedName = decodeText(encodedName);
if (textFields && textFields.indexOf(decodedName) >= 0) {
// Decode the text field.
result[decodedName] = decodeText(encodedVal);
} else {
// Decode the number.
result[decodedName] = encodedVal / 10.0;
}
}
return result;
} catch (error) {
throw error;
}
} /* eslint-enable no-bitwise, operator-assignment */
module.exports = {
decodeMessage,
};