Skip to content

Commit

Permalink
Merge branch 'master' into modify-r603,add-r315la
Browse files Browse the repository at this point in the history
  • Loading branch information
netvox-tech authored Nov 15, 2024
2 parents 487ca2f + 7eba612 commit 500a8ee
Show file tree
Hide file tree
Showing 125 changed files with 6,280 additions and 319 deletions.
31 changes: 13 additions & 18 deletions bin/validate.js
Original file line number Diff line number Diff line change
@@ -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');
Expand All @@ -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 <file> [--vendor-id <id>]')
Expand All @@ -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) {
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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
Expand Down
128 changes: 111 additions & 17 deletions lib/payload.json
Original file line number Diff line number Diff line change
@@ -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)",
Expand Down Expand Up @@ -56,20 +56,25 @@
"format": "date-time",
"description": "Date and time of the measurement (RFC3339)"
},
"battery": {
"type": "number",
"description": "Voltage (V)",
"minimum": 0
},
"soil": {
"type": "object",
"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)",
Expand All @@ -79,33 +84,38 @@
},
"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
},
"air": {
"type": "object",
"properties": {
"location": {
"type": "string",
"enum": ["indoor", "outdoor"],
"description": "Specifies whether the measurement was taken indoors or outdoors."
},
"temperature": {
"description": "Air temperature (°C)",
"$ref": "#/definitions/temperature"
"$ref": "#/$defs/temperature"
},
"relativeHumidity": {
"description": "Relative humidity (%)",
"$ref": "#/definitions/percentage"
"$ref": "#/$defs/percentage"
},
"pressure": {
"type": "number",
Expand All @@ -115,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
Expand All @@ -129,11 +139,95 @@
"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
},
"water": {
"type": "object",
"properties": {
"leak": {
"type": ["boolean", "string"],
"description": "Leak detected"
},
"temperature": {
"type": "object",
"properties": {
"min": {
"description": "Minimum temperature (°C)",
"$ref": "#/$defs/temperature"
},
"max": {
"description": "Maximum temperature (°C)",
"$ref": "#/$defs/temperature"
},
"avg": {
"description": "Average temperature (°C)",
"$ref": "#/$defs/temperature"
},
"current": {
"description": "Current temperature (°C)",
"$ref": "#/$defs/temperature"
}
}
}
},
"additionalProperties": false
},
"metering": {
"type": "object",
"properties": {
"water": {
"type": "object",
"properties": {
"total": {
"type": "number",
"description": "Total volume (L)"
}
}
}
}
},
"action": {
"type": "object",
"properties": {
"motion": {
"type": "object",
"properties": {
"detected": {
"type": "boolean",
"description": "Motion detected"
},
"count": {
"type": "number",
"description": "Number of motion events (count)"
}
},
"additionalProperties": false
},
"contactState": {
"type": "string",
"description": "State of a contact sensor",
"enum": ["OPEN", "CLOSED"]
}
},
"additionalProperties": false
},
"position": {
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "Horizontal distance from equator (°)"
},
"longitude": {
"type": "number",
"description": "Vertical distance from prime meridian (°)"
}
},
"additionalProperties": false
Expand All @@ -144,13 +238,13 @@
"uplinkPayload": {
"type": "array",
"items": {
"$ref": "#/definitions/measurement"
"$ref": "#/$defs/measurement"
}
}
},
"oneOf": [
{
"$ref": "#/definitions/uplinkPayload"
"$ref": "#/$defs/uplinkPayload"
}
]
}
Loading

0 comments on commit 500a8ee

Please sign in to comment.