diff --git a/bin/validate.js b/bin/validate.js index cc203640cd..5a22c93f11 100644 --- a/bin/validate.js +++ b/bin/validate.js @@ -1,6 +1,8 @@ #!/usr/bin/env node -const Ajv = require('ajv'); +const Ajv = require('ajv/dist/2020'); +const addFormats = require('ajv-formats'); + const yargs = require('yargs'); const fs = require('fs'); const yaml = require('js-yaml'); @@ -11,6 +13,7 @@ const readChunk = require('read-chunk'); const imageType = require('image-type'); const ajv = new Ajv({ schemas: [require('../lib/payload.json'), require('../schema.json')] }); +addFormats(ajv); const options = yargs .usage('Usage: --vendor [--vendor-id ]') @@ -26,21 +29,12 @@ const options = yargs type: 'string', }).argv; -let validateVendorsIndex = ajv.compile({ - $ref: 'https://schema.thethings.network/devicerepository/1/schema#/definitions/vendorsIndex', -}); -let validateVendorIndex = ajv.compile({ - $ref: 'https://schema.thethings.network/devicerepository/1/schema#/definitions/vendorIndex', -}); -let validateEndDevice = ajv.compile({ - $ref: 'https://schema.thethings.network/devicerepository/1/schema#/definitions/endDevice', -}); -let validateEndDeviceProfile = ajv.compile({ - $ref: 'https://schema.thethings.network/devicerepository/1/schema#/definitions/endDeviceProfile', -}); -let validateEndDevicePayloadCodec = ajv.compile({ - $ref: 'https://schema.thethings.network/devicerepository/1/schema#/definitions/endDevicePayloadCodec', -}); +const schemaId = 'https://schema.thethings.network/devicerepository/1/schema'; +const validateVendorsIndex = ajv.getSchema(`${schemaId}#/$defs/vendorsIndex`); +const validateVendorIndex = ajv.getSchema(`${schemaId}#/$defs/vendorIndex`); +const validateEndDevice = ajv.getSchema(`${schemaId}#/$defs/endDevice`); +const validateEndDeviceProfile = ajv.getSchema(`${schemaId}#/$defs/endDeviceProfile`); +const validateEndDevicePayloadCodec = ajv.getSchema(`${schemaId}#/$defs/endDevicePayloadCodec`); function requireFile(path) { if (path.toLowerCase() !== path) { @@ -206,7 +200,7 @@ function requireImageDecode(fileName) { } function formatValidationErrors(errors) { - return errors.map((e) => `${e.dataPath} ${e.message}`); + return errors.map((e) => `${e.instancePath} ${e.message}`); } const vendors = yaml.load(fs.readFileSync(options.vendor)); @@ -283,17 +277,18 @@ vendors.vendors.forEach((v) => { console.log(`${v.id}: valid index`); const codecs = {}; - const deviceNames = {}; vendor.endDevices.forEach(async (d) => { const key = `${v.id}: ${d}`; const endDevicePath = `${folder}/${d}.yaml`; const endDevice = yaml.load(fs.readFileSync(endDevicePath)); + if (!validateEndDevice(endDevice)) { console.error(`${key}: invalid: ${formatValidationErrors(validateEndDevice.errors)}`); process.exit(1); } + console.log(`${key}: valid`); // Create a regex to check if the vendor's name is a standalone word in the device name diff --git a/lib/payload.json b/lib/payload.json index 1428bb863c..03e5a9f225 100644 --- a/lib/payload.json +++ b/lib/payload.json @@ -1,9 +1,9 @@ { - "$schema": "http://json-schema.org/draft-07/schema#", + "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schema.thethings.network/devicerepository/1/payload/schema", "title": "LoRaWAN Device Repository Payload", "description": "Payload definitions for the LoRaWAN Device Repository", - "definitions": { + "$defs": { "temperature": { "type": "number", "description": "Temperature (°C)", @@ -66,15 +66,15 @@ "properties": { "depth": { "description": "Depth of the soil measurement (cm)", - "$ref": "#/definitions/depth" + "$ref": "#/$defs/depth" }, "moisture": { "description": "Soil moisture (%)", - "$ref": "#/definitions/percentage" + "$ref": "#/$defs/percentage" }, "temperature": { "description": "Soil temperature (°C)", - "$ref": "#/definitions/temperature" + "$ref": "#/$defs/temperature" }, "ec": { "description": "Soil electrical conductivity (dS/m)", @@ -84,19 +84,19 @@ }, "pH": { "description": "Soil pH level", - "$ref": "#/definitions/pH" + "$ref": "#/$defs/pH" }, "n": { "description": "Concentration of Nitrogen in the soil (ppm)", - "$ref": "#/definitions/concentration" + "$ref": "#/$defs/concentration" }, "p": { "description": "Concentration of Phosphorus in the soil (ppm)", - "$ref": "#/definitions/concentration" + "$ref": "#/$defs/concentration" }, "k": { "description": "Concentration of Potassium in the soil (ppm)", - "$ref": "#/definitions/concentration" + "$ref": "#/$defs/concentration" } }, "additionalProperties": false @@ -111,11 +111,11 @@ }, "temperature": { "description": "Air temperature (°C)", - "$ref": "#/definitions/temperature" + "$ref": "#/$defs/temperature" }, "relativeHumidity": { "description": "Relative humidity (%)", - "$ref": "#/definitions/percentage" + "$ref": "#/$defs/percentage" }, "pressure": { "type": "number", @@ -125,11 +125,11 @@ }, "co2": { "description": "Concentration of CO2 in the air (ppm)", - "$ref": "#/definitions/concentration" + "$ref": "#/$defs/concentration" }, "lightIntensity": { "description": "Light intensity (lux)", - "$ref": "#/definitions/illuminance" + "$ref": "#/$defs/illuminance" } }, "additionalProperties": false @@ -139,11 +139,11 @@ "properties": { "speed": { "description": "Wind speed (m/s)", - "$ref": "#/definitions/speed" + "$ref": "#/$defs/speed" }, "direction": { "description": "Wind direction (°)", - "$ref": "#/definitions/direction" + "$ref": "#/$defs/direction" } }, "additionalProperties": false @@ -160,19 +160,19 @@ "properties": { "min": { "description": "Minimum temperature (°C)", - "$ref": "#/definitions/temperature" + "$ref": "#/$defs/temperature" }, "max": { "description": "Maximum temperature (°C)", - "$ref": "#/definitions/temperature" + "$ref": "#/$defs/temperature" }, "avg": { "description": "Average temperature (°C)", - "$ref": "#/definitions/temperature" + "$ref": "#/$defs/temperature" }, "current": { "description": "Current temperature (°C)", - "$ref": "#/definitions/temperature" + "$ref": "#/$defs/temperature" } } } @@ -238,13 +238,13 @@ "uplinkPayload": { "type": "array", "items": { - "$ref": "#/definitions/measurement" + "$ref": "#/$defs/measurement" } } }, "oneOf": [ { - "$ref": "#/definitions/uplinkPayload" + "$ref": "#/$defs/uplinkPayload" } ] } diff --git a/package-lock.json b/package-lock.json index 051ff8907b..eb92fe0f2b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,7 +1,7 @@ { "name": "lorawan-devices", "version": "1.0.0", - "lockfileVersion": 3, + "lockfileVersion": 2, "requires": true, "packages": { "": { @@ -22,21 +22,22 @@ "validate": "bin/validate.js" }, "devDependencies": { - "ajv": "^6.12.6", + "ajv": "^8.17.1", "ajv-cli": "^5.0.0", - "prettier": "^2.6.2" + "ajv-formats": "^3.0.1", + "prettier": "^2.8.8" } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -69,22 +70,6 @@ } } }, - "node_modules/ajv-cli/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/ajv-cli/node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -107,11 +92,22 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/ajv-cli/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } }, "node_modules/ansi-regex": { "version": "5.0.1", @@ -252,27 +248,15 @@ "dev": true }, "node_modules/fast-json-patch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-2.2.1.tgz", - "integrity": "sha512-4j5uBaTnsYAV5ebkidvxiLUYOwjQ+JSFljeqfTxCrH9bDmlCQaOJFS84oDJ2rAXZq2yskmk3ORfoP9DCwqFNig==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^2.0.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/fast-json-patch/node_modules/fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.1.tgz", + "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==", "dev": true }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "node_modules/fast-uri": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.2.tgz", + "integrity": "sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==", "dev": true }, "node_modules/file-type": { @@ -403,34 +387,12 @@ "ajv": "^8.0.0" } }, - "node_modules/json-schema-migrate/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/json-schema-migrate/node_modules/json-schema-traverse": { + "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -549,15 +511,6 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, - "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/queue": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", @@ -668,15 +621,6 @@ "xtend": "~4.0.1" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -758,5 +702,535 @@ "node": ">=10" } } + }, + "dependencies": { + "ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + } + }, + "ajv-cli": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ajv-cli/-/ajv-cli-5.0.0.tgz", + "integrity": "sha512-LY4m6dUv44HTyhV+u2z5uX4EhPYTM38Iv1jdgDJJJCyOOuqB8KtZEGjPZ2T+sh5ZIJrXUfgErYx/j3gLd3+PlQ==", + "dev": true, + "requires": { + "ajv": "^8.0.0", + "fast-json-patch": "3.1.1", + "glob": "^7.1.0", + "js-yaml": "^3.14.0", + "json-schema-migrate": "^2.0.0", + "json5": "^2.1.3", + "minimist": "^1.2.0" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + } + } + }, + "ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dev": true, + "requires": { + "ajv": "^8.0.0" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "csv-write-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/csv-write-stream/-/csv-write-stream-2.0.0.tgz", + "integrity": "sha512-QTraH6FOYfM5f+YGwx71hW1nR9ZjlWri67/D4CWtiBkdce0UAa91Vc0yyHg0CjC0NeEGnvO/tBSJkA1XF9D9GQ==", + "requires": { + "argparse": "^1.0.7", + "generate-object-property": "^1.0.0", + "ndjson": "^1.3.0" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + } + } + }, + "csv-writer": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/csv-writer/-/csv-writer-1.6.0.tgz", + "integrity": "sha512-NOx7YDFWEsM/fTRAJjRpPp8t+MKRVvniAg9wQlUKx20MFrPs73WLJhFf5iteqrxNYnsy924K3Iroh3yNHeYd2g==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-patch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.1.tgz", + "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==", + "dev": true + }, + "fast-uri": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.2.tgz", + "integrity": "sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==", + "dev": true + }, + "file-type": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-10.11.0.tgz", + "integrity": "sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw==" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha512-TuOwZWgJ2VAMEGJvAyPWvpqxSANF0LDpmyHauMjFYzaACvn+QTT/AZomvPCzVBV7yDN3OmwHQ5OvHaeLKre3JQ==", + "requires": { + "is-property": "^1.0.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "image-size": { + "version": "0.9.7", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.9.7.tgz", + "integrity": "sha512-KRVgLNZkr00YGN0qn9MlIrmlxbRhsCcEb1Byq3WKGnIV4M48iD185cprRtaoK4t5iC+ym2Q5qlArxZ/V1yzDgA==", + "requires": { + "queue": "6.0.2" + } + }, + "image-type": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/image-type/-/image-type-4.1.0.tgz", + "integrity": "sha512-CFJMJ8QK8lJvRlTCEgarL4ro6hfDQKif2HjSvYCdQZESaIPV4v9imrf7BQHK+sQeTeNeMpWciR9hyC/g8ybXEg==", + "requires": { + "file-type": "^10.10.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "requires": { + "argparse": "^2.0.1" + } + }, + "json-schema-migrate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/json-schema-migrate/-/json-schema-migrate-2.0.0.tgz", + "integrity": "sha512-r38SVTtojDRp4eD6WsCqiE0eNDt4v1WalBXb9cyZYw9ai5cGtBwzRNWjHzJl38w6TxFkXAIA7h+fyX3tnrAFhQ==", + "dev": true, + "requires": { + "ajv": "^8.0.0" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "ndjson": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/ndjson/-/ndjson-1.5.0.tgz", + "integrity": "sha512-hUPLuaziboGjNF7wHngkgVc0FOclR8dDk/HfEvTtDr/iUrqBWiRcRSTK3/nLOqKH33th714BrMmTPtObI9gZxQ==", + "requires": { + "json-stringify-safe": "^5.0.1", + "minimist": "^1.2.0", + "split2": "^2.1.0", + "through2": "^2.0.3" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==" + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + }, + "prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "requires": { + "inherits": "~2.0.3" + } + }, + "read-chunk": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-3.2.0.tgz", + "integrity": "sha512-CEjy9LCzhmD7nUpJ1oVOE6s/hBkejlcJEgLQHVnQznOSilOPb+kpKktlLfFDK3/WP43+F80xkUTM2VOkYoSYvQ==", + "requires": { + "pify": "^4.0.1", + "with-open-file": "^0.1.6" + } + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "split2": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", + "integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==", + "requires": { + "through2": "^2.0.2" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "with-open-file": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/with-open-file/-/with-open-file-0.1.7.tgz", + "integrity": "sha512-ecJS2/oHtESJ1t3ZfMI3B7KIDKyfN0O16miWxdn30zdh66Yd3LsRFebXZXq6GU4xfxLf6nVxp9kIqElb5fqczA==", + "requires": { + "p-finally": "^1.0.0", + "p-try": "^2.1.0", + "pify": "^4.0.1" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" + } } } diff --git a/package.json b/package.json index 7cfd3e4d65..1c91ef9385 100644 --- a/package.json +++ b/package.json @@ -21,9 +21,10 @@ }, "homepage": "https://github.com/TheThingsNetwork/lorawan-devices#readme", "devDependencies": { - "ajv": "^6.12.6", + "ajv": "^8.17.1", "ajv-cli": "^5.0.0", - "prettier": "^2.6.2" + "ajv-formats": "^3.0.1", + "prettier": "^2.8.8" }, "dependencies": { "csv-write-stream": "^2.0.0", @@ -34,5 +35,8 @@ "lodash.isequal": "^4.5.0", "read-chunk": "^3.2.0", "yargs": "^16.2.0" + }, + "overrides": { + "fast-json-patch": "3.1.1" } } diff --git a/schema.json b/schema.json index 34118c6040..aea052c930 100644 --- a/schema.json +++ b/schema.json @@ -1,9 +1,9 @@ { - "$schema": "http://json-schema.org/draft-07/schema#", + "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schema.thethings.network/devicerepository/1/schema", "title": "LoRaWAN Device Repository", "description": "Open source repository for LoRaWAN end devices and gateways", - "definitions": { + "$defs": { "identifier": { "type": "string", "pattern": "^[a-z0-9](?:[-]?[a-z0-9]){2,}$", @@ -15,7 +15,7 @@ }, "logo": { "allOf": [ - { "$ref": "#/definitions/localFile" }, + { "$ref": "#/$defs/localFile" }, { "type": "string", "pattern": "\\.(png|svg)$" @@ -24,7 +24,7 @@ }, "photo": { "allOf": [ - { "$ref": "#/definitions/localFile" }, + { "$ref": "#/$defs/localFile" }, { "type": "string", "pattern": "\\.(png|jpg|jpeg)$" @@ -65,7 +65,7 @@ "vendors": { "type": "array", "items": { - "$ref": "#/definitions/vendor" + "$ref": "#/$defs/vendor" } } }, @@ -77,7 +77,7 @@ "endDevices": { "type": "array", "items": { - "$ref": "#/definitions/identifier" + "$ref": "#/$defs/identifier" } }, "profileIDs": { @@ -89,7 +89,7 @@ "type": "object", "properties": { "endDeviceID": { - "$ref": "#/definitions/identifier" + "$ref": "#/$defs/identifier" }, "hardwareVersion": { "type": "string" @@ -99,7 +99,7 @@ "minLength": 1 }, "region": { - "$ref": "#/definitions/region" + "$ref": "#/$defs/region" } }, "required": ["endDeviceID", "hardwareVersion", "firmwareVersion", "region"] @@ -108,10 +108,10 @@ "type": "object", "properties": { "id": { - "$ref": "#/definitions/identifier" + "$ref": "#/$defs/identifier" }, "codec": { - "$ref": "#/definitions/identifier" + "$ref": "#/$defs/identifier" } }, "required": ["id", "codec"] @@ -129,7 +129,7 @@ "description": "Vendor of a device", "type": "object", "properties": { - "id": { "$ref": "#/definitions/identifier" }, + "id": { "$ref": "#/$defs/identifier" }, "name": { "type": "string", "minLength": 1 @@ -194,7 +194,7 @@ "type": "string", "format": "email" }, - "logo": { "$ref": "#/definitions/logo" } + "logo": { "$ref": "#/$defs/logo" } }, "required": ["id", "name"] }, @@ -247,7 +247,7 @@ "properties": { "fileName": { "allOf": [ - { "$ref": "#/definitions/localFile" }, + { "$ref": "#/$defs/localFile" }, { "type": "string", "pattern": "\\.js$" @@ -362,15 +362,15 @@ "decodeInput": { "allOf": [ { - "$ref": "#/definitions/endDevicePayloadCodec/definitions/scriptInput" + "$ref": "#/$defs/endDevicePayloadCodec/definitions/scriptInput" }, { "type": "object", "properties": { - "bytes": { "$ref": "#/definitions/frmPayload" }, + "bytes": { "$ref": "#/$defs/frmPayload" }, "fPort": { "allOf": [ - { "$ref": "#/definitions/fPort" }, + { "$ref": "#/$defs/fPort" }, { "type": "integer", "minimum": 1 @@ -385,7 +385,7 @@ "decodeOutput": { "allOf": [ { - "$ref": "#/definitions/endDevicePayloadCodec/definitions/scriptOutput" + "$ref": "#/$defs/endDevicePayloadCodec/definitions/scriptOutput" }, { "type": "object", @@ -415,7 +415,7 @@ "encodeInput": { "allOf": [ { - "$ref": "#/definitions/endDevicePayloadCodec/definitions/scriptInput" + "$ref": "#/$defs/endDevicePayloadCodec/definitions/scriptInput" }, { "type": "object", @@ -431,15 +431,15 @@ "encodeOutput": { "allOf": [ { - "$ref": "#/definitions/endDevicePayloadCodec/definitions/scriptOutput" + "$ref": "#/$defs/endDevicePayloadCodec/definitions/scriptOutput" }, { "type": "object", "properties": { - "bytes": { "$ref": "#/definitions/frmPayload" }, + "bytes": { "$ref": "#/$defs/frmPayload" }, "fPort": { "allOf": [ - { "$ref": "#/definitions/fPort" }, + { "$ref": "#/$defs/fPort" }, { "type": "integer", "minimum": 1 @@ -477,12 +477,12 @@ "normalizeUplinkOutput": { "allOf": [ { - "$ref": "#/definitions/endDevicePayloadCodec/definitions/scriptOutput" + "$ref": "#/$defs/endDevicePayloadCodec/definitions/scriptOutput" }, { "type": "object", "properties": { - "data": { "$ref": "https://schema.thethings.network/devicerepository/1/payload/schema#/definitions/uplinkPayload" } + "data": { "$ref": "https://schema.thethings.network/devicerepository/1/payload/schema#/$defs/uplinkPayload" } } }, { @@ -506,7 +506,7 @@ "properties": { "uplinkDecoder": { "allOf": [ - { "$ref": "#/definitions/script" }, + { "$ref": "#/$defs/script" }, { "type": "object", "properties": { @@ -516,13 +516,13 @@ "type": "object", "properties": { "input": { - "$ref": "#/definitions/endDevicePayloadCodec/definitions/decodeInput" + "$ref": "#/$defs/endDevicePayloadCodec/definitions/decodeInput" }, "output": { - "$ref": "#/definitions/endDevicePayloadCodec/definitions/decodeOutput" + "$ref": "#/$defs/endDevicePayloadCodec/definitions/decodeOutput" }, "normalizedOutput": { - "$ref": "#/definitions/endDevicePayloadCodec/definitions/normalizeUplinkOutput" + "$ref": "#/$defs/endDevicePayloadCodec/definitions/normalizeUplinkOutput" } } } @@ -533,7 +533,7 @@ }, "downlinkEncoder": { "allOf": [ - { "$ref": "#/definitions/script" }, + { "$ref": "#/$defs/script" }, { "type": "object", "properties": { @@ -543,10 +543,10 @@ "type": "object", "properties": { "input": { - "$ref": "#/definitions/endDevicePayloadCodec/definitions/encodeInput" + "$ref": "#/$defs/endDevicePayloadCodec/definitions/encodeInput" }, "output": { - "$ref": "#/definitions/endDevicePayloadCodec/definitions/encodeOutput" + "$ref": "#/$defs/endDevicePayloadCodec/definitions/encodeOutput" } } } @@ -557,7 +557,7 @@ }, "downlinkDecoder": { "allOf": [ - { "$ref": "#/definitions/script" }, + { "$ref": "#/$defs/script" }, { "type": "object", "properties": { @@ -567,10 +567,10 @@ "type": "object", "properties": { "input": { - "$ref": "#/definitions/endDevicePayloadCodec/definitions/decodeInput" + "$ref": "#/$defs/endDevicePayloadCodec/definitions/decodeInput" }, "output": { - "$ref": "#/definitions/endDevicePayloadCodec/definitions/decodeOutput" + "$ref": "#/$defs/endDevicePayloadCodec/definitions/decodeOutput" } } } @@ -622,13 +622,13 @@ "description": "Maximum delay for the end device to answer a MAC request or confirmed downlink frame (seconds)" }, "pingSlotPeriod": { - "$ref": "#/definitions/pingSlotPeriod" + "$ref": "#/$defs/pingSlotPeriod" }, "pingSlotDataRateIndex": { - "$ref": "#/definitions/dataRateIndex" + "$ref": "#/$defs/dataRateIndex" }, "pingSlotFrequency": { - "$ref": "#/definitions/frequency" + "$ref": "#/$defs/frequency" }, "supportsClassC": { "type": "boolean", @@ -644,32 +644,32 @@ "description": "LoRaWAN version" }, "regionalParametersVersion": { - "$ref": "#/definitions/regionalParametersVersion" + "$ref": "#/$defs/regionalParametersVersion" }, "supportsJoin": { "type": "boolean", "description": "End device supports join (OTAA) or not (ABP)" }, "rx1Delay": { - "$ref": "#/definitions/rxDelay", + "$ref": "#/$defs/rxDelay", "description": "RX1 delay" }, "rx1DataRateOffset": { - "$ref": "#/definitions/rxDataRateOffset", + "$ref": "#/$defs/rxDataRateOffset", "description": "RX1 data rate offset" }, "rx2DataRateIndex": { - "$ref": "#/definitions/dataRateIndex", + "$ref": "#/$defs/dataRateIndex", "description": "RX2 data rate index" }, "rx2Frequency": { - "$ref": "#/definitions/frequency", + "$ref": "#/$defs/frequency", "description": "RX2 channel frequency" }, "factoryPresetFrequencies": { "type": "array", "items": { - "$ref": "#/definitions/frequency" + "$ref": "#/$defs/frequency" }, "uniqueItems": true, "description": "List of factory preset frequencies" @@ -912,16 +912,16 @@ }, "profiles": { "type": "object", - "propertyNames": { "$ref": "#/definitions/region" }, + "propertyNames": { "$ref": "#/$defs/region" }, "patternProperties": { "": { "type": "object", "properties": { - "id": { "$ref": "#/definitions/identifier" }, + "id": { "$ref": "#/$defs/identifier" }, "lorawanCertified": { "type": "boolean" }, - "codec": { "$ref": "#/definitions/identifier" } + "codec": { "$ref": "#/$defs/identifier" } }, "required": ["id"] } @@ -1241,10 +1241,10 @@ "photos": { "type": "object", "properties": { - "main": { "$ref": "#/definitions/photo" }, + "main": { "$ref": "#/$defs/photo" }, "other": { "type": "array", - "items": { "$ref": "#/definitions/photo" } + "items": { "$ref": "#/$defs/photo" } } }, "required": ["main"] @@ -1252,23 +1252,23 @@ "videos": { "type": "object", "properties": { - "main": { "$ref": "#/definitions/video" }, + "main": { "$ref": "#/$defs/video" }, "other": { "type": "array", - "items": { "$ref": "#/definitions/video" } + "items": { "$ref": "#/$defs/video" } } } }, "compliances": { "type": "object", "properties": { - "safety": { "$ref": "#/definitions/compliances" }, - "radioEquipment": { "$ref": "#/definitions/compliances" } + "safety": { "$ref": "#/$defs/compliances" }, + "radioEquipment": { "$ref": "#/$defs/compliances" } } } }, "required": ["name", "firmwareVersions"] } }, - "oneOf": [{ "$ref": "#/definitions/endDevice" }, { "$ref": "#/definitions/endDeviceProfile" }, { "$ref": "#/definitions/vendorsIndex" }, { "$ref": "#/definitions/vendorIndex" }] + "oneOf": [{ "$ref": "#/$defs/endDevice" }, { "$ref": "#/$defs/endDeviceProfile" }, { "$ref": "#/$defs/vendorsIndex" }, { "$ref": "#/$defs/vendorIndex" }] } diff --git a/vendor/accuwatch/3chbatteryvoltagesensor.yaml b/vendor/accuwatch/3chbatteryvoltagesensor.yaml index dd11dc26d1..62abfbc293 100644 --- a/vendor/accuwatch/3chbatteryvoltagesensor.yaml +++ b/vendor/accuwatch/3chbatteryvoltagesensor.yaml @@ -1,12 +1,10 @@ -name: LoRaWAN Voltage Sensor # Device name can not contain the vendor name -description: 3 Channel Battery Volrage Sensor # Description of the device +name: LoraWan 3ch Voltage Sensor # Device name can not contain the vendor name +description: This custom-designed 3-Channel Battery Voltage Sensor is engineered to monitor the voltage of up to three separate batteries with a shared ground connection, making it ideal for applications where multiple batteries need simultaneous tracking. Constructed with an IP67-rated waterproof enclosure, it is built to withstand harsh environments, including marine and outdoor applications, where water and dust resistance are crucial. # Hardware versions (optional, use when you have revisions) hardwareVersions: - version: '1.0' numeric: 1 - - version: '1.0-rev-A' - numeric: 2 # Firmware versions (at least one is mandatory) firmwareVersions: @@ -17,23 +15,15 @@ firmwareVersions: hardwareVersions: - '1.0' - # Firmware features (optional) - # Valid values are: remote rejoin (trigger a join from the application layer), transmission interval (configure how - # often he device sends a message). - # features: - # - remote rejoin - # - transmission interval - # 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: # Optional identifier of the vendor of the profile. When you specify the vendorID, the profile is loaded from # the vendorID's folder. This allows you to reuse profiles from module or LoRaWAN end device stack vendors. # If vendorID is empty, the current vendor ID is used. In this example, the vendorID is the current vendor ID, # which is verbose. - vendorID: + vendorID: accuwatch # Identifier of the profile (lowercase, alphanumeric with dashes, max 36 characters) id: 3chbatteryvoltagesensor-profile lorawanCertified: true @@ -59,10 +49,6 @@ sensors: additionalRadios: - wifi -# Bridge interfaces (optional) -# Valid values are: modbus, m-bus, can bus, rs-485, sdi-12, analog, ethernet. -# bridgeInterfaces: - # Dimensions in mm (optional) # Use width, height, length and/or diameter dimensions: @@ -79,15 +65,15 @@ weight: 190 # type: AA # # Operating conditions (optional) -# operatingConditions: -# # Temperature (Celsius) -# temperature: -# min: -30 -# max: 85 -# # Relative humidity (fraction of 1) -# relativeHumidity: -# min: 0 -# max: 0.97 +# operatingConditions: +# # Temperature (Celsius) +# temperature: +# min: -30 +# max: 85 +# # Relative humidity (fraction of 1) +# relativeHumidity: +# min: 0 +# max: 0.97 # IP rating (optional) ipCode: IP67 @@ -95,19 +81,18 @@ ipCode: IP67 # Key provisioning (optional) # Valid values are: custom (user can configure keys), join server and manifest. keyProvisioning: - # - custom - join server # 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: +# keyProgramming: # - serial # - firmware # Key security (optional) # Valid values are: none, read protected and secure element. -#keySecurity: none +keySecurity: read protected # Firmware programming (optional) # Valid values are: serial (when the user has a serial interface to update the firmware), ethernet, fuota lorawan (when the device @@ -117,27 +102,19 @@ firmwareProgramming: - fuota lorawan # Product and data sheet URLs (optional) -# productURL: https://accuwatch.nl/LoRaWAN-voltage-sensor +productURL: https://accuwatch.nl/LoRaWAN-voltage-sensor # dataSheetURL: https://accuwatch.nl/LoRaWAN-voltage-sensor/datasheet.pdf # Link to simple, easy onboarding instructions for the device (optional). # Please do not use this for marketing or overly technical documents like a data sheet. # onboardingGuideURL: https://www.thethingsindustries.com/docs/devices/models/windsensor # Commercial information -# resellerURLs: -# - name: 'Reseller 1' -# region: # valid regions are: Argentina, Australia, Brazil, Canada, China, European Union, India, Indonesia. -# # Japan, Mexico, Russia, Saudi Arabia, South Africa, South Korea, Turkey, United States, Other -# - European Union -# url: https://accuwatch.nl/reseller1 -# - name: 'Reseller 2' -# region: -# - United States -# - Canada -# url: https://accuwatch.nl/reseller2 -# msrp: -# EUR: 90 -# USD: 120 +resellerURLs: + - name: 'AccuWatch' + region: # valid regions are: Argentina, Australia, Brazil, Canada, China, European Union, India, Indonesia. + # # Japan, Mexico, Russia, Saudi Arabia, South Africa, South Korea, Turkey, United States, Other + - European Union + url: https://accuwatch.nl/ # Photos photos: diff --git a/vendor/accuwatch/index.yaml b/vendor/accuwatch/index.yaml index d9286ab6ea..53e1c440b3 100644 --- a/vendor/accuwatch/index.yaml +++ b/vendor/accuwatch/index.yaml @@ -1,17 +1,3 @@ -# This example contains just one end device: windsensor. It is referenced here in the index. - endDevices: # Unique identifier of the end device (lowercase, alphanumeric with dashes, max 36 characters) - 3chbatteryvoltagesensor # look in 3chbatteryvoltagesensor.yaml for the end device definition - -# The profileIDs is a distinct value for every unique profile listed in the vendor's folder. -# This value can be freely issued by the vendor and is also used on the QR code for LoRaWAN devices, see -# https://lora-alliance.org/wp-content/uploads/2020/11/TR005_LoRaWAN_Device_Identification_QR_Codes.pdf#page=8 -# It can either be a combo of device ID + hardware version + firmware version + region, or profile ID + codec ID -# NOTE: The profileIDs is different from the vendorID. -profileIDs: - '1': - endDeviceID: '3chbatteryvoltagesensor' - firmwareVersion: '1.0' - hardwareVersion: '1.0' - region: 'EU863-870' diff --git a/vendor/index.yaml b/vendor/index.yaml index c43c941c57..5bf0f71347 100644 --- a/vendor/index.yaml +++ b/vendor/index.yaml @@ -2102,3 +2102,6 @@ vendors: website: https://www.infrafon.com/ social: linkedin: https://de.linkedin.com/company/infrafon + + - id: makerfabs + name: AgroSense diff --git a/vendor/makerfabs/ath20-codec.yaml b/vendor/makerfabs/ath20-codec.yaml new file mode 100644 index 0000000000..e5bd7ad6df --- /dev/null +++ b/vendor/makerfabs/ath20-codec.yaml @@ -0,0 +1,61 @@ +# 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: ath20.js + # Examples (optional) + examples: + - description: Temperature + input: + fPort: 2 + bytes: [0x00, 0x01, 0x1F, 0x02, 0x0B, 0x01, 0x32, 0x00, 0x00, 0x00, 0x01] + output: + data: { 'Bat': 3.1, 'Humi': 52.3, 'Temp': 30.6 } + # # Normalized output, uses the normalizeUplink function (optional) + # normalizedOutput: + # data: + # - air: + # location: 'indoor' + # temperature: 30.6 + # relativeHumidity: 52.3 + # - air: + # location: 'outdoor' + # temperature: 27.81 + # battery: 3.062 + + # - description: Unknown FPort + # input: + # fPort: 42 + # bytes: [0x00, 0x01, 0x1F, 0x02, 0x0B, 0x01, 0x32, 0x00, 0x00, 0x00, 0x01] + # output: + # errors: + # - unknown FPort + +# Downlink encoder encodes JSON object into a binary data downlink (optional) +downlinkEncoder: + fileName: ath20.js + examples: + - description: Change Reporting interval + input: + data: + minutes: 10 + output: + bytes: [0x00, 0x00, 0x02, 0x58] + fPort: 1 + # - description: Invalid color + # input: + # data: + # led: blue + # output: + # errors: + # - invalid LED color +# # Downlink decoder decodes the encoded downlink message (optional, must be symmetric with downlinkEncoder) +# downlinkDecoder: +# fileName: Air-Temperature-and-Humidity-Sensor.js +# examples: +# - description: Turn green +# input: +# fPort: 2 +# bytes: [1] +# output: +# data: +# led: green diff --git a/vendor/makerfabs/ath20.jpg b/vendor/makerfabs/ath20.jpg new file mode 100644 index 0000000000..362bdd152f Binary files /dev/null and b/vendor/makerfabs/ath20.jpg differ diff --git a/vendor/makerfabs/ath20.js b/vendor/makerfabs/ath20.js new file mode 100644 index 0000000000..54e5470995 --- /dev/null +++ b/vendor/makerfabs/ath20.js @@ -0,0 +1,54 @@ +function decodeUplink(input) { + + // var num = input.bytes[0] * 256 + input.bytes[1] + var bat = input.bytes[2] / 10.0 + var humi = (input.bytes[3] * 256 + input.bytes[4]) / 10.0 + // var temp = (input.bytes[5] * 256 + input.bytes[6] ) / 10.0 + + var temp = input.bytes[5] * 256 + input.bytes[6] + if (temp >= 0x8000) { + temp -= 0x10000; + } + temp = temp / 10.0 + + + return { + data: { + Bat: bat, + Humi: humi, + Temp: temp, + }, + + }; +} + + + +// Encoder function to be used in the TTN console for downlink payload +function encodeDownlink(input) { + var minutes = input.data.minutes; + + // Converting minutes to seconds + var seconds = minutes * 60; + + // If the number of seconds is less than 300 seconds, set it to 300 seconds + if (seconds < 300) { + seconds = 300; + } + var bytes1 = (seconds >> 24) & 0xFF; + var bytes2 = (seconds >> 16) & 0xFF; + var bytes3 = (seconds >> 8) & 0xFF; + var bytes4 = seconds & 0xFF; + + // var payload = [ + // (seconds >> 24) & 0xFF, + // (seconds >> 16) & 0xFF, + // (seconds >> 8) & 0xFF, + // seconds & 0xFF + // ]; + + return { + bytes: [bytes1,bytes2,bytes3,bytes4], + fPort: 1, + }; +} \ No newline at end of file diff --git a/vendor/makerfabs/ath20.yaml b/vendor/makerfabs/ath20.yaml new file mode 100644 index 0000000000..15d979d8e0 --- /dev/null +++ b/vendor/makerfabs/ath20.yaml @@ -0,0 +1,109 @@ +name: ath20 - air-temperature-and-humidity-sensor # Device name can not contain the vendor name +description: LoRaWAN Temperature & Humidity sensor + +# Hardware versions (optional, use when you have revisions) +hardwareVersions: + - version: '1.0' + numeric: 1 + +# Firmware versions (at least one is mandatory) +firmwareVersions: + - # Firmware version + version: '2.0' + numeric: 1 + + # Corresponding hardware versions (optional) + hardwareVersions: + - '1.0' + + # # Firmware features (optional) + # # Valid values are: remote rejoin (trigger a join from the application layer), transmission interval (configure how + # # often he device sends a message). + # features: + # - remote rejoin + # - transmission interval + + # 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: + # # Optional identifier of the vendor of the profile. When you specify the vendorID, the profile is loaded from + # # the vendorID's folder. This allows you to reuse profiles from module or LoRaWAN end device stack vendors. + # # If vendorID is empty, the current vendor ID is used. In this example, the vendorID is the current vendor ID, + # # which is verbose. + # vendorID: example + # Identifier of the profile (lowercase, alphanumeric with dashes, max 36 characters) + id: eu868-profile + lorawanCertified: true + codec: ath20-codec + US902-928: + id: us915-profile + lorawanCertified: true + codec: ath20-codec + + # - # You can add more firmware versions and use different profiles per version + # version: '2.0' + # numeric: 2 + # hardwareVersions: + # - '1.0-rev-A' + # profiles: + # EU863-870: + # id: windsensor-profile + # lorawanCertified: true + # codec: windsensor-codec + # US902-928: + # id: windsensor-profile + # lorawanCertified: true + # codec: windsensor-codec + # AS923: + # id: windsensor-profile + # codec: windsensor-codec + +# 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: + - temperature + - humidity + +# Operating conditions (optional) +operatingConditions: + # Temperature (Celsius) + temperature: + min: -40 + max: 85 + # Relative humidity (fraction of 1) + relativeHumidity: + min: 0 + max: 1 + +# # IP rating (optional) +# ipCode: IP68 + +# Product and data sheet URLs (optional) +productURL: https://www.agrosense.cc/pd.jsp?recommendFromPid=0&id=6&fromMid=366 +dataSheetURL: https://github.com/Makerfabs/Agrosense-Decoder/blob/main/AgroSense%20LoRaWAN%40%20Sensor%20Catalogue_V1.0.pdf + +# Commercial information +sellerURLs: + - name: 'makerfabs' + region: # valid regions are: Argentina, Australia, Brazil, Canada, China, European Union, India, Indonesia. + # Japan, Mexico, Russia, Saudi Arabia, South Africa, South Korea, Turkey, United States, United Kingdom, Other + - china + url: http://www.makerfabs.com/ + +# Photos +photos: + main: ath20.jpg # Image needs to have a transparent background + # other: + # - windsensor-package.png # Image needs to have a transparent background + +# Youtube or Vimeo Video (optional) +videos: + main: https://www.youtube.com/watch?v=SXF6HpzQwL0 diff --git a/vendor/makerfabs/eu868-profile.yaml b/vendor/makerfabs/eu868-profile.yaml new file mode 100644 index 0000000000..e6cbc7fc49 --- /dev/null +++ b/vendor/makerfabs/eu868-profile.yaml @@ -0,0 +1,47 @@ +# 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 +# If your device is an ABP device (supportsJoin is false), uncomment the following fields: +# RX1 delay +#rx1Delay: 5 +# RX1 data rate offset +#rx1DataRateOffset: 0 +# RX2 data rate index +#rx2DataRateIndex: 0 +# RX2 frequency (MHz) +#rx2Frequency: 869.525 +# Factory preset frequencies (MHz) +#factoryPresetFrequencies: [868.1, 868.3, 868.5, 867.1, 867.3, 867.5, 867.7, 867.9] + +# Maximum EIRP +maxEIRP: 16 +# Whether the end device supports 32-bit frame counters +supports32bitFCnt: true + +# Whether the end device supports class B +supportsClassB: false +# If your device supports class B, uncomment the following fields: +# Maximum delay for the end device to answer a MAC request or confirmed downlink frame (seconds) +#classBTimeout: 60 +# Ping slot period (seconds) +#pingSlotPeriod: 128 +# Ping slot data rate index +#pingSlotDataRateIndex: 0 +# Ping slot frequency (MHz). Set to 0 if the band supports ping slot frequency hopping. +#pingSlotFrequency: 869.525 + +# Whether the end device supports class C +supportsClassC: false +# If your device supports class C, uncomment the following fields: +# Maximum delay for the end device to answer a MAC request or confirmed downlink frame (seconds) +#classCTimeout: 60 diff --git a/vendor/makerfabs/index.yaml b/vendor/makerfabs/index.yaml new file mode 100644 index 0000000000..ca0882e933 --- /dev/null +++ b/vendor/makerfabs/index.yaml @@ -0,0 +1,2 @@ +endDevices: + - ath20 diff --git a/vendor/makerfabs/us915-profile.yaml b/vendor/makerfabs/us915-profile.yaml new file mode 100644 index 0000000000..9c10263ddc --- /dev/null +++ b/vendor/makerfabs/us915-profile.yaml @@ -0,0 +1,47 @@ +# 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 +# If your device is an ABP device (supportsJoin is false), uncomment the following fields: +# RX1 delay +#rx1Delay: 5 +# RX1 data rate offset +#rx1DataRateOffset: 0 +# RX2 data rate index +#rx2DataRateIndex: 0 +# RX2 frequency (MHz) +#rx2Frequency: 869.525 +# Factory preset frequencies (MHz) +#factoryPresetFrequencies: [868.1, 868.3, 868.5, 867.1, 867.3, 867.5, 867.7, 867.9] + +# Maximum EIRP +maxEIRP: 20 +# Whether the end device supports 32-bit frame counters +supports32bitFCnt: true + +# Whether the end device supports class B +supportsClassB: false +# If your device supports class B, uncomment the following fields: +# Maximum delay for the end device to answer a MAC request or confirmed downlink frame (seconds) +#classBTimeout: 60 +# Ping slot period (seconds) +#pingSlotPeriod: 128 +# Ping slot data rate index +#pingSlotDataRateIndex: 0 +# Ping slot frequency (MHz). Set to 0 if the band supports ping slot frequency hopping. +#pingSlotFrequency: 869.525 + +# Whether the end device supports class C +supportsClassC: false +# If your device supports class C, uncomment the following fields: +# Maximum delay for the end device to answer a MAC request or confirmed downlink frame (seconds) +classCTimeout: 60 diff --git a/vendor/mclimate/16aspm-codec.yaml b/vendor/mclimate/16aspm-codec.yaml index bac51d67fa..bcd152574f 100644 --- a/vendor/mclimate/16aspm-codec.yaml +++ b/vendor/mclimate/16aspm-codec.yaml @@ -8,8 +8,8 @@ uplinkDecoder: output: data: internalTemperature: 28 - energy_kWh: 55190.552, - power_W: 1497, - acVoltage_V: 231, - acCurrent_mA: 6482, + energy_kWh: 55190.552 + power_W: 1497 + acVoltage_V: 231 + acCurrent_mA: 6482 relayState: 'ON' diff --git a/vendor/mclimate/16aspm-profile.yaml b/vendor/mclimate/16aspm-profile.yaml index 0e08692680..ad1fba2485 100644 --- a/vendor/mclimate/16aspm-profile.yaml +++ b/vendor/mclimate/16aspm-profile.yaml @@ -5,3 +5,4 @@ regionalParametersVersion: RP001-1.0.3-RevA supportsJoin: true maxEIRP: 16 supports32bitFCnt: true +classCTimeout: 60 diff --git a/vendor/mclimate/16aspm.yaml b/vendor/mclimate/16aspm.yaml index 5256683922..da78728991 100644 --- a/vendor/mclimate/16aspm.yaml +++ b/vendor/mclimate/16aspm.yaml @@ -1,4 +1,4 @@ -name: МClimate 16A Switch & Power Meter (16ASPM) +name: 16A Switch & Power Meter (16ASPM) description: The МClimate 16A Switch & Power Meter LoRaWAN (16ASPM) is a miniature device that features a wet 16A relay and an electricity meter inside. The device has 4 terminals L, N, N, Lout, connecting and disconnecting Lout from Lin. The device operates in LoRaWAN Class C, features FUOTA (Firmware Upgrades Over The Air) and has overheating protection # Hardware versions (optional, use when you have revisions) @@ -29,9 +29,6 @@ firmwareVersions: # vibration, water, wind direction and wind speed. sensors: - temperature - - electricity-meter - - voltage-meter - - current-meter # Dimensions in mm (optional) # Use width, height, length and/or diameter dimensions: diff --git a/vendor/mclimate/co2-display-lite.yaml b/vendor/mclimate/co2-display-lite.yaml index d38d22b8a0..58cd4a1d2f 100644 --- a/vendor/mclimate/co2-display-lite.yaml +++ b/vendor/mclimate/co2-display-lite.yaml @@ -1,4 +1,4 @@ -name: MClimate CO2 Display Lite +name: CO2 Display Lite description: MClimate CO2 Display lite LoRaWAN is a stand-alone CO2 sensor powered entirely by solar energy using an organic solar panel. The device features a 1.54" e-ink screen, temperature and humidity sensor, LUX sensor and NDIR CO2 sensor. # Hardware versions (optional, use when you have revisions) diff --git a/vendor/mclimate/co2-display.yaml b/vendor/mclimate/co2-display.yaml index 88510907a6..0255a982d4 100644 --- a/vendor/mclimate/co2-display.yaml +++ b/vendor/mclimate/co2-display.yaml @@ -1,4 +1,4 @@ -name: MClimate CO2 Display +name: CO2 Display description: MClimate CO2 Display is a stand-alone CO2 sensor powered entirely by solar energy using an organic solar panel. The device features a 2.9" e-ink screen, sensor for movement (PIR), temperature and humidity sensor, LUX sensor and NDIR CO2 sensor. # Hardware versions (optional, use when you have revisions) diff --git a/vendor/mclimate/fan-coil-thermostat-profile.yaml b/vendor/mclimate/fan-coil-thermostat-profile.yaml index 0e08692680..ad1fba2485 100644 --- a/vendor/mclimate/fan-coil-thermostat-profile.yaml +++ b/vendor/mclimate/fan-coil-thermostat-profile.yaml @@ -5,3 +5,4 @@ regionalParametersVersion: RP001-1.0.3-RevA supportsJoin: true maxEIRP: 16 supports32bitFCnt: true +classCTimeout: 60 diff --git a/vendor/mclimate/fan-coil-thermostat.yaml b/vendor/mclimate/fan-coil-thermostat.yaml index e56e3288f2..955a7f751a 100644 --- a/vendor/mclimate/fan-coil-thermostat.yaml +++ b/vendor/mclimate/fan-coil-thermostat.yaml @@ -1,4 +1,4 @@ -name: MClimate Fan Coil Thermostat +name: Fan Coil Thermostat description: MClimate Fan Coil Thermostat (FCT) is a thermostat compatible with 2-pipe and 4-pipe Fan Coil Units with 4 SPST relays, 1 DPST dry relay and 0-10V input/output. It features a 4.2" e-ink display, digital temperature and humidity sensor, and 4 buttons. # Hardware versions (optional, use when you have revisions) diff --git a/vendor/mclimate/index.yaml b/vendor/mclimate/index.yaml index 76f0bbde99..23dae896a0 100644 --- a/vendor/mclimate/index.yaml +++ b/vendor/mclimate/index.yaml @@ -5,3 +5,7 @@ endDevices: - ht-sensor - co2-sensor - wireless-thermostat + - co2-display + - co2-display-lite + - fan-coil-thermostat + - 16aspm diff --git a/vendor/mclimate/vicki-codec.yaml b/vendor/mclimate/vicki-codec.yaml index ead089ff88..f2667d7ccc 100644 --- a/vendor/mclimate/vicki-codec.yaml +++ b/vendor/mclimate/vicki-codec.yaml @@ -23,8 +23,8 @@ uplinkDecoder: calibrationFailed: false perceiveAsOnline: false antiFreezeProtection: false - motorOpenness: 17 - targetTemperatureFloat: '29.00' + valveOpenness: 17 + targetTemperatureFloat: 29 normalizedOutput: data: - air: diff --git a/vendor/mclimate/vicki.js b/vendor/mclimate/vicki.js index 03730aa621..a0480ca691 100644 --- a/vendor/mclimate/vicki.js +++ b/vendor/mclimate/vicki.js @@ -24,14 +24,14 @@ function decodeUplink(input) { batteryTmp = ("0" + bytes[7].toString(16)).substr(-2)[0]; batteryVoltageCalculated = 2 + parseInt("0x" + batteryTmp, 16) * 0.1; - decbin = function(number) { + let decbin = (number) => { if (number < 0) { number = 0xFFFFFFFF + number + 1 } number = number.toString(2); return "00000000".substr(number.length) + number; } - byte7Bin = decbin(bytes[8]); + byte7Bin = decbin(bytes[7]); openWindow = byte7Bin[4]; highMotorConsumption = byte7Bin[5]; lowMotorConsumption = byte7Bin[6]; @@ -67,9 +67,9 @@ function decodeUplink(input) { data.attachedBackplate = toBool(attachedBackplate); data.perceiveAsOnline = toBool(perceiveAsOnline); data.antiFreezeProtection = toBool(antiFreezeProtection); - data.motorOpenness = Math.round((1-(motorPosition/motorRange))*100); + data.valveOpenness = motorRange != 0 ? Math.round((1-(motorPosition/motorRange))*100) : 0; if(!data.hasOwnProperty('targetTemperatureFloat')){ - data.targetTemperatureFloat = bytes[1].toFixed(2); + data.targetTemperatureFloat = parseFloat(bytes[1]) } return data; } @@ -169,8 +169,7 @@ function decodeUplink(input) { { // get default keepalive if it is not available in data command_len = 2; - var deviceKeepAlive = 5; - var wdpC = commands[i + 1] == '00' ? false : commands[i + 1] * deviceKeepAlive + 7; + var wdpC = commands[i + 1] == '00' ? false : parseInt(commands[i + 1], 16); var wdpUc = commands[i + 2] == '00' ? false : parseInt(commands[i + 2], 16); var dataJ = { watchDogParams: { wdpC: wdpC, wdpUc: wdpUc } }; resultToPass = merge_obj(resultToPass, dataJ); @@ -311,14 +310,14 @@ function decodeUplink(input) { case '4d': { command_len = 2; - var data = { maxAllowedIntegralValue : (parseInt(`${commands[i + 1]}${commands[i + 2]}`, 16))/10 }; + var data = { piMaxIntegratedError : (parseInt(`${commands[i + 1]}${commands[i + 2]}`, 16))/10 }; resultToPass = merge_obj(resultToPass, data); } break; case '50': { command_len = 2; - var data = { valveOpennessRangeInPercentage: { min: parseInt(commands[i + 1], 16), max: parseInt(commands[i + 2], 16) } }; + var data = { effectiveMotorRange: { minValveOpenness: 100 - parseInt(commands[i + 2], 16), maxValveOpenness: 100 - parseInt(commands[i + 1], 16) } }; resultToPass = merge_obj(resultToPass, data); } break; diff --git a/vendor/plenom/busylight.js b/vendor/plenom/busylight.js index 786cab94a6..a661822dcd 100644 --- a/vendor/plenom/busylight.js +++ b/vendor/plenom/busylight.js @@ -20,6 +20,68 @@ function decodeUplink(input) { errors: [] }; } + else if (input.bytes.length == 25) + { + switch (input.bytes[24]) + { + case 0x01: + reason="Power On Reset"; + break; + case 0x02: + reason="Brownout 1.2V"; + break; + case 0x04: + reason="Brownout 3.3V"; + break; + case 0x10: + reason="External Reset"; + break; + case 0x20: + reason="WatchDog Timer triggered"; + break; + case 0x40: + reason="Software"; + break; + case 0x80: + reason="Backup"; + break; + } + return { + data: { + RSSI: byteArrayToLong(input.bytes, 0), + SNR: byteArrayToLong(input.bytes, 4), + messages_received: byteArrayToLong(input.bytes, 8), + messages_send: byteArrayToLong(input.bytes, 12), + lastcolor_red: input.bytes[16], + lastcolor_blue: input.bytes[17], + lastcolor_green: input.bytes[18], + lastcolor_ontime: input.bytes[19], + lastcolor_offtime: input.bytes[20], + sw_rev: input.bytes[21], + hw_rev: input.bytes[22], + adr_state: input.bytes[23], + last_reset_reason: reason + }, + warnings: [], + errors: [] + }; + } + else if (input.bytes.length == 10) + { +return { + data: { + messages_send: byteArrayToLong(input.bytes, 0), + lastcolor_red: input.bytes[4], + lastcolor_blue: input.bytes[5], + lastcolor_green: input.bytes[6], + lastcolor_ontime: input.bytes[7], + lastcolor_offtime: input.bytes[8], + last_reset_reason: input.bytes[9] + }, + warnings: [], + errors: [] + }; + } else { return {data: { @@ -48,8 +110,10 @@ function encodeDownlink(input) { } function decodeDownlink(input) { - +if (input.bytes.length == 5) + { return { + data: { red: input.bytes[0], green: input.bytes[2], @@ -60,4 +124,22 @@ function decodeDownlink(input) { warnings: [], errors: [] } + } +else if (input.bytes.length == 6) + { + return { + + data: { + red: input.bytes[0], + green: input.bytes[2], + blue: input.bytes[1], + ontime: input.bytes[3], + offtime: input.bytes[4], + immediate_uplink: input.byte[5] + }, + warnings: [], + errors: [] + } + } } + diff --git a/vendor/quandify/cubicmeter-1-1-uplink.js b/vendor/quandify/cubicmeter-1-1-uplink.js index 663064ed71..cf32182440 100644 --- a/vendor/quandify/cubicmeter-1-1-uplink.js +++ b/vendor/quandify/cubicmeter-1-1-uplink.js @@ -30,8 +30,8 @@ var responseTypes = { /* Smaller water leakages only availble when using Quandify platform API as it requires cloud analytics */ var leakStates = { - 2: 'medium', - 3: 'large', + 3: 'medium', + 4: 'large', }; var pipeTypes = { diff --git a/vendor/thermokon/dpa-lrw.yaml b/vendor/thermokon/dpa-lrw.yaml index 5daa0c3589..ec876478c9 100644 --- a/vendor/thermokon/dpa-lrw.yaml +++ b/vendor/thermokon/dpa-lrw.yaml @@ -41,7 +41,7 @@ sensors: - pressure # Product and data sheet URLs (optional) -productURL: https://www.thermokon.de/direct/en-gb?path=%2F1%2F2%2F20&filter_show=1&q=&limit=18&filter_articles=&sbscf%3Asbscf1%2Fattr%2F8470[]=thermokon%3A%2F%2F{r%3D0%2Cb%3D0%2Cl%3Den_UK}%2F1%2F7%2F8%2F338%2F339%2F8470%2F10570 +productURL: https://www.thermokon.de/direct/en-gb/categories/g-dpaplus-lorawan # Photos photos: diff --git a/vendor/thermokon/ls02-lrw.yaml b/vendor/thermokon/ls02-lrw.yaml index 764e381d31..de4b8d0a01 100644 --- a/vendor/thermokon/ls02-lrw.yaml +++ b/vendor/thermokon/ls02-lrw.yaml @@ -33,7 +33,7 @@ sensors: # - lekage - humidity # Product and data sheet URLs (optional) -productURL: https://www.thermokon.de/direct/en-gb?path=%2F1%2F2%2F20&filter_show=1&q=&limit=18&filter_articles=&sbscf%3Asbscf1%2Fattr%2F8470[]=thermokon%3A%2F%2F{r%3D0%2Cb%3D0%2Cl%3Den_UK}%2F1%2F7%2F8%2F338%2F339%2F8470%2F10570 +productURL: https://www.thermokon.de/direct/en-gb/categories/g-ls02plus-flex-lorawan # Photos photos: diff --git a/vendor/thermokon/mcs-lrw.yaml b/vendor/thermokon/mcs-lrw.yaml index 75d07dfef1..16820b5eaf 100644 --- a/vendor/thermokon/mcs-lrw.yaml +++ b/vendor/thermokon/mcs-lrw.yaml @@ -47,7 +47,7 @@ sensors: - light # Product and data sheet URLs (optional) -productURL: https://www.thermokon.de/direct/en-gb?path=%2F1%2F2%2F20&filter_show=1&q=&limit=18&filter_articles=&sbscf%3Asbscf1%2Fattr%2F8470[]=thermokon%3A%2F%2F{r%3D0%2Cb%3D0%2Cl%3Den_UK}%2F1%2F7%2F8%2F338%2F339%2F8470%2F10570 +productURL: https://www.thermokon.de/direct/en-gb/categories/g-mcs-lorawan # Photos photos: diff --git a/vendor/thermokon/novos-3-lrw.yaml b/vendor/thermokon/novos-3-lrw.yaml index 7dc9306f7a..6d89711ce0 100644 --- a/vendor/thermokon/novos-3-lrw.yaml +++ b/vendor/thermokon/novos-3-lrw.yaml @@ -45,7 +45,7 @@ sensors: - potentiometer # Product and data sheet URLs (optional) -productURL: https://www.thermokon.de/direct/en-gb?path=%2F1%2F2%2F20&filter_show=1&q=&limit=18&filter_articles=&sbscf%3Asbscf1%2Fattr%2F8470[]=thermokon%3A%2F%2F{r%3D0%2Cb%3D0%2Cl%3Den_UK}%2F1%2F7%2F8%2F338%2F339%2F8470%2F10570 +productURL: https://www.thermokon.de/direct/en-gb/categories/g-novos-3-x-lorawan # Photos photos: diff --git a/vendor/thermokon/thanos-evo-lrw.yaml b/vendor/thermokon/thanos-evo-lrw.yaml index 03184f0fcc..2d207142b9 100644 --- a/vendor/thermokon/thanos-evo-lrw.yaml +++ b/vendor/thermokon/thanos-evo-lrw.yaml @@ -43,7 +43,7 @@ sensors: - co2 - tvoc # Product and data sheet URLs (optional) -productURL: https://www.thermokon.de/direct/en-gb?path=%2F1%2F2%2F20&filter_show=1&q=&limit=18&filter_articles=&sbscf%3Asbscf1%2Fattr%2F8470[]=thermokon%3A%2F%2F{r%3D0%2Cb%3D0%2Cl%3Den_UK}%2F1%2F7%2F8%2F338%2F339%2F8470%2F10570 +productURL: https://www.thermokon.de/en-gb/highlights/products/thanos-evo # Photos photos: