Merge pull request #815 from dasdigidings/master
lorawan-device repo initial files
This commit is contained in:
commit
46f3827871
12
src/lorawan-devices-repo/index.yaml
Normal file
12
src/lorawan-devices-repo/index.yaml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
vendors:
|
||||||
|
- id: example
|
||||||
|
name: Example
|
||||||
|
vendorID: 0
|
||||||
|
draft: true
|
||||||
|
|
||||||
|
#SNIP - a lot of other vendors, just attach the lower lines to the index.yaml
|
||||||
|
#SNIP - could add a logo with "logo: filename"
|
||||||
|
|
||||||
|
- id: opensource
|
||||||
|
name: Open Source Community Projects
|
||||||
|
website: https://en.wikipedia.org/wiki/Open_source
|
21
src/lorawan-devices-repo/readme.md
Normal file
21
src/lorawan-devices-repo/readme.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# lorawan-devices repo for The Things Network & The Things Stack V3
|
||||||
|
|
||||||
|
To add bigger payload decoders than 4k (via web ui) we provide the metadata to the lorawan-devices repo on github. For this we create a vendor "opensource" and specify a device "esp32-paxcounter" via this files:
|
||||||
|
|
||||||
|
> /
|
||||||
|
> - index.yaml (include the marked lines at the bottom of the original file)
|
||||||
|
>
|
||||||
|
> /vendor (existing folder in the repo)
|
||||||
|
>
|
||||||
|
> - /opensource (new folder with all the good stuff inside)
|
||||||
|
>
|
||||||
|
> /vendor/opensource
|
||||||
|
>
|
||||||
|
> - index.yaml (name of the device inside)
|
||||||
|
> - esp32-paxcounter.yaml (metadata for the software)
|
||||||
|
> - esp32-paxcounter-profile-eu868.yaml (profile for europe)
|
||||||
|
> - esp32-paxcounter-profile-us915.yaml (profile for north america)
|
||||||
|
> - esp32-paxcounter-codec.yaml (examples for the payload decoder)
|
||||||
|
> - esp32-paxcounter-packed_decodeUplink.js (payload decoder as provided before for the web ui, now for the lorawan devices repo)
|
||||||
|
|
||||||
|
With these files, we can make a pull request at the lorawan-devices repo: https://github.com/TheThingsNetwork/lorawan-devices and hope to be included in the future. Cool thing about it would be that then the users need only to choose "Open Source Community Projects" from the vendor list and "EXP32-Paxcounter" as device and most of the compex things is taking care of (like choosing the right LoRaWAN version and installing the payload decoder).
|
127
src/lorawan-devices-repo/vendor/opensource/esp32-paxcounter-codec.yaml
vendored
Normal file
127
src/lorawan-devices-repo/vendor/opensource/esp32-paxcounter-codec.yaml
vendored
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
# 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: esp32-paxcounter-packed_decodeUplink.js
|
||||||
|
examples:
|
||||||
|
- description: Paxcount data
|
||||||
|
input:
|
||||||
|
fPort: 1
|
||||||
|
bytes: [0x00, 0x07, 0x00, 0x03]
|
||||||
|
output:
|
||||||
|
data:
|
||||||
|
bytes: [0x00, 0x07, 0x00, 0x03]
|
||||||
|
port: 1
|
||||||
|
wifi: 7
|
||||||
|
ble: 3
|
||||||
|
errors: []
|
||||||
|
warnings: []
|
||||||
|
- description: Device status query result
|
||||||
|
input:
|
||||||
|
fPort: 2
|
||||||
|
bytes: [0x01, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x4B, 0xC0, 0x2D, 0x00, 0x03, 0x4B, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00]
|
||||||
|
output:
|
||||||
|
data:
|
||||||
|
bytes: [0x01, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x4B, 0xC0, 0x2D, 0x00, 0x03, 0x4B, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00]
|
||||||
|
port: 2
|
||||||
|
voltage: 303
|
||||||
|
uptime: 216000
|
||||||
|
cputemp: 45
|
||||||
|
memory: 216000
|
||||||
|
reset0: 0
|
||||||
|
restarts: 0
|
||||||
|
errors: []
|
||||||
|
warnings: []
|
||||||
|
- description: Device config data
|
||||||
|
input:
|
||||||
|
fPort: 3
|
||||||
|
bytes: [0x09, 0x0F, 0x00, 0x00, 0x78, 0x32, 0x0A, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
|
||||||
|
output:
|
||||||
|
data:
|
||||||
|
bytes: [0x09, 0x0F, 0x00, 0x00, 0x78, 0x32, 0x0A, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
|
||||||
|
port: 3
|
||||||
|
loradr: 9
|
||||||
|
txpower: 15
|
||||||
|
rssilimit: 0
|
||||||
|
sendcycle: 120
|
||||||
|
wifichancycle: 50
|
||||||
|
blescantime: 10
|
||||||
|
rgblum: 30
|
||||||
|
flags: 0
|
||||||
|
payloadmask: 0
|
||||||
|
version: 0
|
||||||
|
errors: []
|
||||||
|
warnings: []
|
||||||
|
- description: GPS data
|
||||||
|
input:
|
||||||
|
fPort: 4
|
||||||
|
bytes: [0x6E, 0x1C, 0x07, 0x03, 0x0A, 0x63, 0x6F, 0x0B, 0x51, 0x00, 0xCD, 0x00]
|
||||||
|
output:
|
||||||
|
data:
|
||||||
|
bytes: [0x6E, 0x1C, 0x07, 0x03, 0x0A, 0x63, 0x6F, 0x0B, 0x51, 0x00, 0xCD, 0x00]
|
||||||
|
port: 4
|
||||||
|
latitude: 50.797678
|
||||||
|
longitude: 7.29985
|
||||||
|
sats: 11
|
||||||
|
hdop: 0.81
|
||||||
|
altitude: 205
|
||||||
|
errors: []
|
||||||
|
warnings: []
|
||||||
|
- description: Button data
|
||||||
|
input:
|
||||||
|
fPort: 5
|
||||||
|
bytes: [0x01]
|
||||||
|
output:
|
||||||
|
data:
|
||||||
|
bytes: [0x00]
|
||||||
|
port: 5
|
||||||
|
button: 1
|
||||||
|
errors: []
|
||||||
|
warnings: []
|
||||||
|
- description: Environmental sensor data
|
||||||
|
input:
|
||||||
|
fPort: 7
|
||||||
|
bytes: [0x08, 0x34, 0x27, 0x10, 0x1F, 0x40, 0x27, 0x10]
|
||||||
|
output:
|
||||||
|
data:
|
||||||
|
bytes: [0x08, 0x34, 0x27, 0x10, 0x1F, 0x40, 0x27, 0x10]
|
||||||
|
port: 7
|
||||||
|
temperature: 21.00
|
||||||
|
pressure: 1000.0
|
||||||
|
humidity: 80.00
|
||||||
|
air: 100.00
|
||||||
|
errors: []
|
||||||
|
warnings: []
|
||||||
|
- description: Battery voltage data
|
||||||
|
input:
|
||||||
|
fPort: 8
|
||||||
|
bytes: [0x01, 0x2F]
|
||||||
|
output:
|
||||||
|
data:
|
||||||
|
bytes: [0x01, 0x2F]
|
||||||
|
port: 8
|
||||||
|
voltage: 303
|
||||||
|
errors: []
|
||||||
|
warnings: []
|
||||||
|
- description: Time/Date
|
||||||
|
input:
|
||||||
|
fPort: 9
|
||||||
|
bytes: [0x60, 0xC8, 0x86, 0x90, 0x00]
|
||||||
|
output:
|
||||||
|
data:
|
||||||
|
bytes: [0x60, 0xC8, 0x86, 0x90, 0x00]
|
||||||
|
port: 9
|
||||||
|
time: 1623754384
|
||||||
|
timestatus: 0
|
||||||
|
errors: []
|
||||||
|
warnings: []
|
||||||
|
- description: User sensor data
|
||||||
|
input:
|
||||||
|
fPort: 10
|
||||||
|
bytes: [0x00]
|
||||||
|
output:
|
||||||
|
data:
|
||||||
|
bytes: [0x00]
|
||||||
|
port: 10
|
||||||
|
ens: 0
|
||||||
|
errors: []
|
||||||
|
warnings: []
|
344
src/lorawan-devices-repo/vendor/opensource/esp32-paxcounter-packed_decodeUplink.js
vendored
Normal file
344
src/lorawan-devices-repo/vendor/opensource/esp32-paxcounter-packed_decodeUplink.js
vendored
Normal file
@ -0,0 +1,344 @@
|
|||||||
|
// Decoder for device payload encoder "PACKED"
|
||||||
|
// copy&paste to TTN Console V3 -> Applications -> Payload formatters -> Uplink -> Javascript
|
||||||
|
// modified for The Things Stack V3 by Caspar Armster, dasdigidings e.V.
|
||||||
|
|
||||||
|
function decodeUplink(input) {
|
||||||
|
var data = {};
|
||||||
|
|
||||||
|
if (input.fPort === 1) {
|
||||||
|
// only wifi counter data, no gps
|
||||||
|
if (input.bytes.length === 2) {
|
||||||
|
data = decode(input.bytes, [uint16], ['wifi']);
|
||||||
|
}
|
||||||
|
// wifi + ble counter data, no gps
|
||||||
|
if (input.bytes.length === 4) {
|
||||||
|
data = decode(input.bytes, [uint16, uint16], ['wifi', 'ble']);
|
||||||
|
}
|
||||||
|
// combined wifi + ble + SDS011
|
||||||
|
if (input.bytes.length === 8) {
|
||||||
|
data = decode(input.bytes, [uint16, uint16, uint16, uint16], ['wifi', 'ble', 'PM10', 'PM25']);
|
||||||
|
}
|
||||||
|
// combined wifi counter and gps data, used by https://opensensemap.org
|
||||||
|
if (input.bytes.length === 10) {
|
||||||
|
data = decode(input.bytes, [latLng, latLng, uint16], ['latitude', 'longitude', 'wifi']);
|
||||||
|
}
|
||||||
|
// combined wifi + ble counter and gps data, used by https://opensensemap.org
|
||||||
|
if (input.bytes.length === 12) {
|
||||||
|
data = decode(input.bytes, [latLng, latLng, uint16, uint16], ['latitude', 'longitude', 'wifi', 'ble']);
|
||||||
|
}
|
||||||
|
// combined wifi counter and gps data
|
||||||
|
if (input.bytes.length === 15) {
|
||||||
|
data = decode(input.bytes, [uint16, latLng, latLng, uint8, hdop, altitude], ['wifi', 'latitude', 'longitude', 'sats', 'hdop', 'altitude']);
|
||||||
|
}
|
||||||
|
// combined wifi + ble counter and gps data
|
||||||
|
if (input.bytes.length === 17) {
|
||||||
|
data = decode(input.bytes, [uint16, uint16, latLng, latLng, uint8, hdop, altitude], ['wifi', 'ble', 'latitude', 'longitude', 'sats', 'hdop', 'altitude']);
|
||||||
|
}
|
||||||
|
|
||||||
|
data.pax = 0;
|
||||||
|
if ('wifi' in data) {
|
||||||
|
data.pax += data.wifi;
|
||||||
|
}
|
||||||
|
if ('ble' in data) {
|
||||||
|
data.pax += data.ble;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.fPort === 2) {
|
||||||
|
// device status data
|
||||||
|
if (input.bytes.length === 20) {
|
||||||
|
data = decode(input.bytes, [uint16, uptime, uint8, uint32, uint8, uint32], ['voltage', 'uptime', 'cputemp', 'memory', 'reset0', 'restarts']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.fPort === 3) {
|
||||||
|
// device config data
|
||||||
|
data = decode(input.bytes, [uint8, uint8, int16, uint8, uint8, uint8, uint8, bitmap1, bitmap2, version], ['loradr', 'txpower', 'rssilimit', 'sendcycle', 'wifichancycle', 'blescantime', 'rgblum', 'flags', 'payloadmask', 'version']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.fPort === 4) {
|
||||||
|
// gps data
|
||||||
|
if (input.bytes.length === 8) {
|
||||||
|
data = decode(input.bytes, [latLng, latLng], ['latitude', 'longitude']);
|
||||||
|
} else {
|
||||||
|
data = decode(input.bytes, [latLng, latLng, uint8, hdop, altitude], ['latitude', 'longitude', 'sats', 'hdop', 'altitude']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.fPort === 5) {
|
||||||
|
// button pressed
|
||||||
|
data = decode(input.bytes, [uint8], ['button']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.fPort === 7) {
|
||||||
|
// BME680 sensor data
|
||||||
|
data = decode(input.bytes, [float, pressure, ufloat, ufloat], ['temperature', 'pressure', 'humidity', 'air']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.fPort === 8) {
|
||||||
|
// battery voltage
|
||||||
|
data = decode(input.bytes, [uint16], ['voltage']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.fPort === 9) {
|
||||||
|
// timesync request
|
||||||
|
if (input.bytes.length === 1) {
|
||||||
|
data.timesync_seqno = input.bytes[0];
|
||||||
|
}
|
||||||
|
// epoch time answer
|
||||||
|
if (input.bytes.length === 5) {
|
||||||
|
data = decode(input.bytes, [uint32, uint8], ['time', 'timestatus']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.fPort === 10) {
|
||||||
|
// ENS count
|
||||||
|
data = decode(input.bytes, [uint16], ['ens']);
|
||||||
|
}
|
||||||
|
|
||||||
|
data.bytes = input.bytes; // comment out if you do not want to include the original payload
|
||||||
|
data.port = input.fPort; // comment out if you do not want to inlude the port
|
||||||
|
|
||||||
|
return {
|
||||||
|
data: data,
|
||||||
|
warnings: [],
|
||||||
|
errors: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function encodeDownlink(input) {
|
||||||
|
return {
|
||||||
|
data: {
|
||||||
|
bytes: input.bytes
|
||||||
|
},
|
||||||
|
warnings: ["Encoding of downlink is not supported by the JS decoder."],
|
||||||
|
errors: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function decodeDownlink(input) {
|
||||||
|
return {
|
||||||
|
data: {
|
||||||
|
bytes: input.bytes
|
||||||
|
},
|
||||||
|
warnings: ["Decoding of downlink is not supported by the JS decoder."],
|
||||||
|
errors: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----- contents of /src/decoder.js --------------------------------------------
|
||||||
|
// https://github.com/thesolarnomad/lora-serialization/blob/master/src/decoder.js
|
||||||
|
|
||||||
|
var bytesToInt = function (bytes) {
|
||||||
|
var i = 0;
|
||||||
|
for (var x = 0; x < bytes.length; x++) {
|
||||||
|
i |= (bytes[x] << (x * 8));
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
};
|
||||||
|
|
||||||
|
var version = function (bytes) {
|
||||||
|
if (bytes.length !== version.BYTES) {
|
||||||
|
throw new Error('version must have exactly 10 bytes');
|
||||||
|
}
|
||||||
|
return String.fromCharCode.apply(null, bytes).split('\u0000')[0];
|
||||||
|
};
|
||||||
|
version.BYTES = 10;
|
||||||
|
|
||||||
|
var uint8 = function (bytes) {
|
||||||
|
if (bytes.length !== uint8.BYTES) {
|
||||||
|
throw new Error('uint8 must have exactly 1 byte');
|
||||||
|
}
|
||||||
|
return bytesToInt(bytes);
|
||||||
|
};
|
||||||
|
uint8.BYTES = 1;
|
||||||
|
|
||||||
|
var uint16 = function (bytes) {
|
||||||
|
if (bytes.length !== uint16.BYTES) {
|
||||||
|
throw new Error('uint16 must have exactly 2 bytes');
|
||||||
|
}
|
||||||
|
return bytesToInt(bytes);
|
||||||
|
};
|
||||||
|
uint16.BYTES = 2;
|
||||||
|
|
||||||
|
var uint32 = function (bytes) {
|
||||||
|
if (bytes.length !== uint32.BYTES) {
|
||||||
|
throw new Error('uint32 must have exactly 4 bytes');
|
||||||
|
}
|
||||||
|
return bytesToInt(bytes);
|
||||||
|
};
|
||||||
|
uint32.BYTES = 4;
|
||||||
|
|
||||||
|
var uint64 = function (bytes) {
|
||||||
|
if (bytes.length !== uint64.BYTES) {
|
||||||
|
throw new Error('uint64 must have exactly 8 bytes');
|
||||||
|
}
|
||||||
|
return bytesToInt(bytes);
|
||||||
|
};
|
||||||
|
uint64.BYTES = 8;
|
||||||
|
|
||||||
|
var int8 = function (bytes) {
|
||||||
|
if (bytes.length !== int8.BYTES) {
|
||||||
|
throw new Error('int8 must have exactly 1 byte');
|
||||||
|
}
|
||||||
|
var value = +(bytesToInt(bytes));
|
||||||
|
if (value > 127) {
|
||||||
|
value -= 256;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
int8.BYTES = 1;
|
||||||
|
|
||||||
|
var int16 = function (bytes) {
|
||||||
|
if (bytes.length !== int16.BYTES) {
|
||||||
|
throw new Error('int16 must have exactly 2 bytes');
|
||||||
|
}
|
||||||
|
var value = +(bytesToInt(bytes));
|
||||||
|
if (value > 32767) {
|
||||||
|
value -= 65536;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
int16.BYTES = 2;
|
||||||
|
|
||||||
|
var int32 = function (bytes) {
|
||||||
|
if (bytes.length !== int32.BYTES) {
|
||||||
|
throw new Error('int32 must have exactly 4 bytes');
|
||||||
|
}
|
||||||
|
var value = +(bytesToInt(bytes));
|
||||||
|
if (value > 2147483647) {
|
||||||
|
value -= 4294967296;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
int32.BYTES = 4;
|
||||||
|
|
||||||
|
var latLng = function (bytes) {
|
||||||
|
return +(int32(bytes) / 1e6).toFixed(6);
|
||||||
|
};
|
||||||
|
latLng.BYTES = int32.BYTES;
|
||||||
|
|
||||||
|
var uptime = function (bytes) {
|
||||||
|
return uint64(bytes);
|
||||||
|
};
|
||||||
|
uptime.BYTES = uint64.BYTES;
|
||||||
|
|
||||||
|
var hdop = function (bytes) {
|
||||||
|
return +(uint16(bytes) / 100).toFixed(2);
|
||||||
|
};
|
||||||
|
hdop.BYTES = uint16.BYTES;
|
||||||
|
|
||||||
|
var altitude = function (bytes) {
|
||||||
|
// Option to increase altitude resolution (also on encoder side)
|
||||||
|
// return +(int16(bytes) / 4 - 1000).toFixed(1);
|
||||||
|
return +(int16(bytes));
|
||||||
|
};
|
||||||
|
altitude.BYTES = int16.BYTES;
|
||||||
|
|
||||||
|
|
||||||
|
var float = function (bytes) {
|
||||||
|
if (bytes.length !== float.BYTES) {
|
||||||
|
throw new Error('Float must have exactly 2 bytes');
|
||||||
|
}
|
||||||
|
var isNegative = bytes[0] & 0x80;
|
||||||
|
var b = ('00000000' + Number(bytes[0]).toString(2)).slice(-8)
|
||||||
|
+ ('00000000' + Number(bytes[1]).toString(2)).slice(-8);
|
||||||
|
if (isNegative) {
|
||||||
|
var arr = b.split('').map(function (x) { return !Number(x); });
|
||||||
|
for (var i = arr.length - 1; i > 0; i--) {
|
||||||
|
arr[i] = !arr[i];
|
||||||
|
if (arr[i]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b = arr.map(Number).join('');
|
||||||
|
}
|
||||||
|
var t = parseInt(b, 2);
|
||||||
|
if (isNegative) {
|
||||||
|
t = -t;
|
||||||
|
}
|
||||||
|
return +(t / 100).toFixed(2);
|
||||||
|
};
|
||||||
|
float.BYTES = 2;
|
||||||
|
|
||||||
|
var ufloat = function (bytes) {
|
||||||
|
return +(uint16(bytes) / 100).toFixed(2);
|
||||||
|
};
|
||||||
|
ufloat.BYTES = uint16.BYTES;
|
||||||
|
|
||||||
|
var pressure = function (bytes) {
|
||||||
|
return +(uint16(bytes) / 10).toFixed(1);
|
||||||
|
};
|
||||||
|
pressure.BYTES = uint16.BYTES;
|
||||||
|
|
||||||
|
var bitmap1 = function (byte) {
|
||||||
|
if (byte.length !== bitmap1.BYTES) {
|
||||||
|
throw new Error('Bitmap must have exactly 1 byte');
|
||||||
|
}
|
||||||
|
var i = bytesToInt(byte);
|
||||||
|
var bm = ('00000000' + Number(i).toString(2)).substr(-8).split('').map(Number).map(Boolean);
|
||||||
|
return ['adr', 'screensaver', 'screen', 'countermode', 'blescan', 'antenna', 'reserved', 'reserved']
|
||||||
|
.reduce(function (obj, pos, index) {
|
||||||
|
obj[pos] = +bm[index];
|
||||||
|
return obj;
|
||||||
|
}, {});
|
||||||
|
};
|
||||||
|
bitmap1.BYTES = 1;
|
||||||
|
|
||||||
|
var bitmap2 = function (byte) {
|
||||||
|
if (byte.length !== bitmap2.BYTES) {
|
||||||
|
throw new Error('Bitmap must have exactly 1 byte');
|
||||||
|
}
|
||||||
|
var i = bytesToInt(byte);
|
||||||
|
var bm = ('00000000' + Number(i).toString(2)).substr(-8).split('').map(Number).map(Boolean);
|
||||||
|
return ['battery', 'sensor3', 'sensor2', 'sensor1', 'gps', 'bme', 'reserved', 'counter']
|
||||||
|
.reduce(function (obj, pos, index) {
|
||||||
|
obj[pos] = +bm[index];
|
||||||
|
return obj;
|
||||||
|
}, {});
|
||||||
|
};
|
||||||
|
bitmap2.BYTES = 1;
|
||||||
|
|
||||||
|
var decode = function (bytes, mask, names) {
|
||||||
|
|
||||||
|
var maskLength = mask.reduce(function (prev, cur) {
|
||||||
|
return prev + cur.BYTES;
|
||||||
|
}, 0);
|
||||||
|
if (bytes.length < maskLength) {
|
||||||
|
throw new Error('Mask length is ' + maskLength + ' whereas input is ' + bytes.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
names = names || [];
|
||||||
|
var offset = 0;
|
||||||
|
return mask
|
||||||
|
.map(function (decodeFn) {
|
||||||
|
var current = bytes.slice(offset, offset += decodeFn.BYTES);
|
||||||
|
return decodeFn(current);
|
||||||
|
})
|
||||||
|
.reduce(function (prev, cur, idx) {
|
||||||
|
prev[names[idx] || idx] = cur;
|
||||||
|
return prev;
|
||||||
|
}, {});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof module === 'object' && typeof module.exports !== 'undefined') {
|
||||||
|
module.exports = {
|
||||||
|
uint8: uint8,
|
||||||
|
uint16: uint16,
|
||||||
|
uint32: uint32,
|
||||||
|
int8: int8,
|
||||||
|
int16: int16,
|
||||||
|
int32: int32,
|
||||||
|
uptime: uptime,
|
||||||
|
float: float,
|
||||||
|
ufloat: ufloat,
|
||||||
|
pressure: pressure,
|
||||||
|
latLng: latLng,
|
||||||
|
hdop: hdop,
|
||||||
|
altitude: altitude,
|
||||||
|
bitmap1: bitmap1,
|
||||||
|
bitmap2: bitmap2,
|
||||||
|
version: version,
|
||||||
|
decode: decode
|
||||||
|
};
|
||||||
|
}
|
24
src/lorawan-devices-repo/vendor/opensource/esp32-paxcounter-profile-eu868.yaml
vendored
Normal file
24
src/lorawan-devices-repo/vendor/opensource/esp32-paxcounter-profile-eu868.yaml
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Vendor profile ID, can be freely issued by the vendor
|
||||||
|
# This vendor profile ID is also used on the QR code for LoRaWAN devices, see
|
||||||
|
# https://lora-alliance.org/sites/default/files/2020-10/LoRa_Alliance_Vendor_ID_for_QR_Code.pdf
|
||||||
|
#vendorProfileID: 0
|
||||||
|
# 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.3
|
||||||
|
# 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.3-RevA
|
||||||
|
# Whether the end device supports join (OTAA) or not (ABP)
|
||||||
|
supportsJoin: true
|
||||||
|
# Maximum EIRP
|
||||||
|
maxEIRP: 16
|
||||||
|
# Whether the end device supports 32-bit frame counters
|
||||||
|
supports32bitFCnt: true
|
24
src/lorawan-devices-repo/vendor/opensource/esp32-paxcounter-profile-us915.yaml
vendored
Normal file
24
src/lorawan-devices-repo/vendor/opensource/esp32-paxcounter-profile-us915.yaml
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Vendor profile ID, can be freely issued by the vendor
|
||||||
|
# This vendor profile ID is also used on the QR code for LoRaWAN devices, see
|
||||||
|
# https://lora-alliance.org/sites/default/files/2020-10/LoRa_Alliance_Vendor_ID_for_QR_Code.pdf
|
||||||
|
#vendorProfileID: 0
|
||||||
|
# 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.3
|
||||||
|
# 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.3-RevA
|
||||||
|
# Whether the end device supports join (OTAA) or not (ABP)
|
||||||
|
supportsJoin: true
|
||||||
|
# Maximum EIRP
|
||||||
|
maxEIRP: 30
|
||||||
|
# Whether the end device supports 32-bit frame counters
|
||||||
|
supports32bitFCnt: true
|
131
src/lorawan-devices-repo/vendor/opensource/esp32-paxcounter.yaml
vendored
Normal file
131
src/lorawan-devices-repo/vendor/opensource/esp32-paxcounter.yaml
vendored
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
name: ESP32-Paxcounter
|
||||||
|
description: Software providing a basis on the esp32 platform for multiple sensors, including pax (ble/wifi), gps, temperature, humidity, pressure, pm2.5, pm10 and more.
|
||||||
|
|
||||||
|
# Hardware versions (optional, use when you have revisions)
|
||||||
|
#hardwareVersions:
|
||||||
|
# - version: '1.0'
|
||||||
|
# numeric: 1
|
||||||
|
|
||||||
|
# Firmware versions (at least one is mandatory)
|
||||||
|
# LoRaWAN Device Profiles per region
|
||||||
|
# Supported regions are EU863-870, US902-928, AU915-928, AS923, CN779-787, EU433, CN470-510, KR920-923, IN865-867, RU864-870
|
||||||
|
firmwareVersions:
|
||||||
|
- version: '2.4.0'
|
||||||
|
numeric: 240
|
||||||
|
profiles:
|
||||||
|
EU863-870:
|
||||||
|
id: esp32-paxcounter-profile-eu868
|
||||||
|
#lorawanCertified: true
|
||||||
|
codec: esp32-paxcounter-codec
|
||||||
|
US902-928:
|
||||||
|
id: esp32-paxcounter-profile-us915
|
||||||
|
#lorawanCertified: true
|
||||||
|
codec: esp32-paxcounter-codec
|
||||||
|
|
||||||
|
- version: '3.0.0'
|
||||||
|
numeric: 300
|
||||||
|
profiles:
|
||||||
|
EU863-870:
|
||||||
|
id: esp32-paxcounter-profile-eu868
|
||||||
|
#lorawanCertified: true
|
||||||
|
codec: esp32-paxcounter-codec
|
||||||
|
US902-928:
|
||||||
|
id: esp32-paxcounter-profile-us915
|
||||||
|
#lorawanCertified: true
|
||||||
|
codec: esp32-paxcounter-codec
|
||||||
|
|
||||||
|
# Sensors that this device features (optional)
|
||||||
|
# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity,
|
||||||
|
# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light,
|
||||||
|
# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer,
|
||||||
|
# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, smart valve, snr, so2,
|
||||||
|
# solar radiation, sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity,
|
||||||
|
# vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed.
|
||||||
|
sensors:
|
||||||
|
- battery
|
||||||
|
- ble
|
||||||
|
- wifi
|
||||||
|
- pax
|
||||||
|
- gps
|
||||||
|
- altitude
|
||||||
|
- latitude
|
||||||
|
- longitude
|
||||||
|
- hdop
|
||||||
|
- sats
|
||||||
|
- temperature
|
||||||
|
- humidity
|
||||||
|
- barometer
|
||||||
|
- pm2.5
|
||||||
|
- pm10
|
||||||
|
|
||||||
|
# Dimensions in mm (optional)
|
||||||
|
# Use width, height, length and/or diameter
|
||||||
|
#dimensions:
|
||||||
|
# width: 22.5
|
||||||
|
# length: 119
|
||||||
|
# height: 101
|
||||||
|
|
||||||
|
# Weight in grams (optional)
|
||||||
|
#weight: 160
|
||||||
|
|
||||||
|
## Operating conditions (optional)
|
||||||
|
#operatingConditions:
|
||||||
|
# Temperature (Celsius)
|
||||||
|
# temperature:
|
||||||
|
# min: -30
|
||||||
|
# max: 60
|
||||||
|
# Relative humidity (fraction of 1)
|
||||||
|
# relativeHumidity:
|
||||||
|
# min: 0
|
||||||
|
# max: 0.9
|
||||||
|
|
||||||
|
# IP rating (optional)
|
||||||
|
#ipCode: IP20
|
||||||
|
|
||||||
|
# Key provisioning (optional)
|
||||||
|
# Valid values are: custom (user can configure keys), join server and manifest.
|
||||||
|
keyProvisioning:
|
||||||
|
- custom
|
||||||
|
- join server
|
||||||
|
|
||||||
|
# Key security (optional)
|
||||||
|
# Valid values are: none, read protected and secure element.
|
||||||
|
keySecurity: none
|
||||||
|
|
||||||
|
# Product and data sheet URLs (optional)
|
||||||
|
productURL: https://github.com/cyberman54/ESP32-Paxcounter
|
||||||
|
dataSheetURL: https://github.com/cyberman54/ESP32-Paxcounter
|
||||||
|
#resellerURLs:
|
||||||
|
# - name: 'Reseller 1'
|
||||||
|
# region:
|
||||||
|
# - European Union
|
||||||
|
# url: https://example.org/reseller1
|
||||||
|
# - name: 'Reseller 2'
|
||||||
|
# region:
|
||||||
|
# - United States
|
||||||
|
# - Canada
|
||||||
|
# url: https://example.org/reseller2
|
||||||
|
|
||||||
|
# Photos
|
||||||
|
#photos:
|
||||||
|
# main: Paxcounter-title.jpg
|
||||||
|
# other:
|
||||||
|
# - Paxcounter-title.jpg
|
||||||
|
# Youtube or Vimeo Video (optional)
|
||||||
|
###video: https://www.youtube.com/watch?v=JHzxcD2oEn8
|
||||||
|
|
||||||
|
# Regulatory compliances (optional)
|
||||||
|
#compliances:
|
||||||
|
# safety:
|
||||||
|
# - body: IEC
|
||||||
|
# norm: EN
|
||||||
|
# standard: 62368-1
|
||||||
|
# radioEquipment:
|
||||||
|
# - body: ETSI
|
||||||
|
# norm: EN
|
||||||
|
# standard: 301 489-1
|
||||||
|
# version: 2.2.0
|
||||||
|
# - body: ETSI
|
||||||
|
# norm: EN
|
||||||
|
# standard: 301 489-3
|
||||||
|
# version: 2.1.0
|
3
src/lorawan-devices-repo/vendor/opensource/index.yaml
vendored
Normal file
3
src/lorawan-devices-repo/vendor/opensource/index.yaml
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
endDevices:
|
||||||
|
# Unique identifier of the end device (lowercase, alphanumeric with dashes, max 36 characters)
|
||||||
|
- esp32-paxcounter # look in esp32-paxcounter.yaml for the end device definition
|
Loading…
Reference in New Issue
Block a user