-
Notifications
You must be signed in to change notification settings - Fork 378
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
124 changed files
with
8,635 additions
and
296 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
# Uplink decoder decodes binary data uplink into a JSON object (optional) | ||
# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ | ||
uplinkDecoder: | ||
fileName: dc413.js | ||
# Examples (optional) | ||
examples: | ||
- description: heartbeat upload | ||
input: | ||
fPort: 3 | ||
bytes: [0x80, 0x00, 0x01, 0x02, 0x11, 0x06, 0xA4, 0x00, 0x16, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x81] | ||
output: | ||
data: | ||
level: 1700 | ||
alarmLevel: false | ||
alarmFall: false | ||
alarmBattery: false | ||
angle: 0 | ||
temperature: 22 | ||
frameCounter: 1 | ||
|
||
- description: parameter packet | ||
input: | ||
fPort: 3 | ||
bytes: [0x80, 0x00, 0x01, 0x03, 0x19, 0x03, 0x02, 0x06, 0x3C, 0x1E, 0x4B, 0x14, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81] | ||
output: | ||
data: | ||
firmware: '3.2' | ||
uploadInterval: 6 | ||
detectInterval: 60 | ||
levelThreshold: 30 | ||
fallThreshold: 20 | ||
fallEnable: true | ||
workMode: 1 | ||
|
||
# Downlink encoder encodes JSON object into a binary data downlink (optional) | ||
downlinkEncoder: | ||
fileName: dc413.js | ||
examples: | ||
- description: change periodic upload interval to 4 hours | ||
input: | ||
data: | ||
uploadInterval: 4 | ||
output: | ||
bytes: [0x38, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x30, 0x31, 0x30, 0x34, 0x38, 0x31] | ||
fPort: 3 | ||
- description: change periodic detection interval to 10 minutes | ||
input: | ||
data: | ||
detectInterval: 10 | ||
output: | ||
bytes: [0x38, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x30, 0x38, 0x30, 0x41, 0x38, 0x31] | ||
fPort: 3 | ||
- description: change full alarm threshold to 35cm | ||
input: | ||
data: | ||
levelThreshold: 35 | ||
output: | ||
bytes: [0x38, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x30, 0x32, 0x32, 0x33, 0x38, 0x31] | ||
fPort: 3 | ||
- description: change motion alarm threshold to 45° | ||
input: | ||
data: | ||
fallThreshold: 45 | ||
output: | ||
bytes: [0x38, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x30, 0x34, 0x32, 0x44, 0x38, 0x31] | ||
fPort: 3 | ||
- description: enable tilt detection | ||
input: | ||
data: | ||
fallEnable: true | ||
output: | ||
bytes: [0x38, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x30, 0x39, 0x30, 0x41, 0x38, 0x31] | ||
fPort: 3 | ||
|
||
# Downlink decoder decodes the encoded downlink message (optional, must be symmetric with downlinkEncoder) | ||
downlinkDecoder: | ||
fileName: dc413.js | ||
examples: | ||
- description: change periodic upload interval to 4 hours | ||
input: | ||
fPort: 3 | ||
bytes: [0x38, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x30, 0x31, 0x30, 0x34, 0x38, 0x31] | ||
output: | ||
data: | ||
uploadInterval: 4 | ||
- description: change detection interval to 10 minutes | ||
input: | ||
fPort: 3 | ||
bytes: [0x38, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x30, 0x38, 0x30, 0x41, 0x38, 0x31] | ||
output: | ||
data: | ||
detectInterval: 10 | ||
- description: change full alarm threshold to 35cm | ||
input: | ||
fPort: 3 | ||
bytes: [0x38, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x30, 0x32, 0x32, 0x33, 0x38, 0x31] | ||
output: | ||
data: | ||
levelThreshold: 35 | ||
- description: change motion alarm threshold to 45° | ||
input: | ||
fPort: 3 | ||
bytes: [0x38, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x30, 0x34, 0x32, 0x44, 0x38, 0x31] | ||
output: | ||
data: | ||
fallThreshold: 45 | ||
- description: enable motion detection | ||
input: | ||
fPort: 3 | ||
bytes: [0x38, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x30, 0x39, 0x30, 0x41, 0x38, 0x31] | ||
output: | ||
data: | ||
fallEnable: true |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,223 @@ | ||
var units = [' ℃', ' hours', ' minutes', ' mm', ' °', ' cm']; | ||
//IEEE754 hex to float convert | ||
function hex2float(num) { | ||
var sign = num & 0x80000000 ? -1 : 1; | ||
var exponent = ((num >> 23) & 0xff) - 127; | ||
var mantissa = 1 + (num & 0x7fffff) / 0x7fffff; | ||
return sign * mantissa * Math.pow(2, exponent); | ||
} | ||
|
||
function decodeUplink(input) { | ||
if (input.fPort != 3) { | ||
return { | ||
errors: ['unknown FPort'], | ||
}; | ||
} | ||
|
||
switch (input.bytes.length) { | ||
case 17: | ||
return { | ||
// Decoded data | ||
data: { | ||
level: (input.bytes[5] << 8) + input.bytes[6], | ||
alarmLevel: Boolean(input.bytes[11] >> 4), | ||
alarmFall: Boolean(input.bytes[12] >> 4), | ||
alarmBattery: Boolean(input.bytes[12] & 0x0f), | ||
angle: input.bytes[9] & (0x0f === 0x00) ? input.bytes[10] : 0 - input.bytes[10], | ||
temperature: input.bytes[8], | ||
frameCounter: (input.bytes[13] << 8) + input.bytes[14], | ||
}, | ||
}; | ||
case 25: | ||
var data_type = input.bytes[3]; | ||
if (data_type === 0x03) { | ||
return { | ||
// Decoded parameter | ||
data: { | ||
firmware: input.bytes[5] + '.' + input.bytes[6], | ||
uploadInterval: input.bytes[7], | ||
detectInterval: input.bytes[8], | ||
levelThreshold: input.bytes[9], | ||
fallThreshold: input.bytes[11], | ||
fallEnable: Boolean(input.bytes[12]), | ||
workMode: input.bytes[14], | ||
}, | ||
}; | ||
} | ||
default: | ||
return { | ||
errors: ['wrong length'], | ||
}; | ||
} | ||
} | ||
|
||
function encodeDownlink(input) { | ||
if (input.data.uploadInterval != null && !isNaN(input.data.uploadInterval)) { | ||
var periodic_interval = input.data.uploadInterval; | ||
var periodic_interval_high = periodic_interval.toString(16).padStart(2, '0').toUpperCase()[0].charCodeAt(0); | ||
var periodic_interval_low = periodic_interval.toString(16).padStart(2, '0').toUpperCase()[1].charCodeAt(0); | ||
if (periodic_interval > 168 || periodic_interval < 1) { | ||
return { | ||
errors: ['periodic upload interval range 1-168 hours.'], | ||
}; | ||
} else { | ||
return { | ||
// LoRaWAN FPort used for the downlink message | ||
fPort: 3, | ||
// Encoded bytes | ||
bytes: [0x38, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x30, 0x31, periodic_interval_high, periodic_interval_low, 0x38, 0x31], | ||
}; | ||
} | ||
} | ||
if (input.data.detectInterval != null && !isNaN(input.data.detectInterval)) { | ||
var detection_interval = input.data.detectInterval; | ||
var detection_interval_high = detection_interval.toString(16).padStart(2, '0').toUpperCase()[0].charCodeAt(0); | ||
var detection_interval_low = detection_interval.toString(16).padStart(2, '0').toUpperCase()[1].charCodeAt(0); | ||
if (detection_interval > 60 || detection_interval < 1) { | ||
return { | ||
errors: ['periodic detection interval range 1-60 minutes.'], | ||
}; | ||
} else { | ||
return { | ||
// LoRaWAN FPort used for the downlink message | ||
fPort: 3, | ||
// Encoded bytes | ||
bytes: [0x38, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x30, 0x38, detection_interval_high, detection_interval_low, 0x38, 0x31], | ||
}; | ||
} | ||
} | ||
if (input.data.levelThreshold != null && !isNaN(input.data.levelThreshold)) { | ||
var full_alarm_threshold = input.data.levelThreshold; | ||
var full_alarm_threshold_high = full_alarm_threshold.toString(16).padStart(2, '0').toUpperCase()[0].charCodeAt(0); | ||
var full_alarm_threshold_low = full_alarm_threshold.toString(16).padStart(2, '0').toUpperCase()[1].charCodeAt(0); | ||
if (full_alarm_threshold > 255 || full_alarm_threshold < 15) { | ||
return { | ||
errors: ['full alarm threshold range 15-255 cm.'], | ||
}; | ||
} else { | ||
return { | ||
// LoRaWAN FPort used for the downlink message | ||
fPort: 3, | ||
// Encoded bytes | ||
bytes: [0x38, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x30, 0x32, full_alarm_threshold_high, full_alarm_threshold_low, 0x38, 0x31], | ||
}; | ||
} | ||
} | ||
|
||
if (input.data.fallThreshold != null && !isNaN(input.data.fallThreshold)) { | ||
var tilt_alarm_threshold = input.data.fallThreshold; | ||
var tilt_alarm_threshold_high = tilt_alarm_threshold.toString(16).padStart(2, '0').toUpperCase()[0].charCodeAt(0); | ||
var tilt_alarm_threshold_low = tilt_alarm_threshold.toString(16).padStart(2, '0').toUpperCase()[1].charCodeAt(0); | ||
if (tilt_alarm_threshold > 90 || tilt_alarm_threshold < 15) { | ||
return { | ||
errors: ['tilt alarm threshold range 15-90 °.'], | ||
}; | ||
} else { | ||
return { | ||
// LoRaWAN FPort used for the downlink message | ||
fPort: 3, | ||
// Encoded bytes | ||
bytes: [0x38, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x30, 0x34, tilt_alarm_threshold_high, tilt_alarm_threshold_low, 0x38, 0x31], | ||
}; | ||
} | ||
} | ||
if (input.data.fallEnable != null && input.data.fallEnable === !!input.data.fallEnable) { | ||
var tilt_enable = input.data.fallEnable; | ||
if (tilt_enable === true) { | ||
return { | ||
// LoRaWAN FPort used for the downlink message | ||
fPort: 3, | ||
// Encoded bytes | ||
bytes: [0x38, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x30, 0x39, 0x30, 0x41, 0x38, 0x31], | ||
}; | ||
} else { | ||
return { | ||
// LoRaWAN FPort used for the downlink message | ||
fPort: 3, | ||
// Encoded bytes | ||
bytes: [0x38, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x30, 0x39, 0x30, 0x39, 0x38, 0x31], | ||
}; | ||
} | ||
} | ||
return { | ||
errors: ['invalid downlink parameter.'], | ||
}; | ||
} | ||
|
||
function decodeDownlink(input) { | ||
var input_length = input.bytes.length; | ||
if (input.fPort != 3) { | ||
return { | ||
errors: ['invalid FPort.'], | ||
}; | ||
} | ||
|
||
if ( | ||
input_length < 12 || | ||
input.bytes[0] != 0x38 || | ||
input.bytes[1] != 0x30 || | ||
input.bytes[2] != 0x30 || | ||
input.bytes[3] != 0x32 || | ||
input.bytes[4] != 0x39 || | ||
input.bytes[5] != 0x39 || | ||
input.bytes[6] != 0x39 || | ||
input.bytes[7] != 0x39 || | ||
input.bytes[input_length - 2] != 0x38 || | ||
input.bytes[input_length - 1] != 0x31 | ||
) { | ||
return { | ||
errors: ['invalid format.'], | ||
}; | ||
} | ||
var option = parseInt(String.fromCharCode(input.bytes[8]) + String.fromCharCode(input.bytes[9]), 16); | ||
var value = parseInt(String.fromCharCode(input.bytes[10]) + String.fromCharCode(input.bytes[11]), 16); | ||
switch (option) { | ||
case 1: | ||
return { | ||
data: { | ||
uploadInterval: value, | ||
}, | ||
}; | ||
case 8: | ||
return { | ||
data: { | ||
detectInterval: value, | ||
}, | ||
}; | ||
case 2: | ||
return { | ||
data: { | ||
levelThreshold: value, | ||
}, | ||
}; | ||
case 4: | ||
return { | ||
data: { | ||
fallThreshold: value, | ||
}, | ||
}; | ||
case 9: | ||
switch (value) { | ||
case 0x09: | ||
return { | ||
data: { | ||
fallEnable: false, | ||
}, | ||
}; | ||
case 0x0a: | ||
return { | ||
data: { | ||
fallEnable: true, | ||
}, | ||
}; | ||
default: | ||
return { | ||
errors: ['invalid parameter value.'], | ||
}; | ||
} | ||
default: | ||
return { | ||
errors: ['invalid parameter key.'], | ||
}; | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.