forked from TheThingsNetwork/lorawan-devices
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8 from waggle-sensor/add-sap-flow
Add ict as vendor and sap flow meter device
- Loading branch information
Showing
9 changed files
with
468 additions
and
0 deletions.
There are no files selected for viewing
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,3 @@ | ||
endDevices: | ||
# Unique identifier of the end device (lowercase, alphanumeric with dashes, max 36 characters) | ||
- sfm1x # look in sfm1x.yaml for the end device definition |
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,20 @@ | ||
# Whether the end device supports class B | ||
supportsClassB: false | ||
# Whether the end device supports class C | ||
supportsClassC: false | ||
# LoRaWAN MAC version: 1.0, 1.0.1, 1.0.2, 1.0.3, 1.0.4 or 1.1 | ||
macVersion: 1.0.2 | ||
# LoRaWAN Regional Parameters version. Values depend on the LoRaWAN version: | ||
# 1.0: TS001-1.0 | ||
# 1.0.1: TS001-1.0.1 | ||
# 1.0.2: RP001-1.0.2 or RP001-1.0.2-RevB | ||
# 1.0.3: RP001-1.0.3-RevA | ||
# 1.0.4: RP002-1.0.0 or RP002-1.0.1 | ||
# 1.1: RP001-1.1-RevA or RP001-1.1-RevB | ||
regionalParametersVersion: RP001-1.0.2 | ||
# Whether the end device supports join (OTAA) or not (ABP) | ||
supportsJoin: true | ||
# Maximum EIRP | ||
maxEIRP: 16 #NOTE: don't know what is the actual value - FL | ||
# Whether the end device supports 32-bit frame counters | ||
supports32bitFCnt: true #NOTE: don't know what is the actual value - FL |
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,11 @@ | ||
# Uplink decoder decodes binary data uplink into a JSON object (optional) | ||
uplinkDecoder: | ||
fileName: sfm1x-r1-1.js | ||
|
||
# Downlink encoder encodes JSON object into a binary data downlink (optional) | ||
downlinkEncoder: | ||
fileName: sfm1x-r1-1.js | ||
|
||
# Downlink decoder decodes the encoded downlink message (optional, must be symmetric with downlinkEncoder) | ||
downlinkDecoder: | ||
fileName: sfm1x-r1-1.js |
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,184 @@ | ||
/* SFM1x Reduced Packet Decoder Base to be used with lorawan listener plugin | ||
Includes Base Diagnostic and Switchable Result Packet | ||
*/ | ||
|
||
// Structure Type Define, "nested" or "flat" | ||
var TYPE = 'nested'; | ||
|
||
/*Class Buffer | ||
Purpose: A psuedo buffer class for accessing packet data, | ||
allows for uniformity between decoder types | ||
*/ | ||
function Buf(buf) { | ||
this.pl = buf; | ||
this.length = this.pl.length; | ||
} | ||
Buf.prototype.readUInt8 = function (ofs) { | ||
return (this.pl[ofs] << 24) >>> 24; | ||
}; | ||
Buf.prototype.readUInt16BE = function (ofs) { | ||
return ((this.pl[ofs++] << 24) | (this.pl[ofs++] << 16)) >>> 16; | ||
}; | ||
Buf.prototype.readUInt32BE = function (ofs) { | ||
return ((this.pl[ofs++] << 24) | (this.pl[ofs++] << 16) | (this.pl[ofs++] << 8) | this.pl[ofs++]) >>> 0; | ||
}; | ||
Buf.prototype.readUInt16LE = function (ofs) { | ||
return ((this.pl[ofs + 1] << 24) | (this.pl[ofs--] << 16)) >>> 16; | ||
}; | ||
Buf.prototype.readUInt32LE = function (ofs) { | ||
return ((this.pl[ofs + 3] << 24) | (this.pl[ofs + 2] << 16) | (this.pl[ofs + 1] << 8) | this.pl[ofs]) >>> 0; | ||
}; | ||
Buf.prototype.readInt8 = function (ofs) { | ||
return (this.pl[ofs] << 24) >> 24; | ||
}; | ||
Buf.prototype.readInt16BE = function (ofs) { | ||
return ((this.pl[ofs++] << 24) | (this.pl[ofs++] << 16)) >> 16; | ||
}; | ||
Buf.prototype.readInt32BE = function (ofs) { | ||
return ((this.pl[ofs++] << 24) | (this.pl[ofs++] << 16) | (this.pl[ofs++] << 8) | this.pl[ofs++]) >> 0; | ||
}; | ||
Buf.prototype.readInt16LE = function (ofs) { | ||
return ((this.pl[ofs + 1] << 24) | (this.pl[ofs--] << 16)) >> 16; | ||
}; | ||
Buf.prototype.readInt32LE = function (ofs) { | ||
return ((this.pl[ofs + 3] << 24) | (this.pl[ofs + 2] << 16) | (this.pl[ofs + 1] << 8) | this.pl[ofs]) >> 0; | ||
}; | ||
Buf.prototype.readFloatBE = function (ofs) { | ||
return B2Fl(this.readUInt32BE(ofs)); | ||
}; | ||
Buf.prototype.readFloatLE = function (ofs) { | ||
return B2Fl(this.readUInt32LE(ofs)); | ||
}; | ||
Buf.prototype.slice = function (s, e) { | ||
return this.pl.slice(s, e); | ||
}; | ||
Buf.prototype.length = function () { | ||
return this.pl.length; | ||
}; | ||
|
||
/*Function Bytes2Float32(bytes) | ||
Purpose: Decodes an array of bytes(len 4(32 bit) into a float. | ||
Args: bytes - an array of bytes, 4 bytes long | ||
Returns: 32bit Float representation | ||
*/ | ||
function B2Fl(b) { | ||
var sign = b >> 31 ? -1 : 1; | ||
var exp = ((b >> 23) & 0xff) - 127; | ||
var sig = b & ~(-1 << 23); | ||
if (exp == 128) return sign * (sig ? Number.NaN : Number.POSITIVE_INFINITY); | ||
if (exp == -127) { | ||
if (sig === 0) return sign * 0.0; | ||
exp = -126; | ||
sig /= 1 << 22; | ||
} else sig = (sig | (1 << 23)) / (1 << 23); | ||
return sign * sig * Math.pow(2, exp); | ||
} | ||
|
||
/*Function buildNested(a) - SAGE version | ||
Purpose: Takes an array and parses them into a clean and succinct object of nested parameter sets | ||
Args: a - An array of arrays containing Parameter Sets | ||
Returns: An Object containing nested Parameter Sets | ||
*/ | ||
function buildNested(a) { | ||
var exc = ['main', 'diagnostic', 'downlink', 'device_info', 'unknown']; | ||
var ret = []; | ||
for (var el in a) { | ||
var e = a[el]; | ||
var par = {}; | ||
par['name'] = e[0]; | ||
par['channelId'] = e[1]; | ||
par['value'] = e[2]; | ||
var e_length = e.length; | ||
if (e_length > 3 && exc.indexOf(e[3]) < 0) par['source'] = e[3]; | ||
if (e_length > 4) par['unit'] = e[4]; | ||
if (e_length > 5) par['address'] = e[5]; | ||
ret.push(par); | ||
} | ||
return ret; | ||
} | ||
|
||
/*Function buildFlat(a) | ||
Purpose: Takes an array and parses them into a clean and succinct object of flat parameters | ||
Args: a - An array of arrays containing Parameter Sets | ||
Returns: An Object containing nested Parameter Sets | ||
*/ | ||
function buildFlat(a) { | ||
var exc = ['main', 'diagnostic', 'downlink', 'device_info', 'unknown']; | ||
var ret = {}; | ||
for (var el in a) { | ||
var e = a[el]; | ||
var label = ''; | ||
if (e.length == 6) { | ||
e[0] = e[0] + e[5] + '_'; | ||
} | ||
if (e.length <= 4) { | ||
label = exc.indexOf(e[3]) < 0 ? e[0] + e[1] : e[0]; | ||
} else { | ||
label = exc.indexOf(e[3]) < 0 ? e[0] + e[1] + '_' + e[4] : e[0] + '_' + e[4]; | ||
} | ||
ret[label] = e[2]; | ||
} | ||
return ret; | ||
} | ||
|
||
//Function - Decode, Wraps the primary decoder function for Chirpstack - SAGE version | ||
function decodeUplink(input) { | ||
var buf = new Buf(input.bytes); | ||
var decoded = {}; | ||
var readingsArr = primaryDecoder(buf, input.fPort); | ||
if (TYPE == 'flat') { | ||
decoded['measurements'] = buildFlat(readingsArr); | ||
} else decoded['measurements'] = buildNested(readingsArr); | ||
|
||
return { data: decoded }; | ||
} | ||
|
||
/*Function primaryDecoder | ||
Purpose: Main Entry point of TTN Console Decoder | ||
Args: bytes - An array of bytes from LoRaWan raw payload(Hex Represented) | ||
port - LoRaWan Port that the message came through(set by Definium firmware) | ||
Returns: decoded - An object with data fields as decoded parameter values | ||
*/ | ||
function primaryDecoder(buf, p) { | ||
var arr = []; | ||
var byte = 0; | ||
|
||
//Data Packet Recieved | ||
if (p == 1) { | ||
var src = 'main'; | ||
arr.push(['packet-type', 0, 'DATA_PACKET', src]); | ||
arr.push(['uncorrected-outer', 0, +buf.readFloatLE(byte).toFixed(3), src, 'cm/hr']); | ||
arr.push(['uncorrected-inner', 0, +buf.readFloatLE((byte = byte + 4)).toFixed(3), src, 'cm/hr']); | ||
arr.push(['corrected-outer', 0, +buf.readFloatLE((byte = byte + 4)).toFixed(3), src, 'cm/hr']); | ||
arr.push(['corrected-inner', 0, +buf.readFloatLE((byte = byte + 4)).toFixed(3), src, 'cm/hr']); | ||
arr.push(['battery-voltage', 0, +(buf.readUInt16LE((byte = byte + 4)) / 100).toFixed(2), src, 'V']); | ||
arr.push(['external-power-supply-voltage', 0, +(buf.readUInt16LE((byte = byte + 2)) / 100).toFixed(2), src, 'V']); | ||
} else if (p == 10) { | ||
var src = 'device_info'; | ||
arr.push(['packet-type', 0, 'DEVICE_INFO', 'main']); | ||
|
||
var fw_main = buf.readInt16LE(byte).toString(); | ||
fw_main = 'R' + fw_main[0] + '-' + fw_main.slice(1, 3).replace(/^(0)?/, '') + '-' + fw_main.slice(3, fw_main.length).replace(/^(0)?/, ''); | ||
arr.push(['firmware-mainboard', 0, fw_main, src]); | ||
|
||
var fw_ucmi = buf.readInt16LE((byte = byte + 2)).toString(); | ||
var region = ['a', 'e', 'c', 's', 'u']; | ||
var ucmi_reg = region[+fw_ucmi[fw_ucmi.length - 1]]; | ||
fw_ucmi = 'R' + fw_ucmi[0] + '-' + fw_ucmi[1] + '-' + fw_ucmi.slice(2, 4).replace(/^(0)?/, '') + ucmi_reg; | ||
arr.push(['firmware-ucmi', 0, fw_ucmi, src]); | ||
|
||
arr.push(['vs-factor', 0, +(buf.readInt16LE((byte = byte + 2)) / 1000).toFixed(4), src]); | ||
arr.push(['outer-area', 0, +(buf.readInt16LE((byte = byte + 2)) / 1000).toFixed(3), src, 'cm^2']); | ||
arr.push(['inner-area', 0, +(buf.readInt16LE((byte = byte + 2)) / 1000).toFixed(3), src, 'cm^2']); | ||
} else if (p === 100) { | ||
//Downlink Response Packet Recieved | ||
arr.push(['packet-type', 0, 'DOWNLINK_RESPONSE', 'main']); | ||
arr.push(['downlink-response', 0, String.fromCharCode.apply(String, buf.slice(0, buf.length)), 'downlink']); | ||
} else { | ||
// Unknown Response Recieved | ||
arr.push(['packet-type', 0, 'UNKNOWN_RESPONSE', 'main']); | ||
arr.push(['raw-payload', 0, buf.slice(0, buf.length), 'unknown']); | ||
} | ||
|
||
return arr; | ||
} |
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,11 @@ | ||
# Uplink decoder decodes binary data uplink into a JSON object (optional) | ||
uplinkDecoder: | ||
fileName: sfm1x-r3-1.js | ||
|
||
# Downlink encoder encodes JSON object into a binary data downlink (optional) | ||
downlinkEncoder: | ||
fileName: sfm1x-r3-1.js | ||
|
||
# Downlink decoder decodes the encoded downlink message (optional, must be symmetric with downlinkEncoder) | ||
downlinkDecoder: | ||
fileName: sfm1x-r3-1.js |
Oops, something went wrong.