Last active
September 5, 2018 18:50
-
-
Save alnjxn/34ec8c58acf87f9ae8a9c96a656cbfed to your computer and use it in GitHub Desktop.
Elsys Packet Decoder / Encoder for TTN
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Converter(decoded, port) { | |
// Merge, split or otherwise | |
// mutate decoded fields. | |
var converted = decoded; | |
// if (port === 1 && (converted.led === 0 || converted.led === 1)) { | |
// converted.led = Boolean(converted.led); | |
// } | |
return converted; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Decoder(bytes, port) { | |
function bin16dec(bin) { | |
var num = bin&0xFFFF; | |
if (0x8000 & num) { | |
num = - (0x010000 - num); | |
} | |
return num; | |
} | |
function bin8dec(bin) { | |
var num = bin&0xFF; | |
if (0x80 & num) { | |
num = - (0x0100 - num); | |
} | |
return num; | |
} | |
function hexToBytes(hex) { | |
for (var bytes = [], c = 0; c < hex.length; c += 2) { | |
bytes.push(parseInt(hex.substr(c, 2), 16)); | |
} | |
return bytes; | |
} | |
var decoded = {}; | |
if (port === 5) { | |
var TYPE_TEMP = 0x01; //temp 2 bytes -3276.8°C -->3276.7°C | |
var TYPE_RH = 0x02; //Humidity 1 byte 0-100% | |
var TYPE_ACC = 0x03; //acceleration 3 bytes X,Y,Z -128 --> 127 +/-63=1G | |
var TYPE_LIGHT = 0x04; //Light 2 bytes 0-->65535 Lux | |
var TYPE_MOTION = 0x05; //No of motion 1 byte 0-255 | |
var TYPE_CO2 = 0x06; //Co2 2 bytes 0-65535 ppm | |
var TYPE_VDD = 0x07; //VDD 2byte 0-65535mV | |
var TYPE_ANALOG1 = 0x08; //VDD 2byte 0-65535mV | |
var TYPE_GPS = 0x09; //3bytes lat 3bytes long binary | |
var TYPE_PULSE1 = 0x0A; //2bytes relative pulse count | |
var TYPE_PULSE1_ABS = 0x0B; //4bytes no 0->0xFFFFFFFF | |
var TYPE_EXT_TEMP1 = 0x0C; //2bytes -3276.5C-->3276.5C | |
var TYPE_EXT_DIGITAL = 0x0D; //1bytes value 1 or 0 | |
var TYPE_EXT_DISTANCE = 0x0E; //2bytes distance in mm | |
var TYPE_ACC_MOTION = 0x0F; //1byte number of vibration/motion | |
var TYPE_IR_TEMP = 0x10; //2bytes internal temp 2bytes external temp -3276.5C-->3276.5C | |
var TYPE_OCCUPANCY = 0x11; //1byte data | |
var TYPE_WATERLEAK = 0x12; //1byte data 0-255 | |
var TYPE_GRIDEYE = 0x13; //65byte temperature data 1byte ref+64byte external temp | |
var TYPE_PRESSURE = 0x14; //4byte pressure data (hPa) | |
var TYPE_SOUND = 0x15; //2byte sound data (peak/avg) | |
var TYPE_PULSE2 = 0x16; //2bytes 0-->0xFFFF | |
var TYPE_PULSE2_ABS = 0x17; //4bytes no 0->0xFFFFFFFF | |
var TYPE_ANALOG2 = 0x18; //2bytes voltage in mV | |
var TYPE_EXT_TEMP2 = 0x19; //2bytes -3276.5C-->3276.5C | |
for (i = 0; i < bytes.length; i++) { | |
switch(bytes[i]) { | |
case TYPE_TEMP: //Temperature | |
var temp = (bytes[i+1]<<8) | (bytes[i+2]); | |
temp = bin16dec(temp); | |
decoded.temperature = temp / 10; | |
i += 2; | |
break; | |
case TYPE_RH: //Humidity | |
var rh = (bytes[i+1]); | |
decoded.humidity = rh; | |
i += 1; | |
break; | |
case TYPE_ACC: //Acceleration | |
decoded.x = bin8dec(bytes[i+1]); | |
decoded.y = bin8dec(bytes[i+2]); | |
decoded.z=bin8dec(bytes[i+3]); | |
i += 3; | |
break; | |
case TYPE_LIGHT: //Light | |
decoded.light = (bytes[i+1]<<8) | (bytes[i+2]); | |
i += 2; | |
break; | |
case TYPE_MOTION: //Motion sensor(PIR) | |
decoded.motion = (bytes[i+1]); | |
i += 1; | |
break; | |
case TYPE_CO2: //CO2 | |
decoded.co2 = (bytes[i+1]<<8) | (bytes[i+2]); | |
i += 2; | |
break; | |
case TYPE_VDD: //Battery level | |
decoded.vdd = (bytes[i+1]<<8) | (bytes[i+2]); | |
i += 2; | |
break; | |
case TYPE_ANALOG1: //Analog input 1 | |
decoded.analog1 = (bytes[i+1]<<8) | (bytes[i+2]); | |
i += 2; | |
break; | |
case TYPE_GPS: //gps | |
decoded.lat = (bytes[i+1]<<16) | (bytes[i+2]<<8) | (bytes[i+3]); | |
decoded.long = (bytes[i+4]<<16) | (bytes[i+5]<<8) | (bytes[i+6]); | |
i += 6; | |
break; | |
case TYPE_PULSE1: //Pulse input 1 | |
decoded.pulse1 = (bytes[i+1]<<8) | (bytes[i+2]); | |
i += 2; | |
break; | |
case TYPE_PULSE1_ABS: //Pulse input 1 absolute value | |
var pulseAbs = (bytes[i+1]<<24) | (bytes[i+2]<<16) | (bytes[i+3]<<8) | (bytes[i+4]); | |
decoded.pulseAbs=pulseAbs; | |
i += 4; | |
break; | |
case TYPE_EXT_TEMP1: //External temp | |
var extTemp = (bytes[i+1]<<8) | (bytes[i+2]); | |
extTemp = bin16dec(extTemp); | |
decoded.externalTemperature = extTemp / 10; | |
i += 2; | |
break; | |
case TYPE_EXT_DIGITAL: //Digital input | |
decoded.digital=(bytes[i+1]); | |
i += 1; | |
break; | |
case TYPE_EXT_DISTANCE: //Distance sensor input | |
decoded.distance=(bytes[i+1]<<8) | (bytes[i+2]); | |
i += 2; | |
break; | |
case TYPE_ACC_MOTION: //Acc motion | |
decoded.accMotion=(bytes[i+1]); | |
i += 1; | |
break; | |
case TYPE_IR_TEMP: //IR temperature | |
var iTemp = (bytes[i+1]<<8) | (bytes[i+2]); | |
iTemp = bin16dec(iTemp); | |
var eTemp = (bytes[i+3]<<8) | (bytes[i+4]); | |
eTemp = bin16dec(eTemp); | |
decoded.irInternalTemperature = iTemp / 10; | |
decoded.irExternalTemperature = eTemp / 10; | |
i += 4; | |
break; | |
case TYPE_OCCUPANCY: //Body occupancy | |
decoded.occupancy = (bytes[i+1]); | |
i += 1; | |
break; | |
case TYPE_WATERLEAK: //Water leak | |
decoded.waterleak = (bytes[i+1]); | |
i += 1; | |
break; | |
case TYPE_GRIDEYE: //Grideye bytes | |
i += 65; | |
break | |
case TYPE_PRESSURE: //External Pressure | |
var press =(bytes[i+1]<<24) | (bytes[i+2]<<16) | (bytes[i+3]<<8) | (bytes[i+4]); | |
decoded.pressure = press / 1000; | |
i += 4; | |
break; | |
case TYPE_SOUND: //Sound | |
decoded.soundPeak = bytes[i+1]; | |
decoded.soundAvg = bytes[i+2]; | |
i += 2; | |
break; | |
case TYPE_PULSE2: //Pulse 2 | |
decoded.pulse2=(bytes[i+1]<<8)|(bytes[i+2]); | |
i += 2; | |
break; | |
case TYPE_PULSE2_ABS: //Pulse input 2 absolute value | |
decoded.pulseAbs2 = (bytes[i+1]<<24) | (bytes[i+2]<<16) | (bytes[i+3]<<8) | (bytes[i+4]); | |
i += 4; | |
break; | |
case TYPE_ANALOG2: //Analog input 2 | |
decoded.analog2 = (bytes[i+1]<<8) | (bytes[i+2]); | |
i += 2; | |
break; | |
case TYPE_EXT_TEMP2: //External temp 2 | |
var extTemp2 = (bytes[i+1]<<8) | (bytes[i+2]); | |
extTemp2 = bin16dec(extTemp2); | |
decoded.externalTemperature2 = extTemp2 / 10; | |
i += 2; | |
break; | |
default: //something is wrong with bytes | |
i = bytes.length; | |
break; | |
} | |
} | |
} | |
if (port === 6) { | |
var TYPE_APPS_KEY = 0x01; //App Session Key 16 byte | |
var TYPE_NWKS_KEY = 0x02; //Network Session Key 16 byte | |
var TYPE_DEV_EUI = 0x03; //Device EUI 8 byte | |
var TYPE_APP_EUI = 0x04; //Application EUI 8 byte | |
var TYPE_APP_KEY = 0x05; //Application Key 16 byte | |
var TYPE_DEV_ADDR = 0x06; //Device Address 4 byte | |
var TYPE_OTA = 0x07; //OTAA 1 byte bool | |
var TYPE_PORT = 0x08; //Port 1 byte | |
var TYPE_MODE = 0x09; //Mode 1 byte | |
var TYPE_ACK = 0x0A; //Acknowledge Messages 1 byte bool | |
var TYPE_DR_DEF = 0x0B; //Data Rate (Default) 1 byte | |
var TYPE_DR_MAX = 0x0C; //Data Rate (Maximum) 1 byte | |
var TYPE_DR_MIN = 0x0D; //Data Rate (Minimum) 1 byte | |
var TYPE_PAYLOAD = 0x0E; //Payload 1 byte | |
var TYPE_POWER = 0x0F; //Power 1 byte | |
var TYPE_EXT_CFG = 0x10; //External Config 1 byte | |
var TYPE_PIR_CFG = 0x11; //PIR Config 1 byte | |
var TYPE_CO2_CFG = 0x12; //CO2 Config 1 byte | |
var TYPE_ACC_CFG = 0x13; //Acceleration Config 4 byte | |
var TYPE_SPL_PER = 0x14; //Sample Period 4 byte | |
var TYPE_TEMP_PER = 0x15; //Temperature Period 4 byte | |
var TYPE_RH_PER = 0x16; //Humidity Period 4 byte | |
var TYPE_LIGHT_PER = 0x17; //Light Period 4 byte | |
var TYPE_PIR_PER = 0x18; //PIR Period 4 byte | |
var TYPE_CO2_PER = 0x19; //CO2 Period 4 byte | |
var TYPE_EXT_PER = 0x1A; //External Period 4 byte | |
var TYPE_EXT_PWR_TIME = 0x1B; //External Power Time 4 byte (ms) | |
var TYPE_TRIG_TIME = 0x1C; //Trigger Time 4 byte (s) | |
var TYPE_ACC_PER = 0x1D; //Acceleration Period 4 byte | |
var TYPE_VDD_PER = 0x1E; //VDD Period 4 byte | |
var TYPE_SEND_PER = 0x1F; //Send Period 4 byte | |
var TYPE_LOCK = 0x20; //Lock Code 4 byte | |
var TYPE_LINK_CHK = 0x22; //Link Threshold, Period 4 byte | |
var TYPE_PRESS_PER = 0x23; //Pressure Period 4 byte | |
var TYPE_SOUND_PER = 0x24; //Sound Period 4 byte | |
var TYPE_LED_EXT = 0xFA; //4 bit ext mode, 4 bit LED mode | |
var TYPE_VERSION = 0xFB; //Version Number 4 byte | |
var TYPE_SLEEP = 0xFC; //Force Sensor Sleep 4 byte (s) | |
var TYPE_GENERIC = 0xFD; //1 byte lenith, x byte NFC string | |
var TYPE_REBOOT = 0xFE; //Reboot 0 bytes | |
decoded.dataRates = {}; | |
decoded.sensorPeriods = {}; | |
decoded.configurations = {}; | |
for (i = 0; i < bytes.length; i++) { | |
switch(bytes[i]) { | |
case TYPE_OTA: //OTA Activation | |
var ota = (bytes[i+1]); | |
decoded.ota = ota ? true : false; | |
i += 1; | |
break; | |
case TYPE_PORT: //Port | |
var port = (bytes[i+1]); | |
port = bin16dec(port); | |
decoded.port = port; | |
i += 1; | |
break; | |
case TYPE_MODE: //Mode | |
var mode = (bytes[i+1]); | |
mode = bin16dec(mode); | |
decoded.mode = mode; | |
i += 1; | |
break; | |
case TYPE_ACK: //Acknowledge | |
var ack = (bytes[i+1]); | |
decoded.ack = ack ? true : false; | |
i += 1; | |
break; | |
case TYPE_DR_DEF: //Default Data Rate | |
var ddr = (bytes[i+1]); | |
ddr = bin16dec(ddr); | |
decoded.dataRates.default = ddr; | |
i += 1; | |
break; | |
case TYPE_DR_MAX: //Maximum Data Rate | |
var maxdr = (bytes[i+1]); | |
maxdr = bin16dec(maxdr); | |
decoded.dataRates.maximum = maxdr; | |
i += 1; | |
break; | |
case TYPE_DR_MIN: //Minimum Data Rate | |
var mindr = (bytes[i+1]); | |
mindr = bin16dec(mindr); | |
decoded.dataRates.minimum = mindr; | |
i += 1; | |
break; | |
case TYPE_PIR_CFG: //PIR Config | |
var pircfg = (bytes[i+1]); | |
pircfg = bin16dec(pircfg); | |
decoded.configurations.pir = pircfg; | |
i += 1; | |
break; | |
case TYPE_CO2_CFG: //CO2 Config | |
var co2cfg = (bytes[i+1]); | |
co2cfg = bin16dec(co2cfg); | |
decoded.configurations.co2 = co2cfg; | |
i += 1; | |
break; | |
case TYPE_ACC_CFG: //Acceleration Config | |
var acccfg = (bytes[i+1]<<24) | (bytes[i+2]<<16) | (bytes[i+3]<<8) | (bytes[i+4]); | |
acccfg = bin16dec(acccfg); | |
decoded.configurations.acc = acccfg; | |
i += 4; | |
break; | |
case TYPE_SPL_PER: //Sample Period | |
var splper = (bytes[i+1]<<24) | (bytes[i+2]<<16) | (bytes[i+3]<<8) | (bytes[i+4]); | |
splper = bin16dec(splper); | |
decoded.sensorPeriods.sample = splper; | |
i += 4; | |
break; | |
case TYPE_TEMP_PER: //Temperature Period | |
var tempper = (bytes[i+1]<<24) | (bytes[i+2]<<16) | (bytes[i+3]<<8) | (bytes[i+4]); | |
tempper = bin16dec(tempper); | |
decoded.sensorPeriods.temperature = tempper; | |
i += 4; | |
break; | |
case TYPE_RH_PER: //Humidity Period | |
var rhper =(bytes[i+1]<<24) | (bytes[i+2]<<16) | (bytes[i+3]<<8) | (bytes[i+4]); | |
rhper = bin16dec(rhper); | |
decoded.sensorPeriods.humidity = rhper; | |
i += 4; | |
break; | |
case TYPE_LIGHT_PER: //Light Period | |
var lightper = (bytes[i+1]<<24) | (bytes[i+2]<<16) | (bytes[i+3]<<8) | (bytes[i+4]); | |
lightper = bin16dec(lightper); | |
decoded.sensorPeriods.light = lightper; | |
i += 4; | |
break; | |
case TYPE_PIR_PER: //PIR Period | |
var pirper = (bytes[i+1]<<24) | (bytes[i+2]<<16) | (bytes[i+3]<<8) | (bytes[i+4]); | |
pirper = bin16dec(pirper); | |
decoded.sensorPeriods.pir = pirper; | |
i += 4; | |
break; | |
case TYPE_CO2_PER: //CO2 Period | |
var co2per = (bytes[i+1]<<24) | (bytes[i+2]<<16) | (bytes[i+3]<<8) | (bytes[i+4]); | |
co2per = bin16dec(co2per); | |
decoded.sensorPeriods.co2 = co2per; | |
i += 4; | |
break; | |
case TYPE_EXT_PER: //External Period | |
var extper = (bytes[i+1]<<24) | (bytes[i+2]<<16) | (bytes[i+3]<<8) | (bytes[i+4]); | |
extper = bin16dec(extper); | |
decoded.sensorPeriods.external = extper; | |
i += 4; | |
break; | |
case TYPE_EXT_PWR_TIME: //External Power Time (ms) | |
var extpwr = (bytes[i+1]<<24) | (bytes[i+2]<<16) | (bytes[i+3]<<8) | (bytes[i+4]); | |
extpwr = bin16dec(extpwr); | |
decoded.extPwrTime = extpwr; | |
i += 4; | |
break; | |
case TYPE_TRIG_TIME: //Trigger Time (s) | |
var trigtime = (bytes[i+1]<<24) | (bytes[i+2]<<16) | (bytes[i+3]<<8) | (bytes[i+4]); | |
trigtime = bin16dec(trigtime); | |
decoded.triggerTime = trigtime; | |
i += 4; | |
break; | |
case TYPE_ACC_PER: //Acceleration Period | |
var accper = (bytes[i+1]<<24) | (bytes[i+2]<<16) | (bytes[i+3]<<8) | (bytes[i+4]); | |
accper = bin16dec(accper); | |
decoded.sensorPeriods.acc = accper; | |
i += 4; | |
break; | |
case TYPE_VDD_PER: //VDD Period | |
var vddper = (bytes[i+1]<<24) | (bytes[i+2]<<16) | (bytes[i+3]<<8) | (bytes[i+4]); | |
vddper = bin16dec(vddper); | |
decoded.sensorPeriods.vdd = vddper; | |
i += 4; | |
break; | |
case TYPE_SEND_PER: //VDD Period | |
var sendper = (bytes[i+1]<<24) | (bytes[i+2]<<16) | (bytes[i+3]<<8) | (bytes[i+4]); | |
sendper = bin16dec(sendper); | |
decoded.sensorPeriods.transmit = sendper; | |
i += 4; | |
break; | |
case TYPE_LOCK: //Lock Code | |
var lock = (bytes[i+1]<<24) | (bytes[i+2]<<16) | (bytes[i+3]<<8) | (bytes[i+4]); | |
lock = bin16dec(lock); | |
decoded.lock = lock; | |
i += 4; | |
break; | |
case TYPE_LINK_CHK: //Link Threshold | |
var link = (bytes[i+1]<<24) | (bytes[i+2]<<16) | (bytes[i+3]<<8) | (bytes[i+4]); | |
link = bin16dec(link); | |
decoded.linkChk = link; | |
i += 4; | |
break; | |
case TYPE_PRESS_PER: //Pressure Period | |
var press = (bytes[i+1]<<24) | (bytes[i+2]<<16) | (bytes[i+3]<<8) | (bytes[i+4]); | |
press = bin16dec(press); | |
decoded.sensorPeriods.pressure = press; | |
i += 4; | |
break; | |
case TYPE_SOUND_PER: //Sound Period | |
var sound = (bytes[i+1]<<24) | (bytes[i+2]<<16) | (bytes[i+3]<<8) | (bytes[i+4]); | |
sound = bin16dec(sound); | |
decoded.sensorPeriods.sound = sound; | |
i += 4; | |
break; | |
case TYPE_VERSION: //Firmware Version | |
var v = (bytes[i+1]<<8) | (bytes[i+2]); | |
v = bin16dec(v).toString(); | |
var version = v.charAt(0) + '.' + v.charAt(1) + '.' + v.charAt(2); | |
decoded.version = version; | |
i += 2; | |
break; | |
} | |
} | |
} | |
return decoded; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Encoder(object, port) { | |
var TYPE_ACK = 'ack'; | |
// Encode downlink messages sent as | |
// object to an array or buffer of bytes. | |
var bytes = []; | |
if (port === 6) { | |
bytes.push(0x3E, 0x00); | |
for (var key in object) { | |
switch(key) | |
{ | |
case TYPE_ACK: | |
var ackSetting = object[key] ? 1: 0; | |
bytes.push(0x0A, ackSetting); | |
bytes[1] = bytes[1] + 2; | |
break; | |
default: | |
break; | |
} | |
} | |
} | |
return bytes; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Validator(converted, port) { | |
// Return false if the decoded, converted | |
// message is invalid and should be dropped. | |
return true; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment