@ncd-io/node-red-enterprise-sensors
Version:
You can install this library through the Palette Manager in Node-Red's UI.
1,405 lines (1,335 loc) • 447 kB
JavaScript
const events = require('events');
const Queue = require('promise-queue');
const fs = require('fs');
const path = require('path');
globalDevices = {};
module.exports = class WirelessSensor{
constructor(digi){
this.mac;
this.digi = digi;
this.send = digi.send;
this._emitter = new events.EventEmitter();
this.sensor_pool = {};
this.sensor_types = sensor_types(this);
this.queue = new Queue(1);
this.sensor_libs = {};
this.load_sensor_libs();
//route info and link quality objects
this.mesh_map = {};
this.link_quality = {};
this.query_pool = {};
this.payloadType = {
'79': 'manual_sync_check_in',
'95': 'sync_end',
'109': 'sync_ack',
'111': 'sync_check_in',
'122': 'power_up',
'124': 'config_ack',
'125': 'config_error',
'127': 'sensor_data'
};
var that = this;
function receiver(frame){
try{
that.parse(frame);
}catch(e){
console.log(frame);
console.log('unable to parse frame');
console.log(e);
}
}
function routeReceiver(frame){
that.parse_route_information_packet(frame);
}
function linkQualtiyReceiver(frame){
that.parse_link_quality_packet(frame);
}
this.digi.on('receive_packet', receiver);
this.digi.on('explicit_rx_indicator', linkQualtiyReceiver);
this.digi.on('route_information_packet', routeReceiver);
this.on('close', () => {
//console.log('removing listener');
this.digi._emitter.removeListener('receive_packet', receiver);
this.digi._emitter.removeListener('explicit_rx_indicator',linkQualtiyReceiver);
this.digi._emitter.removeListener('route_information_packet',routeReceiver);
});
};
load_sensor_libs() {
const sensors_path = path.join(__dirname, 'sensors');
if (fs.existsSync(sensors_path)) {
fs.readdirSync(sensors_path).forEach(file => {
if (file.endsWith('.js')) {
// Require the "factory" function from the file
const sensorFactory = require(path.join(sensors_path, file));
// We pass 'this.globalDevices' so all libs point to the same object
const sensor = sensorFactory(globalDevices, this._emitter);
// Register the initialized library by type ID
this.sensor_libs[sensor.type] = sensor;
}
});
}
};
send_control(type, mac, msg){
if(this.sensor_types[type] && typeof this.sensor_types[type].control != 'undefined'){
return this.control_send(mac, [249, ...this.sensor_types[type].control(msg)]);
}else{
return new Promise((f,r)=>{r('Unknown sensor type');});
}
}
send_arbitrary(mac, data){
return this.control_send(mac,msg);
}
close(cb){
this._emitter.emit('close');
this.digi.close();
}
parse_route_information_packet(frame){
var destination = frame.destination_mac;
var route_array = this.mesh_map[destination];
var index = this.query_pool[destination];
//This is the route packet from the modem
if(frame.source_mac == frame.responder_mac){
//Add Gateway MAC as first element of array.
route_array[0] = frame.source_mac;
//Add Receiver MAC as second item in array
route_array[1] = frame.receiver_mac;
if(frame.receiver_mac == frame.destination_mac){
//if receiver is the sensor then connection is direct from gateway to receiver so emit route info
var msg_obj = {};
msg_obj.route = route_array;
msg_obj.timestamp = Date.now();
this._emitter.emit("route_info",msg_obj);
}
}else{
//This is the final route packet
if(frame.receiver_mac == destination){
route_array.push(frame.receiver_mac);
var msg_obj = {};
msg_obj.route = route_array;
msg_obj.timestamp = Date.now();
this._emitter.emit("route_info",msg_obj);
delete this.query_pool[frame.destination_mac];
}else{
// This is an intermediate packet
if(frame.responder_mac == route_array[this.query_pool[destination]]){
route_array.push(frame.receiver_mac);
}
}
}
//increment mesh hops index
this.query_pool[destination]++;
}
parse_link_quality_packet(frame){
console.log("parse_link_quality_packet: "+frame);
var msg_obj = {};
msg_obj.source_address = frame.source_mac;
msg_obj.destination = toMac(frame.data.slice(0,8));
msg_obj.payload_size = msbLsb(frame.data[8],frame.data[9]);
msg_obj.iterations = msbLsb(frame.data[10], frame.data[11]);
msg_obj.successful_iterations = msbLsb(frame.data[12],frame.data[13]);
msg_obj.retries = msbLsb(frame.data[14],frame.data[15]);
msg_obj.result = frame.data[16] == 0 ? "success":"failed"
msg_obj.max_allowed_retries = frame.data[17];
msg_obj.max_rssi = 0 - frame.data[18];
msg_obj.min_rssi = 0 - frame.data[19];
msg_obj.avg_rssi = 0 - frame.data[20];
msg_obj.timestamp = Date.now();
this._emitter.emit("link_info",msg_obj);
}
get_sensor_definition(sensor_type){
return this.sensor_libs[sensor_type] || this.sensor_types[sensor_type];
}
parse(frame){
// NOTE this must be above the type selection to prevent rs-485 data from triggering other functionality.
if(globalDevices.hasOwnProperty(frame.mac) && globalDevices[frame.mac].hasOwnProperty('bridge') && globalDevices[frame.mac].bridge){
// if(type === undefined && globalDevices.hasOwnProperty(frame.mac) && globalDevices[frame.mac].hasOwnProperty('bridge') && globalDevices[frame.mac].bridge){
let query_data = {
addr: frame.mac,
payload: frame.data,
}
if(globalDevices[frame.mac].hasOwnProperty('command_queue') && globalDevices[frame.mac].command_queue.length != 0){
if(globalDevices[frame.mac].command_queue[0].hasOwnProperty('command')){
query_data.command = globalDevices[frame.mac].command_queue[0].command;
}
if(globalDevices[frame.mac].command_queue[0].hasOwnProperty('meta')){
query_data.meta = globalDevices[frame.mac].command_queue[0].meta;
}
this._emitter.emit('converter_ack-'+frame.mac, query_data);
return;
}
// }
}
var type = this.payloadType[frame.data[0]];
if(typeof this[type] == 'function'){
var data = this[type](frame.data.slice(1), frame);
if(typeof data == 'undefined'){
return;
}
data.type = type;
data.addr = frame.mac;
data.received = Date.now();
data.original = frame;
var is_new = typeof this.sensor_pool[frame.mac] == 'undefined';
var new_mode = is_new;
var mode = (type == 'power_up') ? data.mode : ((type == 'sensor_data') ? 'RUN' : ((type == 'config_ack') ? 'ACK' : 'PGM'));
if(mode == 'ACK'){
if(data.data.length == 37){
this._emitter.emit('manifest_received', data);
}
}
// #OTF
var otf_devices = [4,12,21,23,26,29,30,32,33,35,39,44,45,48,52,53,54,55,56,58,74,76,78,79,80,81,82,84,88,89,90,91,93,97,98,99,101,102,103,105,106,107,108,109,110,111,112,114,117,118,119,120,121,122,123,124,125,126,180,181,202,217,211,270,519,520,521,531,535,536,537,538,539,540,541,542,543,545,554,1010,1011];
var device_type = msbLsb(frame.data[6], frame.data[7]);
// var device_type = frame.data[7];
if(mode == "RUN"){
if(frame.data[9] == 70 && frame.data[10] == 76 && frame.data[11] == 89) {
var broadcast_otf_devices = [101,102,202];
mode = "FLY";
}
if(frame.data[9] == 85 && frame.data[10] == 80 && frame.data[11] == 84 && frame.data[12] == 72 && frame.data[13] == 87 && frame.data[14] == 82 && frame.data[15] == 78) {
mode = "UPTHWRN";
}
}
if(mode == 'ACK'){
data.firmware_version = frame.data[5];
if(data.firmware_version == 0){
data.sensor_type = frame.data[3];
}else{
data.sensor_type = msbLsb(frame.data[3], frame.data[4]);
}
// Firmware bug fix to alter received OTN into INI for sync
// key = sensor type, value = array of affected firmware versions
// TODO this can be removed if we bypass INI requirement for sync and just trigger on sync_report for both API and device node
const otn_override_list = {
110: [10],
111: [10],
114: [10]
};
if(Object.hasOwn(otn_override_list, data.sensor_type) && otn_override_list[data.sensor_type].includes(data.firmware_version) ){
if(frame.data[7] == 79 && frame.data[8] == 84 && frame.data[9] == 78){
console.log('############OVERRIDE OTN###############');
frame.data[7] = 73;
frame.data[8] = 78;
frame.data[9] = 73;
}
}
if(data.sensor_type == 0){
data.sensor_type = msbLsb(frame.data[3], frame.data[4]);
}
if(frame.data[7] == 79 && frame.data[8] == 84 && frame.data[9] == 78){
mode = "OTN";
}
else if(frame.data[7] == 79 && frame.data[8] == 84 && frame.data[9] == 70){
mode = "OTF";
}
else if(frame.data[7] == 73 && frame.data[8] == 78 && frame.data[9] == 73){
// mode = "FLY";
mode = "INI";
}
else if(frame.data[7] == 69 && frame.data[8] == 78 && frame.data[9] == 68){
mode = "END";
}
}
// If it is not a new sensor
if(!is_new){
// If mode == RUN and type is not 'power_up' don't send RUN
// sensor_data emitter sets status of UI anyay
if(mode == 'RUN' && type != 'power_up'){
new_mode = false;
} else if(mode == 'RUN' && type == 'power_up'){
new_mode = true;
}else{
new_mode = this.sensor_pool[frame.mac].mode != mode;
}
};
this.sensor_pool[frame.mac] = {
mac: frame.mac,
type: data.sensor_type,
nodeId: data.nodeId,
mode: mode,
// data: data,
lastHeard: data.received
};
if(mode === 'FLY' && frame.data.length > 12){
// get sensor definition from either sensor_types or sensor_libs, maybe do this above if used often
const sensor_def = this.get_sensor_definition(data.sensor_type);
// Pull in parse_fly from either if it exists.
const parse_fly = sensor_def?.parse_fly;
if(typeof parse_fly === 'function'){
try{
this.sensor_pool[frame.mac].reported_config = parse_fly(frame.data);
} catch(error) {
console.log('Error detect in parse_fly initiated by FLY message');
console.log(error);
this.sensor_pool[frame.mac].reported_config = "Error parsing reported config. See log for details."
}
}else{
console.log('FLY message received but no parse_fly function found for sensor type '+data.sensor_type);
this.sensor_pool[frame.mac].reported_config = "Error parsing reported config. See log for details."
}
}else if(mode === 'OTF' && frame.data.length > 12){
// restructure and add dead bytes to match FLY message so we only need one parser.
// If we ever need to add any of the additional information of this packet we will need to rebuild to match
// get sensor definition from either sensor_types or sensor_libs, maybe do this above if used often
const sensor_def = this.get_sensor_definition(data.sensor_type);
// Pull in parse_fly from either if it exists.
const parse_fly = sensor_def?.parse_fly;
if(typeof parse_fly === 'function'){
try{
frame.data.splice(2,0,frame.data[5],0);
this.sensor_pool[frame.mac].reported_config = parse_fly(frame.data);
} catch(error){
console.log('Error detect in parse_fly initiated by OTF message');
console.log(error);
this.sensor_pool[frame.mac].reported_config = "Error parsing reported config. See log for details."
}
}else{
console.log('OTF message received but no parse_fly function found for sensor type '+data.sensor_type);
this.sensor_pool[frame.mac].reported_config = "Error parsing reported config. See log for details."
}
}else if(mode === 'ACK'){
this.sensor_pool[frame.mac].status = data.result;
if(data.data.length){
if(data.sensor_type == 110 || data.sensor_type == 111 || data.sensor_type == 112 || data.sensor_type == 114 || data.sensor_type == 543){
if(data.data[0] == 77 && data.data[1] == 79 && data.data[2] == 70 && data.data[3] == 70 && data.data[4] == 0){
this.sensor_pool[frame.mac].mode = 'MOFF';
}
}
this.sensor_pool[frame.mac].data = data.data;
};
}
var that = this;
if(is_new){
that._emitter.emit('found_sensor', that.sensor_pool[frame.mac]);
}
if(mode == 'INI'){
const sync_data = {
type: 'sync_init',
address: frame.mac,
payload: {
type: 'sync_init',
address: frame.mac,
sensor_type: that.sensor_pool[frame.mac].type,
node_id: that.sensor_pool[frame.mac].nodeId,
data: {...that.sensor_pool[frame.mac]}
},
description: 'Sensor is remaining powered to accept configurations and updates.',
}
that._emitter.emit('sync', sync_data);
that._emitter.emit('sync-'+frame.mac, sync_data);
// Emit config_ack to pass enter_otn
that._emitter.emit('config_ack-'+frame.mac, sync_data);
return;
}
// mode === 'ACK' check added to allow multiple configs through front end gateway input
if(new_mode || mode === 'ACK'){
// If RSSI is not enabled send stored values, if it is, request the RSSI and temporarily append it.
if(typeof frame.rssi == 'undefined'){
that._emitter.emit('sensor_mode', that.sensor_pool[frame.mac]);
that._emitter.emit('sensor_mode-'+frame.mac, that.sensor_pool[frame.mac]);
}else{
frame.rssi.then((v) => {
let sensor_pool_rssi = that.sensor_pool[frame.mac];
sensor_pool_rssi.rssi = v.data[0];
that._emitter.emit('sensor_mode', sensor_pool_rssi);
that._emitter.emit('sensor_mode-'+frame.mac, sensor_pool_rssi);
}).catch(console.log);
}
}
if(mode != 'FLY' && mode !='UPTHWRN'){
var send_events = function(){
that._emitter.emit(type, data);
that._emitter.emit(type+'-'+data.sensor_type, data);
that._emitter.emit(type+'-'+frame.mac, data);
// MARK FLY CONFIG DATA
};
if(typeof frame.rssi == 'undefined') send_events();
else frame.rssi.then((v) => {
data.rssi = v.data[0];
send_events();
}).catch(console.log);
}
}else{
this._emitter.emit(frame.type+'-'+frame.mac.toUpperCase(), data);
var data = {};
data.addr = frame.mac;
data.data = frame.data;
this._emitter.emit(frame.type+'-'+'unknown_device', data);
}
}
power_up(payload){
return {
nodeId: payload[0],
sensor_type: msbLsb(payload[2], payload[3]),
mode: String.fromCharCode(...payload.slice(6, 9))
};
}
config_ack(payload){
if((msbLsb(payload[2], payload[3])) == 28){
payload[5] = payload[6];
}
return {
nodeId: payload[0],
counter: payload[1],
sensor_type: msbLsb(payload[2], payload[3]),
result: payload[5],
data: payload.slice(6)
};
};
config_error(payload){
var errors = [
'Unknown',
'Invalid Command',
'Sensor Type Mismatch',
'Node ID Mismatch',
'Apply change command failed',
'Invalid API Packet Command Response Received After Apply Change Command',
'Write command failed',
'Invalid API Packet Command Response Received After Write Command',
'Parameter Change Command Failed',
'Invalid Parameter Change Command Response Received After Write Command',
'Invalid/Incomplete Packet Received',
'Unknown',
'Unknown',
'Unknown',
'Unknown',
'Invalid Parameter for Setup/Saving'
];
return {
nodeId: payload[0],
sensor_type: msbLsb(payload[2], payload[3]),
error: payload[6],
error_message: errors[payload[6]],
last_sent: this.digi.lastSent
};
};
sync_ack(payload, frame){
const rep_buffer = Buffer.from(frame.data);
const sensor_type = rep_buffer.readUInt16BE(5);
let report = {};
if(rep_buffer[2] === 0xff ){
const values = this.sensor_libs[sensor_type].sync_parse(rep_buffer);
try{
report = {
type: 'sync_acknowledgment',
address: frame.mac,
sensor_type: sensor_type,
payload: {
type: 'sync_acknowledgment',
address: frame.mac,
sensor_type: sensor_type,
sync_success: true,
response_bytes: rep_buffer,
...values,
},
description: 'Acknowledgment received from sensor in response to sync command. This report includes the current sensor information or errors.',
};
}catch(e){
console.log(e);
console.log('Error in sync_acknowledgement parsing for sensor type '+sensor_type);
}
this._emitter.emit('sync_acknowledgment-'+frame.mac, report);
}else{
report = {
type: 'sync_acknowledgment',
address: frame.mac,
sensor_type: sensor_type,
payload: {
type: 'sync_acknowledgment',
address: frame.mac,
sensor_type: sensor_type,
sync_success: false,
response_bytes: rep_buffer,
// ...this.sensor_libs[sensor_type].sync_parse(rep_buffer),
},
description: 'Acknowledgment received from sensor in response to sync command. This report includes the current sensor information or errors.',
};
this._emitter.emit('sync_acknowledgment_error-'+frame.mac, response);
}
report.packet_info = frame.receive_options;
// console.log(report);
this._emitter.emit('sync', report);
this._emitter.emit('sync-'+frame.mac, report);
};
manual_sync_check_in(payload, frame){
const rep_buffer = Buffer.from(frame.data);
const sensor_type = rep_buffer.readUInt16BE(5);
// const temp_fly_message = {
// mac: frame.mac,
// type: 114,
// mode: 'PGM',
// }
// this._emitter.emit('sensor_mode', temp_fly_message);
// this._emitter.emit('sensor_mode-'+frame.mac, temp_fly_message);
const values = this.sensor_libs[sensor_type].sync_parse(rep_buffer);
try{
const report = {
type: 'manual_sync_check_in',
address: frame.mac,
sensor_type: sensor_type,
payload: {
type: 'manual_sync_check_in',
address: frame.mac,
sensor_type: sensor_type,
...values,
},
description: 'Manual Sync Check-in received from sensor. This check-in reports sensor information and allows for sync initialization if configuration changes are necessary.',
'packet_info': frame.receive_options
};
this._emitter.emit('sync', report);
this._emitter.emit('sync-'+frame.mac, report);
}catch(e){
console.log(e);
console.log('Error in manual_sync parsing for sensor type '+sensor_type);
}
};
sync_check_in(payload, frame){
const rep_buffer = Buffer.from(frame.data);
const sensor_type = rep_buffer.readUInt16BE(5);
// const temp_fly_message = {
// mac: frame.mac,
// type: 114,
// mode: 'FLY',
// }
// this._emitter.emit('sensor_mode', temp_fly_message);
// this._emitter.emit('sensor_mode-'+frame.mac, temp_fly_message);
const values = this.sensor_libs[sensor_type].sync_parse(rep_buffer);
try{
const report = {
type: 'sync_check_in',
address: frame.mac,
sensor_type: sensor_type,
payload: {
type: 'sync_check_in',
address: frame.mac,
sensor_type: sensor_type,
...values,
},
description: 'Check-in received from sensor. This check-in reports sensor information and allows for sync initialization if configuration changes are necessary.',
'packet_info': frame.receive_options
};
this._emitter.emit('sync', report);
this._emitter.emit('sync-'+frame.mac, report);
}catch(e){
console.log(e);
console.log('Error in sync_check_in parsing for sensor type '+sensor_type);
}
};
sync_end(payload, frame){
const rep_buffer = Buffer.from(frame.data);
const sensor_type = rep_buffer.readUInt16BE(5);
const values = this.sensor_libs[sensor_type].sync_parse(rep_buffer);
try{
const report = {
type: 'sync_end',
address: frame.mac,
sensor_type: sensor_type,
payload: {
type: 'sync_end',
address: frame.mac,
sensor_type: sensor_type,
...values,
},
description: 'Sync process finished. Sensor is reporting its new values after Syn and resuming normal operations.',
'packet_info': frame.receive_options
};
this._emitter.emit('sync', report);
this._emitter.emit('sync-'+frame.mac, report);
}catch(e){
console.log(e);
console.log('Error in sync_end parsing for sensor type '+sensor_type);
}
};
sensor_data(payload, frame){
let sensor_type = msbLsb(payload[5], payload[6]);
let battery_percent = ((msbLsb(payload[2], payload[3]) * 0.361) - 269.66).toFixed(2);
let voltage = (msbLsb(payload[2], payload[3]) * 0.00322).toFixed(2);
if(sensor_type == 110 || sensor_type == 111 || sensor_type == 112 || sensor_type == 114 || sensor_type == 543){
const vMin = 2.5;
const vMax = 3.3;
if (voltage >= vMax){
battery_percent = '100';
} else if (voltage <= vMin){
battery_percent = '0';
} else {
const scale = 5.0; // tuning factor for steepness
const percent = 100 * (1 - Math.exp(-scale * (voltage - vMin)));
battery_percent = (Math.min(100, Math.max(0, percent))).toFixed(2);
}
}
var parsed = {
nodeId: payload[0],
firmware: payload[1],
battery: voltage,
// battery_percent: (msbLsb(payload[2], payload[3]) * 0.537 - 449.9).toFixed(2),
battery_percent: battery_percent,
counter: payload[4],
sensor_type: sensor_type
};
// #OTF
var otf_devices = [4,12,21,23,26,29,30,32,33,35,39,44,45,48,52,53,54,55,56,58,74,76,78,79,80,81,82,84,88,89,90,91,93,97,98,99,101,102,103,105,106,107,108,109,110,111,112,114,117,118,119,120,121,122,123,124,125,126,180,181,202,211,217,270,519,520,521,531,535,536,537,538,539,540,541,542,543,545,554,1010,1011];
if(otf_devices.includes(parsed.sensor_type)){
// If the message says FLY and there is not FLY timer in progress.
if(payload[8] == 70 && payload[9] == 76 && payload[10] == 89) {
parsed.payload = "Fly command";
return parsed;
}
}
if(frame.data[9] == 85 && frame.data[10] == 80 && frame.data[11] == 84 && frame.data[12] == 72 && frame.data[13] == 87 && frame.data[14] == 82 && frame.data[15] == 78) {
parsed.payload = "Upthwrn command";
return parsed;
}
// Sensor type 515 has a unique OTF that is indicated by a reserve byte value with MSb of 1
if(parsed.sensor_type == 515){
// MSb of reserve byte indicates sub-unit/ct firmware.
parsed.ct_firmware = payload[7] >> 4;
// If first bit in reserve is 1 AND current bank equals total banks
if(payload[7] & 1 && payload[8] == payload[9]){
this._emitter.emit('set_destination_address'+frame.mac, frame.mac);
this._emitter.emit('set_destination_address'+parsed.sensor_type, frame.mac);
parsed.otf_515 = true;
} else{
parsed.otf_515 = false;
}
}
if(parsed.sensor_type == 101){
// If the message says FLY and there is not FLY timer in progress.
// if(payload[8] == 70 && payload[9] == 76 && payload[10] == 89 && !this.hasOwnProperty('fly_101_in_progress')) {
// this.fly_101_in_progress = true;
// setTimeout(() => {this.config_set_rtc_101('00:00:00:00:00:00:FF:FF')}, 1000);
// return;
// }
var deviceAddr = frame.mac;
var firmware = payload[1];
var hour = payload[11];
var minute = payload[12];
if(firmware == 0){
var expected_packets = payload[15];
var current_packet = payload[16];
var sdata_start = 17;
}
else{
// Added external temp in firmware 1 inserted at item 15
var expected_packets = payload[17];
var current_packet = payload[18];
var sdata_start = 19;
}
if(globalDevices.hasOwnProperty(deviceAddr)){
// if a packet is already stored with the same packet ID, or if packet ID is 1, or if current packet ID is not one more than last packet ID
if(current_packet == 1 && expected_packets != 1) {
if(current_packet in globalDevices[deviceAddr].data || !(((current_packet&127)-1) in globalDevices[deviceAddr].data)) {
console.log('bad packet breakdown, deleting stream. Current packet:');
console.log(current_packet);
console.log('Total Expected Packets:');
console.log(expected_packets);
if(this.hasOwnProperty('failure_no')){
this.failure_no = this.failure_no + 1;
}
else{
this.failure_no = 1;
}
if(this.hasOwnProperty('failure_no')){
console.log('####falure no');
console.log(this.failure_no);
}
delete globalDevices[deviceAddr];
if(current_packet != 1){
return;
} else{
this.build_101_data(payload, deviceAddr, hour, minute, sdata_start, current_packet, firmware);
return;
}
}
}
if(expected_packets == 1){
this.build_101_data(payload, deviceAddr, hour, minute, sdata_start, current_packet, firmware);
} else{
globalDevices[deviceAddr].data[current_packet] = payload.slice(sdata_start);
}
if(Object.keys(globalDevices[deviceAddr].data).length == expected_packets){
var raw_data = new Array();
for(const packet in globalDevices[deviceAddr].data){
raw_data = raw_data.concat(globalDevices[deviceAddr].data[packet]);
}
var label = 0;
// var fft = {
// data: new Array()
// // test: new Array()
// };
var fft = new Array();
var fft_concat = {};
var en_axis_data = {};
switch (globalDevices[deviceAddr].en_axis){
case 1:
en_axis_data.x_offset = 0;
en_axis_data.increment = 2;
break;
case 2:
en_axis_data.y_offset = 0;
en_axis_data.increment = 2;
break;
case 3:
en_axis_data.x_offset = 0;
en_axis_data.y_offset = 2;
en_axis_data.increment = 4;
break;
case 4:
en_axis_data.z_offset = 0;
en_axis_data.increment = 2;
break;
case 5:
en_axis_data.x_offset = 0;
en_axis_data.z_offset = 2;
en_axis_data.increment = 4;
break;
case 6:
en_axis_data.y_offset = 0;
en_axis_data.z_offset = 2;
en_axis_data.increment = 4;
break;
case 7:
en_axis_data.x_offset = 0;
en_axis_data.y_offset = 2;
en_axis_data.z_offset = 4;
en_axis_data.increment = 6;
break;
default:
en_axis_data.increment = 0;
}
var fsr_mult = 0.000305185;
var fsr_text = "";
switch(globalDevices[deviceAddr].fsr){
case 0:
fsr_mult = 0.000305185;
break;
case 1:
fsr_mult = 0.00061037;
break;
case 2:
fsr_mult = 0.0012207;
break;
}
switch(globalDevices[deviceAddr].fsr){
case 0:
fsr_text = "10g";
break;
case 1:
fsr_text = "20g";
break;
case 2:
fsr_text = "40g";
break;
}
for(var i = 0; i < raw_data.length; i+=en_axis_data.increment){
label++;
fft_concat[label] = {};
if('x_offset' in en_axis_data){
fft_concat[label].x = parseFloat((signInt(((raw_data[i+en_axis_data.x_offset]<<8)+(raw_data[i+en_axis_data.x_offset+1])), 16)*fsr_mult).toFixed(5));
}
if('y_offset' in en_axis_data){
fft_concat[label].y = parseFloat((signInt(((raw_data[i+en_axis_data.y_offset]<<8)+(raw_data[i+en_axis_data.y_offset+1])), 16)*fsr_mult).toFixed(5));
}
if('z_offset' in en_axis_data){
fft_concat[label].z = parseFloat((signInt(((raw_data[i+en_axis_data.z_offset]<<8)+(raw_data[i+en_axis_data.z_offset+1])), 16)*fsr_mult).toFixed(5));
}
}
var fft_concat_obj = {
time_id: globalDevices[deviceAddr].hour +':'+ globalDevices[deviceAddr].minute,
mac_address: deviceAddr,
en_axis: globalDevices[deviceAddr].en_axis,
odr: globalDevices[deviceAddr].odr,
device_temp: globalDevices[deviceAddr].device_temp,
fsr: globalDevices[deviceAddr].fsr,
data: fft_concat
};
if(firmware > 0){
fft_concat_obj.probe_temp = globalDevices[deviceAddr].probe_temp;
}
parsed.sensor_data = fft_concat_obj;
parsed.raw_packets = globalDevices[deviceAddr].data;
parsed.raw_data = raw_data;
delete globalDevices[deviceAddr];
if(this.hasOwnProperty('failure_no')){
console.log('####falure no');
console.log(this.failure_no);
}
return parsed;
}
else{
return;
}
}else{
this.build_101_data(payload, deviceAddr, hour, minute, sdata_start, current_packet, firmware);
return;
}
}
if(parsed.sensor_type == 102){
// If the message says FLY and there is not FLY timer in progress.
// if(payload[8] == 70 && payload[9] == 76 && payload[10] == 89 && !this.hasOwnProperty('fly_101_in_progress')) {
// this.fly_101_in_progress = true;
// this.sensor_pool[frame.mac].mode = "FLY";
// this._emitter.emit('sensor_mode-'+frame.mac, this.sensor_pool[frame.mac]);
// // setTimeout(() => {this.config_set_rtc_101('00:00:00:00:00:00:FF:FF')}, 1000);
// setTimeout(() => {this.config_set_rtc_101(frame.mac)}, 1000);
//
// return;
// }
var deviceAddr = frame.mac;
var firmware = payload[1];
var hour = payload[9];
var minute = payload[10];
var expected_packets = payload[15];
var current_packet = payload[16];
var sdata_start = 17;
if(globalDevices.hasOwnProperty(deviceAddr) || expected_packets == 1){
// if(expected_packets == 1){
// this.build_102_data(payload, deviceAddr, hour, minute, sdata_start, current_packet, firmware);
// }
// if a packet is already stored with the same packet ID,
// or if packet ID is 1,
// or if current packet ID is not one more than last packet ID
if(current_packet == 1 && expected_packets != 1) {
if(current_packet in globalDevices[deviceAddr].data || !(((current_packet&127)-1) in globalDevices[deviceAddr].data)) {
console.log('bad packet breakdown, deleting stream. Current packet:');
console.log(current_packet);
console.log('Total Expected Packets:');
console.log(expected_packets);
if(this.hasOwnProperty('failure_no')){
this.failure_no = this.failure_no + 1;
}
else{
this.failure_no = 1;
}
if(this.hasOwnProperty('failure_no')){
console.log('####falure no');
console.log(this.failure_no);
}
delete globalDevices[deviceAddr];
if(current_packet != 1){
return;
} else{
this.build_102_data(payload, deviceAddr, hour, minute, sdata_start, current_packet, firmware);
return;
}
}
}
if(expected_packets == 1){
this.build_102_data(payload, deviceAddr, hour, minute, sdata_start, current_packet, firmware);
} else{
globalDevices[deviceAddr].data[current_packet] = payload.slice(sdata_start);
}
if(Object.keys(globalDevices[deviceAddr].data).length == expected_packets){
var raw_data = new Array();
for(const packet in globalDevices[deviceAddr].data){
raw_data = raw_data.concat(globalDevices[deviceAddr].data[packet]);
}
var label = 0;
var fft = new Array();
var fft_concat = {};
for(var i = 0; i < raw_data.length; i+=2){
label++;
fft_concat[label] = {'v': parseFloat((signInt(((raw_data[i]<<8)+(raw_data[i+1])), 16)*.00322).toFixed(5))};
}
var fft_concat_obj = {
time_id: globalDevices[deviceAddr].hour +':'+ globalDevices[deviceAddr].minute,
mac_address: deviceAddr,
// en_axis: globalDevices[deviceAddr].en_axis,
odr: globalDevices[deviceAddr].odr,
device_temp: globalDevices[deviceAddr].device_temp,
probe_temp: globalDevices[deviceAddr].probe_temp,
data: fft_concat
};
parsed.sensor_data = fft_concat_obj;
// parsed.sensor_data = fft;
parsed.raw_packets = globalDevices[deviceAddr].data;
parsed.raw_data = raw_data;
// var data = globalDevices[deviceAddr];
delete globalDevices[deviceAddr];
if(this.hasOwnProperty('failure_no')){
console.log('####falure no');
console.log(this.failure_no);
}
return parsed;
}
else{
return;
}
}else{
this.build_102_data(payload, deviceAddr, hour, minute, sdata_start, current_packet, firmware);
return;
}
}
if(payload.length == 179){
if(msbLsb(payload[2], payload[3]) == 40){
delete parsed.firmware;
delete parsed.battery;
delete parsed.battery_percent;
delete parsed.counter;
// parsed.frame_id = payload[1];
parsed.sensor_type = msbLsb(payload[2], payload[3]);
var odr;
switch(payload[4]){
case 5:
odr = 400;
break;
case 6:
odr = 800;
break;
case 7:
odr = 1600;
break;
case 12:
odr = 3200;
break;
case 13:
odr = 6400;
break;
case 14:
odr = 12800;
break;
case 15:
odr = 25600;
break;
default:
odr = 0;
}
// parsed.sensor_data = {data_type: 'FFT', data: payload.slice(5)};
var deviceAddr = frame.mac;
if(deviceAddr in globalDevices){
globalDevices[deviceAddr] = globalDevices[deviceAddr].concat(payload.slice(5));
if(globalDevices[deviceAddr].length == 2088){
var label = 1;
var fft = {};
fft['odr'] = odr;
fft['data_type'] = 'FFT';
for(var i = 0; i < 2064; i+=6){
var xLabel = 'x'+label;
var yLabel = 'y'+label;
var zLabel = 'z'+label;
label++;
fft[xLabel] = ((globalDevices[deviceAddr][i]<<8)+(globalDevices[deviceAddr][i+1]&255))/2048;
fft[yLabel] = ((globalDevices[deviceAddr][i+2]<<8)+(globalDevices[deviceAddr][i+3]&255))/2048;
fft[zLabel] = ((globalDevices[deviceAddr][i+4]<<8)+(globalDevices[deviceAddr][i+5]&255))/2048;
}
parsed.sensor_data = fft;
parsed.sensor_data.xbee_data = globalDevices[deviceAddr];
delete globalDevices[deviceAddr];
return parsed;
}else{
return;
}
}else{
globalDevices[deviceAddr] = payload.slice(5);
return;
}
}
}else{
if(typeof this.sensor_types[parsed.sensor_type] == 'undefined' && typeof this.sensor_libs[parsed.sensor_type] == 'undefined'){
parsed.sensor_data = {
type: 'unknown',
data: payload.slice(8)
};
// #OTF
}else if(parsed.sensor_type == 21 || parsed.sensor_type == 33 || parsed.sensor_type == 39 || parsed.sensor_type == 29 || parsed.sensor_type == 54 || parsed.sensor_type == 55 || parsed.sensor_type == 80 || parsed.sensor_type == 81 || parsed.sensor_type == 82 || parsed.sensor_type == 84 || parsed.sensor_type == 97 || parsed.sensor_type == 98 || parsed.sensor_type == 99 || parsed.sensor_type == 103 || parsed.sensor_type == 110 || parsed.sensor_type == 111 || parsed.sensor_type == 112 || parsed.sensor_type == 114 || parsed.sensor_type == 117 || parsed.sensor_type == 118 || parsed.sensor_type == 128 || parsed.sensor_type == 180 || parsed.sensor_type == 181 || parsed.sensor_type == 202 || parsed.sensor_type == 217 || parsed.sensor_type == 515 || parsed.sensor_type == 519 || parsed.sensor_type == 531 || parsed.sensor_type == 537 || parsed.sensor_type == 538 || parsed.sensor_type == 543 || parsed.sensor_type == 545 || parsed.sensor_type == 554){
// new export based parsers
if(this.sensor_libs.hasOwnProperty(parsed.sensor_type)){
parsed.sensor_data = this.sensor_libs[parsed.sensor_type].parse(payload, parsed, frame.mac);
parsed.sensor_name = this.sensor_libs[parsed.sensor_type].name;
}else{
parsed.sensor_data = this.sensor_types[parsed.sensor_type].parse(payload, parsed, frame.mac);
parsed.sensor_name = this.sensor_types[parsed.sensor_type].name;
}
if(!parsed.sensor_data){
return;
}
}
else{
// new export based parsers
if(this.sensor_libs.hasOwnProperty(parsed.sensor_type)){
parsed.sensor_data = this.sensor_libs[parsed.sensor_type].parse(payload.slice(8), payload);
parsed.sensor_name = this.sensor_libs[parsed.sensor_type].name;
}else{
parsed.sensor_data = this.sensor_types[parsed.sensor_type].parse(payload.slice(8), payload);
parsed.sensor_name = this.sensor_types[parsed.sensor_type].name;
}
}
}
return parsed;
}
build_sync_command(configs, is_wireless_node = false) {
const config_map = this.sensor_libs[configs.sensor_type].get_config_map(configs.firmware_version);
// Get the buffer size defined in library for this specific firmware
const size = this.sensor_libs[configs.sensor_type].get_write_buffer_size(configs.firmware_version);
const buf = Buffer.alloc(size, 0);
// insert command header
buf.set([0x6c, 0x00, 0x00], 0);
let desired_configs = {};
if(is_wireless_node){
desired_configs = { ...configs.reported_configs };
}else{
desired_configs = { ...configs.reported_configs, ...configs.desired_configs };
}
for (const [key, value] of Object.entries(desired_configs)) {
const map_item = config_map[key];
if (!map_item || map_item.write_index === undefined) continue;
const { write_index: idx, validator: { type } } = map_item;
switch (type) {
case 'uint8': buf.writeUInt8(Number(value), idx); break;
case 'uint16be': buf.writeUInt16BE(Number(value), idx); break;
case 'uint32be': buf.writeUInt32BE(Number(value), idx); break;
case 'hex':
Buffer.from(value, 'hex').copy(buf, idx);
case 'mac':
Buffer.from(value, 'hex').copy(buf, idx);
break;
}
}
return buf;
};
send_sync_configs(addr, configs){
console.log('send_sync_configs command');
// [...] converts the buffer to an array of integers, which is the expected format for the radio
const packet = [...this.build_sync_command(configs)];
console.log('Built sync packet: ');
console.log(packet);
return this.config_send_sync(addr, packet);
};
get_intended_wireless_node_configs(data, configs){
const config_map = this.sensor_libs[data.payload.machine_values.sensor_type].get_config_map(data.payload.machine_values.firmware_version);
const html_map = {};
for(const [key, value] of Object.entries(config_map)){
if(value.html_id){
html_map[value.html_id] = key;
}
}
const response = {};
for (let [key, value] of Object.entries(configs)) {
// skip anything with includes_active since those are just indicators for whether or not to include the config item
if(!key.includes('_active')){
const is_node_id_or_delay = key === 'node_id' || key === 'delay';
let active_key = '';
if(is_node_id_or_delay){
active_key = 'node_id_delay_active';
}else{
active_key = key+'_active';
}
if(Object.hasOwn(html_map, key) && configs[active_key] === true){
const map_item = config_map[html_map[key]];
if (!map_item || map_item.write_index === undefined) continue;
switch (config_map[html_map[key]].validator.type) {
case 'hex':
// ensure hex values are even length and do not include 0x
value = value.replace(/:/g, '').toLowerCase();
break;
case 'mac':
value = value.replace(/:/g, '').toLowerCase();
break;
}
response[html_map[key]] = map_item;
response[html_map[key]].html_value = value;
}
}
}
return response;
};
build_sync_command_wireless_node(data, html_map, api_configs) {
console.log('build_sync_command_wireless_node');
// Get the buffer size defined in library for this specific firmware
// const size = this.sensor_libs[data.payload.sensor_type].get_write_buffer_size(data.payload.firmware_version);
// const buf = Buffer.alloc(size, 0);
// insert command header
// buf.set([0x6c, 0x00, 0x00], 0);
// const desired_configs = { ...configs.reported_configs, ...configs.desired_configs };
const buf = this.build_sync_command(api_configs, true);
for (const [key, value] of Object.entries(html_map)) {
if (value.write_index === undefined) continue;
const { write_index: idx, validator: { type } } = value;
switch (type) {
case 'uint8': buf.writeUInt8(Number(value.html_value), idx); break;
case 'uint16be': buf.writeUInt16BE(Number(value.html_value), idx); break;
case 'uint32be': buf.writeUInt32BE(Number(value.html_value), idx); break;
case 'hex':
Buffer.from(value.html_value, 'hex').copy(buf, idx);
break;
case 'mac':
Buffer.from(value.html_value, 'hex').copy(buf, idx);
break;
}
}
return buf;
}
send_sync_config_wireless_node(data, configs, api_configs){
console.log('send_sync_config_wireless_node command');
// [...] converts the buffer to an array of integers, which is the expected format for the radio
const packet = [...this.build_sync_command_wireless_node(data, configs, api_configs)];
console.log('Built sync packet: ');
console.log(packet);
return this.config_send_sync(data.address, packet);
};
firmware_set_to_ota_mode(sensor_mac){
console.log('firmware_set_to_ota_mode');
var packet = [245, 56, 0, 0, 0];
return this.config_send(sensor_mac, packet, {}, 5000);
// return this.config_send(sensor_mac, packet);
}
// TODO no code basis
firmware_exit_ota_mode(sensor_mac){
console.log('firmware_exit_ota_mode');
var packet = [245, 57, 0, 0, 0];
return this.config_send(sensor_mac, packet);
}
firmware_request_manifest(sensor_mac){
console.log('firmware_request_manifest');
var packet = [245, 60, 0, 0, 0];
return this.config_send(sensor_mac, packet, {}, 1500, 500);
}
firmware_send_manifest(sensor_mac, manifest){
console.log('firmware_send_manifest');
// sensor_mac = "00:00:00:00:00:00:ff:ff";
let packet = [245, 58, 0, 0, 0].concat(Array.prototype.slice.call(manifest));
return this.config_send(sensor_mac, packet, {}, 1500, 500);
}
firmware_send_manifest_v13(sensor_mac, manifest){
console.log('firmware_send_manifest_v13');
// sensor_mac = "00:00:00:00:00:00:ff:ff";
let packet = [245, 58, 0, 0, 0].concat(Array.prototype.slice.call(manifest));
return this.firmware_send_v13(sensor_mac, packet, {}, 7000, 140, true);
}
firmware_send_chunk(sensor_mac, offset, chunk){
console.log('firmware_send_chunk');
// sensor_mac = "00:00:00:00:00:00:ff:ff";
let packet = [245, 59, 0, 0, 0].concat(offset, Array.prototype.slice.call(chunk));
// console.log(packet);
return this.config_send(sensor_mac, packet);
}
firmware_request_last_segment(sensor_mac){
console.log('firmware_request_last_segment');
let packet = [245, 61, 0, 0, 0];
// console.log(packet);
return this.config_send(sensor_mac, packet);
}
config_reboot_sensor(sensor_mac){
console.log('config_reboot_sensor: '+sensor_mac)
var packet = [247, 64, 0, 0, 0];
return this.config_send(sensor_mac, packet);
}
config_set_broadcast(sensor_mac){
return config_set_destination(sensor_mac, 0x0000FFFF);
}
config_set_destination(sensor_mac, modem_mac){
console.log('config_set_destination');
console.log(modem_mac);
var packet = [247, 3, 0, 0, 0];
var bytes = int2Bytes(modem_mac, 4);
packet.push(...bytes);
console.log(packet);
return this.config_send(sensor_mac, packet);
}
config_set_id_delay(sensor_mac, node_id, delay_s){
console.log('config_set_id_delay');
var packet = [247, 2, 0, 0, 0, node_id];
var delay_b = int2Bytes(delay_s, 3);
packet.push(...delay_b);
console.log(packet);
return this.config_send(sensor_mac, packet);
}
config_set_only_delay(sensor_mac, delay_s){
console.log('config_set_only_delay');
var packet = [247, 2, 0, 0, 0, 0];
var delay_b = int2Bytes(delay_s, 3);
packet.push(...delay_b);
console.log(packet);
return this.config_send(sensor_mac, packet);
}
config_set_power(sensor_mac, pwr){
var packet = [247, 4, 0, 0, 0, pwr];
return this.config_send(sensor_mac, packet);
}
config_set_pan_id(sensor_mac, pan_id){
var packet = [247, 5, 0, 0, 0];
packet.push(...int2Bytes(pan_id, 2));
return this.config_send(sensor_mac, packet);
}
config_set_retries(sensor_mac, retries){
var packet = [247, 6, 0, 0, 0, retries];
return this.config_send(sensor_mac, packet);
}
config_set_change_detection(sensor_mac, enabled, perc, interval){
console.log('config_set_change_detection_ch1');
if(!perc) perc = 0;
if(!interval) interval = 0;
var packet = [247, 7, 0, 0, 0, enabled, perc, interval >> 16, (interval >> 8) & 255, interval & 255];
return this.config_send(sensor_mac, packet);
}
config_set_change_detection_ch2(sensor_mac, enabled, perc, interval){
console.log('config_set_change_detection_ch2');
if(!perc) perc = 0;
if(!interval) interval = 0;
var packet = [247, 8, 0, 0, 0, enabled, perc, interval >> 16, (interval >> 8) & 255, interval & 255];
return this.config_send(sensor_mac, packet);
}
config_set_change_detection_ch3(sensor_mac, enabled, perc, interval){
console.log('config_set_change_detection_ch3');
if(!perc) perc = 0;
if(!interval) interval = 0;
var packet = [247, 9, 0, 0, 0, enabled, perc, interval >> 16, (interval >> 8) & 255, interval & 255];
return this.config_send(sensor_mac, packet);
}
config_set_bp_altitude(sensor_mac, alt){
var packet = [244, 1, 0, 0, 0, alt >> 8, alt & 255];
return this.config_send(sensor_mac, packet);
}
config_set_bp_pressure(sensor_mac, press){
var packet = [244, 4, 0, 0, 0, press >> 8, press & 255];
return this.config_send(sensor_mac, packet);
}
config_set_bp_temp_precision(sensor_mac, prec){
var packet = [244, 2, 0, 0, 0, prec];
return this.config_send(sensor_mac, packet);
}
config_set_bp_press_precision(sensor_mac, prec){
var packet = [244, 3, 0, 0, 0, prec];
return this.config_send(sensor_mac, packet);
}
config_set_amgt_accel(sensor_mac, range){
var packet = [244, 1, 0, 0, 0, range];
return this.config_send(sensor_mac, packet);
}
config_set_amgt_magnet(sensor_mac, gain){
var packet = [244, 2, 0, 0, 0, gain];
return this.config_send(sensor_mac, packet);
}
config_set_amgt_gyro(sensor_mac, scale){
var packet = [244, 3, 0, 0, 0, scale];
return this.config_send(sensor_mac, packet);
}
config_set_filtering(sensor_mac, enable){
var packet = [244, 2, 0, 0, 0, enable];
return this.config_send(sensor_mac, packet);
}
config_set_data_rate(sensor_mac, data_rate){
var packet = [244, 3, 0, 0, 0, data_rate];
return this.config_send(sensor_mac, packet);
}
config_set_time_series(sensor_mac, time_series){
var packet = [244, 8, 0, 0, 0, time_series];
return this.config_send(sensor_mac, packet);
}
config_set_reading_type(sensor_mac, reading_type){
var packet = [244, 4, 0, 0, 0, reading_type];
return this.config_send(sensor_mac, packet);
}
config_set_motion_threshold_46(sensor_mac, value){
console.log('config_set_motion_threshold_46');
let packet = [244, 1, 0, 0, 0];
let threshold = int2Bytes((value), 4);
packet.push(...threshold);
console.log(packet);
return this.config_send(sensor_mac, packet);
}
config_set_acceleration_range_24(sensor_mac, value){
console.log('config_set_acceleration_range_24');
var packet = [244, 1, 0, 0, 0, value];
console.log(packet);
return this.config_send(sensor_mac, packet);
}
config_set_periodic_check_rate_76(sensor_mac, value){
console.log('config_set_periodic_check_rate');
let rate = int2Bytes((value), 2);
var packet = [244, 32, 0, 0, 0];
packet.push(...rate);
console.log(packet);
return this.config_send(sensor_mac, packet);
}
config_set_ppm_threshold_76(sensor_mac, value){
console.log('config_set_ppm_threshold_76');
let rate = int2Bytes((value), 2);
var packet = [244, 36, 0, 0, 0];
// packet.push(...rate);
console.log(packet);
return this.config_send(sensor_mac, packet);
}
config_set_alert_duration_76(sensor_mac, value){
console.log('config_set_alert_duration_76');
var packet = [244, 38, 0, 0, value];
// packet.push(...rate);
console.log(packet);
return this.config_send(sensor_mac, packet);
}
config_set_sensor_boot_time_76(sensor_mac, value){
console.log('config_set_sensor_boot_time_76');
var packet = [244, 36, 0, 0, 0, value];
console.log(packet);
return this.config_send(sensor_mac, packet);
}
config_set_data_rate_24(sensor_mac, value){
console.log('config_set_data_rate_24');
var packet = [244, 2, 0, 0, 0, value];
console.log(packet);
return this.config_send(sensor_mac, packet);
}
config_set_threshold_24(sensor_mac, value){
console.log('config_set_threshold_24');
var packet = [244, 3, 0, 0, 0, value];
console.log(packet);
return this.config_send(sensor_mac, packet);
}
config_set_duration_24(sensor_mac, value){
console.log('config_set_duration_24');
var packet = [244, 4, 0, 0, 0, value];
console.log(packet);
return this.config_send(sensor_mac, packet);
}
config_set_interrupt_24(sensor_mac, value){
console.log('config_set_interrupt_24');
var packet = [244, 9, 0, 0, 0, value];
console.log(packet);
return this.config_send(sensor_mac, packet);
}
// config_set_impact_accel(sensor_mac, range){
// var packet = [244, 1, 0, 0, 0, range];
// return this.config_send(sensor_mac, packet);
// }
// config_set_impact_data_rate(sensor_mac, rate){
// var packet = [244, 2, 0, 0, 0, rate];
// return this.config_send(sensor_mac, packet);
// }
// config_set_impact_threshold(sensor_mac, threshold){
// var packet = [244, 3, 0, 0, 0, threshold];
// return this.config_send(sensor_mac, packet);
// }
// config_set_impact_duration(sensor_mac, duration){
// var packet = [244, 4, 0, 0, 0, duration];
// return this.config_send(sensor_mac, packet);
// }
config_set_sensor_forced_calibration(sensor_mac, value){
var packet = [244, 31, 0, 0, 0];
var cal_val = int2Bytes(value, 2);
packet.push(...cal_val);
return this.config_send(sensor_mac, packet);
}
config_set_sensor_forced_calibration_535(sensor_mac){
console.log('config_set_sensor_forced_calibration_535');
// convert before processing
var packet = [244, 32, 0, 0, 0];
return this.config_send(sensor_mac, packet);
}
config_set_sensor_temperature_offset_44(sensor_mac, value){
console.log('config_set_sensor_temperature_offset_44');
// convert before processing
value = value * 100;
var packet = [244, 30, 0, 0, 0];
var cal_val = int2Bytes(value, 2);
packet.push(...cal_val);
console.log(packet);
return this.config_send(sensor_mac, packet);
}
config_set_output_data_rate_p2_81(sensor_mac, output_rate){
console.log('config_set_output_data_rate_p2_81');
var packet = [244, 79, 0, 0, 101, 36, output_rate];
console.log(packet);
return this.config_send(sensor_mac, packet);
}
config_set_sampling_duration_p2_81(sensor_mac, sampling_duration){
console.log('config_set_sampling_duration_p2_81');
var packet = [244, 79, 0, 0, 101, 38, sampling_dur