diff --git a/vendor/index.yaml b/vendor/index.yaml index 74fcb41387..cbc3b0da39 100644 --- a/vendor/index.yaml +++ b/vendor/index.yaml @@ -591,6 +591,16 @@ vendors: name: Parametric Engineering GmbH vendorID: 315 + - id: pmx + name: PMX Systems AG + vendorID: 1141 + website: https://www.pmx.systems + logo: pmx-logo.svg + description: PMX Systems AG is a Swiss company specialising in smart outdoor sensors. + social: + linkedin: https://www.linkedin.com/company/pmx-systems + github: pmx-systems + - id: proesys name: ProEsys SRL vendorID: 323 diff --git a/vendor/pmx/index.yaml b/vendor/pmx/index.yaml new file mode 100644 index 0000000000..9643c7d5ae --- /dev/null +++ b/vendor/pmx/index.yaml @@ -0,0 +1,2 @@ +endDevices: + - pmx-tcr diff --git a/vendor/pmx/pmx-logo.svg b/vendor/pmx/pmx-logo.svg new file mode 100644 index 0000000000..ac87815c10 --- /dev/null +++ b/vendor/pmx/pmx-logo.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + Smart Sensors + + diff --git a/vendor/pmx/pmx-tcr-codec.yaml b/vendor/pmx/pmx-tcr-codec.yaml new file mode 100644 index 0000000000..444efbef48 --- /dev/null +++ b/vendor/pmx/pmx-tcr-codec.yaml @@ -0,0 +1,81 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://www.thethingsindustries.com/docs/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: pmx-tcr.js + examples: + - description: device id uplink + input: + fPort: 190 + bytes: [210, 10, 2, 2, 17, 0, 66, 0] + output: + data: + typestr: TCR-DLI + fu_level: PRO + speedclass: HS + fw_version: 1.1.0 + sbx_version: 4.2.0 + + - description: Unfiltered detections counter (UDC) uplink (port 13) + input: + fPort: 13 + bytes: [162, 20, 10, 3, 232, 50, 4, 76, 52, 51] + output: + data: + time: 2010 + udc_ltr_cnt: 1000 + udc_ltr_spd: 50 + udc_rtl_cnt: 1100 + udc_rtl_spd: 52 + volts: 5.1 + + - description: cat 1 counter uplink (port 14) + input: + fPort: 14 + bytes: [162, 20, 10, 3, 232, 50, 4, 76, 52, 51] + output: + data: + time: 2010 + cat1_ltr_cnt: 1000 + cat1_ltr_spd: 50 + cat1_rtl_cnt: 1100 + cat1_rtl_spd: 52 + volts: 5.1 + + - description: cat 2 counter uplink (port 15) + input: + fPort: 15 + bytes: [162, 20, 10, 3, 232, 50, 4, 76, 52, 51] + output: + data: + time: 2010 + cat2_ltr_cnt: 1000 + cat2_ltr_spd: 50 + cat2_rtl_cnt: 1100 + cat2_rtl_spd: 52 + volts: 5.1 + + - description: cat 3 counter uplink (port 16) + input: + fPort: 16 + bytes: [162, 20, 10, 3, 232, 50, 4, 76, 52, 51] + output: + data: + time: 2010 + cat3_ltr_cnt: 1000 + cat3_ltr_spd: 50 + cat3_rtl_cnt: 1100 + cat3_rtl_spd: 52 + volts: 5.1 + + - description: cat 4 counter uplink (port 17) + input: + fPort: 17 + bytes: [162, 20, 10, 3, 232, 50, 4, 76, 52, 51] + output: + data: + time: 2010 + cat4_ltr_cnt: 1000 + cat4_ltr_spd: 50 + cat4_rtl_cnt: 1100 + cat4_rtl_spd: 52 + volts: 5.1 diff --git a/vendor/pmx/pmx-tcr-kit.png b/vendor/pmx/pmx-tcr-kit.png new file mode 100644 index 0000000000..8e723e1375 Binary files /dev/null and b/vendor/pmx/pmx-tcr-kit.png differ diff --git a/vendor/pmx/pmx-tcr.js b/vendor/pmx/pmx-tcr.js new file mode 100644 index 0000000000..17c1caa0d3 --- /dev/null +++ b/vendor/pmx/pmx-tcr.js @@ -0,0 +1,223 @@ +/** + * PMX TCR Payload + * + * THIS SOFTWARE IS PROVIDED BY PMX SYSTEMS AG AND ITS CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * +*/ +const DeviceTypes = [ + "TCR-LS", /* 0 Low Speed (2 Speed Groups) */ + "TCR-LSS", /* 1 Low Speed Solar (2 Speed Groups) */ + "TCR-HS", /* 2 High Speed (4 Speed Groups) */ + "TCR-HSS", /* 3 High Speed Solar (4 Speed Groups) */ + "TCR-LSA", /* 4 Low Speed AC Powered (2 Speed Groups) */ + "TCR-LSB", /* 5 Low Speed AC External Battery Powered (4 Speed Groups) */ + "TCR-HSA", /* 6 High Speed AC Powered (4 Speed Groups) */ + "TCR-HSB", /* 7 High Speed External Battery Powered (4 Speed Groups) */ + "TCR-LSBS", /* 8 Low Speed External Battery (External) + Solar (2 Speed Groups) */ + "TCR-HSBS", /* 9 High Speed External Battery (External) + Solar (4 Speed Groups) */ + "TCR-DLI", /* 10 DC powered, LoRaWAN, Internal Antenna */ + "TCR-DLE", /* 11 DC powered, LoRaWAN, External Antenna */ + "TCR-SLI", /* 12 Solar powered, LoRaWAN, Internal Antenna */ + "TCR-SLE", /* 13 Solar powered, LoRaWAN, External Antenna */ + "PCR2-OD", /* 14 Outdoor Models w/o battery*/ + "PCR2-ODS", /* 15 Outdoor Models, Solar Powered */ +]; + +// Function levels +const FeatureLevel = [ + "BASIC", /* 0 BASIC Features enabled (no licence installed) */ + "ADVANCED", /* 1 ADVANCED Features enabled */ + "PRO" /* 2 PRO Features enabled */ +]; + +// Speed classes +const SpeedClassTypes = [ + "P", /* 0 Speed class for people counting (very low speed) */ + "LS", /* 1 Low speed traffic counting */ + "HS" /* 2 High speed traffic counting */ +]; + +// Array of all available config keys (since JavaScript has no enum) +// Use this array to have a key instead of just an index number +const ConfigKeys = { + + // 0 Totals + LR_CF_CMD_CAT0_ENABLED: 0x01, /** Enable category */ + LR_CF_CMD_CAT0_MIN_SIZE: 0x02, /** Change min object size of category */ + LR_CF_CMD_CAT0_MAX_SIZE: 0x03, /** Overwrite max object size of category */ + LR_CF_CMD_CAT0_MIN_SPEED: 0x04, /** Overwrite min object speed of category */ + LR_CF_CMD_CAT0_MAX_SPEED: 0x05, /** Overwrite max object speed of category */ + + // 1 + LR_CF_CMD_CAT1_ENABLED: 0x11, /** Enable category */ + LR_CF_CMD_CAT1_MIN_SIZE: 0x12, /** Overwrite min object size of category */ + LR_CF_CMD_CAT1_MAX_SIZE: 0x13, /** Overwrite max object size of category */ + LR_CF_CMD_CAT1_MIN_SPEED: 0x14, /** Overwrite min object speed of category */ + LR_CF_CMD_CAT1_MAX_SPEED: 0x15, /** Overwrite max object speed of category */ + + // 2 + LR_CF_CMD_CAT2_ENABLED: 0x21, /** Enable category */ + LR_CF_CMD_CAT2_MIN_SIZE: 0x22, /** Overwrite min object size of category */ + LR_CF_CMD_CAT2_MAX_SIZE: 0x23, /** Overwrite max object size of category */ + LR_CF_CMD_CAT2_MIN_SPEED: 0x24, /** Overwrite min object speed of category */ + LR_CF_CMD_CAT2_MAX_SPEED: 0x25, /** Overwrite max object speed of category */ + + // 3 + LR_CF_CMD_CAT3_ENABLED: 0x31, /** Enable category */ + LR_CF_CMD_CAT3_MIN_SIZE: 0x32, /** Overwrite min object size of category */ + LR_CF_CMD_CAT3_MAX_SIZE: 0x33, /** Overwrite max object size of category */ + LR_CF_CMD_CAT3_MIN_SPEED: 0x34, /** Overwrite min object speed of category */ + LR_CF_CMD_CAT3_MAX_SPEED: 0x35, /** Overwrite max object speed of category */ + + // 4 + LR_CF_CMD_CAT4_ENABLED: 0x41, /** Enable category */ + LR_CF_CMD_CAT4_MIN_SIZE: 0x42, /** Overwrite min object size of category */ + LR_CF_CMD_CAT4_MAX_SIZE: 0x43, /** Overwrite max object size of category */ + LR_CF_CMD_CAT4_MIN_SPEED: 0x44, /** Overwrite min object speed of category */ + LR_CF_CMD_CAT4_MAX_SPEED: 0x45, /** Overwrite max object speed of category */ + + /* Device Settings */ + LR_CF_CMD_LIC_KEY: 0x51, /** Licence Key RW */ + LR_CF_CMD_FU_LEVEL: 0x52, /** Feauture Level RO*/ + LR_CF_CMD_SPEED_CLASS: 0x53, /** Feauture Level RO*/ + LR_CF_CMD_MEAS_INTERVAL: 0x54, /** Meas Interval RW */ + + /* Radar Settings */ + LR_CF_CMD_RADAR_ENABLED: 0x61, /** Switch radar module on / off */ + LR_CF_CMD_RADAR_CHANNEL: 0x62, /** Choose Radar Channel: 1, 2 */ + LR_CF_CMD_RADAR_SENS: 0x63, /** Radar Sensitivity Level [%]*/ + LR_CF_CMD_RADAR_AUTOSENS: 0x64, /** Enable Autosens, 0 = off , 1 = on */ + + /* LoRaWAN Settings */ + LR_CF_CMD_LORA_UL_CONFIRMED: 0x71, /** Set confirmed uplinks mode*/ + + + LR_CF_CMD_CLEAR: 0xcc, /** cf starts the configuration uplink sequence */ + LR_CF_CMD_CONFIG_SEQ: 0xcf, /** cf starts the configuration uplink sequence */ + LR_CF_CMD_DEFAULTS: 0xdf, /** df set factory defaults (use ee for saving to ROM) */ + LR_CF_CMD_RESTART: 0xee /** ee Restart device with new settings */ +}; + +function d2_decoder(bytes, port) { + var obj = {}; + obj.typestr = DeviceTypes[bytes[1]]; // 00: TCR-LS, 01: TCR-LSS , ... + obj.fu_level = FeatureLevel[bytes[2]]; // 00: BASIC, 01: ADVANCED , ... + obj.speedclass = SpeedClassTypes[bytes[3]]; // 00: Speedclass, 01: LS , 02: HS + obj.fw_version = (bytes[4] & 0xf0) / 0x10 + "." + (bytes[4] & 0x0f) + "." + bytes[5]; // Firmware Major Version + obj.sbx_version = (bytes[6] & 0xf0) / 0x10 + "." + (bytes[6] & 0x0f) + "." + bytes[7]; // SBX Solar Charger Firmware Version + return obj; +} + +function a2_decoder(bytes, port) { + var obj = {}; + + if (port == 13) // Unfiltered Detections + { + obj.time = bytes[1] * 100 + bytes[2]; // Measure Interval End Timestamp (Military Time format) + obj.udc_ltr_cnt = (bytes[3] << 8) | (bytes[4]); // Left-to-Right (LTR) Counter Value (0-65535) + obj.udc_ltr_spd = bytes[5]; // Left-to-Right (LTR) average speed of all objects counted in this interval [km/h] + obj.udc_rtl_cnt = (bytes[6] << 8) | (bytes[7]); // Right-to-Left (RTL) Counter Value (0-65535) + obj.udc_rtl_spd = bytes[8]; // Right-to-Left (RTL) average speed of all objects counted in this interval [km/h] + } + + if (port == 14) // Filter Category 1 + { + obj.time = bytes[1] * 100 + bytes[2]; // Measure Interval End Timestamp (Military Time format) + obj.cat1_ltr_cnt = (bytes[3] << 8) | (bytes[4]); // Left-to-Right (LTR) Counter Value (0-65535) + obj.cat1_ltr_spd = bytes[5]; // Left-to-Right (LTR) average speed of all objects counted in this interval [km/h] + obj.cat1_rtl_cnt = (bytes[6] << 8) | (bytes[7]); // Right-to-Left (RTL) Counter Value (0-65535) + obj.cat1_rtl_spd = bytes[8]; // Right-to-Left (RTL) average speed of all objects counted in this interval [km/h] + } + + if (port == 15) // Filter Category 2 + { + obj.time = bytes[1] * 100 + bytes[2]; // Measure Interval End Timestamp (Military Time format) + obj.cat2_ltr_cnt = (bytes[3] << 8) | (bytes[4]); // Left-to-Right (LTR) Counter Value (0-65535) + obj.cat2_ltr_spd = bytes[5]; // Left-to-Right (LTR) average speed of all objects counted in this interval [km/h] + obj.cat2_rtl_cnt = (bytes[6] << 8) | (bytes[7]); // Right-to-Left (RTL) Counter Value (0-65535) + obj.cat2_rtl_spd = bytes[8]; // Right-to-Left (RTL) average speed of all objects counted in this interval [km/h] + } + + if (port == 16) // Filter Category 3 + { + obj.time = bytes[1] * 100 + bytes[2]; // Measure Interval End Timestamp (Military Time format) + obj.cat3_ltr_cnt = (bytes[3] << 8) | (bytes[4]); // Left-to-Right (LTR) Counter Value (0-65535) + obj.cat3_ltr_spd = bytes[5]; // Left-to-Right (LTR) average speed of all objects counted in this interval [km/h] + obj.cat3_rtl_cnt = (bytes[6] << 8) | (bytes[7]); // Right-to-Left (RTL) Counter Value (0-65535) + obj.cat3_rtl_spd = bytes[8]; // Right-to-Left (RTL) average speed of all objects counted in this interval [km/h] + } + + if (port == 17) // Filter Category 4 + { + obj.time = bytes[1] * 100 + bytes[2]; // Measure Interval End Timestamp (Military Time format) + obj.cat4_ltr_cnt = (bytes[3] << 8) | (bytes[4]); // Left-to-Right (LTR) Counter Value (0-65535) + obj.cat4_ltr_spd = bytes[5]; // Left-to-Right (LTR) average speed of all objects counted in this interval [km/h] + obj.cat4_rtl_cnt = (bytes[6] << 8) | (bytes[7]); // Right-to-Left (RTL) Counter Value (0-65535) + obj.cat4_rtl_spd = bytes[8]; // Right-to-Left (RTL) average speed of all objects counted in this interval [km/h] + } + + obj.volts = bytes[9] / 10; // Power supply voltage. Divide by 10 to get volts. + return obj; +} + +function c2_decoder(bytes, port) { + var obj = {}; + + // 8 Bit values + if (bytes.length == 3) { + obj[ConfigKeys[bytes[1]]] = bytes[2]; + } + + // 16 Bit values + if (bytes.length >= 4) { + obj[ConfigKeys[bytes[1]]] = (bytes[2] << 8) | (bytes[3]); + } + return obj; +} + +function bin16dec(bin) { + var num = bin & 0xFFFF; + if (0x8000 & num) num = -(0x010000 - num); + return num; +} + +function hexToBytes(hex) { + hex = hex.replace(/\s/g, ""); + for (var bytes = [], c = 0; c < hex.length; c += 2) + bytes.push(parseInt(hex.substr(c, 2), 16)); + return bytes; +} + + +function decodeUplink(input) { + var data = {}; + var bytes = input.bytes; + var port = input.fPort; + + // it's a Device ID Payload V2 (PMX Firmware for TCR) + if (port == 190 && bytes[0] == 0xd2) { + + data = d2_decoder(bytes, port); + } + + // it's a Counter Payload V2 (PMX Firmware for TCR) + if (port >= 13 && port <= 17 && bytes[0] == 0xa2) { + + data = a2_decoder(bytes, port); + } + + // it's a Config Payload Response (PMX Firmware for TCR) + if (port == 1 && bytes[0] == 0xc2) { + + data = c2_decoder(bytes, port); + } + return { + data: data, + }; +} \ No newline at end of file diff --git a/vendor/pmx/pmx-tcr.png b/vendor/pmx/pmx-tcr.png new file mode 100644 index 0000000000..721585ce5e Binary files /dev/null and b/vendor/pmx/pmx-tcr.png differ diff --git a/vendor/pmx/pmx-tcr.yaml b/vendor/pmx/pmx-tcr.yaml new file mode 100644 index 0000000000..34adc58120 --- /dev/null +++ b/vendor/pmx/pmx-tcr.yaml @@ -0,0 +1,87 @@ +name: LoRaWAN Radar Traffic Counter +description: PMX TCR LoRaWAN Radar Traffic Counter is a real-time traffic counting sensor for smart cities, providing accurate vehicle and pedestrian statistics for optimised traffic management and urban planning. + +# Hardware versions (optional, use when you have revisions) +hardwareVersions: + - version: '03' + numeric: 3 + - version: '04' + numeric: 4 + - version: '05' + numeric: 5 + +# Firmware versions (at least one is mandatory) +firmwareVersions: + - # Firmware version + version: '1.0.x' + numeric: 10 + hardwareVersions: + - '03' + - '04' + - '05' + + # 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 + profiles: + EU863-870: + # Identifier of the profile (lowercase, alphanumeric with dashes, max 36 characters) + id: profile-v11 + lorawanCertified: false + codec: pmx-tcr-codec + AS923: + id: profile-v11 + lorawanCertified: false + codec: pmx-tcr-codec + AU915-928: + id: profile-v11 + lorawanCertified: false + codec: pmx-tcr-codec + +# Type of device (optional) +# Valid values are: devkit, module, cots +deviceType: cots + +# Sensors that this device features (optional) +# Valid values are: +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, current, digital input, +# digital output, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, hall effect, humidity, iaq, infrared, leaf wetness, level, +# light, lightning, link, magnetometer, moisture, motion, nfc, no, no2, o3, occupancy, optical meter, particulate matter, ph, pir, +# pm2.5, pm10, potentiometer, power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, reed switch, rssi, +# sap flow, smart valve, smoke, snr, so2, solar radiation, sound, strain, surface temperature, switch, temperature, tilt, time, turbidity, +# tvoc, uv, vapor pressure, velocity, vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. +sensors: + - radar + +# IP rating (optional) +ipCode: IP65 + +# Key provisioning (optional) +# Valid values are: custom (user can configure keys), join server and manifest. +keyProvisioning: + - custom + +# Key programming (optional) +# Valid values are: bluetooth, nfc, wifi, ethernet (via a webpage), serial (when the user has a serial interface to set the keys) +# and firmware (when the user should change the firmware to set the keys). +keyProgramming: + - serial + +# Firmware programming (optional) +# Valid values are: serial (when the user has a serial interface to update the firmware), ethernet, fuota lorawan (when the device +# supports LoRaWAN FUOTA via standard interfaces) and fuota other (other wireless update mechanism). +firmwareProgramming: + - serial + +# Product and data sheet URLs (optional) +productURL: https://www.pmx.systems/products/tcr + +# Photos +photos: + main: pmx-tcr.png # Image needs to have a transparent background + other: + - pmx-tcr-kit.png + +# Youtube or Vimeo Video (optional) +videos: + main: https://www.youtube.com/watch?v=dC293LOZnWM diff --git a/vendor/pmx/profile-v104.yaml b/vendor/pmx/profile-v104.yaml new file mode 100644 index 0000000000..083e1bb502 --- /dev/null +++ b/vendor/pmx/profile-v104.yaml @@ -0,0 +1,25 @@ +# LoRaWAN MAC version: 1.0, 1.0.1, 1.0.2, 1.0.3, 1.0.4 or 1.1 +macVersion: '1.0.4' +# 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: 'RP002-1.0.1' + +# 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 + +# Whether the end device supports class B +supportsClassB: false + +# Whether the end device supports class C +supportsClassC: false diff --git a/vendor/pmx/profile-v11.yaml b/vendor/pmx/profile-v11.yaml new file mode 100644 index 0000000000..795e053eb2 --- /dev/null +++ b/vendor/pmx/profile-v11.yaml @@ -0,0 +1,25 @@ +# LoRaWAN MAC version: 1.0, 1.0.1, 1.0.2, 1.0.3, 1.0.4 or 1.1 +macVersion: '1.1' +# 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.1-RevB' + +# 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 + +# Whether the end device supports class B +supportsClassB: false + +# Whether the end device supports class C +supportsClassC: false